Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

629 lines
17 KiB

  1. // DSQuery.cpp : Implementation of ds routines and classes
  2. //+-------------------------------------------------------------------------
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1992 - 1999
  6. //
  7. // File: querysup.cpp
  8. //
  9. // Contents: DS Enumeration routines and classes
  10. //
  11. // History: 02-Oct-96 WayneSc Created
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "stdafx.h"
  16. #include "resource.h"
  17. #include "dsutil.h"
  18. #include "dssnap.h" // NOTE: this must be befroe querysup.h
  19. #include "querysup.h"
  20. #include "dsdirect.h"
  21. #include <lmaccess.h>
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. extern const INT g_nADsPath;
  28. extern const INT g_nName;
  29. extern const INT g_nDisplayName;
  30. extern const INT g_nObjectClass;
  31. extern const INT g_nGroupType;
  32. extern const INT g_nDescription;
  33. extern const INT g_nUserAccountControl;
  34. extern const INT g_nSystemFlags;
  35. ///////////////////////////////////////////////////////////////////////////////
  36. CDSSearch::CDSSearch()
  37. {
  38. m_bInitialized = FALSE;
  39. m_pwszFilter = NULL;
  40. m_pCache = NULL;
  41. m_pCD = NULL;
  42. m_pObj = NULL;
  43. m_SearchHandle = NULL;
  44. }
  45. CDSSearch::CDSSearch(CDSCache *pCache, CDSComponentData *pCD)
  46. {
  47. m_bInitialized = FALSE;
  48. m_pwszFilter = NULL;
  49. m_pCache = pCache;
  50. m_pCD = pCD;
  51. m_pObj = NULL;
  52. m_SearchHandle = NULL;
  53. }
  54. void CDSSearch::_Reset()
  55. {
  56. if (m_pObj != NULL)
  57. {
  58. if (m_SearchHandle)
  59. {
  60. m_pObj->CloseSearchHandle (m_SearchHandle);
  61. m_SearchHandle = NULL;
  62. }
  63. m_pObj->Release();
  64. m_pObj = NULL;
  65. }
  66. }
  67. CDSSearch::~CDSSearch()
  68. {
  69. _Reset();
  70. }
  71. HRESULT CDSSearch::Init(IDirectorySearch * pObj)
  72. {
  73. HRESULT hr = S_OK;
  74. _Reset();
  75. m_pObj = pObj;
  76. pObj->AddRef();
  77. m_bInitialized = TRUE;
  78. m_scope = ADS_SCOPE_ONELEVEL;
  79. return hr;
  80. }
  81. HRESULT CDSSearch::Init(LPCWSTR lpszObjectPath)
  82. {
  83. HRESULT hr;
  84. _Reset();
  85. hr = DSAdminOpenObject(lpszObjectPath,
  86. IID_IDirectorySearch,
  87. (void **)&m_pObj);
  88. if (SUCCEEDED(hr)) {
  89. m_bInitialized = TRUE;
  90. } else {
  91. m_bInitialized = FALSE;
  92. m_pObj = NULL;
  93. }
  94. return hr;
  95. }
  96. HRESULT CDSSearch::SetAttributeList (LPTSTR *pszAttribs, INT cAttrs)
  97. {
  98. if ( !m_pszAttribs.SetCount(cAttrs) )
  99. return E_OUTOFMEMORY;
  100. for (INT i = 0; i < cAttrs; i++)
  101. {
  102. if ( !m_pszAttribs.Set(pszAttribs[i], i) )
  103. return E_OUTOFMEMORY;
  104. }
  105. return S_OK;
  106. }
  107. HRESULT CDSSearch::SetAttributeListForContainerClass (CDSColumnSet* pColumnSet)
  108. {
  109. ASSERT(pColumnSet != NULL);
  110. PWSTR *pAttributes = new PWSTR[g_nStdCols + pColumnSet->GetNumCols()]; // leave extra space
  111. if (!pAttributes)
  112. {
  113. return E_OUTOFMEMORY;
  114. }
  115. int nCols = 0;
  116. for (int i=0; i < g_nStdCols; i++)
  117. {
  118. pAttributes[nCols++] = g_pStandardAttributes[i];
  119. }
  120. POSITION pos = pColumnSet->GetHeadPosition();
  121. while (pos != NULL)
  122. {
  123. CDSColumn* pCol = (CDSColumn*)pColumnSet->GetNext(pos);
  124. ASSERT(pCol != NULL);
  125. if (!(pCol->GetColumnType() == ATTR_COLTYPE_SPECIAL || pCol->GetColumnType() == ATTR_COLTYPE_MODIFIED_TIME) ||
  126. !pCol->IsVisible())
  127. continue;
  128. LPWSTR pNewAttribute = const_cast<LPWSTR>(pCol->GetColumnAttribute());
  129. //
  130. // JonN 2/8/99: Do not query the same attribute more than once
  131. //
  132. for (int j = 0; j < nCols; j++)
  133. {
  134. if ( pNewAttribute != NULL)
  135. {
  136. if ( 0 == _wcsicmp( pAttributes[j], pNewAttribute ) )
  137. {
  138. pNewAttribute = NULL;
  139. break;
  140. }
  141. }
  142. }
  143. if (NULL != pNewAttribute)
  144. pAttributes[nCols++] = pNewAttribute;
  145. }
  146. // JonN 6/29/99: remember the container class name (NULL is OK)
  147. m_strContainerClassName = pColumnSet->GetClassName();
  148. HRESULT hr = SetAttributeList (pAttributes, nCols);
  149. delete[] pAttributes;
  150. pAttributes = 0;
  151. return hr;
  152. }
  153. HRESULT CDSSearch::SetSearchScope (ADS_SCOPEENUM scope)
  154. {
  155. if (m_bInitialized) {
  156. m_scope = scope;
  157. }
  158. return S_OK;
  159. }
  160. const int NUM_PREFS=4;
  161. HRESULT _SetSearchPreference(IDirectorySearch* piSearch, ADS_SCOPEENUM scope)
  162. {
  163. if (NULL == piSearch)
  164. {
  165. ASSERT(FALSE);
  166. return E_INVALIDARG;
  167. }
  168. ADS_SEARCHPREF_INFO aSearchPref[NUM_PREFS];
  169. aSearchPref[0].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
  170. aSearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
  171. aSearchPref[0].vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
  172. aSearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  173. aSearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
  174. aSearchPref[1].vValue.Integer = QUERY_PAGESIZE;
  175. aSearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  176. aSearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN;
  177. aSearchPref[2].vValue.Integer = FALSE;
  178. aSearchPref[3].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  179. aSearchPref[3].vValue.dwType = ADSTYPE_INTEGER;
  180. aSearchPref[3].vValue.Integer = scope;
  181. return piSearch->SetSearchPreference (aSearchPref, NUM_PREFS);
  182. }
  183. HRESULT _FRSMemberQuery( IDirectorySearch* piAnyMember, CMapStringToString& strmap )
  184. {
  185. #define IFTRUERETURN(b) if (b) { return E_FAIL; }
  186. #define IFFAILRETURN(hr) if (FAILED(hr)) { return hr; }
  187. // get path to container
  188. CComQIPtr<IADs, &IID_IADs> spIADsContainer( piAnyMember );
  189. IFTRUERETURN( !spIADsContainer );
  190. CComBSTR sbstr;
  191. HRESULT hr = spIADsContainer->get_ADsPath( &sbstr );
  192. IFFAILRETURN(hr);
  193. // remove leaf element from path (get path to grandparent)
  194. CPathCracker pathCracker;
  195. hr = pathCracker.Set(sbstr, ADS_SETTYPE_FULL);
  196. IFFAILRETURN(hr);
  197. hr = pathCracker.RemoveLeafElement();
  198. IFFAILRETURN(hr);
  199. sbstr.Empty();
  200. hr = pathCracker.Retrieve( ADS_FORMAT_X500, &sbstr );
  201. IFFAILRETURN(hr);
  202. // set up search
  203. CComPtr<IDirectorySearch> spSearch;
  204. hr = DSAdminOpenObject(sbstr,
  205. IID_IDirectorySearch,
  206. (void **)&spSearch);
  207. IFFAILRETURN(hr);
  208. hr = _SetSearchPreference(spSearch, ADS_SCOPE_ONELEVEL);
  209. IFFAILRETURN(hr);
  210. DSPROP_BSTR_BLOCK bstrblockAttribs;
  211. bstrblockAttribs.SetCount( 2 );
  212. IFTRUERETURN( !bstrblockAttribs.Set( L"distinguishedName", 0 ) );
  213. IFTRUERETURN( !bstrblockAttribs.Set( L"fRSComputerReference", 1 ) );
  214. // perform search
  215. ADS_SEARCH_HANDLE hSearch = NULL;
  216. hr = spSearch->ExecuteSearch (L"(objectClass=nTFRSMember)",
  217. bstrblockAttribs,
  218. bstrblockAttribs.QueryCount(),
  219. &hSearch);
  220. // build mapping
  221. hr = spSearch->GetNextRow ( hSearch );
  222. while (hr == S_OK) {
  223. ADS_SEARCH_COLUMN adscol;
  224. hr = spSearch->GetColumn( hSearch, L"distinguishedName", &adscol );
  225. IFFAILRETURN(hr);
  226. CString strDistinguishedName;
  227. IFTRUERETURN( !ColumnExtractString( strDistinguishedName, NULL, &adscol ) );
  228. spSearch->FreeColumn( &adscol );
  229. hr = spSearch->GetColumn( hSearch, L"fRSComputerReference", &adscol );
  230. IFFAILRETURN(hr);
  231. CString strFRSComputerReference;
  232. IFTRUERETURN( !ColumnExtractString( strFRSComputerReference, NULL, &adscol ) );
  233. spSearch->FreeColumn( &adscol );
  234. strmap.SetAt( strDistinguishedName, strFRSComputerReference );
  235. hr = spSearch->GetNextRow( hSearch );
  236. }
  237. IFFAILRETURN(hr);
  238. return S_OK;
  239. }
  240. HRESULT CDSSearch::DoQuery()
  241. {
  242. BEGIN_PROFILING_BLOCK("CDSSearch::DoQuery");
  243. if (!m_bInitialized)
  244. return E_ADS_BAD_PATHNAME;
  245. HRESULT hr = _SetSearchPreference(m_pObj, m_scope);
  246. if (SUCCEEDED(hr)) {
  247. hr = m_pObj->ExecuteSearch (m_pwszFilter,
  248. m_pszAttribs,
  249. m_pszAttribs.QueryCount(),
  250. &m_SearchHandle);
  251. }
  252. //
  253. // JonN 6/29/99: If we are enumerating an nTFRSMember container, we must
  254. // now perform an auxiliary search for the fRSComputerReference attribute
  255. // on the nTFRSMember objects which are the parent container and
  256. // the siblings of the container.
  257. //
  258. if (SUCCEEDED(hr) && !m_strContainerClassName.Compare( _T("nTFRSMember") ) )
  259. {
  260. _FRSMemberQuery( m_pObj, m_mapMemberToComputer );
  261. }
  262. END_PROFILING_BLOCK;
  263. return hr;
  264. }
  265. HRESULT
  266. CDSSearch::GetNextRow()
  267. {
  268. BEGIN_PROFILING_BLOCK("CDSSearch::GetNextRow");
  269. DWORD status = ERROR_MORE_DATA;
  270. HRESULT hr = S_OK;
  271. HRESULT hr2 = S_OK;
  272. WCHAR Buffer1[512], Buffer2[512];
  273. if (!m_bInitialized) {
  274. END_PROFILING_BLOCK;
  275. return E_ADS_BAD_PATHNAME;
  276. }
  277. while (status == ERROR_MORE_DATA ) {
  278. hr = m_pObj->GetNextRow (m_SearchHandle);
  279. if (hr == S_ADS_NOMORE_ROWS) {
  280. hr2 = ADsGetLastError(&status, Buffer1, 512,
  281. Buffer2, 512);
  282. ASSERT(SUCCEEDED(hr2));
  283. } else {
  284. status = 0;
  285. }
  286. }
  287. END_PROFILING_BLOCK;
  288. return hr;
  289. }
  290. HRESULT
  291. CDSSearch::GetColumn(LPWSTR Attribute,
  292. PADS_SEARCH_COLUMN pColumnData)
  293. {
  294. if (m_bInitialized) {
  295. return m_pObj->GetColumn (m_SearchHandle,
  296. Attribute,
  297. pColumnData);
  298. }
  299. return E_ADS_BAD_PATHNAME;
  300. }
  301. HRESULT
  302. CDSSearch::SetCookieFromData(CDSCookie* pCookie,
  303. CDSColumnSet* pColumnSet)
  304. {
  305. CPathCracker pathCracker;
  306. return SetCookieFromData(pCookie, pathCracker, pColumnSet);
  307. }
  308. HRESULT
  309. CDSSearch::SetCookieFromData (CDSCookie* pCookie,
  310. CPathCracker& specialPerformancePathCracker,
  311. CDSColumnSet* pColumnSet)
  312. {
  313. if (pCookie==NULL) {
  314. ASSERT(FALSE); // Invalid Arguments
  315. return E_INVALIDARG;
  316. }
  317. BEGIN_PROFILING_BLOCK("CDSSearch::SetCookieFromData");
  318. CString str;
  319. HRESULT hr = S_OK;
  320. BOOL BadArgs = FALSE;
  321. INT GroupType = 0;
  322. ADS_SEARCH_COLUMN ColumnData, ColumnData2;
  323. CString szClass;
  324. // ---------- Get Path --------------
  325. hr = m_pObj->GetColumn(m_SearchHandle,
  326. m_pszAttribs[g_nADsPath],
  327. &ColumnData);
  328. if (SUCCEEDED(hr) && ColumnExtractString( str, pCookie, &ColumnData ))
  329. {
  330. CString szPath;
  331. StripADsIPath (str, szPath);
  332. pCookie->SetPath(szPath);
  333. } else {
  334. str.LoadString( IDS_DISPLAYTEXT_NONE );
  335. BadArgs = TRUE;
  336. TRACE(_T("cannot read ADsPath, tossing cookie... (hr is %lx)\n"),
  337. hr);
  338. ReportErrorEx (m_pCD->GetHWnd(), IDS_INVALID_ROW, S_OK,
  339. MB_OK | MB_ICONINFORMATION, NULL, 0);
  340. goto badargs;
  341. }
  342. if (SUCCEEDED(hr)) m_pObj->FreeColumn (&ColumnData);
  343. // ---------- Get Name --------------
  344. hr = m_pObj->GetColumn(m_SearchHandle,
  345. m_pszAttribs[g_nName],
  346. &ColumnData);
  347. if (!(SUCCEEDED(hr) && ColumnExtractString( str, pCookie, &ColumnData ))) {
  348. CString Path;
  349. // CPathCracker pathCracker;
  350. Path = pCookie->GetPath();
  351. specialPerformancePathCracker.Set((LPWSTR)(LPCWSTR)Path,
  352. ADS_SETTYPE_DN);
  353. specialPerformancePathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
  354. BSTR ObjName = NULL;
  355. specialPerformancePathCracker.GetElement( 0, &ObjName );
  356. str = ObjName;
  357. }
  358. pCookie->SetName(str);
  359. if (SUCCEEDED(hr)) m_pObj->FreeColumn (&ColumnData);
  360. // ---------- Get Class (and Group Type) --------------
  361. hr = m_pObj->GetColumn(m_SearchHandle,
  362. m_pszAttribs[g_nObjectClass],
  363. &ColumnData);
  364. if (SUCCEEDED(hr))
  365. {
  366. szClass = ColumnData.pADsValues[ColumnData.dwNumValues-1].CaseIgnoreString;
  367. }
  368. if (szClass.IsEmpty() || FAILED(hr))
  369. {
  370. szClass = L"Unknown";
  371. }
  372. else
  373. {
  374. HRESULT hr2 = m_pObj->GetColumn(m_SearchHandle,
  375. m_pszAttribs[g_nGroupType],
  376. &ColumnData2);
  377. if (SUCCEEDED(hr2))
  378. {
  379. GroupType = ColumnData2.pADsValues[ColumnData2.dwNumValues-1].Integer;
  380. m_pObj->FreeColumn (&ColumnData2);
  381. }
  382. }
  383. if (SUCCEEDED(hr)) m_pObj->FreeColumn (&ColumnData);
  384. // ---------- Get Description --------------
  385. hr = m_pObj->GetColumn(m_SearchHandle,
  386. m_pszAttribs[g_nDescription],
  387. &ColumnData);
  388. if (SUCCEEDED(hr)) {
  389. if (ColumnExtractString( str, pCookie, &ColumnData)) {
  390. pCookie->SetDesc(str);
  391. }
  392. m_pObj->FreeColumn (&ColumnData);
  393. }
  394. else {
  395. pCookie->SetDesc(L"");
  396. }
  397. // ---------- Get AccountControl Flag word --------------
  398. hr = m_pObj->GetColumn(m_SearchHandle,
  399. m_pszAttribs[g_nUserAccountControl],
  400. &ColumnData);
  401. if (SUCCEEDED(hr))
  402. {
  403. if (ColumnData.pADsValues->dwType == ADSTYPE_INTEGER)
  404. {
  405. if (((DWORD)ColumnData.pADsValues->Integer & UF_INTERDOMAIN_TRUST_ACCOUNT) == UF_INTERDOMAIN_TRUST_ACCOUNT)
  406. {
  407. BadArgs = TRUE;
  408. }
  409. else if ((((DWORD)ColumnData.pADsValues->Integer & UF_ACCOUNTDISABLE)) != UF_ACCOUNTDISABLE)
  410. {
  411. pCookie->ReSetDisabled();
  412. }
  413. else
  414. {
  415. pCookie->SetDisabled();
  416. }
  417. if ((((DWORD)ColumnData.pADsValues->Integer & UF_DONT_EXPIRE_PASSWD)) != UF_DONT_EXPIRE_PASSWD)
  418. {
  419. pCookie->ReSetNonExpiringPwd();
  420. }
  421. else
  422. {
  423. pCookie->SetNonExpiringPwd();
  424. }
  425. }
  426. else
  427. {
  428. pCookie->ReSetDisabled();
  429. pCookie->ReSetNonExpiringPwd();
  430. }
  431. m_pObj->FreeColumn (&ColumnData);
  432. }
  433. // ---------- Get System Flags --------------
  434. pCookie->SetSystemFlags(0);
  435. hr = m_pObj->GetColumn(m_SearchHandle,
  436. m_pszAttribs[g_nSystemFlags],
  437. &ColumnData);
  438. if (SUCCEEDED(hr)) {
  439. if (ColumnData.pADsValues->dwType == ADSTYPE_INTEGER) {
  440. pCookie->SetSystemFlags(ColumnData.pADsValues->Integer);
  441. }
  442. m_pObj->FreeColumn (&ColumnData);
  443. }
  444. // ---------- Get Class Cache and Cookie Extra Info --------------
  445. // JonN 6/17/99: moved from BadArgs clause
  446. if (!BadArgs)
  447. {
  448. CString szPath;
  449. m_pCD->GetBasePathsInfo()->ComposeADsIPath(szPath, pCookie->GetPath());
  450. CDSClassCacheItemBase* pItem = m_pCache->FindClassCacheItem(m_pCD, szClass, szPath);
  451. if (pItem != NULL)
  452. {
  453. pCookie->SetCacheItem(pItem);
  454. if (szClass == L"group")
  455. {
  456. CDSCookieInfoGroup* pExtraInfo = new CDSCookieInfoGroup;
  457. pExtraInfo->m_GroupType = GroupType;
  458. pCookie->SetExtraInfo(pExtraInfo);
  459. } else if (szClass == L"nTDSConnection") {
  460. CDSCookieInfoConnection* pExtraInfo = new CDSCookieInfoConnection;
  461. ASSERT( NULL != pExtraInfo );
  462. hr = m_pObj->GetColumn(m_SearchHandle,
  463. L"fromServer",
  464. &ColumnData);
  465. if (SUCCEEDED(hr)) {
  466. CString strFromServer;
  467. if ( ColumnExtractString( strFromServer, NULL, &ColumnData) ) {
  468. CString strFRSComputerReference;
  469. if ( m_mapMemberToComputer.Lookup( strFromServer, strFRSComputerReference ) )
  470. {
  471. pExtraInfo->m_strFRSComputerReference = strFRSComputerReference;
  472. }
  473. }
  474. m_pObj->FreeColumn (&ColumnData);
  475. }
  476. hr = m_pObj->GetColumn(m_SearchHandle,
  477. L"options",
  478. &ColumnData);
  479. if (SUCCEEDED(hr) && NULL != ColumnData.pADsValues) {
  480. pExtraInfo->m_nOptions = ColumnData.pADsValues[0].Integer;
  481. m_pObj->FreeColumn (&ColumnData);
  482. }
  483. pExtraInfo->m_fFRSConnection = !m_strContainerClassName.Compare( _T("nTFRSMember") );
  484. pCookie->SetExtraInfo(pExtraInfo);
  485. }
  486. } else {
  487. BadArgs = TRUE;
  488. }
  489. }
  490. hr = S_OK;
  491. // ---------- Get optional Columns -----------
  492. if ((pColumnSet != NULL)) {
  493. CStringList& strlist = pCookie->GetParentClassSpecificStrings();
  494. strlist.RemoveAll(); // remove contents, if we do an update
  495. POSITION pos = pColumnSet->GetHeadPosition();
  496. while (pos != NULL)
  497. {
  498. CDSColumn* pCol = (CDSColumn*)pColumnSet->GetNext(pos);
  499. if (!(pCol->GetColumnType() == ATTR_COLTYPE_SPECIAL || pCol->GetColumnType() == ATTR_COLTYPE_MODIFIED_TIME) ||
  500. !pCol->IsVisible())
  501. continue;
  502. str = L"";
  503. COLUMN_EXTRACTION_FUNCTION pfn = pCol->GetExtractionFunction();
  504. if (NULL == pfn) {
  505. pfn = ColumnExtractString;
  506. }
  507. hr = m_pObj->GetColumn(m_SearchHandle,
  508. const_cast<LPWSTR>(pCol->GetColumnAttribute()),
  509. &ColumnData);
  510. if (SUCCEEDED(hr)) {
  511. if ( NULL == pfn || !(pfn)( str, pCookie, &ColumnData ) ) {
  512. str = L" ";
  513. }
  514. // If the column is the modified time, then copy it into the cookie as a SYSTEMTIME so that
  515. // we can do a comparison for sorting
  516. if (pCol->GetColumnType() == ATTR_COLTYPE_MODIFIED_TIME)
  517. {
  518. pCookie->SetModifiedTime(&(ColumnData.pADsValues->UTCTime));
  519. }
  520. FreeColumn (&ColumnData);
  521. }
  522. else
  523. {
  524. if ( NULL == pfn || !(pfn)( str, pCookie, NULL ) ) {
  525. str = L" ";
  526. }
  527. }
  528. strlist.AddTail( str );
  529. }
  530. }
  531. hr = S_OK;
  532. badargs:
  533. if (BadArgs) {
  534. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  535. }
  536. END_PROFILING_BLOCK;
  537. return hr;
  538. }