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.

2648 lines
65 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997
  5. //
  6. // File: ndsutil.cxx
  7. //
  8. // Contents: Functions that encapsulate NDS API functions for ADSI
  9. //
  10. //
  11. // History:
  12. // Shanksh Created 10/27/97
  13. //----------------------------------------------------------------------------
  14. #include "nds.hxx"
  15. #pragma hdrstop
  16. HRESULT
  17. ADsNdsOpenContext(
  18. LPWSTR pszNDSTreeName,
  19. CCredentials& Credentials,
  20. PNDS_CONTEXT_HANDLE phADsContext
  21. )
  22. {
  23. NWDSCCODE ccode;
  24. NWDSContextHandle context = 0;
  25. BOOL fLoggedIn = FALSE;
  26. HRESULT hr = S_OK;
  27. PNDS_CONTEXT pADsContext = NULL;
  28. PNDS_CONTEXT *ppADsContext = (PNDS_CONTEXT *) phADsContext;
  29. nuint32 flags;
  30. LPWSTR pszUserName = NULL, pszPassword = NULL;
  31. pnstr8 aPassword = NULL;
  32. nstr8 treeName[MAX_DN_CHARS+1];
  33. DWORD dwLenUserName;
  34. LPWSTR pszCanonicalUserName = NULL;
  35. LPWSTR pbCanonicalUserName = NULL;
  36. LPWSTR pszCanonicalPrefix = L".";
  37. WCHAR szCurrentUserName[MAX_DN_CHARS+1];
  38. if (!ppADsContext) {
  39. RRETURN(E_ADS_BAD_PARAMETER);
  40. }
  41. *ppADsContext = NULL;
  42. //
  43. // Try the cache for the passed in credentials.
  44. //
  45. ENTER_BIND_CRITSECT() ;
  46. if (pADsContext = BindCacheLookup(pszNDSTreeName, Credentials)) {
  47. *ppADsContext = pADsContext ;
  48. LEAVE_BIND_CRITSECT() ;
  49. return S_OK;
  50. }
  51. //
  52. // Entry not found in the cache, need to allocate a new one.
  53. //
  54. hr = BindCacheAllocEntry(&pADsContext) ;
  55. if (FAILED(hr)) {
  56. LEAVE_BIND_CRITSECT() ;
  57. RRETURN(hr);
  58. }
  59. ccode = NWDSCreateContextHandle(&context);
  60. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  61. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  62. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  63. flags &= ~DCV_CANONICALIZE_NAMES;
  64. flags &= ~DCV_XLATE_STRINGS;
  65. flags |= DCV_TYPELESS_NAMES; // for NWDSWhoAmI below
  66. ccode = NWDSSetContext(context, DCK_FLAGS, &flags);
  67. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  68. if (pszNDSTreeName) {
  69. ccode = NWDSSetContext(
  70. context,
  71. DCK_TREE_NAME,
  72. pszNDSTreeName
  73. );
  74. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  75. }
  76. ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
  77. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  78. // Find out who the currently logged-in user (if any) is,
  79. // then reset the DCV_TYPELESS_NAMES flag.
  80. ccode = NWDSWhoAmI(context, (pnstr8)szCurrentUserName);
  81. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  82. flags &= ~DCV_TYPELESS_NAMES;
  83. ccode = NWDSSetContext(context, DCK_FLAGS, &flags);
  84. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  85. hr = Credentials.GetUserName(&pszUserName);
  86. BAIL_ON_FAILURE(hr);
  87. // We want to do the login code if (1) we're not authenticated, or
  88. // (2) we are authenticated, but as a different user. If we're
  89. // doing an ADsGetObject, pszUserName is NULL and case 2 doesn't
  90. // apply.
  91. if ( (!NWDSCanDSAuthenticate(context)) ||
  92. (pszUserName && (_wcsicmp(pszUserName, szCurrentUserName) != 0)) )
  93. {
  94. hr = Credentials.GetPassword(&pszPassword);
  95. BAIL_ON_FAILURE(hr);
  96. if (pszUserName != NULL)
  97. {
  98. //
  99. // If password is NULL, pass a Null string, otherwise Client32 will AV
  100. //
  101. aPassword = AllocateAnsiString(pszPassword);
  102. #if 0
  103. //
  104. // Some builds of the Client32 NDS libraries seem to have a bug in their
  105. // usage of the DCV_CANONICALIZE_NAMES flag, in that they do not behave
  106. // properly when the flag is cleared. The following is a work-around. To
  107. // use it, delete the line above which clears the flag. This code will
  108. // prepend the name with a period (unless it already begins with one),
  109. // achieving the same result.
  110. //
  111. if (*pszUserName == L'.')
  112. {
  113. if (!(pszCanonicalUserName = AllocADsStr(pszUserName)))
  114. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  115. }
  116. else
  117. {
  118. dwLenUserName = wcslen(pszUserName) + 4;
  119. if (!(pbCanonicalUserName = (LPWSTR) AllocADsMem(dwLenUserName * sizeof(WCHAR))))
  120. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  121. wcscpy(pbCanonicalUserName, pszCanonicalPrefix);
  122. wcscat(pbCanonicalUserName, pszUserName);
  123. if (!(pszCanonicalUserName = AllocADsStr(pbCanonicalUserName)))
  124. {
  125. FreeADsMem(pbCanonicalUserName);
  126. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  127. }
  128. FreeADsMem(pbCanonicalUserName);
  129. }
  130. #endif
  131. ccode = NWDSLogin(
  132. context,
  133. 0,
  134. pszUserName ? (pnstr8) pszUserName : (pnstr8) L"",
  135. aPassword ? aPassword : "",
  136. 0
  137. );
  138. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  139. fLoggedIn = TRUE;
  140. }
  141. }
  142. pADsContext->hContext = context;
  143. pADsContext->fLoggedIn = fLoggedIn;
  144. hr = BindCacheAdd(pszNDSTreeName, Credentials, fLoggedIn, pADsContext) ;
  145. BAIL_ON_FAILURE(hr);
  146. *ppADsContext = pADsContext;
  147. if (pszCanonicalUserName)
  148. FreeADsStr(pszCanonicalUserName);
  149. if (pszUserName)
  150. FreeADsStr(pszUserName);
  151. if (pszPassword)
  152. FreeADsStr(pszPassword);
  153. FreeADsMem(aPassword);
  154. LEAVE_BIND_CRITSECT() ;
  155. RRETURN (hr);
  156. error:
  157. if (pszCanonicalUserName)
  158. FreeADsStr(pszCanonicalUserName);
  159. if ( fLoggedIn ) {
  160. NWDSLogout(context);
  161. }
  162. NWDSFreeContext(context);
  163. if (pADsContext) {
  164. FreeADsMem(pADsContext);
  165. }
  166. if (pszUserName)
  167. FreeADsStr(pszUserName);
  168. if (pszPassword)
  169. FreeADsStr(pszPassword);
  170. FreeADsMem(aPassword);
  171. LEAVE_BIND_CRITSECT() ;
  172. RRETURN (hr);
  173. }
  174. HRESULT
  175. ADsNdsCloseContext(
  176. NDS_CONTEXT_HANDLE hADsContext
  177. )
  178. {
  179. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  180. if (!pADsContext) {
  181. RRETURN(E_FAIL);
  182. }
  183. if (BindCacheDeref(pADsContext) == 0) {
  184. //
  185. // ref count has dropped to zero and its gone from cache.
  186. //
  187. if (pADsContext->fLoggedIn) {
  188. NWDSLogout(pADsContext->hContext);
  189. }
  190. NWDSFreeContext(pADsContext->hContext);
  191. FreeADsMem(pADsContext);
  192. }
  193. RRETURN(S_OK);
  194. }
  195. HRESULT
  196. ADsNdsReadObject(
  197. NDS_CONTEXT_HANDLE hADsContext,
  198. LPWSTR pszDn,
  199. DWORD dwInfoType,
  200. LPWSTR *ppszAttrs,
  201. DWORD nAttrs,
  202. pTimeStamp_T pTimeStamp,
  203. PNDS_ATTR_INFO *ppAttrEntries,
  204. DWORD *pAttrsReturned
  205. )
  206. {
  207. NWDSCCODE ccode;
  208. HRESULT hr = S_OK;
  209. nint32 lIterationHandle = NO_MORE_ITERATIONS;
  210. NWDSContextHandle context;
  211. DWORD i, j;
  212. pnstr8 *ppAttrs = NULL, aDn = NULL;
  213. nstr treeName[MAX_DN_CHARS+1];
  214. nuint32 flags;
  215. pBuf_T pInBuf = NULL;
  216. pBuf_T pOutBuf = NULL;
  217. BOOL fAllAttrs = FALSE;
  218. DWORD dwAttrsReturned = 0;
  219. DWORD dwAttrsReturnedCurrIter = 0;
  220. PNDS_ATTR_INFO pAttrEntries = NULL;
  221. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  222. if (!pADsContext || !pAttrsReturned || !ppAttrEntries) {
  223. RRETURN(E_ADS_BAD_PARAMETER);
  224. }
  225. context = pADsContext->hContext;
  226. *ppAttrEntries = NULL;
  227. //
  228. //Allocate the output buffer to hold returned values
  229. //
  230. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pOutBuf);
  231. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  232. ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
  233. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  234. if (nAttrs == (DWORD) -1) {
  235. fAllAttrs = TRUE;
  236. pInBuf = NULL;
  237. }
  238. else {
  239. // Allocate and initialize input buffer a directory services
  240. // read operation.
  241. //
  242. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
  243. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  244. ccode = NWDSInitBuf(context, DSV_READ, pInBuf);
  245. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  246. // To prepare for the read, place the names of the attributes
  247. // into the input buffer
  248. //
  249. for(i = 0; i < nAttrs; i++)
  250. {
  251. ccode = NWDSPutAttrName(context, pInBuf, (pnstr8) ppszAttrs[i]);
  252. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  253. }
  254. }
  255. do {
  256. // Perform the read. The second arg to NWDSRead specifies that
  257. // attribute values are to be returned. The third attribute, FALSE,
  258. // indicates that only attribute information is desired.
  259. //
  260. //
  261. // To ensure that read/search doesn't collide with GenObjectKeyPair().
  262. // GenObjectKeyPair() changes the context state which will cause read/search
  263. // to return type-less DNs
  264. //
  265. EnterCriticalSection(&g_ContextCritSect);
  266. ccode = NWDSRead(
  267. context,
  268. (pnstr8) (!pszDn || (*pszDn == L'\0') ? L"[Root]" : pszDn),
  269. dwInfoType,
  270. fAllAttrs,
  271. pInBuf,
  272. &lIterationHandle,
  273. pOutBuf
  274. );
  275. LeaveCriticalSection(&g_ContextCritSect);
  276. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  277. // If pAttrEntries == NULL, this is the first iteration and there's
  278. // no previous attr list to append to.
  279. if (!pAttrEntries) {
  280. hr = ADsNdsGetAttrListFromBuffer(
  281. hADsContext,
  282. pOutBuf,
  283. FALSE,
  284. (void **) &pAttrEntries,
  285. &dwAttrsReturnedCurrIter
  286. );
  287. } else {
  288. hr = ADsNdsAppendAttrListFromBuffer(
  289. hADsContext,
  290. pOutBuf,
  291. FALSE,
  292. (void **) &pAttrEntries,
  293. &dwAttrsReturnedCurrIter,
  294. dwAttrsReturned
  295. );
  296. }
  297. BAIL_ON_FAILURE(hr);
  298. dwAttrsReturned += dwAttrsReturnedCurrIter;
  299. } while (lIterationHandle != NO_MORE_ITERATIONS);
  300. *pAttrsReturned = dwAttrsReturned;
  301. *ppAttrEntries = pAttrEntries;
  302. error:
  303. NWDSFreeBuf(pInBuf);
  304. NWDSFreeBuf(pOutBuf);
  305. RRETURN(hr);
  306. }
  307. HRESULT
  308. ADsNdsGetAttrListFromBuffer(
  309. NDS_CONTEXT_HANDLE hADsContext,
  310. pBuf_T pBuf,
  311. BOOL fAttrsOnly,
  312. PVOID *ppAttrEntries,
  313. PDWORD pAttrsReturned
  314. )
  315. {
  316. NWCCODE ccode;
  317. HRESULT hr = S_OK;
  318. NWDSContextHandle context;
  319. nuint32 luAttrCount = 0;
  320. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  321. if (!hADsContext || !ppAttrEntries || !pAttrsReturned) {
  322. RRETURN(E_ADS_BAD_PARAMETER);
  323. }
  324. *pAttrsReturned = 0;
  325. context = pADsContext->hContext;
  326. ccode = NWDSGetAttrCount(context, pBuf, &luAttrCount);
  327. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  328. hr = ADsNdsGetAttrsFromBuffer(
  329. hADsContext,
  330. pBuf,
  331. luAttrCount,
  332. fAttrsOnly,
  333. ppAttrEntries
  334. );
  335. BAIL_ON_FAILURE(hr);
  336. *pAttrsReturned = luAttrCount;
  337. error:
  338. RRETURN (hr);
  339. }
  340. HRESULT
  341. ADsNdsAppendAttrListFromBuffer(
  342. NDS_CONTEXT_HANDLE hADsContext,
  343. pBuf_T pBuf,
  344. BOOL fAttrsOnly,
  345. PVOID *ppAttrEntries, // ptr to list to be appended to
  346. PDWORD pdwNewAttrsReturned, // # of new attribs appended
  347. DWORD dwCurrentAttrs // # of attributes currently in list
  348. )
  349. {
  350. NWCCODE ccode;
  351. HRESULT hr = S_OK;
  352. NWDSContextHandle context;
  353. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  354. DWORD cbOld = 0;
  355. DWORD cbNew = 0;
  356. PNDS_ATTR_INFO pCombinedAttrEntries = NULL;
  357. DWORD dwCombinedCurrentIndex = 0; // index of next unused entry
  358. PVOID pNewAttrEntries = NULL;
  359. nuint32 luAttrCount = 0; //count of new attribs (those in pNewAttrEntries)
  360. DWORD i, j;
  361. if (!hADsContext || !ppAttrEntries || !pdwNewAttrsReturned) {
  362. RRETURN(E_ADS_BAD_PARAMETER);
  363. }
  364. // BUGBUG: Ideally, we should be able to handle both NDS_ATTR_INFO and
  365. // NDS_NAME_ONLY entries.
  366. // However, currently we are always called with fAttrsOnly == FALSE,
  367. // and that is all we support.
  368. if (fAttrsOnly)
  369. RRETURN(E_ADS_BAD_PARAMETER);
  370. *pdwNewAttrsReturned = 0;
  371. context = pADsContext->hContext;
  372. // Build the list of the new attributes in this block
  373. ccode = NWDSGetAttrCount(context, pBuf, &luAttrCount);
  374. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  375. hr = ADsNdsGetAttrsFromBuffer(
  376. hADsContext,
  377. pBuf,
  378. luAttrCount,
  379. fAttrsOnly,
  380. &pNewAttrEntries
  381. );
  382. BAIL_ON_FAILURE(hr);
  383. // Append the list of new attributes (luAttrCount entries pointed to by
  384. // pNewAttrEntries) to the list of old attributes (dwCurrentAttrs entries
  385. // pointed to by *ppAttrEntries)
  386. // Allocate a new list big enough to hold old and new attributes.
  387. // We make the list the maximum possible size, assuming no dupes.
  388. // We may shrink it later if there are dupes.
  389. cbOld = dwCurrentAttrs * sizeof(NDS_ATTR_INFO);
  390. cbNew = cbOld + (luAttrCount * sizeof(NDS_ATTR_INFO));
  391. dwCombinedCurrentIndex = dwCurrentAttrs;
  392. pCombinedAttrEntries = (PNDS_ATTR_INFO) ReallocADsMem(
  393. *ppAttrEntries,
  394. cbOld,
  395. cbNew
  396. );
  397. if (!pCombinedAttrEntries)
  398. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  399. *ppAttrEntries = NULL;
  400. // For each new attrib entry, copy it into the combined list (if not
  401. // a dupe) or merge it into the corresponding old entry (if a dupe)
  402. for (j = 0; j < luAttrCount; j++) {
  403. PNDS_ATTR_INFO pNewEntry = ((PNDS_ATTR_INFO)pNewAttrEntries) + j;
  404. DWORD dwDupeIndex = -1;
  405. // Determine if the new entry is a duplicate of an old entry.
  406. // Note the implicit assumption that there is at most one of any
  407. // given attribute entry in the list of old entries (i.e., there
  408. // are no dupes within the list). This should always hold, since
  409. // a NWDSRead should not yield any dupes in its results, and we take
  410. // care of merging dupes between multiple NWDSRead results.
  411. for (i = 0; i < dwCurrentAttrs; i++) {
  412. PNDS_ATTR_INFO pOldEntry = (pCombinedAttrEntries) + i;
  413. if (!_wcsicmp(pOldEntry->szAttributeName, pNewEntry->szAttributeName)) {
  414. // found a dupe
  415. dwDupeIndex = i;
  416. break;
  417. }
  418. }
  419. if (dwDupeIndex == -1) {
  420. // not a duplicate attribute, so just copy it from the new entries list
  421. // to the next available position in the combined entries list
  422. memcpy(
  423. (BYTE*)(pCombinedAttrEntries + dwCombinedCurrentIndex),
  424. (BYTE*)pNewEntry,
  425. sizeof(NDS_ATTR_INFO)
  426. );
  427. dwCombinedCurrentIndex++;
  428. }
  429. else {
  430. // duplicate, merge attribute values
  431. PNDS_ATTR_INFO pOldEntry = (pCombinedAttrEntries) + dwDupeIndex;
  432. cbOld = pOldEntry->dwNumberOfValues * sizeof(NDSOBJECT);
  433. cbNew = cbOld + pNewEntry->dwNumberOfValues * sizeof(NDSOBJECT);
  434. PNDSOBJECT lpValue = (PNDSOBJECT)ReallocADsMem(
  435. pOldEntry->lpValue,
  436. cbOld,
  437. cbNew
  438. );
  439. if (!lpValue)
  440. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  441. pOldEntry->lpValue = lpValue;
  442. // the new NDSOBJECTs will come after the preexisting ones
  443. memcpy(
  444. ((BYTE*) pOldEntry->lpValue) + cbOld,
  445. (BYTE*)pNewEntry->lpValue,
  446. cbNew-cbOld
  447. );
  448. pOldEntry->dwNumberOfValues += pNewEntry->dwNumberOfValues;
  449. FreeADsMem(pNewEntry->lpValue);
  450. pNewEntry->lpValue = NULL;
  451. FreeADsMem(pNewEntry->szAttributeName);
  452. pNewEntry->szAttributeName = NULL;
  453. }
  454. }
  455. // We allocated memory for the combined list assuming there were no duplicates. If
  456. // there were duplicates, the combined list is shorter than what we allocated for,
  457. // and we shrink the allocated list down to size.
  458. if (dwCombinedCurrentIndex < luAttrCount + dwCurrentAttrs) {
  459. PNDS_ATTR_INFO pCombinedAttrEntriesResized;
  460. pCombinedAttrEntriesResized = (PNDS_ATTR_INFO)ReallocADsMem(
  461. pCombinedAttrEntries,
  462. (luAttrCount + dwCurrentAttrs) * sizeof(NDS_ATTR_INFO),
  463. dwCombinedCurrentIndex * sizeof(NDS_ATTR_INFO)
  464. );
  465. if (!pCombinedAttrEntriesResized)
  466. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  467. pCombinedAttrEntries = pCombinedAttrEntriesResized;
  468. }
  469. *ppAttrEntries = pCombinedAttrEntries;
  470. *pdwNewAttrsReturned = dwCombinedCurrentIndex - dwCurrentAttrs;
  471. FreeADsMem(pNewAttrEntries);
  472. RRETURN (hr);
  473. error:
  474. if (pNewAttrEntries)
  475. FreeNdsAttrInfo((PNDS_ATTR_INFO)pNewAttrEntries, luAttrCount);
  476. if (pCombinedAttrEntries)
  477. FreeNdsAttrInfo((PNDS_ATTR_INFO)pCombinedAttrEntries, dwCombinedCurrentIndex);
  478. if (*ppAttrEntries)
  479. FreeNdsAttrInfo((PNDS_ATTR_INFO)*ppAttrEntries, dwCurrentAttrs);
  480. RRETURN (hr);
  481. }
  482. HRESULT
  483. FreeNdsAttrInfo(
  484. PNDS_ATTR_INFO pAttrEntries,
  485. DWORD dwNumEntries
  486. )
  487. {
  488. DWORD i;
  489. PNDS_ATTR_INFO pThisEntry = NULL;
  490. if (!pAttrEntries) {
  491. RRETURN(S_OK);
  492. }
  493. for (i=0; i < dwNumEntries; i++) {
  494. pThisEntry = pAttrEntries+i;
  495. if (pThisEntry->szAttributeName)
  496. FreeADsMem(pThisEntry->szAttributeName);
  497. if (pThisEntry->lpValue)
  498. NdsTypeFreeNdsObjects( pThisEntry->lpValue,
  499. pThisEntry->dwNumberOfValues );
  500. }
  501. FreeADsMem(pAttrEntries);
  502. RRETURN(S_OK);
  503. }
  504. HRESULT
  505. FreeNdsAttrNames(
  506. PNDS_NAME_ONLY pAttrNames,
  507. DWORD dwNumEntries
  508. )
  509. {
  510. DWORD i;
  511. if (!pAttrNames) {
  512. RRETURN(S_OK);
  513. }
  514. for (i=0; i < dwNumEntries; i++) {
  515. if (pAttrNames[i].szName)
  516. FreeADsMem(pAttrNames[i].szName);
  517. }
  518. FreeADsMem(pAttrNames);
  519. RRETURN(S_OK);
  520. }
  521. HRESULT
  522. ADsNdsListObjects(
  523. NDS_CONTEXT_HANDLE hADsContext,
  524. LPWSTR pszDn,
  525. LPWSTR classFilter,
  526. LPWSTR objectFilter,
  527. pTimeStamp_T pTimeStamp,
  528. BOOL fOnlyContainers,
  529. NDS_BUFFER_HANDLE *phBuf
  530. )
  531. {
  532. NWDSCCODE ccode;
  533. HRESULT hr = S_OK;
  534. BOOL fBufAllocated = FALSE;
  535. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  536. PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
  537. if ( !pADsContext || !phBuf) {
  538. RRETURN(E_ADS_BAD_PARAMETER);
  539. }
  540. if( pBufData == NULL) {
  541. pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
  542. if (!pBufData) {
  543. RRETURN(E_OUTOFMEMORY);
  544. }
  545. fBufAllocated = TRUE;
  546. pBufData->lIterationHandle = NO_MORE_ITERATIONS;
  547. pBufData->pOutBuf = NULL;
  548. pBufData->pInBuf = NULL;
  549. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pOutBuf);
  550. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  551. }
  552. else {
  553. if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  554. RRETURN (S_ADS_NOMORE_ROWS);
  555. }
  556. }
  557. ccode = NWDSExtSyncList(
  558. pADsContext->hContext,
  559. (pnstr8) (!pszDn || (*pszDn == L'\0') ? L"[Root]" : pszDn),
  560. (pnstr8) classFilter,
  561. (pnstr8) objectFilter,
  562. &pBufData->lIterationHandle,
  563. NULL,
  564. FALSE,
  565. pBufData->pOutBuf
  566. );
  567. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  568. if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  569. hr = S_ADS_NOMORE_ROWS;
  570. }
  571. else {
  572. hr = S_OK;
  573. }
  574. *phBuf = pBufData;
  575. RRETURN(hr);
  576. error:
  577. if (fBufAllocated) {
  578. if (pBufData->pOutBuf) {
  579. NWDSFreeBuf(pBufData->pOutBuf);
  580. }
  581. FreeADsMem(pBufData);
  582. }
  583. RRETURN(hr);
  584. }
  585. HRESULT
  586. ADsNdsGetObjectListFromBuffer(
  587. NDS_CONTEXT_HANDLE hADsContext,
  588. NDS_BUFFER_HANDLE hBufData,
  589. PDWORD pdwObjectsReturned,
  590. PADSNDS_OBJECT_INFO *ppObjects
  591. )
  592. {
  593. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  594. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  595. nuint32 luObjectCount = 0, luAttrCount = 0;
  596. WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
  597. Object_Info_T objectInfo;
  598. DWORD j, i;
  599. PADSNDS_OBJECT_INFO pThisObject = NULL, pObjectInfo = NULL;
  600. HRESULT hr = S_OK;
  601. NWDSCCODE ccode;
  602. PNDS_ATTR_INFO pAttrEntries = NULL, pThisEntry = NULL;
  603. PNDS_NAME_ONLY pAttrNames = NULL, pThisName = NULL;
  604. if (!pADsContext || !pBufData || !pdwObjectsReturned || !ppObjects ||
  605. !pBufData->pOutBuf ) {
  606. RRETURN(E_ADS_BAD_PARAMETER);
  607. }
  608. *ppObjects = NULL;
  609. *pdwObjectsReturned = 0;
  610. ccode = NWDSGetObjectCount(pADsContext->hContext, pBufData->pOutBuf, &luObjectCount);
  611. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  612. if (luObjectCount) {
  613. pObjectInfo = (PADSNDS_OBJECT_INFO) AllocADsMem(
  614. sizeof(ADSNDS_OBJECT_INFO) *
  615. luObjectCount );
  616. if (!pObjectInfo) {
  617. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  618. }
  619. memset (pObjectInfo, 0x0, sizeof(ADSNDS_OBJECT_INFO) * luObjectCount);
  620. }
  621. for (j = 0; j < luObjectCount; j++) {
  622. pThisObject = pObjectInfo + j;
  623. ccode = NWDSGetObjectName(
  624. pADsContext->hContext,
  625. pBufData->pOutBuf,
  626. (pnstr8) pszTemp,
  627. &luAttrCount,
  628. &objectInfo
  629. );
  630. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  631. pThisObject->szObjectName = AllocADsStr(pszTemp);
  632. pThisObject->szObjectClass = AllocADsStr( (LPWSTR) objectInfo.baseClass);
  633. pThisObject->dwModificationTime = objectInfo.modificationTime;
  634. pThisObject->dwSubordinateCount = objectInfo.subordinateCount;
  635. pThisObject->dwNumAttributes = luAttrCount;
  636. pThisObject->dwObjectFlags = objectInfo.objectFlags;
  637. //
  638. // Get the attributes if we are doing search
  639. //
  640. if (pBufData->dwOperation == DSV_SEARCH ) {
  641. hr = ADsNdsGetAttrsFromBuffer(
  642. hADsContext,
  643. pBufData->pOutBuf,
  644. luAttrCount,
  645. !pBufData->dwInfoType,
  646. &pThisObject->lpAttribute
  647. );
  648. BAIL_ON_FAILURE(hr);
  649. if (!pBufData->dwInfoType)
  650. pThisObject->fNameOnly = TRUE;
  651. else
  652. pThisObject->fNameOnly = FALSE;
  653. }
  654. }
  655. *pdwObjectsReturned = luObjectCount;
  656. *ppObjects = pObjectInfo;
  657. RRETURN(hr);
  658. error:
  659. ADsNdsFreeNdsObjInfoList(pObjectInfo, luObjectCount);
  660. RRETURN(hr);
  661. }
  662. HRESULT
  663. ADsNdsFreeNdsObjInfoList(
  664. PADSNDS_OBJECT_INFO pObjInfo,
  665. DWORD dwNumEntries
  666. )
  667. {
  668. PADSNDS_OBJECT_INFO pThisObjInfo;
  669. if (!pObjInfo)
  670. RRETURN(S_OK);
  671. for (DWORD i = 0; i < dwNumEntries; i++)
  672. {
  673. pThisObjInfo = pObjInfo + i;
  674. FreeADsStr(pThisObjInfo->szObjectName);
  675. FreeADsStr(pThisObjInfo->szObjectClass);
  676. if (pThisObjInfo->fNameOnly)
  677. FreeNdsAttrNames((PNDS_NAME_ONLY)pThisObjInfo->lpAttribute, pThisObjInfo->dwNumAttributes);
  678. else
  679. FreeNdsAttrInfo((PNDS_ATTR_INFO)pThisObjInfo->lpAttribute, pThisObjInfo->dwNumAttributes);
  680. }
  681. FreeADsMem(pObjInfo);
  682. RRETURN(S_OK);
  683. }
  684. HRESULT
  685. ADsNdsGetAttrsFromBuffer(
  686. NDS_CONTEXT_HANDLE hADsContext,
  687. pBuf_T pBuf,
  688. DWORD luAttrCount,
  689. BOOL fAttrsOnly,
  690. PVOID *ppAttrEntries
  691. )
  692. {
  693. NWCCODE ccode;
  694. HRESULT hr = S_OK;
  695. NWDSContextHandle context;
  696. nuint32 luAttrValCount = 0;
  697. nuint32 luAttrValSize = 0;
  698. nuint32 luSyntax;
  699. nptr attrVal = NULL;
  700. PNDS_ATTR_INFO pAttrEntries = NULL, pThisEntry = NULL;
  701. PNDS_NAME_ONLY pAttrNames = NULL, pThisName = NULL;
  702. nstr pszAttrName[MAX_DN_CHARS+1];
  703. DWORD i, j;
  704. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  705. ADsAssert(pADsContext);
  706. ADsAssert(ppAttrEntries);
  707. context = pADsContext->hContext;
  708. if (fAttrsOnly) {
  709. if (luAttrCount) {
  710. pAttrNames = (PNDS_NAME_ONLY) AllocADsMem(
  711. sizeof(NDS_NAME_ONLY) * luAttrCount );
  712. if (!pAttrNames) {
  713. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  714. }
  715. }
  716. for(i = 0; i < luAttrCount; i++) {
  717. // Initialize this entry so that we can free them if an error
  718. // occurs in building this entry
  719. //
  720. ccode = NWDSGetAttrName(context, pBuf, (pnstr8) pszAttrName,
  721. &luAttrValCount, &luSyntax);
  722. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  723. pThisName->szName = AllocADsStr(pszAttrName);
  724. if (!pThisName->szName) {
  725. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  726. }
  727. }
  728. *ppAttrEntries = pAttrNames;
  729. }
  730. else {
  731. if (luAttrCount) {
  732. pAttrEntries = (PNDS_ATTR_INFO) AllocADsMem(
  733. sizeof(NDS_ATTR_INFO) * luAttrCount );
  734. if (!pAttrEntries) {
  735. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  736. }
  737. }
  738. /* Get the name and value for each attribute */
  739. for(i = 0; i < luAttrCount; i++) {
  740. // Initialize this entry so that we can free them if an error
  741. // occurs in building this entry
  742. //
  743. pThisEntry = pAttrEntries+i;
  744. pThisEntry->szAttributeName = NULL;
  745. pThisEntry->dwNumberOfValues = 0;
  746. pThisEntry->lpValue = NULL;
  747. ccode = NWDSGetAttrName(context, pBuf, (pnstr8) pszAttrName,
  748. &luAttrValCount, &luSyntax);
  749. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  750. pThisEntry->szAttributeName = AllocADsStr(pszAttrName);
  751. if (!pThisEntry->szAttributeName) {
  752. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  753. }
  754. pThisEntry->dwNumberOfValues = luAttrValCount;
  755. pThisEntry->dwSyntaxId = luSyntax;
  756. pThisEntry->lpValue = (PNDSOBJECT) AllocADsMem(
  757. luAttrValCount * sizeof(NDSOBJECT)
  758. );
  759. for (j = 0; j < luAttrValCount; j++) {
  760. ccode = NWDSComputeAttrValSize(
  761. context,
  762. pBuf,
  763. luSyntax,
  764. &luAttrValSize
  765. );
  766. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  767. attrVal = AllocADsMem(luAttrValSize);
  768. if (!attrVal) {
  769. FreeNdsAttrInfo(pAttrEntries, i);
  770. pAttrEntries = NULL;
  771. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  772. }
  773. ccode = NWDSGetAttrVal(context, pBuf, luSyntax, attrVal);
  774. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  775. hr = CopyNdsValueToNdsObject(
  776. (nptr) attrVal,
  777. luAttrValSize,
  778. luSyntax,
  779. (PNDSOBJECT) pThisEntry->lpValue + j
  780. );
  781. if (hr == E_ADS_CANT_CONVERT_DATATYPE) {
  782. hr = S_OK;
  783. }
  784. BAIL_ON_FAILURE(hr);
  785. FreeADsMem(attrVal);
  786. attrVal = NULL;
  787. }
  788. *ppAttrEntries = pAttrEntries;
  789. }
  790. }
  791. RRETURN(S_OK);
  792. error:
  793. // This function frees all the memory related to this array of entries
  794. // for i entries. The ith entry may not have be fully set, but that is ok
  795. // because we have initialized it properly in the beginning of the for loop
  796. //
  797. if (pAttrEntries) {
  798. FreeNdsAttrInfo(pAttrEntries, i);
  799. }
  800. if (pAttrNames) {
  801. FreeNdsAttrNames(pAttrNames, i);
  802. }
  803. if (attrVal) {
  804. FreeADsMem(attrVal);
  805. }
  806. RRETURN (hr);
  807. }
  808. HRESULT
  809. ADsNdsReadClassDef(
  810. NDS_CONTEXT_HANDLE hADsContext,
  811. DWORD dwInfoType,
  812. LPWSTR *ppszClasses,
  813. DWORD nClasses,
  814. NDS_BUFFER_HANDLE *phBuf
  815. )
  816. {
  817. NWDSCCODE ccode;
  818. HRESULT hr = S_OK;
  819. DWORD i;
  820. pBuf_T pInBuf = NULL;
  821. BOOL fAllClasses = FALSE;
  822. BOOL fBufAllocated = FALSE;
  823. NWDSContextHandle context;
  824. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  825. PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
  826. if ( !pADsContext || !phBuf) {
  827. RRETURN(E_ADS_BAD_PARAMETER);
  828. }
  829. context = pADsContext->hContext;
  830. if( pBufData == NULL) {
  831. pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
  832. if (!pBufData) {
  833. RRETURN(E_OUTOFMEMORY);
  834. }
  835. fBufAllocated = TRUE;
  836. pBufData->lIterationHandle = NO_MORE_ITERATIONS;
  837. pBufData->pOutBuf = NULL;
  838. pBufData->dwInfoType = dwInfoType;
  839. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN*2, &pBufData->pOutBuf);
  840. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  841. }
  842. else {
  843. if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  844. RRETURN (S_ADS_NOMORE_ROWS);
  845. }
  846. }
  847. if (nClasses == (DWORD) -1) {
  848. fAllClasses = TRUE;
  849. pInBuf = NULL;
  850. }
  851. else {
  852. // Allocate and initialize input buffer a directory services
  853. // read operation.
  854. //
  855. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
  856. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  857. ccode = NWDSInitBuf(context, DSV_READ_CLASS_DEF, pInBuf);
  858. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  859. // To prepare for the read, place the names of the attributes
  860. // into the input buffer
  861. //
  862. for(i = 0; i < nClasses; i++)
  863. {
  864. ccode = NWDSPutClassName(context, pInBuf, (pnstr8) ppszClasses[i]);
  865. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  866. }
  867. }
  868. ccode = NWDSReadClassDef(
  869. context,
  870. dwInfoType,
  871. fAllClasses,
  872. pInBuf,
  873. &pBufData->lIterationHandle,
  874. pBufData->pOutBuf
  875. );
  876. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  877. if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  878. hr = S_ADS_NOMORE_ROWS;
  879. }
  880. else {
  881. hr = S_OK;
  882. }
  883. *phBuf = pBufData;
  884. if (pInBuf) {
  885. NWDSFreeBuf(pInBuf);
  886. }
  887. RRETURN(hr);
  888. error:
  889. if (pInBuf) {
  890. NWDSFreeBuf(pInBuf);
  891. }
  892. if (fBufAllocated) {
  893. if (pBufData->pOutBuf) {
  894. NWDSFreeBuf(pBufData->pOutBuf);
  895. }
  896. FreeADsMem(pBufData);
  897. }
  898. RRETURN(hr);
  899. }
  900. HRESULT
  901. ADsNdsGetClassDefListFromBuffer(
  902. NDS_CONTEXT_HANDLE hADsContext,
  903. NDS_BUFFER_HANDLE hBufData,
  904. PDWORD pdwNumEntries,
  905. PDWORD pdwInfoType,
  906. PNDS_CLASS_DEF *ppClassDef
  907. )
  908. {
  909. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  910. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  911. nuint32 luClassDefCount = 0, luItemCount = 0;
  912. WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
  913. Class_Info_T classInfo;
  914. DWORD j;
  915. PNDS_CLASS_DEF pThisClassDef = NULL, pClassDef = NULL;
  916. HRESULT hr = S_OK;
  917. NWDSCCODE ccode;
  918. NWDSContextHandle context;
  919. if (!pADsContext || !pBufData || !pdwNumEntries ||
  920. !pdwInfoType || !ppClassDef || !pBufData->pOutBuf) {
  921. RRETURN(E_ADS_BAD_PARAMETER);
  922. }
  923. context = pADsContext->hContext;
  924. *ppClassDef = NULL;
  925. *pdwNumEntries = 0;
  926. *pdwInfoType = pBufData->dwInfoType;
  927. ccode = NWDSGetClassDefCount(context, pBufData->pOutBuf, &luClassDefCount);
  928. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  929. if (luClassDefCount) {
  930. pClassDef = (PNDS_CLASS_DEF) AllocADsMem(
  931. sizeof(NDS_CLASS_DEF) *
  932. luClassDefCount );
  933. if (!pClassDef) {
  934. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  935. }
  936. memset (pClassDef, 0x0, sizeof(NDS_CLASS_DEF) * luClassDefCount);
  937. }
  938. for (j = 0; j < luClassDefCount; j++) {
  939. pThisClassDef = pClassDef + j;
  940. if (pBufData->dwInfoType == DS_CLASS_DEF_NAMES) {
  941. ccode = NWDSGetClassItem(
  942. context,
  943. pBufData->pOutBuf,
  944. (pnstr8) pszTemp
  945. );
  946. if (pszTemp) {
  947. pThisClassDef->szClassName = AllocADsStr( pszTemp );
  948. if (!pThisClassDef->szClassName) {
  949. RRETURN (hr = E_OUTOFMEMORY);
  950. }
  951. }
  952. //
  953. // This is all that is available for this class (only name)
  954. // move to the next class
  955. //
  956. continue;
  957. }
  958. ccode = NWDSGetClassDef(
  959. context,
  960. pBufData->pOutBuf,
  961. (pnstr8) pszTemp,
  962. &classInfo
  963. );
  964. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  965. pThisClassDef->dwFlags = classInfo.classFlags;
  966. pThisClassDef->asn1ID = classInfo.asn1ID;
  967. if (pBufData->dwInfoType == DS_INFO_CLASS_DEFS) {
  968. //
  969. // Name won't be there
  970. //
  971. pThisClassDef->szClassName = NULL;
  972. }
  973. else {
  974. pThisClassDef->szClassName = AllocADsStr(pszTemp);
  975. //
  976. // This is for getting superior classes
  977. //
  978. ccode = NWDSGetClassItemCount(
  979. context,
  980. pBufData->pOutBuf,
  981. &luItemCount
  982. );
  983. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  984. pThisClassDef->dwNumberOfSuperClasses = luItemCount;
  985. hr = GetItemsToList(
  986. context,
  987. pBufData->pOutBuf,
  988. luItemCount,
  989. &pThisClassDef->lpSuperClasses
  990. );
  991. BAIL_ON_FAILURE(hr);
  992. //
  993. // This is for getting Containment classes
  994. //
  995. ccode = NWDSGetClassItemCount(
  996. context,
  997. pBufData->pOutBuf,
  998. &luItemCount
  999. );
  1000. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1001. pThisClassDef->dwNumberOfContainmentClasses = luItemCount;
  1002. hr = GetItemsToList(
  1003. context,
  1004. pBufData->pOutBuf,
  1005. luItemCount,
  1006. &pThisClassDef->lpContainmentClasses
  1007. );
  1008. BAIL_ON_FAILURE(hr);
  1009. //
  1010. // This is for getting the Naming Attribute List
  1011. //
  1012. ccode = NWDSGetClassItemCount(
  1013. context,
  1014. pBufData->pOutBuf,
  1015. &luItemCount
  1016. );
  1017. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1018. pThisClassDef->dwNumberOfNamingAttributes = luItemCount;
  1019. hr = GetItemsToList(
  1020. context,
  1021. pBufData->pOutBuf,
  1022. luItemCount,
  1023. &pThisClassDef->lpNamingAttributes
  1024. );
  1025. BAIL_ON_FAILURE(hr);
  1026. //
  1027. // This is for getting the Mandatory Attribute List
  1028. //
  1029. ccode = NWDSGetClassItemCount(
  1030. context,
  1031. pBufData->pOutBuf,
  1032. &luItemCount
  1033. );
  1034. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1035. pThisClassDef->dwNumberOfMandatoryAttributes = luItemCount;
  1036. hr = GetItemsToList(
  1037. context,
  1038. pBufData->pOutBuf,
  1039. luItemCount,
  1040. &pThisClassDef->lpMandatoryAttributes
  1041. );
  1042. BAIL_ON_FAILURE(hr);
  1043. //
  1044. // This is for getting the Optional Attribute List
  1045. //
  1046. ccode = NWDSGetClassItemCount(
  1047. context,
  1048. pBufData->pOutBuf,
  1049. &luItemCount
  1050. );
  1051. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1052. pThisClassDef->dwNumberOfOptionalAttributes = luItemCount;
  1053. hr = GetItemsToList(
  1054. context,
  1055. pBufData->pOutBuf,
  1056. luItemCount,
  1057. &pThisClassDef->lpOptionalAttributes
  1058. );
  1059. BAIL_ON_FAILURE(hr);
  1060. }
  1061. }
  1062. *pdwNumEntries = luClassDefCount;
  1063. *ppClassDef = pClassDef;
  1064. RRETURN(hr);
  1065. error:
  1066. if (pClassDef) {
  1067. ADsNdsFreeClassDefList(pClassDef, luClassDefCount);
  1068. }
  1069. RRETURN(hr);
  1070. }
  1071. HRESULT
  1072. GetItemsToList(
  1073. NWDSContextHandle context,
  1074. pBuf_T pBuf,
  1075. DWORD luItemCount,
  1076. LPWSTR_LIST *ppList
  1077. )
  1078. {
  1079. WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
  1080. HRESULT hr = S_OK;
  1081. NWDSCCODE ccode;
  1082. LPWSTR_LIST pPrevItem = NULL, pCurrItem = NULL, pItems = NULL;
  1083. DWORD i;
  1084. if (!ppList) {
  1085. RRETURN(E_FAIL);
  1086. }
  1087. *ppList = NULL;
  1088. if (luItemCount > 0) {
  1089. pItems = (LPWSTR_LIST ) AllocADsMem(sizeof(WSTR_LIST_ELEM) * luItemCount);
  1090. if (!pItems) {
  1091. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1092. }
  1093. memset(pItems, 0x0, sizeof(WSTR_LIST_ELEM) * luItemCount);
  1094. for (i = 0; i < luItemCount ; i++) {
  1095. pCurrItem = pItems + i;
  1096. ccode = NWDSGetClassItem(
  1097. context,
  1098. pBuf,
  1099. (pnstr8) &pszTemp
  1100. );
  1101. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1102. pCurrItem->szString = AllocADsStr(pszTemp);
  1103. if (pPrevItem) {
  1104. pPrevItem->Next = pCurrItem;
  1105. }
  1106. pPrevItem = pCurrItem;
  1107. }
  1108. pCurrItem->Next = NULL;
  1109. }
  1110. *ppList = pItems;
  1111. RRETURN(hr);
  1112. error:
  1113. if (pItems) {
  1114. FreeItemList(pItems);
  1115. }
  1116. RRETURN(hr);
  1117. }
  1118. HRESULT
  1119. ADsNdsFreeClassDef(
  1120. PNDS_CLASS_DEF pClassDef
  1121. )
  1122. {
  1123. if (!pClassDef) {
  1124. RRETURN(S_OK);
  1125. }
  1126. FreeADsStr(pClassDef->szClassName);
  1127. FreeItemList(pClassDef->lpSuperClasses);
  1128. FreeItemList(pClassDef->lpContainmentClasses);
  1129. FreeItemList(pClassDef->lpNamingAttributes);
  1130. FreeItemList(pClassDef->lpMandatoryAttributes);
  1131. FreeItemList(pClassDef->lpOptionalAttributes);
  1132. FreeADsMem(pClassDef);
  1133. RRETURN(S_OK);
  1134. }
  1135. HRESULT
  1136. ADsNdsFreeClassDefList(
  1137. PNDS_CLASS_DEF pClassDef,
  1138. DWORD dwNumEntries
  1139. )
  1140. {
  1141. PNDS_CLASS_DEF pThisClassDef;
  1142. if (!pClassDef) {
  1143. RRETURN(S_OK);
  1144. }
  1145. for (DWORD i = 0; i < dwNumEntries; i++) {
  1146. pThisClassDef = pClassDef + i;
  1147. FreeADsStr(pThisClassDef->szClassName);
  1148. FreeItemList(pThisClassDef->lpSuperClasses);
  1149. FreeItemList(pThisClassDef->lpContainmentClasses);
  1150. FreeItemList(pThisClassDef->lpNamingAttributes);
  1151. FreeItemList(pThisClassDef->lpMandatoryAttributes);
  1152. FreeItemList(pThisClassDef->lpOptionalAttributes);
  1153. }
  1154. FreeADsMem(pClassDef);
  1155. RRETURN(S_OK);
  1156. }
  1157. HRESULT
  1158. ADsNdsReadAttrDef(
  1159. NDS_CONTEXT_HANDLE hADsContext,
  1160. DWORD dwInfoType,
  1161. LPWSTR *ppszAttrs,
  1162. DWORD nAttrs,
  1163. NDS_BUFFER_HANDLE *phBuf
  1164. )
  1165. {
  1166. NWDSCCODE ccode;
  1167. HRESULT hr = S_OK;
  1168. DWORD i;
  1169. pBuf_T pInBuf = NULL;
  1170. BOOL fAllAttrs = FALSE;
  1171. BOOL fBufAllocated = FALSE;
  1172. NWDSContextHandle context;
  1173. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1174. PNDS_BUFFER_DATA pBufData = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
  1175. if ( !pADsContext || !phBuf) {
  1176. RRETURN(E_ADS_BAD_PARAMETER);
  1177. }
  1178. context = pADsContext->hContext;
  1179. if( pBufData == NULL) {
  1180. pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
  1181. if (!pBufData) {
  1182. RRETURN(E_OUTOFMEMORY);
  1183. }
  1184. fBufAllocated = TRUE;
  1185. pBufData->lIterationHandle = NO_MORE_ITERATIONS;
  1186. pBufData->pOutBuf = NULL;
  1187. pBufData->dwInfoType = dwInfoType;
  1188. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pOutBuf);
  1189. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1190. }
  1191. else {
  1192. if ( pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  1193. RRETURN (S_ADS_NOMORE_COLUMNS);
  1194. }
  1195. }
  1196. if (nAttrs == (DWORD) -1) {
  1197. fAllAttrs = TRUE;
  1198. pInBuf = NULL;
  1199. }
  1200. else {
  1201. // Allocate and initialize input buffer a directory services
  1202. // read operation.
  1203. //
  1204. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
  1205. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1206. ccode = NWDSInitBuf(context, DSV_READ_ATTR_DEF, pInBuf);
  1207. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1208. // To prepare for the read, place the names of the attributes
  1209. // into the input buffer
  1210. //
  1211. for(i = 0; i < nAttrs; i++)
  1212. {
  1213. ccode = NWDSPutAttrName(context, pInBuf, (pnstr8) ppszAttrs[i]);
  1214. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1215. }
  1216. }
  1217. ccode = NWDSReadAttrDef(
  1218. context,
  1219. dwInfoType,
  1220. fAllAttrs,
  1221. pInBuf,
  1222. &pBufData->lIterationHandle,
  1223. pBufData->pOutBuf
  1224. );
  1225. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1226. if (pBufData->lIterationHandle == NO_MORE_ITERATIONS) {
  1227. hr = S_ADS_NOMORE_COLUMNS;
  1228. }
  1229. else {
  1230. hr = S_OK;
  1231. }
  1232. *phBuf = pBufData;
  1233. if (pInBuf) {
  1234. NWDSFreeBuf(pInBuf);
  1235. }
  1236. RRETURN(hr);
  1237. error:
  1238. if (pInBuf) {
  1239. NWDSFreeBuf(pInBuf);
  1240. }
  1241. if (fBufAllocated) {
  1242. if (pBufData->pOutBuf) {
  1243. NWDSFreeBuf(pBufData->pOutBuf);
  1244. }
  1245. FreeADsMem(pBufData);
  1246. }
  1247. RRETURN(hr);
  1248. }
  1249. HRESULT
  1250. ADsNdsGetAttrDefListFromBuffer(
  1251. NDS_CONTEXT_HANDLE hADsContext,
  1252. NDS_BUFFER_HANDLE hBufData,
  1253. PDWORD pdwNumEntries,
  1254. PDWORD pdwInfoType,
  1255. PNDS_ATTR_DEF *ppAttrDef
  1256. )
  1257. {
  1258. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1259. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  1260. nuint32 luAttrDefCount = 0, luItemCount = 0;
  1261. WCHAR pszTemp[MAX_DN_CHARS+1] = L"";
  1262. Attr_Info_T attrInfo;
  1263. DWORD j;
  1264. LPNDS_ATTR_DEF pThisAttrDef = NULL, pAttrDef = NULL;
  1265. HRESULT hr = S_OK;
  1266. NWDSCCODE ccode;
  1267. NWDSContextHandle context;
  1268. if (!pADsContext || !pBufData || !pdwNumEntries ||
  1269. !pdwInfoType || !ppAttrDef || !pBufData->pOutBuf) {
  1270. RRETURN(E_ADS_BAD_PARAMETER);
  1271. }
  1272. context = pADsContext->hContext;
  1273. *ppAttrDef = NULL;
  1274. *pdwNumEntries = 0;
  1275. *pdwInfoType = pBufData->dwInfoType;
  1276. ccode = NWDSGetAttrCount(context, pBufData->pOutBuf, &luAttrDefCount);
  1277. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1278. if (luAttrDefCount) {
  1279. pAttrDef = (PNDS_ATTR_DEF) AllocADsMem(
  1280. sizeof(NDS_ATTR_DEF) *
  1281. luAttrDefCount );
  1282. if (!pAttrDef) {
  1283. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1284. }
  1285. memset (pAttrDef, 0x0, sizeof(NDS_ATTR_DEF) * luAttrDefCount);
  1286. }
  1287. for (j = 0; j < luAttrDefCount; j++) {
  1288. pThisAttrDef = pAttrDef + j;
  1289. ccode = NWDSGetAttrDef(
  1290. context,
  1291. pBufData->pOutBuf,
  1292. (pnstr8) pszTemp,
  1293. &attrInfo
  1294. );
  1295. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1296. pThisAttrDef->szAttributeName = AllocADsStr(pszTemp);
  1297. if (pBufData->dwInfoType == DS_ATTR_DEFS) {
  1298. pThisAttrDef->dwFlags = attrInfo.attrFlags;
  1299. pThisAttrDef->dwSyntaxID = attrInfo.attrSyntaxID;
  1300. pThisAttrDef->dwLowerLimit = attrInfo.attrLower;
  1301. pThisAttrDef->dwUpperLimit = attrInfo.attrUpper;
  1302. }
  1303. }
  1304. *pdwNumEntries = luAttrDefCount;
  1305. *ppAttrDef = pAttrDef;
  1306. RRETURN(hr);
  1307. error:
  1308. if (pAttrDef) {
  1309. ADsNdsFreeAttrDefList(pAttrDef,luAttrDefCount);
  1310. }
  1311. RRETURN(hr);
  1312. }
  1313. HRESULT
  1314. ADsNdsFreeAttrDef(
  1315. PNDS_ATTR_DEF pAttrDef
  1316. )
  1317. {
  1318. if (!pAttrDef) {
  1319. RRETURN(S_OK);
  1320. }
  1321. FreeADsStr(pAttrDef->szAttributeName);
  1322. FreeADsMem(pAttrDef);
  1323. RRETURN(S_OK);
  1324. }
  1325. HRESULT
  1326. ADsNdsFreeAttrDefList(
  1327. PNDS_ATTR_DEF pAttrDef,
  1328. DWORD dwNumEntries
  1329. )
  1330. {
  1331. PNDS_ATTR_DEF pThisAttrDef;
  1332. if (!pAttrDef) {
  1333. RRETURN(S_OK);
  1334. }
  1335. for (DWORD i = 0; i < dwNumEntries; i++) {
  1336. pThisAttrDef = pAttrDef + i;
  1337. FreeADsStr(pThisAttrDef->szAttributeName);
  1338. }
  1339. FreeADsMem(pAttrDef);
  1340. RRETURN(S_OK);
  1341. }
  1342. //
  1343. // Free all the allocated memory in the list and the list itself.
  1344. //
  1345. HRESULT
  1346. FreeItemList(
  1347. LPWSTR_LIST pList
  1348. )
  1349. {
  1350. LPWSTR_LIST pCurr = pList;
  1351. while (pCurr) {
  1352. FreeADsStr(pCurr->szString);
  1353. pCurr = pCurr->Next;
  1354. }
  1355. FreeADsMem(pList);
  1356. RRETURN(S_OK);
  1357. }
  1358. HRESULT
  1359. ADsNdsFreeBuffer(
  1360. NDS_BUFFER_HANDLE hBuf
  1361. )
  1362. {
  1363. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBuf;
  1364. if (pBufData) {
  1365. if (pBufData->pOutBuf) {
  1366. NWDSFreeBuf(pBufData->pOutBuf);
  1367. }
  1368. if (pBufData->pInBuf) {
  1369. NWDSFreeBuf(pBufData->pInBuf);
  1370. }
  1371. FreeADsMem(pBufData);
  1372. }
  1373. RRETURN(S_OK);
  1374. }
  1375. HRESULT
  1376. ADsNdsCreateBuffer(
  1377. NDS_CONTEXT_HANDLE hADsContext,
  1378. DWORD dwOperation,
  1379. NDS_BUFFER_HANDLE *phBufData
  1380. )
  1381. {
  1382. HRESULT hr = S_OK;
  1383. NWDSCCODE ccode;
  1384. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1385. if (!hADsContext || !phBufData) {
  1386. RRETURN(E_ADS_BAD_PARAMETER);
  1387. }
  1388. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
  1389. if (!pBufData) {
  1390. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1391. }
  1392. pBufData->lIterationHandle = NO_MORE_ITERATIONS;
  1393. pBufData->pOutBuf = NULL;
  1394. pBufData->dwOperation = dwOperation;
  1395. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBufData->pInBuf);
  1396. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1397. ccode = NWDSInitBuf(
  1398. pADsContext->hContext,
  1399. dwOperation,
  1400. pBufData->pInBuf
  1401. );
  1402. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1403. *phBufData = pBufData;
  1404. error:
  1405. RRETURN(hr);
  1406. }
  1407. HRESULT
  1408. ADsNdsPutInBuffer(
  1409. NDS_CONTEXT_HANDLE hADsContext,
  1410. NDS_BUFFER_HANDLE hBufData,
  1411. LPWSTR szAttributeName,
  1412. DWORD dwSyntaxID,
  1413. LPNDSOBJECT lpAttributeValues,
  1414. DWORD dwValueCount,
  1415. DWORD dwChangeType
  1416. )
  1417. {
  1418. LPNDSOBJECT pThisValue = NULL;
  1419. NWDSContextHandle context;
  1420. HRESULT hr = S_OK;
  1421. NWDSCCODE ccode;
  1422. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1423. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  1424. nptr attrVal = NULL;
  1425. DWORD i = 0, luSyntax, luAttrValSize = 0;
  1426. if (!hADsContext || !hBufData) {
  1427. RRETURN(E_ADS_BAD_PARAMETER);
  1428. }
  1429. context = pADsContext->hContext;
  1430. switch (pBufData->dwOperation) {
  1431. case DSV_ADD_ENTRY:
  1432. ccode = NWDSPutAttrName (
  1433. context,
  1434. pBufData->pInBuf,
  1435. (pnstr8) szAttributeName
  1436. );
  1437. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1438. break;
  1439. default:
  1440. ccode = NWDSPutChange (
  1441. context,
  1442. pBufData->pInBuf,
  1443. dwChangeType,
  1444. (pnstr8) szAttributeName
  1445. );
  1446. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1447. break;
  1448. }
  1449. for (i=0; i < dwValueCount; i++) {
  1450. pThisValue = lpAttributeValues + i;
  1451. hr = CopyNdsObjectToNdsValue(
  1452. (PNDSOBJECT) pThisValue,
  1453. (nptr *) &attrVal,
  1454. &luAttrValSize,
  1455. &luSyntax
  1456. );
  1457. BAIL_ON_FAILURE(hr);
  1458. ccode = NWDSPutAttrVal (
  1459. context,
  1460. pBufData->pInBuf,
  1461. luSyntax,
  1462. attrVal
  1463. );
  1464. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1465. if (attrVal) {
  1466. FreeNdsValues(luSyntax, attrVal, luAttrValSize);
  1467. attrVal = NULL;
  1468. }
  1469. }
  1470. error:
  1471. if (attrVal) {
  1472. FreeNdsValues(luSyntax, attrVal, luAttrValSize);
  1473. }
  1474. RRETURN(hr);
  1475. }
  1476. HRESULT
  1477. ADsNdsPutFilter(
  1478. NDS_CONTEXT_HANDLE hADsContext,
  1479. NDS_BUFFER_HANDLE hBufData,
  1480. pFilter_Cursor_T pCur,
  1481. void (N_FAR N_CDECL *freeVal)(nuint32 syntax, nptr val)
  1482. )
  1483. {
  1484. NWDSContextHandle context;
  1485. HRESULT hr = S_OK;
  1486. NWDSCCODE ccode;
  1487. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1488. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  1489. nstr treeName[MAX_DN_CHARS+1];
  1490. nuint32 flags;
  1491. if (!hADsContext || !hBufData) {
  1492. RRETURN(E_ADS_BAD_PARAMETER);
  1493. }
  1494. context = pADsContext->hContext;
  1495. ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
  1496. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  1497. NWDSPutFilter(
  1498. pADsContext->hContext,
  1499. pBufData->pInBuf,
  1500. pCur,
  1501. freeVal
  1502. );
  1503. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1504. ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
  1505. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  1506. error:
  1507. RRETURN(hr);
  1508. }
  1509. HRESULT
  1510. ADsNdsModifyObject(
  1511. NDS_CONTEXT_HANDLE hADsContext,
  1512. LPWSTR szObjectName,
  1513. NDS_BUFFER_HANDLE hBufData
  1514. )
  1515. {
  1516. NWDSContextHandle context;
  1517. nint32 lIterationHandle = NO_MORE_ITERATIONS;
  1518. HRESULT hr = S_OK;
  1519. NWDSCCODE ccode;
  1520. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1521. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  1522. if (!hADsContext || !hBufData) {
  1523. RRETURN (E_ADS_BAD_PARAMETER);
  1524. }
  1525. context = pADsContext->hContext;
  1526. ccode = NWDSModifyObject(
  1527. context,
  1528. (pnstr8) szObjectName,
  1529. &lIterationHandle,
  1530. FALSE,
  1531. pBufData->pInBuf
  1532. );
  1533. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1534. error:
  1535. RRETURN(hr);
  1536. }
  1537. HRESULT
  1538. ADsNdsAddObject(
  1539. NDS_CONTEXT_HANDLE hADsContext,
  1540. LPWSTR szObjectName,
  1541. NDS_BUFFER_HANDLE hBufData
  1542. )
  1543. {
  1544. NWDSContextHandle context;
  1545. nint32 lIterationHandle = NO_MORE_ITERATIONS;
  1546. HRESULT hr = S_OK;
  1547. NWDSCCODE ccode;
  1548. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1549. PNDS_BUFFER_DATA pBufData = (PNDS_BUFFER_DATA) hBufData;
  1550. if (!hADsContext || !hBufData) {
  1551. RRETURN (E_ADS_BAD_PARAMETER);
  1552. }
  1553. context = pADsContext->hContext;
  1554. ccode = NWDSAddObject(
  1555. context,
  1556. (pnstr8) szObjectName,
  1557. &lIterationHandle,
  1558. FALSE,
  1559. pBufData->pInBuf
  1560. );
  1561. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1562. error:
  1563. RRETURN(hr);
  1564. }
  1565. HRESULT
  1566. ADsNdsGenObjectKey(
  1567. NDS_CONTEXT_HANDLE hADsContext,
  1568. LPWSTR szObjectName
  1569. )
  1570. {
  1571. NWDSContextHandle context;
  1572. HRESULT hr = S_OK;
  1573. NWDSCCODE ccode;
  1574. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1575. if (!hADsContext) {
  1576. RRETURN (E_ADS_BAD_PARAMETER);
  1577. }
  1578. context = pADsContext->hContext;
  1579. //
  1580. // To ensure that read/search doesn't collide with GenObjectKeyPair().
  1581. // GenObjectKeyPair() changes the context state which will cause read/search
  1582. // to return type-less DNs
  1583. //
  1584. EnterCriticalSection(&g_ContextCritSect);
  1585. ccode = NWDSGenerateObjectKeyPair(
  1586. context,
  1587. (pnstr8) szObjectName,
  1588. "",
  1589. 0);
  1590. LeaveCriticalSection(&g_ContextCritSect);
  1591. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1592. error:
  1593. RRETURN(hr);
  1594. }
  1595. HRESULT
  1596. ADsNdsRemoveObject(
  1597. NDS_CONTEXT_HANDLE hADsContext,
  1598. LPWSTR szObjectName
  1599. )
  1600. {
  1601. NWDSContextHandle context;
  1602. HRESULT hr = S_OK;
  1603. NWDSCCODE ccode;
  1604. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1605. if (!hADsContext) {
  1606. RRETURN (E_ADS_BAD_PARAMETER);
  1607. }
  1608. context = pADsContext->hContext;
  1609. ccode = NWDSRemoveObject(
  1610. context,
  1611. (pnstr8) szObjectName
  1612. );
  1613. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1614. error:
  1615. RRETURN(hr);
  1616. }
  1617. HRESULT
  1618. ADsNdsGetSyntaxID(
  1619. NDS_CONTEXT_HANDLE hADsContext,
  1620. LPWSTR szAttributeName,
  1621. PDWORD pdwSyntaxId
  1622. )
  1623. {
  1624. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1625. HRESULT hr = S_OK;
  1626. NWDSCCODE ccode;
  1627. if (!pADsContext) {
  1628. RRETURN(E_ADS_BAD_PARAMETER);
  1629. }
  1630. ccode = NWDSGetSyntaxID(
  1631. pADsContext->hContext,
  1632. (pnstr8) szAttributeName,
  1633. pdwSyntaxId
  1634. );
  1635. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1636. error:
  1637. RRETURN(hr);
  1638. }
  1639. HRESULT
  1640. ADsNdsSearch(
  1641. NDS_CONTEXT_HANDLE hADsContext,
  1642. LPWSTR szObjectName,
  1643. DWORD scope,
  1644. BOOL fSearchAliases,
  1645. NDS_BUFFER_HANDLE hFilterBuf,
  1646. pTimeStamp_T pTimeStamp,
  1647. DWORD dwInfoType,
  1648. LPWSTR *ppszAttrs,
  1649. DWORD nAttrs,
  1650. DWORD nObjectsTobeSearched,
  1651. PDWORD pnObjectsSearched,
  1652. NDS_BUFFER_HANDLE *phBuf,
  1653. pnint32 plIterationHandle
  1654. )
  1655. {
  1656. NWDSContextHandle context;
  1657. HRESULT hr = S_OK;
  1658. NWDSCCODE ccode;
  1659. BOOL fBufAllocated = FALSE;
  1660. DWORD i, j;
  1661. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1662. PNDS_BUFFER_DATA pFilterBuf = (PNDS_BUFFER_DATA) hFilterBuf;
  1663. PNDS_BUFFER_DATA pBuf = phBuf ? (PNDS_BUFFER_DATA) *phBuf : NULL;
  1664. nstr treeName[MAX_DN_CHARS+1];
  1665. nuint32 flags;
  1666. if (!hADsContext || !hFilterBuf || !phBuf ) {
  1667. RRETURN (E_ADS_BAD_PARAMETER);
  1668. }
  1669. context = pADsContext->hContext;
  1670. ccode = NWDSGetContext(context, DCK_TREE_NAME, &treeName);
  1671. ccode = NWDSGetContext(context, DCK_FLAGS, &flags);
  1672. //
  1673. // Allocate the result buffer if not already done
  1674. //
  1675. if( pBuf == NULL) {
  1676. pBuf = (PNDS_BUFFER_DATA) AllocADsMem( sizeof(NDS_BUFFER_DATA) );
  1677. if (!pBuf) {
  1678. RRETURN(E_OUTOFMEMORY);
  1679. }
  1680. fBufAllocated = TRUE;
  1681. pBuf->pOutBuf = NULL;
  1682. pBuf->pInBuf = NULL;
  1683. pBuf->dwInfoType = dwInfoType;
  1684. pBuf->dwOperation = DSV_SEARCH;
  1685. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN * 4, &pBuf->pOutBuf);
  1686. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1687. if (nAttrs == (DWORD) -1) {
  1688. pBuf->fAllAttrs = TRUE;
  1689. pBuf->pInBuf = NULL;
  1690. }
  1691. else {
  1692. // Allocate and initialize input buffer a directory services
  1693. // read operation.
  1694. //
  1695. ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pBuf->pInBuf);
  1696. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1697. ccode = NWDSInitBuf(context, DSV_SEARCH, pBuf->pInBuf);
  1698. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1699. // To prepare for the read, place the names of the attributes
  1700. // into the input buffer
  1701. //
  1702. for(i = 0; i < nAttrs; i++)
  1703. {
  1704. ccode = NWDSPutAttrName(context, pBuf->pInBuf, (pnstr8) ppszAttrs[i]);
  1705. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1706. }
  1707. }
  1708. }
  1709. //
  1710. // To ensure that read/search doesn't collide with GenObjectKeyPair().
  1711. // GenObjectKeyPair() changes the context state which will cause read/search
  1712. // to return type-less DNs
  1713. //
  1714. EnterCriticalSection(&g_ContextCritSect);
  1715. if (pTimeStamp) {
  1716. ccode = NWDSExtSyncSearch(
  1717. context,
  1718. (pnstr8) szObjectName,
  1719. (nint) scope,
  1720. (nbool8) fSearchAliases,
  1721. pFilterBuf->pInBuf,
  1722. pTimeStamp,
  1723. pBuf->dwInfoType,
  1724. (nbool8) pBuf->fAllAttrs,
  1725. pBuf->pInBuf,
  1726. plIterationHandle,
  1727. (nint32) nObjectsTobeSearched,
  1728. (pnint32) pnObjectsSearched,
  1729. pBuf->pOutBuf
  1730. );
  1731. }
  1732. else {
  1733. ccode = NWDSSearch(
  1734. context,
  1735. (pnstr8) szObjectName,
  1736. (nint) scope,
  1737. (nbool8) fSearchAliases,
  1738. pFilterBuf->pInBuf,
  1739. pBuf->dwInfoType,
  1740. (nbool8) pBuf->fAllAttrs,
  1741. pBuf->pInBuf,
  1742. plIterationHandle,
  1743. (nint32) nObjectsTobeSearched,
  1744. (pnint32) pnObjectsSearched,
  1745. pBuf->pOutBuf
  1746. );
  1747. }
  1748. LeaveCriticalSection(&g_ContextCritSect);
  1749. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1750. *phBuf = pBuf;
  1751. RRETURN(hr);
  1752. error:
  1753. if (fBufAllocated) {
  1754. if (pBuf->pOutBuf) {
  1755. NWDSFreeBuf(pBuf->pOutBuf);
  1756. }
  1757. if (pBuf->pInBuf) {
  1758. NWDSFreeBuf(pBuf->pInBuf);
  1759. }
  1760. FreeADsMem(pBuf);
  1761. }
  1762. RRETURN(hr);
  1763. }
  1764. HRESULT
  1765. ADsNdsMoveObject(
  1766. NDS_CONTEXT_HANDLE hADsContext,
  1767. LPWSTR pszSrcObjectDn,
  1768. LPWSTR pszDestContainerDn,
  1769. LPWSTR pszNewRDN
  1770. )
  1771. {
  1772. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1773. HRESULT hr = S_OK;
  1774. NWDSCCODE ccode;
  1775. if (!pADsContext) {
  1776. RRETURN(E_ADS_BAD_PARAMETER);
  1777. }
  1778. ccode = NWDSMoveObject(
  1779. pADsContext->hContext,
  1780. (pnstr8) pszSrcObjectDn,
  1781. (pnstr8) pszDestContainerDn,
  1782. (pnstr8) pszNewRDN
  1783. );
  1784. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1785. error:
  1786. RRETURN(hr);
  1787. }
  1788. HRESULT
  1789. ADsNdsRenameObject(
  1790. NDS_CONTEXT_HANDLE hADsContext,
  1791. LPWSTR pszSrcObjectDn,
  1792. LPWSTR pszNewRDN
  1793. )
  1794. {
  1795. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1796. HRESULT hr = S_OK;
  1797. NWDSCCODE ccode;
  1798. if (!pADsContext) {
  1799. RRETURN(E_ADS_BAD_PARAMETER);
  1800. }
  1801. ccode = NWDSModifyRDN(
  1802. pADsContext->hContext,
  1803. (pnstr8) pszSrcObjectDn,
  1804. (pnstr8) pszNewRDN,
  1805. TRUE
  1806. );
  1807. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1808. error:
  1809. RRETURN(hr);
  1810. }
  1811. HRESULT
  1812. ADsNdsChangeObjectPassword(
  1813. NDS_CONTEXT_HANDLE hADsContext,
  1814. LPWSTR szObjectName,
  1815. NWOBJ_TYPE dwOT_ID,
  1816. LPWSTR szOldPassword,
  1817. LPWSTR szNewPassword
  1818. )
  1819. {
  1820. NWCCODE ccode = 0;
  1821. HRESULT hr = S_OK;
  1822. nuint32 connRef = 0;
  1823. NWCONN_HANDLE connHandle;
  1824. PNDS_CONTEXT pADsContext = (PNDS_CONTEXT) hADsContext;
  1825. char *szAnsiNewPassword = szNewPassword ? (char *)AllocADsMem(wcslen(szNewPassword)+1) : NULL;
  1826. char *szAnsiOldPassword = szOldPassword ? (char *)AllocADsMem(wcslen(szOldPassword)+1) : (char *) AllocADsMem(1);
  1827. if ( !szObjectName || !szNewPassword ) {
  1828. hr = E_INVALIDARG ;
  1829. BAIL_ON_FAILURE(hr);
  1830. }
  1831. //
  1832. // Convert UNICODE into ANSI representation required by NW APIs. "0" is
  1833. // passed to UnicodeToAnsiString when the length of the string is unknown.
  1834. //
  1835. UnicodeToAnsiString(
  1836. szNewPassword,
  1837. szAnsiNewPassword,
  1838. 0
  1839. );
  1840. //
  1841. // If the old password is passed in, we'll call change password
  1842. //
  1843. if (szOldPassword) {
  1844. UnicodeToAnsiString(
  1845. szOldPassword,
  1846. szAnsiOldPassword,
  1847. 0
  1848. );
  1849. ccode = NWDSChangeObjectPassword(
  1850. pADsContext->hContext,
  1851. 0,
  1852. (pnstr8) szObjectName, //IMP: send the unicode string itself
  1853. szAnsiOldPassword,
  1854. szAnsiNewPassword
  1855. );
  1856. }
  1857. //
  1858. // Else, we'll set the password to the supplied password
  1859. //
  1860. else {
  1861. szAnsiOldPassword[0] = 0 ;
  1862. //
  1863. // To ensure that read/search doesn't collide with GenObjectKeyPair().
  1864. // GenObjectKeyPair() changes the context state which will cause
  1865. // read/search to return type-less DNs
  1866. //
  1867. EnterCriticalSection(&g_ContextCritSect);
  1868. ccode = NWDSGenerateObjectKeyPair(
  1869. pADsContext->hContext,
  1870. (pnstr8) szObjectName,
  1871. szAnsiNewPassword,
  1872. 0);
  1873. LeaveCriticalSection(&g_ContextCritSect);
  1874. }
  1875. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  1876. error:
  1877. FreeADsMem(szAnsiOldPassword);
  1878. FreeADsMem(szAnsiNewPassword);
  1879. RRETURN(hr);
  1880. }
  1881. //
  1882. // General function to convert variant array to string array
  1883. //
  1884. HRESULT
  1885. ConvertVariantArrayToStringArray(
  1886. PVARIANT pVarArray,
  1887. PWSTR **pppszStringArray,
  1888. DWORD dwNumStrings
  1889. )
  1890. {
  1891. HRESULT hr = S_OK;
  1892. PWSTR *ppszStringArray = NULL;
  1893. DWORD i = 0;
  1894. //
  1895. // Start off with a zero-length array.
  1896. //
  1897. *pppszStringArray = NULL;
  1898. ppszStringArray = (PWSTR *)AllocADsMem(dwNumStrings * sizeof(PWSTR));
  1899. if (!ppszStringArray)
  1900. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1901. for (i = 0; i < dwNumStrings; i++)
  1902. {
  1903. if (!(V_VT(pVarArray + i) == VT_BSTR))
  1904. BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE);
  1905. ppszStringArray[i] = AllocADsStr(V_BSTR(pVarArray + i));
  1906. if (!ppszStringArray[i])
  1907. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1908. }
  1909. *pppszStringArray = ppszStringArray;
  1910. RRETURN(hr);
  1911. error:
  1912. if (ppszStringArray)
  1913. {
  1914. for (DWORD j = 0; j < i; j++)
  1915. if (ppszStringArray[i])
  1916. FreeADsStr(ppszStringArray[i]);
  1917. FreeADsMem(ppszStringArray);
  1918. }
  1919. RRETURN(hr);
  1920. }
  1921. //----------------------------------------------------------------------------
  1922. //
  1923. // Function: NWApiOpenPrinter
  1924. //
  1925. // Synopsis:
  1926. //
  1927. //----------------------------------------------------------------------------
  1928. HRESULT
  1929. NWApiOpenPrinter(
  1930. LPWSTR lpszUncPrinterName,
  1931. HANDLE *phPrinter,
  1932. DWORD dwAccess
  1933. )
  1934. {
  1935. BOOL fStatus = TRUE;
  1936. HANDLE hPrinter;
  1937. HRESULT hr = S_OK;
  1938. PRINTER_DEFAULTS PrinterDefault = {0, 0, dwAccess};
  1939. //
  1940. // Set desired access right.
  1941. //
  1942. PrinterDefault.DesiredAccess = dwAccess;
  1943. //
  1944. // Get a handle to the speccified printer using Win32 API.
  1945. //
  1946. fStatus = OpenPrinter(
  1947. lpszUncPrinterName,
  1948. &hPrinter,
  1949. &PrinterDefault
  1950. );
  1951. //
  1952. // Convert error code into HRESULT.
  1953. //
  1954. if (fStatus == FALSE) {
  1955. hr = HRESULT_FROM_WIN32(GetLastError());
  1956. }
  1957. //
  1958. // Return.
  1959. //
  1960. else {
  1961. *phPrinter = hPrinter;
  1962. }
  1963. RRETURN(hr);
  1964. }
  1965. //----------------------------------------------------------------------------
  1966. //
  1967. // Function: NWApiClosePrinter
  1968. //
  1969. // Synopsis:
  1970. //
  1971. //----------------------------------------------------------------------------
  1972. HRESULT
  1973. NWApiClosePrinter(
  1974. HANDLE hPrinter
  1975. )
  1976. {
  1977. BOOL fStatus = TRUE;
  1978. HRESULT hr = S_OK;
  1979. //
  1980. // Close a printer using Win32 API.
  1981. //
  1982. fStatus = ClosePrinter(hPrinter);
  1983. //
  1984. // Convert error code into HRESULT.
  1985. //
  1986. if (fStatus == FALSE) {
  1987. hr = HRESULT_FROM_WIN32(GetLastError());
  1988. }
  1989. //
  1990. // Return.
  1991. //
  1992. RRETURN(hr);
  1993. }
  1994. //----------------------------------------------------------------------------
  1995. //
  1996. // Function: NWApiSetPrinter
  1997. //
  1998. // Synopsis:
  1999. //
  2000. //----------------------------------------------------------------------------
  2001. HRESULT
  2002. NWApiSetPrinter(
  2003. HANDLE hPrinter,
  2004. DWORD dwLevel,
  2005. LPBYTE lpbPrinters,
  2006. DWORD dwAccess
  2007. )
  2008. {
  2009. BOOL fStatus = FALSE;
  2010. HRESULT hr = S_OK;
  2011. fStatus = SetPrinter(
  2012. hPrinter,
  2013. dwLevel,
  2014. lpbPrinters,
  2015. dwAccess
  2016. );
  2017. if (!fStatus) {
  2018. goto error;
  2019. }
  2020. RRETURN(S_OK);
  2021. error:
  2022. hr = HRESULT_FROM_WIN32(GetLastError());
  2023. RRETURN(hr);
  2024. }