Leaked source code of windows server 2003
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.

1479 lines
46 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1992 - 1995
  6. //
  7. // File: cdssrch.cxx
  8. //
  9. // Contents: Microsoft ADs NDS Provider Generic Object
  10. //
  11. //
  12. // History: 03-02-97 ShankSh Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "nds.hxx"
  16. #pragma hdrstop
  17. const int NO_NDS_RESULT_HANDLES = 32;
  18. static
  19. HRESULT
  20. NdsValueToADsColumn(
  21. LPWSTR pszColumnName,
  22. DWORD dwSyntaxId,
  23. DWORD dwValues,
  24. LPBYTE lpValue,
  25. ADS_SEARCH_COLUMN * pColumn
  26. );
  27. static
  28. HRESULT
  29. NdsValueToADsColumnAppend(
  30. DWORD dwSyntaxId,
  31. DWORD dwValues,
  32. LPBYTE lpValue,
  33. ADS_SEARCH_COLUMN * pColumn
  34. );
  35. static
  36. HRESULT
  37. NdsAddAttributes(
  38. IN ADS_SEARCH_HANDLE hSearchHandle,
  39. OUT HANDLE *phSearchResult
  40. );
  41. //
  42. // Sets the appropriate search preferences.
  43. //
  44. HRESULT
  45. CNDSGenObject::SetSearchPreference(
  46. IN PADS_SEARCHPREF_INFO pSearchPrefs,
  47. IN DWORD dwNumPrefs
  48. )
  49. {
  50. HRESULT hr = S_OK;
  51. BOOL fWarning = FALSE;
  52. DWORD i;
  53. if (!pSearchPrefs && dwNumPrefs > 0) {
  54. RRETURN (E_ADS_BAD_PARAMETER);
  55. }
  56. for (i=0; i<dwNumPrefs; i++) {
  57. pSearchPrefs[i].dwStatus = ADS_STATUS_S_OK;
  58. switch(pSearchPrefs[i].dwSearchPref) {
  59. case ADS_SEARCHPREF_ASYNCHRONOUS:
  60. case ADS_SEARCHPREF_SIZE_LIMIT:
  61. case ADS_SEARCHPREF_TIME_LIMIT:
  62. case ADS_SEARCHPREF_TIMEOUT:
  63. case ADS_SEARCHPREF_PAGESIZE:
  64. case ADS_SEARCHPREF_PAGED_TIME_LIMIT:
  65. case ADS_SEARCHPREF_CHASE_REFERRALS:
  66. //
  67. // Can't be set
  68. //
  69. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF;
  70. fWarning = TRUE;
  71. continue;
  72. case ADS_SEARCHPREF_DEREF_ALIASES:
  73. if (pSearchPrefs[i].vValue.dwType != ADSTYPE_INTEGER) {
  74. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE;
  75. fWarning = TRUE;
  76. continue;
  77. }
  78. switch (pSearchPrefs[i].vValue.Integer) {
  79. case ADS_DEREF_NEVER:
  80. _SearchPref._fDerefAliases = FALSE;
  81. break;
  82. case ADS_DEREF_ALWAYS:
  83. _SearchPref._fDerefAliases = TRUE;
  84. break;
  85. default:
  86. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE;
  87. fWarning = TRUE;
  88. continue;
  89. }
  90. break;
  91. case ADS_SEARCHPREF_ATTRIBTYPES_ONLY:
  92. if (pSearchPrefs[i].vValue.dwType != ADSTYPE_BOOLEAN) {
  93. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE;
  94. fWarning = TRUE;
  95. continue;
  96. }
  97. _SearchPref._fAttrsOnly = pSearchPrefs[i].vValue.Boolean;
  98. break;
  99. case ADS_SEARCHPREF_SEARCH_SCOPE:
  100. if (pSearchPrefs[i].vValue.dwType != ADSTYPE_INTEGER) {
  101. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE;
  102. fWarning = TRUE;
  103. continue;
  104. }
  105. switch (pSearchPrefs[i].vValue.Integer) {
  106. case ADS_SCOPE_ONELEVEL:
  107. _SearchPref._iScope = 0;
  108. break;
  109. case ADS_SCOPE_SUBTREE:
  110. _SearchPref._iScope = 1;
  111. break;
  112. case ADS_SCOPE_BASE:
  113. _SearchPref._iScope = 2;
  114. break;
  115. default:
  116. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREFVALUE;
  117. fWarning = TRUE;
  118. continue;
  119. }
  120. break;
  121. default:
  122. pSearchPrefs[i].dwStatus = ADS_STATUS_INVALID_SEARCHPREF;
  123. fWarning = TRUE;
  124. continue;
  125. }
  126. }
  127. RRETURN (fWarning ? S_ADS_ERRORSOCCURRED : S_OK);
  128. }
  129. HRESULT
  130. CNDSGenObject::ExecuteSearch(
  131. IN LPWSTR pszSearchFilter,
  132. IN LPWSTR * pAttributeNames,
  133. IN DWORD dwNumberAttributes,
  134. OUT PADS_SEARCH_HANDLE phSearchHandle
  135. )
  136. {
  137. PNDS_SEARCHINFO phSearchInfo = NULL;
  138. LPWSTR pszNDSContext = NULL, szCurrAttr = NULL;
  139. DWORD dwAttrNamesLen = 0;
  140. HRESULT hr = S_OK;
  141. ULONG i, j;
  142. LPWSTR pszAttrNameBuffer = NULL, *ppszAttrs = NULL;
  143. if (!phSearchHandle) {
  144. RRETURN (E_ADS_BAD_PARAMETER);
  145. }
  146. //
  147. // Allocate search handle
  148. //
  149. phSearchInfo = (PNDS_SEARCHINFO) AllocADsMem(sizeof(NDS_SEARCHINFO));
  150. if(!phSearchInfo)
  151. BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
  152. if (pszSearchFilter) {
  153. phSearchInfo->_pszSearchFilter = AllocADsStr(pszSearchFilter);
  154. }
  155. else {
  156. phSearchInfo->_pszSearchFilter = AllocADsStr(L"(object class=*)");
  157. }
  158. if(!(phSearchInfo->_pszSearchFilter))
  159. BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
  160. hr = BuildNDSPathFromADsPath(
  161. _ADsPath,
  162. &phSearchInfo->_pszBindContext
  163. );
  164. BAIL_ON_FAILURE(hr);
  165. hr = AdsNdsGenerateParseTree(
  166. phSearchInfo->_pszSearchFilter,
  167. phSearchInfo->_pszBindContext,
  168. &phSearchInfo->_pQueryNode
  169. );
  170. BAIL_ON_FAILURE(hr);
  171. phSearchInfo->_fADsPathPresent = FALSE;
  172. phSearchInfo->_fADsPathReturned = FALSE;
  173. if (dwNumberAttributes == -1) {
  174. //
  175. // Specifies returning all attributes
  176. //
  177. phSearchInfo->_ppszAttrs = NULL;
  178. phSearchInfo->_pszAttrNameBuffer = NULL;
  179. phSearchInfo->_fADsPathPresent = TRUE;
  180. }
  181. else {
  182. ppszAttrs = (LPWSTR *) AllocADsMem(
  183. sizeof(LPWSTR) *
  184. (dwNumberAttributes + 1)
  185. );
  186. if (!ppszAttrs)
  187. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  188. for (i = 0; i < dwNumberAttributes; i++)
  189. dwAttrNamesLen+= (wcslen(pAttributeNames[i]) + 1) * sizeof(WCHAR);
  190. pszAttrNameBuffer = (LPWSTR) AllocADsMem(
  191. dwAttrNamesLen
  192. );
  193. if (!pszAttrNameBuffer)
  194. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  195. szCurrAttr = pszAttrNameBuffer;
  196. for (i = 0, j = 0; i < dwNumberAttributes; i++) {
  197. wcscpy(szCurrAttr, pAttributeNames[i]);
  198. ppszAttrs[j] = szCurrAttr;
  199. szCurrAttr += wcslen(ppszAttrs[j]) + 1;
  200. if(_wcsicmp(ppszAttrs[j], L"ADsPath") == 0) {
  201. //
  202. // ADsPath need not be sent
  203. //
  204. phSearchInfo->_fADsPathPresent = TRUE;
  205. }
  206. else {
  207. j++;
  208. }
  209. }
  210. ppszAttrs[j] = NULL;
  211. phSearchInfo->_ppszAttrs = ppszAttrs;
  212. phSearchInfo->_pszAttrNameBuffer = pszAttrNameBuffer;
  213. }
  214. phSearchInfo->_hConnection = NULL;
  215. phSearchInfo->_dwIterHandle = NDS_INITIAL_SEARCH;
  216. phSearchInfo->_pSearchResults = NULL;
  217. phSearchInfo->_cSearchResults = 0;
  218. phSearchInfo->_dwCurrResult = 0;
  219. phSearchInfo->_fResultPrefetched = FALSE;
  220. phSearchInfo->_fCheckForDuplicates = TRUE;
  221. phSearchInfo->_dwCurrAttr = 0;
  222. phSearchInfo->_SearchPref = _SearchPref;
  223. *phSearchHandle = phSearchInfo;
  224. RRETURN(S_OK);
  225. error:
  226. if(phSearchInfo) {
  227. if(phSearchInfo->_pszBindContext)
  228. FreeADsStr(phSearchInfo->_pszBindContext);
  229. if(phSearchInfo->_pszSearchFilter)
  230. FreeADsStr(phSearchInfo->_pszSearchFilter);
  231. if(phSearchInfo->_ppszAttrs)
  232. FreeADsMem(phSearchInfo->_ppszAttrs);
  233. if(phSearchInfo->_pszAttrNameBuffer)
  234. FreeADsMem(phSearchInfo->_pszAttrNameBuffer);
  235. FreeADsMem(phSearchInfo);
  236. }
  237. RRETURN (hr);
  238. }
  239. HRESULT
  240. CNDSGenObject::AbandonSearch(
  241. IN ADS_SEARCH_HANDLE hSearchHandle
  242. )
  243. {
  244. RRETURN(E_NOTIMPL);
  245. }
  246. HRESULT
  247. CNDSGenObject::CloseSearchHandle (
  248. IN ADS_SEARCH_HANDLE hSearchHandle
  249. )
  250. {
  251. HRESULT hr = S_OK;
  252. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  253. DWORD dwStatus;
  254. if (!phSearchInfo)
  255. RRETURN (E_ADS_BAD_PARAMETER);
  256. if (phSearchInfo->_pQueryNode) {
  257. dwStatus = NwNdsDeleteQueryTree(phSearchInfo->_pQueryNode);
  258. if (dwStatus) {
  259. hr = HRESULT_FROM_WIN32(GetLastError());
  260. }
  261. }
  262. if (phSearchInfo->_hConnection) {
  263. dwStatus = NwNdsCloseObject(phSearchInfo->_hConnection);
  264. if (dwStatus) {
  265. hr = HRESULT_FROM_WIN32(GetLastError());
  266. }
  267. }
  268. if(phSearchInfo->_pszBindContext)
  269. FreeADsStr(phSearchInfo->_pszBindContext);
  270. if(phSearchInfo->_pszSearchFilter)
  271. FreeADsStr(phSearchInfo->_pszSearchFilter);
  272. if(phSearchInfo->_ppszAttrs)
  273. FreeADsMem(phSearchInfo->_ppszAttrs);
  274. if(phSearchInfo->_pszAttrNameBuffer)
  275. FreeADsMem(phSearchInfo->_pszAttrNameBuffer);
  276. if (phSearchInfo->_pSearchResults) {
  277. for (DWORD i=0; i <= phSearchInfo->_dwCurrResult; i++) {
  278. NwNdsFreeBuffer(phSearchInfo->_pSearchResults[i]._hSearchResult);
  279. }
  280. FreeADsMem(phSearchInfo->_pSearchResults);
  281. }
  282. FreeADsMem(phSearchInfo);
  283. RRETURN (hr);
  284. }
  285. HRESULT
  286. CNDSGenObject::GetFirstRow(
  287. IN ADS_SEARCH_HANDLE hSearchHandle
  288. )
  289. {
  290. RRETURN(E_NOTIMPL);
  291. }
  292. HRESULT
  293. CNDSGenObject::GetNextRow(
  294. IN ADS_SEARCH_HANDLE hSearchHandle
  295. )
  296. {
  297. HRESULT hr;
  298. DWORD dwStatus = NO_ERROR;
  299. PNDS_SEARCH_RESULT pResult, pNextResult;
  300. LPNDS_OBJECT_INFO pObject, pNextObject;
  301. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  302. if (!phSearchInfo) {
  303. RRETURN(E_ADS_BAD_PARAMETER);
  304. }
  305. if (phSearchInfo->_fCheckForDuplicates) {
  306. phSearchInfo->_dwCurrAttr = 0;
  307. phSearchInfo->_fADsPathReturned = FALSE;
  308. }
  309. if (!phSearchInfo->_hConnection) {
  310. dwStatus = ADsNwNdsOpenObject(
  311. phSearchInfo->_pszBindContext,
  312. _Credentials,
  313. &phSearchInfo->_hConnection,
  314. NULL,
  315. NULL,
  316. NULL,
  317. NULL
  318. );
  319. if (dwStatus) {
  320. hr = HRESULT_FROM_WIN32(GetLastError());
  321. RRETURN (hr);
  322. }
  323. }
  324. if (phSearchInfo->_pSearchResults) {
  325. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  326. if (pResult->_pObjects &&
  327. ((pResult->_lObjectCurrent+1) < pResult->_lObjects)) {
  328. pResult->_lObjectCurrent++;
  329. RRETURN(S_OK);
  330. }
  331. if (pResult->_lObjectCurrent+1 == pResult->_lObjects &&
  332. phSearchInfo->_fResultPrefetched) {
  333. phSearchInfo->_dwCurrResult++;
  334. pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  335. pNextResult->_lObjectCurrent = 0;
  336. phSearchInfo->_fResultPrefetched = FALSE;
  337. if(phSearchInfo->_fCheckForDuplicates) {
  338. pObject = pResult->_pObjects + pResult->_lObjectCurrent;
  339. pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent;
  340. if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) {
  341. //
  342. // Duplicates; Skip one more result
  343. //
  344. if (pNextResult->_lObjectCurrent+1 < pNextResult->_lObjects)
  345. pNextResult->_lObjectCurrent++;
  346. else
  347. {
  348. pNextResult->_lObjectCurrent++;
  349. RRETURN(S_ADS_NOMORE_ROWS);
  350. }
  351. }
  352. }
  353. if( pNextResult->_lObjectCurrent >= pNextResult->_lObjects &&
  354. phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS)
  355. RRETURN(S_ADS_NOMORE_ROWS);
  356. else
  357. RRETURN(S_OK);
  358. }
  359. else if( pResult->_lObjectCurrent+1 >= pResult->_lObjects &&
  360. phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS)
  361. {
  362. // Make sure _lObjectCurrent doesn't exceed _lObjects. If the
  363. // result set is empty, _lObjectCurrent should stay at -1
  364. if( ((pResult->_lObjectCurrent+1) == pResult->_lObjects) &&
  365. (pResult->_lObjectCurrent != -1) )
  366. pResult->_lObjectCurrent++;
  367. RRETURN(S_ADS_NOMORE_ROWS);
  368. }
  369. }
  370. if (!phSearchInfo->_pQueryNode) {
  371. //
  372. // querynode not setup yet
  373. //
  374. RRETURN (E_FAIL);
  375. }
  376. if(!phSearchInfo->_pSearchResults) {
  377. //
  378. // Allocate an array of handles to Search Handles
  379. //
  380. phSearchInfo->_pSearchResults = (PNDS_SEARCH_RESULT) AllocADsMem(
  381. sizeof(NDS_SEARCH_RESULT) *
  382. NO_NDS_RESULT_HANDLES);
  383. if(!phSearchInfo->_pSearchResults) {
  384. hr = E_OUTOFMEMORY;
  385. goto error;
  386. }
  387. phSearchInfo->_dwCurrResult = 0;
  388. phSearchInfo->_cSearchResults = NO_NDS_RESULT_HANDLES;
  389. }
  390. else {
  391. phSearchInfo->_dwCurrResult++;
  392. if (phSearchInfo->_dwCurrResult >= phSearchInfo->_cSearchResults) {
  393. //
  394. // Need to allocate more memory for handles
  395. //
  396. phSearchInfo->_pSearchResults = (PNDS_SEARCH_RESULT) ReallocADsMem(
  397. (void *) phSearchInfo->_pSearchResults,
  398. sizeof(NDS_SEARCH_RESULT) *
  399. phSearchInfo->_cSearchResults,
  400. sizeof(NDS_SEARCH_RESULT) *
  401. (phSearchInfo->_cSearchResults +
  402. NO_NDS_RESULT_HANDLES)
  403. );
  404. if(!phSearchInfo->_pSearchResults) {
  405. hr = E_OUTOFMEMORY;
  406. goto error;
  407. }
  408. phSearchInfo->_cSearchResults += NO_NDS_RESULT_HANDLES;
  409. }
  410. }
  411. pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  412. hr = NdsAddAttributes(phSearchInfo,
  413. &pNextResult->_hSearchResult
  414. );
  415. BAIL_ON_FAILURE(hr);
  416. pNextResult->_lObjects = 0;
  417. pNextResult->_pObjects = NULL;
  418. // Set _lObjectCurrent to -1 so that empty result set is handled correctly.
  419. // If it is set to 0 and the result set is empty, then a subsequent call
  420. // to GetNextRow will not return S_ADS_NOMORE_ROWS. Instead, it will try to
  421. // search again (in the process, possibly allocate memory for
  422. // _pSearchResults etc.). Also, setting it to -1 ensures that a call to
  423. // GetColumn returns error if the result set is empty.
  424. // Setting it to -1 also ensures that if an error occurs during the search,
  425. // subsequent calls to GetNextRow and GetColumn are handled correctly.
  426. pNextResult->_lObjectCurrent = -1;
  427. dwStatus = NwNdsSearch(
  428. phSearchInfo->_hConnection,
  429. _SearchPref._fAttrsOnly ?
  430. NDS_INFO_NAMES : NDS_INFO_ATTR_NAMES_VALUES,
  431. _SearchPref._iScope,
  432. _SearchPref._fDerefAliases,
  433. phSearchInfo->_pQueryNode,
  434. &phSearchInfo->_dwIterHandle,
  435. &pNextResult->_hSearchResult
  436. );
  437. if (dwStatus) {
  438. hr = HRESULT_FROM_WIN32(GetLastError());
  439. RRETURN (hr);
  440. }
  441. DWORD dwType;
  442. dwStatus = NwNdsGetObjectListFromBuffer(
  443. pNextResult->_hSearchResult,
  444. (DWORD *) (&pNextResult->_lObjects),
  445. &dwType,
  446. &pNextResult->_pObjects
  447. );
  448. if (dwStatus) {
  449. dwStatus = GetLastError();
  450. if (dwStatus == ERROR_NO_DATA)
  451. RRETURN(S_ADS_NOMORE_ROWS);
  452. else
  453. RRETURN (HRESULT_FROM_WIN32(dwStatus));
  454. }
  455. if (pNextResult->_lObjects > 0) {
  456. pNextResult->_lObjectCurrent = 0;
  457. if(phSearchInfo->_fCheckForDuplicates && phSearchInfo->_dwCurrResult > 0) {
  458. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult-1]);
  459. pObject = pResult->_pObjects + pResult->_lObjectCurrent;
  460. pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent;
  461. if (!_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) {
  462. //
  463. // Duplicates; Skip one more result
  464. //
  465. pNextResult->_lObjectCurrent++;
  466. }
  467. }
  468. if( pNextResult->_lObjectCurrent >= pNextResult->_lObjects &&
  469. phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS)
  470. RRETURN(S_ADS_NOMORE_ROWS);
  471. RRETURN(S_OK);
  472. }
  473. else
  474. RRETURN(E_FAIL);
  475. error:
  476. RRETURN(hr);
  477. }
  478. HRESULT
  479. CNDSGenObject::GetPreviousRow(
  480. IN ADS_SEARCH_HANDLE hSearchHandle
  481. )
  482. {
  483. PNDS_SEARCH_RESULT pResult, pPrevResult;
  484. LPNDS_OBJECT_INFO pPrevObject, pObject;
  485. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  486. if(!phSearchInfo || !phSearchInfo->_pSearchResults)
  487. RRETURN(E_FAIL);
  488. if (phSearchInfo->_fCheckForDuplicates) {
  489. phSearchInfo->_dwCurrAttr = 0;
  490. phSearchInfo->_fADsPathReturned = FALSE;
  491. }
  492. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  493. if (pResult->_lObjectCurrent > 0)
  494. {
  495. pResult->_lObjectCurrent--;
  496. if(phSearchInfo->_fCheckForDuplicates &&
  497. (phSearchInfo->_dwCurrResult > 0) && (0 == pResult->_lObjectCurrent))
  498. {
  499. pPrevResult = &(phSearchInfo->_pSearchResults[
  500. phSearchInfo->_dwCurrResult - 1]);
  501. pPrevObject = pPrevResult->_pObjects + pPrevResult->_lObjects - 1;
  502. pObject = pResult->_pObjects + pResult->_lObjectCurrent;
  503. if(!_wcsicmp(pObject->szObjectName, pPrevObject->szObjectName)) {
  504. // Current row is a duplicate. Go to previous result
  505. phSearchInfo->_dwCurrResult--;
  506. pResult = &(phSearchInfo->_pSearchResults[
  507. phSearchInfo->_dwCurrResult]);
  508. pResult->_lObjectCurrent = pResult->_lObjects-1;
  509. phSearchInfo->_fResultPrefetched = TRUE;
  510. }
  511. }
  512. }
  513. else if (phSearchInfo->_dwCurrResult > 0) {
  514. phSearchInfo->_dwCurrResult--;
  515. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  516. pResult->_lObjectCurrent = pResult->_lObjects-1;
  517. phSearchInfo->_fResultPrefetched = TRUE;
  518. }
  519. else if(0 == pResult->_lObjectCurrent)
  520. // we are at the very beginning of the result set
  521. pResult->_lObjectCurrent--;
  522. else
  523. RRETURN(S_ADS_NOMORE_ROWS);
  524. RRETURN(S_OK);
  525. }
  526. HRESULT
  527. CNDSGenObject::GetColumn(
  528. IN ADS_SEARCH_HANDLE hSearchHandle,
  529. IN LPWSTR pszColumnName,
  530. OUT PADS_SEARCH_COLUMN pColumn
  531. )
  532. {
  533. HRESULT hr = S_OK;
  534. DWORD dwStatus;
  535. DWORD dwSyntaxId = 0;
  536. DWORD dwNumValues = 0;
  537. LPNDS_ATTR_INFO pAttribute;
  538. PNDS_SEARCH_RESULT pResult, pNextResult;
  539. LPNDS_OBJECT_INFO pObject, pNextObject;
  540. DWORD cAttr;
  541. BOOL fRowAdvanced = FALSE;
  542. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  543. if( !pColumn ||
  544. !phSearchInfo ||
  545. !phSearchInfo->_pSearchResults )
  546. RRETURN (E_ADS_BAD_PARAMETER);
  547. pColumn->pszAttrName = NULL;
  548. pColumn->dwADsType = ADSTYPE_INVALID;
  549. pColumn->pADsValues = NULL;
  550. pColumn->dwNumValues = 0;
  551. pColumn->hReserved = NULL;
  552. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  553. if( pResult->_lObjectCurrent < 0 )
  554. RRETURN (E_ADS_BAD_PARAMETER);
  555. pObject = pResult->_pObjects + pResult->_lObjectCurrent;
  556. pColumn->pszAttrName = AllocADsStr(pszColumnName);
  557. if (pColumn->pszAttrName)
  558. BAIL_ON_FAILURE(hr);
  559. if(!_wcsicmp (pszColumnName, L"ADsPath")) {
  560. LPWSTR szNDSPath = pObject->szObjectFullName;
  561. //
  562. // Build the ADsPathName
  563. //
  564. WCHAR szTree[MAX_PATH];
  565. WCHAR szCN[MAX_PATH];
  566. WCHAR szADsPath[MAX_PATH];
  567. // Building the CN and the TreeName
  568. LPWSTR szCurrent = szNDSPath;
  569. szCurrent+=2;
  570. while ((WCHAR)(*szCurrent) != (WCHAR)'\\')
  571. szCurrent++;
  572. wcsncpy( szTree,
  573. szNDSPath,
  574. (UINT) (szCurrent-szNDSPath) );
  575. // Make the first two characters "//" instead of "\\"
  576. szTree[0] = (WCHAR)'/';
  577. szTree[1] = (WCHAR)'/';
  578. szTree[szCurrent-szNDSPath] = (WCHAR)'\0';
  579. szCurrent++;
  580. wcscpy( szCN,
  581. szCurrent );
  582. // Building the ADsPath
  583. hr = BuildADsPathFromNDSPath(
  584. szTree,
  585. szCN,
  586. szADsPath
  587. );
  588. BAIL_ON_FAILURE(hr);
  589. if(*szADsPath) {
  590. pColumn->pADsValues = (PADSVALUE) AllocADsMem(sizeof(ADSVALUE));
  591. if (!pColumn->pADsValues)
  592. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  593. pColumn->dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  594. pColumn->dwNumValues = 1;
  595. pColumn->pADsValues[0].dwType = ADSTYPE_CASE_IGNORE_STRING;
  596. pColumn->pADsValues[0].CaseIgnoreString = AllocADsStr(szADsPath);
  597. if (!pColumn->pADsValues[0].CaseIgnoreString)
  598. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  599. pColumn->hReserved = pColumn->pADsValues[0].CaseIgnoreString;
  600. }
  601. RRETURN(S_OK);
  602. }
  603. if (phSearchInfo->_SearchPref._fAttrsOnly) {
  604. //
  605. // Only Names got. So, don't return any values
  606. //
  607. RRETURN (S_OK);
  608. }
  609. pAttribute = (LPNDS_ATTR_INFO)pObject->lpAttribute;
  610. for (cAttr=0;cAttr<pObject->dwNumberOfAttributes;cAttr++,pAttribute++) {
  611. if (_wcsicmp(
  612. pAttribute->szAttributeName,
  613. pszColumnName
  614. ) == 0)
  615. break;
  616. }
  617. if (cAttr == pObject->dwNumberOfAttributes) {
  618. if(pResult->_lObjectCurrent+1 != pResult->_lObjects ||
  619. (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS &&
  620. !phSearchInfo->_fResultPrefetched)) {
  621. //
  622. // No need to look in the next result set;
  623. //
  624. BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET);
  625. }
  626. else {
  627. //
  628. // There is a chance that the column may come in the next
  629. // result set. So, fetch the next set of results.
  630. //
  631. phSearchInfo->_fCheckForDuplicates = FALSE;
  632. hr = GetNextRow(
  633. phSearchInfo
  634. );
  635. phSearchInfo->_fCheckForDuplicates = TRUE;
  636. BAIL_ON_FAILURE(hr);
  637. if (hr == S_ADS_NOMORE_ROWS) {
  638. BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET);
  639. }
  640. fRowAdvanced = TRUE;
  641. pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  642. pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent;
  643. if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) {
  644. //
  645. // No need to look in the next object;
  646. //
  647. BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET);
  648. }
  649. else {
  650. //
  651. // Look in the next object
  652. //
  653. pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute;
  654. for (cAttr=0;cAttr<pNextObject->dwNumberOfAttributes;cAttr++,pAttribute++) {
  655. if (_wcsicmp(
  656. pAttribute->szAttributeName,
  657. pszColumnName
  658. ) == 0)
  659. break;
  660. }
  661. if (cAttr == pNextObject->dwNumberOfAttributes) {
  662. //
  663. // Didn't find in the next result set containing the row too
  664. //
  665. BAIL_ON_FAILURE(hr = E_ADS_COLUMN_NOT_SET);
  666. }
  667. }
  668. }
  669. }
  670. hr = NdsValueToADsColumn(
  671. pszColumnName,
  672. pAttribute->dwSyntaxId,
  673. pAttribute->dwNumberOfValues,
  674. pAttribute->lpValue,
  675. pColumn
  676. );
  677. BAIL_ON_FAILURE(hr);
  678. //
  679. // Added in to support the case when one multivalue attribute is split into 2 packets. The
  680. // following case checks
  681. // 1) if we haven't advanced the row, if we have advanced already, the whole
  682. // Attribute will already be completely residing in the second packet
  683. // 2) the attribute was the last attribute from the last packet, thus
  684. // the next attribute, (the first attribute of the next row) might be
  685. // the same.
  686. //
  687. if ((!fRowAdvanced) &&
  688. (cAttr == (pObject->dwNumberOfAttributes - 1))) {
  689. //
  690. // If there is indeed a need to try out an extra packet
  691. //
  692. if(pResult->_lObjectCurrent+1 != pResult->_lObjects ||
  693. (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS &&
  694. !phSearchInfo->_fResultPrefetched)) {
  695. //
  696. // No need to look in the next result set;
  697. //
  698. hr = S_OK;
  699. goto done;
  700. }
  701. else {
  702. //
  703. // There is a chance that the column may come in the next
  704. // result set. So, fetch the next set of results.
  705. //
  706. phSearchInfo->_fCheckForDuplicates = FALSE;
  707. hr = GetNextRow(
  708. phSearchInfo
  709. );
  710. phSearchInfo->_fCheckForDuplicates = TRUE;
  711. BAIL_ON_FAILURE(hr);
  712. if (hr == S_ADS_NOMORE_ROWS) {
  713. hr = S_OK;
  714. goto done;
  715. }
  716. fRowAdvanced = TRUE;
  717. pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  718. pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent;
  719. if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) {
  720. //
  721. // No need to look in the next object, since objname is different
  722. //
  723. hr = S_OK;
  724. goto done;
  725. }
  726. else {
  727. //
  728. // Look in the next object, look for the same attribute
  729. //
  730. pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute;
  731. for (cAttr=0;cAttr<pNextObject->dwNumberOfAttributes;cAttr++,pAttribute++) {
  732. if (_wcsicmp(
  733. pAttribute->szAttributeName,
  734. pszColumnName
  735. ) == 0)
  736. break;
  737. }
  738. if (cAttr == pNextObject->dwNumberOfAttributes) {
  739. //
  740. // Didn't find in the next result set containing the row too
  741. //
  742. hr = S_OK;
  743. goto done;
  744. }
  745. }
  746. }
  747. //
  748. // If found, we'll append it to the last column
  749. //
  750. hr = NdsValueToADsColumnAppend(
  751. pAttribute->dwSyntaxId,
  752. pAttribute->dwNumberOfValues,
  753. pAttribute->lpValue,
  754. pColumn
  755. );
  756. BAIL_ON_FAILURE(hr);
  757. }
  758. done:
  759. if (fRowAdvanced) {
  760. phSearchInfo->_fCheckForDuplicates = FALSE;
  761. GetPreviousRow(phSearchInfo);
  762. phSearchInfo->_fCheckForDuplicates = TRUE;
  763. }
  764. RRETURN(S_OK);
  765. error:
  766. if (fRowAdvanced) {
  767. phSearchInfo->_fCheckForDuplicates = FALSE;
  768. GetPreviousRow(phSearchInfo);
  769. phSearchInfo->_fCheckForDuplicates = TRUE;
  770. }
  771. FreeColumn(pColumn);
  772. RRETURN (hr);
  773. }
  774. HRESULT
  775. CNDSGenObject::GetNextColumnName(
  776. IN ADS_SEARCH_HANDLE hSearchHandle,
  777. OUT LPWSTR * ppszColumnName
  778. )
  779. {
  780. HRESULT hr = S_OK;
  781. LPNDS_ATTR_INFO pAttribute;
  782. LPNDS_ATTR_INFO pAttributeOld = NULL;
  783. LPNDS_NAME_ONLY pNameOnlyAttr;
  784. PNDS_SEARCH_RESULT pResult, pNextResult;
  785. LPNDS_OBJECT_INFO pObject, pNextObject;
  786. BOOL fRowAdvanced = FALSE;
  787. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  788. if( !phSearchInfo ||
  789. !phSearchInfo->_pSearchResults ||
  790. !ppszColumnName)
  791. RRETURN (E_ADS_BAD_PARAMETER);
  792. *ppszColumnName = NULL;
  793. pResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  794. if( pResult->_lObjectCurrent < 0 )
  795. RRETURN (E_ADS_BAD_PARAMETER);
  796. pObject = pResult->_pObjects + pResult->_lObjectCurrent;
  797. pNameOnlyAttr = (LPNDS_NAME_ONLY)pObject->lpAttribute +
  798. phSearchInfo->_dwCurrAttr;
  799. pAttribute = (LPNDS_ATTR_INFO)pObject->lpAttribute +
  800. phSearchInfo->_dwCurrAttr;
  801. //
  802. // Get the last attribute's name to test it to avoid getting duplicate
  803. // column names. This will happen if a multi-value got divided into two
  804. // packets. In that case, both attribute names would be the same.
  805. // We are only getting the last attribute if this object has greater than
  806. // 1 object, or else if this attribute is the first attribute, there would
  807. // not be a one before
  808. //
  809. if (phSearchInfo->_dwCurrAttr > 0) {
  810. pAttributeOld = pAttribute - 1;
  811. }
  812. if (phSearchInfo->_dwCurrAttr >= pObject->dwNumberOfAttributes) {
  813. if(pResult->_lObjectCurrent+1 != pResult->_lObjects ||
  814. (phSearchInfo->_dwIterHandle == NDS_NO_MORE_ITERATIONS &&
  815. !phSearchInfo->_fResultPrefetched)) {
  816. //
  817. // No need to look in the next result set;
  818. //
  819. hr = S_ADS_NOMORE_COLUMNS;
  820. goto error;
  821. }
  822. else {
  823. //
  824. // There is a chance that the column may come in the next
  825. // result set. So, fetch the next set of results.
  826. //
  827. phSearchInfo->_fCheckForDuplicates = FALSE;
  828. hr = GetNextRow(
  829. phSearchInfo
  830. );
  831. phSearchInfo->_fCheckForDuplicates = TRUE;
  832. BAIL_ON_FAILURE(hr);
  833. if (hr == S_ADS_NOMORE_ROWS) {
  834. hr = S_ADS_NOMORE_COLUMNS;
  835. goto error;
  836. }
  837. fRowAdvanced = TRUE;
  838. pNextResult = &(phSearchInfo->_pSearchResults[phSearchInfo->_dwCurrResult]);
  839. pNextObject = pNextResult->_pObjects + pNextResult->_lObjectCurrent;
  840. if (_wcsicmp(pObject->szObjectName, pNextObject->szObjectName)) {
  841. //
  842. // No need to look in the next object;
  843. //
  844. hr = S_ADS_NOMORE_COLUMNS;
  845. goto error;
  846. }
  847. else {
  848. //
  849. // Look in the next object
  850. //
  851. pNameOnlyAttr = (LPNDS_NAME_ONLY)pNextObject->lpAttribute +
  852. phSearchInfo->_dwCurrAttr -
  853. pObject->dwNumberOfAttributes;
  854. pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute +
  855. phSearchInfo->_dwCurrAttr -
  856. pObject->dwNumberOfAttributes;
  857. //
  858. // If the new attribute is after the first attribute in the new object,
  859. // we'll reset AttributeOld to point to the attribute before this.
  860. // Because the old attribute will be the one before the current one
  861. // in this case.
  862. //
  863. if ((phSearchInfo->_dwCurrAttr - pObject->dwNumberOfAttributes) > 0) {
  864. pAttributeOld = pAttribute - 1;
  865. }
  866. if (phSearchInfo->_dwCurrAttr >= (pObject->dwNumberOfAttributes +
  867. pNextObject->dwNumberOfAttributes)) {
  868. //
  869. // Didn't find in the next result set
  870. // containing the row too
  871. //
  872. hr = S_ADS_NOMORE_COLUMNS;
  873. goto error;
  874. }
  875. //
  876. // If it is a duplicate column, go on to the next one
  877. //
  878. if (pAttributeOld) {
  879. if(wcscmp(pAttribute->szAttributeName,
  880. pAttributeOld->szAttributeName) == 0) {
  881. phSearchInfo->_dwCurrAttr++;
  882. if (phSearchInfo->_dwCurrAttr >= (pObject->dwNumberOfAttributes +
  883. pNextObject->dwNumberOfAttributes)) {
  884. //
  885. // Didn't find in the next result set
  886. // containing the row too
  887. //
  888. hr = S_ADS_NOMORE_COLUMNS;
  889. goto error;
  890. }
  891. pNameOnlyAttr = (LPNDS_NAME_ONLY)pNextObject->lpAttribute +
  892. phSearchInfo->_dwCurrAttr -
  893. pObject->dwNumberOfAttributes;
  894. pAttribute = (LPNDS_ATTR_INFO)pNextObject->lpAttribute +
  895. phSearchInfo->_dwCurrAttr -
  896. pObject->dwNumberOfAttributes;
  897. }
  898. }
  899. }
  900. }
  901. }
  902. if (phSearchInfo->_SearchPref._fAttrsOnly)
  903. *ppszColumnName = AllocADsStr(
  904. pNameOnlyAttr->szName
  905. );
  906. else
  907. *ppszColumnName = AllocADsStr(
  908. pAttribute->szAttributeName
  909. );
  910. phSearchInfo->_dwCurrAttr++;
  911. if (fRowAdvanced) {
  912. phSearchInfo->_fCheckForDuplicates = FALSE;
  913. GetPreviousRow(phSearchInfo);
  914. phSearchInfo->_fCheckForDuplicates = TRUE;
  915. }
  916. RRETURN(S_OK);
  917. error:
  918. if (fRowAdvanced) {
  919. phSearchInfo->_fCheckForDuplicates = FALSE;
  920. GetPreviousRow(phSearchInfo);
  921. phSearchInfo->_fCheckForDuplicates = TRUE;
  922. }
  923. if (*ppszColumnName)
  924. FreeADsStr(*ppszColumnName);
  925. if (hr == S_ADS_NOMORE_COLUMNS && phSearchInfo->_fADsPathPresent) {
  926. //
  927. // If ADsPath was specified, return it as the last column in the row
  928. //
  929. if (!phSearchInfo->_fADsPathReturned) {
  930. *ppszColumnName = AllocADsStr(L"ADsPath");
  931. phSearchInfo->_fADsPathReturned = TRUE;
  932. hr = S_OK;
  933. }
  934. else {
  935. hr = S_ADS_NOMORE_COLUMNS;
  936. }
  937. }
  938. RRETURN (hr);
  939. }
  940. HRESULT
  941. CNDSGenObject::FreeColumn(
  942. IN PADS_SEARCH_COLUMN pColumn
  943. )
  944. {
  945. HRESULT hr = S_OK;
  946. if(!pColumn)
  947. RRETURN (E_ADS_BAD_PARAMETER);
  948. if (pColumn->pszAttrName)
  949. FreeADsStr(pColumn->pszAttrName);
  950. switch(pColumn->dwADsType) {
  951. case ADSTYPE_CASE_IGNORE_STRING:
  952. if ((PNDSOBJECT)pColumn->hReserved) {
  953. //ADsPath does not have hReserved, it is a direct string allocation
  954. if (pColumn->pADsValues) {
  955. FreeADsStr(pColumn->pADsValues[0].CaseIgnoreString);
  956. }
  957. }
  958. break;
  959. default:
  960. // Nothing to free
  961. break;
  962. }
  963. if (pColumn->pADsValues)
  964. FreeADsMem(pColumn->pADsValues);
  965. RRETURN(hr);
  966. }
  967. HRESULT
  968. NdsValueToADsColumn(
  969. LPWSTR pszColumnName,
  970. DWORD dwSyntaxId,
  971. DWORD dwValues,
  972. LPBYTE lpValue,
  973. ADS_SEARCH_COLUMN * pColumn
  974. )
  975. {
  976. HRESULT hr = S_OK;
  977. LPASN1_TYPE_1 lpASN1_1;
  978. LPASN1_TYPE_7 lpASN1_7;
  979. LPASN1_TYPE_8 lpASN1_8;
  980. LPASN1_TYPE_9 lpASN1_9;
  981. LPASN1_TYPE_14 lpASN1_14;
  982. LPASN1_TYPE_24 lpASN1_24;
  983. DWORD i, j;
  984. if(!pszColumnName || !pColumn)
  985. RRETURN(E_ADS_BAD_PARAMETER);
  986. pColumn->hReserved = NULL;
  987. pColumn->dwNumValues = dwValues;
  988. pColumn->pADsValues = (PADSVALUE) AllocADsMem(
  989. sizeof(ADSVALUE) * dwValues
  990. );
  991. if (!pColumn->pADsValues)
  992. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  993. if (dwSyntaxId >= g_cMapNdsTypeToADsType)
  994. pColumn->dwADsType = ADSTYPE_INVALID;
  995. else
  996. pColumn->dwADsType = g_MapNdsTypeToADsType[dwSyntaxId];
  997. switch (dwSyntaxId) {
  998. // WIDE STRING
  999. case NDS_SYNTAX_ID_1:
  1000. case NDS_SYNTAX_ID_2:
  1001. case NDS_SYNTAX_ID_3:
  1002. case NDS_SYNTAX_ID_4:
  1003. case NDS_SYNTAX_ID_5:
  1004. case NDS_SYNTAX_ID_10:
  1005. case NDS_SYNTAX_ID_11:
  1006. case NDS_SYNTAX_ID_20:
  1007. for (i=0; i < dwValues; i++) {
  1008. lpASN1_1 = (LPASN1_TYPE_1) lpValue + i;
  1009. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1010. pColumn->pADsValues[i].CaseIgnoreString = lpASN1_1->DNString;
  1011. }
  1012. break;
  1013. case NDS_SYNTAX_ID_14 :
  1014. for (i=0; i < dwValues; i++) {
  1015. lpASN1_14 = (LPASN1_TYPE_14) lpValue + i;
  1016. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1017. pColumn->pADsValues[i].CaseIgnoreString = lpASN1_14->Address;
  1018. }
  1019. break;
  1020. // BYTE STREAM
  1021. case NDS_SYNTAX_ID_9:
  1022. for (i=0; i < dwValues; i++) {
  1023. lpASN1_9 = (LPASN1_TYPE_9) lpValue + i;
  1024. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1025. pColumn->pADsValues[i].OctetString.dwLength =lpASN1_9->Length;
  1026. pColumn->pADsValues[i].OctetString.lpValue = lpASN1_9->OctetString;
  1027. }
  1028. break;
  1029. // BOOLEAN
  1030. case NDS_SYNTAX_ID_7:
  1031. for (i=0; i < dwValues; i++) {
  1032. lpASN1_7 = (LPASN1_TYPE_7) lpValue + i;
  1033. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1034. pColumn->pADsValues[i].Boolean = lpASN1_7->Boolean;
  1035. }
  1036. break;
  1037. // INTEGER
  1038. case NDS_SYNTAX_ID_8:
  1039. case NDS_SYNTAX_ID_22:
  1040. case NDS_SYNTAX_ID_27:
  1041. for (i=0; i < dwValues; i++) {
  1042. lpASN1_8 = (LPASN1_TYPE_8) lpValue + i;
  1043. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1044. pColumn->pADsValues[i].Integer = lpASN1_8->Integer;
  1045. }
  1046. break;
  1047. case NDS_SYNTAX_ID_24 :
  1048. for (i=0; i < dwValues; i++) {
  1049. lpASN1_24 = (LPASN1_TYPE_24) lpValue + i;
  1050. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1051. hr = ConvertDWORDtoSYSTEMTIME(
  1052. lpASN1_24->Time,
  1053. &(pColumn->pADsValues[i].UTCTime)
  1054. );
  1055. BAIL_ON_FAILURE(hr);
  1056. }
  1057. break;
  1058. case NDS_SYNTAX_ID_6 :
  1059. case NDS_SYNTAX_ID_12 :
  1060. case NDS_SYNTAX_ID_13 :
  1061. case NDS_SYNTAX_ID_15 :
  1062. case NDS_SYNTAX_ID_16 :
  1063. case NDS_SYNTAX_ID_17 :
  1064. case NDS_SYNTAX_ID_18 :
  1065. case NDS_SYNTAX_ID_19 :
  1066. case NDS_SYNTAX_ID_21 :
  1067. case NDS_SYNTAX_ID_23 :
  1068. case NDS_SYNTAX_ID_25 :
  1069. case NDS_SYNTAX_ID_26 :
  1070. default:
  1071. for (i=0; i < dwValues; i++) {
  1072. pColumn->pADsValues[i].dwType = pColumn->dwADsType;
  1073. pColumn->pADsValues[i].ProviderSpecific.dwLength =0;
  1074. pColumn->pADsValues[i].ProviderSpecific.lpValue = NULL;
  1075. }
  1076. break;
  1077. }
  1078. RRETURN(hr);
  1079. error:
  1080. if (pColumn->pADsValues)
  1081. FreeADsMem(pColumn->pADsValues);
  1082. RRETURN(hr);
  1083. }
  1084. /*++
  1085. Routine Description:
  1086. Given a column, this function will append more values to the end
  1087. Return Value:
  1088. S_OK on success, error code otherwise
  1089. --*/
  1090. HRESULT
  1091. NdsValueToADsColumnAppend(
  1092. DWORD dwSyntaxId,
  1093. DWORD dwValues,
  1094. LPBYTE lpValue,
  1095. ADS_SEARCH_COLUMN * pColumn
  1096. )
  1097. {
  1098. HRESULT hr = S_OK;
  1099. LPASN1_TYPE_1 lpASN1_1;
  1100. LPASN1_TYPE_7 lpASN1_7;
  1101. LPASN1_TYPE_8 lpASN1_8;
  1102. LPASN1_TYPE_9 lpASN1_9;
  1103. LPASN1_TYPE_14 lpASN1_14;
  1104. LPASN1_TYPE_24 lpASN1_24;
  1105. DWORD i, j;
  1106. PADSVALUE pADsValuesNew = NULL;
  1107. DWORD dwValuesBase;
  1108. if(!pColumn)
  1109. RRETURN(E_ADS_BAD_PARAMETER);
  1110. dwValuesBase = pColumn->dwNumValues;
  1111. //
  1112. // Allocate memory for new values + old values
  1113. //
  1114. pADsValuesNew = (PADSVALUE) AllocADsMem(
  1115. sizeof(ADSVALUE) * (pColumn->dwNumValues + dwValues)
  1116. );
  1117. if (!pADsValuesNew) {
  1118. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1119. }
  1120. //
  1121. // Copy old values into new array, and free the old one
  1122. //
  1123. memcpy(pADsValuesNew,
  1124. pColumn->pADsValues,
  1125. sizeof(ADSVALUE) * dwValuesBase);
  1126. FreeADsMem(pColumn->pADsValues);
  1127. pColumn->pADsValues = pADsValuesNew;
  1128. switch (dwSyntaxId) {
  1129. // WIDE STRING
  1130. case NDS_SYNTAX_ID_1:
  1131. case NDS_SYNTAX_ID_2:
  1132. case NDS_SYNTAX_ID_3:
  1133. case NDS_SYNTAX_ID_4:
  1134. case NDS_SYNTAX_ID_5:
  1135. case NDS_SYNTAX_ID_10:
  1136. case NDS_SYNTAX_ID_11:
  1137. case NDS_SYNTAX_ID_20:
  1138. for (i=0; i < dwValues; i++) {
  1139. lpASN1_1 = (LPASN1_TYPE_1) lpValue + i;
  1140. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1141. pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString = lpASN1_1->DNString;
  1142. }
  1143. break;
  1144. case NDS_SYNTAX_ID_14 :
  1145. for (i=0; i < dwValues; i++) {
  1146. lpASN1_14 = (LPASN1_TYPE_14) lpValue + i;
  1147. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1148. pColumn->pADsValues[dwValuesBase+i].CaseIgnoreString = lpASN1_14->Address;
  1149. }
  1150. break;
  1151. // BYTE STREAM
  1152. case NDS_SYNTAX_ID_9:
  1153. for (i=0; i < dwValues; i++) {
  1154. lpASN1_9 = (LPASN1_TYPE_9) lpValue + i;
  1155. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1156. pColumn->pADsValues[dwValuesBase+i].OctetString.dwLength =lpASN1_9->Length;
  1157. pColumn->pADsValues[dwValuesBase+i].OctetString.lpValue = lpASN1_9->OctetString;
  1158. }
  1159. break;
  1160. // BOOLEAN
  1161. case NDS_SYNTAX_ID_7:
  1162. for (i=0; i < dwValues; i++) {
  1163. lpASN1_7 = (LPASN1_TYPE_7) lpValue + i;
  1164. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1165. pColumn->pADsValues[dwValuesBase+i].Boolean = lpASN1_7->Boolean;
  1166. }
  1167. break;
  1168. // INTEGER
  1169. case NDS_SYNTAX_ID_8:
  1170. case NDS_SYNTAX_ID_22:
  1171. case NDS_SYNTAX_ID_27:
  1172. for (i=0; i < dwValues; i++) {
  1173. lpASN1_8 = (LPASN1_TYPE_8) lpValue + i;
  1174. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1175. pColumn->pADsValues[dwValuesBase+i].Integer = lpASN1_8->Integer;
  1176. }
  1177. break;
  1178. case NDS_SYNTAX_ID_24 :
  1179. for (i=0; i < dwValues; i++) {
  1180. lpASN1_24 = (LPASN1_TYPE_24) lpValue + i;
  1181. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1182. hr = ConvertDWORDtoSYSTEMTIME(
  1183. lpASN1_24->Time,
  1184. &(pColumn->pADsValues[dwValuesBase+i].UTCTime)
  1185. );
  1186. BAIL_ON_FAILURE(hr);
  1187. }
  1188. break;
  1189. case NDS_SYNTAX_ID_6 :
  1190. case NDS_SYNTAX_ID_12 :
  1191. case NDS_SYNTAX_ID_13 :
  1192. case NDS_SYNTAX_ID_15 :
  1193. case NDS_SYNTAX_ID_16 :
  1194. case NDS_SYNTAX_ID_17 :
  1195. case NDS_SYNTAX_ID_18 :
  1196. case NDS_SYNTAX_ID_19 :
  1197. case NDS_SYNTAX_ID_21 :
  1198. case NDS_SYNTAX_ID_23 :
  1199. case NDS_SYNTAX_ID_25 :
  1200. case NDS_SYNTAX_ID_26 :
  1201. default:
  1202. for (i=0; i < dwValues; i++) {
  1203. pColumn->pADsValues[dwValuesBase+i].dwType = pColumn->dwADsType;
  1204. pColumn->pADsValues[dwValuesBase+i].ProviderSpecific.dwLength =0;
  1205. pColumn->pADsValues[dwValuesBase+i].ProviderSpecific.lpValue = NULL;
  1206. }
  1207. break;
  1208. }
  1209. pColumn->dwNumValues = pColumn->dwNumValues + dwValues;
  1210. error:
  1211. //
  1212. // We don't need to free memory even in error case because it has been
  1213. // put into the column
  1214. //
  1215. RRETURN(hr);
  1216. }
  1217. HRESULT
  1218. NdsAddAttributes(
  1219. IN ADS_SEARCH_HANDLE hSearchHandle,
  1220. OUT HANDLE *phSearchResult
  1221. )
  1222. {
  1223. DWORD dwStatus = NO_ERROR;
  1224. HANDLE hSearchResult = NULL;
  1225. HRESULT hr;
  1226. DWORD i;
  1227. PNDS_SEARCHINFO phSearchInfo = (PNDS_SEARCHINFO) hSearchHandle;
  1228. if (!phSearchResult || !phSearchResult)
  1229. RRETURN( E_FAIL );
  1230. *phSearchResult = NULL;
  1231. if(!phSearchInfo->_ppszAttrs)
  1232. RRETURN(S_OK);
  1233. dwStatus = NwNdsCreateBuffer( NDS_SEARCH,
  1234. &hSearchResult );
  1235. if (dwStatus) {
  1236. hr = HRESULT_FROM_WIN32(GetLastError());
  1237. goto error;
  1238. }
  1239. for (i=0; phSearchInfo->_ppszAttrs[i]; i++) {
  1240. dwStatus = NwNdsPutInBuffer( phSearchInfo->_ppszAttrs[i],
  1241. 0,
  1242. NULL,
  1243. 0,
  1244. 0,
  1245. hSearchResult );
  1246. if (dwStatus) {
  1247. hr = HRESULT_FROM_WIN32(GetLastError());
  1248. goto error;
  1249. }
  1250. }
  1251. *phSearchResult = hSearchResult;
  1252. RRETURN( S_OK );
  1253. error:
  1254. if(hSearchResult)
  1255. NwNdsFreeBuffer(phSearchInfo);
  1256. RRETURN(hr);
  1257. }