netdsfnd.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "shellprv.h"
  2. #pragma  hdrstop
  3. #include "docfind.h"
  4. #include "dsgetdc.h"
  5. #include "ntdsapi.h"
  6. #include "activeds.h"
  7. #include "iadsp.h"
  8. #include "lm.h"
  9. #ifdef WINNT
  10. //
  11. // search the DS for computer objects
  12. //
  13. // BUGBUG: this should be const, but ADSI 
  14. LPTSTR c_aszAttributes[] = { TEXT("DNShostname"), };
  15. class CNetFindInDS : public IDFEnum
  16. {
  17. private:
  18.     LPTSTR              _pszCompName;
  19.     IDocFindFolder      *_pdfFolder;
  20.     LONG                _cRef;
  21.     IDirectorySearch*   _pds;
  22.     IADsPathname*       _padp;
  23.     ADS_SEARCH_HANDLE   _hSearch;
  24.     // helper methods
  25.     HRESULT _StrFromRow(LPTSTR pszProperty, LPTSTR pszBuffer, INT cchBuffer);
  26.     HRESULT _InitSearch(LPCTSTR pszName);
  27. public:
  28.     CNetFindInDS(LPCTSTR pszCompName, IShellFolder *psf);
  29.     ~CNetFindInDS();
  30.     // *** IUnknown methods ***
  31.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  32.     STDMETHODIMP_(ULONG) AddRef();
  33.     STDMETHODIMP_(ULONG) Release();
  34.     // *** IDFEnum methods ***
  35.     STDMETHODIMP Next(LPITEMIDLIST *ppidl,
  36.                        int *pcObjectSearched, int *pcFoldersSearched, BOOL *pfContinue,
  37.                        int *pState, HWND hwnd);
  38.     STDMETHODIMP Skip(int celt)
  39.         { return E_NOTIMPL; };
  40.     STDMETHODIMP Reset()
  41.         { return E_NOTIMPL; };
  42.     STDMETHODIMP StopSearch()
  43.         { return E_NOTIMPL; };
  44.     STDMETHODIMP_(BOOL) FQueryIsAsync()
  45.         { return FALSE; };
  46.     STDMETHODIMP GetAsyncCount(DBCOUNTITEM *pdwTotalAsync, int *pnPercentComplete, BOOL *pfQueryDone)
  47.         { return E_NOTIMPL; };
  48.         
  49.     STDMETHODIMP GetItemIDList(UINT iItem, LPITEMIDLIST *ppidl)
  50.         { return E_NOTIMPL; };
  51.     STDMETHODIMP GetExtendedDetailsOf(LPCITEMIDLIST pidl, UINT iCol, LPSHELLDETAILS pdi)
  52.         { return E_NOTIMPL; };
  53.     STDMETHODIMP GetExtendedDetailsULong(LPCITEMIDLIST pidl, UINT iCol, ULONG *pul)
  54.         { return E_NOTIMPL; };
  55.     STDMETHODIMP GetItemID(UINT iItem, DWORD *puWorkID)
  56.         { return E_NOTIMPL; };
  57.     STDMETHODIMP SortOnColumn(UINT iCol, BOOL fAscending)
  58.         { return E_NOTIMPL; };
  59. };
  60. //
  61. // IUnknown
  62. //
  63. STDMETHODIMP CNetFindInDS::QueryInterface(REFIID riid, void **ppv)
  64. {
  65.     static const QITAB qit[] = 
  66.     {
  67.         { 0 },
  68.     };
  69.     return QISearch(this, qit, riid, ppv);    
  70. }
  71. STDMETHODIMP_(ULONG) CNetFindInDS::AddRef()
  72. {
  73.     return InterlockedIncrement(&_cRef);
  74. }
  75. STDMETHODIMP_(ULONG) CNetFindInDS::Release()
  76. {
  77.    if (InterlockedDecrement(&_cRef))
  78.         return _cRef;
  79.  
  80.     delete this;
  81.     return 0;   
  82. }
  83. //
  84. // construction / destruction
  85. //
  86. CNetFindInDS::CNetFindInDS(LPCTSTR pszCompName, IShellFolder* psf) :
  87.     _pszCompName(NULL),
  88.     _pdfFolder(NULL),
  89.     _cRef(1),
  90.     _pds(NULL),
  91.     _hSearch(NULL)
  92. {
  93.     Str_SetPtr(&_pszCompName, pszCompName);
  94.     psf->QueryInterface(IID_IDocFindFolder, (void **)&_pdfFolder);
  95. }
  96. CNetFindInDS::~CNetFindInDS()
  97. {
  98.     Str_SetPtr(&_pszCompName, NULL);
  99.     if ( _hSearch )
  100.         _pds->CloseSearchHandle(_hSearch);
  101.     if ( _pds )
  102.         _pds->Release();
  103.     if ( _padp )
  104.         _padp->Release();
  105.     
  106.     _pdfFolder->Release();
  107. }
  108. //
  109. // given the ADS_SEARCH_COLUMN get a string back from it.
  110. //
  111. HRESULT CNetFindInDS::_StrFromRow(LPTSTR pszProperty, LPTSTR pszBuffer, INT cchBuffer)
  112. {
  113.     HRESULT hres = S_OK;
  114.     ADS_SEARCH_COLUMN asc;
  115.     hres = _pds->GetColumn(_hSearch, pszProperty, &asc);
  116.     if ( SUCCEEDED(hres) )
  117.     {
  118.         switch ( asc.dwADsType )
  119.         {
  120.             case ADSTYPE_DN_STRING:
  121.             case ADSTYPE_CASE_EXACT_STRING:
  122.             case ADSTYPE_CASE_IGNORE_STRING:
  123.             case ADSTYPE_PRINTABLE_STRING:
  124.             case ADSTYPE_NUMERIC_STRING:
  125.                 StrCpyN(pszBuffer, asc.pADsValues[0].DNString, cchBuffer);
  126.                 break;
  127.             default:
  128.                 hres = E_INVALIDARG;       // bad column type
  129.                 break;
  130.         }
  131.     }
  132.     return hres;
  133. }
  134. //
  135. // initialize the search ready with the path the GC:
  136. //
  137. HRESULT CNetFindInDS::_InitSearch(LPCTSTR pszName)
  138. {
  139.     HRESULT hres = E_FAIL;
  140.     PDOMAIN_CONTROLLER_INFO pdci = NULL;
  141.     
  142.     //
  143.     // get the DNS of the domain forest we are part of
  144.     //
  145.     DWORD dwres = DsGetDcName(NULL, NULL, NULL, NULL, DS_RETURN_DNS_NAME|DS_DIRECTORY_SERVICE_REQUIRED, &pdci);
  146.     if ( (NO_ERROR == dwres) && pdci->DnsForestName )
  147.     {
  148.         TCHAR szBuffer[MAX_PATH];
  149.         wnsprintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("GC://%s"), pdci->DnsForestName);        
  150.         hres = ADsOpenObject(szBuffer, 
  151.                              NULL, NULL, ADS_SECURE_AUTHENTICATION,
  152.                              IID_IDirectorySearch, (void **)&_pds);
  153.         if ( SUCCEEDED(hres) )
  154.         {
  155.             ADS_SEARCHPREF_INFO prefInfo[3];
  156.             //
  157.             // do a sub tree, async paged search.
  158.             //
  159.             prefInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;     // sub-tree search
  160.             prefInfo[0].vValue.dwType = ADSTYPE_INTEGER;
  161.             prefInfo[0].vValue.Integer = ADS_SCOPE_SUBTREE;
  162.             prefInfo[1].dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;     // async
  163.             prefInfo[1].vValue.dwType = ADSTYPE_BOOLEAN;
  164.             prefInfo[1].vValue.Boolean = TRUE;
  165.             prefInfo[2].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;         // paged results
  166.             prefInfo[2].vValue.dwType = ADSTYPE_INTEGER;
  167.             prefInfo[2].vValue.Integer = 32;
  168.             hres = _pds->SetSearchPreference(prefInfo, ARRAYSIZE(prefInfo));        
  169.             if ( SUCCEEDED(hres) )
  170.             {
  171.                 //
  172.                 // build a filter that will find all the computer objects whose name starts
  173.                 // or ends with the string we have been given, the DS is bad at "contains"
  174.                 //
  175.                 wnsprintf(szBuffer, ARRAYSIZE(szBuffer), 
  176.                           TEXT("(&(sAMAccountType=805306369)(|(SAMAccountName=%s*)(SAMAccountName=*%s)))"),
  177.                           pszName, pszName);
  178.                 hres = _pds->ExecuteSearch(szBuffer, c_aszAttributes, ARRAYSIZE(c_aszAttributes), &_hSearch);
  179.             }
  180.         }
  181.         NetApiBufferFree(pdci);
  182.     }
  183.     return hres;
  184. }
  185. //
  186. // itterate over results from a DS search
  187. //
  188. STDMETHODIMP CNetFindInDS::Next(LPITEMIDLIST *ppidl, int *pcObjectSearched, int *pcFoldersSearched, 
  189.                                      BOOL *pfContinue, int *pState, HWND hwnd)
  190. {
  191.     HRESULT hres = S_OK;
  192.     WCHAR szName[MAX_PATH], szUNC[MAX_PATH+2];
  193.     *pState = GNF_DONE;
  194.     *pfContinue = FALSE;
  195.     //
  196.     // if _hSearch == NULL then we have not searched yet, therefore initialize the
  197.     // query against the DS.
  198.     //
  199.     if ( !_hSearch )
  200.         hres = _InitSearch(_pszCompName);
  201.     while ( SUCCEEDED(hres) && _hSearch )
  202.     {
  203.         hres = _pds->GetNextRow(_hSearch);
  204.         if ( SUCCEEDED(hres) )
  205.         {                    
  206.             if ( (hres == S_ADS_NOMORE_ROWS) )
  207.                 break;
  208.             *pcObjectSearched += 1;                    // we have another object
  209.             //
  210.             // get the DNSHostName of the object, this we can then use to construct a
  211.             // UNC name for the object.   If this fails then we skip the result (the
  212.             // column may not be defined, or perhaps its not a string, eitherway
  213.             // we should ignore it).
  214.             //
  215.             if ( SUCCEEDED(_StrFromRow(TEXT("DNShostName"), szName, ARRAYSIZE(szName))) )
  216.             {
  217.                 LPITEMIDLIST pidl;
  218.                 INT iFolder;    
  219.                 
  220.                 wnsprintf(szUNC, ARRAYSIZE(szUNC), TEXT("\\%s"), szName);
  221.                 pidl = ILCreateFromPath(szUNC);
  222.                 if ( !pidl )
  223.                     continue;
  224.                 LPITEMIDLIST pidlParent = ILCloneParent(pidl);
  225.                 if (!pidlParent)
  226.                     continue;
  227.                 hres = _pdfFolder->AddFolderToFolderList(pidl, FALSE, &iFolder);  
  228.                 ILFree(pidlParent);
  229.                 if ( SUCCEEDED(hres) )
  230.                 {
  231.                     //  append attempts to resize an existing pidl
  232.                     //  it will return NULL on failure.
  233.                     *ppidl = DocFind_AppendIFolder(ILClone(ILFindLastID(pidl)), iFolder);
  234.                     
  235.                     if ( *ppidl )
  236.                     {
  237.                         ILFree(pidl);
  238.                         *pState = GNF_MATCH;
  239.                         *pfContinue = TRUE;
  240.         
  241.                         break;                  // success we have a result
  242.                     }
  243.                 }
  244.                 ILFree(pidl);
  245.                 ILFree(*ppidl);
  246.             }    
  247.         }
  248.     }
  249.     return hres;
  250. }
  251. #endif
  252. //
  253. // return an enumerator if the user is logged into the DS, if they are
  254. // not then we return S_FALSE.
  255. //
  256. STDAPI CNetFindInDS_CreateInstance(LPCTSTR pszCompName, IShellFolder *psf, IDFEnum **ppdfe)
  257. {
  258. #ifdef WINNT
  259.     *ppdfe = NULL;
  260.     if ( !GetEnvironmentVariable(TEXT("USERDNSDOMAIN"), NULL, 0) )
  261.         return S_FALSE;
  262.     *ppdfe = new CNetFindInDS(pszCompName, psf);
  263.     if ( !*ppdfe )
  264.         return E_OUTOFMEMORY;
  265.     return S_OK;
  266. #else
  267.     return S_FALSE;         // S_FALSE == use old search
  268. #endif
  269. }