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.

1257 lines
39 KiB

  1. //
  2. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  3. //
  4. // ***************************************************************************
  5. //
  6. // Original Author: Rajesh Rao
  7. //
  8. // $Author: rajeshr $
  9. // $Date: 6/11/98 4:43p $
  10. // $Workfile:ldaphelp.cpp $
  11. //
  12. // $Modtime: 6/11/98 11:21a $
  13. // $Revision: 1 $
  14. // $Nokeywords: $
  15. //
  16. //
  17. // Description: Contains the implementation the CLDAPHelper class. This is
  18. // a class that has many static helper functions pertaining to ADSI LDAP Provider
  19. //***************************************************************************
  20. /////////////////////////////////////////////////////////////////////////
  21. #include "precomp.h"
  22. LPCWSTR CLDAPHelper :: LDAP_CN_EQUALS = L"LDAP://CN=";
  23. LPCWSTR CLDAPHelper :: LDAP_DISP_NAME_EQUALS = L"(lDAPDisplayName=";
  24. LPCWSTR CLDAPHelper :: OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA = L"(objectCategory=classSchema)";
  25. LPCWSTR CLDAPHelper :: SUB_CLASS_OF_EQUALS = L"(subclassOf=";
  26. LPCWSTR CLDAPHelper :: NOT_LDAP_NAME_EQUALS = L"(!ldapDisplayName=";
  27. LPCWSTR CLDAPHelper :: LEFT_BRACKET_AND = L"(&";
  28. LPCWSTR CLDAPHelper :: GOVERNS_ID_EQUALS = L"(governsId=";
  29. LPCWSTR CLDAPHelper :: CLASS_SCHEMA = L"classSchema";
  30. LPCWSTR CLDAPHelper :: CN_EQUALS = L"cn=";
  31. //***************************************************************************
  32. //
  33. // CLDAPHelper :: GetLDAPClassFromLDAPName
  34. //
  35. // Purpose : See Header
  36. //***************************************************************************
  37. HRESULT CLDAPHelper :: GetLDAPClassFromLDAPName(
  38. IDirectorySearch *pDirectorySearchSchemaContainer,
  39. LPCWSTR lpszSchemaContainerSuffix,
  40. PADS_SEARCHPREF_INFO pSearchInfo,
  41. DWORD dwSearchInfoCount,
  42. CADSIClass *pADSIClass
  43. )
  44. {
  45. // We map the object from the LDAP Display name
  46. // Hence we cannot directly do an ADsOpenObject().
  47. // We have to send an LDAP query for the instance of ClassSchema/AttributeSchema where the
  48. // ldapdisplayname attribute is the lpszObjectName parameter.
  49. HRESULT result = E_FAIL;
  50. // For the search filter;
  51. LPCWSTR lpszLDAPObjectName = pADSIClass->GetADSIClassName();
  52. LPWSTR lpszSearchFilter = NULL;
  53. if(lpszSearchFilter = new WCHAR[ wcslen(LDAP_DISP_NAME_EQUALS) + wcslen(lpszLDAPObjectName) + wcslen(RIGHT_BRACKET_STR) + 1])
  54. {
  55. try
  56. {
  57. wcscpy(lpszSearchFilter, LDAP_DISP_NAME_EQUALS);
  58. wcscat(lpszSearchFilter, lpszLDAPObjectName);
  59. wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
  60. ADS_SEARCH_HANDLE hADSSearch;
  61. if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch(lpszSearchFilter, NULL, -1, &hADSSearch)))
  62. {
  63. try
  64. {
  65. if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearch)) && result != S_ADS_NOMORE_ROWS)
  66. {
  67. // Get the column for the CN attribute
  68. ADS_SEARCH_COLUMN adsColumn;
  69. // Store each of the LDAP class attributes
  70. // Reset the LDAP and WBEM names to take care of change in case
  71. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
  72. {
  73. try
  74. {
  75. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  76. result = E_FAIL;
  77. else
  78. {
  79. pADSIClass->SetADSIClassName(adsColumn.pADsValues->CaseIgnoreString);
  80. LPWSTR lpszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM(adsColumn.pADsValues->CaseIgnoreString);
  81. try
  82. {
  83. pADSIClass->SetWBEMClassName(lpszWBEMName);
  84. }
  85. catch ( ... )
  86. {
  87. delete [] lpszWBEMName;
  88. throw;
  89. }
  90. delete [] lpszWBEMName;
  91. }
  92. }
  93. catch ( ... )
  94. {
  95. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  96. throw;
  97. }
  98. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  99. }
  100. // Store each of the LDAP class attributes
  101. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)COMMON_NAME_ATTR, &adsColumn)))
  102. {
  103. try
  104. {
  105. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  106. result = E_FAIL;
  107. else
  108. pADSIClass->SetCommonName(adsColumn.pADsValues->CaseIgnoreString);
  109. }
  110. catch ( ... )
  111. {
  112. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  113. throw;
  114. }
  115. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  116. }
  117. // Special case for top since ADSI returns "top" as the parent class of "top" and we
  118. // will go into an infinite loop later if we dont check this
  119. if(pADSIClass->GetCommonName() && _wcsicmp(pADSIClass->GetCommonName(), TOP_CLASS) != 0)
  120. {
  121. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  122. result = E_FAIL;
  123. else
  124. {
  125. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SUB_CLASS_OF_ATTR, &adsColumn)))
  126. {
  127. try
  128. {
  129. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  130. result = E_FAIL;
  131. else
  132. pADSIClass->SetSuperClassLDAPName(adsColumn.pADsValues->CaseIgnoreString);
  133. }
  134. catch ( ... )
  135. {
  136. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  137. throw;
  138. }
  139. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  140. }
  141. }
  142. }
  143. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)GOVERNS_ID_ATTR, &adsColumn)))
  144. {
  145. try
  146. {
  147. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  148. result = E_FAIL;
  149. else
  150. pADSIClass->SetGovernsID(adsColumn.pADsValues->CaseIgnoreString);
  151. }
  152. catch ( ... )
  153. {
  154. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  155. throw;
  156. }
  157. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  158. }
  159. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SCHEMA_ID_GUID_ATTR, &adsColumn)))
  160. {
  161. try
  162. {
  163. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  164. result = E_FAIL;
  165. else
  166. pADSIClass->SetSchemaIDGUID((adsColumn.pADsValues->OctetString).lpValue, (adsColumn.pADsValues->OctetString).dwLength);
  167. }
  168. catch ( ... )
  169. {
  170. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  171. throw;
  172. }
  173. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  174. }
  175. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)RDN_ATT_ID_ATTR, &adsColumn)))
  176. {
  177. try
  178. {
  179. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  180. result = E_FAIL;
  181. else
  182. pADSIClass->SetRDNAttribute(adsColumn.pADsValues->CaseIgnoreString);
  183. }
  184. catch ( ... )
  185. {
  186. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  187. throw;
  188. }
  189. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  190. }
  191. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)DEFAULT_SECURITY_DESCRP_ATTR, &adsColumn)))
  192. {
  193. try
  194. {
  195. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  196. result = E_FAIL;
  197. else
  198. pADSIClass->SetDefaultSecurityDescriptor(adsColumn.pADsValues->CaseIgnoreString);
  199. }
  200. catch ( ... )
  201. {
  202. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  203. throw;
  204. }
  205. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  206. }
  207. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)OBJECT_CLASS_CATEGORY_ATTR, &adsColumn)))
  208. {
  209. try
  210. {
  211. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  212. result = E_FAIL;
  213. else
  214. pADSIClass->SetObjectClassCategory(adsColumn.pADsValues->Integer);
  215. }
  216. catch ( ... )
  217. {
  218. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  219. throw;
  220. }
  221. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  222. }
  223. /*
  224. if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)NT_SECURITY_DESCRIPTOR_ATTR, &adsColumn)))
  225. {
  226. pADSIClass->SetNTSecurityDescriptor((adsColumn.pADsValues->SecurityDescriptor).lpValue, (adsColumn.pADsValues->SecurityDescriptor).dwLength);
  227. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  228. }
  229. */
  230. if(SUCCEEDED(result) && SUCCEEDED(result = pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)DEFAULT_OBJECTCATEGORY_ATTR, &adsColumn)))
  231. {
  232. try
  233. {
  234. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  235. result = E_FAIL;
  236. else
  237. {
  238. // Get the LDAPDIpslayName of the class
  239. LPWSTR lpszLDAPName = NULL;
  240. if(SUCCEEDED(result) && SUCCEEDED(result = GetLDAPClassNameFromCN(adsColumn.pADsValues->DNString, &lpszLDAPName)))
  241. {
  242. try
  243. {
  244. pADSIClass->SetDefaultObjectCategory(lpszLDAPName);
  245. }
  246. catch ( ... )
  247. {
  248. delete [] lpszLDAPName;
  249. throw;
  250. }
  251. delete [] lpszLDAPName;
  252. }
  253. }
  254. }
  255. catch ( ... )
  256. {
  257. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  258. throw;
  259. }
  260. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  261. }
  262. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_ONLY_ATTR, &adsColumn)))
  263. {
  264. try
  265. {
  266. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  267. result = E_FAIL;
  268. else
  269. pADSIClass->SetSystemOnly((BOOLEAN)adsColumn.pADsValues->Boolean);
  270. }
  271. catch ( ... )
  272. {
  273. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  274. throw;
  275. }
  276. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  277. }
  278. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)AUXILIARY_CLASS_ATTR, &adsColumn)))
  279. {
  280. try
  281. {
  282. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  283. result = E_FAIL;
  284. else
  285. pADSIClass->SetAuxiliaryClasses(adsColumn.pADsValues, adsColumn.dwNumValues);
  286. }
  287. catch ( ... )
  288. {
  289. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  290. throw;
  291. }
  292. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  293. }
  294. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_AUXILIARY_CLASS_ATTR, &adsColumn)))
  295. {
  296. try
  297. {
  298. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  299. result = E_FAIL;
  300. else
  301. pADSIClass->SetSystemAuxiliaryClasses(adsColumn.pADsValues, adsColumn.dwNumValues);
  302. }
  303. catch ( ... )
  304. {
  305. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  306. throw;
  307. }
  308. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  309. }
  310. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_MAY_CONTAIN_ATTR, &adsColumn)))
  311. {
  312. try
  313. {
  314. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  315. result = E_FAIL;
  316. else
  317. pADSIClass->SetSystemMayContains(adsColumn.pADsValues, adsColumn.dwNumValues);
  318. }
  319. catch ( ... )
  320. {
  321. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  322. throw;
  323. }
  324. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  325. }
  326. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)MAY_CONTAIN_ATTR, &adsColumn)))
  327. {
  328. try
  329. {
  330. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  331. result = E_FAIL;
  332. else
  333. pADSIClass->SetMayContains(adsColumn.pADsValues, adsColumn.dwNumValues);
  334. }
  335. catch ( ... )
  336. {
  337. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  338. throw;
  339. }
  340. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  341. }
  342. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_MUST_CONTAIN_ATTR, &adsColumn)))
  343. {
  344. try
  345. {
  346. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  347. result = E_FAIL;
  348. else
  349. pADSIClass->SetSystemMustContains(adsColumn.pADsValues, adsColumn.dwNumValues);
  350. }
  351. catch ( ... )
  352. {
  353. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  354. throw;
  355. }
  356. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  357. }
  358. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)MUST_CONTAIN_ATTR, &adsColumn)))
  359. {
  360. try
  361. {
  362. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  363. result = E_FAIL;
  364. else
  365. pADSIClass->SetMustContains(adsColumn.pADsValues, adsColumn.dwNumValues);
  366. }
  367. catch ( ... )
  368. {
  369. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  370. throw;
  371. }
  372. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  373. }
  374. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)SYSTEM_POSS_SUPERIORS_ATTR, &adsColumn)))
  375. {
  376. try
  377. {
  378. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  379. result = E_FAIL;
  380. else
  381. pADSIClass->SetSystemPossibleSuperiors(adsColumn.pADsValues, adsColumn.dwNumValues);
  382. }
  383. catch ( ... )
  384. {
  385. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  386. throw;
  387. }
  388. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  389. }
  390. if(SUCCEEDED(result) && SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearch, (LPWSTR)POSS_SUPERIORS_ATTR, &adsColumn)))
  391. {
  392. try
  393. {
  394. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  395. result = E_FAIL;
  396. else
  397. pADSIClass->SetPossibleSuperiors(adsColumn.pADsValues, adsColumn.dwNumValues);
  398. }
  399. catch ( ... )
  400. {
  401. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  402. throw;
  403. }
  404. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  405. }
  406. }
  407. else
  408. result = E_FAIL;
  409. }
  410. catch ( ... )
  411. {
  412. // Close the search
  413. pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearch);
  414. throw;
  415. }
  416. // Close the search
  417. pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearch);
  418. }
  419. }
  420. catch ( ... )
  421. {
  422. if ( lpszSearchFilter )
  423. {
  424. // Delete the filter
  425. delete [] lpszSearchFilter;
  426. lpszSearchFilter = NULL;
  427. }
  428. throw;
  429. }
  430. if ( lpszSearchFilter )
  431. {
  432. // Delete the filter
  433. delete [] lpszSearchFilter;
  434. lpszSearchFilter = NULL;
  435. }
  436. }
  437. else
  438. result = E_OUTOFMEMORY;
  439. return result;
  440. }
  441. //***************************************************************************
  442. //
  443. // CLDAPHelper :: GetLDAPSchemaObjectFromCommonName
  444. //
  445. // Purpose : To fetch the IDirectoryObject interface on a class/property provided by the LDAP Provider
  446. // Parameters:
  447. // lpszSchemaContainerSuffix : The suffix to be used. The actual object fetced will be:
  448. // LDAP://CN=<lpszCommonName>,<lpszSchemaContainerSuffix>
  449. // lpszCommonName : The 'cn' attribute of the LDAP class or property to be fetched.
  450. // ppLDAPObject : The address where the pointer to IDirectoryObject will be stored
  451. // It is the caller's responsibility to delete the object when done with it
  452. //
  453. // Return Value: The COM status value indicating the status of the request.
  454. //***************************************************************************
  455. HRESULT CLDAPHelper :: GetLDAPSchemaObjectFromCommonName(
  456. LPCWSTR lpszSchemaContainerSuffix,
  457. LPCWSTR lpszCommonName,
  458. IDirectoryObject **ppLDAPObject)
  459. {
  460. HRESULT result = S_OK;
  461. // Form the ADSI path to the LDAP object
  462. LPWSTR lpszLDAPObjectPath = NULL;
  463. if(lpszLDAPObjectPath = new WCHAR[wcslen(LDAP_CN_EQUALS) + wcslen(lpszCommonName) + wcslen(COMMA_STR) + wcslen(lpszSchemaContainerSuffix) + 1])
  464. {
  465. wcscpy(lpszLDAPObjectPath, LDAP_CN_EQUALS);
  466. wcscat(lpszLDAPObjectPath, lpszCommonName);
  467. wcscat(lpszLDAPObjectPath, COMMA_STR);
  468. wcscat(lpszLDAPObjectPath, lpszSchemaContainerSuffix);
  469. result = ADsOpenObject(lpszLDAPObjectPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)ppLDAPObject);
  470. delete[] lpszLDAPObjectPath;
  471. }
  472. else
  473. result = E_OUTOFMEMORY;
  474. return result;
  475. }
  476. //***************************************************************************
  477. //
  478. // CLDAPHelper :: GetLDAPClassNameFromCN
  479. //
  480. // Purpose : To fetch the LDAPDisplayNAme of a class from its path
  481. // Parameters:
  482. //
  483. // lpszLDAPClassPath : The path to the class object without the LDAP prefix. Ex CN=user,CN=Schema, CN=COnfiguration ...
  484. // Return Value: The COM status value indicating the status of the request. The user should delete the
  485. // name returned, when done
  486. //***************************************************************************
  487. HRESULT CLDAPHelper :: GetLDAPClassNameFromCN(LPCWSTR lpszLDAPClassPath,
  488. LPWSTR *lppszLDAPName)
  489. {
  490. IDirectoryObject *pLDAPClass = NULL;
  491. // Prepend the LDAP:// perfix
  492. LPWSTR lpszRealPath = NULL;
  493. HRESULT result = S_OK;
  494. if(lpszRealPath = new WCHAR[ wcslen(LDAP_PREFIX) + wcslen(lpszLDAPClassPath) + 1])
  495. {
  496. wcscpy(lpszRealPath, LDAP_PREFIX);
  497. wcscat(lpszRealPath, lpszLDAPClassPath);
  498. result = ADsOpenObject(lpszRealPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)&pLDAPClass);
  499. delete [] lpszRealPath;
  500. }
  501. else
  502. result = E_OUTOFMEMORY;
  503. // Get the attribute LDAPDisplayName
  504. if(SUCCEEDED(result))
  505. {
  506. PADS_ATTR_INFO pAttributes = NULL;
  507. DWORD dwReturnCount = 0;
  508. if(SUCCEEDED(result = pLDAPClass->GetObjectAttributes((LPWSTR *)&LDAP_DISPLAY_NAME_ATTR, 1, &pAttributes, &dwReturnCount)) && dwReturnCount == 1)
  509. {
  510. if(pAttributes->pADsValues->dwType == ADSTYPE_PROV_SPECIFIC)
  511. result = E_FAIL;
  512. else
  513. {
  514. *lppszLDAPName = NULL;
  515. if(*lppszLDAPName = new WCHAR[wcslen(pAttributes->pADsValues->DNString) + 1])
  516. wcscpy(*lppszLDAPName, pAttributes->pADsValues->DNString);
  517. else
  518. result = E_OUTOFMEMORY;
  519. }
  520. FreeADsMem((LPVOID *)pAttributes);
  521. }
  522. pLDAPClass->Release();
  523. }
  524. return result;
  525. }
  526. //***************************************************************************
  527. //
  528. // CLDAPHelper :: EnumerateClasses
  529. //
  530. // Purpose : See Header
  531. //***************************************************************************
  532. HRESULT CLDAPHelper :: EnumerateClasses(
  533. IDirectorySearch *pDirectorySearchSchemaContainer,
  534. LPCWSTR lpszSchemaContainerSuffix,
  535. PADS_SEARCHPREF_INFO pSearchInfo,
  536. DWORD dwSearchInfoCount,
  537. LPCWSTR lpszLDAPSuperClass,
  538. BOOLEAN bDeep,
  539. LPWSTR **pppszClassNames,
  540. DWORD *pdwNumRows,
  541. BOOLEAN bArtificialClass)
  542. {
  543. // Initialize the return values
  544. HRESULT result = E_FAIL;
  545. *pdwNumRows = 0;
  546. // The search filter;
  547. LPWSTR lpszSearchFilter = NULL;
  548. // There's various cases to be considered here.
  549. // if(lpszLDAPSuperClass is NULL)
  550. // then
  551. // if bDeep is false, then no objects is returned (since we do not provide the LDAP base class
  552. // else all the classes are returned using the filter (objectCategory=classSchema)
  553. // else
  554. // if bDeep is false, then the filter (&(objectCategory=classSchema)(subClassOf=lpszLDAPSuperClass)) is used
  555. // else a lot of work has to be done!
  556. if(lpszLDAPSuperClass == NULL)
  557. {
  558. if(!bDeep)
  559. {
  560. *pppszClassNames = NULL;
  561. *pdwNumRows = 0;
  562. return S_OK;
  563. }
  564. else
  565. {
  566. if(!(lpszSearchFilter = new WCHAR[ wcslen(OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA) + 1]))
  567. return E_OUTOFMEMORY;
  568. wcscpy(lpszSearchFilter, OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA);
  569. }
  570. }
  571. else
  572. {
  573. if(!bDeep)
  574. {
  575. // One would imagine that a filter of the kind
  576. //(&(objectClass=classSchema)(subClassOf=<lpszLDAPSuperClass>))
  577. // would be enough. Unfortunately it also gives the Top class
  578. //in the results when the value of lpszLDAPSuperClass is Top
  579. // we dont need that. Hnce we form the filter
  580. //(&(objectClass=classSchema)(subClassOf=<lpszLDAPSuperClass>)(!ldapDisplayName=<lpszLDAPSuperClass>))
  581. if(lpszSearchFilter = new WCHAR[ wcslen(LEFT_BRACKET_AND) // (&
  582. + wcslen(OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA) // (objectCategory=classSchema)
  583. + wcslen(SUB_CLASS_OF_EQUALS) // (subClassOf=
  584. + wcslen(lpszLDAPSuperClass) // superClass
  585. + wcslen(RIGHT_BRACKET_STR) // )
  586. + wcslen(NOT_LDAP_NAME_EQUALS) // (!ldapDisplayName=
  587. + wcslen(lpszLDAPSuperClass) // superClass
  588. + 2*wcslen(RIGHT_BRACKET_STR) // ))
  589. +1])
  590. {
  591. wcscpy(lpszSearchFilter, LEFT_BRACKET_AND);
  592. wcscat(lpszSearchFilter, OBJECT_CATEGORY_EQUALS_CLASS_SCHEMA);
  593. wcscat(lpszSearchFilter, SUB_CLASS_OF_EQUALS);
  594. wcscat(lpszSearchFilter, lpszLDAPSuperClass);
  595. wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
  596. wcscat(lpszSearchFilter, NOT_LDAP_NAME_EQUALS); // (!ldapDisplayName=
  597. wcscat(lpszSearchFilter, lpszLDAPSuperClass);
  598. wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
  599. wcscat(lpszSearchFilter, RIGHT_BRACKET_STR);
  600. }
  601. else
  602. result = E_OUTOFMEMORY;
  603. }
  604. else
  605. lpszSearchFilter = NULL; // THIS SPECIAL CASE IS TACKLED LATER
  606. }
  607. if(lpszSearchFilter)
  608. {
  609. ADS_SEARCH_HANDLE hADSSearchOuter;
  610. if(SUCCEEDED(result = pDirectorySearchSchemaContainer->ExecuteSearch(lpszSearchFilter, (LPWSTR *)&LDAP_DISPLAY_NAME_ATTR, 1, &hADSSearchOuter)))
  611. {
  612. *pdwNumRows = 0;
  613. DWORD dwFirstCount = 0; // Number of rows retreived on the first count
  614. // Calculate the number of rows first.
  615. while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchOuter)) &&
  616. result != S_ADS_NOMORE_ROWS)
  617. dwFirstCount ++;
  618. // Allocate enough memory for the classes and names
  619. *pppszClassNames = NULL;
  620. if(bArtificialClass)
  621. {
  622. dwFirstCount ++;
  623. if(*pppszClassNames = new LPWSTR [dwFirstCount])
  624. (*pppszClassNames)[0] = NULL;
  625. else
  626. result = E_OUTOFMEMORY;
  627. }
  628. else
  629. {
  630. if(!(*pppszClassNames = new LPWSTR [dwFirstCount]))
  631. result = E_OUTOFMEMORY;
  632. }
  633. // The index of the attribute being processed
  634. DWORD dwSecondCount = 0;
  635. if(bArtificialClass)
  636. dwSecondCount ++;
  637. // Get the columns for the attributes
  638. ADS_SEARCH_COLUMN adsColumn;
  639. // Move to the beginning of the search
  640. if(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetFirstRow(hADSSearchOuter))
  641. && result != S_ADS_NOMORE_ROWS)
  642. {
  643. // Store each of the LDAP class attributes
  644. if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearchOuter, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
  645. {
  646. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  647. {
  648. result = E_FAIL;
  649. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  650. }
  651. else
  652. {
  653. // Create the CADSIClass
  654. (*pppszClassNames)[dwSecondCount] = NULL;
  655. if((*pppszClassNames)[dwSecondCount] = new WCHAR[wcslen(adsColumn.pADsValues->CaseIgnoreString) + 1])
  656. wcscpy((*pppszClassNames)[dwSecondCount], adsColumn.pADsValues->CaseIgnoreString);
  657. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  658. dwSecondCount++;
  659. // Get the rest of the rows
  660. while(SUCCEEDED(result = pDirectorySearchSchemaContainer->GetNextRow(hADSSearchOuter))&&
  661. result != S_ADS_NOMORE_ROWS)
  662. {
  663. // Store each of the LDAP class attributes
  664. if(SUCCEEDED(pDirectorySearchSchemaContainer->GetColumn(hADSSearchOuter, (LPWSTR)LDAP_DISPLAY_NAME_ATTR, &adsColumn)))
  665. {
  666. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  667. {
  668. result = E_FAIL;
  669. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  670. }
  671. else
  672. {
  673. // Create the CADSIClass
  674. (*pppszClassNames)[dwSecondCount] = NULL;
  675. if((*pppszClassNames)[dwSecondCount] = new WCHAR[wcslen(adsColumn.pADsValues->CaseIgnoreString) + 1])
  676. wcscpy((*pppszClassNames)[dwSecondCount], adsColumn.pADsValues->CaseIgnoreString);
  677. pDirectorySearchSchemaContainer->FreeColumn( &adsColumn );
  678. dwSecondCount++;
  679. }
  680. }
  681. }
  682. }
  683. }
  684. }
  685. // Something went wrong? Release allocated resources
  686. if(dwSecondCount != dwFirstCount)
  687. {
  688. // Delete the contents of the array
  689. for(DWORD j=0; j<dwSecondCount; j++)
  690. {
  691. delete [] (*pppszClassNames)[j];
  692. }
  693. // Delete the array itself
  694. delete [] (*pppszClassNames);
  695. // Set return values to empty
  696. *pppszClassNames = NULL;
  697. *pdwNumRows = 0;
  698. result = E_FAIL;
  699. }
  700. else
  701. *pdwNumRows = dwFirstCount;
  702. // Close the search
  703. pDirectorySearchSchemaContainer->CloseSearchHandle(hADSSearchOuter);
  704. } // ExecuteSearch() - Outer
  705. delete [] lpszSearchFilter;
  706. }
  707. else // THIS IS THE SPECIAL CASE WHERE ALL SUBCLASSES (RECURSIVELY) OF A GIVEN CLASS ARE REQUIRED
  708. {
  709. // A lot of work has to be done. THis is handled by CLDAPClassProvider. Hence control shold never reach here
  710. result = E_FAIL;
  711. }
  712. return result;
  713. }
  714. // Gets the IDIrectoryObject interface on an ADSI instance
  715. HRESULT CLDAPHelper :: GetADSIInstance(LPCWSTR szADSIPath, CADSIInstance **ppADSIObject, ProvDebugLog *pLogObject)
  716. {
  717. HRESULT result;
  718. IDirectoryObject *pDirectoryObject;
  719. *ppADSIObject = NULL;
  720. try
  721. {
  722. if(SUCCEEDED(result = ADsOpenObject((LPWSTR)szADSIPath, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, (LPVOID *)&pDirectoryObject)))
  723. {
  724. if(*ppADSIObject = new CADSIInstance(szADSIPath, pDirectoryObject))
  725. {
  726. PADS_ATTR_INFO pAttributeEntries;
  727. DWORD dwNumAttributes;
  728. if(SUCCEEDED(result = pDirectoryObject->GetObjectAttributes(NULL, -1, &pAttributeEntries, &dwNumAttributes)))
  729. {
  730. (*ppADSIObject)->SetAttributes(pAttributeEntries, dwNumAttributes);
  731. PADS_OBJECT_INFO pObjectInfo = NULL;
  732. if(SUCCEEDED(result = pDirectoryObject->GetObjectInformation(&pObjectInfo)))
  733. {
  734. (*ppADSIObject)->SetObjectInfo(pObjectInfo);
  735. }
  736. else
  737. pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance GetObjectInformation() FAILED on %s with %x\r\n", szADSIPath, result);
  738. }
  739. else
  740. pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance GetObjectAttributes() FAILED on %s with %x\r\n", szADSIPath, result);
  741. }
  742. else
  743. result = E_OUTOFMEMORY;
  744. pDirectoryObject->Release();
  745. }
  746. else
  747. pLogObject->WriteW( L"CLDAPHelper :: GetADSIInstance ADsOpenObject() FAILED on %s with %x\r\n", szADSIPath, result);
  748. }
  749. catch ( ... )
  750. {
  751. if ( *ppADSIObject )
  752. {
  753. delete *ppADSIObject;
  754. *ppADSIObject = NULL;
  755. }
  756. throw;
  757. }
  758. if(!SUCCEEDED(result))
  759. {
  760. delete *ppADSIObject;
  761. *ppADSIObject = NULL;
  762. }
  763. return result;
  764. }
  765. //***************************************************************************
  766. //
  767. // CLDAPHelper :: CreateADSIPath
  768. //
  769. // Purpose : Forms the ADSI path from a class or property name
  770. //
  771. // Parameters:
  772. // lpszLDAPSchemaObjectName : The LDAP class or property name
  773. // lpszSchemaContainerSuffix : The suffix to be used. The actual object fetced will be:
  774. // LDAP://CN=<lpszLDAPSchemaObjectName>,<lpszSchemaContainerSuffix>
  775. //
  776. // Return Value: The ADSI path to the class or property object. This has to
  777. // be deallocated by the user
  778. //***************************************************************************
  779. LPWSTR CLDAPHelper :: CreateADSIPath(LPCWSTR lpszLDAPSchemaObjectName,
  780. LPCWSTR lpszSchemaContainerSuffix)
  781. {
  782. LPWSTR lpszADSIObjectPath = NULL;
  783. if(lpszADSIObjectPath = new WCHAR[wcslen(LDAP_CN_EQUALS) + wcslen(lpszLDAPSchemaObjectName) + wcslen(COMMA_STR) + wcslen(lpszSchemaContainerSuffix) + 1])
  784. {
  785. wcscpy(lpszADSIObjectPath, LDAP_CN_EQUALS);
  786. wcscat(lpszADSIObjectPath, lpszLDAPSchemaObjectName);
  787. wcscat(lpszADSIObjectPath, COMMA_STR);
  788. wcscat(lpszADSIObjectPath, lpszSchemaContainerSuffix);
  789. }
  790. return lpszADSIObjectPath;
  791. }
  792. //***************************************************************************
  793. //
  794. // CLDAPHelper :: UnmangleWBEMNameToLDAP
  795. //
  796. // Purpose : Converts a mangled WBEM name to LDAP
  797. // An underscore in LDAP maps to two underscores in WBEM
  798. // An hyphen in LDAP maps to one underscore in WBEM
  799. //
  800. // Parameters:
  801. // lpszWBEMName : The WBEM class or property name
  802. //
  803. // Return Value: The LDAP name to the class or property object. This has to
  804. // be deallocated by the user
  805. //***************************************************************************
  806. LPWSTR CLDAPHelper :: UnmangleWBEMNameToLDAP(LPCWSTR lpszWBEMName)
  807. {
  808. DWORD iPrefixLength = 0;
  809. if(_wcsnicmp(lpszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
  810. {
  811. iPrefixLength = LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH;
  812. }
  813. else if (_wcsnicmp(lpszWBEMName, LDAP_CLASS_NAME_PREFIX, LDAP_CLASS_NAME_PREFIX_LENGTH) == 0)
  814. {
  815. iPrefixLength = LDAP_CLASS_NAME_PREFIX_LENGTH;
  816. }
  817. else
  818. return NULL;
  819. // The length of the resulting string (LDAP Name) is bound to be less than of equal to the length of WBEM name
  820. // So let's allocate the same as the wbem name length
  821. DWORD dwWbemNameLength = wcslen(lpszWBEMName) - iPrefixLength;
  822. LPWSTR lpszLDAPName = NULL;
  823. if(lpszLDAPName = new WCHAR[dwWbemNameLength + 1])
  824. {
  825. LPCWSTR lpszWBEMNameWithoutPrefix = lpszWBEMName + iPrefixLength;
  826. DWORD j=0;
  827. for(DWORD i=0; i<dwWbemNameLength; )
  828. {
  829. switch(lpszWBEMNameWithoutPrefix[i])
  830. {
  831. case (L'_'):
  832. if(lpszWBEMNameWithoutPrefix[i+1] == L'_')
  833. {
  834. i += 2;
  835. lpszLDAPName[j++] = L'_';
  836. }
  837. else
  838. {
  839. i++;
  840. lpszLDAPName[j++] = L'-';
  841. }
  842. break;
  843. default:
  844. lpszLDAPName[j++] = lpszWBEMNameWithoutPrefix[i++];
  845. }
  846. }
  847. lpszLDAPName[j] = NULL;
  848. }
  849. return lpszLDAPName;
  850. }
  851. //***************************************************************************
  852. //
  853. // CLDAPHelper :: MangleLDAPNameToWBEM
  854. //
  855. // Purpose : Converts a LDAP name to WBEM by mangling it
  856. // An underscore in LDAP maps to two underscores in WBEM
  857. // An hyphen in LDAP maps to one underscore in WBEM
  858. //
  859. // Parameters:
  860. // lpszLDAPName : The LDAP class or property name
  861. //
  862. // Return Value: The LDAP name to the class or property object. This has to
  863. // be deallocated by the user
  864. //***************************************************************************
  865. LPWSTR CLDAPHelper :: MangleLDAPNameToWBEM(LPCWSTR lpszLDAPName, BOOLEAN bArtificalName)
  866. {
  867. if(!lpszLDAPName)
  868. return NULL;
  869. // The length of the resulting string (WBEM Name) is bound to be less than of equal to twice the length of LDAP name
  870. // So let's allocate double the LDAP name length
  871. DWORD dwLDAPNameLength = wcslen(lpszLDAPName);
  872. DWORD dwPrefixLength = (bArtificalName)? LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH : LDAP_CLASS_NAME_PREFIX_LENGTH;
  873. LPWSTR lpszWBEMName = NULL;
  874. if(lpszWBEMName = new WCHAR[2*dwLDAPNameLength + dwPrefixLength + 1])
  875. {
  876. // Prefix "DS_" or "ADS_"
  877. if(bArtificalName)
  878. wcscpy(lpszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX);
  879. else
  880. wcscpy(lpszWBEMName, LDAP_CLASS_NAME_PREFIX);
  881. DWORD j=dwPrefixLength;
  882. for(DWORD i=0; i<dwLDAPNameLength; i++)
  883. {
  884. switch(lpszLDAPName[i])
  885. {
  886. case (__TEXT('-')):
  887. lpszWBEMName[j++] = L'_';
  888. break;
  889. case (__TEXT('_')):
  890. lpszWBEMName[j++] = L'_';
  891. lpszWBEMName[j++] = L'_';
  892. break;
  893. default:
  894. lpszWBEMName[j++] = lpszLDAPName[i];
  895. }
  896. }
  897. lpszWBEMName[j] = NULL;
  898. }
  899. return lpszWBEMName;
  900. }
  901. void CLDAPHelper :: DeleteAttributeContents(PADS_ATTR_INFO pAttribute)
  902. {
  903. // delete the name
  904. delete [] pAttribute->pszAttrName;
  905. // Delete each value
  906. for(DWORD i=0; i<pAttribute->dwNumValues; i++)
  907. DeleteADsValueContents(pAttribute->pADsValues + i);
  908. // Delete the array of values
  909. delete [] pAttribute->pADsValues;
  910. }
  911. void CLDAPHelper :: DeleteADsValueContents(PADSVALUE pValue)
  912. {
  913. switch(pValue->dwType)
  914. {
  915. // Nothing to delete
  916. case ADSTYPE_BOOLEAN:
  917. case ADSTYPE_INTEGER:
  918. case ADSTYPE_LARGE_INTEGER:
  919. break;
  920. case ADSTYPE_UTC_TIME:
  921. case ADSTYPE_DN_STRING:
  922. case ADSTYPE_CASE_EXACT_STRING:
  923. case ADSTYPE_CASE_IGNORE_STRING:
  924. case ADSTYPE_PRINTABLE_STRING:
  925. case ADSTYPE_NUMERIC_STRING:
  926. delete [] pValue->DNString;
  927. break;
  928. case ADSTYPE_OCTET_STRING:
  929. case ADSTYPE_NT_SECURITY_DESCRIPTOR:
  930. delete [] (pValue->OctetString.lpValue);
  931. break;
  932. case ADSTYPE_DN_WITH_BINARY:
  933. delete [] (pValue->pDNWithBinary->lpBinaryValue);
  934. delete [] (pValue->pDNWithBinary->pszDNString);
  935. delete pValue->pDNWithBinary;
  936. break;
  937. case ADSTYPE_DN_WITH_STRING:
  938. delete [] (pValue->pDNWithString->pszStringValue);
  939. delete [] (pValue->pDNWithString->pszDNString);
  940. delete pValue->pDNWithString;
  941. break;
  942. default:
  943. // Cause a Null Pointer violation intentionally
  944. // Otherwise we leak memory
  945. {
  946. assert(0);
  947. }
  948. break;
  949. }
  950. }
  951. //***************************************************************************
  952. //
  953. // CLDAPHelper :: ExecuteQuery
  954. //
  955. // Purpose : See Header
  956. //***************************************************************************
  957. HRESULT CLDAPHelper :: ExecuteQuery(
  958. LPCWSTR pszPathToRoot,
  959. PADS_SEARCHPREF_INFO pSearchInfo,
  960. DWORD dwSearchInfoCount,
  961. LPCWSTR pszLDAPQuery,
  962. CADSIInstance ***pppADSIInstances,
  963. DWORD *pdwNumRows,
  964. ProvDebugLog *pLogObject)
  965. {
  966. // Initialize the return values
  967. HRESULT result = E_FAIL;
  968. *pdwNumRows = 0;
  969. *pppADSIInstances = NULL;
  970. // Bind to the node from which the search should start
  971. IDirectorySearch *pDirectorySearchContainer = NULL;
  972. if(SUCCEEDED(result = ADsOpenObject((LPWSTR)pszPathToRoot, NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (LPVOID *)&pDirectorySearchContainer)))
  973. {
  974. try
  975. {
  976. // Now perform a search for the attribute DISTINGUISHED_NAME_ATTR name
  977. if(SUCCEEDED(result = pDirectorySearchContainer->SetSearchPreference(pSearchInfo, dwSearchInfoCount)))
  978. {
  979. ADS_SEARCH_HANDLE hADSSearchOuter;
  980. if(SUCCEEDED(result = pDirectorySearchContainer->ExecuteSearch((LPWSTR) pszLDAPQuery, (LPWSTR *)&ADS_PATH_ATTR, 1, &hADSSearchOuter)))
  981. {
  982. *pdwNumRows = 0;
  983. // Calculate the number of rows first.
  984. while(SUCCEEDED(result = pDirectorySearchContainer->GetNextRow(hADSSearchOuter)) &&
  985. result != S_ADS_NOMORE_ROWS)
  986. (*pdwNumRows) ++;
  987. try
  988. {
  989. // Do only if there were any rows
  990. if(*pdwNumRows)
  991. {
  992. // The index of the attribute being processed
  993. DWORD i = 0;
  994. // Allocate enough memory for the classes and names
  995. *pppADSIInstances = NULL;
  996. if(*pppADSIInstances = new CADSIInstance * [*pdwNumRows])
  997. {
  998. try
  999. {
  1000. // Get the columns for the attributes
  1001. ADS_SEARCH_COLUMN adsColumn;
  1002. CADSIInstance *pADSIInstance = NULL;
  1003. // Move to the first row
  1004. if (SUCCEEDED(result = pDirectorySearchContainer->GetFirstRow(hADSSearchOuter))&&
  1005. result != S_ADS_NOMORE_ROWS)
  1006. {
  1007. // Store each of the LDAP class attributes
  1008. if(SUCCEEDED(pDirectorySearchContainer->GetColumn(hADSSearchOuter, (LPWSTR)ADS_PATH_ATTR, &adsColumn)))
  1009. {
  1010. try
  1011. {
  1012. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  1013. result = E_FAIL;
  1014. else
  1015. {
  1016. // Create the CADSIInstance
  1017. // Now get the attributes on this object
  1018. if(SUCCEEDED(result = GetADSIInstance(adsColumn.pADsValues->DNString, &pADSIInstance, pLogObject)))
  1019. {
  1020. (*pppADSIInstances)[i] = pADSIInstance;
  1021. i++;
  1022. }
  1023. else
  1024. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetADSIInstance() FAILED on %s with %x\r\n", adsColumn.pADsValues->DNString, result);
  1025. }
  1026. }
  1027. catch ( ... )
  1028. {
  1029. pDirectorySearchContainer->FreeColumn( &adsColumn );
  1030. throw;
  1031. }
  1032. // Free resouces
  1033. pDirectorySearchContainer->FreeColumn( &adsColumn );
  1034. }
  1035. else
  1036. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetColumn() FAILED on %s with %x\r\n", pszLDAPQuery, result);
  1037. // Get the other rows now
  1038. if(SUCCEEDED(result))
  1039. {
  1040. while(SUCCEEDED(result = pDirectorySearchContainer->GetNextRow(hADSSearchOuter))&&
  1041. result != S_ADS_NOMORE_ROWS)
  1042. {
  1043. // Store each of the LDAP class attributes
  1044. if(SUCCEEDED(pDirectorySearchContainer->GetColumn(hADSSearchOuter, (LPWSTR)ADS_PATH_ATTR, &adsColumn)))
  1045. {
  1046. try
  1047. {
  1048. if(adsColumn.dwADsType == ADSTYPE_PROV_SPECIFIC)
  1049. result = E_FAIL;
  1050. else
  1051. {
  1052. // Create the CADSIInstance
  1053. // Now get the attributes on this object
  1054. if(SUCCEEDED(result = GetADSIInstance(adsColumn.pADsValues->DNString, &pADSIInstance, pLogObject)))
  1055. {
  1056. (*pppADSIInstances)[i] = pADSIInstance;
  1057. i++;
  1058. }
  1059. else
  1060. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetADSIInstance() FAILED on %s with %x\r\n", adsColumn.pADsValues->DNString, result);
  1061. }
  1062. }
  1063. catch ( ... )
  1064. {
  1065. pDirectorySearchContainer->FreeColumn( &adsColumn );
  1066. throw;
  1067. }
  1068. // Free resouces
  1069. pDirectorySearchContainer->FreeColumn( &adsColumn );
  1070. }
  1071. else
  1072. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetColumn() FAILED on %s with %x\r\n", pszLDAPQuery, result);
  1073. }
  1074. }
  1075. }
  1076. else
  1077. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery GetFirstRow() FAILED on %s with %x\r\n", pszLDAPQuery, result);
  1078. }
  1079. catch ( ... )
  1080. {
  1081. // Delete the contents of the array
  1082. for(DWORD j=0; j<i; j++)
  1083. delete (*pppADSIInstances)[j];
  1084. // Delete the array itself
  1085. delete [] (*pppADSIInstances);
  1086. // Set return values to empty
  1087. *pppADSIInstances = NULL;
  1088. *pdwNumRows = 0;
  1089. throw;
  1090. }
  1091. }
  1092. // Something went wrong? Release allocated resources
  1093. if(i != *pdwNumRows)
  1094. {
  1095. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery() Difference between Number of rows in 2 searches %d %d on %s Am invalidating the search as FAILED\r\n", i, *pdwNumRows, pszLDAPQuery);
  1096. // Delete the contents of the array
  1097. for(DWORD j=0; j<i; j++)
  1098. delete (*pppADSIInstances)[j];
  1099. // Delete the array itself
  1100. delete [] (*pppADSIInstances);
  1101. // Set return values to empty
  1102. *pppADSIInstances = NULL;
  1103. *pdwNumRows = 0;
  1104. result = E_FAIL;
  1105. }
  1106. }
  1107. }
  1108. catch ( ... )
  1109. {
  1110. pDirectorySearchContainer->CloseSearchHandle(hADSSearchOuter);
  1111. throw;
  1112. }
  1113. // Close the search.
  1114. pDirectorySearchContainer->CloseSearchHandle(hADSSearchOuter);
  1115. } // ExecuteSearch()
  1116. else
  1117. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery ExecuteSearch() %s FAILED with %x\r\n", pszLDAPQuery, result);
  1118. } // SetSearchPreference()
  1119. else
  1120. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery SetSearchPreference() on %s FAILED with %x \r\n", pszPathToRoot, result);
  1121. }
  1122. catch ( ... )
  1123. {
  1124. pDirectorySearchContainer->Release();
  1125. throw;
  1126. }
  1127. pDirectorySearchContainer->Release();
  1128. } // ADsOpenObject
  1129. else
  1130. pLogObject->WriteW( L"CLDAPHelper :: ExecuteQuery ADsOpenObject() on %s FAILED with %x \r\n", pszPathToRoot, result);
  1131. return result;
  1132. }