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.

10483 lines
342 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Nds32.c
  5. Abstract:
  6. This module implements functions to Read, Add, Modify, and Remove
  7. NDS Objects and Attributes using the Microsoft Netware redirector.
  8. Author:
  9. Glenn Curtis [GlennC] 04-Jan-1996 - New NDS function implementations
  10. Glenn Curtis [GlennC] 24-Apr-1996 - Added schema APIs
  11. Glenn Curtis [GlennC] 20-Jun-1996 - Added search API
  12. Felix Wong [t-felixw] 24-Sep-1995 - Added Win95 Support
  13. Glenn Curtis [GlennC] 20-Nov-1996 - Improved search API
  14. Glenn Curtis [GlennC] 02-Jan-1997 - Added rename object API
  15. Tommy Evans [tommye] 21-Apr-2000 - Moved the NDS_OBJECT typedef out and
  16. renamed to NDS_OBJECT_PRIV.
  17. --*/
  18. #include <procs.h>
  19. #include <nds32.h>
  20. #include <align.h>
  21. #include <nwapi32.h>
  22. #include <nwpkstr.h>
  23. #ifdef WIN95
  24. #include <msnwapi.h>
  25. #include <utils95.h>
  26. #include <ndsapi95.h>
  27. #endif
  28. /* Definitions */
  29. #define NDS_SIGNATURE 0x6E656C67 /* glen */
  30. #define ONE_KB 1024
  31. #define TWO_KB (ONE_KB*2)
  32. #define FOUR_KB (ONE_KB*4)
  33. #define EIGHT_KB (ONE_KB*8)
  34. #define SIXTEEN_KB (ONE_KB*16)
  35. #define THIRY_TWO_KB (ONE_KB*32)
  36. #define SIXTY_FOUR_KB (ONE_KB*64)
  37. #define ONE_TWENTY_EIGHT_KB (ONE_KB*128)
  38. #define NDS_MAX_BUFFER (ONE_KB*63)
  39. #define NDS_SEARCH_ENTRY 0
  40. #define NDS_SEARCH_SUBORDINATES 1
  41. #define NDS_SEARCH_SUBTREE 2
  42. #define NDS_DEREF_ALIASES 0x00000000
  43. #define NDS_DONT_DEREF_ALIASES 0x00010000
  44. /* NetWare NDS NCP function identifiers */
  45. #define NETWARE_NDS_FUNCTION_RESOLVE_NAME 0x00000001
  46. #define NETWARE_NDS_FUNCTION_READ_OBJECT 0x00000003
  47. #define NETWARE_NDS_FUNCTION_LIST 0x00000005
  48. #define NETWARE_NDS_FUNCTION_SEARCH 0x00000006
  49. #define NETWARE_NDS_FUNCTION_ADD_OBJECT 0x00000007
  50. #define NETWARE_NDS_FUNCTION_REMOVE_OBJECT 0x00000008
  51. #define NETWARE_NDS_FUNCTION_MODIFY_OBJECT 0x00000009
  52. #define NETWARE_NDS_FUNCTION_MODIFY_RDN 0x0000000A
  53. #define NETWARE_NDS_FUNCTION_DEFINE_ATTR 0x0000000B
  54. #define NETWARE_NDS_FUNCTION_READ_ATTR_DEF 0x0000000C
  55. #define NETWARE_NDS_FUNCTION_REMOVE_ATTR_DEF 0x0000000D
  56. #define NETWARE_NDS_FUNCTION_DEFINE_CLASS 0x0000000E
  57. #define NETWARE_NDS_FUNCTION_READ_CLASS_DEF 0x0000000F
  58. #define NETWARE_NDS_FUNCTION_MODIFY_CLASS 0x00000010
  59. #define NETWARE_NDS_FUNCTION_REMOVE_CLASS_DEF 0x00000011
  60. #define NETWARE_NDS_FUNCTION_LIST_CONT_CLASSES 0x00000012
  61. #define NETWARE_NDS_FUNCTION_GET_EFFECTIVE_RIGHTS 0x00000013
  62. #define NETWARE_NDS_FUNCTION_BEGIN_MOVE_OBJECT 0x0000002A
  63. #define NETWARE_NDS_FUNCTION_FINISH_MOVE_OBJECT 0x0000002B
  64. #define NETWARE_NDS_FUNCTION_GET_SERVER_ADDRESS 0x00000035
  65. /* Data structure definitions */
  66. typedef struct
  67. {
  68. DWORD dwBufferId;
  69. DWORD dwOperation;
  70. //
  71. // About the request buffer
  72. //
  73. DWORD dwRequestBufferSize;
  74. DWORD dwRequestAvailableBytes;
  75. DWORD dwNumberOfRequestEntries;
  76. DWORD dwLengthOfRequestData;
  77. //
  78. // The request buffer
  79. //
  80. LPBYTE lpRequestBuffer;
  81. //
  82. // About the reply buffer
  83. //
  84. DWORD dwReplyBufferSize;
  85. DWORD dwReplyAvailableBytes;
  86. DWORD dwNumberOfReplyEntries;
  87. DWORD dwLengthOfReplyData;
  88. //
  89. // More about the reply buffer
  90. //
  91. DWORD dwReplyInformationType;
  92. //
  93. // The reply buffer
  94. //
  95. LPBYTE lpReplyBuffer;
  96. //
  97. // About the index buffer
  98. //
  99. DWORD dwIndexBufferSize;
  100. DWORD dwIndexAvailableBytes;
  101. DWORD dwNumberOfIndexEntries;
  102. DWORD dwLengthOfIndexData;
  103. //
  104. // More about the index buffer
  105. //
  106. DWORD dwCurrentIndexEntry;
  107. //
  108. // The index buffer
  109. //
  110. LPBYTE lpIndexBuffer;
  111. //
  112. // About the syntax buffer
  113. //
  114. DWORD dwSyntaxBufferSize;
  115. DWORD dwSyntaxAvailableBytes;
  116. DWORD dwNumberOfSyntaxEntries;
  117. DWORD dwLengthOfSyntaxData;
  118. //
  119. // The syntax buffer
  120. //
  121. LPBYTE lpSyntaxBuffer;
  122. //
  123. // A place to keep the search from object path ...
  124. //
  125. WCHAR szPath[NDS_MAX_NAME_CHARS + 1];
  126. } NDS_BUFFER, * LPNDS_BUFFER;
  127. /* Local Function Definitions */
  128. VOID
  129. PrepareAddEntry(
  130. LPBYTE lpTempEntry,
  131. UNICODE_STRING AttributeName,
  132. DWORD dwSyntaxID,
  133. LPBYTE lpAttributeValues,
  134. DWORD dwValueCount,
  135. LPDWORD lpdwLengthInBytes );
  136. VOID
  137. PrepareModifyEntry(
  138. LPBYTE lpTempEntry,
  139. UNICODE_STRING AttributeName,
  140. DWORD dwSyntaxID,
  141. DWORD dwAttrModificationOperation,
  142. LPBYTE lpAttributeValues,
  143. DWORD dwValueCount,
  144. LPDWORD lpdwLengthInBytes );
  145. VOID
  146. PrepareReadEntry(
  147. LPBYTE lpTempEntry,
  148. UNICODE_STRING AttributeName,
  149. LPDWORD lpdwLengthInBytes );
  150. DWORD
  151. CalculateValueDataSize(
  152. DWORD dwSyntaxId,
  153. LPBYTE lpAttributeValues,
  154. DWORD dwValueCount );
  155. VOID
  156. AppendValueToEntry(
  157. LPBYTE lpBuffer,
  158. DWORD dwSyntaxId,
  159. LPBYTE lpAttributeValues,
  160. DWORD dwValueCount,
  161. LPDWORD lpdwLengthInBytes );
  162. DWORD
  163. MapNetwareErrorCode(
  164. DWORD dwNetwareError );
  165. DWORD
  166. IndexReadAttrDefReplyBuffer(
  167. LPNDS_BUFFER lpNdsBuffer );
  168. DWORD
  169. IndexReadClassDefReplyBuffer(
  170. LPNDS_BUFFER lpNdsBuffer );
  171. DWORD
  172. IndexReadObjectReplyBuffer(
  173. LPNDS_BUFFER lpNdsBuffer );
  174. DWORD
  175. IndexReadNameReplyBuffer(
  176. LPNDS_BUFFER lpNdsBuffer );
  177. DWORD
  178. IndexSearchObjectReplyBuffer(
  179. LPNDS_BUFFER lpNdsBuffer );
  180. DWORD
  181. SizeOfASN1Structure(
  182. LPBYTE * lppRawBuffer,
  183. DWORD dwSyntaxId );
  184. DWORD
  185. ParseASN1ValueBlob(
  186. LPBYTE RawDataBuffer,
  187. DWORD dwSyntaxId,
  188. DWORD dwNumberOfValues,
  189. LPBYTE SyntaxStructure );
  190. DWORD
  191. ParseStringListBlob(
  192. LPBYTE RawDataBuffer,
  193. DWORD dwNumberOfStrings,
  194. LPBYTE SyntaxStructure );
  195. DWORD
  196. ReadAttrDef_AllAttrs(
  197. IN HANDLE hTree,
  198. IN DWORD dwInformationType,
  199. OUT HANDLE lphOperationData );
  200. DWORD
  201. ReadAttrDef_SomeAttrs(
  202. IN HANDLE hTree,
  203. IN DWORD dwInformationType,
  204. IN OUT HANDLE lphOperationData );
  205. DWORD
  206. ReadClassDef_AllClasses(
  207. IN HANDLE hTree,
  208. IN DWORD dwInformationType,
  209. OUT HANDLE lphOperationData );
  210. DWORD
  211. ReadClassDef_SomeClasses(
  212. IN HANDLE hTree,
  213. IN DWORD dwInformationType,
  214. IN OUT HANDLE lphOperationData );
  215. DWORD
  216. ReadObject_AllAttrs(
  217. IN HANDLE hObject,
  218. IN DWORD dwInformationType,
  219. OUT HANDLE * lphOperationData );
  220. DWORD
  221. ReadObject_SomeAttrs(
  222. IN HANDLE hObject,
  223. IN DWORD dwInformationType,
  224. IN OUT HANDLE * lphOperationData );
  225. DWORD
  226. Search_AllAttrs(
  227. IN HANDLE hStartFromObject,
  228. IN DWORD dwInformationType,
  229. IN DWORD dwScope,
  230. IN BOOL fDerefAliases,
  231. IN LPQUERY_TREE lpQueryTree,
  232. IN OUT LPDWORD lpdwIterHandle,
  233. OUT HANDLE * lphOperationData );
  234. DWORD
  235. Search_SomeAttrs(
  236. IN HANDLE hStartFromObject,
  237. IN DWORD dwInformationType,
  238. IN DWORD dwScope,
  239. IN BOOL fDerefAliases,
  240. IN LPQUERY_TREE lpQueryTree,
  241. IN OUT LPDWORD lpdwIterHandle,
  242. IN OUT HANDLE * lphOperationData );
  243. DWORD
  244. GetFirstNdsSubTreeEntry(
  245. OUT LPNDS_OBJECT_PRIV lpNdsObject,
  246. IN DWORD BufferSize );
  247. DWORD
  248. GetNextNdsSubTreeEntry(
  249. OUT LPNDS_OBJECT_PRIV lpNdsObject );
  250. VOID
  251. GetSubTreeData(
  252. IN DWORD NdsRawDataPtr,
  253. OUT LPDWORD lpdwEntryId,
  254. OUT LPDWORD lpdwSubordinateCount,
  255. OUT LPDWORD lpdwModificationTime,
  256. OUT LPDWORD lpdwClassNameLen,
  257. OUT LPWSTR * szClassName,
  258. OUT LPDWORD lpdwObjectNameLen,
  259. OUT LPWSTR * szObjectName );
  260. LPBYTE
  261. GetSearchResultData( IN LPBYTE lpResultBufferPtr,
  262. OUT LPDWORD lpdwFlags,
  263. OUT LPDWORD lpdwSubordinateCount,
  264. OUT LPDWORD lpdwModificationTime,
  265. OUT LPDWORD lpdwClassNameLen,
  266. OUT LPWSTR * szClassName,
  267. OUT LPDWORD lpdwObjectNameLen,
  268. OUT LPWSTR * szObjectName,
  269. OUT LPDWORD lpdwEntryInfo1,
  270. OUT LPDWORD lpdwEntryInfo2 );
  271. DWORD
  272. WriteObjectToBuffer(
  273. IN OUT LPBYTE * FixedPortion,
  274. IN OUT LPWSTR * EndOfVariableData,
  275. IN LPWSTR ObjectFullName,
  276. IN LPWSTR ObjectName,
  277. IN LPWSTR ClassName,
  278. IN DWORD EntryId,
  279. IN DWORD ModificationTime,
  280. IN DWORD SubordinateCount,
  281. IN DWORD NumberOfAttributes,
  282. IN LPNDS_ATTR_INFO lpAttributeInfos );
  283. DWORD
  284. VerifyBufferSize(
  285. IN LPBYTE lpRawBuffer,
  286. IN DWORD dwBufferSize,
  287. IN DWORD dwSyntaxID,
  288. IN DWORD dwNumberOfValues,
  289. OUT LPDWORD lpdwLength );
  290. DWORD
  291. VerifyBufferSizeForStringList(
  292. IN DWORD dwBufferSize,
  293. IN DWORD dwNumberOfValues,
  294. OUT LPDWORD lpdwLength );
  295. DWORD
  296. WriteQueryTreeToBuffer(
  297. IN LPQUERY_TREE lpQueryTree,
  298. IN LPNDS_BUFFER lpNdsBuffer );
  299. DWORD
  300. WriteQueryNodeToBuffer(
  301. IN LPQUERY_NODE lpQueryNode,
  302. IN LPNDS_BUFFER lpNdsBuffer );
  303. DWORD
  304. NwNdsGetServerDN(
  305. IN HANDLE hTree,
  306. OUT LPWSTR szServerDN );
  307. DWORD
  308. AllocateOrIncreaseSyntaxBuffer(
  309. IN LPNDS_BUFFER lpNdsBuffer );
  310. DWORD
  311. AllocateOrIncreaseRequestBuffer(
  312. IN LPNDS_BUFFER lpNdsBuffer );
  313. //
  314. // Flags used for the function ParseNdsUncPath()
  315. //
  316. #define PARSE_NDS_GET_TREE_NAME 0
  317. #define PARSE_NDS_GET_PATH_NAME 1
  318. #define PARSE_NDS_GET_OBJECT_NAME 2
  319. WORD
  320. ParseNdsUncPath( IN OUT LPWSTR * Result,
  321. IN LPWSTR ObjectPathName,
  322. IN DWORD flag );
  323. /* Function Implementations */
  324. DWORD
  325. NwNdsAddObject(
  326. IN HANDLE hParentObject,
  327. IN LPWSTR szObjectName,
  328. IN HANDLE hOperationData )
  329. /*
  330. NwNdsAddObject()
  331. This function is used to add a leaf object to an NDS directory tree.
  332. Arguments:
  333. HANDLE hParentObject - A handle to the parent object in
  334. the directory tree to add a new leaf to. Handle is
  335. obtained by calling NwNdsOpenObject.
  336. LPWSTR szObjectName - The directory name that the new leaf
  337. object will be known by.
  338. HANDLE hOperationData - A buffer containing a list of
  339. attributes and values to create the new object. This
  340. buffer is manipulated by the following functions:
  341. NwNdsCreateBuffer (NDS_OBJECT_ADD),
  342. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  343. Returns:
  344. NO_ERROR
  345. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  346. */
  347. {
  348. DWORD nwstatus;
  349. NTSTATUS ntstatus;
  350. DWORD dwReplyLength;
  351. BYTE NdsReply[NDS_BUFFER_SIZE];
  352. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  353. LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
  354. UNICODE_STRING ObjectName;
  355. if ( lpNdsBuffer == NULL ||
  356. lpNdsParentObject == NULL ||
  357. szObjectName == NULL ||
  358. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  359. lpNdsBuffer->dwOperation != NDS_OBJECT_ADD ||
  360. lpNdsParentObject->Signature != NDS_SIGNATURE )
  361. {
  362. SetLastError( ERROR_INVALID_PARAMETER );
  363. return (DWORD) UNSUCCESSFUL;
  364. }
  365. RtlInitUnicodeString( &ObjectName, szObjectName );
  366. ntstatus =
  367. FragExWithWait(
  368. lpNdsParentObject->NdsTree,
  369. NETWARE_NDS_FUNCTION_ADD_OBJECT,
  370. NdsReply,
  371. NDS_BUFFER_SIZE,
  372. &dwReplyLength,
  373. "DDDSDr",
  374. 0, // Version
  375. 0, // Flags
  376. lpNdsParentObject->ObjectId,
  377. &ObjectName,
  378. lpNdsBuffer->dwNumberOfRequestEntries,
  379. lpNdsBuffer->lpRequestBuffer, // Object attributes to be added
  380. (WORD)lpNdsBuffer->dwLengthOfRequestData // Length of data
  381. );
  382. if ( !NT_SUCCESS( ntstatus ) )
  383. {
  384. #if DBG
  385. KdPrint(( "NDS32: NwNdsAddObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  386. #endif
  387. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  388. return (DWORD) UNSUCCESSFUL;
  389. }
  390. ntstatus = ParseResponse( NdsReply,
  391. dwReplyLength,
  392. "GD",
  393. &nwstatus );
  394. if ( !NT_SUCCESS( ntstatus ) )
  395. {
  396. #if DBG
  397. KdPrint(( "NDS32: NwNdsAddObject: The add name response was undecipherable.\n" ));
  398. #endif
  399. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  400. return (DWORD) UNSUCCESSFUL;
  401. }
  402. SetLastError( MapNetwareErrorCode( nwstatus ) );
  403. return nwstatus;
  404. }
  405. DWORD
  406. NwNdsAddAttributeToClass(
  407. IN HANDLE hTree,
  408. IN LPWSTR szClassName,
  409. IN LPWSTR szAttributeName )
  410. /*
  411. NwNdsAddAttributeToClass()
  412. This function is used to modify the schema definition of a class by adding
  413. an optional attribute to a particular class. Modification of existing NDS
  414. class defintions is limited to only adding additional optional attributes.
  415. Arguments:
  416. HANDLE hTree - A handle to the directory tree to be
  417. manipulated. Handle is obtained by calling
  418. NwNdsOpenObject.
  419. LPWSTR szClassName - The name of the class definition to be
  420. modified.
  421. LPWSTR szAttributeName - The name of the attribute to be added
  422. as an optional attribute to the class defintion in the
  423. schema.
  424. Returns:
  425. NO_ERROR
  426. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  427. */
  428. {
  429. DWORD nwstatus;
  430. DWORD status = NO_ERROR;
  431. NTSTATUS ntstatus = STATUS_SUCCESS;
  432. DWORD dwReplyLength;
  433. BYTE NdsReply[NDS_BUFFER_SIZE];
  434. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  435. UNICODE_STRING ClassName;
  436. UNICODE_STRING AttributeName;
  437. if ( szAttributeName == NULL ||
  438. szClassName == NULL ||
  439. lpNdsObject == NULL ||
  440. lpNdsObject->Signature != NDS_SIGNATURE )
  441. {
  442. SetLastError( ERROR_INVALID_PARAMETER );
  443. return (DWORD) UNSUCCESSFUL;
  444. }
  445. RtlInitUnicodeString( &ClassName, szClassName );
  446. RtlInitUnicodeString( &AttributeName, szAttributeName );
  447. ntstatus =
  448. FragExWithWait(
  449. lpNdsObject->NdsTree,
  450. NETWARE_NDS_FUNCTION_MODIFY_CLASS,
  451. NdsReply,
  452. NDS_BUFFER_SIZE,
  453. &dwReplyLength,
  454. "DSDS",
  455. 0, // Version
  456. &ClassName,
  457. 1, // Number of attributes
  458. &AttributeName
  459. );
  460. if ( !NT_SUCCESS( ntstatus ) )
  461. {
  462. #if DBG
  463. KdPrint(( "NDS32: NwNdsAddAttributeToClass: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  464. #endif
  465. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  466. return (DWORD) UNSUCCESSFUL;
  467. }
  468. ntstatus = ParseResponse( NdsReply,
  469. dwReplyLength,
  470. "GD",
  471. &nwstatus );
  472. if ( !NT_SUCCESS( ntstatus ) )
  473. {
  474. #if DBG
  475. KdPrint(( "NDS32: NwNdsAddAttributeToClass: The modify class definition response was undecipherable.\n" ));
  476. #endif
  477. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  478. return (DWORD) UNSUCCESSFUL;
  479. }
  480. SetLastError( MapNetwareErrorCode( nwstatus ) );
  481. return nwstatus;
  482. }
  483. DWORD
  484. NwNdsChangeUserPassword(
  485. IN HANDLE hUserObject,
  486. IN LPWSTR szOldPassword,
  487. IN LPWSTR szNewPassword )
  488. /*
  489. NwNdsChangeUserPassword()
  490. This function is used to change the password for a given user object
  491. in a NDS directory tree.
  492. Arguments:
  493. HANDLE hUserObject - A handle to a specific user object in
  494. the directory tree to change the password on. Handle
  495. is obtained by calling NwNdsOpenObject.
  496. LPWSTR szOldPassword - The current password set on the user
  497. object hUserObject.
  498. - OR -
  499. If NwNdsChangeUserPassword is called from a client with
  500. administrative priveleges to the specified user object
  501. identified by hUserObject, then the szOldPassword
  502. value can be blank (L""). This way resetting the user
  503. password to szNewPassword.
  504. LPWSTR szNewPassword - The new password to be set on the user
  505. object hUserObject.
  506. Returns:
  507. NO_ERROR
  508. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  509. */
  510. {
  511. DWORD status = NO_ERROR;
  512. NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
  513. UNICODE_STRING TreeNameStr;
  514. UNICODE_STRING UserNameStr;
  515. UNICODE_STRING OldPasswordStr;
  516. UNICODE_STRING NewPasswordStr;
  517. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hUserObject;
  518. DWORD tempStrLen = 0;
  519. LPWSTR tempStr = NULL;
  520. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  521. lpNdsObject->szContainerName,
  522. PARSE_NDS_GET_TREE_NAME );
  523. TreeNameStr.Buffer = tempStr;
  524. TreeNameStr.Length = (WORD) tempStrLen;
  525. TreeNameStr.MaximumLength = (WORD) tempStrLen;
  526. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  527. lpNdsObject->szContainerName,
  528. PARSE_NDS_GET_PATH_NAME );
  529. #ifndef WIN95
  530. UserNameStr.Buffer = tempStr;
  531. UserNameStr.Length = (WORD) tempStrLen;
  532. UserNameStr.MaximumLength = (WORD) tempStrLen;
  533. RtlInitUnicodeString( &OldPasswordStr, szOldPassword );
  534. RtlInitUnicodeString( &NewPasswordStr, szNewPassword );
  535. ntstatus = NwNdsChangePassword( lpNdsObject->NdsTree,
  536. &TreeNameStr,
  537. &UserNameStr,
  538. &OldPasswordStr,
  539. &NewPasswordStr );
  540. #else
  541. {
  542. LPSTR pszUser = NULL;
  543. LPSTR pszOldPasswd = NULL;
  544. LPSTR pszNewPasswd = NULL;
  545. NW_STATUS nwstatus;
  546. if (!(pszUser = AllocateAnsiString(tempStr))) {
  547. ntstatus = STATUS_NO_MEMORY;
  548. goto Exit;
  549. }
  550. if (!(pszOldPasswd = AllocateAnsiString(szOldPassword))) {
  551. ntstatus = STATUS_NO_MEMORY;
  552. goto Exit;
  553. }
  554. if (!(pszNewPasswd= AllocateAnsiString(szNewPassword))) {
  555. ntstatus = STATUS_NO_MEMORY;
  556. goto Exit;
  557. }
  558. nwstatus = NDSChangePassword( pszUser,
  559. pszOldPasswd,
  560. pszNewPasswd );
  561. ntstatus = MapNwToNtStatus(nwstatus);
  562. Exit:
  563. if (pszUser)
  564. FreeAnsiString(pszUser);
  565. if (pszOldPasswd)
  566. FreeAnsiString(pszOldPasswd);
  567. if (pszNewPasswd)
  568. FreeAnsiString(pszNewPasswd);
  569. }
  570. #endif
  571. if ( ntstatus != STATUS_SUCCESS )
  572. {
  573. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  574. status = (DWORD) UNSUCCESSFUL;
  575. }
  576. return status;
  577. }
  578. DWORD
  579. NwNdsCloseObject(
  580. IN HANDLE hObject )
  581. /*
  582. NwNdsCloseObject()
  583. This function is used to close the handle used to manipulate an object
  584. in an NDS directory tree. The handle must be one Opened by NwNdsOpenObject.
  585. Arguments:
  586. HANDLE lphObject - The handle of the object to be closed.
  587. Returns:
  588. NO_ERROR
  589. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  590. */
  591. {
  592. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  593. if ( lpNdsObject->Signature != NDS_SIGNATURE )
  594. {
  595. SetLastError( ERROR_INVALID_PARAMETER );
  596. return (DWORD) UNSUCCESSFUL;
  597. }
  598. if ( lpNdsObject )
  599. {
  600. if ( lpNdsObject->NdsTree )
  601. CloseHandle( lpNdsObject->NdsTree );
  602. if ( lpNdsObject->NdsRawDataBuffer )
  603. {
  604. (void) LocalFree( (HLOCAL) lpNdsObject->NdsRawDataBuffer );
  605. lpNdsObject->NdsRawDataBuffer = 0;
  606. lpNdsObject->NdsRawDataSize = 0;
  607. lpNdsObject->NdsRawDataId = INITIAL_ITERATION;
  608. lpNdsObject->NdsRawDataCount = 0;
  609. }
  610. (void) LocalFree( (HLOCAL) lpNdsObject );
  611. }
  612. else
  613. {
  614. SetLastError( ERROR_INVALID_PARAMETER );
  615. return (DWORD) UNSUCCESSFUL;
  616. }
  617. return NO_ERROR;
  618. }
  619. DWORD
  620. NwNdsCreateBuffer(
  621. IN DWORD dwOperation,
  622. OUT HANDLE * lphOperationData )
  623. /*
  624. NwNdsCreateBuffer()
  625. This function is used to create a buffer used to describe object
  626. transactions to a specific object in an NDS directory tree. This routine
  627. allocates memory and is automatically resized as needed during calls
  628. to NwNdsPutInBuffer. This buffer must be freed with NwNdsFreeBuffer.
  629. Arguments:
  630. DWORD dwOperation - Indicates how buffer is to be utilized.
  631. Use defined values NDS_OBJECT_ADD, NDS_OBJECT_MODIFY,
  632. NDS_OBJECT_READ, NDS_SCHEMA_DEFINE_CLASS,
  633. NDS_SCHEMA_READ_ATTR_DEF, NDS_SCHEMA_READ_CLASS_DEF,
  634. NDS_OBJECT_LIST_SUBORDINATES, NDS_SEARCH.
  635. HANDLE * lphOperationData - Address of a HANDLE handle to
  636. receive created buffer.
  637. Returns:
  638. NO_ERROR
  639. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  640. */
  641. {
  642. LPNDS_BUFFER lpNdsBuffer = NULL;
  643. DWORD dwSizeOfBuffer = TWO_KB; // Initial size, grow as needed.
  644. switch( dwOperation )
  645. {
  646. case NDS_OBJECT_ADD:
  647. case NDS_OBJECT_MODIFY:
  648. case NDS_OBJECT_READ:
  649. case NDS_SCHEMA_DEFINE_CLASS:
  650. case NDS_SCHEMA_READ_ATTR_DEF:
  651. case NDS_SCHEMA_READ_CLASS_DEF:
  652. case NDS_OBJECT_LIST_SUBORDINATES:
  653. case NDS_SEARCH:
  654. break;
  655. default:
  656. #if DBG
  657. KdPrint(( "NDS32: NwNdsCreateBuffer parameter dwOperation unknown 0x%.8X\n", dwOperation ));
  658. ASSERT( FALSE );
  659. #endif
  660. SetLastError( ERROR_INVALID_PARAMETER );
  661. return (DWORD) UNSUCCESSFUL;
  662. }
  663. //
  664. // Allocate memory for the buffer.
  665. //
  666. lpNdsBuffer =
  667. (LPNDS_BUFFER) LocalAlloc( LPTR, sizeof(NDS_BUFFER) );
  668. if ( lpNdsBuffer == NULL )
  669. {
  670. #if DBG
  671. KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  672. #endif
  673. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  674. return (DWORD) UNSUCCESSFUL;
  675. }
  676. //
  677. // Initialize the contents of the header structure.
  678. //
  679. lpNdsBuffer->dwBufferId = NDS_SIGNATURE;
  680. lpNdsBuffer->dwOperation = dwOperation;
  681. if ( dwOperation == NDS_OBJECT_LIST_SUBORDINATES )
  682. {
  683. lpNdsBuffer->dwIndexBufferSize = dwSizeOfBuffer;
  684. lpNdsBuffer->dwIndexAvailableBytes = dwSizeOfBuffer;
  685. }
  686. else
  687. {
  688. lpNdsBuffer->dwRequestBufferSize = dwSizeOfBuffer;
  689. lpNdsBuffer->dwRequestAvailableBytes = dwSizeOfBuffer;
  690. }
  691. //
  692. // NOTE: The following are set to zero by LPTR
  693. //
  694. // lpNdsBuffer->dwNumberOfRequestEntries = 0;
  695. // lpNdsBuffer->dwLengthOfRequestData = 0;
  696. // lpNdsBuffer->dwReplyBufferSize = 0;
  697. // lpNdsBuffer->dwReplyAvailableBytes = 0;
  698. // lpNdsBuffer->dwNumberOfReplyEntries = 0;
  699. // lpNdsBuffer->dwLengthOfReplyData = 0;
  700. // lpNdsBuffer->dwReplyInformationType = 0;
  701. // lpNdsBuffer->lpReplyBuffer = NULL;
  702. // lpNdsBuffer->dwNumberOfIndexEntries = 0;
  703. // lpNdsBuffer->dwLengthOfIndexData = 0;
  704. // lpNdsBuffer->dwCurrentIndexEntry = 0;
  705. // lpNdsBuffer->dwSyntaxBufferSize = 0;
  706. // lpNdsBuffer->dwSyntaxAvailableBytes = 0;
  707. // lpNdsBuffer->dwNumberOfSyntaxEntries = 0;
  708. // lpNdsBuffer->dwLengthOfSyntaxData = 0;
  709. // lpNdsBuffer->lpSyntaxBuffer = NULL;
  710. //
  711. // Now allocate the data buffer.
  712. //
  713. if ( dwOperation == NDS_OBJECT_LIST_SUBORDINATES )
  714. {
  715. lpNdsBuffer->lpIndexBuffer =
  716. (LPBYTE) LocalAlloc( LPTR, dwSizeOfBuffer );
  717. if ( lpNdsBuffer->lpIndexBuffer == NULL )
  718. {
  719. #if DBG
  720. KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  721. #endif
  722. (void) LocalFree((HLOCAL) lpNdsBuffer);
  723. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  724. return (DWORD) UNSUCCESSFUL;
  725. }
  726. }
  727. else
  728. {
  729. lpNdsBuffer->lpRequestBuffer =
  730. (LPBYTE) LocalAlloc( LPTR, dwSizeOfBuffer );
  731. if ( lpNdsBuffer->lpRequestBuffer == NULL )
  732. {
  733. #if DBG
  734. KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  735. #endif
  736. (void) LocalFree((HLOCAL) lpNdsBuffer);
  737. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  738. return (DWORD) UNSUCCESSFUL;
  739. }
  740. }
  741. *lphOperationData = (HANDLE) lpNdsBuffer;
  742. return NO_ERROR;
  743. }
  744. DWORD
  745. NwNdsCreateQueryNode(
  746. IN DWORD dwOperation,
  747. IN LPVOID lpLValue,
  748. IN DWORD dwSyntaxId,
  749. IN LPVOID lpRValue,
  750. OUT LPQUERY_NODE * lppQueryNode
  751. )
  752. /*
  753. NwNdsCreateQueryNode()
  754. This function is used to generate a tree node that is part of a query
  755. to be used with the function NwNdsSearch.
  756. Arguments:
  757. DWORD dwOperation - Indicates the type of node to create
  758. for a search query. Use one of the defined values
  759. below:
  760. NDS_QUERY_OR
  761. NDS_QUERY_AND :
  762. These operations must have both lpLValue and
  763. lpRValue pointing to a QUERY_NODE structure.
  764. In this case the dwSyntaxId value is ignored.
  765. NDS_QUERY_NOT :
  766. This operation must have lpLValue pointing to a
  767. QUERY_NODE structure and lpRValue set to NULL.
  768. In this case the dwSyntaxId value is ignored.
  769. NDS_QUERY_EQUAL
  770. NDS_QUERY_GE
  771. NDS_QUERY_LE
  772. NDS_QUERY_APPROX :
  773. These operations must have lpLValue pointing to
  774. a LPWSTR containing the name of an NDS attribute,
  775. and lpRValue pointing to an ASN1 structure defined
  776. in NdsSntx.h. dwSyntaxId must be set to the syntax
  777. identifier of the ASN1 structure pointed to by
  778. lpRValue.
  779. NDS_QUERY_PRESENT :
  780. This operation must have lpLValue pointing to a
  781. LPWSTR containing the name of an NDS attribute,
  782. and lpRValue set to NULL. In this case the
  783. dwSyntaxId value is ignored.
  784. LPVOID lpLValue - A pointer to either a QUERY_NODE structure
  785. or a LPWSTR depending on the value for dwOperation.
  786. DWORD dwSyntaxId - The syntax identifier of the ASN1
  787. structure pointed to by lpRValue for the dwOperations
  788. NDS_QUERY_EQUAL, NDS_QUERY_GE, NDS_QUERY_LE, or
  789. NDS_QUERY_APPROX. For other dwOperation values, this
  790. is ignored.
  791. LPVOID lpRValue - A pointer to either a QUERY_NODE structure,
  792. an ASN1 structure, or NULL, depending on the value for
  793. dwOperation.
  794. LPQUERY_NODE * lppQueryNode - Address of a LPQUERY_NODE to receive
  795. a pointer to created node.
  796. Returns:
  797. NO_ERROR
  798. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  799. */
  800. {
  801. LPWSTR szAttributeName;
  802. DWORD dwAttributeNameLen;
  803. LPWSTR szRValueString;
  804. DWORD dwRValueStringLen;
  805. switch( dwOperation )
  806. {
  807. case NDS_QUERY_OR :
  808. case NDS_QUERY_AND :
  809. if ( lpLValue == NULL || lpRValue == NULL )
  810. {
  811. #if DBG
  812. KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L or R value.\n" ));
  813. #endif
  814. SetLastError( ERROR_INVALID_PARAMETER );
  815. return (DWORD) UNSUCCESSFUL;
  816. }
  817. *lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
  818. sizeof(QUERY_NODE) );
  819. if ( *lppQueryNode == NULL )
  820. {
  821. #if DBG
  822. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  823. #endif
  824. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  825. return (DWORD) UNSUCCESSFUL;
  826. }
  827. (*lppQueryNode)->dwOperation = dwOperation;
  828. (*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
  829. (*lppQueryNode)->lpLVal = lpLValue;
  830. (*lppQueryNode)->lpRVal = lpRValue;
  831. break;
  832. case NDS_QUERY_NOT :
  833. if ( lpLValue == NULL )
  834. {
  835. #if DBG
  836. KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
  837. #endif
  838. SetLastError( ERROR_INVALID_PARAMETER );
  839. return (DWORD) UNSUCCESSFUL;
  840. }
  841. *lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
  842. sizeof(QUERY_NODE) );
  843. if ( *lppQueryNode == NULL )
  844. {
  845. #if DBG
  846. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  847. #endif
  848. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  849. return (DWORD) UNSUCCESSFUL;
  850. }
  851. (*lppQueryNode)->dwOperation = dwOperation;
  852. (*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
  853. (*lppQueryNode)->lpLVal = lpLValue;
  854. (*lppQueryNode)->lpRVal = NULL;
  855. break;
  856. case NDS_QUERY_EQUAL :
  857. case NDS_QUERY_GE :
  858. case NDS_QUERY_LE :
  859. case NDS_QUERY_APPROX :
  860. switch( dwSyntaxId )
  861. {
  862. case NDS_SYNTAX_ID_1 :
  863. case NDS_SYNTAX_ID_2 :
  864. case NDS_SYNTAX_ID_3 :
  865. case NDS_SYNTAX_ID_4 :
  866. case NDS_SYNTAX_ID_5 :
  867. case NDS_SYNTAX_ID_10 :
  868. case NDS_SYNTAX_ID_20 :
  869. //
  870. // This syntax is in the form of a LPWSTR.
  871. //
  872. szAttributeName = (LPWSTR) lpLValue;
  873. dwAttributeNameLen = ROUND_UP_COUNT(
  874. ( wcslen( szAttributeName ) + 1 ) *
  875. sizeof(WCHAR),
  876. ALIGN_DWORD );
  877. szRValueString = ((LPASN1_TYPE_1) lpRValue)->DNString;
  878. dwRValueStringLen = ROUND_UP_COUNT(
  879. ( wcslen( szRValueString ) + 1 ) *
  880. sizeof(WCHAR),
  881. ALIGN_DWORD );
  882. *lppQueryNode = (LPQUERY_NODE)
  883. LocalAlloc( LPTR,
  884. sizeof(QUERY_NODE) +
  885. dwAttributeNameLen +
  886. dwRValueStringLen );
  887. if ( *lppQueryNode == NULL )
  888. {
  889. #if DBG
  890. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  891. #endif
  892. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  893. return (DWORD) UNSUCCESSFUL;
  894. }
  895. (*lppQueryNode)->dwOperation = dwOperation;
  896. (*lppQueryNode)->dwSyntaxId = dwSyntaxId;
  897. (*lppQueryNode)->lpLVal = *lppQueryNode;
  898. (LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
  899. wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
  900. (*lppQueryNode)->lpRVal = (*lppQueryNode)->lpLVal;
  901. (LPBYTE) (*lppQueryNode)->lpRVal += dwAttributeNameLen;
  902. wcscpy( (LPWSTR) (*lppQueryNode)->lpRVal, szRValueString );
  903. break;
  904. case NDS_SYNTAX_ID_7 :
  905. case NDS_SYNTAX_ID_8 :
  906. case NDS_SYNTAX_ID_22 :
  907. case NDS_SYNTAX_ID_24 :
  908. case NDS_SYNTAX_ID_27 :
  909. //
  910. // This syntax is in the form of a DWORD.
  911. //
  912. szAttributeName = (LPWSTR) lpLValue;
  913. dwAttributeNameLen = ROUND_UP_COUNT(
  914. ( wcslen( szAttributeName ) + 1 ) *
  915. sizeof(WCHAR),
  916. ALIGN_DWORD );
  917. *lppQueryNode = (LPQUERY_NODE)
  918. LocalAlloc( LPTR,
  919. sizeof(QUERY_NODE) +
  920. dwAttributeNameLen +
  921. sizeof(ASN1_TYPE_8) );
  922. if ( *lppQueryNode == NULL )
  923. {
  924. #if DBG
  925. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  926. #endif
  927. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  928. return (DWORD) UNSUCCESSFUL;
  929. }
  930. (*lppQueryNode)->dwOperation = dwOperation;
  931. (*lppQueryNode)->dwSyntaxId = dwSyntaxId;
  932. (*lppQueryNode)->lpLVal = *lppQueryNode;
  933. (LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
  934. wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal,
  935. szAttributeName );
  936. (*lppQueryNode)->lpRVal = (LPQUERY_NODE)((LPBYTE)((*lppQueryNode)->lpLVal) +
  937. dwAttributeNameLen);
  938. ((LPASN1_TYPE_8)(*lppQueryNode)->lpRVal)->Integer =
  939. ((LPASN1_TYPE_8)lpRValue)->Integer;
  940. break;
  941. case NDS_SYNTAX_ID_9 :
  942. //
  943. // This syntax is in the form of an Octet String.
  944. //
  945. szAttributeName = (LPWSTR) lpLValue;
  946. dwAttributeNameLen = ROUND_UP_COUNT(
  947. ( wcslen( szAttributeName ) + 1 ) *
  948. sizeof(WCHAR),
  949. ALIGN_DWORD );
  950. *lppQueryNode = (LPQUERY_NODE)
  951. LocalAlloc( LPTR,
  952. sizeof(QUERY_NODE) +
  953. dwAttributeNameLen +
  954. sizeof( DWORD ) +
  955. ((LPASN1_TYPE_9) lpRValue)->Length + 1 );
  956. if ( *lppQueryNode == NULL )
  957. {
  958. #if DBG
  959. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  960. #endif
  961. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  962. return (DWORD) UNSUCCESSFUL;
  963. }
  964. (*lppQueryNode)->dwOperation = dwOperation;
  965. (*lppQueryNode)->dwSyntaxId = dwSyntaxId;
  966. (*lppQueryNode)->lpLVal = *lppQueryNode;
  967. (LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
  968. wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
  969. (*lppQueryNode)->lpRVal = (*lppQueryNode)->lpLVal;
  970. (LPBYTE) (*lppQueryNode)->lpRVal += dwAttributeNameLen;
  971. *((LPDWORD) (*lppQueryNode)->lpRVal) =
  972. ((LPASN1_TYPE_9) lpRValue)->Length;
  973. (LPBYTE) (*lppQueryNode)->lpRVal += sizeof( DWORD );
  974. memcpy( (*lppQueryNode)->lpRVal,
  975. ((LPASN1_TYPE_9) lpRValue)->OctetString,
  976. ((LPASN1_TYPE_9) lpRValue)->Length );
  977. (LPBYTE) (*lppQueryNode)->lpRVal -= sizeof( DWORD );
  978. break;
  979. default :
  980. SetLastError( ERROR_NOT_SUPPORTED );
  981. return (DWORD) UNSUCCESSFUL;
  982. }
  983. break;
  984. case NDS_QUERY_PRESENT :
  985. if ( lpLValue == NULL )
  986. {
  987. #if DBG
  988. KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
  989. #endif
  990. SetLastError( ERROR_INVALID_PARAMETER );
  991. return (DWORD) UNSUCCESSFUL;
  992. }
  993. szAttributeName = (LPWSTR) lpLValue;
  994. dwAttributeNameLen = ( wcslen( szAttributeName ) + 1 ) *
  995. sizeof(WCHAR);
  996. *lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
  997. sizeof(QUERY_NODE) +
  998. dwAttributeNameLen );
  999. if ( *lppQueryNode == NULL )
  1000. {
  1001. #if DBG
  1002. KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  1003. #endif
  1004. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1005. return (DWORD) UNSUCCESSFUL;
  1006. }
  1007. (*lppQueryNode)->dwOperation = dwOperation;
  1008. (*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
  1009. (*lppQueryNode)->lpLVal = (*lppQueryNode);
  1010. (LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
  1011. wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
  1012. (*lppQueryNode)->lpRVal = NULL;
  1013. break;
  1014. default :
  1015. #if DBG
  1016. KdPrint(( "NDS32: NwNdsCreateQueryNode was passed an unidentified operation - 0x%.8X.\n", dwOperation ));
  1017. #endif
  1018. SetLastError( ERROR_INVALID_PARAMETER );
  1019. return (DWORD) UNSUCCESSFUL;
  1020. }
  1021. return NO_ERROR;
  1022. }
  1023. DWORD
  1024. NwNdsDefineAttribute(
  1025. IN HANDLE hTree,
  1026. IN LPWSTR szAttributeName,
  1027. IN DWORD dwFlags,
  1028. IN DWORD dwSyntaxID,
  1029. IN DWORD dwLowerLimit,
  1030. IN DWORD dwUpperLimit,
  1031. IN ASN1_ID asn1ID )
  1032. /*
  1033. NwNdsDefineAttribute()
  1034. This function is used to create an attribute definition in the schema of
  1035. NDS tree hTree.
  1036. Arguments:
  1037. HANDLE hTree - A handle to the directory tree to be
  1038. manipulated. Handle is obtained by calling
  1039. NwNdsOpenObject.
  1040. LPWSTR szAttributeName - The name that the new attribute will
  1041. be referred to by.
  1042. DWORD dwFlags - Flags values to be set for new attribute
  1043. definition. Definitions for flag values are found at
  1044. the top of the file Nds32.h.
  1045. DWORD dwSyntaxID - The ID of the syntax structure to be use
  1046. for the new attribute. Syntax IDs and their associated
  1047. structures are defined in the file NdsSntx.h. According
  1048. to the NetWare NDS schema spec, there is and always will
  1049. be, only 28 (0..27) different syntaxes.
  1050. DWORD dwLowerLimit - The lower limit of a sized attribute
  1051. (dwFlags value set to NDS_SIZED_ATTR). Can be set to
  1052. zero if attribute is not sized.
  1053. DWORD dwUpperLimit - The upper limit of a sized attribute
  1054. (dwFlags value set to NDS_SIZED_ATTR). Can be set to
  1055. zero if attribute is not sized.
  1056. ASN1_ID asn1ID - The ASN.1 ID for the attribute. If no
  1057. attribute identifier has been registered, a
  1058. zero-length octet string is specified.
  1059. Returns:
  1060. NO_ERROR
  1061. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1062. */
  1063. {
  1064. DWORD nwstatus;
  1065. DWORD status = NO_ERROR;
  1066. NTSTATUS ntstatus = STATUS_SUCCESS;
  1067. DWORD dwReplyLength;
  1068. BYTE NdsReply[NDS_BUFFER_SIZE];
  1069. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  1070. UNICODE_STRING AttributeName;
  1071. if ( szAttributeName == NULL ||
  1072. lpNdsObject == NULL ||
  1073. lpNdsObject->Signature != NDS_SIGNATURE )
  1074. {
  1075. SetLastError( ERROR_INVALID_PARAMETER );
  1076. return (DWORD) UNSUCCESSFUL;
  1077. }
  1078. RtlInitUnicodeString( &AttributeName, szAttributeName );
  1079. ntstatus =
  1080. FragExWithWait(
  1081. lpNdsObject->NdsTree,
  1082. NETWARE_NDS_FUNCTION_DEFINE_ATTR,
  1083. NdsReply,
  1084. NDS_BUFFER_SIZE,
  1085. &dwReplyLength,
  1086. "DDSDDDD",
  1087. 0, // Version
  1088. dwFlags,
  1089. &AttributeName,
  1090. dwSyntaxID,
  1091. dwLowerLimit,
  1092. dwUpperLimit,
  1093. 0 // ASN1 Id
  1094. );
  1095. if ( !NT_SUCCESS( ntstatus ) )
  1096. {
  1097. #if DBG
  1098. KdPrint(( "NDS32: NwNdsDefineAttribute: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  1099. #endif
  1100. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1101. return (DWORD) UNSUCCESSFUL;
  1102. }
  1103. ntstatus = ParseResponse( NdsReply,
  1104. dwReplyLength,
  1105. "GD",
  1106. &nwstatus );
  1107. if ( !NT_SUCCESS( ntstatus ) )
  1108. {
  1109. #if DBG
  1110. KdPrint(( "NDS32: NwNdsDefineAttribute: The define attribute response was undecipherable.\n" ));
  1111. #endif
  1112. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1113. return (DWORD) UNSUCCESSFUL;
  1114. }
  1115. SetLastError( MapNetwareErrorCode( nwstatus ) );
  1116. return nwstatus;
  1117. }
  1118. DWORD
  1119. NwNdsDefineClass(
  1120. IN HANDLE hTree,
  1121. IN LPWSTR szClassName,
  1122. IN DWORD dwFlags,
  1123. IN ASN1_ID asn1ID,
  1124. IN HANDLE hSuperClasses,
  1125. IN HANDLE hContainmentClasses,
  1126. IN HANDLE hNamingAttributes,
  1127. IN HANDLE hMandatoryAttributes,
  1128. IN HANDLE hOptionalAttributes )
  1129. /*
  1130. NwNdsDefineClass()
  1131. This function is used to create a class definition in the schema of
  1132. NDS tree hTree.
  1133. Arguments:
  1134. HANDLE hTree - A handle to the directory tree to be
  1135. manipulated. Handle is obtained by calling
  1136. NwNdsOpenObject.
  1137. LPWSTR szClassName - The name that the new class will
  1138. be referred to by.
  1139. DWORD dwFlags - Flags values to be set for new class
  1140. definition. Definitions for flag values are found at
  1141. the top of the file Nds32.h.
  1142. ASN1_ID asn1ID - The ASN.1 ID for the class. If no
  1143. class identifier has been registered, a
  1144. zero-length octet string is specified.
  1145. HANDLE(S) hSuperClasses,
  1146. hContainmentClasses,
  1147. hNamingAttributes,
  1148. hMandatoryAttributes,
  1149. hOptionalAttributes -
  1150. Handle to buffers that contain class definition
  1151. information to create new class in schema.
  1152. These handles are manipulated by the following
  1153. functions:
  1154. NwNdsCreateBuffer (NDS_SCHEMA_DEFINE_CLASS),
  1155. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  1156. - OR -
  1157. Handles can be NULL to indicate that no list
  1158. is associated with the specific class defintion
  1159. item.
  1160. Returns:
  1161. NO_ERROR
  1162. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1163. */
  1164. {
  1165. DWORD nwstatus;
  1166. DWORD status = NO_ERROR;
  1167. NTSTATUS ntstatus = STATUS_SUCCESS;
  1168. DWORD dwReplyLength;
  1169. BYTE NdsReply[NDS_BUFFER_SIZE];
  1170. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  1171. UNICODE_STRING ClassName;
  1172. LPNDS_BUFFER lpSuperClasses = (LPNDS_BUFFER) hSuperClasses;
  1173. LPNDS_BUFFER lpContainmentClasses = (LPNDS_BUFFER) hContainmentClasses;
  1174. LPNDS_BUFFER lpNamingAttributes = (LPNDS_BUFFER) hNamingAttributes;
  1175. LPNDS_BUFFER lpMandatoryAttributes = (LPNDS_BUFFER) hMandatoryAttributes;
  1176. LPNDS_BUFFER lpOptionalAttributes = (LPNDS_BUFFER) hOptionalAttributes;
  1177. DWORD NumberOfSuperClasses = 0;
  1178. DWORD NumberOfContainmentClasses = 0;
  1179. DWORD NumberOfNamingAttributes = 0;
  1180. DWORD NumberOfMandatoryAttributes = 0;
  1181. DWORD NumberOfOptionalAttributes = 0;
  1182. WORD SuperClassesBufferLength = 0;
  1183. WORD ContainmentClassesBufferLength = 0;
  1184. WORD NamingAttributesBufferLength = 0;
  1185. WORD MandatoryAttributesBufferLength = 0;
  1186. WORD OptionalAttributesBufferLength = 0;
  1187. LPBYTE SuperClassesBuffer = NULL;
  1188. LPBYTE ContainmentClassesBuffer = NULL;
  1189. LPBYTE NamingAttributesBuffer = NULL;
  1190. LPBYTE MandatoryAttributesBuffer = NULL;
  1191. LPBYTE OptionalAttributesBuffer = NULL;
  1192. if ( szClassName == NULL ||
  1193. lpNdsObject == NULL ||
  1194. lpNdsObject->Signature != NDS_SIGNATURE )
  1195. {
  1196. SetLastError( ERROR_INVALID_PARAMETER );
  1197. return (DWORD) UNSUCCESSFUL;
  1198. }
  1199. if ( lpSuperClasses )
  1200. {
  1201. if ( lpSuperClasses->dwBufferId != NDS_SIGNATURE ||
  1202. lpSuperClasses->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
  1203. {
  1204. SetLastError( ERROR_INVALID_PARAMETER );
  1205. return (DWORD) UNSUCCESSFUL;
  1206. }
  1207. NumberOfSuperClasses = lpSuperClasses->dwNumberOfRequestEntries,
  1208. SuperClassesBuffer = lpSuperClasses->lpRequestBuffer,
  1209. SuperClassesBufferLength = (WORD)lpSuperClasses->dwLengthOfRequestData;
  1210. }
  1211. if ( lpContainmentClasses )
  1212. {
  1213. if ( lpContainmentClasses->dwBufferId != NDS_SIGNATURE ||
  1214. lpContainmentClasses->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
  1215. {
  1216. SetLastError( ERROR_INVALID_PARAMETER );
  1217. return (DWORD) UNSUCCESSFUL;
  1218. }
  1219. NumberOfContainmentClasses =
  1220. lpContainmentClasses->dwNumberOfRequestEntries,
  1221. ContainmentClassesBuffer =
  1222. lpContainmentClasses->lpRequestBuffer,
  1223. ContainmentClassesBufferLength =
  1224. (WORD)lpContainmentClasses->dwLengthOfRequestData;
  1225. }
  1226. if ( lpNamingAttributes )
  1227. {
  1228. if ( lpNamingAttributes->dwBufferId != NDS_SIGNATURE ||
  1229. lpNamingAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
  1230. {
  1231. SetLastError( ERROR_INVALID_PARAMETER );
  1232. return (DWORD) UNSUCCESSFUL;
  1233. }
  1234. NumberOfNamingAttributes =
  1235. lpNamingAttributes->dwNumberOfRequestEntries,
  1236. NamingAttributesBuffer =
  1237. lpNamingAttributes->lpRequestBuffer,
  1238. NamingAttributesBufferLength =
  1239. (WORD)lpNamingAttributes->dwLengthOfRequestData;
  1240. }
  1241. if ( lpMandatoryAttributes )
  1242. {
  1243. if ( lpMandatoryAttributes->dwBufferId != NDS_SIGNATURE ||
  1244. lpMandatoryAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
  1245. {
  1246. SetLastError( ERROR_INVALID_PARAMETER );
  1247. return (DWORD) UNSUCCESSFUL;
  1248. }
  1249. NumberOfMandatoryAttributes =
  1250. lpMandatoryAttributes->dwNumberOfRequestEntries,
  1251. MandatoryAttributesBuffer =
  1252. lpMandatoryAttributes->lpRequestBuffer,
  1253. MandatoryAttributesBufferLength =
  1254. (WORD)lpMandatoryAttributes->dwLengthOfRequestData;
  1255. }
  1256. if ( lpOptionalAttributes )
  1257. {
  1258. if ( lpOptionalAttributes->dwBufferId != NDS_SIGNATURE ||
  1259. lpOptionalAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
  1260. {
  1261. SetLastError( ERROR_INVALID_PARAMETER );
  1262. return (DWORD) UNSUCCESSFUL;
  1263. }
  1264. NumberOfOptionalAttributes =
  1265. lpOptionalAttributes->dwNumberOfRequestEntries,
  1266. OptionalAttributesBuffer =
  1267. lpOptionalAttributes->lpRequestBuffer,
  1268. OptionalAttributesBufferLength =
  1269. (WORD)lpOptionalAttributes->dwLengthOfRequestData;
  1270. }
  1271. RtlInitUnicodeString( &ClassName, szClassName );
  1272. ntstatus =
  1273. FragExWithWait(
  1274. lpNdsObject->NdsTree,
  1275. NETWARE_NDS_FUNCTION_DEFINE_CLASS,
  1276. NdsReply,
  1277. NDS_BUFFER_SIZE,
  1278. &dwReplyLength,
  1279. "DDSDDrDrDrDrDr",
  1280. 0, // Version
  1281. dwFlags,
  1282. &ClassName,
  1283. 0, // ASN1 Id
  1284. NumberOfSuperClasses,
  1285. SuperClassesBuffer,
  1286. SuperClassesBufferLength,
  1287. NumberOfContainmentClasses,
  1288. ContainmentClassesBuffer,
  1289. ContainmentClassesBufferLength,
  1290. NumberOfNamingAttributes,
  1291. NamingAttributesBuffer,
  1292. NamingAttributesBufferLength,
  1293. NumberOfMandatoryAttributes,
  1294. MandatoryAttributesBuffer,
  1295. MandatoryAttributesBufferLength,
  1296. NumberOfOptionalAttributes,
  1297. OptionalAttributesBuffer,
  1298. OptionalAttributesBufferLength
  1299. );
  1300. if ( !NT_SUCCESS( ntstatus ) )
  1301. {
  1302. #if DBG
  1303. KdPrint(( "NDS32: NwNdsDefineClass: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  1304. #endif
  1305. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1306. return (DWORD) UNSUCCESSFUL;
  1307. }
  1308. ntstatus = ParseResponse( NdsReply,
  1309. dwReplyLength,
  1310. "GD",
  1311. &nwstatus );
  1312. if ( !NT_SUCCESS( ntstatus ) )
  1313. {
  1314. #if DBG
  1315. KdPrint(( "NDS32: NwNdsDefineClass: The define class response was undecipherable.\n" ));
  1316. #endif
  1317. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1318. return (DWORD) UNSUCCESSFUL;
  1319. }
  1320. SetLastError( MapNetwareErrorCode( nwstatus ) );
  1321. return nwstatus;
  1322. }
  1323. DWORD
  1324. NwNdsDeleteAttrDef(
  1325. IN HANDLE hTree,
  1326. IN LPWSTR szAttributeName )
  1327. /*
  1328. NwNdsDeleteAttrDef()
  1329. This function is used to remove an attribute definition from the schema of
  1330. NDS tree hTree.
  1331. Arguments:
  1332. HANDLE hTree - A handle to the directory tree to be
  1333. manipulated. Handle is obtained by calling
  1334. NwNdsOpenObject.
  1335. LPWSTR szAttributeName - The name of the attribute
  1336. defintion to remove.
  1337. Returns:
  1338. NO_ERROR
  1339. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1340. */
  1341. {
  1342. DWORD nwstatus;
  1343. DWORD status = NO_ERROR;
  1344. NTSTATUS ntstatus = STATUS_SUCCESS;
  1345. DWORD dwReplyLength;
  1346. BYTE NdsReply[NDS_BUFFER_SIZE];
  1347. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  1348. UNICODE_STRING AttributeName;
  1349. if ( szAttributeName == NULL ||
  1350. lpNdsObject == NULL ||
  1351. lpNdsObject->Signature != NDS_SIGNATURE )
  1352. {
  1353. SetLastError( ERROR_INVALID_PARAMETER );
  1354. return (DWORD) UNSUCCESSFUL;
  1355. }
  1356. RtlInitUnicodeString( &AttributeName, szAttributeName );
  1357. ntstatus =
  1358. FragExWithWait(
  1359. lpNdsObject->NdsTree,
  1360. NETWARE_NDS_FUNCTION_REMOVE_ATTR_DEF,
  1361. NdsReply,
  1362. NDS_BUFFER_SIZE,
  1363. &dwReplyLength,
  1364. "DS",
  1365. 0, // Version
  1366. &AttributeName
  1367. );
  1368. if ( !NT_SUCCESS( ntstatus ) )
  1369. {
  1370. #if DBG
  1371. KdPrint(( "NDS32: NwNdsDeleteAttrDef: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  1372. #endif
  1373. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1374. return (DWORD) UNSUCCESSFUL;
  1375. }
  1376. ntstatus = ParseResponse( NdsReply,
  1377. dwReplyLength,
  1378. "GD",
  1379. &nwstatus );
  1380. if ( !NT_SUCCESS( ntstatus ) )
  1381. {
  1382. #if DBG
  1383. KdPrint(( "NDS32: NwNdsDeleteAttrDef: The delete attribute response was undecipherable.\n" ));
  1384. #endif
  1385. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1386. return (DWORD) UNSUCCESSFUL;
  1387. }
  1388. SetLastError( MapNetwareErrorCode( nwstatus ) );
  1389. return nwstatus;
  1390. }
  1391. DWORD
  1392. NwNdsDeleteClassDef(
  1393. IN HANDLE hTree,
  1394. IN LPWSTR szClassName )
  1395. /*
  1396. NwNdsDeleteClassDef()
  1397. This function is used to remove a class definition from the schema of
  1398. NDS tree hTree.
  1399. Arguments:
  1400. HANDLE hTree - A handle to the directory tree to be
  1401. manipulated. Handle is obtained by calling
  1402. NwNdsOpenObject.
  1403. LPWSTR szClassName - The name of the class defintion to remove.
  1404. Returns:
  1405. NO_ERROR
  1406. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1407. */
  1408. {
  1409. DWORD nwstatus;
  1410. DWORD status = NO_ERROR;
  1411. NTSTATUS ntstatus = STATUS_SUCCESS;
  1412. DWORD dwReplyLength;
  1413. BYTE NdsReply[NDS_BUFFER_SIZE];
  1414. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  1415. UNICODE_STRING ClassName;
  1416. if ( szClassName == NULL ||
  1417. lpNdsObject == NULL ||
  1418. lpNdsObject->Signature != NDS_SIGNATURE )
  1419. {
  1420. SetLastError( ERROR_INVALID_PARAMETER );
  1421. return (DWORD) UNSUCCESSFUL;
  1422. }
  1423. RtlInitUnicodeString( &ClassName, szClassName );
  1424. ntstatus =
  1425. FragExWithWait(
  1426. lpNdsObject->NdsTree,
  1427. NETWARE_NDS_FUNCTION_REMOVE_CLASS_DEF,
  1428. NdsReply,
  1429. NDS_BUFFER_SIZE,
  1430. &dwReplyLength,
  1431. "DS",
  1432. 0, // Version
  1433. &ClassName
  1434. );
  1435. if ( !NT_SUCCESS( ntstatus ) )
  1436. {
  1437. #if DBG
  1438. KdPrint(( "NDS32: NwNdsDeleteClassDef: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  1439. #endif
  1440. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1441. return (DWORD) UNSUCCESSFUL;
  1442. }
  1443. ntstatus = ParseResponse( NdsReply,
  1444. dwReplyLength,
  1445. "GD",
  1446. &nwstatus );
  1447. if ( !NT_SUCCESS( ntstatus ) )
  1448. {
  1449. #if DBG
  1450. KdPrint(( "NDS32: NwNdsDeleteClassDef: The delete class response was undecipherable.\n" ));
  1451. #endif
  1452. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1453. return (DWORD) UNSUCCESSFUL;
  1454. }
  1455. SetLastError( MapNetwareErrorCode( nwstatus ) );
  1456. return nwstatus;
  1457. }
  1458. VOID
  1459. NwNdsDeleteQueryNode(
  1460. IN LPQUERY_NODE lpQueryNode
  1461. )
  1462. /*
  1463. NwNdsDeleteQueryNode()
  1464. This function is used to free a tree node that was part of a query
  1465. used with the function NwNdsSearch.
  1466. Arguments:
  1467. LPQUERY_NODE lpQueryNode - A pointer to a particular node of
  1468. a query tree that defines a search. The tree is
  1469. created manually by the user through the function
  1470. NwNdsCreateQueryNode.
  1471. Returns:
  1472. Nothing
  1473. */
  1474. {
  1475. (void) LocalFree( (HLOCAL) lpQueryNode );
  1476. lpQueryNode = NULL;
  1477. }
  1478. DWORD
  1479. NwNdsDeleteQueryTree(
  1480. IN LPQUERY_TREE lpQueryTree
  1481. )
  1482. /*
  1483. NwNdsDeleteQueryTree()
  1484. This function is used to free a tree that describes a query that was
  1485. used with the function NwNdsSearch.
  1486. Arguments:
  1487. LPQUERY_TREE lpQueryTree - A pointer to the root of a query
  1488. tree that defines a search.
  1489. Returns:
  1490. NO_ERROR
  1491. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1492. */
  1493. {
  1494. DWORD status;
  1495. switch( lpQueryTree->dwOperation )
  1496. {
  1497. case NDS_QUERY_OR :
  1498. case NDS_QUERY_AND :
  1499. if ( lpQueryTree->lpLVal == NULL || lpQueryTree->lpRVal == NULL )
  1500. {
  1501. #if DBG
  1502. KdPrint(( "NDS32: NwNdsDeleteQueryTree was not passed a pointer to an L or R value.\n" ));
  1503. #endif
  1504. SetLastError( ERROR_INVALID_PARAMETER );
  1505. return (DWORD) UNSUCCESSFUL;
  1506. }
  1507. status = NwNdsDeleteQueryTree( lpQueryTree->lpLVal );
  1508. if ( status != NO_ERROR )
  1509. {
  1510. return status;
  1511. }
  1512. lpQueryTree->lpLVal = NULL;
  1513. status = NwNdsDeleteQueryTree( lpQueryTree->lpRVal );
  1514. if ( status != NO_ERROR )
  1515. {
  1516. return status;
  1517. }
  1518. lpQueryTree->lpRVal = NULL;
  1519. NwNdsDeleteQueryNode( lpQueryTree );
  1520. break;
  1521. case NDS_QUERY_NOT :
  1522. if ( lpQueryTree->lpLVal == NULL )
  1523. {
  1524. #if DBG
  1525. KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
  1526. #endif
  1527. SetLastError( ERROR_INVALID_PARAMETER );
  1528. return (DWORD) UNSUCCESSFUL;
  1529. }
  1530. status = NwNdsDeleteQueryTree( lpQueryTree->lpLVal );
  1531. if ( status != NO_ERROR )
  1532. {
  1533. return status;
  1534. }
  1535. lpQueryTree->lpLVal = NULL;
  1536. NwNdsDeleteQueryNode( lpQueryTree );
  1537. break;
  1538. case NDS_QUERY_EQUAL :
  1539. case NDS_QUERY_GE :
  1540. case NDS_QUERY_LE :
  1541. case NDS_QUERY_APPROX :
  1542. case NDS_QUERY_PRESENT :
  1543. NwNdsDeleteQueryNode( lpQueryTree );
  1544. break;
  1545. default :
  1546. #if DBG
  1547. KdPrint(( "NDS32: NwNdsDeleteQueryTree was passed an unidentified operation - 0x%.8X.\n", lpQueryTree->dwOperation ));
  1548. #endif
  1549. SetLastError( ERROR_INVALID_PARAMETER );
  1550. return (DWORD) UNSUCCESSFUL;
  1551. }
  1552. return NO_ERROR;
  1553. }
  1554. DWORD
  1555. NwNdsFreeBuffer(
  1556. IN HANDLE hOperationData
  1557. )
  1558. /*
  1559. NwNdsFreeBuffer()
  1560. This function is used to free the buffer used to describe object
  1561. operations to a specific object in an NDS directory tree. The buffer must
  1562. be one created by NwNdsCreateBuffer, or returned by calling NwNdsReadObject,
  1563. NwNdsReadAttrDef, or NwNdsReadClassDef.
  1564. Arguments:
  1565. HANDLE hOperationData - Handle to buffer that is to be freed.
  1566. Returns:
  1567. NO_ERROR
  1568. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1569. */
  1570. {
  1571. DWORD status = NO_ERROR;
  1572. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  1573. if ( lpNdsBuffer == NULL )
  1574. {
  1575. #if DBG
  1576. KdPrint(( "NDS32: NwNdsFreeBuffer was passed a NULL buffer pointer.\n" ));
  1577. #endif
  1578. SetLastError( ERROR_INVALID_PARAMETER );
  1579. return (DWORD) UNSUCCESSFUL;
  1580. }
  1581. if ( lpNdsBuffer->dwBufferId != NDS_SIGNATURE )
  1582. {
  1583. #if DBG
  1584. KdPrint(( "NDS32: NwNdsFreeBuffer was passed an unidentified buffer.\n" ));
  1585. ASSERT( FALSE );
  1586. #endif
  1587. SetLastError( ERROR_INVALID_PARAMETER );
  1588. return (DWORD) UNSUCCESSFUL;
  1589. }
  1590. //
  1591. // If this buffer contains a pointer to an index buffer. Need to free
  1592. // the index buffer.
  1593. //
  1594. if ( lpNdsBuffer->lpIndexBuffer )
  1595. {
  1596. if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
  1597. lpNdsBuffer->dwNumberOfIndexEntries )
  1598. {
  1599. LPNDS_OBJECT_INFO lpObjectInfo = (LPNDS_OBJECT_INFO)
  1600. lpNdsBuffer->lpIndexBuffer;
  1601. DWORD iter;
  1602. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
  1603. {
  1604. (void) LocalFree( (HLOCAL) lpObjectInfo[iter].lpAttribute );
  1605. lpObjectInfo[iter].lpAttribute = NULL;
  1606. lpObjectInfo[iter].dwNumberOfAttributes = 0;
  1607. }
  1608. }
  1609. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
  1610. lpNdsBuffer->lpIndexBuffer = NULL;
  1611. }
  1612. //
  1613. // If this buffer contains a pointer to a reply buffer. Need to free
  1614. // the reply buffer.
  1615. //
  1616. if ( lpNdsBuffer->lpReplyBuffer )
  1617. {
  1618. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  1619. lpNdsBuffer->lpReplyBuffer = NULL;
  1620. }
  1621. //
  1622. // If this buffer contains a pointer to a request buffer. Need to free
  1623. // the request buffer.
  1624. //
  1625. if ( lpNdsBuffer->lpRequestBuffer )
  1626. {
  1627. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
  1628. lpNdsBuffer->lpRequestBuffer = NULL;
  1629. }
  1630. //
  1631. // If this buffer contains a pointer to a syntax buffer. Need to free
  1632. // the syntax buffer.
  1633. //
  1634. if ( lpNdsBuffer->lpSyntaxBuffer )
  1635. {
  1636. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpSyntaxBuffer );
  1637. lpNdsBuffer->lpSyntaxBuffer = NULL;
  1638. }
  1639. //
  1640. // Now free the handle buffer.
  1641. //
  1642. (void) LocalFree((HLOCAL) lpNdsBuffer);
  1643. return NO_ERROR;
  1644. }
  1645. DWORD
  1646. NwNdsGetAttrDefListFromBuffer(
  1647. IN HANDLE hOperationData,
  1648. OUT LPDWORD lpdwNumberOfEntries,
  1649. OUT LPDWORD lpdwInformationType,
  1650. OUT LPVOID * lppEntries )
  1651. /*
  1652. NwNdsGetAttrDefListFromBuffer()
  1653. This function is used to retrieve an array of attribute definition entries
  1654. for a schema that was read with a prior call to NwNdsReadAttrDef.
  1655. Arguments:
  1656. HANDLE hOperationData - Buffer containing the read
  1657. response from calling NwNdsReadAttrDef.
  1658. LPDWORD lpdwNumberOfEntries - The address of a DWORD to
  1659. receive the number of array elements pointed to by
  1660. lppEntries.
  1661. LPDWORD lpdwInformationType - The address of a DWORD to
  1662. receive a value that indicates the type of information
  1663. returned by the call to NwNdsReadAttrDef.
  1664. LPVOID * lppEntries - The address of a pointer to the beginning
  1665. of an array of attribute schema structures. Each
  1666. structure contains the details of each attribute
  1667. definition read from a given schema by calling
  1668. NwNdsReadAttrDef. The lppEntries value should be
  1669. cast to either a LPNDS_ATTR_DEF or LPNDS_NAME_ONLY
  1670. structure depending on the value returned in
  1671. lpdwInformationType.
  1672. Returns:
  1673. NO_ERROR
  1674. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1675. */
  1676. {
  1677. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  1678. //
  1679. // Check to see if the data handle is one for reading attribute definitions.
  1680. //
  1681. if ( lpNdsBuffer == NULL ||
  1682. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  1683. lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_ATTR_DEF )
  1684. {
  1685. SetLastError( ERROR_INVALID_PARAMETER );
  1686. return (DWORD) UNSUCCESSFUL;
  1687. }
  1688. //
  1689. // Check to see if NwNdsReadAttrDef has been called yet.
  1690. //
  1691. if ( lpNdsBuffer->lpReplyBuffer == NULL )
  1692. {
  1693. SetLastError( ERROR_INVALID_PARAMETER );
  1694. return (DWORD) UNSUCCESSFUL;
  1695. }
  1696. //
  1697. // Check to see if the call to NwNdsReadAttrDef returned any attributes.
  1698. //
  1699. if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
  1700. {
  1701. SetLastError( ERROR_NO_DATA );
  1702. return (DWORD) UNSUCCESSFUL;
  1703. }
  1704. //
  1705. // If TRUE, we need to walk raw response to set indexes to data within.
  1706. //
  1707. if ( lpNdsBuffer->lpIndexBuffer == NULL )
  1708. {
  1709. DWORD status;
  1710. if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
  1711. {
  1712. status = IndexReadNameReplyBuffer( lpNdsBuffer );
  1713. }
  1714. else
  1715. {
  1716. status = IndexReadAttrDefReplyBuffer( lpNdsBuffer );
  1717. }
  1718. if ( status )
  1719. {
  1720. SetLastError( status );
  1721. return (DWORD) UNSUCCESSFUL;
  1722. }
  1723. }
  1724. lpNdsBuffer->dwCurrentIndexEntry = 0;
  1725. *lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
  1726. *lpdwInformationType = lpNdsBuffer->dwReplyInformationType;
  1727. *lppEntries = (LPVOID) lpNdsBuffer->lpIndexBuffer;
  1728. return NO_ERROR;
  1729. }
  1730. DWORD
  1731. NwNdsGetAttrListFromBuffer(
  1732. IN HANDLE hOperationData,
  1733. OUT LPDWORD lpdwNumberOfEntries,
  1734. OUT LPNDS_ATTR_INFO * lppEntries )
  1735. /*
  1736. NwNdsGetAttrListFromBuffer()
  1737. This function is used to retrieve an array of attribute entries for an
  1738. object that was read with a prior call to NwNdsReadObject.
  1739. Arguments:
  1740. HANDLE hOperationData - Buffer containing the read
  1741. response from calling NwNdsReadObject.
  1742. LPDWORD lpdwNumberOfEntries - The address of a DWORD to
  1743. receive the number of array elements pointed to by
  1744. lppEntries.
  1745. LPNDS_ATTR_INFO *
  1746. lppEntries - The address of a pointer to the beginning
  1747. of an array of NDS_ATTR_INFO structures. Each
  1748. structure contains the details of each attribute read
  1749. from a given object by calling NwNdsReadObject.
  1750. Returns:
  1751. NO_ERROR
  1752. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1753. */
  1754. {
  1755. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  1756. //
  1757. // Check to see if the data handle is one for reading attributes.
  1758. //
  1759. if ( lpNdsBuffer == NULL ||
  1760. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  1761. lpNdsBuffer->dwOperation != NDS_OBJECT_READ )
  1762. {
  1763. SetLastError( ERROR_INVALID_PARAMETER );
  1764. return (DWORD) UNSUCCESSFUL;
  1765. }
  1766. //
  1767. // Check to see if NwNdsReadObject has been called yet.
  1768. //
  1769. if ( lpNdsBuffer->lpReplyBuffer == NULL )
  1770. {
  1771. SetLastError( ERROR_INVALID_PARAMETER );
  1772. return (DWORD) UNSUCCESSFUL;
  1773. }
  1774. //
  1775. // Check to see if the call to NwNdsReadObject returned any attributes.
  1776. //
  1777. if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
  1778. {
  1779. SetLastError( ERROR_NO_DATA );
  1780. return (DWORD) UNSUCCESSFUL;
  1781. }
  1782. //
  1783. // If TRUE, we need to walk raw response to set indexes to data within.
  1784. //
  1785. if ( lpNdsBuffer->lpIndexBuffer == NULL )
  1786. {
  1787. DWORD status;
  1788. if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
  1789. {
  1790. status = IndexReadNameReplyBuffer( lpNdsBuffer );
  1791. }
  1792. else
  1793. {
  1794. status = IndexReadObjectReplyBuffer( lpNdsBuffer );
  1795. }
  1796. if ( status )
  1797. {
  1798. SetLastError( status );
  1799. return (DWORD) UNSUCCESSFUL;
  1800. }
  1801. }
  1802. ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
  1803. lpNdsBuffer->dwCurrentIndexEntry = 0;
  1804. *lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
  1805. *lppEntries = (LPNDS_ATTR_INFO) lpNdsBuffer->lpIndexBuffer;
  1806. return NO_ERROR;
  1807. }
  1808. DWORD
  1809. NwNdsGetClassDefListFromBuffer(
  1810. IN HANDLE hOperationData,
  1811. OUT LPDWORD lpdwNumberOfEntries,
  1812. OUT LPDWORD lpdwInformationType,
  1813. OUT LPVOID * lppEntries )
  1814. /*
  1815. NwNdsGetClassDefListFromBuffer()
  1816. This function is used to retrieve an array of class definition entries
  1817. for a schema that was read with a prior call to NwNdsReadClassDef.
  1818. Arguments:
  1819. HANDLE hOperationData - Buffer containing the read
  1820. response from calling NwNdsReadClassDef.
  1821. LPDWORD lpdwNumberOfEntries - The address of a DWORD to
  1822. receive the number of array elements pointed to by
  1823. lppEntries.
  1824. LPDWORD lpdwInformationType - The address of a DWORD to
  1825. receive a value that indicates the type of information
  1826. returned by the call to NwNdsReadClassDef.
  1827. LPVOID * lppEntries - The address of a pointer to the beginning
  1828. of an array of schema class structures. Each
  1829. structure contains the details of each class
  1830. definition read from a given schema by calling
  1831. NwNdsReadClassDef. The lppEntries value should be
  1832. cast to either a LPNDS_CLASS_DEF or LPNDS_DEF_NAME_ONLY
  1833. structure depending on the value returned in
  1834. lpdwInformationType.
  1835. Returns:
  1836. NO_ERROR
  1837. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1838. */
  1839. {
  1840. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  1841. //
  1842. // Check to see if the data handle is one for reading class definitions.
  1843. //
  1844. if ( lpNdsBuffer == NULL ||
  1845. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  1846. lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_CLASS_DEF )
  1847. {
  1848. SetLastError( ERROR_INVALID_PARAMETER );
  1849. return (DWORD) UNSUCCESSFUL;
  1850. }
  1851. //
  1852. // Check to see if NwNdsReadClassDef has been called yet.
  1853. //
  1854. if ( lpNdsBuffer->lpReplyBuffer == NULL )
  1855. {
  1856. SetLastError( ERROR_INVALID_PARAMETER );
  1857. return (DWORD) UNSUCCESSFUL;
  1858. }
  1859. //
  1860. // Check to see if the call to NwNdsReadClassDef returned any classes.
  1861. //
  1862. if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
  1863. {
  1864. SetLastError( ERROR_NO_DATA );
  1865. return (DWORD) UNSUCCESSFUL;
  1866. }
  1867. //
  1868. // If TRUE, we need to walk raw response to set indexes to data within.
  1869. //
  1870. if ( lpNdsBuffer->lpIndexBuffer == NULL )
  1871. {
  1872. DWORD status;
  1873. if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
  1874. {
  1875. status = IndexReadNameReplyBuffer( lpNdsBuffer );
  1876. }
  1877. else
  1878. {
  1879. status = IndexReadClassDefReplyBuffer( lpNdsBuffer );
  1880. }
  1881. if ( status )
  1882. {
  1883. SetLastError( status );
  1884. return (DWORD) UNSUCCESSFUL;
  1885. }
  1886. }
  1887. ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
  1888. lpNdsBuffer->dwCurrentIndexEntry = 0;
  1889. *lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
  1890. *lpdwInformationType = lpNdsBuffer->dwReplyInformationType;
  1891. *lppEntries = (LPVOID) lpNdsBuffer->lpIndexBuffer;
  1892. return NO_ERROR;
  1893. }
  1894. DWORD
  1895. NwNdsGetEffectiveRights(
  1896. IN HANDLE hObject,
  1897. IN LPWSTR szSubjectName,
  1898. IN LPWSTR szAttributeName,
  1899. OUT LPDWORD lpdwRights )
  1900. /*
  1901. NwNdsGetEffectiveRights()
  1902. This function is used to determine the effective rights of a particular
  1903. subject on a particular object in the NDS tree. The user needs to have
  1904. appropriate priveleges to make the determination.
  1905. Arguments:
  1906. HANDLE hObject - A handle to the object in the directory
  1907. tree to determine effective rights on. Handle is
  1908. obtained by calling NwNdsOpenObject.
  1909. LPWSTR szSubjectName - The distinguished name of user whose
  1910. rights we're interested in determining.
  1911. LPWSTR szAttributeName - Regular attribute name (i.e.
  1912. L"Surname" , L"CN" ) for reading a particular
  1913. attribute right, or L"[All Attribute Rights]" and
  1914. L"[Entry Rights]" can be used to determine the default
  1915. attribute rights and object rights respectively.
  1916. LPDWORD lpdwRights - A pointer to a DWORD to receive the
  1917. results. If the call is successful, lpdwRights will
  1918. contain a mask representing the subject's rights:
  1919. Attribute rights - NDS_RIGHT_COMPARE_ATTR,
  1920. NDS_RIGHT_READ_ATTR, NDS_RIGHT_WRITE_ATTR,
  1921. NDS_RIGHT_ADD_SELF_ATTR, and
  1922. NDS_RIGHT_SUPERVISE_ATTR.
  1923. Object rights - NDS_RIGHT_BROWSE_OBJECT,
  1924. NDS_RIGHT_CREATE_OBJECT, NDS_RIGHT_DELETE_OBJECT,
  1925. NDS_RIGHT_RENAME_OBJECT, and
  1926. NDS_RIGHT_SUPERVISE_OBJECT.
  1927. Returns:
  1928. NO_ERROR
  1929. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  1930. */
  1931. {
  1932. DWORD nwstatus;
  1933. DWORD status = NO_ERROR;
  1934. NTSTATUS ntstatus = STATUS_SUCCESS;
  1935. DWORD dwReplyLength;
  1936. BYTE NdsReply[NDS_BUFFER_SIZE];
  1937. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  1938. UNICODE_STRING SubjectName;
  1939. UNICODE_STRING AttributeName;
  1940. if ( szAttributeName == NULL ||
  1941. szSubjectName == NULL ||
  1942. lpNdsObject == NULL ||
  1943. lpNdsObject->Signature != NDS_SIGNATURE )
  1944. {
  1945. SetLastError( ERROR_INVALID_PARAMETER );
  1946. return (DWORD) UNSUCCESSFUL;
  1947. }
  1948. RtlInitUnicodeString( &SubjectName, szSubjectName );
  1949. RtlInitUnicodeString( &AttributeName, szAttributeName );
  1950. ntstatus =
  1951. FragExWithWait(
  1952. lpNdsObject->NdsTree,
  1953. NETWARE_NDS_FUNCTION_GET_EFFECTIVE_RIGHTS,
  1954. NdsReply,
  1955. NDS_BUFFER_SIZE,
  1956. &dwReplyLength,
  1957. "DDSS",
  1958. 0, // Version
  1959. lpNdsObject->ObjectId,
  1960. &SubjectName,
  1961. &AttributeName
  1962. );
  1963. if ( !NT_SUCCESS( ntstatus ) )
  1964. {
  1965. #if DBG
  1966. KdPrint(( "NDS32: NwNdsGetEffectiveRights: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  1967. #endif
  1968. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1969. return (DWORD) UNSUCCESSFUL;
  1970. }
  1971. ntstatus = ParseResponse( NdsReply,
  1972. dwReplyLength,
  1973. "GD",
  1974. &nwstatus );
  1975. if ( !NT_SUCCESS( ntstatus ) )
  1976. {
  1977. #if DBG
  1978. KdPrint(( "NDS32: NwNdsGetEffectiveRights: The status code response was undecipherable.\n" ));
  1979. #endif
  1980. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1981. return (DWORD) UNSUCCESSFUL;
  1982. }
  1983. if ( nwstatus )
  1984. {
  1985. SetLastError( MapNetwareErrorCode( nwstatus ) );
  1986. return nwstatus;
  1987. }
  1988. ntstatus = ParseResponse( NdsReply,
  1989. dwReplyLength,
  1990. "G_D",
  1991. 1 * sizeof(DWORD),
  1992. lpdwRights );
  1993. if ( !NT_SUCCESS( ntstatus ) )
  1994. {
  1995. #if DBG
  1996. KdPrint(( "NDS32: NwNdsGetEffectiveRights: The effective rights response was undecipherable.\n" ));
  1997. #endif
  1998. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  1999. return (DWORD) UNSUCCESSFUL;
  2000. }
  2001. SetLastError( MapNetwareErrorCode( nwstatus ) );
  2002. return nwstatus;
  2003. }
  2004. DWORD
  2005. NwNdsGetObjectListFromBuffer(
  2006. IN HANDLE hOperationData,
  2007. OUT LPDWORD lpdwNumberOfEntries,
  2008. OUT LPDWORD lpdwAttrInformationType OPTIONAL,
  2009. OUT LPNDS_OBJECT_INFO * lppEntries )
  2010. /*
  2011. NwNdsGetObjectListFromBuffer()
  2012. This function is used to retrieve an array of object entries for
  2013. objects that were read with a prior call to either
  2014. NwNdsListSubObjects or NwNdsSearch.
  2015. Arguments:
  2016. HANDLE hOperationData - Buffer containing the read
  2017. response from calling NwNdsListSubObjects, or a
  2018. buffer containing the search results from a call
  2019. to NwNdsSearch.
  2020. LPDWORD lpdwNumberOfEntries - The address of a DWORD to
  2021. receive the number of array elements pointed to by
  2022. lppEntries.
  2023. LPDWORD lpdwAttrInformationType - The address of a DWORD to
  2024. receive a value that indicates the type of attribute
  2025. information returned by the call to NwNdsSearch.
  2026. This attribute information type determines which
  2027. buffer structure (LPNDS_ATTR_INFO or LPNDS_NAME_ONLY)
  2028. should be used for the lpAttribute field found in
  2029. each NDS_OBJECT_INFO structure below.
  2030. - or -
  2031. NULL to indicate that the callee is not interested,
  2032. especially when the object list is that from a call
  2033. to NwNdsListSubObjects.
  2034. LPNDS_OBJECT_INFO *
  2035. lppEntries - The address of a pointer to the beginning
  2036. of an array of NDS_OBJECT_INFO structures. Each
  2037. structure contains the details of each object returned
  2038. from a call to NwNdsListSubObjects or NwNdsSearch.
  2039. Returns:
  2040. NO_ERROR
  2041. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2042. */
  2043. {
  2044. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  2045. *lpdwNumberOfEntries = 0;
  2046. *lppEntries = NULL;
  2047. //
  2048. // Check to see if the data handle is one for listing subordinates or
  2049. // for searching.
  2050. //
  2051. if ( lpNdsBuffer == NULL ||
  2052. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  2053. ( lpNdsBuffer->dwOperation != NDS_OBJECT_LIST_SUBORDINATES &&
  2054. lpNdsBuffer->dwOperation != NDS_SEARCH ) )
  2055. {
  2056. SetLastError( ERROR_INVALID_PARAMETER );
  2057. return (DWORD) UNSUCCESSFUL;
  2058. }
  2059. //
  2060. // Check to see if the call to NwNdsListSubObjects returned any objects.
  2061. //
  2062. if ( lpNdsBuffer->dwOperation == NDS_OBJECT_LIST_SUBORDINATES &&
  2063. lpNdsBuffer->dwNumberOfIndexEntries == 0 )
  2064. {
  2065. SetLastError( ERROR_NO_DATA );
  2066. return (DWORD) UNSUCCESSFUL;
  2067. }
  2068. //
  2069. // Check to see if the call to NwNdsSearch returned any objects.
  2070. //
  2071. if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
  2072. lpNdsBuffer->dwNumberOfReplyEntries == 0 )
  2073. {
  2074. SetLastError( ERROR_NO_DATA );
  2075. return (DWORD) UNSUCCESSFUL;
  2076. }
  2077. //
  2078. // If TRUE, we need to walk raw response to set indexes to data within.
  2079. //
  2080. if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
  2081. lpNdsBuffer->lpIndexBuffer == NULL )
  2082. {
  2083. DWORD status;
  2084. status = IndexSearchObjectReplyBuffer( lpNdsBuffer );
  2085. if ( status )
  2086. {
  2087. SetLastError( status );
  2088. return (DWORD) UNSUCCESSFUL;
  2089. }
  2090. }
  2091. ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
  2092. lpNdsBuffer->dwCurrentIndexEntry = 0;
  2093. *lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
  2094. *lppEntries = (LPNDS_OBJECT_INFO) lpNdsBuffer->lpIndexBuffer;
  2095. if ( lpdwAttrInformationType )
  2096. {
  2097. *lpdwAttrInformationType = lpNdsBuffer->dwReplyInformationType;
  2098. }
  2099. return NO_ERROR;
  2100. }
  2101. DWORD
  2102. NwNdsGetSyntaxID(
  2103. IN HANDLE hTree,
  2104. IN LPWSTR szlpAttributeName,
  2105. OUT LPDWORD lpdwSyntaxID )
  2106. /*
  2107. NwNdsGetObjListFromBuffer()
  2108. This function is used to retrieve the Syntax ID of a given attribute name.
  2109. Arguments:
  2110. HANDLE hTree - A handle to the directory tree to be
  2111. manipulated. Handle is obtained by calling
  2112. NwNdsOpenObject.
  2113. LPWSTR szlpAttributeName - The attribute name whose Syntax ID
  2114. is requested.
  2115. LPDWORD lpdwSyntaxID - The address of a DWORD to receive the
  2116. SyntaxID.
  2117. Returns:
  2118. NO_ERROR
  2119. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2120. */
  2121. {
  2122. DWORD nwstatus;
  2123. DWORD status = NO_ERROR;
  2124. NTSTATUS ntstatus = STATUS_SUCCESS;
  2125. DWORD dwReplyLength;
  2126. BYTE NdsReply[NDS_BUFFER_SIZE];
  2127. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  2128. UNICODE_STRING AttributeName;
  2129. DWORD dwNumEntries;
  2130. DWORD dwStringLen;
  2131. LPBYTE lpByte;
  2132. DWORD LengthInBytes;
  2133. LPBYTE lpTempEntry = NULL;
  2134. if ( lpNdsObject == NULL ||
  2135. szlpAttributeName == NULL ||
  2136. lpNdsObject->Signature != NDS_SIGNATURE )
  2137. {
  2138. SetLastError( ERROR_INVALID_PARAMETER );
  2139. return (DWORD) UNSUCCESSFUL;
  2140. }
  2141. RtlInitUnicodeString( &AttributeName, szlpAttributeName );
  2142. // allocate enough extra space for the padding PrepareReadEntry will do
  2143. lpTempEntry = LocalAlloc( LPTR, AttributeName.Length + (2*sizeof(DWORD)) );
  2144. if ( ! lpTempEntry )
  2145. {
  2146. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  2147. return (DWORD) UNSUCCESSFUL;
  2148. }
  2149. PrepareReadEntry( lpTempEntry,
  2150. AttributeName,
  2151. &LengthInBytes );
  2152. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  2153. NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
  2154. NdsReply,
  2155. NDS_BUFFER_SIZE,
  2156. &dwReplyLength,
  2157. "DDDDDr",
  2158. 0, // Version
  2159. NDS_NO_MORE_ITERATIONS, // Initial iteration
  2160. NDS_INFO_NAMES_DEFS,
  2161. (DWORD) FALSE, // All attributes indicator
  2162. 1, // Number of attributes
  2163. lpTempEntry,
  2164. LengthInBytes);
  2165. (void) LocalFree((HLOCAL) lpTempEntry );
  2166. if ( !NT_SUCCESS( ntstatus ) )
  2167. {
  2168. #if DBG
  2169. KdPrint(( "NDS32: NwNdsGetSyntaxID: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  2170. #endif
  2171. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2172. return (DWORD) UNSUCCESSFUL;
  2173. }
  2174. ntstatus = ParseResponse( NdsReply,
  2175. dwReplyLength,
  2176. "GD",
  2177. &nwstatus );
  2178. if ( !NT_SUCCESS( ntstatus ) )
  2179. {
  2180. #if DBG
  2181. KdPrint(( "NDS32: NwNdsGetSyntaxID: The get syntax id response was undecipherable.\n" ));
  2182. #endif
  2183. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2184. return (DWORD) UNSUCCESSFUL;
  2185. }
  2186. if ( nwstatus )
  2187. {
  2188. #if DBG
  2189. KdPrint(( "NDS32: NwNdsGetSyntaxID: NetWare error 0x%.8X reading %ws.\n", nwstatus, szlpAttributeName ));
  2190. #endif
  2191. SetLastError( MapNetwareErrorCode( nwstatus ) );
  2192. return nwstatus;
  2193. }
  2194. ntstatus = ParseResponse( NdsReply,
  2195. dwReplyLength,
  2196. "G_D",
  2197. 3 * sizeof(DWORD),
  2198. &dwNumEntries );
  2199. if ( !NT_SUCCESS( ntstatus ) )
  2200. {
  2201. #if DBG
  2202. KdPrint(( "NDS32: NwNdsGetSyntaxID: The attribute read response was undecipherable.\n" ));
  2203. #endif
  2204. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2205. return (DWORD) UNSUCCESSFUL;
  2206. }
  2207. ASSERT( dwNumEntries == 1 );
  2208. //
  2209. // Set lpByte to the point in the reply buffer that has the attribute
  2210. // name length.
  2211. //
  2212. lpByte = NdsReply + ( 4 * sizeof(DWORD) );
  2213. //
  2214. // Get the attribute name length and move lpByte to beginning of
  2215. // attribute name
  2216. //
  2217. dwStringLen = * (LPDWORD) lpByte;
  2218. lpByte += sizeof(DWORD);
  2219. //
  2220. // Move lpByte past the attribute name so that it points to the
  2221. // attribute flags value
  2222. //
  2223. lpByte += ROUND_UP_COUNT( dwStringLen,
  2224. ALIGN_DWORD);
  2225. //
  2226. // Move lpByte past the attribute flags value so that it now points to
  2227. // the attribute syntax id value
  2228. //
  2229. lpByte += sizeof(DWORD);
  2230. *lpdwSyntaxID = * (LPDWORD) lpByte;
  2231. return NO_ERROR;
  2232. }
  2233. DWORD
  2234. NwNdsListSubObjects(
  2235. IN HANDLE hParentObject,
  2236. IN DWORD dwEntriesRequested,
  2237. OUT LPDWORD lpdwEntriesReturned,
  2238. IN LPNDS_FILTER_LIST lpFilters OPTIONAL,
  2239. OUT HANDLE * lphOperationData )
  2240. /*
  2241. NwNdsListSubObjects()
  2242. This function is used to enumerate the subordinate objects for a particular
  2243. parent object. A filter can be passed in to restrict enumeration to a
  2244. a specific class type or list of class types.
  2245. Arguments:
  2246. HANDLE hParentObject - A handle to the object in the directory
  2247. tree whose subordinate objects (if any) will be
  2248. enumerated.
  2249. DWORD dwEntriesRequested - The number of subordinate objects
  2250. to list. A subsequent call to NwNdsListSubObjects will
  2251. continue enumeration following the last item returned.
  2252. LPDWORD lpdwEntriesReturned - A pointer to a DWORD that will
  2253. contain the actual number of subobjects enumerated in
  2254. the call.
  2255. LPNDS_FILTER_LIST lpFilters - The caller can specify the object class
  2256. names for the kinds of objects that they would like
  2257. to enumerate. For example if just User and Group
  2258. object classes should be enumerated, then a filter
  2259. for class names NDS_CLASS_USER and NDS_CLASS_GROUP
  2260. should be pass in.
  2261. - or -
  2262. NULL to indicate that all objects should be returned
  2263. (no filter).
  2264. HANDLE * lphOperationData - Address of a HANDLE handle to
  2265. receive created buffer that contains the list of
  2266. subordinate objects read from the object
  2267. hParentObject. This handle is manipulated by the
  2268. following functions:
  2269. NwNdsGetObjListFromBuffer and NwNdsFreeBuffer.
  2270. Returns:
  2271. NO_ERROR
  2272. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2273. */
  2274. {
  2275. DWORD status = NO_ERROR;
  2276. LPNDS_BUFFER lpNdsBuffer = NULL;
  2277. LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
  2278. LPBYTE FixedPortion = NULL;
  2279. LPWSTR EndOfVariableData = NULL;
  2280. BOOL FitInBuffer = TRUE;
  2281. //
  2282. // Test the parameters.
  2283. //
  2284. if ( lpNdsParentObject == NULL ||
  2285. lpNdsParentObject->Signature != NDS_SIGNATURE )
  2286. {
  2287. SetLastError( ERROR_INVALID_PARAMETER );
  2288. return (DWORD) UNSUCCESSFUL;
  2289. }
  2290. if ( lpNdsParentObject->ResumeId == NDS_NO_MORE_ITERATIONS )
  2291. {
  2292. if ( lpNdsParentObject->NdsRawDataBuffer )
  2293. {
  2294. (void) LocalFree( (HLOCAL) lpNdsParentObject->NdsRawDataBuffer );
  2295. lpNdsParentObject->NdsRawDataBuffer = 0;
  2296. lpNdsParentObject->NdsRawDataSize = 0;
  2297. lpNdsParentObject->NdsRawDataId = INITIAL_ITERATION;
  2298. lpNdsParentObject->NdsRawDataCount = 0;
  2299. }
  2300. //
  2301. // Reached the end of enumeration.
  2302. //
  2303. return WN_NO_MORE_ENTRIES;
  2304. }
  2305. //
  2306. // Allocate a results buffer
  2307. //
  2308. status = NwNdsCreateBuffer( NDS_OBJECT_LIST_SUBORDINATES,
  2309. (HANDLE *) &lpNdsBuffer );
  2310. if ( status )
  2311. {
  2312. return status;
  2313. }
  2314. FixedPortion = lpNdsBuffer->lpIndexBuffer;
  2315. EndOfVariableData = (LPWSTR) ((DWORD_PTR) FixedPortion +
  2316. ROUND_DOWN_COUNT(
  2317. lpNdsBuffer->dwIndexAvailableBytes,
  2318. ALIGN_DWORD ) );
  2319. *lpdwEntriesReturned = 0;
  2320. *lphOperationData = NULL;
  2321. while ( FitInBuffer &&
  2322. dwEntriesRequested > *lpdwEntriesReturned &&
  2323. status == NO_ERROR )
  2324. {
  2325. if ( lpNdsParentObject->ResumeId == 0 )
  2326. {
  2327. //
  2328. // Get the first subtree entry.
  2329. //
  2330. status = GetFirstNdsSubTreeEntry( lpNdsParentObject,
  2331. lpNdsBuffer->dwRequestAvailableBytes );
  2332. }
  2333. //
  2334. // Either ResumeId contains the first entry we just got from
  2335. // GetFirstNdsSubTreeEntry or it contains the next directory
  2336. // entry to return.
  2337. //
  2338. if (status == NO_ERROR && lpNdsParentObject->ResumeId != 0)
  2339. {
  2340. WORD tempStrLen;
  2341. LPWSTR newPathStr = NULL;
  2342. LPWSTR tempStr = NULL;
  2343. LPWSTR ClassName;
  2344. LPWSTR ObjectName;
  2345. DWORD ClassNameLen;
  2346. DWORD ObjectNameLen;
  2347. DWORD EntryId;
  2348. DWORD SubordinateCount;
  2349. DWORD ModificationTime;
  2350. BOOL fWriteThisObject = FALSE;
  2351. //
  2352. // Get current subtree data from lpNdsParentObject
  2353. //
  2354. GetSubTreeData( lpNdsParentObject->ResumeId,
  2355. &EntryId,
  2356. &SubordinateCount,
  2357. &ModificationTime,
  2358. &ClassNameLen,
  2359. &ClassName,
  2360. &ObjectNameLen,
  2361. &ObjectName );
  2362. if ( lpFilters )
  2363. {
  2364. DWORD iter;
  2365. for ( iter = 0; iter < lpFilters->dwNumberOfFilters; iter++ )
  2366. {
  2367. if (!wcscmp(lpFilters->Filters[iter].szObjectClass, ClassName))
  2368. fWriteThisObject = TRUE;
  2369. }
  2370. }
  2371. else
  2372. {
  2373. fWriteThisObject = TRUE;
  2374. }
  2375. if ( fWriteThisObject )
  2376. {
  2377. //
  2378. // Need to build a string with the new NDS UNC path
  2379. // for subtree object
  2380. //
  2381. newPathStr = (PVOID) LocalAlloc( LPTR,
  2382. ( wcslen(ObjectName) +
  2383. wcslen(lpNdsParentObject->szContainerName) +
  2384. 3 ) * sizeof(WCHAR) );
  2385. if ( newPathStr == NULL )
  2386. {
  2387. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  2388. #if DBG
  2389. KdPrint(("NDS32: NwNdsListSubObjects LocalAlloc Failed 0x%.8X\n", GetLastError()));
  2390. #endif
  2391. return ERROR_NOT_ENOUGH_MEMORY;
  2392. }
  2393. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  2394. lpNdsParentObject->szContainerName,
  2395. PARSE_NDS_GET_TREE_NAME );
  2396. tempStrLen /= sizeof(WCHAR);
  2397. if ( tempStrLen > 0 )
  2398. {
  2399. wcscpy( newPathStr, L"\\\\" );
  2400. wcsncat( newPathStr, tempStr, tempStrLen );
  2401. wcscat( newPathStr, L"\\" );
  2402. wcscat( newPathStr, ObjectName );
  2403. _wcsupr( newPathStr );
  2404. }
  2405. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  2406. lpNdsParentObject->szContainerName,
  2407. PARSE_NDS_GET_PATH_NAME );
  2408. tempStrLen /= sizeof(WCHAR);
  2409. if ( tempStrLen > 0 )
  2410. {
  2411. wcscat( newPathStr, L"." );
  2412. wcsncat( newPathStr, tempStr, tempStrLen );
  2413. }
  2414. //
  2415. // Pack subtree name into output buffer.
  2416. //
  2417. status = WriteObjectToBuffer( &FixedPortion,
  2418. &EndOfVariableData,
  2419. newPathStr,
  2420. ObjectName,
  2421. ClassName,
  2422. EntryId,
  2423. ModificationTime,
  2424. SubordinateCount,
  2425. 0, // No attribute
  2426. NULL ); // infos here
  2427. if ( status == NO_ERROR )
  2428. {
  2429. //
  2430. // Note that we've returned the current entry.
  2431. //
  2432. (*lpdwEntriesReturned)++;
  2433. (lpNdsBuffer->dwNumberOfIndexEntries)++;
  2434. }
  2435. if ( newPathStr )
  2436. (void) LocalFree( (HLOCAL) newPathStr );
  2437. }
  2438. if (status == WN_MORE_DATA)
  2439. {
  2440. //
  2441. // Could not write current entry into output buffer.
  2442. //
  2443. if (*lpdwEntriesReturned)
  2444. {
  2445. //
  2446. // Still return success because we got at least one.
  2447. //
  2448. status = NO_ERROR;
  2449. }
  2450. FitInBuffer = FALSE;
  2451. }
  2452. else if (status == NO_ERROR)
  2453. {
  2454. //
  2455. // Get next directory entry.
  2456. //
  2457. status = GetNextNdsSubTreeEntry( lpNdsParentObject );
  2458. }
  2459. } // end of if data to process
  2460. if (status == WN_NO_MORE_ENTRIES)
  2461. {
  2462. lpNdsParentObject->ResumeId = NDS_NO_MORE_ITERATIONS;
  2463. }
  2464. } //end of while loop
  2465. //
  2466. // User asked for more than there are entries. We just say that
  2467. // all is well.
  2468. //
  2469. // This is incompliance with the wierd provider API definition where
  2470. // if user gets NO_ERROR, and EntriesRequested > *EntriesRead, and
  2471. // at least one entry fit into output buffer, there's no telling if
  2472. // the buffer was too small for more entries or there are no more
  2473. // entries. The user has to call this API again and get WN_NO_MORE_ENTRIES
  2474. // before knowing that the last call had actually reached the end of list.
  2475. //
  2476. if ( *lpdwEntriesReturned && status == WN_NO_MORE_ENTRIES )
  2477. {
  2478. status = NO_ERROR;
  2479. }
  2480. if ( *lpdwEntriesReturned )
  2481. {
  2482. *lphOperationData = lpNdsBuffer;
  2483. }
  2484. if ( *lpdwEntriesReturned == 0 )
  2485. {
  2486. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  2487. lpNdsBuffer = NULL;
  2488. }
  2489. if ( lpNdsParentObject->NdsRawDataBuffer &&
  2490. lpNdsParentObject->ResumeId == NDS_NO_MORE_ITERATIONS )
  2491. {
  2492. (void) LocalFree( (HLOCAL) lpNdsParentObject->NdsRawDataBuffer );
  2493. lpNdsParentObject->NdsRawDataBuffer = 0;
  2494. lpNdsParentObject->NdsRawDataSize = 0;
  2495. lpNdsParentObject->NdsRawDataId = INITIAL_ITERATION;
  2496. lpNdsParentObject->NdsRawDataCount = 0;
  2497. }
  2498. return status;
  2499. }
  2500. DWORD
  2501. NwNdsModifyObject(
  2502. IN HANDLE hObject,
  2503. IN HANDLE hOperationData )
  2504. /*
  2505. NwNdsModifyObject()
  2506. This function is used to modify a leaf object in an NDS directory tree.
  2507. Modifying a leaf object means: changing, adding, removing, and clearing of
  2508. specified attributes for a given object.
  2509. Arguments:
  2510. HANDLE hObject - A handle to the object in the directory
  2511. tree to be manipulated. Handle is obtained by calling
  2512. NwNdsOpenObject.
  2513. HANDLE hOperationData - A handle to data containing a
  2514. list of attribute changes to be applied to the object.
  2515. This buffer is manipulated by the following functions:
  2516. NwNdsCreateBuffer (NDS_OBJECT_MODIFY),
  2517. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  2518. Returns:
  2519. NO_ERROR
  2520. ERROR_INVALID_PARAMETER
  2521. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2522. */
  2523. {
  2524. DWORD nwstatus;
  2525. NTSTATUS ntstatus = STATUS_SUCCESS;
  2526. DWORD dwReplyLength;
  2527. BYTE NdsReply[NDS_BUFFER_SIZE];
  2528. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  2529. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  2530. if ( lpNdsBuffer == NULL ||
  2531. lpNdsObject == NULL ||
  2532. lpNdsBuffer->dwOperation != NDS_OBJECT_MODIFY ||
  2533. lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  2534. lpNdsObject->Signature != NDS_SIGNATURE )
  2535. {
  2536. SetLastError( ERROR_INVALID_PARAMETER );
  2537. return (DWORD) UNSUCCESSFUL;
  2538. }
  2539. ntstatus =
  2540. FragExWithWait(
  2541. lpNdsObject->NdsTree,
  2542. NETWARE_NDS_FUNCTION_MODIFY_OBJECT,
  2543. NdsReply,
  2544. NDS_BUFFER_SIZE,
  2545. &dwReplyLength,
  2546. "DDDDr",
  2547. 0, // Version
  2548. 0, // Flags
  2549. lpNdsObject->ObjectId, // The id of the object
  2550. lpNdsBuffer->dwNumberOfRequestEntries,
  2551. lpNdsBuffer->lpRequestBuffer, // Object attribute changes
  2552. (WORD)lpNdsBuffer->dwLengthOfRequestData // Length of data
  2553. );
  2554. if ( !NT_SUCCESS( ntstatus ) )
  2555. {
  2556. #if DBG
  2557. KdPrint(( "NDS32: NwNdsModifyObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  2558. #endif
  2559. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2560. return (DWORD) UNSUCCESSFUL;
  2561. }
  2562. ntstatus = ParseResponse( NdsReply,
  2563. dwReplyLength,
  2564. "GD",
  2565. &nwstatus );
  2566. if ( !NT_SUCCESS( ntstatus ) )
  2567. {
  2568. #if DBG
  2569. KdPrint(( "NDS32: NwNdsModifyObject: The modify object response was undecipherable.\n" ));
  2570. #endif
  2571. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2572. return (DWORD) UNSUCCESSFUL;
  2573. }
  2574. SetLastError( MapNetwareErrorCode( nwstatus ) );
  2575. return nwstatus;
  2576. }
  2577. DWORD
  2578. NwNdsMoveObject(
  2579. IN HANDLE hObject,
  2580. IN LPWSTR szDestObjectParentDN )
  2581. /*
  2582. NwNdsMoveObject()
  2583. This function is used to move a leaf object in an NDS directory tree
  2584. from one container to another.
  2585. Arguments:
  2586. HANDLE hObject - A handle to the object in the directory
  2587. tree to be moved. Handle is obtained by calling
  2588. NwNdsOpenObject.
  2589. LPWSTR szDestObjectParentDN - The DN of the object's new
  2590. parent.
  2591. Returns:
  2592. NO_ERROR
  2593. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2594. */
  2595. {
  2596. DWORD nwstatus;
  2597. DWORD status = NO_ERROR;
  2598. NTSTATUS ntstatus = STATUS_SUCCESS;
  2599. DWORD dwReplyLength;
  2600. BYTE NdsReply[NDS_BUFFER_SIZE];
  2601. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  2602. LPNDS_OBJECT_PRIV lpNdsDestParentObject = NULL;
  2603. WCHAR szServerDN[NDS_MAX_NAME_CHARS];
  2604. UNICODE_STRING ObjectName;
  2605. UNICODE_STRING ServerDN;
  2606. DWORD dwDestParentObjectId;
  2607. if ( szDestObjectParentDN == NULL ||
  2608. lpNdsObject == NULL ||
  2609. lpNdsObject->Signature != NDS_SIGNATURE )
  2610. {
  2611. SetLastError( ERROR_INVALID_PARAMETER );
  2612. return (DWORD) UNSUCCESSFUL;
  2613. }
  2614. RtlZeroMemory( &szServerDN, sizeof( szServerDN ) );
  2615. status = NwNdsGetServerDN( lpNdsObject, szServerDN );
  2616. if ( status )
  2617. {
  2618. return status;
  2619. }
  2620. status = NwNdsOpenObject( szDestObjectParentDN,
  2621. NULL,
  2622. NULL,
  2623. (HANDLE *) &lpNdsDestParentObject,
  2624. NULL,
  2625. NULL,
  2626. NULL,
  2627. NULL,
  2628. NULL );
  2629. if ( status )
  2630. {
  2631. return status;
  2632. }
  2633. dwDestParentObjectId = lpNdsDestParentObject->ObjectId;
  2634. (void) NwNdsCloseObject( (HANDLE) lpNdsDestParentObject );
  2635. RtlInitUnicodeString( &ObjectName, lpNdsObject->szRelativeName );
  2636. RtlInitUnicodeString( &ServerDN, szServerDN );
  2637. ntstatus =
  2638. FragExWithWait( lpNdsObject->NdsTree,
  2639. NETWARE_NDS_FUNCTION_BEGIN_MOVE_OBJECT,
  2640. NdsReply,
  2641. NDS_BUFFER_SIZE,
  2642. &dwReplyLength,
  2643. "DDDSS",
  2644. 0, // Version
  2645. 0x00000000, // Some value
  2646. dwDestParentObjectId,
  2647. &ObjectName,
  2648. &ServerDN
  2649. );
  2650. if ( !NT_SUCCESS( ntstatus ) )
  2651. {
  2652. #if DBG
  2653. KdPrint(( "NDS32: NwNdsMoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  2654. #endif
  2655. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2656. return (DWORD) UNSUCCESSFUL;
  2657. }
  2658. ntstatus = ParseResponse( NdsReply,
  2659. dwReplyLength,
  2660. "GD",
  2661. &nwstatus );
  2662. if ( !NT_SUCCESS( ntstatus ) )
  2663. {
  2664. #if DBG
  2665. KdPrint(( "NDS32: NwNdsMoveObject: The status code response was undecipherable.\n" ));
  2666. #endif
  2667. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2668. return (DWORD) UNSUCCESSFUL;
  2669. }
  2670. if ( nwstatus )
  2671. {
  2672. SetLastError( MapNetwareErrorCode( nwstatus ) );
  2673. return nwstatus;
  2674. }
  2675. ntstatus =
  2676. FragExWithWait( lpNdsObject->NdsTree,
  2677. NETWARE_NDS_FUNCTION_FINISH_MOVE_OBJECT,
  2678. NdsReply,
  2679. NDS_BUFFER_SIZE,
  2680. &dwReplyLength,
  2681. "DDDDSS",
  2682. 0, // Version
  2683. 0x00000001, // Some value
  2684. lpNdsObject->ObjectId,
  2685. dwDestParentObjectId,
  2686. &ObjectName,
  2687. &ServerDN
  2688. );
  2689. if ( !NT_SUCCESS( ntstatus ) )
  2690. {
  2691. #if DBG
  2692. KdPrint(( "NDS32: NwNdsMoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  2693. #endif
  2694. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2695. return (DWORD) UNSUCCESSFUL;
  2696. }
  2697. ntstatus = ParseResponse( NdsReply,
  2698. dwReplyLength,
  2699. "GD",
  2700. &nwstatus );
  2701. if ( !NT_SUCCESS( ntstatus ) )
  2702. {
  2703. #if DBG
  2704. KdPrint(( "NDS32: NwNdsMoveObject: The status code response was undecipherable.\n" ));
  2705. #endif
  2706. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2707. return (DWORD) UNSUCCESSFUL;
  2708. }
  2709. if ( nwstatus )
  2710. {
  2711. SetLastError( MapNetwareErrorCode( nwstatus ) );
  2712. return nwstatus;
  2713. }
  2714. return nwstatus;
  2715. }
  2716. DWORD
  2717. NwNdsOpenObject(
  2718. IN LPWSTR szObjectDN,
  2719. IN LPWSTR UserName OPTIONAL,
  2720. IN LPWSTR Password OPTIONAL,
  2721. OUT HANDLE * lphObject,
  2722. OUT LPWSTR szObjectName OPTIONAL,
  2723. OUT LPWSTR szObjectFullName OPTIONAL,
  2724. OUT LPWSTR szObjectClassName OPTIONAL,
  2725. OUT LPDWORD lpdwModificationTime OPTIONAL,
  2726. OUT LPDWORD lpdwSubordinateCount OPTIONAL )
  2727. /*
  2728. NwNdsOpenObject()
  2729. Arguments:
  2730. LPWSTR szObjectDN - The distinguished name of the object
  2731. that we want resolved into an object handle.
  2732. LPWSTR UserName - The name of the user account to create
  2733. connection to object with.
  2734. - OR -
  2735. NULL to use the base credentials of the callee's LUID.
  2736. LPWSTR Password - The password of the user account to create
  2737. connection to object with. If password is blank, callee
  2738. should pass "".
  2739. - OR -
  2740. NULL to use the base credentials of the callee's LUID.
  2741. HANDLE * lphObject - The address of a NDS_OBJECT_HANDLE
  2742. to receive the handle of the object specified by
  2743. szObjectDN.
  2744. Optional arguments: ( Callee can pass NULL in for these parameters to
  2745. indicate ignore )
  2746. LPWSTR szObjectName - A LPWSTR buffer to receive
  2747. the object's NDS name, or NULL if not
  2748. interested. The buffer for this string must be
  2749. provided by the user. Buffer should be at least
  2750. NDS_MAX_NAME_SIZE
  2751. LPWSTR szObjectFullName - A LPWSTR buffer to receive
  2752. the object's full NDS name (DN), or NULL if not
  2753. interested. The buffer for this string must be
  2754. provided by the user. Buffer should be at least
  2755. NDS_MAX_NAME_SIZE
  2756. LPWSTR szObjectClassName - A LPWSTR buffer to receive
  2757. the class name of the object opened, or NULL if not
  2758. interested. The buffer for this string must be
  2759. provided by the user. Buffer should be at least
  2760. NDS_MAX_NAME_SIZE.
  2761. LPDWORD lpdwModificationTime - The address of a DWORD to
  2762. receive the last date/time the object was modified.
  2763. LPDWORD lpdwSubordinateCount - The address of a DWORD to
  2764. receive the number of subordinate objects that may
  2765. be found under szObjectDN, if it is a container object.
  2766. Or, NULL in not interested.
  2767. If szObjectDN is not a container, then the value is set
  2768. to zero. Although a value of zero does not imply
  2769. that object is not a container, it could just be empty.
  2770. Returns:
  2771. NO_ERROR
  2772. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  2773. */
  2774. {
  2775. DWORD status = NO_ERROR;
  2776. NTSTATUS ntstatus = STATUS_SUCCESS;
  2777. WCHAR szServerName[NW_MAX_SERVER_LEN];
  2778. UNICODE_STRING ServerName;
  2779. UNICODE_STRING ObjectName;
  2780. LPNDS_OBJECT_PRIV lpNdsObject = NULL;
  2781. #ifdef WIN95
  2782. LPWSTR pszObjectName = NULL;
  2783. LPWSTR szWin95ClassName = NULL;
  2784. #endif
  2785. if ( szObjectDN == NULL )
  2786. {
  2787. SetLastError( ERROR_INVALID_PARAMETER );
  2788. return (DWORD) UNSUCCESSFUL;
  2789. }
  2790. lpNdsObject = (LPNDS_OBJECT_PRIV) LocalAlloc( LPTR,
  2791. sizeof(NDS_OBJECT_PRIV) );
  2792. if (lpNdsObject == NULL) {
  2793. #if DBG
  2794. KdPrint(("NDS32: NwNdsOpenObject LocalAlloc Failed 0x%.8X\n", GetLastError()));
  2795. #endif
  2796. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  2797. return (DWORD) UNSUCCESSFUL;
  2798. }
  2799. ServerName.Length = 0;
  2800. ServerName.MaximumLength = sizeof(szServerName);
  2801. ServerName.Buffer = szServerName;
  2802. ObjectName.Buffer = NULL;
  2803. ObjectName.MaximumLength = (wcslen( szObjectDN ) + 1) * sizeof(WCHAR);
  2804. ObjectName.Length = ParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
  2805. szObjectDN,
  2806. PARSE_NDS_GET_TREE_NAME );
  2807. if ( ObjectName.Length == 0 || ObjectName.Buffer == NULL )
  2808. {
  2809. SetLastError( ERROR_PATH_NOT_FOUND );
  2810. goto ErrorExit;
  2811. }
  2812. //
  2813. // Open a NDS tree connection handle to \\treename
  2814. //
  2815. if ( UserName && Password )
  2816. {
  2817. UNICODE_STRING usUserName;
  2818. UNICODE_STRING usPassword;
  2819. DWORD dwHandleType;
  2820. RtlInitUnicodeString( &usUserName, UserName );
  2821. RtlInitUnicodeString( &usPassword, Password );
  2822. ntstatus = NwOpenHandleWithSupplementalCredentials(
  2823. &ObjectName,
  2824. &usUserName,
  2825. &usPassword,
  2826. &dwHandleType,
  2827. &lpNdsObject->NdsTree );
  2828. if ( ntstatus == STATUS_SUCCESS &&
  2829. dwHandleType != HANDLE_TYPE_NDS_TREE )
  2830. {
  2831. SetLastError( ERROR_PATH_NOT_FOUND );
  2832. goto ErrorExit;
  2833. }
  2834. }
  2835. else if ( !UserName && !Password )
  2836. {
  2837. ntstatus = NwNdsOpenTreeHandle( &ObjectName, &lpNdsObject->NdsTree );
  2838. }
  2839. else
  2840. {
  2841. SetLastError( ERROR_INVALID_PARAMETER );
  2842. goto ErrorExit;
  2843. }
  2844. if ( ntstatus != STATUS_SUCCESS )
  2845. {
  2846. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2847. goto ErrorExit;
  2848. }
  2849. ObjectName.Length /= sizeof(WCHAR);
  2850. wcscpy( lpNdsObject->szContainerName, L"\\\\" );
  2851. wcsncat( lpNdsObject->szContainerName, ObjectName.Buffer, ObjectName.Length );
  2852. wcscat( lpNdsObject->szContainerName, L"\\" );
  2853. _wcsupr( lpNdsObject->szContainerName );
  2854. //
  2855. // Get the path to the container to open.
  2856. //
  2857. ObjectName.Length = ParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
  2858. szObjectDN,
  2859. PARSE_NDS_GET_PATH_NAME );
  2860. if ( ObjectName.Length == 0 )
  2861. {
  2862. UNICODE_STRING Root;
  2863. RtlInitUnicodeString(&Root, L"[Root]");
  2864. //
  2865. // Resolve the path to get a NDS object id of [Root].
  2866. //
  2867. #ifndef WIN95
  2868. ntstatus = NwNdsResolveName( lpNdsObject->NdsTree,
  2869. &Root,
  2870. &lpNdsObject->ObjectId,
  2871. &ServerName,
  2872. NULL,
  2873. 0 );
  2874. #else
  2875. ntstatus = NwNdsResolveNameWin95( lpNdsObject->NdsTree,
  2876. &Root,
  2877. &lpNdsObject->ObjectId,
  2878. &lpNdsObject->NdsTree,
  2879. NULL,
  2880. 0 );
  2881. #endif
  2882. if ( ntstatus != STATUS_SUCCESS )
  2883. {
  2884. DWORD status;
  2885. status = RtlNtStatusToDosError( ntstatus );
  2886. if ( status == ERROR_NOT_CONNECTED )
  2887. SetLastError( ERROR_PATH_NOT_FOUND );
  2888. else
  2889. SetLastError( status );
  2890. goto ErrorExit;
  2891. }
  2892. }
  2893. else
  2894. {
  2895. //
  2896. // Resolve the path to get a NDS object id.
  2897. //
  2898. #ifndef WIN95
  2899. ntstatus = NwNdsResolveName( lpNdsObject->NdsTree,
  2900. &ObjectName,
  2901. &lpNdsObject->ObjectId,
  2902. &ServerName,
  2903. NULL,
  2904. 0 );
  2905. #else
  2906. ntstatus = NwNdsResolveNameWin95( lpNdsObject->NdsTree,
  2907. &ObjectName,
  2908. &lpNdsObject->ObjectId,
  2909. &lpNdsObject->NdsTree,
  2910. NULL,
  2911. 0 );
  2912. #endif
  2913. if ( ntstatus != STATUS_SUCCESS )
  2914. {
  2915. DWORD status;
  2916. status = RtlNtStatusToDosError( ntstatus );
  2917. if ( status == ERROR_NOT_CONNECTED )
  2918. SetLastError( ERROR_PATH_NOT_FOUND );
  2919. else
  2920. SetLastError( status );
  2921. goto ErrorExit;
  2922. }
  2923. }
  2924. #ifndef WIN95
  2925. if ( ServerName.Length )
  2926. {
  2927. DWORD dwHandleType;
  2928. //
  2929. // NwNdsResolveName succeeded, but we were referred to
  2930. // another server, though lpNdsObject->ObjectId is still valid.
  2931. //
  2932. if ( lpNdsObject->NdsTree )
  2933. CloseHandle( lpNdsObject->NdsTree );
  2934. lpNdsObject->NdsTree = 0;
  2935. //
  2936. // Open a NDS generic connection handle to \\ServerName
  2937. //
  2938. ntstatus = NwNdsOpenGenericHandle( &ServerName,
  2939. &dwHandleType,
  2940. &lpNdsObject->NdsTree );
  2941. if ( ntstatus != STATUS_SUCCESS )
  2942. {
  2943. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2944. goto ErrorExit;
  2945. }
  2946. }
  2947. {
  2948. PBYTE RawResponse = NULL;
  2949. PNDS_RESPONSE_GET_OBJECT_INFO psGetInfo;
  2950. PBYTE pbRawGetInfo;
  2951. LPWSTR szClassName;
  2952. DWORD dwStrLen;
  2953. RawResponse = LocalAlloc( LPTR, TWO_KB );
  2954. if ( ! RawResponse )
  2955. {
  2956. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2957. goto ErrorExit;
  2958. }
  2959. ntstatus = NwNdsReadObjectInfo( lpNdsObject->NdsTree,
  2960. lpNdsObject->ObjectId,
  2961. RawResponse,
  2962. TWO_KB );
  2963. if ( ntstatus != STATUS_SUCCESS )
  2964. {
  2965. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  2966. goto ErrorExit;
  2967. }
  2968. psGetInfo = ( PNDS_RESPONSE_GET_OBJECT_INFO ) RawResponse;
  2969. if ( lpdwModificationTime != NULL )
  2970. {
  2971. *lpdwModificationTime = psGetInfo->ModificationTime;
  2972. }
  2973. if ( lpdwSubordinateCount != NULL )
  2974. {
  2975. *lpdwSubordinateCount = psGetInfo->SubordinateCount;
  2976. }
  2977. //
  2978. // Dig out the two unicode strings for class name and object name.
  2979. //
  2980. pbRawGetInfo = RawResponse;
  2981. pbRawGetInfo += sizeof (NDS_RESPONSE_GET_OBJECT_INFO);
  2982. dwStrLen = * (LPDWORD) pbRawGetInfo;
  2983. pbRawGetInfo += sizeof(DWORD);
  2984. szClassName = (LPWSTR) pbRawGetInfo;
  2985. if ( szObjectClassName != NULL )
  2986. {
  2987. wcscpy( szObjectClassName, szClassName );
  2988. }
  2989. pbRawGetInfo += ROUNDUP4( dwStrLen );
  2990. dwStrLen = * ( DWORD * ) pbRawGetInfo;
  2991. pbRawGetInfo += sizeof(DWORD);
  2992. //
  2993. // Clean up the object's relative name ...
  2994. //
  2995. if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
  2996. {
  2997. LPWSTR szTempStr = (LPWSTR) pbRawGetInfo;
  2998. while ( *szTempStr != L'=' )
  2999. {
  3000. szTempStr++;
  3001. }
  3002. szTempStr++;
  3003. wcscpy( lpNdsObject->szRelativeName, szTempStr );
  3004. szTempStr = lpNdsObject->szRelativeName;
  3005. while ( *szTempStr && *szTempStr != L'.' )
  3006. {
  3007. szTempStr++;
  3008. }
  3009. *szTempStr = L'\0';
  3010. }
  3011. else
  3012. {
  3013. wcscpy( lpNdsObject->szRelativeName, (LPWSTR) pbRawGetInfo );
  3014. }
  3015. if ( szObjectName != NULL )
  3016. {
  3017. wcscpy( szObjectName, lpNdsObject->szRelativeName );
  3018. }
  3019. if ( szObjectFullName != NULL )
  3020. {
  3021. if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
  3022. {
  3023. wcscpy( szObjectFullName, lpNdsObject->szContainerName );
  3024. wcscat( szObjectFullName, (LPWSTR) pbRawGetInfo );
  3025. }
  3026. else
  3027. {
  3028. wcscpy( szObjectFullName,
  3029. lpNdsObject->szContainerName );
  3030. szObjectFullName[wcslen( szObjectFullName ) - 1] = L'\0';
  3031. }
  3032. }
  3033. //
  3034. // If the object is at a level below the root of the tree, append
  3035. // it's full DN to handle Name.
  3036. //
  3037. if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
  3038. {
  3039. wcscat(lpNdsObject->szContainerName, (LPWSTR) pbRawGetInfo);
  3040. }
  3041. if ( RawResponse )
  3042. LocalFree( RawResponse );
  3043. }
  3044. lpNdsObject->Signature = NDS_SIGNATURE;
  3045. //
  3046. // Initialize ListSubObject/Search structure values.
  3047. //
  3048. // lpNdsObject->ResumeId = 0; // Start of enumeration
  3049. //
  3050. // lpNdsObject->NdsRawDataBuffer = 0;
  3051. // lpNdsObject->NdsRawDataSize = 0;
  3052. // lpNdsObject->NdsRawDataId = 0; // These are initialized by
  3053. // lpNdsObject->NdsRawDataCount = 0; // LPTR
  3054. //
  3055. // Return the newly created object handle.
  3056. //
  3057. *lphObject = (HANDLE) lpNdsObject;
  3058. return NO_ERROR;
  3059. #else
  3060. {
  3061. DS_OBJ_INFO dsobj;
  3062. DWORD dwStrLen;
  3063. NW_STATUS nwstatus;
  3064. memset(&dsobj, 0, sizeof(DS_OBJ_INFO));
  3065. nwstatus = NDSGetObjectInfoWithId(lpNdsObject->NdsTree,
  3066. lpNdsObject->ObjectId,
  3067. &dsobj );
  3068. ntstatus = MapNwToNtStatus(nwstatus);
  3069. if ( ntstatus != STATUS_SUCCESS )
  3070. {
  3071. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  3072. goto ErrorExit;
  3073. }
  3074. if ( lpdwSubordinateCount != NULL )
  3075. {
  3076. *lpdwSubordinateCount = dsobj.subordinateCount;
  3077. }
  3078. if (!(szWin95ClassName = AllocateUnicodeString(dsobj.className))) {
  3079. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3080. goto ErrorExit;
  3081. }
  3082. if ( szObjectClassName != NULL )
  3083. {
  3084. wcscpy( szObjectClassName, szWin95ClassName);
  3085. }
  3086. if (!(pszObjectName = AllocateUnicodeString(dsobj.objectName))) {
  3087. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3088. goto ErrorExit;
  3089. }
  3090. //
  3091. // Clean up the object's relative name ...
  3092. //
  3093. if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
  3094. {
  3095. LPWSTR szTempStr = pszObjectName;
  3096. while ( *szTempStr != L'=' )
  3097. {
  3098. szTempStr++;
  3099. }
  3100. szTempStr++;
  3101. wcscpy( lpNdsObject->szRelativeName, szTempStr );
  3102. szTempStr = lpNdsObject->szRelativeName;
  3103. while ( *szTempStr && *szTempStr != L'.' )
  3104. {
  3105. szTempStr++;
  3106. }
  3107. *szTempStr = L'\0';
  3108. }
  3109. else
  3110. {
  3111. wcscpy( lpNdsObject->szRelativeName, pszObjectName );
  3112. }
  3113. if ( szObjectName != NULL )
  3114. {
  3115. wcscpy( szObjectName, lpNdsObject->szRelativeName );
  3116. }
  3117. if ( szObjectFullName != NULL )
  3118. {
  3119. if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
  3120. {
  3121. wcscpy( szObjectFullName, lpNdsObject->szContainerName );
  3122. wcscat( szObjectFullName, pszObjectName );
  3123. }
  3124. else
  3125. {
  3126. wcscpy( szObjectFullName,
  3127. lpNdsObject->szContainerName );
  3128. szObjectFullName[wcslen( szObjectFullName ) - 1] = L'\0';
  3129. }
  3130. }
  3131. //
  3132. // If the object is at a level below the root of the tree, append
  3133. // it full DN to handle Name.
  3134. //
  3135. if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
  3136. {
  3137. wcscat(lpNdsObject->szContainerName, pszObjectName);
  3138. }
  3139. if(szWin95ClassName){
  3140. FreeUnicodeString(szWin95ClassName);
  3141. }
  3142. if(pszObjectName){
  3143. FreeUnicodeString(pszObjectName);
  3144. }
  3145. }
  3146. lpNdsObject->Signature = NDS_SIGNATURE;
  3147. *lphObject = (HANDLE) lpNdsObject;
  3148. return NO_ERROR;
  3149. #endif
  3150. ErrorExit:
  3151. if ( lpNdsObject )
  3152. {
  3153. #ifndef WIN95
  3154. // There is no ref count in Win95, the connection will time out itself
  3155. if ( lpNdsObject->NdsTree )
  3156. CloseHandle( lpNdsObject->NdsTree );
  3157. #endif
  3158. (void) LocalFree( (HLOCAL) lpNdsObject );
  3159. }
  3160. #ifdef WIN95
  3161. if(szWin95ClassName)
  3162. {
  3163. FreeUnicodeString(szWin95ClassName);
  3164. }
  3165. if(pszObjectName)
  3166. {
  3167. FreeUnicodeString(pszObjectName);
  3168. }
  3169. #endif
  3170. *lphObject = NULL;
  3171. return (DWORD) UNSUCCESSFUL;
  3172. }
  3173. DWORD
  3174. NwNdsPutInBuffer(
  3175. IN LPWSTR szAttributeName,
  3176. IN DWORD dwSyntaxID,
  3177. IN LPVOID lpAttributeValues,
  3178. IN DWORD dwValueCount,
  3179. IN DWORD dwAttrModificationOperation,
  3180. IN OUT HANDLE hOperationData )
  3181. /*
  3182. NwNdsPutInBuffer()
  3183. This function is used to add an entry to the buffer used to describe
  3184. an object attribute or change to an object attribute. The buffer must
  3185. be created using NwNdsCreateBuffer. If the buffer was created using the
  3186. operations, NDS_OBJECT_ADD, NDS_SCHEMA_DEFINE_CLASS,
  3187. NDS_SCHEMA_READ_ATTR_DEF, or NDS_SCHEMA_READ_CLASS_DEF, then
  3188. dwAttrModificationOperation is ignored. If the buffer was created using
  3189. either the operation NDS_OBJECT_READ or NDS_SEARCH, then
  3190. dwAttrModificationOperation, puAttributeType, and lpAttributeValue are
  3191. all ingnored.
  3192. Arguments:
  3193. LPWSTR szAttributeName - A NULL terminated WCHAR string
  3194. that contains name of the attribute value to be
  3195. added to the buffer. It can be a user supplied
  3196. string, or one of the many defined string macros
  3197. in ndsnames.h.
  3198. DWORD dwSyntaxID - The ID of the syntax structure used to
  3199. represent the attribute value. Syntax IDs and their
  3200. associated structures are defined in the file
  3201. NdsSntx.h. According to the NetWare NDS schema spec,
  3202. there is and always will be, only 28 (0..27)
  3203. different syntaxes.
  3204. LPVOID lpAttributeValues - A pointer to the beginning of a
  3205. buffer containing the value(s) for a particular
  3206. object attribute with data syntax dwSyntaxID.
  3207. DWORD dwValueCount - The number of value entries found in
  3208. buffer pointed to by lpAttributeValues.
  3209. DWORD dwAttrModificationOperation - If the buffer was created
  3210. using the operation NDS_MODIFY_OBJECT, then this is
  3211. used to desribe which type of modification operation
  3212. to apply for a given attribute. These attribute
  3213. modification operations are defined near the beginning
  3214. of this file.
  3215. HANDLE hOperationData - A handle to data created by
  3216. calling NwNdsCreateBuffer. The buffer stores the
  3217. attributes used to define transactions for
  3218. NwNdsAddObject, NwNdsModifyObject, NwNdsReadObject,
  3219. NwNdsReadAttrDef, NwNdsReadClassDef, or NwNdsSearch.
  3220. Returns:
  3221. NO_ERROR
  3222. ERROR_NOT_ENOUGH_MEMORY
  3223. ERROR_INVALID_PARAMETER
  3224. */
  3225. {
  3226. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
  3227. DWORD LengthInBytes;
  3228. LPBYTE lpTempEntry = NULL;
  3229. UNICODE_STRING AttributeName;
  3230. DWORD bufferSize = TWO_KB;
  3231. if ( lpNdsBuffer == NULL ||
  3232. szAttributeName == NULL ||
  3233. lpNdsBuffer->dwBufferId != NDS_SIGNATURE )
  3234. {
  3235. SetLastError( ERROR_INVALID_PARAMETER );
  3236. return (DWORD) UNSUCCESSFUL;
  3237. }
  3238. RtlInitUnicodeString( &AttributeName, szAttributeName );
  3239. //
  3240. // Check to see if the buffer was already used by a read operation.
  3241. //
  3242. if ( lpNdsBuffer->lpReplyBuffer )
  3243. {
  3244. SetLastError( ERROR_ACCESS_DENIED );
  3245. return NDS_ERR_NO_ACCESS;
  3246. }
  3247. if ( lpNdsBuffer->dwOperation == NDS_OBJECT_MODIFY )
  3248. {
  3249. switch( dwAttrModificationOperation )
  3250. {
  3251. case NDS_ATTR_ADD:
  3252. case NDS_ATTR_REMOVE:
  3253. case NDS_ATTR_ADD_VALUE:
  3254. case NDS_ATTR_REMOVE_VALUE:
  3255. case NDS_ATTR_ADDITIONAL_VALUE:
  3256. case NDS_ATTR_OVERWRITE_VALUE:
  3257. case NDS_ATTR_CLEAR:
  3258. case NDS_ATTR_CLEAR_VALUE:
  3259. break;
  3260. default:
  3261. #if DBG
  3262. KdPrint(( "NDS32: NwNdsPutInBuffer was passed an unidentified modification operation.\n" ));
  3263. #endif
  3264. SetLastError( ERROR_INVALID_PARAMETER );
  3265. return (DWORD) UNSUCCESSFUL;
  3266. }
  3267. }
  3268. if ( lpNdsBuffer->dwOperation == NDS_OBJECT_ADD ||
  3269. lpNdsBuffer->dwOperation == NDS_OBJECT_MODIFY )
  3270. {
  3271. bufferSize += CalculateValueDataSize ( dwSyntaxID,
  3272. lpAttributeValues,
  3273. dwValueCount );
  3274. }
  3275. lpTempEntry = LocalAlloc( LPTR, bufferSize );
  3276. if ( ! lpTempEntry )
  3277. {
  3278. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  3279. return (DWORD) UNSUCCESSFUL;
  3280. }
  3281. switch ( lpNdsBuffer->dwOperation )
  3282. {
  3283. case NDS_OBJECT_ADD:
  3284. PrepareAddEntry( lpTempEntry,
  3285. AttributeName,
  3286. dwSyntaxID,
  3287. lpAttributeValues,
  3288. dwValueCount,
  3289. &LengthInBytes );
  3290. break;
  3291. case NDS_OBJECT_MODIFY:
  3292. PrepareModifyEntry( lpTempEntry,
  3293. AttributeName,
  3294. dwSyntaxID,
  3295. dwAttrModificationOperation,
  3296. lpAttributeValues,
  3297. dwValueCount,
  3298. &LengthInBytes );
  3299. break;
  3300. case NDS_OBJECT_READ:
  3301. case NDS_SCHEMA_DEFINE_CLASS:
  3302. case NDS_SCHEMA_READ_ATTR_DEF:
  3303. case NDS_SCHEMA_READ_CLASS_DEF:
  3304. case NDS_SEARCH:
  3305. //
  3306. // Check to see if this buffer has already been used. If so,
  3307. // return with error.
  3308. //
  3309. if ( lpNdsBuffer->lpReplyBuffer )
  3310. {
  3311. if ( lpTempEntry )
  3312. LocalFree( lpTempEntry );
  3313. SetLastError( ERROR_INVALID_PARAMETER );
  3314. return (DWORD) UNSUCCESSFUL;
  3315. }
  3316. PrepareReadEntry( lpTempEntry,
  3317. AttributeName,
  3318. &LengthInBytes );
  3319. break;
  3320. default:
  3321. #if DBG
  3322. KdPrint(( "NDS32: NwNdsPutInBuffer has unknown buffer operation!\n" ));
  3323. #endif
  3324. if ( lpTempEntry )
  3325. LocalFree( lpTempEntry );
  3326. SetLastError( ERROR_INVALID_PARAMETER );
  3327. return (DWORD) UNSUCCESSFUL;
  3328. }
  3329. if ( lpNdsBuffer->dwRequestAvailableBytes >= LengthInBytes )
  3330. {
  3331. //
  3332. // Copy temporary buffer entry into buffer and update buffer header.
  3333. //
  3334. RtlCopyMemory( (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData],
  3335. lpTempEntry,
  3336. LengthInBytes );
  3337. lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
  3338. lpNdsBuffer->dwNumberOfRequestEntries += 1;
  3339. lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
  3340. }
  3341. else
  3342. {
  3343. LPBYTE lpNewBuffer = NULL;
  3344. //
  3345. // Need to reallocate buffer to a bigger size.
  3346. //
  3347. lpNewBuffer = (LPBYTE) LocalAlloc(
  3348. LPTR,
  3349. lpNdsBuffer->dwRequestBufferSize +
  3350. LengthInBytes +
  3351. TWO_KB );
  3352. if ( lpNewBuffer == NULL )
  3353. {
  3354. #if DBG
  3355. KdPrint(( "NDS32: NwNdsPutInBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  3356. #endif
  3357. if ( lpTempEntry )
  3358. LocalFree( lpTempEntry );
  3359. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  3360. return (DWORD) UNSUCCESSFUL;
  3361. }
  3362. RtlCopyMemory( lpNewBuffer,
  3363. lpNdsBuffer->lpRequestBuffer,
  3364. lpNdsBuffer->dwLengthOfRequestData );
  3365. LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
  3366. lpNdsBuffer->lpRequestBuffer = lpNewBuffer;
  3367. lpNdsBuffer->dwRequestBufferSize += LengthInBytes + TWO_KB;
  3368. lpNdsBuffer->dwRequestAvailableBytes += LengthInBytes + TWO_KB;
  3369. //
  3370. // Copy temporary buffer entry into the resized buffer and
  3371. // update buffer header.
  3372. //
  3373. RtlCopyMemory( (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData],
  3374. lpTempEntry,
  3375. LengthInBytes );
  3376. lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
  3377. lpNdsBuffer->dwNumberOfRequestEntries += 1;
  3378. lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
  3379. }
  3380. if ( lpTempEntry )
  3381. LocalFree( lpTempEntry );
  3382. return NO_ERROR;
  3383. }
  3384. DWORD
  3385. NwNdsReadAttrDef(
  3386. IN HANDLE hTree,
  3387. IN DWORD dwInformationType, // NDS_INFO_NAMES
  3388. // or NDS_INFO_NAMES_DEFS
  3389. IN OUT HANDLE * lphOperationData OPTIONAL )
  3390. /*
  3391. NwNdsReadAttrDef()
  3392. This function is used to read attribute definitions in the schema of an
  3393. NDS directory tree.
  3394. Arguments:
  3395. HANDLE hTree - A handle to the directory tree to be
  3396. manipulated. Handle is obtained by calling
  3397. NwNdsOpenObject.
  3398. DWORD dwInformationType - Indicates whether user chooses to
  3399. read only the defined attribute name(s) in the schema or
  3400. read both the attribute name(s) and definition(s)
  3401. from the schema.
  3402. HANDLE * lphOperationData - The address of a HANDLE to data
  3403. containing a list of attribute names to be read from
  3404. the schema. This handle is manipulated by the following
  3405. functions:
  3406. NwNdsCreateBuffer (NDS_SCHEMA_READ_ATTR_DEF),
  3407. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  3408. - OR -
  3409. The address of a HANDLE set to NULL, which indicates
  3410. that all attributes should be read from the schema.
  3411. If these calls are successful, this handle will also
  3412. contain the read results from the call. In the later
  3413. case, a buffer will be created to contain the read
  3414. results. Attribute values can be retrieved from the
  3415. buffer with the functions:
  3416. NwNdsGetAttrDefListFromBuffer.
  3417. After the call to this function, this buffer is ONLY
  3418. manipulated by the functions:
  3419. NwNdsGetAttrDefListFromBuffer and NwNdsFreeBuffer.
  3420. Returns:
  3421. NO_ERROR
  3422. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3423. */
  3424. {
  3425. if ( hTree == NULL ||
  3426. ((LPNDS_OBJECT_PRIV) hTree)->Signature != NDS_SIGNATURE )
  3427. {
  3428. SetLastError( ERROR_INVALID_PARAMETER );
  3429. return (DWORD) UNSUCCESSFUL;
  3430. }
  3431. if ( *lphOperationData == NULL ) // If TRUE, we need to read all attr defs
  3432. return ReadAttrDef_AllAttrs( hTree,
  3433. dwInformationType,
  3434. lphOperationData );
  3435. else // Else, we read the attr definitions specified in lphOperationData
  3436. return ReadAttrDef_SomeAttrs( hTree,
  3437. dwInformationType,
  3438. lphOperationData );
  3439. }
  3440. DWORD
  3441. NwNdsReadClassDef(
  3442. IN HANDLE hTree,
  3443. IN DWORD dwInformationType, // NDS_INFO_NAMES,
  3444. // NDS_INFO_NAMES_DEFS,
  3445. // NDS_CLASS_INFO_EXPANDED_DEFS,
  3446. // or NDS_CLASS_INFO
  3447. IN OUT HANDLE * lphOperationData OPTIONAL )
  3448. /*
  3449. NwNdsReadClassDef()
  3450. This function is used to read class definitions in the schema of an
  3451. NDS directory tree.
  3452. Arguments:
  3453. HANDLE hTree - A handle to the directory tree to be
  3454. manipulated. Handle is obtained by calling
  3455. NwNdsOpenObject.
  3456. DWORD dwInformationType - Indicates whether user chooses to
  3457. read only the defined class name(s) in the schema or
  3458. read both the class name(s) and definition(s)
  3459. from the schema.
  3460. HANDLE * lphOperationData - The address of a HANDLE to data
  3461. containing a list of class names to be read from
  3462. the schema. This handle is manipulated by the following
  3463. functions:
  3464. NwNdsCreateBuffer (NDS_SCHEMA_READ_CLASS_DEF),
  3465. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  3466. - OR -
  3467. The address of a HANDLE set to NULL, which indicates
  3468. that all classes should be read from the schema.
  3469. If these calls are successful, this handle will also
  3470. contain the read results from the call. In the later
  3471. case, a buffer will be created to contain the read
  3472. results. Class read results can be retrieved from the
  3473. buffer with the functions:
  3474. NwNdsGetClassDefListFromBuffer.
  3475. After the call to this function, this buffer is ONLY
  3476. manipulated by the functions:
  3477. NwNdsGetClassDefListFromBuffer and NwNdsFreeBuffer.
  3478. Returns:
  3479. NO_ERROR
  3480. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3481. */
  3482. {
  3483. if ( hTree == NULL ||
  3484. ((LPNDS_OBJECT_PRIV) hTree)->Signature != NDS_SIGNATURE )
  3485. {
  3486. SetLastError( ERROR_INVALID_PARAMETER );
  3487. return (DWORD) UNSUCCESSFUL;
  3488. }
  3489. if ( *lphOperationData == NULL ) // If TRUE, we need to read all class defs
  3490. return ReadClassDef_AllClasses( hTree,
  3491. dwInformationType,
  3492. lphOperationData );
  3493. else // Else, we read the class definitions specified in lphOperationData
  3494. return ReadClassDef_SomeClasses( hTree,
  3495. dwInformationType,
  3496. lphOperationData );
  3497. }
  3498. DWORD
  3499. NwNdsReadObject(
  3500. IN HANDLE hObject,
  3501. IN DWORD dwInformationType, // NDS_INFO_NAMES
  3502. // or NDS_INFO_ATTR_NAMES_VALUES
  3503. IN OUT HANDLE * lphOperationData OPTIONAL )
  3504. /*
  3505. NwNdsReadObject()
  3506. This function is used to read attributes about an object of an NDS
  3507. directory tree.
  3508. Arguments:
  3509. HANDLE hObject - A handle to the object in the directory
  3510. tree to be manipulated. Handle is obtained by calling
  3511. NwNdsOpenObject.
  3512. DWORD dwInformationType - Indicates whether user chooses to
  3513. read only the attribute name(s) on the object or
  3514. read both the attribute name(s) and value(s)
  3515. from the object.
  3516. HANDLE * lphOperationData - The address of a HANDLE to data
  3517. containing a list of attributes to be read from the
  3518. object hObject. This handle is manipulated by the
  3519. following functions:
  3520. NwNdsCreateBuffer (NDS_OBJECT_READ),
  3521. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  3522. - OR -
  3523. The address of a HANDLE set to NULL, which indicates
  3524. that all object attributes should be read from object
  3525. hObject.
  3526. If these calls are successful, this pointer will also
  3527. contain the read results from the call. In the later
  3528. case, a buffer will be created to contain the read
  3529. results. Attribute values can be retrieved from the
  3530. buffer with the functions:
  3531. NwNdsGetAttrListFromBuffer
  3532. After the call to this function, this buffer is ONLY
  3533. manipulated by the functions:
  3534. NwNdsGetAttrListFromBuffer and NwNdsFreeBuffer.
  3535. Returns:
  3536. NO_ERROR
  3537. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3538. */
  3539. {
  3540. if ( hObject == NULL ||
  3541. ((LPNDS_OBJECT_PRIV) hObject)->Signature != NDS_SIGNATURE )
  3542. {
  3543. SetLastError( ERROR_INVALID_PARAMETER );
  3544. return (DWORD) UNSUCCESSFUL;
  3545. }
  3546. if ( *lphOperationData == NULL ) // If TRUE, we need to read all attributes
  3547. return ReadObject_AllAttrs( hObject,
  3548. dwInformationType,
  3549. lphOperationData );
  3550. else // Else, we read the attributes specified in lphOperationData
  3551. return ReadObject_SomeAttrs( hObject,
  3552. dwInformationType,
  3553. lphOperationData );
  3554. }
  3555. DWORD
  3556. NwNdsRemoveObject(
  3557. IN HANDLE hParentObject,
  3558. IN LPWSTR szObjectName )
  3559. /*
  3560. NwNdsRemoveObject()
  3561. This function is used to remove a leaf object from an NDS directory tree.
  3562. Arguments:
  3563. HANDLE hParentObject - A handle to the parent object container
  3564. in the directory tree to remove leaf object from.
  3565. Handle is obtained by calling NwNdsOpenObject.
  3566. LPWSTR szObjectName - The directory name of the leaf object
  3567. to be removed.
  3568. Returns:
  3569. NO_ERROR
  3570. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3571. */
  3572. {
  3573. DWORD nwstatus;
  3574. DWORD status = NO_ERROR;
  3575. NTSTATUS ntstatus = STATUS_SUCCESS;
  3576. DWORD dwReplyLength;
  3577. BYTE NdsReply[TWO_KB]; // A 2K buffer is plenty for a response
  3578. LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
  3579. LPNDS_OBJECT_PRIV lpNdsObject = NULL;
  3580. LPWSTR szFullObjectDN = NULL;
  3581. LPWSTR szTempStr = NULL;
  3582. DWORD length;
  3583. UNICODE_STRING ObjectName;
  3584. if ( szObjectName == NULL ||
  3585. lpNdsParentObject == NULL ||
  3586. lpNdsParentObject->Signature != NDS_SIGNATURE )
  3587. {
  3588. SetLastError( ERROR_INVALID_PARAMETER );
  3589. return (DWORD) UNSUCCESSFUL;
  3590. }
  3591. RtlInitUnicodeString( &ObjectName, szObjectName );
  3592. //
  3593. // Create a buffer to hold the full object distinguished name.
  3594. // \\tree\<--Object Name-->.<existing container path, if any>
  3595. //
  3596. szFullObjectDN = (LPWSTR) LocalAlloc(
  3597. LPTR,
  3598. ( wcslen( lpNdsParentObject->szContainerName ) *
  3599. sizeof(WCHAR) ) + // Container name
  3600. ObjectName.Length + // Object name
  3601. ( 2 * sizeof(WCHAR) ) ); // Extras
  3602. //
  3603. // Check that the memory allocation was successful.
  3604. //
  3605. if ( szFullObjectDN == NULL )
  3606. {
  3607. #if DBG
  3608. KdPrint(( "NDS32: NwNdsRemoveObject LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  3609. #endif
  3610. return ERROR_NOT_ENOUGH_MEMORY;
  3611. }
  3612. length = ParseNdsUncPath( &szTempStr,
  3613. lpNdsParentObject->szContainerName,
  3614. PARSE_NDS_GET_TREE_NAME );
  3615. length /= sizeof(WCHAR);
  3616. wcscpy( szFullObjectDN, L"\\\\" ); // <\\>
  3617. wcsncat( szFullObjectDN, szTempStr, length ); // <\\tree>
  3618. wcscat( szFullObjectDN, L"\\" ); // <\\tree\>
  3619. wcsncat( szFullObjectDN, ObjectName.Buffer,
  3620. ObjectName.Length ); // <\\tree\obj>
  3621. length = ParseNdsUncPath( &szTempStr,
  3622. lpNdsParentObject->szContainerName,
  3623. PARSE_NDS_GET_PATH_NAME );
  3624. if ( length > 0 )
  3625. {
  3626. length /= sizeof(WCHAR);
  3627. wcscat( szFullObjectDN, L"." ); // <\\tree\obj.>
  3628. wcsncat( szFullObjectDN, szTempStr, length );// <\\tree\obj.org_unt.org>
  3629. }
  3630. status = NwNdsOpenObject( szFullObjectDN,
  3631. NULL,
  3632. NULL,
  3633. (HANDLE *) &lpNdsObject,
  3634. NULL,
  3635. NULL,
  3636. NULL,
  3637. NULL,
  3638. NULL );
  3639. if ( status != NO_ERROR )
  3640. {
  3641. // NwNdsOpenObject will have already set the last error . . .
  3642. goto ErrorExit;
  3643. }
  3644. (void) LocalFree( szFullObjectDN );
  3645. szFullObjectDN = NULL;
  3646. ntstatus =
  3647. FragExWithWait(
  3648. lpNdsParentObject->NdsTree,
  3649. NETWARE_NDS_FUNCTION_REMOVE_OBJECT,
  3650. NdsReply, // Response buffer.
  3651. sizeof(NdsReply), // Size of response buffer.
  3652. &dwReplyLength, // Length of response returned.
  3653. "DD", // Going to send 2 DWORDs, they are ...
  3654. 0, // Version
  3655. lpNdsObject->ObjectId // The id of the object
  3656. );
  3657. if ( !NT_SUCCESS( ntstatus ) )
  3658. {
  3659. #if DBG
  3660. KdPrint(( "NDS32: NwNdsRemoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  3661. #endif
  3662. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  3663. goto ErrorExit;
  3664. }
  3665. (void) NwNdsCloseObject( (HANDLE) lpNdsObject );
  3666. lpNdsObject = NULL;
  3667. ntstatus = ParseResponse( NdsReply,
  3668. dwReplyLength,
  3669. "GD",
  3670. &nwstatus );
  3671. if ( !NT_SUCCESS( ntstatus ) )
  3672. {
  3673. #if DBG
  3674. KdPrint(( "NDS32: NwNdsRemoveObject: The remove object response was undecipherable.\n" ));
  3675. #endif
  3676. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  3677. goto ErrorExit;
  3678. }
  3679. SetLastError( MapNetwareErrorCode( nwstatus ) );
  3680. return nwstatus;
  3681. ErrorExit :
  3682. if ( szFullObjectDN )
  3683. {
  3684. (void) LocalFree( szFullObjectDN );
  3685. }
  3686. if ( lpNdsObject )
  3687. {
  3688. (void) NwNdsCloseObject( (HANDLE) lpNdsObject );
  3689. }
  3690. return (DWORD) UNSUCCESSFUL;
  3691. }
  3692. DWORD
  3693. NwNdsRenameObject(
  3694. IN HANDLE hParentObject,
  3695. IN LPWSTR szObjectName,
  3696. IN LPWSTR szNewObjectName,
  3697. IN BOOL fDeleteOldName )
  3698. /*
  3699. NwNdsRenameObject()
  3700. This function is used to rename an object in a NDS directory tree.
  3701. Arguments:
  3702. HANDLE hParentObject - A handle to the parent object container
  3703. in the directory tree to rename leaf object in.
  3704. Handle is obtained by calling NwNdsOpenObject.
  3705. LPWSTR szObjectName - The directory name of the object to be
  3706. renamed.
  3707. LPWSTR szNewObjectName - The new directory name of the object.
  3708. BOOL fDeleteOldName - If true, the old name is discarded;
  3709. Otherwise, the old name is retained as an additional
  3710. attribute.
  3711. Returns:
  3712. NO_ERROR
  3713. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3714. */
  3715. {
  3716. DWORD nwstatus;
  3717. DWORD status = NO_ERROR;
  3718. NTSTATUS ntstatus = STATUS_SUCCESS;
  3719. DWORD dwReplyLength;
  3720. BYTE NdsReply[TWO_KB]; // A 2K buffer is plenty for a response
  3721. LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
  3722. LPNDS_OBJECT_PRIV lpNdsObject = NULL;
  3723. LPWSTR szFullObjectDN = NULL;
  3724. LPWSTR szTempStr = NULL;
  3725. DWORD length;
  3726. UNICODE_STRING ObjectName;
  3727. UNICODE_STRING NewObjectName;
  3728. if ( szObjectName == NULL ||
  3729. szNewObjectName == NULL ||
  3730. lpNdsParentObject == NULL ||
  3731. lpNdsParentObject->Signature != NDS_SIGNATURE )
  3732. {
  3733. SetLastError( ERROR_INVALID_PARAMETER );
  3734. return (DWORD) UNSUCCESSFUL;
  3735. }
  3736. RtlInitUnicodeString( &ObjectName, szObjectName );
  3737. RtlInitUnicodeString( &NewObjectName, szNewObjectName );
  3738. //
  3739. // Create a buffer to hold the full object distinguished name.
  3740. // \\tree\<--Object Name-->.<existing container path, if any>
  3741. //
  3742. szFullObjectDN = (LPWSTR) LocalAlloc(
  3743. LPTR,
  3744. ( wcslen( lpNdsParentObject->szContainerName ) *
  3745. sizeof(WCHAR) ) + // Container name
  3746. ObjectName.Length + // Object name
  3747. ( 2 * sizeof(WCHAR) ) ); // Extras
  3748. //
  3749. // Check that the memory allocation was successful.
  3750. //
  3751. if ( szFullObjectDN == NULL )
  3752. {
  3753. #if DBG
  3754. KdPrint(( "NDS32: NwNdsRenameObject LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  3755. #endif
  3756. return ERROR_NOT_ENOUGH_MEMORY;
  3757. }
  3758. length = ParseNdsUncPath( &szTempStr,
  3759. lpNdsParentObject->szContainerName,
  3760. PARSE_NDS_GET_TREE_NAME );
  3761. length /= sizeof(WCHAR);
  3762. wcscpy( szFullObjectDN, L"\\\\" ); // <\\>
  3763. wcsncat( szFullObjectDN, szTempStr, length ); // <\\tree>
  3764. wcscat( szFullObjectDN, L"\\" ); // <\\tree\>
  3765. wcsncat( szFullObjectDN, ObjectName.Buffer,
  3766. ObjectName.Length ); // <\\tree\obj>
  3767. length = ParseNdsUncPath( &szTempStr,
  3768. lpNdsParentObject->szContainerName,
  3769. PARSE_NDS_GET_PATH_NAME );
  3770. if ( length > 0 )
  3771. {
  3772. length /= sizeof(WCHAR);
  3773. wcscat( szFullObjectDN, L"." ); // <\\tree\obj.>
  3774. wcsncat( szFullObjectDN, szTempStr, length );// <\\tree\obj.org_unt.org>
  3775. }
  3776. status = NwNdsOpenObject( szFullObjectDN,
  3777. NULL,
  3778. NULL,
  3779. (HANDLE *) &lpNdsObject,
  3780. NULL,
  3781. NULL,
  3782. NULL,
  3783. NULL,
  3784. NULL );
  3785. if ( status != NO_ERROR )
  3786. {
  3787. // NwNdsOpenObject will have already set the last error . . .
  3788. goto ErrorExit;
  3789. }
  3790. (void) LocalFree( szFullObjectDN );
  3791. szFullObjectDN = NULL;
  3792. ntstatus =
  3793. FragExWithWait(
  3794. lpNdsParentObject->NdsTree,
  3795. NETWARE_NDS_FUNCTION_MODIFY_RDN,
  3796. NdsReply, // Response buffer.
  3797. sizeof(NdsReply), // Size of response buffer.
  3798. &dwReplyLength, // Length of response returned.
  3799. "DDDS",
  3800. 0x00000000, // Version
  3801. lpNdsObject->ObjectId,
  3802. fDeleteOldName ? 0x00021701 : 0x00021700,
  3803. &NewObjectName
  3804. );
  3805. if ( !NT_SUCCESS( ntstatus ) )
  3806. {
  3807. #if DBG
  3808. KdPrint(( "NDS32: NwNdsRenameObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  3809. #endif
  3810. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  3811. goto ErrorExit;
  3812. }
  3813. (void) NwNdsCloseObject( (HANDLE) lpNdsObject );
  3814. lpNdsObject = NULL;
  3815. ntstatus = ParseResponse( NdsReply,
  3816. dwReplyLength,
  3817. "GD",
  3818. &nwstatus );
  3819. if ( !NT_SUCCESS( ntstatus ) )
  3820. {
  3821. #if DBG
  3822. KdPrint(( "NDS32: NwNdsRenameObject: The rename object response was undecipherable.\n" ));
  3823. #endif
  3824. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  3825. goto ErrorExit;
  3826. }
  3827. SetLastError( MapNetwareErrorCode( nwstatus ) );
  3828. return nwstatus;
  3829. ErrorExit :
  3830. if ( szFullObjectDN )
  3831. {
  3832. (void) LocalFree( szFullObjectDN );
  3833. }
  3834. if ( lpNdsObject )
  3835. {
  3836. (void) NwNdsCloseObject( (HANDLE) lpNdsObject );
  3837. }
  3838. return (DWORD) UNSUCCESSFUL;
  3839. }
  3840. DWORD
  3841. NwNdsSearch(
  3842. IN HANDLE hStartFromObject,
  3843. IN DWORD dwInformationType, // NDS_INFO_NAMES
  3844. // or NDS_INFO_ATTR_NAMES_VALUES
  3845. IN DWORD dwScope,
  3846. IN BOOL fDerefAliases,
  3847. IN LPQUERY_TREE lpQueryTree,
  3848. IN OUT LPDWORD lpdwIterHandle,
  3849. IN OUT HANDLE * lphOperationData )
  3850. /*
  3851. NwNdsSearch()
  3852. This function is used to query an NDS directory tree to find objects of
  3853. a certain object type that match a specified search filter.
  3854. Arguments:
  3855. HANDLE hStartFromObject - A HANDLE to an object in the
  3856. directory tree to start search from. Handle is
  3857. obtained by calling NwNdsOpenObject.
  3858. DWORD dwInformationType - Indicates whether user chooses to
  3859. read only the attribute name(s) on the search result
  3860. objects or read both the attribute name(s) and value(s)
  3861. from the search result objects.
  3862. DWORD dwScope -
  3863. NDS_SCOPE_ONE_LEVEL - Search subordinates from given
  3864. object, one level only
  3865. NDS_SCOPE_SUB_TREE - Search from given object on down
  3866. NDS_SCOPE_BASE_LEVEL - Applies search to an object
  3867. BOOL fDerefAliases - If TRUE the search will dereference
  3868. aliased objects to the real objects and continue
  3869. to search in the aliased objects subtree. If FALSE
  3870. the search will not dereference aliases.
  3871. LPQUERY_TREE lpQueryTree - A pointer to the root of a
  3872. search tree which defines a query. This tree
  3873. is manipulated by the following functions:
  3874. NwNdsCreateQueryNode, NwNdsDeleteQueryNode,
  3875. and NwNdsDeleteQueryTree.
  3876. LPDWORD lpdwIterHandle - A pointer to a DWORD that has the
  3877. iteration handle value. On input, the handle value
  3878. is set to NDS_INITIAL_SEARCH or to a value previously
  3879. returned from a prior call to NwNdsSearch. On ouput,
  3880. the handle value is set to NDS_NO_MORE_ITERATIONS if
  3881. search is complete, or to some other value otherwise.
  3882. HANDLE * lphOperationData - The address of a HANDLE to data
  3883. containing a list of attributes to be read from the
  3884. objects that meet the search query. This handle is
  3885. manipulated by the following functions:
  3886. NwNdsCreateBuffer (NDS_SEARCH),
  3887. NwNdsPutInBuffer, and NwNdsFreeBuffer.
  3888. - OR -
  3889. The address of a HANDLE set to NULL, which indicates
  3890. that all object attributes should be read from the
  3891. search objects found.
  3892. If these calls are successful, this handle will also
  3893. contain the read results from the call. In the later
  3894. case, a buffer will be created to contain the read
  3895. results. Object information with attribute information
  3896. can be retrieved from the buffer with the function:
  3897. NwNdsGetObjectListFromBuffer.
  3898. After the call to this function, this buffer is ONLY
  3899. manipulated by the functions:
  3900. NwNdsGetObjectListFromBuffer,
  3901. and NwNdsFreeBuffer.
  3902. Returns:
  3903. NO_ERROR
  3904. UNSUCCESSFUL - Call GetLastError for Win32 error code.
  3905. */
  3906. {
  3907. DWORD dwNdsScope = NDS_SEARCH_SUBTREE;
  3908. switch ( dwScope )
  3909. {
  3910. case NDS_SCOPE_ONE_LEVEL :
  3911. dwNdsScope = NDS_SEARCH_SUBORDINATES;
  3912. break;
  3913. case NDS_SCOPE_SUB_TREE :
  3914. dwNdsScope = NDS_SEARCH_SUBTREE;
  3915. break;
  3916. case NDS_SCOPE_BASE_LEVEL :
  3917. dwNdsScope = NDS_SEARCH_ENTRY;
  3918. break;
  3919. }
  3920. if ( hStartFromObject == NULL ||
  3921. lpQueryTree == NULL ||
  3922. lpdwIterHandle == NULL ||
  3923. ((LPNDS_OBJECT_PRIV) hStartFromObject)->Signature != NDS_SIGNATURE )
  3924. {
  3925. SetLastError( ERROR_INVALID_PARAMETER );
  3926. return (DWORD) UNSUCCESSFUL;
  3927. }
  3928. if ( *lphOperationData == NULL )
  3929. {
  3930. //
  3931. // The callee is asking for all attributes to be returned from search.
  3932. //
  3933. return Search_AllAttrs( hStartFromObject,
  3934. dwInformationType,
  3935. dwNdsScope,
  3936. fDerefAliases,
  3937. lpQueryTree,
  3938. lpdwIterHandle,
  3939. lphOperationData );
  3940. }
  3941. else if ( ((LPNDS_BUFFER) *lphOperationData)->lpRequestBuffer == NULL )
  3942. {
  3943. //
  3944. // The callee has a handle from a prior call to NwNdsSearch, and is
  3945. // still asking for all attributes to be returned from search.
  3946. //
  3947. return Search_AllAttrs( hStartFromObject,
  3948. dwInformationType,
  3949. dwNdsScope,
  3950. fDerefAliases,
  3951. lpQueryTree,
  3952. lpdwIterHandle,
  3953. lphOperationData );
  3954. }
  3955. else
  3956. {
  3957. //
  3958. // The callee has a handle that they created with calls to
  3959. // NwNdsCreateBuffer and NwNdsPutInBuffer to specify attributes
  3960. // to be returned from search or NwNdsSearch was called once before
  3961. // and we are resuming the search.
  3962. //
  3963. return Search_SomeAttrs( hStartFromObject,
  3964. dwInformationType,
  3965. dwNdsScope,
  3966. fDerefAliases,
  3967. lpQueryTree,
  3968. lpdwIterHandle,
  3969. lphOperationData );
  3970. }
  3971. }
  3972. /* Local Function Implementations */
  3973. VOID
  3974. PrepareAddEntry(
  3975. LPBYTE lpTempEntry,
  3976. UNICODE_STRING AttributeName,
  3977. DWORD dwSyntaxID,
  3978. LPBYTE lpAttributeValues,
  3979. DWORD dwValueCount,
  3980. LPDWORD lpdwLengthInBytes )
  3981. {
  3982. LPBYTE lpTemp = lpTempEntry;
  3983. DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
  3984. DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
  3985. dwStringLen;
  3986. *lpdwLengthInBytes = 0;
  3987. //
  3988. // tommye - MS bug 71653 - added try/except wrapper
  3989. //
  3990. try {
  3991. //
  3992. // Write attribute name length to temp entry buffer.
  3993. //
  3994. * (LPDWORD) lpTemp = dwStringLen;
  3995. *lpdwLengthInBytes += sizeof(DWORD);
  3996. lpTemp += sizeof(DWORD);
  3997. //
  3998. // Write attribute name to temp entry buffer.
  3999. //
  4000. RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
  4001. *lpdwLengthInBytes += AttributeName.Length;
  4002. lpTemp += AttributeName.Length;
  4003. //
  4004. // Add the null character.
  4005. //
  4006. * (LPWSTR) lpTemp = L'\0';
  4007. *lpdwLengthInBytes += sizeof(WCHAR);
  4008. lpTemp += sizeof(WCHAR);
  4009. //
  4010. // Write padding (if needed) to temp entry buffer.
  4011. //
  4012. if ( dwPadLen )
  4013. {
  4014. RtlZeroMemory( lpTemp, dwPadLen );
  4015. lpTemp += dwPadLen;
  4016. *lpdwLengthInBytes += dwPadLen;
  4017. }
  4018. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  4019. return;
  4020. }
  4021. //
  4022. // Now add the value(s) to temp entry.
  4023. //
  4024. AppendValueToEntry( lpTemp,
  4025. dwSyntaxID,
  4026. lpAttributeValues,
  4027. dwValueCount,
  4028. lpdwLengthInBytes );
  4029. }
  4030. VOID
  4031. PrepareModifyEntry(
  4032. LPBYTE lpTempEntry,
  4033. UNICODE_STRING AttributeName,
  4034. DWORD dwSyntaxID,
  4035. DWORD dwAttrModificationOperation,
  4036. LPBYTE lpAttributeValues,
  4037. DWORD dwValueCount,
  4038. LPDWORD lpdwLengthInBytes )
  4039. {
  4040. LPBYTE lpTemp = lpTempEntry;
  4041. DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
  4042. DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
  4043. dwStringLen;
  4044. *lpdwLengthInBytes = 0;
  4045. //
  4046. // tommye - MS bug 71654 - added try/except wrapper
  4047. //
  4048. try {
  4049. //
  4050. // Write attribute modification operation to temp entry buffer.
  4051. //
  4052. * (LPDWORD) lpTemp = dwAttrModificationOperation;
  4053. lpTemp += sizeof(DWORD);
  4054. *lpdwLengthInBytes += sizeof(DWORD);
  4055. //
  4056. // Write attribute name length to temp entry buffer.
  4057. //
  4058. * (LPDWORD) lpTemp = dwStringLen;
  4059. *lpdwLengthInBytes += sizeof(DWORD);
  4060. lpTemp += sizeof(DWORD);
  4061. //
  4062. // Write attribute name to temp entry buffer.
  4063. //
  4064. RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
  4065. *lpdwLengthInBytes += AttributeName.Length;
  4066. lpTemp += AttributeName.Length;
  4067. //
  4068. // Add the null character.
  4069. //
  4070. * (LPWSTR) lpTemp = L'\0';
  4071. *lpdwLengthInBytes += sizeof(WCHAR);
  4072. lpTemp += sizeof(WCHAR);
  4073. //
  4074. // Write padding (if needed) to temp entry buffer.
  4075. //
  4076. if ( dwPadLen )
  4077. {
  4078. RtlZeroMemory( lpTemp, dwPadLen );
  4079. lpTemp += dwPadLen;
  4080. *lpdwLengthInBytes += dwPadLen;
  4081. }
  4082. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  4083. return;
  4084. }
  4085. //
  4086. // Now add the value(s) to temp entry (if needed).
  4087. //
  4088. switch( dwAttrModificationOperation )
  4089. {
  4090. case NDS_ATTR_ADD_VALUE:
  4091. case NDS_ATTR_ADDITIONAL_VALUE:
  4092. case NDS_ATTR_OVERWRITE_VALUE:
  4093. case NDS_ATTR_REMOVE_VALUE:
  4094. case NDS_ATTR_CLEAR_VALUE:
  4095. case NDS_ATTR_ADD:
  4096. AppendValueToEntry( lpTemp,
  4097. dwSyntaxID,
  4098. lpAttributeValues,
  4099. dwValueCount,
  4100. lpdwLengthInBytes );
  4101. break;
  4102. case NDS_ATTR_REMOVE:
  4103. case NDS_ATTR_CLEAR:
  4104. // Don't need to do anything for these modification operations.
  4105. break;
  4106. default :
  4107. #if DBG
  4108. KdPrint(( "NDS32: PrepareModifyEntry warning, unknown modification operation 0x%.8X\n", dwAttrModificationOperation ));
  4109. ASSERT( FALSE );
  4110. #endif
  4111. ; // Nothing, skip it.
  4112. }
  4113. }
  4114. VOID
  4115. PrepareReadEntry(
  4116. LPBYTE lpTempEntry,
  4117. UNICODE_STRING AttributeName,
  4118. LPDWORD lpdwLengthInBytes )
  4119. {
  4120. LPBYTE lpTemp = lpTempEntry;
  4121. DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
  4122. DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
  4123. dwStringLen;
  4124. *lpdwLengthInBytes = 0;
  4125. //
  4126. // tommye - MS bug 71655 - added try/except wrapper
  4127. //
  4128. try {
  4129. //
  4130. // Write attribute name length to temp entry buffer.
  4131. //
  4132. * (LPDWORD) lpTemp = dwStringLen;
  4133. *lpdwLengthInBytes += sizeof(DWORD);
  4134. lpTemp += sizeof(DWORD);
  4135. //
  4136. // Write attribute name to temp entry buffer.
  4137. //
  4138. RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
  4139. *lpdwLengthInBytes += AttributeName.Length;
  4140. lpTemp += AttributeName.Length;
  4141. //
  4142. // Add the null character.
  4143. //
  4144. * (LPWSTR) lpTemp = L'\0';
  4145. *lpdwLengthInBytes += sizeof(WCHAR);
  4146. lpTemp += sizeof(WCHAR);
  4147. //
  4148. // Write padding (if needed) to temp entry buffer.
  4149. //
  4150. if ( dwPadLen )
  4151. {
  4152. RtlZeroMemory( lpTemp, dwPadLen );
  4153. lpTemp += dwPadLen;
  4154. *lpdwLengthInBytes += dwPadLen;
  4155. }
  4156. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  4157. return;
  4158. }
  4159. }
  4160. DWORD
  4161. CalculateValueDataSize(
  4162. DWORD dwSyntaxId,
  4163. LPBYTE lpAttributeValues,
  4164. DWORD dwValueCount )
  4165. {
  4166. LPBYTE lpAttrStart, lpAttrTemp = lpAttributeValues;
  4167. LPBYTE lpField1, lpField2;
  4168. DWORD numFields;
  4169. DWORD length = 0;
  4170. DWORD stringLen, stringLen2;
  4171. DWORD iter, i;
  4172. DWORD dwLengthInBytes = 0;
  4173. dwLengthInBytes += sizeof(DWORD);
  4174. for ( iter = 0; iter < dwValueCount; iter++ )
  4175. {
  4176. switch ( dwSyntaxId )
  4177. {
  4178. case NDS_SYNTAX_ID_0 :
  4179. break;
  4180. case NDS_SYNTAX_ID_1 :
  4181. case NDS_SYNTAX_ID_2 :
  4182. case NDS_SYNTAX_ID_3 :
  4183. case NDS_SYNTAX_ID_4 :
  4184. case NDS_SYNTAX_ID_5 :
  4185. case NDS_SYNTAX_ID_10 :
  4186. case NDS_SYNTAX_ID_20 :
  4187. stringLen = wcslen(((LPASN1_TYPE_1) lpAttrTemp)->DNString);
  4188. dwLengthInBytes += sizeof(DWORD);
  4189. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4190. ALIGN_DWORD);
  4191. lpAttrTemp += sizeof(ASN1_TYPE_1);
  4192. break;
  4193. case NDS_SYNTAX_ID_6 :
  4194. dwLengthInBytes += sizeof(DWORD);
  4195. dwLengthInBytes += sizeof(DWORD);
  4196. lpAttrStart = lpAttrTemp;
  4197. while( ((LPASN1_TYPE_6) lpAttrTemp)->Next )
  4198. {
  4199. stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
  4200. dwLengthInBytes += sizeof(DWORD);
  4201. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4202. sizeof(WCHAR),
  4203. ALIGN_DWORD);
  4204. lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_6) lpAttrTemp)->Next);
  4205. }
  4206. stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
  4207. dwLengthInBytes += sizeof(DWORD);
  4208. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4209. sizeof(WCHAR),
  4210. ALIGN_DWORD);
  4211. lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_6);
  4212. break;
  4213. case NDS_SYNTAX_ID_7 :
  4214. dwLengthInBytes += sizeof(DWORD);
  4215. dwLengthInBytes += sizeof(DWORD);
  4216. lpAttrTemp += sizeof(ASN1_TYPE_7);
  4217. break;
  4218. case NDS_SYNTAX_ID_8 :
  4219. case NDS_SYNTAX_ID_22 :
  4220. case NDS_SYNTAX_ID_24 :
  4221. case NDS_SYNTAX_ID_27 :
  4222. dwLengthInBytes += sizeof(DWORD);
  4223. dwLengthInBytes += sizeof(DWORD);
  4224. lpAttrTemp += sizeof(ASN1_TYPE_8);
  4225. break;
  4226. case NDS_SYNTAX_ID_9 :
  4227. stringLen = ((LPASN1_TYPE_9) lpAttrTemp)->Length;
  4228. dwLengthInBytes += sizeof(DWORD);
  4229. dwLengthInBytes += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
  4230. ALIGN_DWORD );
  4231. lpAttrTemp += sizeof(ASN1_TYPE_9);
  4232. break;
  4233. case NDS_SYNTAX_ID_11 :
  4234. stringLen = wcslen(((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber);
  4235. dwLengthInBytes += sizeof(DWORD);
  4236. dwLengthInBytes += sizeof(DWORD);
  4237. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4238. ALIGN_DWORD );
  4239. dwLengthInBytes += 2*sizeof(DWORD);
  4240. lpAttrTemp += sizeof(ASN1_TYPE_11);
  4241. break;
  4242. case NDS_SYNTAX_ID_12 :
  4243. dwLengthInBytes += sizeof(DWORD);
  4244. dwLengthInBytes += sizeof(DWORD);
  4245. dwLengthInBytes += sizeof(DWORD);
  4246. dwLengthInBytes += ((LPASN1_TYPE_12)
  4247. lpAttrTemp)->AddressLength * sizeof(WCHAR);
  4248. lpAttrTemp += sizeof(ASN1_TYPE_12);
  4249. break;
  4250. case NDS_SYNTAX_ID_13 :
  4251. dwLengthInBytes += sizeof(DWORD);
  4252. dwLengthInBytes += sizeof(DWORD);
  4253. lpAttrStart = lpAttrTemp;
  4254. while ( ((LPASN1_TYPE_13) lpAttrTemp)->Next )
  4255. {
  4256. stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
  4257. dwLengthInBytes += sizeof(DWORD);
  4258. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4259. sizeof(BYTE),
  4260. ALIGN_DWORD);
  4261. lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_13) lpAttrTemp)->Next);
  4262. }
  4263. stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
  4264. dwLengthInBytes += sizeof(DWORD);
  4265. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4266. sizeof(BYTE),
  4267. ALIGN_DWORD);
  4268. lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_13);
  4269. break;
  4270. case NDS_SYNTAX_ID_14 :
  4271. stringLen = wcslen(((LPASN1_TYPE_14) lpAttrTemp)->Address);
  4272. dwLengthInBytes += sizeof(DWORD);
  4273. dwLengthInBytes += sizeof(DWORD);
  4274. dwLengthInBytes += sizeof(DWORD);
  4275. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4276. ALIGN_DWORD);
  4277. lpAttrTemp += sizeof(ASN1_TYPE_14);
  4278. break;
  4279. case NDS_SYNTAX_ID_15 :
  4280. stringLen = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->VolumeName);
  4281. stringLen2 = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->Path);
  4282. dwLengthInBytes += sizeof(DWORD);
  4283. dwLengthInBytes += sizeof(DWORD);
  4284. dwLengthInBytes += sizeof(DWORD);
  4285. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4286. ALIGN_DWORD);
  4287. dwLengthInBytes += sizeof(DWORD);
  4288. dwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4289. ALIGN_DWORD);
  4290. lpAttrTemp += sizeof(ASN1_TYPE_15);
  4291. break;
  4292. case NDS_SYNTAX_ID_16 :
  4293. stringLen = wcslen(((LPASN1_TYPE_16) lpAttrTemp)->ServerName);
  4294. dwLengthInBytes += sizeof(DWORD);
  4295. dwLengthInBytes += sizeof(DWORD);
  4296. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4297. ALIGN_DWORD);
  4298. dwLengthInBytes += sizeof(DWORD);
  4299. dwLengthInBytes += sizeof(DWORD);
  4300. dwLengthInBytes += sizeof(DWORD);
  4301. lpAttrTemp += sizeof(ASN1_TYPE_16);
  4302. break;
  4303. case NDS_SYNTAX_ID_17 :
  4304. stringLen = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->ProtectedAttrName);
  4305. stringLen2 = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->SubjectName);
  4306. dwLengthInBytes += sizeof(DWORD);
  4307. dwLengthInBytes += sizeof(DWORD);
  4308. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4309. ALIGN_DWORD);
  4310. dwLengthInBytes += sizeof(DWORD);
  4311. dwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4312. ALIGN_DWORD);
  4313. dwLengthInBytes += sizeof(DWORD);
  4314. lpAttrTemp += sizeof(ASN1_TYPE_17);
  4315. break;
  4316. case NDS_SYNTAX_ID_18 :
  4317. dwLengthInBytes += sizeof(DWORD);
  4318. dwLengthInBytes += sizeof(DWORD);
  4319. for ( i = 0; i < 6; i++ )
  4320. {
  4321. stringLen = wcslen(((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i]);
  4322. dwLengthInBytes += sizeof(DWORD);
  4323. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4324. sizeof(WCHAR),
  4325. ALIGN_DWORD);
  4326. }
  4327. lpAttrTemp += sizeof(ASN1_TYPE_18);
  4328. break;
  4329. case NDS_SYNTAX_ID_19 :
  4330. dwLengthInBytes += sizeof(DWORD);
  4331. dwLengthInBytes += sizeof(DWORD);
  4332. lpAttrTemp += sizeof(ASN1_TYPE_19);
  4333. break;
  4334. case NDS_SYNTAX_ID_21 :
  4335. dwLengthInBytes += sizeof(DWORD);
  4336. lpAttrTemp += sizeof(ASN1_TYPE_21);
  4337. break;
  4338. case NDS_SYNTAX_ID_23 :
  4339. break;
  4340. case NDS_SYNTAX_ID_25 :
  4341. stringLen = wcslen(((LPASN1_TYPE_25) lpAttrTemp)->ObjectName);
  4342. dwLengthInBytes += sizeof(DWORD);
  4343. dwLengthInBytes += sizeof(DWORD);
  4344. dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4345. ALIGN_DWORD);
  4346. dwLengthInBytes += sizeof(DWORD);
  4347. dwLengthInBytes += sizeof(DWORD);
  4348. lpAttrTemp += sizeof(ASN1_TYPE_25);
  4349. break;
  4350. case NDS_SYNTAX_ID_26 :
  4351. break;
  4352. default :
  4353. #if DBG
  4354. KdPrint(( "NDS32: CalculateValueDataSize() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
  4355. ASSERT( FALSE );
  4356. #endif
  4357. break; // empty statement not allowed
  4358. }
  4359. }
  4360. return dwLengthInBytes;
  4361. }
  4362. VOID
  4363. AppendValueToEntry(
  4364. LPBYTE lpBuffer,
  4365. DWORD dwSyntaxId,
  4366. LPBYTE lpAttributeValues,
  4367. DWORD dwValueCount,
  4368. LPDWORD lpdwLengthInBytes )
  4369. {
  4370. LPBYTE lpTemp = lpBuffer;
  4371. LPBYTE lpAttrStart, lpAttrTemp = lpAttributeValues;
  4372. LPBYTE lpField1, lpField2;
  4373. DWORD numFields;
  4374. DWORD length = 0;
  4375. DWORD stringLen, stringLen2;
  4376. DWORD iter, i;
  4377. *(LPDWORD)lpTemp = dwValueCount;
  4378. lpTemp += sizeof(DWORD);
  4379. *lpdwLengthInBytes += sizeof(DWORD);
  4380. for ( iter = 0; iter < dwValueCount; iter++ )
  4381. {
  4382. switch ( dwSyntaxId )
  4383. {
  4384. case NDS_SYNTAX_ID_0 :
  4385. break;
  4386. case NDS_SYNTAX_ID_1 :
  4387. case NDS_SYNTAX_ID_2 :
  4388. case NDS_SYNTAX_ID_3 :
  4389. case NDS_SYNTAX_ID_4 :
  4390. case NDS_SYNTAX_ID_5 :
  4391. case NDS_SYNTAX_ID_10 :
  4392. case NDS_SYNTAX_ID_20 :
  4393. stringLen = wcslen(((LPASN1_TYPE_1) lpAttrTemp)->DNString);
  4394. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4395. lpTemp += sizeof(DWORD);
  4396. *lpdwLengthInBytes += sizeof(DWORD);
  4397. RtlCopyMemory( lpTemp,
  4398. ((LPASN1_TYPE_1) lpAttrTemp)->DNString,
  4399. stringLen*sizeof(WCHAR) );
  4400. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4401. ALIGN_DWORD);
  4402. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4403. ALIGN_DWORD);
  4404. lpAttrTemp += sizeof(ASN1_TYPE_1);
  4405. break;
  4406. case NDS_SYNTAX_ID_6 :
  4407. lpField1 = lpTemp; // Save field to store the number of
  4408. // bytes following
  4409. lpTemp += sizeof(DWORD);
  4410. *lpdwLengthInBytes += sizeof(DWORD);
  4411. *(LPDWORD)lpField1 = 0;
  4412. lpField2 = lpTemp; // Save field to store the number of
  4413. // elements
  4414. lpTemp += sizeof(DWORD);
  4415. *lpdwLengthInBytes += sizeof(DWORD);
  4416. *(LPDWORD)lpField1 += sizeof(DWORD);
  4417. numFields = 0;
  4418. lpAttrStart = lpAttrTemp;
  4419. while( ((LPASN1_TYPE_6) lpAttrTemp)->Next )
  4420. {
  4421. stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
  4422. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4423. lpTemp += sizeof(DWORD);
  4424. *lpdwLengthInBytes += sizeof(DWORD);
  4425. *(LPDWORD)lpField1 += sizeof(DWORD);
  4426. RtlCopyMemory( lpTemp,
  4427. ((LPASN1_TYPE_6) lpAttrTemp)->String,
  4428. stringLen*sizeof(WCHAR) );
  4429. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4430. ALIGN_DWORD);
  4431. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4432. sizeof(WCHAR),
  4433. ALIGN_DWORD);
  4434. *(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
  4435. sizeof(WCHAR),
  4436. ALIGN_DWORD);
  4437. lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_6) lpAttrTemp)->Next);
  4438. numFields++;
  4439. }
  4440. stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
  4441. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4442. lpTemp += sizeof(DWORD);
  4443. *lpdwLengthInBytes += sizeof(DWORD);
  4444. *(LPDWORD)lpField1 += sizeof(DWORD);
  4445. RtlCopyMemory( lpTemp,
  4446. ((LPASN1_TYPE_6) lpAttrTemp)->String,
  4447. stringLen*sizeof(WCHAR) );
  4448. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4449. ALIGN_DWORD);
  4450. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4451. sizeof(WCHAR),
  4452. ALIGN_DWORD);
  4453. *(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
  4454. sizeof(WCHAR),
  4455. ALIGN_DWORD);
  4456. lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_6);
  4457. numFields++;
  4458. *(LPDWORD)lpField2 = numFields;
  4459. break;
  4460. case NDS_SYNTAX_ID_7 :
  4461. *(LPDWORD)lpTemp = 1; // Needs to have value 1, representing one byte even though it is
  4462. // padded out to four bytes.
  4463. lpTemp += sizeof(DWORD);
  4464. *lpdwLengthInBytes += sizeof(DWORD);
  4465. *(LPDWORD)lpTemp = 0; // This clears all bits of the DWORD
  4466. *(LPBYTE)lpTemp = (BYTE) (((LPASN1_TYPE_7)
  4467. lpAttrTemp)->Boolean);
  4468. lpTemp += sizeof(DWORD);
  4469. *lpdwLengthInBytes += sizeof(DWORD);
  4470. lpAttrTemp += sizeof(ASN1_TYPE_7);
  4471. break;
  4472. case NDS_SYNTAX_ID_8 :
  4473. case NDS_SYNTAX_ID_22 :
  4474. case NDS_SYNTAX_ID_24 :
  4475. case NDS_SYNTAX_ID_27 :
  4476. *(LPDWORD)lpTemp = 4; // Needs to have value 4, representing four bytes - already DWORD aligned.
  4477. lpTemp += sizeof(DWORD);
  4478. *lpdwLengthInBytes += sizeof(DWORD);
  4479. *(LPDWORD)lpTemp = ((LPASN1_TYPE_8) lpAttrTemp)->Integer;
  4480. lpTemp += sizeof(DWORD);
  4481. *lpdwLengthInBytes += sizeof(DWORD);
  4482. lpAttrTemp += sizeof(ASN1_TYPE_8);
  4483. break;
  4484. case NDS_SYNTAX_ID_9 :
  4485. stringLen = ((LPASN1_TYPE_9) lpAttrTemp)->Length;
  4486. *(LPDWORD)lpTemp = (stringLen) * sizeof(BYTE);
  4487. lpTemp += sizeof(DWORD);
  4488. *lpdwLengthInBytes += sizeof(DWORD);
  4489. RtlCopyMemory( lpTemp,
  4490. ((LPASN1_TYPE_9) lpAttrTemp)->OctetString,
  4491. stringLen*sizeof(BYTE) );
  4492. lpTemp += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
  4493. ALIGN_DWORD );
  4494. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
  4495. ALIGN_DWORD );
  4496. lpAttrTemp += sizeof(ASN1_TYPE_9);
  4497. break;
  4498. case NDS_SYNTAX_ID_11 :
  4499. stringLen = wcslen(((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber);
  4500. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4501. ALIGN_DWORD) +
  4502. ( 2*sizeof(DWORD) );
  4503. lpTemp += sizeof(DWORD);
  4504. *lpdwLengthInBytes += sizeof(DWORD);
  4505. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4506. lpTemp += sizeof(DWORD);
  4507. *lpdwLengthInBytes += sizeof(DWORD);
  4508. RtlCopyMemory( lpTemp,
  4509. ((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber,
  4510. stringLen*sizeof(WCHAR) );
  4511. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),ALIGN_DWORD);
  4512. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4513. ALIGN_DWORD );
  4514. lpTemp += 2*sizeof(DWORD);
  4515. *lpdwLengthInBytes += 2*sizeof(DWORD);
  4516. lpAttrTemp += sizeof(ASN1_TYPE_11);
  4517. break;
  4518. case NDS_SYNTAX_ID_12 :
  4519. *(LPDWORD)lpTemp =
  4520. (2*sizeof(DWORD)) +
  4521. (((LPASN1_TYPE_12) lpAttrTemp)->AddressLength*sizeof(WCHAR));
  4522. lpTemp += sizeof(DWORD);
  4523. *lpdwLengthInBytes += sizeof(DWORD);
  4524. *(LPDWORD)lpTemp = ((LPASN1_TYPE_12) lpAttrTemp)->AddressType;
  4525. lpTemp += sizeof(DWORD);
  4526. *lpdwLengthInBytes += sizeof(DWORD);
  4527. //
  4528. // Write address length value to buffer
  4529. //
  4530. *(LPDWORD)lpTemp = ((LPASN1_TYPE_12) lpAttrTemp)->AddressLength;
  4531. lpTemp += sizeof(DWORD);
  4532. *lpdwLengthInBytes += sizeof(DWORD);
  4533. //
  4534. // Write the address to the buffer
  4535. //
  4536. RtlCopyMemory( lpTemp,
  4537. ((LPASN1_TYPE_12) lpAttrTemp)->Address,
  4538. ((LPASN1_TYPE_12) lpAttrTemp)->AddressLength
  4539. * sizeof(WCHAR) );
  4540. lpTemp += ((LPASN1_TYPE_12) lpAttrTemp)->AddressLength *
  4541. sizeof(WCHAR);
  4542. *lpdwLengthInBytes += ((LPASN1_TYPE_12)
  4543. lpAttrTemp)->AddressLength * sizeof(WCHAR);
  4544. lpAttrTemp += sizeof(ASN1_TYPE_12);
  4545. break;
  4546. case NDS_SYNTAX_ID_13 :
  4547. lpField1 = lpTemp; // Save field to store the number of
  4548. // bytes following
  4549. lpTemp += sizeof(DWORD);
  4550. *lpdwLengthInBytes += sizeof(DWORD);
  4551. *(LPDWORD)lpField1 = 0;
  4552. lpField2 = lpTemp; // Save field to store the number of
  4553. // elements
  4554. lpTemp += sizeof(DWORD);
  4555. *lpdwLengthInBytes += sizeof(DWORD);
  4556. *(LPDWORD)lpField1 += sizeof(DWORD);
  4557. numFields = 0;
  4558. lpAttrStart = lpAttrTemp;
  4559. while ( ((LPASN1_TYPE_13) lpAttrTemp)->Next )
  4560. {
  4561. stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
  4562. *(LPDWORD)lpTemp = stringLen;
  4563. lpTemp += sizeof(DWORD);
  4564. *lpdwLengthInBytes += sizeof(DWORD);
  4565. *(LPDWORD)lpField1 += sizeof(DWORD);
  4566. RtlCopyMemory( lpTemp,
  4567. ((LPASN1_TYPE_13) lpAttrTemp)->Data,
  4568. stringLen*sizeof(BYTE) );
  4569. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(BYTE),
  4570. ALIGN_DWORD);
  4571. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4572. sizeof(BYTE),
  4573. ALIGN_DWORD);
  4574. *(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
  4575. sizeof(BYTE),
  4576. ALIGN_DWORD);
  4577. lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_13) lpAttrTemp)->Next);
  4578. numFields++;
  4579. }
  4580. stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
  4581. *(LPDWORD)lpTemp = stringLen;
  4582. lpTemp += sizeof(DWORD);
  4583. *lpdwLengthInBytes += sizeof(DWORD);
  4584. *(LPDWORD)lpField1 += sizeof(DWORD);
  4585. RtlCopyMemory( lpTemp,
  4586. ((LPASN1_TYPE_13) lpAttrTemp)->Data,
  4587. stringLen*sizeof(BYTE) );
  4588. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(BYTE),
  4589. ALIGN_DWORD);
  4590. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4591. sizeof(BYTE),
  4592. ALIGN_DWORD);
  4593. *(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
  4594. sizeof(BYTE),
  4595. ALIGN_DWORD);
  4596. lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_13);
  4597. numFields++;
  4598. *(LPDWORD)lpField2 = numFields;
  4599. break;
  4600. case NDS_SYNTAX_ID_14 :
  4601. stringLen = wcslen(((LPASN1_TYPE_14) lpAttrTemp)->Address);
  4602. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4603. ALIGN_DWORD) +
  4604. sizeof(DWORD);
  4605. lpTemp += sizeof(DWORD);
  4606. *lpdwLengthInBytes += sizeof(DWORD);
  4607. *(LPDWORD)lpTemp = ((LPASN1_TYPE_14) lpAttrTemp)->Type;
  4608. lpTemp += sizeof(DWORD);
  4609. *lpdwLengthInBytes += sizeof(DWORD);
  4610. *(LPDWORD)lpTemp = (stringLen + 1)*sizeof(WCHAR);
  4611. lpTemp += sizeof(DWORD);
  4612. *lpdwLengthInBytes += sizeof(DWORD);
  4613. RtlCopyMemory( lpTemp,
  4614. ((LPASN1_TYPE_14) lpAttrTemp)->Address,
  4615. stringLen*sizeof(WCHAR) );
  4616. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4617. ALIGN_DWORD);
  4618. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4619. ALIGN_DWORD);
  4620. lpAttrTemp += sizeof(ASN1_TYPE_14);
  4621. break;
  4622. case NDS_SYNTAX_ID_15 :
  4623. stringLen = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->VolumeName);
  4624. stringLen2 = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->Path);
  4625. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4626. ALIGN_DWORD) +
  4627. ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4628. ALIGN_DWORD) +
  4629. sizeof(DWORD);
  4630. lpTemp += sizeof(DWORD);
  4631. *lpdwLengthInBytes += sizeof(DWORD);
  4632. *(LPDWORD)lpTemp = ((LPASN1_TYPE_15) lpAttrTemp)->Type;
  4633. lpTemp += sizeof(DWORD);
  4634. *lpdwLengthInBytes += sizeof(DWORD);
  4635. *(LPDWORD)lpTemp = (stringLen+1) * sizeof(WCHAR);
  4636. lpTemp += sizeof(DWORD);
  4637. *lpdwLengthInBytes += sizeof(DWORD);
  4638. RtlCopyMemory( lpTemp,
  4639. ((LPASN1_TYPE_15) lpAttrTemp)->VolumeName,
  4640. stringLen*sizeof(WCHAR) );
  4641. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4642. ALIGN_DWORD);
  4643. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4644. ALIGN_DWORD);
  4645. *(LPDWORD)lpTemp = (stringLen2+1) * sizeof(WCHAR);
  4646. lpTemp += sizeof(DWORD);
  4647. *lpdwLengthInBytes += sizeof(DWORD);
  4648. RtlCopyMemory( lpTemp,
  4649. ((LPASN1_TYPE_15) lpAttrTemp)->Path,
  4650. stringLen2*sizeof(WCHAR) );
  4651. lpTemp += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4652. ALIGN_DWORD);
  4653. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4654. ALIGN_DWORD);
  4655. lpAttrTemp += sizeof(ASN1_TYPE_15);
  4656. break;
  4657. case NDS_SYNTAX_ID_16 :
  4658. stringLen = wcslen(((LPASN1_TYPE_16) lpAttrTemp)->ServerName);
  4659. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4660. ALIGN_DWORD) +
  4661. (4*sizeof(DWORD));
  4662. lpTemp += sizeof(DWORD);
  4663. *lpdwLengthInBytes += sizeof(DWORD);
  4664. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4665. lpTemp += sizeof(DWORD);
  4666. *lpdwLengthInBytes += sizeof(DWORD);
  4667. RtlCopyMemory( lpTemp,
  4668. ((LPASN1_TYPE_16) lpAttrTemp)->ServerName,
  4669. stringLen*sizeof(WCHAR) );
  4670. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4671. ALIGN_DWORD);
  4672. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4673. ALIGN_DWORD);
  4674. *(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->ReplicaType;
  4675. lpTemp += sizeof(DWORD);
  4676. *lpdwLengthInBytes += sizeof(DWORD);
  4677. *(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->ReplicaNumber;
  4678. lpTemp += sizeof(DWORD);
  4679. *lpdwLengthInBytes += sizeof(DWORD);
  4680. *(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->Count;
  4681. lpTemp += sizeof(DWORD);
  4682. *lpdwLengthInBytes += sizeof(DWORD);
  4683. lpAttrTemp += sizeof(ASN1_TYPE_16);
  4684. break;
  4685. case NDS_SYNTAX_ID_17 :
  4686. stringLen = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->ProtectedAttrName);
  4687. stringLen2 = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->SubjectName);
  4688. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4689. ALIGN_DWORD) +
  4690. ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4691. ALIGN_DWORD) +
  4692. sizeof(DWORD);
  4693. lpTemp += sizeof(DWORD);
  4694. *lpdwLengthInBytes += sizeof(DWORD);
  4695. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4696. lpTemp += sizeof(DWORD);
  4697. *lpdwLengthInBytes += sizeof(DWORD);
  4698. RtlCopyMemory( lpTemp,
  4699. ((LPASN1_TYPE_17)lpAttrTemp)->ProtectedAttrName,
  4700. stringLen*sizeof(WCHAR) );
  4701. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4702. ALIGN_DWORD);
  4703. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4704. ALIGN_DWORD);
  4705. *(LPDWORD)lpTemp = (stringLen2 + 1) * sizeof(WCHAR);
  4706. lpTemp += sizeof(DWORD);
  4707. *lpdwLengthInBytes += sizeof(DWORD);
  4708. RtlCopyMemory( lpTemp,
  4709. ((LPASN1_TYPE_17) lpAttrTemp)->SubjectName,
  4710. stringLen2*sizeof(WCHAR) );
  4711. lpTemp += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4712. ALIGN_DWORD);
  4713. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
  4714. ALIGN_DWORD);
  4715. *(LPDWORD)lpTemp = ((LPASN1_TYPE_17) lpAttrTemp)->Privileges;
  4716. lpTemp += sizeof(DWORD);
  4717. *lpdwLengthInBytes += sizeof(DWORD);
  4718. lpAttrTemp += sizeof(ASN1_TYPE_17);
  4719. break;
  4720. case NDS_SYNTAX_ID_18 :
  4721. lpField1 = lpTemp; // Save field to store the number of
  4722. // bytes following
  4723. lpTemp += sizeof(DWORD);
  4724. *lpdwLengthInBytes += sizeof(DWORD);
  4725. *(LPDWORD)lpField1 = 0;
  4726. *(LPDWORD)lpTemp = 6; // The number of postal address fields
  4727. // is always six.
  4728. lpTemp += sizeof(DWORD);
  4729. *lpdwLengthInBytes += sizeof(DWORD);
  4730. *(LPDWORD)lpField1 += sizeof(DWORD);
  4731. for ( i = 0; i < 6; i++ )
  4732. {
  4733. stringLen = wcslen(((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i]);
  4734. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4735. lpTemp += sizeof(DWORD);
  4736. *lpdwLengthInBytes += sizeof(DWORD);
  4737. *(LPDWORD)lpField1 += sizeof(DWORD);
  4738. RtlCopyMemory( lpTemp,
  4739. ((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i],
  4740. stringLen*sizeof(WCHAR) );
  4741. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4742. ALIGN_DWORD);
  4743. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
  4744. sizeof(WCHAR),
  4745. ALIGN_DWORD);
  4746. *(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
  4747. sizeof(WCHAR),
  4748. ALIGN_DWORD);
  4749. }
  4750. lpAttrTemp += sizeof(ASN1_TYPE_18);
  4751. break;
  4752. case NDS_SYNTAX_ID_19 :
  4753. *(LPDWORD)lpTemp = ((LPASN1_TYPE_19) lpAttrTemp)->WholeSeconds;
  4754. lpTemp += sizeof(DWORD);
  4755. *lpdwLengthInBytes += sizeof(DWORD);
  4756. *(LPDWORD)lpTemp = ((LPASN1_TYPE_19) lpAttrTemp)->EventID;
  4757. lpTemp += sizeof(DWORD);
  4758. *lpdwLengthInBytes += sizeof(DWORD);
  4759. lpAttrTemp += sizeof(ASN1_TYPE_19);
  4760. break;
  4761. case NDS_SYNTAX_ID_21 :
  4762. *(LPDWORD)lpTemp = ((LPASN1_TYPE_21) lpAttrTemp)->Length;
  4763. lpTemp += sizeof(DWORD);
  4764. *lpdwLengthInBytes += sizeof(DWORD);
  4765. lpAttrTemp += sizeof(ASN1_TYPE_21);
  4766. break;
  4767. case NDS_SYNTAX_ID_23 :
  4768. break;
  4769. case NDS_SYNTAX_ID_25 :
  4770. stringLen = wcslen(((LPASN1_TYPE_25) lpAttrTemp)->ObjectName);
  4771. *(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4772. ALIGN_DWORD) +
  4773. 2*sizeof(DWORD);
  4774. lpTemp += sizeof(DWORD);
  4775. *lpdwLengthInBytes += sizeof(DWORD);
  4776. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  4777. lpTemp += sizeof(DWORD);
  4778. *lpdwLengthInBytes += sizeof(DWORD);
  4779. RtlCopyMemory( lpTemp,
  4780. ((LPASN1_TYPE_25) lpAttrTemp)->ObjectName,
  4781. stringLen*sizeof(WCHAR) );
  4782. lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4783. ALIGN_DWORD);
  4784. *lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
  4785. ALIGN_DWORD);
  4786. *(LPDWORD)lpTemp = ((LPASN1_TYPE_25) lpAttrTemp)->Level;
  4787. lpTemp += sizeof(DWORD);
  4788. *lpdwLengthInBytes += sizeof(DWORD);
  4789. *(LPDWORD)lpTemp = ((LPASN1_TYPE_25) lpAttrTemp)->Interval;
  4790. lpTemp += sizeof(DWORD);
  4791. *lpdwLengthInBytes += sizeof(DWORD);
  4792. lpAttrTemp += sizeof(ASN1_TYPE_25);
  4793. break;
  4794. case NDS_SYNTAX_ID_26 :
  4795. break;
  4796. default :
  4797. #if DBG
  4798. KdPrint(( "NDS32: AppendValueToEntry() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
  4799. ASSERT( FALSE );
  4800. #endif
  4801. break; // empty statement not allowed
  4802. }
  4803. }
  4804. }
  4805. DWORD
  4806. MapNetwareErrorCode(
  4807. DWORD dwNetwareError )
  4808. {
  4809. DWORD status = NO_ERROR;
  4810. switch( dwNetwareError )
  4811. {
  4812. case NDS_ERR_SUCCESS :
  4813. status = NO_ERROR;
  4814. break;
  4815. case NDS_ERR_NO_SUCH_ENTRY :
  4816. case NDS_ERR_NO_SUCH_VALUE :
  4817. case NDS_ERR_NO_SUCH_ATTRIBUTE :
  4818. case NDS_ERR_NO_SUCH_CLASS :
  4819. case NDS_ERR_NO_SUCH_PARTITION :
  4820. status = ERROR_EXTENDED_ERROR;
  4821. break;
  4822. case NDS_ERR_ENTRY_ALREADY_EXISTS :
  4823. status = ERROR_ALREADY_EXISTS;
  4824. break;
  4825. case NDS_ERR_NOT_EFFECTIVE_CLASS :
  4826. case NDS_ERR_ILLEGAL_ATTRIBUTE :
  4827. case NDS_ERR_MISSING_MANDATORY :
  4828. case NDS_ERR_ILLEGAL_DS_NAME :
  4829. case NDS_ERR_ILLEGAL_CONTAINMENT :
  4830. case NDS_ERR_CANT_HAVE_MULTIPLE_VALUES :
  4831. case NDS_ERR_SYNTAX_VIOLATION :
  4832. case NDS_ERR_DUPLICATE_VALUE :
  4833. case NDS_ERR_ATTRIBUTE_ALREADY_EXISTS :
  4834. case NDS_ERR_MAXIMUM_ENTRIES_EXIST :
  4835. case NDS_ERR_DATABASE_FORMAT :
  4836. case NDS_ERR_INCONSISTANT_DATABASE :
  4837. case NDS_ERR_INVALID_COMPARISON :
  4838. case NDS_ERR_COMPARISON_FAILED :
  4839. case NDS_ERR_TRANSACTIONS_DISABLED :
  4840. case NDS_ERR_INVALID_TRANSPORT :
  4841. case NDS_ERR_SYNTAX_INVALID_IN_NAME :
  4842. case NDS_ERR_REPLICA_ALREADY_EXISTS :
  4843. case NDS_ERR_TRANSPORT_FAILURE :
  4844. case NDS_ERR_ALL_REFERRALS_FAILED :
  4845. case NDS_ERR_CANT_REMOVE_NAMING_VALUE :
  4846. case NDS_ERR_OBJECT_CLASS_VIOLATION :
  4847. case NDS_ERR_ENTRY_IS_NOT_LEAF :
  4848. case NDS_ERR_DIFFERENT_TREE :
  4849. case NDS_ERR_ILLEGAL_REPLICA_TYPE :
  4850. case NDS_ERR_SYSTEM_FAILURE :
  4851. case NDS_ERR_INVALID_ENTRY_FOR_ROOT :
  4852. case NDS_ERR_NO_REFERRALS :
  4853. case NDS_ERR_REMOTE_FAILURE :
  4854. case NDS_ERR_INVALID_REQUEST :
  4855. case NDS_ERR_INVALID_ITERATION :
  4856. case NDS_ERR_SCHEMA_IS_NONREMOVABLE :
  4857. case NDS_ERR_SCHEMA_IS_IN_USE :
  4858. case NDS_ERR_CLASS_ALREADY_EXISTS :
  4859. case NDS_ERR_BAD_NAMING_ATTRIBUTES :
  4860. case NDS_ERR_NOT_ROOT_PARTITION :
  4861. case NDS_ERR_INSUFFICIENT_STACK :
  4862. case NDS_ERR_INSUFFICIENT_BUFFER :
  4863. case NDS_ERR_AMBIGUOUS_CONTAINMENT :
  4864. case NDS_ERR_AMBIGUOUS_NAMING :
  4865. case NDS_ERR_DUPLICATE_MANDATORY :
  4866. case NDS_ERR_DUPLICATE_OPTIONAL :
  4867. case NDS_ERR_MULTIPLE_REPLICAS :
  4868. case NDS_ERR_CRUCIAL_REPLICA :
  4869. case NDS_ERR_SCHEMA_SYNC_IN_PROGRESS :
  4870. case NDS_ERR_SKULK_IN_PROGRESS :
  4871. case NDS_ERR_TIME_NOT_SYNCRONIZED :
  4872. case NDS_ERR_RECORD_IN_USE :
  4873. case NDS_ERR_DS_VOLUME_NOT_MOUNTED :
  4874. case NDS_ERR_DS_VOLUME_IO_FAILURE :
  4875. case NDS_ERR_DS_LOCKED :
  4876. case NDS_ERR_OLD_EPOCH :
  4877. case NDS_ERR_NEW_EPOCH :
  4878. case NDS_ERR_PARTITION_ROOT :
  4879. case NDS_ERR_ENTRY_NOT_CONTAINER :
  4880. case NDS_ERR_FAILED_AUTHENTICATION :
  4881. case NDS_ERR_NO_SUCH_PARENT :
  4882. status = ERROR_EXTENDED_ERROR;
  4883. break;
  4884. case NDS_ERR_NO_ACCESS :
  4885. status = ERROR_ACCESS_DENIED;
  4886. break;
  4887. case NDS_ERR_REPLICA_NOT_ON :
  4888. case NDS_ERR_DUPLICATE_ACL :
  4889. case NDS_ERR_PARTITION_ALREADY_EXISTS :
  4890. case NDS_ERR_NOT_SUBREF :
  4891. case NDS_ERR_ALIAS_OF_AN_ALIAS :
  4892. case NDS_ERR_AUDITING_FAILED :
  4893. case NDS_ERR_INVALID_API_VERSION :
  4894. case NDS_ERR_SECURE_NCP_VIOLATION :
  4895. case NDS_ERR_FATAL :
  4896. status = ERROR_EXTENDED_ERROR;
  4897. break;
  4898. default :
  4899. #if DBG
  4900. KdPrint(( "NDS32: MapNetwareErrorCode failed, Netware error = 0x%.8X\n", dwNetwareError ));
  4901. ASSERT( FALSE );
  4902. #endif
  4903. status = ERROR_EXTENDED_ERROR;
  4904. }
  4905. return status;
  4906. }
  4907. DWORD
  4908. IndexReadAttrDefReplyBuffer(
  4909. LPNDS_BUFFER lpNdsBuffer )
  4910. {
  4911. LPNDS_ATTR_DEF lpReplyIndex = NULL;
  4912. DWORD iter;
  4913. LPBYTE lpByte = NULL;
  4914. DWORD dwStringLen;
  4915. //
  4916. // Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
  4917. //
  4918. lpNdsBuffer->dwCurrentIndexEntry = 0;
  4919. //
  4920. // Set values used to track the memory used in the index buffer.
  4921. //
  4922. lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
  4923. sizeof(NDS_ATTR_DEF);
  4924. lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
  4925. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  4926. lpNdsBuffer->dwLengthOfIndexData = 0;
  4927. //
  4928. // Create a buffer to hold the ReplyBufferIndex
  4929. //
  4930. lpReplyIndex = (LPNDS_ATTR_DEF)
  4931. LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
  4932. //
  4933. // Check that the memory allocation was successful.
  4934. //
  4935. if ( lpReplyIndex == NULL )
  4936. {
  4937. #if DBG
  4938. KdPrint(( "NDS32: IndexReadAttrDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  4939. #endif
  4940. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  4941. return (DWORD) UNSUCCESSFUL;
  4942. }
  4943. lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
  4944. //
  4945. // Move lpByte so that it points to the first attribute definition
  4946. //
  4947. lpByte = lpNdsBuffer->lpReplyBuffer;
  4948. // lpByte += sizeof(DWORD); // Move past Completion Code
  4949. // lpByte += sizeof(DWORD); // Move past Iteration Handle
  4950. // lpByte += sizeof(DWORD); // Move past Information Type
  4951. // lpByte += sizeof(DWORD); // Move past Amount Of Attributes
  4952. lpByte += 4 * sizeof(DWORD); // Equivalent to above
  4953. //
  4954. // In a for loop, walk the reply buffer index and fill it up with
  4955. // data by referencing the Reply buffer or Syntax buffer.
  4956. //
  4957. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
  4958. {
  4959. dwStringLen = *((LPDWORD) lpByte);
  4960. lpByte += sizeof(DWORD); // Move past Attribute Name Length
  4961. lpReplyIndex[iter].szAttributeName = (LPWSTR) lpByte;
  4962. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  4963. lpReplyIndex[iter].dwFlags = *((LPDWORD) lpByte);
  4964. lpByte += sizeof(DWORD); // Move past Flags
  4965. lpReplyIndex[iter].dwSyntaxID = *((LPDWORD) lpByte);
  4966. lpByte += sizeof(DWORD); // Move past Syntax ID
  4967. lpReplyIndex[iter].dwLowerLimit = *((LPDWORD) lpByte);
  4968. lpByte += sizeof(DWORD); // Move past Lower Limit
  4969. lpReplyIndex[iter].dwUpperLimit = *((LPDWORD) lpByte);
  4970. lpByte += sizeof(DWORD); // Move past Upper Limit
  4971. lpReplyIndex[iter].asn1ID.length = *((LPDWORD) lpByte);
  4972. lpByte += sizeof(DWORD); // Move past ASN.1 ID length
  4973. RtlCopyMemory( lpReplyIndex[iter].asn1ID.data,
  4974. lpByte,
  4975. sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN );
  4976. lpByte += sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN;
  4977. lpNdsBuffer->dwNumberOfIndexEntries++;
  4978. lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_ATTR_DEF );
  4979. lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_ATTR_DEF );
  4980. }
  4981. #if DBG
  4982. if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
  4983. {
  4984. KdPrint(( "ASSERT in NDS32: IndexReadAttrDefReplyBuffer\n" ));
  4985. KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
  4986. KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
  4987. ASSERT( FALSE );
  4988. }
  4989. #endif
  4990. return NO_ERROR;
  4991. }
  4992. DWORD
  4993. IndexReadClassDefReplyBuffer(
  4994. LPNDS_BUFFER lpNdsBuffer )
  4995. {
  4996. LPNDS_CLASS_DEF lpReplyIndex = NULL;
  4997. DWORD iter;
  4998. LPBYTE lpByte = NULL;
  4999. DWORD LengthOfValueStructs;
  5000. DWORD dwStringLen;
  5001. //
  5002. // Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
  5003. //
  5004. lpNdsBuffer->dwCurrentIndexEntry = 0;
  5005. //
  5006. // Set values used to track the memory used in the index buffer.
  5007. //
  5008. lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
  5009. sizeof(NDS_CLASS_DEF);
  5010. lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
  5011. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  5012. lpNdsBuffer->dwLengthOfIndexData = 0;
  5013. //
  5014. // Create a buffer to hold the ReplyBufferIndex
  5015. //
  5016. lpReplyIndex = (LPNDS_CLASS_DEF)
  5017. LocalAlloc( LPTR,
  5018. lpNdsBuffer->dwIndexBufferSize );
  5019. //
  5020. // Check that the memory allocation was successful.
  5021. //
  5022. if ( lpReplyIndex == NULL )
  5023. {
  5024. #if DBG
  5025. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5026. #endif
  5027. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5028. return (DWORD) UNSUCCESSFUL;
  5029. }
  5030. lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
  5031. //
  5032. // Move lpByte so that it points to the SyntaxId of the first attribute
  5033. //
  5034. lpByte = lpNdsBuffer->lpReplyBuffer;
  5035. // lpByte += sizeof(DWORD); // Move past Completion Code
  5036. // lpByte += sizeof(DWORD); // Move past Iteration Handle
  5037. // lpByte += sizeof(DWORD); // Move past Information Type
  5038. // lpByte += sizeof(DWORD); // Move past Amount Of Attributes
  5039. lpByte += 4 * sizeof(DWORD); // Equivalent to above
  5040. //
  5041. // In a for loop, walk the index buffer and fill it up with
  5042. // data by referencing the reply buffer. Note references to
  5043. // the syntax buffer are stored as offsets while un-marshalling.
  5044. //
  5045. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
  5046. {
  5047. dwStringLen = *((LPDWORD) lpByte);
  5048. lpByte += sizeof(DWORD); // Move past Class Name Length
  5049. lpReplyIndex[iter].szClassName = (LPWSTR) lpByte;
  5050. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  5051. lpReplyIndex[iter].dwFlags = *((LPDWORD) lpByte);
  5052. lpByte += sizeof(DWORD); // Move past Flags
  5053. lpReplyIndex[iter].asn1ID.length = *((LPDWORD) lpByte);
  5054. lpByte += sizeof(DWORD); // Move past ASN.1 ID length
  5055. RtlCopyMemory( lpReplyIndex[iter].asn1ID.data,
  5056. lpByte,
  5057. sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN );
  5058. lpByte += sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN;
  5059. lpReplyIndex[iter].dwNumberOfSuperClasses = *((LPDWORD) lpByte);
  5060. lpByte += sizeof(DWORD);
  5061. if ( lpReplyIndex[iter].dwNumberOfSuperClasses > 0 )
  5062. {
  5063. if ( VerifyBufferSizeForStringList(
  5064. lpNdsBuffer->dwSyntaxAvailableBytes,
  5065. lpReplyIndex[iter].dwNumberOfSuperClasses,
  5066. &LengthOfValueStructs ) != NO_ERROR )
  5067. {
  5068. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5069. {
  5070. #if DBG
  5071. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5072. #endif
  5073. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5074. return (DWORD) UNSUCCESSFUL;
  5075. }
  5076. }
  5077. lpByte += ParseStringListBlob(
  5078. lpByte,
  5079. lpReplyIndex[iter].dwNumberOfSuperClasses,
  5080. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5081. lpReplyIndex[iter].lpSuperClasses =
  5082. (LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
  5083. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5084. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5085. }
  5086. else
  5087. {
  5088. lpReplyIndex[iter].lpSuperClasses = NULL;
  5089. }
  5090. lpReplyIndex[iter].dwNumberOfContainmentClasses = *((LPDWORD) lpByte);
  5091. lpByte += sizeof(DWORD);
  5092. if ( lpReplyIndex[iter].dwNumberOfContainmentClasses > 0 )
  5093. {
  5094. if ( VerifyBufferSizeForStringList(
  5095. lpNdsBuffer->dwSyntaxAvailableBytes,
  5096. lpReplyIndex[iter].dwNumberOfContainmentClasses,
  5097. &LengthOfValueStructs ) != NO_ERROR )
  5098. {
  5099. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) !=
  5100. NO_ERROR )
  5101. {
  5102. #if DBG
  5103. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5104. #endif
  5105. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5106. return (DWORD) UNSUCCESSFUL;
  5107. }
  5108. }
  5109. lpByte += ParseStringListBlob(
  5110. lpByte,
  5111. lpReplyIndex[iter].dwNumberOfContainmentClasses,
  5112. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5113. lpReplyIndex[iter].lpContainmentClasses =
  5114. (LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
  5115. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5116. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5117. }
  5118. else
  5119. {
  5120. lpReplyIndex[iter].lpContainmentClasses = NULL;
  5121. }
  5122. lpReplyIndex[iter].dwNumberOfNamingAttributes = *((LPDWORD) lpByte);
  5123. lpByte += sizeof(DWORD);
  5124. if ( lpReplyIndex[iter].dwNumberOfNamingAttributes > 0 )
  5125. {
  5126. if ( VerifyBufferSizeForStringList(
  5127. lpNdsBuffer->dwSyntaxAvailableBytes,
  5128. lpReplyIndex[iter].dwNumberOfNamingAttributes,
  5129. &LengthOfValueStructs ) != NO_ERROR )
  5130. {
  5131. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5132. {
  5133. #if DBG
  5134. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5135. #endif
  5136. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5137. return (DWORD) UNSUCCESSFUL;
  5138. }
  5139. }
  5140. lpByte += ParseStringListBlob(
  5141. lpByte,
  5142. lpReplyIndex[iter].dwNumberOfNamingAttributes,
  5143. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5144. lpReplyIndex[iter].lpNamingAttributes =
  5145. (LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
  5146. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5147. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5148. }
  5149. else
  5150. {
  5151. lpReplyIndex[iter].lpNamingAttributes = NULL;
  5152. }
  5153. lpReplyIndex[iter].dwNumberOfMandatoryAttributes = *((LPDWORD) lpByte);
  5154. lpByte += sizeof(DWORD);
  5155. if ( lpReplyIndex[iter].dwNumberOfMandatoryAttributes > 0 )
  5156. {
  5157. if ( VerifyBufferSizeForStringList(
  5158. lpNdsBuffer->dwSyntaxAvailableBytes,
  5159. lpReplyIndex[iter].dwNumberOfMandatoryAttributes,
  5160. &LengthOfValueStructs ) != NO_ERROR )
  5161. {
  5162. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5163. {
  5164. #if DBG
  5165. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5166. #endif
  5167. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5168. return (DWORD) UNSUCCESSFUL;
  5169. }
  5170. }
  5171. lpByte += ParseStringListBlob(
  5172. lpByte,
  5173. lpReplyIndex[iter].dwNumberOfMandatoryAttributes,
  5174. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5175. lpReplyIndex[iter].lpMandatoryAttributes =
  5176. (LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
  5177. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5178. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5179. }
  5180. else
  5181. {
  5182. lpReplyIndex[iter].lpMandatoryAttributes = NULL;
  5183. }
  5184. lpReplyIndex[iter].dwNumberOfOptionalAttributes = *((LPDWORD) lpByte);
  5185. lpByte += sizeof(DWORD);
  5186. if ( lpReplyIndex[iter].dwNumberOfOptionalAttributes > 0 )
  5187. {
  5188. if ( VerifyBufferSizeForStringList(
  5189. lpNdsBuffer->dwSyntaxAvailableBytes,
  5190. lpReplyIndex[iter].dwNumberOfOptionalAttributes,
  5191. &LengthOfValueStructs ) != NO_ERROR )
  5192. {
  5193. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5194. {
  5195. #if DBG
  5196. KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5197. #endif
  5198. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5199. return (DWORD) UNSUCCESSFUL;
  5200. }
  5201. }
  5202. lpByte += ParseStringListBlob(
  5203. lpByte,
  5204. lpReplyIndex[iter].dwNumberOfOptionalAttributes,
  5205. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5206. lpReplyIndex[iter].lpOptionalAttributes =
  5207. (LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
  5208. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5209. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5210. }
  5211. else
  5212. {
  5213. lpReplyIndex[iter].lpOptionalAttributes = NULL;
  5214. }
  5215. lpNdsBuffer->dwNumberOfIndexEntries++;
  5216. lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_CLASS_DEF );
  5217. lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_CLASS_DEF );
  5218. }
  5219. //
  5220. // Now convert all syntax buffer references to pointers.
  5221. //
  5222. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
  5223. {
  5224. if ( lpReplyIndex[iter].dwNumberOfSuperClasses > 0 )
  5225. {
  5226. (LPBYTE) lpReplyIndex[iter].lpSuperClasses +=
  5227. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5228. }
  5229. if ( lpReplyIndex[iter].dwNumberOfContainmentClasses > 0 )
  5230. {
  5231. (LPBYTE) lpReplyIndex[iter].lpContainmentClasses +=
  5232. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5233. }
  5234. if ( lpReplyIndex[iter].dwNumberOfNamingAttributes > 0 )
  5235. {
  5236. (LPBYTE) lpReplyIndex[iter].lpNamingAttributes +=
  5237. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5238. }
  5239. if ( lpReplyIndex[iter].dwNumberOfMandatoryAttributes > 0 )
  5240. {
  5241. (LPBYTE) lpReplyIndex[iter].lpMandatoryAttributes +=
  5242. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5243. }
  5244. if ( lpReplyIndex[iter].dwNumberOfOptionalAttributes > 0 )
  5245. {
  5246. (LPBYTE) lpReplyIndex[iter].lpOptionalAttributes +=
  5247. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5248. }
  5249. }
  5250. #if DBG
  5251. if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
  5252. {
  5253. KdPrint(( "ASSERT in NDS32: IndexReadClassDefReplyBuffer\n" ));
  5254. KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
  5255. KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
  5256. ASSERT( FALSE );
  5257. }
  5258. #endif
  5259. return NO_ERROR;
  5260. }
  5261. DWORD
  5262. IndexReadObjectReplyBuffer(
  5263. LPNDS_BUFFER lpNdsBuffer )
  5264. {
  5265. LPNDS_ATTR_INFO lpReplyIndex = NULL;
  5266. DWORD iter;
  5267. LPBYTE lpByte = NULL;
  5268. DWORD LengthOfValueStructs;
  5269. DWORD dwStringLen;
  5270. //
  5271. // Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
  5272. //
  5273. lpNdsBuffer->dwCurrentIndexEntry = 0;
  5274. //
  5275. // Set values used to track the memory used in the index buffer.
  5276. //
  5277. lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
  5278. sizeof(NDS_ATTR_INFO);
  5279. lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
  5280. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  5281. lpNdsBuffer->dwLengthOfIndexData = 0;
  5282. //
  5283. // Create a buffer to hold the ReplyBufferIndex
  5284. //
  5285. lpReplyIndex = (LPNDS_ATTR_INFO)
  5286. LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
  5287. //
  5288. // Check that the memory allocation was successful.
  5289. //
  5290. if ( lpReplyIndex == NULL )
  5291. {
  5292. #if DBG
  5293. KdPrint(( "NDS32: IndexReadObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5294. #endif
  5295. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5296. return (DWORD) UNSUCCESSFUL;
  5297. }
  5298. lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
  5299. //
  5300. // Move lpByte so that it points to the SyntaxId of the first attribute
  5301. //
  5302. lpByte = lpNdsBuffer->lpReplyBuffer;
  5303. // lpByte += sizeof(DWORD); // Move past Completion Code
  5304. // lpByte += sizeof(DWORD); // Move past Iteration Handle
  5305. // lpByte += sizeof(DWORD); // Move past Information Type
  5306. // lpByte += sizeof(DWORD); // Move past Amount Of Attributes
  5307. lpByte += 4 * sizeof(DWORD); // Equivalent to above
  5308. //
  5309. // In a for loop, walk the index buffer and fill it up with
  5310. // data by referencing the reply buffer. Note references to
  5311. // the syntax buffer are stored as offsets while un-marshalling.
  5312. //
  5313. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
  5314. {
  5315. lpReplyIndex[iter].dwSyntaxId = *((LPDWORD) lpByte);
  5316. lpByte += sizeof(DWORD); // Move past Syntax Id
  5317. dwStringLen = *((LPDWORD) lpByte);
  5318. lpByte += sizeof(DWORD); // Move past Attribute Name Length
  5319. lpReplyIndex[iter].szAttributeName = (LPWSTR) lpByte;
  5320. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  5321. lpReplyIndex[iter].dwNumberOfValues = *((LPDWORD) lpByte);
  5322. lpByte += sizeof(DWORD); // Move past Count Of Values
  5323. //
  5324. // See if the syntax buffer is large enough to hold the number of
  5325. // SyntaxID structures that will be used to store the value(s)
  5326. // for the current attribute. If the buffer isn't large enough
  5327. // it is reallocated to a bigger size (if possible).
  5328. //
  5329. if ( VerifyBufferSize( lpByte,
  5330. lpNdsBuffer->dwSyntaxAvailableBytes,
  5331. lpReplyIndex[iter].dwSyntaxId,
  5332. lpReplyIndex[iter].dwNumberOfValues,
  5333. &LengthOfValueStructs ) != NO_ERROR )
  5334. {
  5335. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5336. {
  5337. #if DBG
  5338. KdPrint(( "NDS32: IndexReadObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5339. #endif
  5340. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5341. return (DWORD) UNSUCCESSFUL;
  5342. }
  5343. }
  5344. //
  5345. // Parse the raw data buffer by mapping the network structures to
  5346. // the NDS Syntax structures we define in NdsSntx.h. Then move the
  5347. // pointer used to walk the raw data buffer past the ASN.1 Values.
  5348. //
  5349. lpByte += ParseASN1ValueBlob( lpByte,
  5350. lpReplyIndex[iter].dwSyntaxId,
  5351. lpReplyIndex[iter].dwNumberOfValues,
  5352. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5353. lpReplyIndex[iter].lpValue =
  5354. (LPBYTE) lpNdsBuffer->dwLengthOfSyntaxData;
  5355. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5356. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5357. lpNdsBuffer->dwNumberOfIndexEntries++;
  5358. lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_ATTR_INFO );
  5359. lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_ATTR_INFO );
  5360. }
  5361. //
  5362. // Now convert all syntax buffer references to pointers.
  5363. //
  5364. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
  5365. {
  5366. (LPBYTE) lpReplyIndex[iter].lpValue +=
  5367. (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5368. }
  5369. #if DBG
  5370. if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
  5371. {
  5372. KdPrint(( "ASSERT in NDS32: IndexReadObjectReplyBuffer\n" ));
  5373. KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
  5374. KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
  5375. ASSERT( FALSE );
  5376. }
  5377. #endif
  5378. return NO_ERROR;
  5379. }
  5380. DWORD
  5381. IndexReadNameReplyBuffer(
  5382. LPNDS_BUFFER lpNdsBuffer )
  5383. {
  5384. LPNDS_NAME_ONLY lpReplyIndex = NULL;
  5385. DWORD iter;
  5386. LPBYTE lpByte = NULL;
  5387. DWORD dwStringLen;
  5388. //
  5389. // Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
  5390. //
  5391. lpNdsBuffer->dwCurrentIndexEntry = 0;
  5392. //
  5393. // Set values used to track the memory used in the index buffer.
  5394. //
  5395. lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
  5396. sizeof(NDS_NAME_ONLY);
  5397. lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
  5398. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  5399. lpNdsBuffer->dwLengthOfIndexData = 0;
  5400. //
  5401. // Create a buffer to hold the ReplyBufferIndex
  5402. //
  5403. lpReplyIndex = (LPNDS_NAME_ONLY)
  5404. LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
  5405. //
  5406. // Check that the memory allocation was successful.
  5407. //
  5408. if ( lpReplyIndex == NULL )
  5409. {
  5410. #if DBG
  5411. KdPrint(( "NDS32: IndexReadNameReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5412. #endif
  5413. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5414. return (DWORD) UNSUCCESSFUL;
  5415. }
  5416. lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
  5417. //
  5418. // Move lpByte so that it points to the first name
  5419. //
  5420. lpByte = lpNdsBuffer->lpReplyBuffer;
  5421. // lpByte += sizeof(DWORD); // Move past Completion Code
  5422. // lpByte += sizeof(DWORD); // Move past Iteration Handle
  5423. // lpByte += sizeof(DWORD); // Move past Information Type
  5424. // lpByte += sizeof(DWORD); // Move past Amount Of Attributes
  5425. lpByte += 4 * sizeof(DWORD); // Equivalent to above
  5426. //
  5427. // In a for loop, walk the reply buffer index and fill it up with
  5428. // data by referencing the Reply buffer or Syntax buffer.
  5429. //
  5430. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
  5431. {
  5432. dwStringLen = *((LPDWORD) lpByte);
  5433. lpByte += sizeof(DWORD); // Move past Attribute Name Length
  5434. lpReplyIndex[iter].szName = (LPWSTR) lpByte;
  5435. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  5436. lpNdsBuffer->dwNumberOfIndexEntries++;
  5437. lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_NAME_ONLY );
  5438. lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_NAME_ONLY );
  5439. }
  5440. #if DBG
  5441. if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
  5442. {
  5443. KdPrint(( "ASSERT in NDS32: IndexReadNameReplyBuffer\n" ));
  5444. KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
  5445. KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
  5446. ASSERT( FALSE );
  5447. }
  5448. #endif
  5449. return NO_ERROR;
  5450. }
  5451. DWORD
  5452. IndexSearchObjectReplyBuffer(
  5453. LPNDS_BUFFER lpNdsBuffer )
  5454. {
  5455. LPNDS_OBJECT_INFO lpReplyIndex = NULL;
  5456. DWORD iter;
  5457. DWORD iter2;
  5458. LPBYTE lpByte = NULL;
  5459. DWORD LengthOfValueStructs;
  5460. DWORD dwStringLen;
  5461. LPBYTE FixedPortion;
  5462. LPWSTR EndOfVariableData;
  5463. //
  5464. // Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
  5465. //
  5466. lpNdsBuffer->dwCurrentIndexEntry = 0;
  5467. //
  5468. // Set values used to track the memory used in the index buffer.
  5469. //
  5470. lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
  5471. ( sizeof(NDS_OBJECT_INFO) +
  5472. ( MAX_NDS_NAME_CHARS * 4 *
  5473. sizeof( WCHAR ) ) );
  5474. lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
  5475. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  5476. lpNdsBuffer->dwLengthOfIndexData = 0;
  5477. //
  5478. // Create a buffer to hold the ReplyBufferIndex
  5479. //
  5480. lpReplyIndex = (LPNDS_OBJECT_INFO)
  5481. LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
  5482. //
  5483. // Check that the memory allocation was successful.
  5484. //
  5485. if ( lpReplyIndex == NULL )
  5486. {
  5487. #if DBG
  5488. KdPrint(( "NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5489. #endif
  5490. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5491. return (DWORD) UNSUCCESSFUL;
  5492. }
  5493. lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
  5494. FixedPortion = lpNdsBuffer->lpIndexBuffer;
  5495. EndOfVariableData = (LPWSTR) ((DWORD_PTR) FixedPortion +
  5496. ROUND_DOWN_COUNT(
  5497. lpNdsBuffer->dwIndexAvailableBytes,
  5498. ALIGN_DWORD ) );
  5499. //
  5500. // Move lpByte so that it points to the first object
  5501. //
  5502. lpByte = lpNdsBuffer->lpReplyBuffer;
  5503. // lpByte += sizeof(DWORD); // Move past Completion Code
  5504. // lpByte += sizeof(DWORD); // Move past Iteration Handle
  5505. // lpByte += sizeof(DWORD); // Move past Information Type
  5506. // lpByte += sizeof(DWORD); // Move past Amount Of Attributes
  5507. // lpByte += sizeof(DWORD); // Move past Length Of Search
  5508. // lpByte += sizeof(DWORD); // Move past Amount Of Entries
  5509. lpByte += 6 * sizeof(DWORD); // Equivalent to above
  5510. //
  5511. // In a for loop, walk the reply buffer index and fill it up with
  5512. // data by referencing the Reply buffer or Syntax buffer.
  5513. //
  5514. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
  5515. {
  5516. WORD tempStrLen;
  5517. LPWSTR newPathStr = NULL;
  5518. LPWSTR tempStr = NULL;
  5519. LPWSTR ClassName;
  5520. LPWSTR DistinguishedObjectName;
  5521. LPWSTR ObjectName;
  5522. DWORD ClassNameLen;
  5523. DWORD DistinguishedObjectNameLen;
  5524. DWORD Flags;
  5525. DWORD SubordinateCount;
  5526. DWORD ModificationTime;
  5527. DWORD NumberOfAttributes = 0;
  5528. LPNDS_ATTR_INFO lpAttributeInfos = NULL;
  5529. DWORD EntryInfo1;
  5530. //
  5531. // Get current subtree data from lpNdsParentObject
  5532. //
  5533. lpByte = GetSearchResultData( lpByte,
  5534. &Flags,
  5535. &SubordinateCount,
  5536. &ModificationTime,
  5537. &ClassNameLen,
  5538. &ClassName,
  5539. &DistinguishedObjectNameLen,
  5540. &DistinguishedObjectName,
  5541. &EntryInfo1,
  5542. &NumberOfAttributes );
  5543. //
  5544. // Need to build a string with the new NDS UNC path
  5545. // for search object
  5546. //
  5547. newPathStr = (PVOID) LocalAlloc( LPTR,
  5548. ( wcslen( DistinguishedObjectName ) +
  5549. wcslen( lpNdsBuffer->szPath ) +
  5550. 3 ) * sizeof( WCHAR ) );
  5551. if ( newPathStr == NULL )
  5552. {
  5553. #if DBG
  5554. KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
  5555. #endif
  5556. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5557. return (DWORD) UNSUCCESSFUL;
  5558. }
  5559. //
  5560. // Need to build a string for the relative object name.
  5561. //
  5562. ObjectName = (PVOID) LocalAlloc( LPTR,
  5563. ( wcslen( DistinguishedObjectName ) +
  5564. 1 ) * sizeof( WCHAR ) );
  5565. if ( ObjectName == NULL )
  5566. {
  5567. #if DBG
  5568. KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
  5569. #endif
  5570. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5571. return (DWORD) UNSUCCESSFUL;
  5572. }
  5573. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  5574. lpNdsBuffer->szPath,
  5575. PARSE_NDS_GET_TREE_NAME );
  5576. tempStrLen /= sizeof(WCHAR);
  5577. if ( tempStrLen > 0 )
  5578. {
  5579. wcscpy( newPathStr, L"\\\\" );
  5580. wcsncat( newPathStr, tempStr, tempStrLen );
  5581. wcscat( newPathStr, L"\\" );
  5582. wcscat( newPathStr, DistinguishedObjectName );
  5583. _wcsupr( newPathStr );
  5584. }
  5585. else
  5586. {
  5587. wcscpy( newPathStr, L"" );
  5588. }
  5589. tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
  5590. newPathStr,
  5591. PARSE_NDS_GET_OBJECT_NAME );
  5592. tempStrLen /= sizeof(WCHAR);
  5593. if ( tempStrLen > 0 )
  5594. {
  5595. wcsncpy( ObjectName, tempStr, tempStrLen );
  5596. }
  5597. else
  5598. {
  5599. wcscpy( ObjectName, L"" );
  5600. }
  5601. if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_ATTR_NAMES_VALUES )
  5602. {
  5603. lpAttributeInfos = (LPNDS_ATTR_INFO) LocalAlloc(
  5604. LPTR,
  5605. NumberOfAttributes *
  5606. sizeof( NDS_ATTR_INFO )
  5607. );
  5608. if ( lpAttributeInfos == NULL )
  5609. {
  5610. #if DBG
  5611. KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
  5612. #endif
  5613. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5614. return (DWORD) UNSUCCESSFUL;
  5615. }
  5616. for ( iter2 = 0; iter2 < NumberOfAttributes; iter2++ )
  5617. {
  5618. lpAttributeInfos[iter2].dwSyntaxId = *((LPDWORD) lpByte);
  5619. lpByte += sizeof(DWORD); // Move past Syntax Id
  5620. dwStringLen = *((LPDWORD) lpByte);
  5621. lpByte += sizeof(DWORD); // Move past Attribute Name Length
  5622. lpAttributeInfos[iter2].szAttributeName = (LPWSTR) lpByte;
  5623. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  5624. lpAttributeInfos[iter2].dwNumberOfValues = *((LPDWORD) lpByte);
  5625. lpByte += sizeof(DWORD); // Move past Count Of Values
  5626. //
  5627. // See if the syntax buffer is large enough to hold the number of
  5628. // SyntaxID structures that will be used to store the value(s)
  5629. // for the current attribute. If the buffer isn't large enough
  5630. // it is reallocated to a bigger size (if possible).
  5631. //
  5632. if ( VerifyBufferSize( lpByte,
  5633. lpNdsBuffer->dwSyntaxAvailableBytes,
  5634. lpAttributeInfos[iter2].dwSyntaxId,
  5635. lpAttributeInfos[iter2].dwNumberOfValues,
  5636. &LengthOfValueStructs ) != NO_ERROR )
  5637. {
  5638. if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer ) != NO_ERROR )
  5639. {
  5640. #if DBG
  5641. KdPrint(( "NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  5642. #endif
  5643. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5644. return (DWORD) UNSUCCESSFUL;
  5645. }
  5646. }
  5647. //
  5648. // Parse the raw data buffer by mapping the network structures to
  5649. // the NDS Syntax structures we define in NdsSntx.h. Then move the
  5650. // pointer used to walk the raw data buffer past the ASN.1 Values.
  5651. //
  5652. lpByte += ParseASN1ValueBlob( lpByte,
  5653. lpAttributeInfos[iter2].dwSyntaxId,
  5654. lpAttributeInfos[iter2].dwNumberOfValues,
  5655. (LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
  5656. lpAttributeInfos[iter2].lpValue =
  5657. (LPBYTE) lpNdsBuffer->dwLengthOfSyntaxData;
  5658. lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
  5659. lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
  5660. }
  5661. }
  5662. else
  5663. {
  5664. lpAttributeInfos = (LPNDS_ATTR_INFO) LocalAlloc(
  5665. LPTR,
  5666. NumberOfAttributes *
  5667. sizeof( NDS_NAME_ONLY )
  5668. );
  5669. if ( lpAttributeInfos == NULL )
  5670. {
  5671. #if DBG
  5672. KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
  5673. #endif
  5674. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  5675. return (DWORD) UNSUCCESSFUL;
  5676. }
  5677. for ( iter2 = 0; iter2 < NumberOfAttributes; iter2++ )
  5678. {
  5679. dwStringLen = *((LPDWORD) lpByte);
  5680. lpByte += sizeof(DWORD); // Move past Attribute Name Length
  5681. ((LPNDS_NAME_ONLY) lpAttributeInfos)[iter2].szName =
  5682. (LPWSTR) lpByte;
  5683. lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
  5684. }
  5685. }
  5686. (void) WriteObjectToBuffer( &FixedPortion,
  5687. &EndOfVariableData,
  5688. newPathStr,
  5689. ObjectName,
  5690. ClassName,
  5691. 0, // Don't have this data to write out!
  5692. ModificationTime,
  5693. SubordinateCount,
  5694. NumberOfAttributes,
  5695. lpAttributeInfos );
  5696. if ( newPathStr )
  5697. {
  5698. (void) LocalFree( (HLOCAL) newPathStr );
  5699. newPathStr = NULL;
  5700. }
  5701. if ( ObjectName )
  5702. {
  5703. (void) LocalFree( (HLOCAL) ObjectName );
  5704. ObjectName = NULL;
  5705. }
  5706. lpNdsBuffer->dwNumberOfIndexEntries++;
  5707. lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_CLASS_DEF );
  5708. lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_CLASS_DEF );
  5709. }
  5710. //
  5711. // If the syntax buffer was used for the index, we need to convert
  5712. // offset values to pointers
  5713. //
  5714. if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_ATTR_NAMES_VALUES )
  5715. {
  5716. for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
  5717. {
  5718. LPNDS_ATTR_INFO lpNdsAttr = (LPNDS_ATTR_INFO)
  5719. lpReplyIndex[iter].lpAttribute;
  5720. for ( iter2 = 0;
  5721. iter2 < lpReplyIndex[iter].dwNumberOfAttributes;
  5722. iter2++ )
  5723. {
  5724. lpNdsAttr[iter2].lpValue += (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
  5725. }
  5726. }
  5727. }
  5728. #if DBG
  5729. if ( lpNdsBuffer->dwLengthOfIndexData > lpNdsBuffer->dwIndexBufferSize )
  5730. {
  5731. KdPrint(( "ASSERT in NDS32: IndexSearchObjectReplyBuffer\n" ));
  5732. KdPrint(( " lpNdsBuffer->dwLengthOfIndexData >\n" ));
  5733. KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
  5734. ASSERT( FALSE );
  5735. }
  5736. #endif
  5737. return NO_ERROR;
  5738. }
  5739. DWORD
  5740. SizeOfASN1Structure(
  5741. LPBYTE * lppRawBuffer,
  5742. DWORD dwSyntaxId )
  5743. {
  5744. DWORD dwSize = 0;
  5745. DWORD numFields = 0;
  5746. DWORD StringLen = 0;
  5747. DWORD dwBlobLength = 0;
  5748. LPBYTE lpBlobBeginning = NULL;
  5749. LPBYTE lpRawBuffer = *lppRawBuffer;
  5750. switch ( dwSyntaxId )
  5751. {
  5752. case NDS_SYNTAX_ID_1 :
  5753. dwSize = sizeof(ASN1_TYPE_1);
  5754. break;
  5755. case NDS_SYNTAX_ID_2 :
  5756. dwSize = sizeof(ASN1_TYPE_2);
  5757. break;
  5758. case NDS_SYNTAX_ID_3 :
  5759. dwSize = sizeof(ASN1_TYPE_3);
  5760. break;
  5761. case NDS_SYNTAX_ID_4 :
  5762. dwSize = sizeof(ASN1_TYPE_4);
  5763. break;
  5764. case NDS_SYNTAX_ID_5 :
  5765. dwSize = sizeof(ASN1_TYPE_5);
  5766. break;
  5767. case NDS_SYNTAX_ID_6 :
  5768. numFields = *(LPDWORD)(lpRawBuffer + sizeof(DWORD));
  5769. dwSize = sizeof(ASN1_TYPE_6)*numFields;
  5770. break;
  5771. case NDS_SYNTAX_ID_7 :
  5772. dwSize = sizeof(ASN1_TYPE_7);
  5773. break;
  5774. case NDS_SYNTAX_ID_8 :
  5775. dwSize = sizeof(ASN1_TYPE_8);
  5776. break;
  5777. case NDS_SYNTAX_ID_9 :
  5778. dwSize = sizeof(ASN1_TYPE_9);
  5779. break;
  5780. case NDS_SYNTAX_ID_10 :
  5781. dwSize = sizeof(ASN1_TYPE_10);
  5782. break;
  5783. case NDS_SYNTAX_ID_11 :
  5784. dwSize = sizeof(ASN1_TYPE_11);
  5785. break;
  5786. case NDS_SYNTAX_ID_12 :
  5787. dwSize = sizeof(ASN1_TYPE_12);
  5788. break;
  5789. case NDS_SYNTAX_ID_13 :
  5790. dwSize = sizeof(ASN1_TYPE_13);
  5791. break;
  5792. case NDS_SYNTAX_ID_14 :
  5793. dwSize = sizeof(ASN1_TYPE_14);
  5794. break;
  5795. case NDS_SYNTAX_ID_15 :
  5796. dwSize = sizeof(ASN1_TYPE_15);
  5797. break;
  5798. case NDS_SYNTAX_ID_16 :
  5799. lpBlobBeginning = lpRawBuffer;
  5800. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  5801. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  5802. lpRawBuffer += sizeof(DWORD);
  5803. StringLen = *(LPDWORD)lpRawBuffer;
  5804. lpRawBuffer += sizeof(DWORD);
  5805. //
  5806. // Skip past ServerName
  5807. //
  5808. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5809. //
  5810. // Skip past ReplicaType
  5811. //
  5812. lpRawBuffer += sizeof(DWORD);
  5813. //
  5814. // Skip past ReplicaNumber
  5815. //
  5816. lpRawBuffer += sizeof(DWORD);
  5817. //
  5818. // Store address count and move past it
  5819. //
  5820. numFields = *(LPDWORD)lpRawBuffer;
  5821. lpRawBuffer += sizeof(DWORD);
  5822. dwSize = sizeof(ASN1_TYPE_16) - sizeof(ASN1_TYPE_12) +
  5823. ( numFields * sizeof(ASN1_TYPE_12) );
  5824. *lppRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  5825. break;
  5826. case NDS_SYNTAX_ID_17 :
  5827. dwSize = sizeof(ASN1_TYPE_17);
  5828. break;
  5829. case NDS_SYNTAX_ID_18 :
  5830. dwSize = sizeof(ASN1_TYPE_18);
  5831. break;
  5832. case NDS_SYNTAX_ID_19 :
  5833. dwSize = sizeof(ASN1_TYPE_19);
  5834. break;
  5835. case NDS_SYNTAX_ID_20 :
  5836. dwSize = sizeof(ASN1_TYPE_20);
  5837. break;
  5838. case NDS_SYNTAX_ID_21 :
  5839. dwSize = sizeof(ASN1_TYPE_21);
  5840. break;
  5841. case NDS_SYNTAX_ID_22 :
  5842. dwSize = sizeof(ASN1_TYPE_22);
  5843. break;
  5844. case NDS_SYNTAX_ID_23 :
  5845. dwSize = sizeof(ASN1_TYPE_23);
  5846. break;
  5847. case NDS_SYNTAX_ID_24 :
  5848. dwSize = sizeof(ASN1_TYPE_24);
  5849. break;
  5850. case NDS_SYNTAX_ID_25 :
  5851. dwSize = sizeof(ASN1_TYPE_25);
  5852. break;
  5853. case NDS_SYNTAX_ID_26 :
  5854. dwSize = sizeof(ASN1_TYPE_26);
  5855. break;
  5856. case NDS_SYNTAX_ID_27 :
  5857. dwSize = sizeof(ASN1_TYPE_27);
  5858. break;
  5859. default :
  5860. KdPrint(( "NDS32: SizeOfASN1Structure() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
  5861. ASSERT( FALSE );
  5862. }
  5863. return dwSize;
  5864. }
  5865. DWORD
  5866. ParseASN1ValueBlob(
  5867. LPBYTE RawDataBuffer,
  5868. DWORD dwSyntaxId,
  5869. DWORD dwNumberOfValues,
  5870. LPBYTE SyntaxStructure )
  5871. {
  5872. DWORD iter;
  5873. DWORD i;
  5874. DWORD length = 0;
  5875. LPBYTE lpRawBuffer = RawDataBuffer;
  5876. LPBYTE lpSyntaxBuffer = SyntaxStructure;
  5877. DWORD StringLen;
  5878. DWORD numFields;
  5879. DWORD dwBlobLength;
  5880. LPBYTE lpBlobBeginning;
  5881. for ( iter = 0; iter < dwNumberOfValues; iter++ )
  5882. {
  5883. switch ( dwSyntaxId )
  5884. {
  5885. case NDS_SYNTAX_ID_0 :
  5886. break;
  5887. case NDS_SYNTAX_ID_1 :
  5888. case NDS_SYNTAX_ID_2 :
  5889. case NDS_SYNTAX_ID_3 :
  5890. case NDS_SYNTAX_ID_4 :
  5891. case NDS_SYNTAX_ID_5 :
  5892. case NDS_SYNTAX_ID_10 :
  5893. case NDS_SYNTAX_ID_20 :
  5894. StringLen = *(LPDWORD)lpRawBuffer;
  5895. length += sizeof(DWORD);
  5896. lpRawBuffer += sizeof(DWORD);
  5897. ((LPASN1_TYPE_1) lpSyntaxBuffer)->DNString =
  5898. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  5899. lpSyntaxBuffer += sizeof(ASN1_TYPE_1);
  5900. length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5901. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5902. break;
  5903. case NDS_SYNTAX_ID_6 :
  5904. lpBlobBeginning = lpRawBuffer;
  5905. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  5906. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  5907. lpRawBuffer += sizeof(DWORD);
  5908. numFields = *(LPDWORD)lpRawBuffer;
  5909. lpRawBuffer += sizeof(DWORD);
  5910. for ( iter = 0; iter < numFields; iter++ )
  5911. {
  5912. StringLen = *(LPDWORD)lpRawBuffer;
  5913. lpRawBuffer += sizeof(DWORD);
  5914. ((LPASN1_TYPE_6) lpSyntaxBuffer)->String =
  5915. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  5916. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5917. if ( (iter+1) < numFields )
  5918. {
  5919. ((LPASN1_TYPE_6) lpSyntaxBuffer)->Next =
  5920. (LPASN1_TYPE_6)
  5921. (lpSyntaxBuffer +
  5922. sizeof(ASN1_TYPE_6) );
  5923. }
  5924. else
  5925. {
  5926. ((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = NULL;
  5927. }
  5928. lpSyntaxBuffer += sizeof(ASN1_TYPE_6);
  5929. }
  5930. length += dwBlobLength + sizeof(DWORD);
  5931. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  5932. break;
  5933. case NDS_SYNTAX_ID_7 :
  5934. StringLen = *(LPDWORD)lpRawBuffer;
  5935. length += sizeof(DWORD);
  5936. lpRawBuffer += sizeof(DWORD);
  5937. ASSERT( StringLen == 1 ); // Booleans are sent as a single
  5938. // element DWORD array on the net.
  5939. // Although booleans are only the
  5940. // first single byte value.
  5941. ((LPASN1_TYPE_7) lpSyntaxBuffer)->Boolean = *(LPDWORD)lpRawBuffer;
  5942. lpSyntaxBuffer += sizeof(ASN1_TYPE_7);
  5943. length += StringLen*sizeof(DWORD);
  5944. lpRawBuffer += StringLen*sizeof(DWORD);
  5945. break;
  5946. case NDS_SYNTAX_ID_8 :
  5947. case NDS_SYNTAX_ID_22 :
  5948. case NDS_SYNTAX_ID_24 :
  5949. case NDS_SYNTAX_ID_27 :
  5950. StringLen = *(LPDWORD)lpRawBuffer;
  5951. length += sizeof(DWORD);
  5952. lpRawBuffer += sizeof(DWORD);
  5953. ASSERT( StringLen == 4 ); // These DWORD values are all sent
  5954. // as a 4 element BYTE array on
  5955. // the net.
  5956. ((LPASN1_TYPE_8) lpSyntaxBuffer)->Integer =
  5957. *(LPDWORD)lpRawBuffer;
  5958. lpSyntaxBuffer += sizeof(ASN1_TYPE_8);
  5959. length += StringLen*sizeof(BYTE);
  5960. lpRawBuffer += StringLen*sizeof(BYTE);
  5961. break;
  5962. case NDS_SYNTAX_ID_9 :
  5963. StringLen = *(LPDWORD)lpRawBuffer;
  5964. length += sizeof(DWORD);
  5965. lpRawBuffer += sizeof(DWORD);
  5966. ((LPASN1_TYPE_9) lpSyntaxBuffer)->Length = StringLen;
  5967. ((LPASN1_TYPE_9) lpSyntaxBuffer)->OctetString =
  5968. StringLen == 0 ? NULL : lpRawBuffer;
  5969. lpSyntaxBuffer += sizeof(ASN1_TYPE_9);
  5970. length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5971. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5972. break;
  5973. case NDS_SYNTAX_ID_11 :
  5974. lpBlobBeginning = lpRawBuffer;
  5975. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  5976. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  5977. lpRawBuffer += sizeof(DWORD);
  5978. StringLen = *(LPDWORD)lpRawBuffer;
  5979. lpRawBuffer += sizeof(DWORD);
  5980. ((LPASN1_TYPE_11) lpSyntaxBuffer)->TelephoneNumber =
  5981. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  5982. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  5983. ((LPASN1_TYPE_11) lpSyntaxBuffer)->NumberOfBits =
  5984. *(LPDWORD)lpRawBuffer;
  5985. if ( ((LPASN1_TYPE_11) lpSyntaxBuffer)->NumberOfBits )
  5986. {
  5987. lpRawBuffer += sizeof(DWORD);
  5988. ((LPASN1_TYPE_11) lpSyntaxBuffer)->Parameters = lpRawBuffer;
  5989. }
  5990. else
  5991. {
  5992. ((LPASN1_TYPE_11) lpSyntaxBuffer)->Parameters = NULL;
  5993. }
  5994. lpSyntaxBuffer += sizeof(ASN1_TYPE_11);
  5995. length += dwBlobLength + sizeof(DWORD);
  5996. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  5997. break;
  5998. case NDS_SYNTAX_ID_12 :
  5999. lpBlobBeginning = lpRawBuffer;
  6000. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6001. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6002. lpRawBuffer += sizeof(DWORD);
  6003. ((LPASN1_TYPE_12) lpSyntaxBuffer)->AddressType =
  6004. *(LPDWORD)lpRawBuffer;
  6005. lpRawBuffer += sizeof(DWORD);
  6006. StringLen = *(LPDWORD)lpRawBuffer;
  6007. ((LPASN1_TYPE_12) lpSyntaxBuffer)->AddressLength = StringLen;
  6008. lpRawBuffer += sizeof(DWORD);
  6009. ((LPASN1_TYPE_12) lpSyntaxBuffer)->Address =
  6010. StringLen == 0 ? NULL : lpRawBuffer;
  6011. lpSyntaxBuffer += sizeof(ASN1_TYPE_12);
  6012. length += dwBlobLength + sizeof(DWORD);
  6013. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6014. break;
  6015. case NDS_SYNTAX_ID_13 :
  6016. #if DBG
  6017. KdPrint(( "NDS32: ParseASN1ValueBlob() - Don't know how to parse SyntaxId 0x%.8X. Get a sniff and give it to GlennC.\n", dwSyntaxId ));
  6018. ASSERT( FALSE );
  6019. #endif
  6020. break;
  6021. case NDS_SYNTAX_ID_14 :
  6022. lpBlobBeginning = lpRawBuffer;
  6023. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6024. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6025. lpRawBuffer += sizeof(DWORD);
  6026. ((LPASN1_TYPE_14) lpSyntaxBuffer)->Type =
  6027. *(LPDWORD)lpRawBuffer;
  6028. lpRawBuffer += sizeof(DWORD);
  6029. StringLen = *(LPDWORD)lpRawBuffer;
  6030. lpRawBuffer += sizeof(DWORD);
  6031. ((LPASN1_TYPE_14) lpSyntaxBuffer)->Address =
  6032. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6033. lpSyntaxBuffer += sizeof(ASN1_TYPE_14);
  6034. length += dwBlobLength + sizeof(DWORD);
  6035. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6036. break;
  6037. case NDS_SYNTAX_ID_15 :
  6038. lpBlobBeginning = lpRawBuffer;
  6039. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6040. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6041. lpRawBuffer += sizeof(DWORD);
  6042. ((LPASN1_TYPE_15) lpSyntaxBuffer)->Type =
  6043. *(LPDWORD)lpRawBuffer;
  6044. lpRawBuffer += sizeof(DWORD);
  6045. StringLen = *(LPDWORD)lpRawBuffer;
  6046. lpRawBuffer += sizeof(DWORD);
  6047. ((LPASN1_TYPE_15) lpSyntaxBuffer)->VolumeName =
  6048. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6049. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6050. StringLen = *(LPDWORD)lpRawBuffer;
  6051. lpRawBuffer += sizeof(DWORD);
  6052. ((LPASN1_TYPE_15) lpSyntaxBuffer)->Path =
  6053. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6054. lpSyntaxBuffer += sizeof(ASN1_TYPE_15);
  6055. length += dwBlobLength + sizeof(DWORD);
  6056. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6057. break;
  6058. case NDS_SYNTAX_ID_16 :
  6059. lpBlobBeginning = lpRawBuffer;
  6060. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6061. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6062. lpRawBuffer += sizeof(DWORD);
  6063. StringLen = *(LPDWORD)lpRawBuffer;
  6064. lpRawBuffer += sizeof(DWORD);
  6065. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ServerName =
  6066. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6067. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6068. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaType =
  6069. *(LPDWORD)lpRawBuffer;
  6070. lpRawBuffer += sizeof(DWORD);
  6071. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaNumber =
  6072. *(LPDWORD)lpRawBuffer;
  6073. lpRawBuffer += sizeof(DWORD);
  6074. ((LPASN1_TYPE_16) lpSyntaxBuffer)->Count =
  6075. *(LPDWORD)lpRawBuffer;
  6076. lpRawBuffer += sizeof(DWORD);
  6077. for ( i=0; i < ((LPASN1_TYPE_16) lpSyntaxBuffer)->Count; i++ )
  6078. {
  6079. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].AddressType = *(LPDWORD)lpRawBuffer;
  6080. lpRawBuffer += sizeof(DWORD);
  6081. StringLen = *(LPDWORD)lpRawBuffer;
  6082. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].AddressLength = StringLen;
  6083. lpRawBuffer += sizeof(DWORD);
  6084. ((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].Address = StringLen == 0 ? NULL : lpRawBuffer;
  6085. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6086. }
  6087. lpSyntaxBuffer += sizeof(ASN1_TYPE_16) -
  6088. sizeof(ASN1_TYPE_12) +
  6089. ( ((LPASN1_TYPE_16) lpSyntaxBuffer)->Count*
  6090. sizeof(ASN1_TYPE_12) );
  6091. length += dwBlobLength + sizeof(DWORD);
  6092. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6093. break;
  6094. case NDS_SYNTAX_ID_17 :
  6095. lpBlobBeginning = lpRawBuffer;
  6096. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6097. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6098. lpRawBuffer += sizeof(DWORD);
  6099. StringLen = *(LPDWORD)lpRawBuffer;
  6100. lpRawBuffer += sizeof(DWORD);
  6101. ((LPASN1_TYPE_17) lpSyntaxBuffer)->ProtectedAttrName =
  6102. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6103. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6104. StringLen = *(LPDWORD)lpRawBuffer;
  6105. lpRawBuffer += sizeof(DWORD);
  6106. ((LPASN1_TYPE_17) lpSyntaxBuffer)->SubjectName =
  6107. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6108. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6109. ((LPASN1_TYPE_17) lpSyntaxBuffer)->Privileges =
  6110. *(LPDWORD)lpRawBuffer;
  6111. lpSyntaxBuffer += sizeof(ASN1_TYPE_17);
  6112. length += dwBlobLength + sizeof(DWORD);
  6113. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6114. break;
  6115. case NDS_SYNTAX_ID_18 :
  6116. lpBlobBeginning = lpRawBuffer;
  6117. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6118. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6119. lpRawBuffer += sizeof(DWORD);
  6120. numFields = *(LPDWORD)lpRawBuffer;
  6121. lpRawBuffer += sizeof(DWORD);
  6122. for ( i = 0; i < numFields; i++ )
  6123. {
  6124. StringLen = *(LPDWORD)lpRawBuffer;
  6125. lpRawBuffer += sizeof(DWORD);
  6126. ((LPASN1_TYPE_18) lpSyntaxBuffer)->PostalAddress[i] =
  6127. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6128. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6129. }
  6130. lpSyntaxBuffer += sizeof(ASN1_TYPE_18);
  6131. length += dwBlobLength + sizeof(DWORD);
  6132. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6133. break;
  6134. case NDS_SYNTAX_ID_19 :
  6135. lpBlobBeginning = lpRawBuffer;
  6136. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6137. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6138. lpRawBuffer += sizeof(DWORD);
  6139. ((LPASN1_TYPE_19) lpSyntaxBuffer)->WholeSeconds =
  6140. *(LPDWORD)lpRawBuffer;
  6141. lpRawBuffer += sizeof(DWORD);
  6142. ((LPASN1_TYPE_19) lpSyntaxBuffer)->EventID =
  6143. *(LPDWORD)lpRawBuffer;
  6144. lpRawBuffer += sizeof(DWORD);
  6145. lpSyntaxBuffer += sizeof(ASN1_TYPE_19);
  6146. length += dwBlobLength + sizeof(DWORD);
  6147. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6148. break;
  6149. case NDS_SYNTAX_ID_21 :
  6150. ((LPASN1_TYPE_21) lpSyntaxBuffer)->Length =
  6151. *(LPDWORD)lpRawBuffer;
  6152. lpSyntaxBuffer += sizeof(ASN1_TYPE_21);
  6153. length += sizeof(DWORD);
  6154. lpRawBuffer += sizeof(DWORD);
  6155. break;
  6156. case NDS_SYNTAX_ID_23 :
  6157. lpBlobBeginning = lpRawBuffer;
  6158. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6159. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6160. lpRawBuffer += sizeof(DWORD);
  6161. ((LPASN1_TYPE_23) lpSyntaxBuffer)->RemoteID =
  6162. *(LPDWORD)lpRawBuffer;
  6163. lpRawBuffer += sizeof(DWORD);
  6164. StringLen = *(LPDWORD)lpRawBuffer;
  6165. lpRawBuffer += sizeof(DWORD);
  6166. ((LPASN1_TYPE_23) lpSyntaxBuffer)->ObjectName =
  6167. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6168. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6169. lpSyntaxBuffer += sizeof(ASN1_TYPE_23);
  6170. length += dwBlobLength + sizeof(DWORD);
  6171. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6172. break;
  6173. case NDS_SYNTAX_ID_25 :
  6174. lpBlobBeginning = lpRawBuffer;
  6175. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6176. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6177. lpRawBuffer += sizeof(DWORD);
  6178. ((LPASN1_TYPE_25) lpSyntaxBuffer)->Level =
  6179. *(LPDWORD)lpRawBuffer;
  6180. lpRawBuffer += sizeof(DWORD);
  6181. ((LPASN1_TYPE_25) lpSyntaxBuffer)->Interval =
  6182. *(LPDWORD)lpRawBuffer;
  6183. lpRawBuffer += sizeof(DWORD);
  6184. StringLen = *(LPDWORD)lpRawBuffer;
  6185. lpRawBuffer += sizeof(DWORD);
  6186. ((LPASN1_TYPE_25) lpSyntaxBuffer)->ObjectName =
  6187. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6188. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6189. lpSyntaxBuffer += sizeof(ASN1_TYPE_25);
  6190. length += dwBlobLength + sizeof(DWORD);
  6191. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6192. break;
  6193. case NDS_SYNTAX_ID_26 :
  6194. lpBlobBeginning = lpRawBuffer;
  6195. dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
  6196. dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
  6197. lpRawBuffer += sizeof(DWORD);
  6198. StringLen = *(LPDWORD)lpRawBuffer;
  6199. lpRawBuffer += sizeof(DWORD);
  6200. ((LPASN1_TYPE_26) lpSyntaxBuffer)->ObjectName =
  6201. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6202. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6203. ((LPASN1_TYPE_26) lpSyntaxBuffer)->Amount =
  6204. *(LPDWORD)lpRawBuffer;
  6205. lpRawBuffer += sizeof(DWORD);
  6206. lpSyntaxBuffer += sizeof(ASN1_TYPE_26);
  6207. length += dwBlobLength + sizeof(DWORD);
  6208. lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
  6209. break;
  6210. default :
  6211. #if DBG
  6212. KdPrint(( "NDS32: ParseASN1ValueBlob() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
  6213. ASSERT( FALSE );
  6214. #endif
  6215. return 0;
  6216. }
  6217. }
  6218. return length;
  6219. }
  6220. DWORD
  6221. ParseStringListBlob(
  6222. LPBYTE RawDataBuffer,
  6223. DWORD dwNumberOfStrings,
  6224. LPBYTE SyntaxStructure )
  6225. {
  6226. DWORD iter;
  6227. DWORD length = 0;
  6228. LPBYTE lpRawBuffer = RawDataBuffer;
  6229. LPBYTE lpSyntaxBuffer = SyntaxStructure;
  6230. DWORD StringLen;
  6231. for ( iter = 0; iter < dwNumberOfStrings; iter++ )
  6232. {
  6233. StringLen = *(LPDWORD)lpRawBuffer;
  6234. lpRawBuffer += sizeof(DWORD);
  6235. length += sizeof(DWORD);
  6236. ((LPASN1_TYPE_6) lpSyntaxBuffer)->String =
  6237. StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
  6238. lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6239. length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
  6240. if ( (iter+1) < dwNumberOfStrings )
  6241. {
  6242. ((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = (LPASN1_TYPE_6)
  6243. (lpSyntaxBuffer +
  6244. sizeof(ASN1_TYPE_6) );
  6245. }
  6246. else
  6247. {
  6248. ((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = NULL;
  6249. }
  6250. lpSyntaxBuffer += sizeof(ASN1_TYPE_6);
  6251. }
  6252. return length;
  6253. }
  6254. WORD
  6255. ParseNdsUncPath(
  6256. IN OUT LPWSTR * lpszResult,
  6257. IN LPWSTR szObjectPathName,
  6258. IN DWORD flag )
  6259. {
  6260. unsigned short length = 2;
  6261. unsigned short totalLength = (USHORT) wcslen( szObjectPathName );
  6262. if ( totalLength < 2 )
  6263. return 0;
  6264. //
  6265. // Get length to indicate the character in the string that indicates the
  6266. // "\" in between the tree name and the rest of the UNC path.
  6267. //
  6268. // Example: \\<tree name>\<path to object>[\|.]<object>
  6269. // ^
  6270. // |
  6271. //
  6272. while ( length < totalLength && szObjectPathName[length] != L'\\' )
  6273. {
  6274. length++;
  6275. }
  6276. if ( flag == PARSE_NDS_GET_TREE_NAME )
  6277. {
  6278. *lpszResult = (LPWSTR) ( szObjectPathName + 2 );
  6279. return ( length - 2 ) * sizeof(WCHAR); // Take off 2 for the two \\'s
  6280. }
  6281. if ( flag == PARSE_NDS_GET_PATH_NAME && length == totalLength )
  6282. {
  6283. *lpszResult = szObjectPathName;
  6284. return 0;
  6285. }
  6286. if ( flag == PARSE_NDS_GET_PATH_NAME )
  6287. {
  6288. *lpszResult = szObjectPathName + length + 1;
  6289. return ( totalLength - length - 1 ) * sizeof(WCHAR);
  6290. }
  6291. if ( flag == PARSE_NDS_GET_OBJECT_NAME )
  6292. {
  6293. unsigned short ObjectNameLength = 0;
  6294. *lpszResult = szObjectPathName + length + 1;
  6295. length++;
  6296. while ( length < totalLength && szObjectPathName[length] != L'.' )
  6297. {
  6298. length++;
  6299. ObjectNameLength++;
  6300. }
  6301. return ObjectNameLength * sizeof(WCHAR);
  6302. }
  6303. *lpszResult = szObjectPathName + totalLength - 1;
  6304. length = 1;
  6305. while ( *lpszResult[0] != L'\\' )
  6306. {
  6307. *lpszResult--;
  6308. length++;
  6309. }
  6310. *lpszResult++;
  6311. length--;
  6312. return length * sizeof(WCHAR);
  6313. }
  6314. DWORD
  6315. ReadAttrDef_AllAttrs(
  6316. IN HANDLE hTree,
  6317. IN DWORD dwInformationType,
  6318. OUT HANDLE * lphOperationData )
  6319. {
  6320. DWORD status;
  6321. DWORD nwstatus;
  6322. NTSTATUS ntstatus;
  6323. LPNDS_BUFFER lpNdsBuffer = NULL;
  6324. DWORD dwReplyLength;
  6325. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  6326. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6327. DWORD dwNumEntries = 0;
  6328. DWORD dwCurrNumEntries = 0;
  6329. DWORD dwCurrBuffSize = 0;
  6330. DWORD dwCopyOffset = 0;
  6331. PVOID lpCurrBuff = NULL;
  6332. PVOID lpTempBuff = NULL;
  6333. DWORD dwInfoType = dwInformationType;
  6334. *lphOperationData = NULL;
  6335. status = NwNdsCreateBuffer( NDS_SCHEMA_READ_ATTR_DEF,
  6336. (HANDLE *) &lpNdsBuffer );
  6337. if ( status )
  6338. {
  6339. goto ErrorExit;
  6340. }
  6341. lpNdsBuffer->lpReplyBuffer = NULL;
  6342. lpNdsBuffer->dwReplyBufferSize = 0;
  6343. //
  6344. // Reasonable guess is that the response buffer needs to be 8K bytes.
  6345. //
  6346. dwCurrBuffSize = EIGHT_KB;
  6347. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  6348. //
  6349. // Check that the memory allocation was successful.
  6350. //
  6351. if ( lpCurrBuff == NULL )
  6352. {
  6353. #if DBG
  6354. KdPrint(( "NDS32: ReadAttrDef_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6355. #endif
  6356. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6357. status = (DWORD) UNSUCCESSFUL;
  6358. goto ErrorExit;
  6359. }
  6360. do
  6361. {
  6362. SendRequest:
  6363. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  6364. NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
  6365. lpCurrBuff,
  6366. dwCurrBuffSize,
  6367. &dwReplyLength,
  6368. "DDDDD",
  6369. 0, // Version
  6370. dwIterHandle, // Initial iteration
  6371. dwInformationType,
  6372. (DWORD) TRUE, // All attributes indicator
  6373. 0 ); // Number of attribute names
  6374. if ( !NT_SUCCESS( ntstatus ) )
  6375. {
  6376. #if DBG
  6377. KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  6378. #endif
  6379. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6380. status = (DWORD) UNSUCCESSFUL;
  6381. goto ErrorExit;
  6382. }
  6383. ntstatus = ParseResponse( lpCurrBuff,
  6384. dwReplyLength,
  6385. "GD",
  6386. &nwstatus );
  6387. if ( !NT_SUCCESS( ntstatus ) )
  6388. {
  6389. #if DBG
  6390. KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The read object response was undecipherable.\n" ));
  6391. #endif
  6392. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6393. status = (DWORD) UNSUCCESSFUL;
  6394. goto ErrorExit;
  6395. }
  6396. if ( nwstatus )
  6397. {
  6398. if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
  6399. {
  6400. #if DBG
  6401. KdPrint(( "NDS32: ReadAttrDef_AllAttrs - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
  6402. #endif
  6403. //
  6404. // The buffer was too small, make it twice as big.
  6405. //
  6406. if ( dwCurrBuffSize <= THIRY_TWO_KB)
  6407. { // NDS_MAX_BUFFER = 0xFC00
  6408. dwCurrBuffSize *= 2;
  6409. if (dwCurrBuffSize > NDS_MAX_BUFFER)
  6410. dwCurrBuffSize = NDS_MAX_BUFFER;
  6411. lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
  6412. if (lpTempBuff)
  6413. {
  6414. (void) LocalFree((HLOCAL) lpCurrBuff);
  6415. lpCurrBuff = lpTempBuff;
  6416. lpTempBuff = NULL;
  6417. // Error cancels iteration, so reset any previously read responses and start over
  6418. dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6419. if (lpNdsBuffer->lpReplyBuffer)
  6420. {
  6421. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6422. lpNdsBuffer->lpReplyBuffer = NULL;
  6423. lpNdsBuffer->dwReplyBufferSize = 0;
  6424. dwNumEntries = 0;
  6425. }
  6426. goto SendRequest;
  6427. }
  6428. #if DBG
  6429. else {
  6430. KdPrint(( "NDS32: ReadAttrDef_AllAttrs - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
  6431. }
  6432. #endif
  6433. }
  6434. }
  6435. #if DBG
  6436. KdPrint(( "NDS32: ReadAttrDef_AllAttrs - NetWare error 0x%.8X.\n", nwstatus ));
  6437. #endif
  6438. SetLastError( MapNetwareErrorCode( nwstatus ) );
  6439. status = nwstatus;
  6440. goto ErrorExit;
  6441. }
  6442. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  6443. dwReplyLength,
  6444. "G_DDD",
  6445. sizeof(DWORD),
  6446. &dwIterHandle,
  6447. &dwInfoType,
  6448. &dwCurrNumEntries );
  6449. if ( !NT_SUCCESS( ntstatus ) )
  6450. {
  6451. #if DBG
  6452. KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The read object response was undecipherable.\n" ));
  6453. #endif
  6454. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6455. status = (DWORD) UNSUCCESSFUL;
  6456. goto ErrorExit;
  6457. }
  6458. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  6459. {
  6460. dwCopyOffset = 0; // we want the entire buffer the first time
  6461. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  6462. }
  6463. else
  6464. {
  6465. #if DBG
  6466. KdPrint(( "NDS32: ReadAttrDef_AllAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  6467. #endif
  6468. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  6469. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  6470. // grow reply buffer to hold additional data
  6471. if (lpTempBuff)
  6472. {
  6473. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  6474. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6475. }
  6476. }
  6477. if (lpTempBuff == NULL)
  6478. {
  6479. #if DBG
  6480. KdPrint(( "NDS32: ReadAttrDef_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6481. #endif
  6482. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6483. status = (DWORD) UNSUCCESSFUL;
  6484. goto ErrorExit;
  6485. }
  6486. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  6487. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  6488. (dwCurrBuffSize - dwCopyOffset) );
  6489. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  6490. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  6491. dwNumEntries += dwCurrNumEntries;
  6492. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  6493. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  6494. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  6495. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  6496. *lphOperationData = lpNdsBuffer;
  6497. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6498. return NO_ERROR;
  6499. ErrorExit :
  6500. if ( lpCurrBuff )
  6501. {
  6502. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6503. lpCurrBuff = NULL;
  6504. }
  6505. if ( lpNdsBuffer )
  6506. {
  6507. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  6508. lpNdsBuffer = NULL;
  6509. }
  6510. return status;
  6511. }
  6512. DWORD
  6513. ReadAttrDef_SomeAttrs(
  6514. IN HANDLE hTree,
  6515. IN DWORD dwInformationType,
  6516. IN OUT HANDLE * lphOperationData )
  6517. {
  6518. DWORD status;
  6519. DWORD nwstatus;
  6520. NTSTATUS ntstatus;
  6521. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
  6522. DWORD dwReplyLength;
  6523. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  6524. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6525. DWORD dwInfoType = dwInformationType;
  6526. DWORD dwNumEntries = 0;
  6527. DWORD dwCurrNumEntries = 0;
  6528. DWORD dwCurrBuffSize = 0;
  6529. DWORD dwCopyOffset = 0;
  6530. PVOID lpCurrBuff = NULL;
  6531. PVOID lpTempBuff = NULL;
  6532. if ( lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_ATTR_DEF )
  6533. {
  6534. SetLastError( ERROR_INVALID_PARAMETER );
  6535. return (DWORD) UNSUCCESSFUL;
  6536. }
  6537. //
  6538. // Check to see if this buffer has already been used for a read reply.
  6539. //
  6540. if ( lpNdsBuffer->lpReplyBuffer )
  6541. {
  6542. SetLastError( ERROR_INVALID_PARAMETER );
  6543. return (DWORD) UNSUCCESSFUL;
  6544. }
  6545. lpNdsBuffer->dwReplyBufferSize = 0;
  6546. //
  6547. // Reasonable guess is that the response buffer needs to be 8K bytes.
  6548. //
  6549. dwCurrBuffSize = EIGHT_KB;
  6550. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  6551. //
  6552. // Check that the memory allocation was successful.
  6553. //
  6554. if ( lpCurrBuff == NULL )
  6555. {
  6556. #if DBG
  6557. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6558. #endif
  6559. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6560. status = (DWORD) UNSUCCESSFUL;
  6561. goto ErrorExit;
  6562. }
  6563. do
  6564. {
  6565. SendRequest:
  6566. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  6567. NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
  6568. lpCurrBuff,
  6569. dwCurrBuffSize,
  6570. &dwReplyLength,
  6571. "DDDDDr",
  6572. 0, // Version
  6573. dwIterHandle, // Initial iteration
  6574. dwInformationType,
  6575. (DWORD) FALSE, // All attributes indicator
  6576. lpNdsBuffer->dwNumberOfRequestEntries,
  6577. lpNdsBuffer->lpRequestBuffer,
  6578. (WORD)lpNdsBuffer->dwLengthOfRequestData );
  6579. if ( !NT_SUCCESS( ntstatus ) )
  6580. {
  6581. #if DBG
  6582. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  6583. #endif
  6584. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6585. status = (DWORD) UNSUCCESSFUL;
  6586. goto ErrorExit;
  6587. }
  6588. ntstatus = ParseResponse( lpCurrBuff,
  6589. dwReplyLength,
  6590. "GD",
  6591. &nwstatus );
  6592. if ( !NT_SUCCESS( ntstatus ) )
  6593. {
  6594. #if DBG
  6595. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  6596. #endif
  6597. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6598. status = (DWORD) UNSUCCESSFUL;
  6599. goto ErrorExit;
  6600. }
  6601. if ( nwstatus )
  6602. {
  6603. if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
  6604. {
  6605. #if DBG
  6606. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
  6607. #endif
  6608. //
  6609. // The buffer was too small, make it twice as big.
  6610. //
  6611. if ( dwCurrBuffSize <= THIRY_TWO_KB)
  6612. { // NDS_MAX_BUFFER = 0xFC00
  6613. dwCurrBuffSize *= 2;
  6614. if (dwCurrBuffSize > NDS_MAX_BUFFER)
  6615. dwCurrBuffSize = NDS_MAX_BUFFER;
  6616. lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
  6617. if (lpTempBuff)
  6618. {
  6619. (void) LocalFree((HLOCAL) lpCurrBuff);
  6620. lpCurrBuff = lpTempBuff;
  6621. lpTempBuff = NULL;
  6622. // Error cancels iteration, so reset any previously read responses and start over
  6623. dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6624. if (lpNdsBuffer->lpReplyBuffer)
  6625. {
  6626. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6627. lpNdsBuffer->lpReplyBuffer = NULL;
  6628. lpNdsBuffer->dwReplyBufferSize = 0;
  6629. dwNumEntries = 0;
  6630. }
  6631. goto SendRequest;
  6632. }
  6633. #if DBG
  6634. else {
  6635. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
  6636. }
  6637. #endif
  6638. }
  6639. }
  6640. #if DBG
  6641. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - NetWare error 0x%.8X.\n", nwstatus ));
  6642. #endif
  6643. SetLastError( MapNetwareErrorCode( nwstatus ) );
  6644. status = nwstatus;
  6645. goto ErrorExit;
  6646. }
  6647. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  6648. dwReplyLength,
  6649. "G_DDD",
  6650. sizeof(DWORD),
  6651. &dwIterHandle,
  6652. &dwInfoType,
  6653. &dwCurrNumEntries );
  6654. if ( !NT_SUCCESS( ntstatus ) )
  6655. {
  6656. #if DBG
  6657. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  6658. #endif
  6659. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6660. status = (DWORD) UNSUCCESSFUL;
  6661. goto ErrorExit;
  6662. }
  6663. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  6664. {
  6665. dwCopyOffset = 0; // we want the entire buffer the first time
  6666. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  6667. }
  6668. else
  6669. {
  6670. #if DBG
  6671. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  6672. #endif
  6673. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  6674. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  6675. // grow reply buffer to hold additional data
  6676. if (lpTempBuff)
  6677. {
  6678. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  6679. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6680. }
  6681. }
  6682. if (lpTempBuff == NULL)
  6683. {
  6684. #if DBG
  6685. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6686. #endif
  6687. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6688. status = (DWORD) UNSUCCESSFUL;
  6689. goto ErrorExit;
  6690. }
  6691. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  6692. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  6693. (dwCurrBuffSize - dwCopyOffset) );
  6694. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  6695. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  6696. dwNumEntries += dwCurrNumEntries;
  6697. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  6698. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  6699. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  6700. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  6701. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6702. return NO_ERROR;
  6703. ErrorExit :
  6704. if ( lpCurrBuff )
  6705. {
  6706. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6707. lpCurrBuff = NULL;
  6708. }
  6709. if ( lpNdsBuffer->lpReplyBuffer )
  6710. {
  6711. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  6712. lpNdsBuffer->lpReplyBuffer = NULL;
  6713. lpNdsBuffer->dwReplyBufferSize = 0;
  6714. }
  6715. return status;
  6716. }
  6717. DWORD
  6718. ReadClassDef_AllClasses(
  6719. IN HANDLE hTree,
  6720. IN DWORD dwInformationType,
  6721. OUT HANDLE * lphOperationData )
  6722. {
  6723. DWORD status;
  6724. DWORD nwstatus;
  6725. NTSTATUS ntstatus;
  6726. LPNDS_BUFFER lpNdsBuffer = NULL;
  6727. DWORD dwReplyLength;
  6728. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  6729. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6730. DWORD dwNumEntries = 0;
  6731. DWORD dwCurrNumEntries = 0;
  6732. DWORD dwCurrBuffSize = 0;
  6733. DWORD dwCopyOffset = 0;
  6734. PVOID lpCurrBuff = NULL;
  6735. PVOID lpTempBuff = NULL;
  6736. DWORD dwInfoType = dwInformationType;
  6737. *lphOperationData = NULL;
  6738. status = NwNdsCreateBuffer( NDS_SCHEMA_READ_CLASS_DEF,
  6739. (HANDLE *) &lpNdsBuffer );
  6740. if ( status )
  6741. {
  6742. goto ErrorExit;
  6743. }
  6744. lpNdsBuffer->lpReplyBuffer = NULL;
  6745. lpNdsBuffer->dwReplyBufferSize = 0;
  6746. //
  6747. // Reasonable guess is that the response buffer needs to be 16K bytes.
  6748. //
  6749. dwCurrBuffSize = SIXTEEN_KB;
  6750. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  6751. //
  6752. // Check that the memory allocation was successful.
  6753. //
  6754. if ( lpCurrBuff == NULL )
  6755. {
  6756. #if DBG
  6757. KdPrint(( "NDS32: ReadClassDef_AllClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6758. #endif
  6759. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6760. status = (DWORD) UNSUCCESSFUL;
  6761. goto ErrorExit;
  6762. }
  6763. do
  6764. {
  6765. SendRequest:
  6766. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  6767. NETWARE_NDS_FUNCTION_READ_CLASS_DEF,
  6768. lpCurrBuff,
  6769. dwCurrBuffSize,
  6770. &dwReplyLength,
  6771. "DDDDD",
  6772. 0, // Version
  6773. dwIterHandle, // Initial iteration
  6774. dwInformationType,
  6775. (DWORD) TRUE, // All attributes indicator
  6776. 0 ); // Number of attribute names
  6777. if ( !NT_SUCCESS( ntstatus ) )
  6778. {
  6779. #if DBG
  6780. KdPrint(( "NDS32: ReadClassDef_AllClasses: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  6781. #endif
  6782. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6783. status = (DWORD) UNSUCCESSFUL;
  6784. goto ErrorExit;
  6785. }
  6786. ntstatus = ParseResponse( lpCurrBuff,
  6787. dwReplyLength,
  6788. "GD",
  6789. &nwstatus );
  6790. if ( !NT_SUCCESS( ntstatus ) )
  6791. {
  6792. #if DBG
  6793. KdPrint(( "NDS32: ReadClassDef_AllClasses: The read response was undecipherable.\n" ));
  6794. #endif
  6795. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6796. status = (DWORD) UNSUCCESSFUL;
  6797. goto ErrorExit;
  6798. }
  6799. if ( nwstatus )
  6800. {
  6801. if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
  6802. {
  6803. #if DBG
  6804. KdPrint(( "NDS32: ReadClassDef_AllClasses - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
  6805. #endif
  6806. //
  6807. // The buffer was too small, make it twice as big.
  6808. //
  6809. if ( dwCurrBuffSize <= THIRY_TWO_KB)
  6810. { // NDS_MAX_BUFFER = 0xFC00
  6811. dwCurrBuffSize *= 2;
  6812. if (dwCurrBuffSize > NDS_MAX_BUFFER)
  6813. dwCurrBuffSize = NDS_MAX_BUFFER;
  6814. lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
  6815. if (lpTempBuff)
  6816. {
  6817. (void) LocalFree((HLOCAL) lpCurrBuff);
  6818. lpCurrBuff = lpTempBuff;
  6819. lpTempBuff = NULL;
  6820. // Error cancels iteration, so reset any previously read responses and start over
  6821. dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6822. if (lpNdsBuffer->lpReplyBuffer)
  6823. {
  6824. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6825. lpNdsBuffer->lpReplyBuffer = NULL;
  6826. lpNdsBuffer->dwReplyBufferSize = 0;
  6827. dwNumEntries = 0;
  6828. }
  6829. goto SendRequest;
  6830. }
  6831. #if DBG
  6832. else {
  6833. KdPrint(( "NDS32: ReadClassDef_AllClasses - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
  6834. }
  6835. #endif
  6836. }
  6837. }
  6838. #if DBG
  6839. KdPrint(( "NDS32: ReadClassDef_AllClasses - NetWare error 0x%.8X.\n", nwstatus ));
  6840. #endif
  6841. SetLastError( MapNetwareErrorCode( nwstatus ) );
  6842. status = nwstatus;
  6843. goto ErrorExit;
  6844. }
  6845. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  6846. dwReplyLength,
  6847. "G_DDD",
  6848. sizeof(DWORD),
  6849. &dwIterHandle,
  6850. &dwInfoType,
  6851. &dwCurrNumEntries );
  6852. if ( !NT_SUCCESS( ntstatus ) )
  6853. {
  6854. #if DBG
  6855. KdPrint(( "NDS32: ReadClassDef_AllClasses: The read object response was undecipherable.\n" ));
  6856. #endif
  6857. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6858. status = (DWORD) UNSUCCESSFUL;
  6859. goto ErrorExit;
  6860. }
  6861. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  6862. {
  6863. dwCopyOffset = 0; // we want the entire buffer the first time
  6864. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  6865. }
  6866. else
  6867. {
  6868. #if DBG
  6869. KdPrint(( "NDS32: ReadClassDef_AllClasses - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  6870. #endif
  6871. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  6872. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  6873. // grow reply buffer to hold additional data
  6874. if (lpTempBuff)
  6875. {
  6876. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  6877. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  6878. }
  6879. }
  6880. if (lpTempBuff == NULL)
  6881. {
  6882. #if DBG
  6883. KdPrint(( "NDS32: ReadClassDef_AllClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6884. #endif
  6885. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6886. status = (DWORD) UNSUCCESSFUL;
  6887. goto ErrorExit;
  6888. }
  6889. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  6890. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  6891. (dwCurrBuffSize - dwCopyOffset) );
  6892. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  6893. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  6894. dwNumEntries += dwCurrNumEntries;
  6895. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  6896. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  6897. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  6898. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  6899. *lphOperationData = lpNdsBuffer;
  6900. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6901. return NO_ERROR;
  6902. ErrorExit :
  6903. if ( lpCurrBuff )
  6904. {
  6905. (void) LocalFree( (HLOCAL) lpCurrBuff );
  6906. lpCurrBuff = NULL;
  6907. }
  6908. if ( lpNdsBuffer )
  6909. {
  6910. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  6911. lpNdsBuffer = NULL;
  6912. }
  6913. return status;
  6914. }
  6915. DWORD
  6916. ReadClassDef_SomeClasses(
  6917. IN HANDLE hTree,
  6918. IN DWORD dwInformationType,
  6919. IN OUT HANDLE * lphOperationData )
  6920. {
  6921. DWORD status;
  6922. DWORD nwstatus;
  6923. NTSTATUS ntstatus;
  6924. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
  6925. DWORD dwReplyLength;
  6926. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  6927. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  6928. DWORD dwInfoType = dwInformationType;
  6929. DWORD dwNumEntries = 0;
  6930. DWORD dwCurrNumEntries = 0;
  6931. DWORD dwCurrBuffSize = 0;
  6932. DWORD dwCopyOffset = 0;
  6933. PVOID lpCurrBuff = NULL;
  6934. PVOID lpTempBuff = NULL;
  6935. if ( lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_CLASS_DEF )
  6936. {
  6937. SetLastError( ERROR_INVALID_PARAMETER );
  6938. return (DWORD) UNSUCCESSFUL;
  6939. }
  6940. //
  6941. // Check to see if this buffer has already been used for a read reply.
  6942. //
  6943. if ( lpNdsBuffer->lpReplyBuffer )
  6944. {
  6945. SetLastError( ERROR_INVALID_PARAMETER );
  6946. return (DWORD) UNSUCCESSFUL;
  6947. }
  6948. lpNdsBuffer->dwReplyBufferSize = 0;
  6949. //
  6950. // Reasonable guess is that the response buffer needs to be 16K bytes.
  6951. //
  6952. dwCurrBuffSize = SIXTEEN_KB;
  6953. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  6954. //
  6955. // Check that the memory allocation was successful.
  6956. //
  6957. if ( lpCurrBuff == NULL )
  6958. {
  6959. #if DBG
  6960. KdPrint(( "NDS32: ReadClassDef_SomeClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  6961. #endif
  6962. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  6963. status = (DWORD) UNSUCCESSFUL;
  6964. goto ErrorExit;
  6965. }
  6966. do
  6967. {
  6968. SendRequest:
  6969. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  6970. NETWARE_NDS_FUNCTION_READ_CLASS_DEF,
  6971. lpCurrBuff,
  6972. dwCurrBuffSize,
  6973. &dwReplyLength,
  6974. "DDDDDr",
  6975. 0, // Version
  6976. dwIterHandle, // Initial iteration
  6977. dwInformationType,
  6978. (DWORD) FALSE, // All attributes indicator
  6979. lpNdsBuffer->dwNumberOfRequestEntries,
  6980. lpNdsBuffer->lpRequestBuffer,
  6981. (WORD)lpNdsBuffer->dwLengthOfRequestData );
  6982. if ( !NT_SUCCESS( ntstatus ) )
  6983. {
  6984. #if DBG
  6985. KdPrint(( "NDS32: ReadClassDef_SomeClasses: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  6986. #endif
  6987. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  6988. status = (DWORD) UNSUCCESSFUL;
  6989. goto ErrorExit;
  6990. }
  6991. ntstatus = ParseResponse( lpCurrBuff,
  6992. dwReplyLength,
  6993. "GD",
  6994. &nwstatus );
  6995. if ( !NT_SUCCESS( ntstatus ) )
  6996. {
  6997. #if DBG
  6998. KdPrint(( "NDS32: ReadClassDef_SomeClasses: The read object response was undecipherable.\n" ));
  6999. #endif
  7000. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7001. status = (DWORD) UNSUCCESSFUL;
  7002. goto ErrorExit;
  7003. }
  7004. if ( nwstatus )
  7005. {
  7006. if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
  7007. {
  7008. #if DBG
  7009. KdPrint(( "NDS32: ReadClassDef_SomeClasses - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
  7010. #endif
  7011. //
  7012. // The buffer was too small, make it twice as big.
  7013. //
  7014. if ( dwCurrBuffSize <= THIRY_TWO_KB)
  7015. { // NDS_MAX_BUFFER = 0xFC00
  7016. dwCurrBuffSize *= 2;
  7017. if (dwCurrBuffSize > NDS_MAX_BUFFER)
  7018. dwCurrBuffSize = NDS_MAX_BUFFER;
  7019. lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
  7020. if (lpTempBuff)
  7021. {
  7022. (void) LocalFree((HLOCAL) lpCurrBuff);
  7023. lpCurrBuff = lpTempBuff;
  7024. lpTempBuff = NULL;
  7025. // Error cancels iteration, so reset any previously read responses and start over
  7026. dwIterHandle = NDS_NO_MORE_ITERATIONS;
  7027. if (lpNdsBuffer->lpReplyBuffer)
  7028. {
  7029. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  7030. lpNdsBuffer->lpReplyBuffer = NULL;
  7031. lpNdsBuffer->dwReplyBufferSize = 0;
  7032. dwNumEntries = 0;
  7033. }
  7034. goto SendRequest;
  7035. }
  7036. #if DBG
  7037. else {
  7038. KdPrint(( "NDS32: ReadClassDef_SomeClasses - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
  7039. }
  7040. #endif
  7041. }
  7042. }
  7043. #if DBG
  7044. KdPrint(( "NDS32: ReadClassDef_SomeClasses - NetWare error 0x%.8X.\n", nwstatus ));
  7045. #endif
  7046. SetLastError( MapNetwareErrorCode( nwstatus ) );
  7047. status = nwstatus;
  7048. goto ErrorExit;
  7049. }
  7050. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  7051. dwReplyLength,
  7052. "G_DDD",
  7053. sizeof(DWORD),
  7054. &dwIterHandle,
  7055. &dwInfoType,
  7056. &dwCurrNumEntries );
  7057. if ( !NT_SUCCESS( ntstatus ) )
  7058. {
  7059. #if DBG
  7060. KdPrint(( "NDS32: ReadClassDef_SomeClasses: The read object response was undecipherable.\n" ));
  7061. #endif
  7062. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7063. status = (DWORD) UNSUCCESSFUL;
  7064. goto ErrorExit;
  7065. }
  7066. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  7067. {
  7068. dwCopyOffset = 0; // we want the entire buffer the first time
  7069. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  7070. }
  7071. else
  7072. {
  7073. #if DBG
  7074. KdPrint(( "NDS32: ReadClassDef_SomeClasses - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  7075. #endif
  7076. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  7077. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  7078. // grow reply buffer to hold additional data
  7079. if (lpTempBuff)
  7080. {
  7081. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  7082. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  7083. }
  7084. }
  7085. if (lpTempBuff == NULL)
  7086. {
  7087. #if DBG
  7088. KdPrint(( "NDS32: ReadClassDef_SomeClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7089. #endif
  7090. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7091. status = (DWORD) UNSUCCESSFUL;
  7092. goto ErrorExit;
  7093. }
  7094. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  7095. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  7096. (dwCurrBuffSize - dwCopyOffset) );
  7097. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  7098. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  7099. dwNumEntries += dwCurrNumEntries;
  7100. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  7101. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  7102. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  7103. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  7104. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7105. return NO_ERROR;
  7106. ErrorExit :
  7107. if ( lpCurrBuff )
  7108. {
  7109. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7110. lpCurrBuff = NULL;
  7111. }
  7112. if ( lpNdsBuffer->lpReplyBuffer )
  7113. {
  7114. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  7115. lpNdsBuffer->lpReplyBuffer = NULL;
  7116. lpNdsBuffer->dwReplyBufferSize = 0;
  7117. }
  7118. return status;
  7119. }
  7120. DWORD
  7121. ReadObject_AllAttrs(
  7122. IN HANDLE hObject,
  7123. IN DWORD dwInformationType,
  7124. OUT HANDLE * lphOperationData )
  7125. {
  7126. DWORD status;
  7127. DWORD nwstatus;
  7128. NTSTATUS ntstatus;
  7129. LPNDS_BUFFER lpNdsBuffer = NULL;
  7130. DWORD dwReplyLength;
  7131. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  7132. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  7133. DWORD dwNumEntries = 0;
  7134. DWORD dwCurrNumEntries = 0;
  7135. DWORD dwCurrBuffSize = 0;
  7136. DWORD dwCopyOffset = 0;
  7137. PVOID lpCurrBuff = NULL;
  7138. PVOID lpTempBuff = NULL;
  7139. DWORD dwInfoType = dwInformationType;
  7140. if ( lpNdsObject->Signature != NDS_SIGNATURE )
  7141. {
  7142. SetLastError( ERROR_INVALID_PARAMETER );
  7143. return (DWORD) UNSUCCESSFUL;
  7144. }
  7145. status = NwNdsCreateBuffer( NDS_OBJECT_READ,
  7146. (HANDLE *) &lpNdsBuffer );
  7147. if ( status )
  7148. {
  7149. goto ErrorExit;
  7150. }
  7151. lpNdsBuffer->lpReplyBuffer = NULL;
  7152. lpNdsBuffer->dwReplyBufferSize = 0;
  7153. //
  7154. // We're asking for all attribute values, so let's start with max buffer to avoid iterations.
  7155. //
  7156. dwCurrBuffSize = NDS_MAX_BUFFER;
  7157. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  7158. //
  7159. // Check that the memory allocation was successful.
  7160. //
  7161. if ( lpCurrBuff == NULL )
  7162. {
  7163. #if DBG
  7164. KdPrint(( "NDS32: ReadObject_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7165. #endif
  7166. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7167. status = (DWORD) UNSUCCESSFUL;
  7168. goto ErrorExit;
  7169. }
  7170. do
  7171. {
  7172. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7173. NETWARE_NDS_FUNCTION_READ_OBJECT,
  7174. lpCurrBuff,
  7175. dwCurrBuffSize,
  7176. &dwReplyLength,
  7177. "DDDDDD",
  7178. 0, // Version
  7179. dwIterHandle, // Initial iteration
  7180. lpNdsObject->ObjectId, // Id of the object
  7181. dwInformationType,
  7182. (DWORD) TRUE, // All attributes indicator
  7183. 0 ); // Number of attribute names
  7184. if ( !NT_SUCCESS( ntstatus ) )
  7185. {
  7186. #if DBG
  7187. KdPrint(( "NDS32: ReadObject_AllAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  7188. #endif
  7189. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7190. status = (DWORD) UNSUCCESSFUL;
  7191. goto ErrorExit;
  7192. }
  7193. ntstatus = ParseResponse( lpCurrBuff,
  7194. dwReplyLength,
  7195. "GD",
  7196. &nwstatus );
  7197. if ( !NT_SUCCESS( ntstatus ) )
  7198. {
  7199. #if DBG
  7200. KdPrint(( "NDS32: ReadObject_AllAttrs: The read object response was undecipherable.\n" ));
  7201. #endif
  7202. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7203. status = (DWORD) UNSUCCESSFUL;
  7204. goto ErrorExit;
  7205. }
  7206. if ( nwstatus )
  7207. {
  7208. #if DBG
  7209. KdPrint(( "NDS32: ReadObject_AllAttrs - NetWare error 0x%.8X.\n", nwstatus ));
  7210. #endif
  7211. SetLastError( MapNetwareErrorCode( nwstatus ) );
  7212. status = nwstatus;
  7213. goto ErrorExit;
  7214. }
  7215. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  7216. dwReplyLength,
  7217. "G_DDD",
  7218. sizeof(DWORD),
  7219. &dwIterHandle,
  7220. &dwInfoType,
  7221. &dwCurrNumEntries );
  7222. if ( !NT_SUCCESS( ntstatus ) )
  7223. {
  7224. #if DBG
  7225. KdPrint(( "NDS32: ReadObject_AllAttrs: The read object response was undecipherable.\n" ));
  7226. #endif
  7227. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7228. status = (DWORD) UNSUCCESSFUL;
  7229. goto ErrorExit;
  7230. }
  7231. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  7232. {
  7233. dwCopyOffset = 0; // we want the entire buffer the first time
  7234. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  7235. }
  7236. else
  7237. {
  7238. #if DBG
  7239. KdPrint(( "NDS32: ReadObject_AllAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  7240. #endif
  7241. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  7242. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  7243. // grow reply buffer to hold additional data
  7244. if (lpTempBuff)
  7245. {
  7246. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  7247. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  7248. }
  7249. }
  7250. if (lpTempBuff == NULL)
  7251. {
  7252. #if DBG
  7253. KdPrint(( "NDS32: ReadObject_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7254. #endif
  7255. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7256. status = (DWORD) UNSUCCESSFUL;
  7257. goto ErrorExit;
  7258. }
  7259. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  7260. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  7261. (dwCurrBuffSize - dwCopyOffset) );
  7262. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  7263. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  7264. dwNumEntries += dwCurrNumEntries;
  7265. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  7266. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  7267. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  7268. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  7269. *lphOperationData = lpNdsBuffer;
  7270. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7271. return NO_ERROR;
  7272. ErrorExit :
  7273. if ( lpCurrBuff )
  7274. {
  7275. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7276. lpCurrBuff = NULL;
  7277. }
  7278. if ( lpNdsBuffer )
  7279. {
  7280. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  7281. lpNdsBuffer = NULL;
  7282. }
  7283. return status;
  7284. }
  7285. DWORD
  7286. ReadObject_SomeAttrs(
  7287. IN HANDLE hObject,
  7288. IN DWORD dwInformationType,
  7289. IN OUT HANDLE * lphOperationData )
  7290. {
  7291. DWORD status;
  7292. DWORD nwstatus;
  7293. NTSTATUS ntstatus;
  7294. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
  7295. DWORD dwReplyLength;
  7296. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
  7297. DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
  7298. DWORD dwInfoType = dwInformationType;
  7299. DWORD dwNumEntries = 0;
  7300. DWORD dwCurrNumEntries = 0;
  7301. DWORD dwCurrBuffSize = 0;
  7302. DWORD dwCopyOffset = 0;
  7303. PVOID lpCurrBuff = NULL;
  7304. PVOID lpTempBuff = NULL;
  7305. if ( lpNdsObject->Signature != NDS_SIGNATURE )
  7306. {
  7307. SetLastError( ERROR_INVALID_PARAMETER );
  7308. return (DWORD) UNSUCCESSFUL;
  7309. }
  7310. if ( lpNdsBuffer->dwOperation != NDS_OBJECT_READ )
  7311. {
  7312. SetLastError( ERROR_INVALID_PARAMETER );
  7313. return (DWORD) UNSUCCESSFUL;
  7314. }
  7315. //
  7316. // Check to see if this buffer has already been used for a read reply.
  7317. //
  7318. if ( lpNdsBuffer->lpReplyBuffer )
  7319. {
  7320. SetLastError( ERROR_INVALID_PARAMETER );
  7321. return (DWORD) UNSUCCESSFUL;
  7322. }
  7323. lpNdsBuffer->dwReplyBufferSize = 0;
  7324. //
  7325. // We may be asking for all values, so let's start with max buffer to avoid iterations.
  7326. //
  7327. dwCurrBuffSize = NDS_MAX_BUFFER;
  7328. lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
  7329. //
  7330. // Check that the memory allocation was successful.
  7331. //
  7332. if ( lpCurrBuff == NULL )
  7333. {
  7334. #if DBG
  7335. KdPrint(( "NDS32: ReadObject_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7336. #endif
  7337. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7338. status = (DWORD) UNSUCCESSFUL;
  7339. goto ErrorExit;
  7340. }
  7341. do
  7342. {
  7343. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7344. NETWARE_NDS_FUNCTION_READ_OBJECT,
  7345. lpCurrBuff,
  7346. dwCurrBuffSize,
  7347. &dwReplyLength,
  7348. "DDDDDDr",
  7349. 0, // Version
  7350. dwIterHandle, // Initial iteration
  7351. lpNdsObject->ObjectId, // Id of the object
  7352. dwInformationType,
  7353. (DWORD) FALSE, // All attributes indicator
  7354. lpNdsBuffer->dwNumberOfRequestEntries,
  7355. lpNdsBuffer->lpRequestBuffer, // Object info
  7356. (WORD)lpNdsBuffer->dwLengthOfRequestData );
  7357. if ( !NT_SUCCESS( ntstatus ) )
  7358. {
  7359. #if DBG
  7360. KdPrint(( "NDS32: ReadObject_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  7361. #endif
  7362. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7363. status = (DWORD) UNSUCCESSFUL;
  7364. goto ErrorExit;
  7365. }
  7366. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  7367. dwReplyLength,
  7368. "GD",
  7369. &nwstatus );
  7370. if ( !NT_SUCCESS( ntstatus ) )
  7371. {
  7372. #if DBG
  7373. KdPrint(( "NDS32: ReadObject_SomeAttrs: The read object response was undecipherable.\n" ));
  7374. #endif
  7375. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7376. status = (DWORD) UNSUCCESSFUL;
  7377. goto ErrorExit;
  7378. }
  7379. if ( nwstatus )
  7380. {
  7381. #if DBG
  7382. KdPrint(( "NDS32: ReadClassDef_SomeClasses - NetWare error 0x%.8X.\n", nwstatus ));
  7383. #endif
  7384. SetLastError( MapNetwareErrorCode( nwstatus ) );
  7385. status = nwstatus;
  7386. goto ErrorExit;
  7387. }
  7388. ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
  7389. dwReplyLength,
  7390. "G_DDD",
  7391. sizeof(DWORD),
  7392. &dwIterHandle,
  7393. &dwInfoType,
  7394. &dwCurrNumEntries );
  7395. if ( !NT_SUCCESS( ntstatus ) )
  7396. {
  7397. #if DBG
  7398. KdPrint(( "NDS32: ReadObject_SomeAttrs: The read object response was undecipherable.\n" ));
  7399. #endif
  7400. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7401. status = (DWORD) UNSUCCESSFUL;
  7402. goto ErrorExit;
  7403. }
  7404. if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
  7405. {
  7406. dwCopyOffset = 0; // we want the entire buffer the first time
  7407. lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
  7408. }
  7409. else
  7410. {
  7411. #if DBG
  7412. KdPrint(( "NDS32: ReadObject_SomeAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
  7413. #endif
  7414. dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
  7415. lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
  7416. // grow reply buffer to hold additional data
  7417. if (lpTempBuff)
  7418. {
  7419. RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
  7420. (void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
  7421. }
  7422. }
  7423. if (lpTempBuff == NULL)
  7424. {
  7425. #if DBG
  7426. KdPrint(( "NDS32: ReadObject_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7427. #endif
  7428. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7429. status = (DWORD) UNSUCCESSFUL;
  7430. goto ErrorExit;
  7431. }
  7432. RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
  7433. (LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
  7434. (dwCurrBuffSize - dwCopyOffset) );
  7435. lpNdsBuffer->lpReplyBuffer = lpTempBuff;
  7436. lpNdsBuffer->dwReplyBufferSize += (dwCurrBuffSize - dwCopyOffset);
  7437. dwNumEntries += dwCurrNumEntries;
  7438. RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
  7439. } while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
  7440. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  7441. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  7442. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7443. return NO_ERROR;
  7444. ErrorExit :
  7445. if ( lpCurrBuff )
  7446. {
  7447. (void) LocalFree( (HLOCAL) lpCurrBuff );
  7448. lpCurrBuff = NULL;
  7449. }
  7450. if ( lpNdsBuffer->lpReplyBuffer )
  7451. {
  7452. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  7453. lpNdsBuffer->lpReplyBuffer = NULL;
  7454. lpNdsBuffer->dwReplyBufferSize = 0;
  7455. }
  7456. return status;
  7457. }
  7458. DWORD
  7459. Search_AllAttrs(
  7460. IN HANDLE hStartFromObject,
  7461. IN DWORD dwInformationType,
  7462. IN DWORD dwScope,
  7463. IN BOOL fDerefAliases,
  7464. IN LPQUERY_TREE lpQueryTree,
  7465. IN OUT LPDWORD lpdwIterHandle,
  7466. IN OUT HANDLE * lphOperationData )
  7467. {
  7468. DWORD status;
  7469. DWORD nwstatus;
  7470. NTSTATUS ntstatus;
  7471. LPNDS_BUFFER lpNdsBuffer = NULL;
  7472. LPNDS_BUFFER lpNdsQueryTreeBuffer = NULL;
  7473. DWORD dwReplyLength;
  7474. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hStartFromObject;
  7475. DWORD dwIterHandle;
  7476. DWORD dwNumEntries;
  7477. DWORD dwAmountOfNodesSearched;
  7478. DWORD dwLengthOfSearch;
  7479. DWORD iter;
  7480. //
  7481. // Search NCP parameters
  7482. //
  7483. DWORD dwFlags = fDerefAliases ?
  7484. NDS_DEREF_ALIASES :
  7485. NDS_DONT_DEREF_ALIASES;
  7486. DWORD dwNumNodes = 0;
  7487. DWORD dwNumAttributes = 0;
  7488. DWORD dwInfoType = dwInformationType;
  7489. LPBYTE FixedPortion;
  7490. LPWSTR EndOfVariableData;
  7491. BOOL FitInBuffer = TRUE;
  7492. if ( *lphOperationData == NULL )
  7493. {
  7494. //
  7495. // This is the first time that NwNdsSearch has been called,
  7496. // need to create a hOperationData buffer . . .
  7497. //
  7498. status = NwNdsCreateBuffer( NDS_SEARCH,
  7499. (HANDLE *) &lpNdsBuffer );
  7500. if ( status )
  7501. {
  7502. goto ErrorExit;
  7503. }
  7504. //
  7505. // Not specifying any particular attributes in the search request.
  7506. //
  7507. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
  7508. lpNdsBuffer->lpRequestBuffer = NULL;
  7509. lpNdsBuffer->dwRequestBufferSize = 0;
  7510. lpNdsBuffer->dwRequestAvailableBytes = 0;
  7511. lpNdsBuffer->dwNumberOfRequestEntries = 0;
  7512. lpNdsBuffer->dwLengthOfRequestData = 0;
  7513. //
  7514. // Reasonable guess is that the response buffer needs to be 16K bytes.
  7515. //
  7516. lpNdsBuffer->dwReplyBufferSize = SIXTEEN_KB;
  7517. }
  7518. else if ( ((LPNDS_BUFFER) *lphOperationData)->dwBufferId == NDS_SIGNATURE &&
  7519. ((LPNDS_BUFFER) *lphOperationData)->dwOperation == NDS_SEARCH &&
  7520. ((LPNDS_BUFFER) *lphOperationData)->lpReplyBuffer )
  7521. {
  7522. //
  7523. // This seems to be a sub-sequent call to NwNdsSearch with a resume
  7524. // handle, need to clean up the hOperationData buffer from the last
  7525. // time this was called.
  7526. //
  7527. lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
  7528. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  7529. lpNdsBuffer->lpReplyBuffer = NULL;
  7530. lpNdsBuffer->dwReplyAvailableBytes = 0;
  7531. lpNdsBuffer->dwNumberOfReplyEntries = 0;
  7532. lpNdsBuffer->dwLengthOfReplyData = 0;
  7533. if ( lpNdsBuffer->lpIndexBuffer )
  7534. {
  7535. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
  7536. lpNdsBuffer->lpIndexBuffer = NULL;
  7537. lpNdsBuffer->dwIndexAvailableBytes = 0;
  7538. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  7539. lpNdsBuffer->dwLengthOfIndexData = 0;
  7540. }
  7541. //
  7542. // Since the last call to NwNdsSearch needed a bigger buffer for all
  7543. // of the response data, let's continue this time with a bigger reply
  7544. // buffer. We grow the buffer up to a point, 128K bytes.
  7545. //
  7546. if ( lpNdsBuffer->dwReplyBufferSize < SIXTY_FOUR_KB )
  7547. {
  7548. lpNdsBuffer->dwReplyBufferSize *= 2;
  7549. }
  7550. }
  7551. else
  7552. {
  7553. SetLastError( ERROR_INVALID_PARAMETER );
  7554. return (DWORD) UNSUCCESSFUL;
  7555. }
  7556. status = NwNdsCreateBuffer( NDS_SEARCH,
  7557. (HANDLE *) &lpNdsQueryTreeBuffer );
  7558. if ( status )
  7559. {
  7560. goto ErrorExit;
  7561. }
  7562. //
  7563. // Prepare request buffer stream with search query.
  7564. //
  7565. status = WriteQueryTreeToBuffer( lpQueryTree, lpNdsQueryTreeBuffer );
  7566. if ( status )
  7567. {
  7568. goto ErrorExit;
  7569. }
  7570. lpNdsBuffer->lpReplyBuffer =
  7571. (PVOID) LocalAlloc( LPTR, lpNdsBuffer->dwReplyBufferSize );
  7572. //
  7573. // Check that the memory allocation was successful.
  7574. //
  7575. if ( lpNdsBuffer->lpReplyBuffer == NULL )
  7576. {
  7577. #if DBG
  7578. KdPrint(( "NDS32: Search_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7579. #endif
  7580. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7581. status = (DWORD) UNSUCCESSFUL;
  7582. goto ErrorExit;
  7583. }
  7584. /*
  7585. //
  7586. // This is the format of a version 3 search request ...
  7587. //
  7588. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7589. NETWARE_NDS_FUNCTION_SEARCH,
  7590. lpNdsBuffer->lpReplyBuffer,
  7591. lpNdsBuffer->dwReplyBufferSize,
  7592. &dwReplyLength,
  7593. "DDDDDDDDDDr",
  7594. 0x00000003, // Version
  7595. dwFlags,
  7596. *lpdwIterHandle,
  7597. lpNdsObject->ObjectId, // Id of object to
  7598. // start search from.
  7599. dwScope,
  7600. dwNumNodes,
  7601. dwInfoType,
  7602. 0x0000281D, // Flags??
  7603. 0x741E0000, // ??
  7604. (DWORD) TRUE, // All attributes?
  7605. lpNdsQueryTreeBuffer->lpRequestBuffer,
  7606. (WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
  7607. */
  7608. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7609. NETWARE_NDS_FUNCTION_SEARCH,
  7610. lpNdsBuffer->lpReplyBuffer,
  7611. lpNdsBuffer->dwReplyBufferSize,
  7612. &dwReplyLength,
  7613. "DDDDDDDDDr",
  7614. 0x00000002, // Version
  7615. dwFlags,
  7616. *lpdwIterHandle,
  7617. lpNdsObject->ObjectId, // Id of object to
  7618. // start search from.
  7619. dwScope,
  7620. dwNumNodes,
  7621. dwInfoType,
  7622. (DWORD) TRUE, // All attributes?
  7623. dwNumAttributes,
  7624. lpNdsQueryTreeBuffer->lpRequestBuffer,
  7625. (WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
  7626. if ( !NT_SUCCESS( ntstatus ) )
  7627. {
  7628. #if DBG
  7629. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  7630. #endif
  7631. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7632. status = (DWORD) UNSUCCESSFUL;
  7633. goto ErrorExit;
  7634. }
  7635. ntstatus = ParseResponse( lpNdsBuffer->lpReplyBuffer,
  7636. dwReplyLength,
  7637. "GD",
  7638. &nwstatus );
  7639. if ( !NT_SUCCESS( ntstatus ) )
  7640. {
  7641. #if DBG
  7642. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  7643. #endif
  7644. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7645. status = (DWORD) UNSUCCESSFUL;
  7646. goto ErrorExit;
  7647. }
  7648. if ( nwstatus )
  7649. {
  7650. SetLastError( MapNetwareErrorCode( nwstatus ) );
  7651. status = nwstatus;
  7652. goto ErrorExit;
  7653. }
  7654. ntstatus = ParseResponse( (BYTE *) lpNdsBuffer->lpReplyBuffer,
  7655. dwReplyLength,
  7656. "G_DDDDD",
  7657. sizeof(DWORD),
  7658. &dwIterHandle,
  7659. &dwAmountOfNodesSearched,
  7660. &dwInfoType,
  7661. &dwLengthOfSearch,
  7662. &dwNumEntries );
  7663. if ( !NT_SUCCESS( ntstatus ) )
  7664. {
  7665. #if DBG
  7666. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  7667. #endif
  7668. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7669. status = (DWORD) UNSUCCESSFUL;
  7670. goto ErrorExit;
  7671. }
  7672. //
  7673. // Finished the search call, free up lpNDsQueryTreeBuffer
  7674. //
  7675. (void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
  7676. lpNdsQueryTreeBuffer = NULL;
  7677. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  7678. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  7679. *lpdwIterHandle = dwIterHandle;
  7680. *lphOperationData = (HANDLE) lpNdsBuffer;
  7681. //
  7682. // Keep the search from object path . . .
  7683. //
  7684. wcscpy( lpNdsBuffer->szPath, lpNdsObject->szContainerName );
  7685. return NO_ERROR;
  7686. ErrorExit :
  7687. if ( lpNdsBuffer )
  7688. {
  7689. (void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
  7690. lpNdsBuffer = NULL;
  7691. }
  7692. if ( lpNdsQueryTreeBuffer )
  7693. {
  7694. (void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
  7695. lpNdsQueryTreeBuffer = NULL;
  7696. }
  7697. return status;
  7698. }
  7699. DWORD
  7700. Search_SomeAttrs(
  7701. IN HANDLE hStartFromObject,
  7702. IN DWORD dwInformationType,
  7703. IN DWORD dwScope,
  7704. IN BOOL fDerefAliases,
  7705. IN LPQUERY_TREE lpQueryTree,
  7706. IN OUT LPDWORD lpdwIterHandle,
  7707. IN OUT HANDLE * lphOperationData )
  7708. {
  7709. DWORD status;
  7710. DWORD nwstatus;
  7711. NTSTATUS ntstatus;
  7712. LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
  7713. LPNDS_BUFFER lpNdsQueryTreeBuffer = NULL;
  7714. DWORD dwReplyLength;
  7715. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hStartFromObject;
  7716. DWORD dwIterHandle;
  7717. DWORD dwNumEntries;
  7718. DWORD dwAmountOfNodesSearched;
  7719. DWORD dwLengthOfSearch;
  7720. DWORD iter;
  7721. //
  7722. // Search NCP parameters
  7723. //
  7724. DWORD dwFlags = fDerefAliases ?
  7725. NDS_DEREF_ALIASES :
  7726. NDS_DONT_DEREF_ALIASES;
  7727. DWORD dwNumNodes = 0;
  7728. DWORD dwInfoType = dwInformationType;
  7729. LPBYTE FixedPortion;
  7730. LPWSTR EndOfVariableData;
  7731. BOOL FitInBuffer = TRUE;
  7732. //
  7733. // A quick check of the buffer passed to us.
  7734. //
  7735. if ( lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
  7736. lpNdsBuffer->dwOperation != NDS_SEARCH )
  7737. {
  7738. SetLastError( ERROR_INVALID_PARAMETER );
  7739. return (DWORD) UNSUCCESSFUL;
  7740. }
  7741. //
  7742. // Prepare request buffer stream with search query.
  7743. //
  7744. status = NwNdsCreateBuffer( NDS_SEARCH,
  7745. (HANDLE *) &lpNdsQueryTreeBuffer );
  7746. if ( status )
  7747. {
  7748. goto ErrorExit;
  7749. }
  7750. status = WriteQueryTreeToBuffer( lpQueryTree, lpNdsQueryTreeBuffer );
  7751. if ( status )
  7752. {
  7753. goto ErrorExit;
  7754. }
  7755. if ( lpNdsBuffer->lpReplyBuffer == NULL ||
  7756. lpNdsBuffer->dwReplyBufferSize == 0 )
  7757. {
  7758. //
  7759. // Reasonable guess is that the initial response buffer needs to
  7760. // be 16K bytes.
  7761. //
  7762. lpNdsBuffer->dwReplyBufferSize = SIXTEEN_KB;
  7763. }
  7764. if ( lpNdsBuffer->lpReplyBuffer )
  7765. {
  7766. //
  7767. // This seems to be a sub-sequent call to NwNdsSearch,
  7768. // need to clean up the hOperationData buffer from the last
  7769. // time this was called.
  7770. //
  7771. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
  7772. lpNdsBuffer->lpReplyBuffer = NULL;
  7773. lpNdsBuffer->dwReplyAvailableBytes = 0;
  7774. lpNdsBuffer->dwNumberOfReplyEntries = 0;
  7775. lpNdsBuffer->dwLengthOfReplyData = 0;
  7776. if ( lpNdsBuffer->lpIndexBuffer )
  7777. {
  7778. (void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
  7779. lpNdsBuffer->lpIndexBuffer = NULL;
  7780. lpNdsBuffer->dwIndexAvailableBytes = 0;
  7781. lpNdsBuffer->dwNumberOfIndexEntries = 0;
  7782. lpNdsBuffer->dwLengthOfIndexData = 0;
  7783. }
  7784. //
  7785. // Since the last call to NwNdsSearch needed a bigger buffer for all
  7786. // of the response data, let's continue this time with a bigger reply
  7787. // buffer. We grow the buffer up to a point, 64K bytes.
  7788. //
  7789. if ( lpNdsBuffer->dwReplyBufferSize < SIXTY_FOUR_KB )
  7790. {
  7791. lpNdsBuffer->dwReplyBufferSize *= 2;
  7792. }
  7793. }
  7794. lpNdsBuffer->lpReplyBuffer =
  7795. (PVOID) LocalAlloc( LPTR, lpNdsBuffer->dwReplyBufferSize );
  7796. //
  7797. // Check that the memory allocation was successful.
  7798. //
  7799. if ( lpNdsBuffer->lpReplyBuffer == NULL )
  7800. {
  7801. #if DBG
  7802. KdPrint(( "NDS32: Search_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  7803. #endif
  7804. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  7805. status = (DWORD) UNSUCCESSFUL;
  7806. goto ErrorExit;
  7807. }
  7808. /*
  7809. //
  7810. // This is the format of a version 3 search request ...
  7811. //
  7812. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7813. NETWARE_NDS_FUNCTION_SEARCH,
  7814. lpNdsBuffer->lpReplyBuffer,
  7815. lpNdsBuffer->dwReplyBufferSize,
  7816. &dwReplyLength,
  7817. "DDDDDDDDDDrr",
  7818. 0x00000003,
  7819. dwFlags,
  7820. *lpdwIterHandle,
  7821. lpNdsObject->ObjectId, // Id of object to
  7822. // start search from.
  7823. dwScope,
  7824. dwNumNodes,
  7825. dwInfoType,
  7826. 0x0000281D, // (DWORD) FALSE,// All attributes?
  7827. 0x741E0000, // dwNumAttributes,
  7828. lpNdsBuffer->dwNumberOfRequestEntries,
  7829. lpNdsBuffer->lpRequestBuffer,
  7830. lpNdsBuffer->dwLengthOfRequestData,
  7831. lpNdsQueryTreeBuffer->lpRequestBuffer,
  7832. (WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
  7833. */
  7834. ntstatus = FragExWithWait( lpNdsObject->NdsTree,
  7835. NETWARE_NDS_FUNCTION_SEARCH,
  7836. lpNdsBuffer->lpReplyBuffer,
  7837. lpNdsBuffer->dwReplyBufferSize,
  7838. &dwReplyLength,
  7839. "DDDDDDDDDrr",
  7840. 0x00000002,
  7841. dwFlags,
  7842. *lpdwIterHandle,
  7843. lpNdsObject->ObjectId, // Id of object to
  7844. // start search from.
  7845. dwScope,
  7846. dwNumNodes,
  7847. dwInfoType,
  7848. (DWORD) FALSE, // All attributes?
  7849. lpNdsBuffer->dwNumberOfRequestEntries,
  7850. lpNdsBuffer->lpRequestBuffer,
  7851. lpNdsBuffer->dwLengthOfRequestData,
  7852. lpNdsQueryTreeBuffer->lpRequestBuffer,
  7853. (WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
  7854. if ( !NT_SUCCESS( ntstatus ) )
  7855. {
  7856. #if DBG
  7857. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  7858. #endif
  7859. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7860. status = (DWORD) UNSUCCESSFUL;
  7861. goto ErrorExit;
  7862. }
  7863. ntstatus = ParseResponse( lpNdsBuffer->lpReplyBuffer,
  7864. dwReplyLength,
  7865. "GD",
  7866. &nwstatus );
  7867. if ( !NT_SUCCESS( ntstatus ) )
  7868. {
  7869. #if DBG
  7870. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  7871. #endif
  7872. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7873. status = (DWORD) UNSUCCESSFUL;
  7874. goto ErrorExit;
  7875. }
  7876. if ( nwstatus )
  7877. {
  7878. SetLastError( MapNetwareErrorCode( nwstatus ) );
  7879. status = nwstatus;
  7880. goto ErrorExit;
  7881. }
  7882. ntstatus = ParseResponse( (BYTE *) lpNdsBuffer->lpReplyBuffer,
  7883. dwReplyLength,
  7884. "G_DDDDD",
  7885. sizeof(DWORD),
  7886. &dwIterHandle,
  7887. &dwAmountOfNodesSearched,
  7888. &dwInfoType,
  7889. &dwLengthOfSearch,
  7890. &dwNumEntries );
  7891. if ( !NT_SUCCESS( ntstatus ) )
  7892. {
  7893. #if DBG
  7894. KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
  7895. #endif
  7896. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  7897. status = (DWORD) UNSUCCESSFUL;
  7898. goto ErrorExit;
  7899. }
  7900. //
  7901. // Finished the search call, free up lpNDsQueryTreeBuffer
  7902. //
  7903. (void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
  7904. lpNdsQueryTreeBuffer = NULL;
  7905. lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
  7906. lpNdsBuffer->dwReplyInformationType = dwInfoType;
  7907. *lpdwIterHandle = dwIterHandle;
  7908. *lphOperationData = (HANDLE) lpNdsBuffer;
  7909. //
  7910. // Keep the search from object path . . .
  7911. //
  7912. wcscpy( lpNdsBuffer->szPath, lpNdsObject->szContainerName );
  7913. return NO_ERROR;
  7914. ErrorExit :
  7915. if ( lpNdsQueryTreeBuffer )
  7916. {
  7917. (void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
  7918. lpNdsQueryTreeBuffer = NULL;
  7919. }
  7920. return status;
  7921. }
  7922. VOID
  7923. GetSubTreeData( IN DWORD NdsRawDataPtr,
  7924. OUT LPDWORD lpdwEntryId,
  7925. OUT LPDWORD lpdwSubordinateCount,
  7926. OUT LPDWORD lpdwModificationTime,
  7927. OUT LPDWORD lpdwClassNameLen,
  7928. OUT LPWSTR * lpszClassName,
  7929. OUT LPDWORD lpdwObjectNameLen,
  7930. OUT LPWSTR * lpszObjectName )
  7931. {
  7932. PNDS_RESPONSE_SUBORDINATE_ENTRY pSubEntry =
  7933. (PNDS_RESPONSE_SUBORDINATE_ENTRY) NdsRawDataPtr;
  7934. PBYTE pbRaw;
  7935. //
  7936. // The structure of a NDS_RESPONSE_SUBORDINATE_ENTRY consists of 4 DWORDs
  7937. // followed by two standard NDS format UNICODE strings. Below we jump pbRaw
  7938. // into the buffer, past the 4 DWORDs.
  7939. //
  7940. *lpdwEntryId = pSubEntry->EntryId;
  7941. *lpdwSubordinateCount = pSubEntry->SubordinateCount;
  7942. *lpdwModificationTime = pSubEntry->ModificationTime;
  7943. pbRaw = (BYTE *) pSubEntry;
  7944. pbRaw += sizeof(NDS_RESPONSE_SUBORDINATE_ENTRY);
  7945. //
  7946. // Now we get the length of the first string (Base Class).
  7947. //
  7948. *lpdwClassNameLen = * (DWORD *) pbRaw;
  7949. //
  7950. // Now we point pbRaw to the first WCHAR of the first string (Base Class).
  7951. //
  7952. pbRaw += sizeof(DWORD);
  7953. *lpszClassName = (LPWSTR) pbRaw;
  7954. //
  7955. // Move pbRaw into the buffer, past the first UNICODE string (WORD aligned)
  7956. //
  7957. pbRaw += ROUNDUP4( *lpdwClassNameLen );
  7958. //
  7959. // Now we get the length of the second string (Entry Name).
  7960. //
  7961. *lpdwObjectNameLen = * (DWORD *) pbRaw;
  7962. //
  7963. // Now we point pbRaw to the first WCHAR of the second string (Entry Name).
  7964. //
  7965. pbRaw += sizeof(DWORD);
  7966. *lpszObjectName = (LPWSTR) pbRaw;
  7967. }
  7968. LPBYTE
  7969. GetSearchResultData( IN LPBYTE lpResultBufferPtr,
  7970. OUT LPDWORD lpdwFlags,
  7971. OUT LPDWORD lpdwSubordinateCount,
  7972. OUT LPDWORD lpdwModificationTime,
  7973. OUT LPDWORD lpdwClassNameLen,
  7974. OUT LPWSTR * lpszClassName,
  7975. OUT LPDWORD lpdwObjectNameLen,
  7976. OUT LPWSTR * lpszObjectName,
  7977. OUT LPDWORD lpdwEntryInfo1,
  7978. OUT LPDWORD lpdwEntryInfo2 )
  7979. {
  7980. LPBYTE lpRaw = lpResultBufferPtr;
  7981. *lpdwFlags = * (LPDWORD) lpRaw;
  7982. lpRaw += sizeof(DWORD);
  7983. *lpdwSubordinateCount = * (LPDWORD) lpRaw;
  7984. lpRaw += sizeof(DWORD);
  7985. *lpdwModificationTime = * (LPDWORD) lpRaw;
  7986. lpRaw += sizeof(DWORD);
  7987. //
  7988. // Now we get the length of the first string (Base Class).
  7989. //
  7990. *lpdwClassNameLen = * (DWORD *) lpRaw;
  7991. //
  7992. // Now we point lpRaw to the first WCHAR of the first string (Base Class).
  7993. //
  7994. lpRaw += sizeof(DWORD);
  7995. *lpszClassName = (LPWSTR) lpRaw;
  7996. //
  7997. // Move lpRaw into the buffer, past the first UNICODE string
  7998. // (DWORD aligned)
  7999. //
  8000. lpRaw += ROUNDUP4( *lpdwClassNameLen );
  8001. //
  8002. // Now we get the length of the second string (Entry Name).
  8003. //
  8004. *lpdwObjectNameLen = * (DWORD *) lpRaw;
  8005. //
  8006. // Now we point lpRaw to the first WCHAR of the second string (Entry Name).
  8007. //
  8008. lpRaw += sizeof(DWORD);
  8009. *lpszObjectName = (LPWSTR) lpRaw;
  8010. //
  8011. // Move lpRaw into the buffer, past the second UNICODE string
  8012. // (DWORD aligned)
  8013. //
  8014. lpRaw += ROUNDUP4( *lpdwObjectNameLen );
  8015. //
  8016. // Now skip over the last two DWORDs, I don't know what they represent?
  8017. //
  8018. *lpdwEntryInfo1 = * (LPDWORD) lpRaw;
  8019. lpRaw += sizeof(DWORD);
  8020. *lpdwEntryInfo2 = * (LPDWORD) lpRaw;
  8021. lpRaw += sizeof(DWORD);
  8022. return lpRaw;
  8023. }
  8024. DWORD
  8025. WriteObjectToBuffer(
  8026. IN OUT LPBYTE * FixedPortion,
  8027. IN OUT LPWSTR * EndOfVariableData,
  8028. IN LPWSTR szObjectFullName,
  8029. IN LPWSTR szObjectName,
  8030. IN LPWSTR szClassName,
  8031. IN DWORD EntryId,
  8032. IN DWORD ModificationTime,
  8033. IN DWORD SubordinateCount,
  8034. IN DWORD NumberOfAttributes,
  8035. IN LPNDS_ATTR_INFO lpAttributeInfos )
  8036. {
  8037. BOOL FitInBuffer = TRUE;
  8038. LPNDS_OBJECT_INFO lpNdsObjectInfo = (LPNDS_OBJECT_INFO) *FixedPortion;
  8039. DWORD EntrySize = sizeof( NDS_OBJECT_INFO ) +
  8040. ( wcslen( szObjectFullName ) +
  8041. wcslen( szObjectName ) +
  8042. wcslen( szClassName ) +
  8043. 3 ) * sizeof( WCHAR );
  8044. EntrySize = ROUND_UP_COUNT( EntrySize, ALIGN_DWORD );
  8045. //
  8046. // See if buffer is large enough to fit the entry.
  8047. //
  8048. if (((DWORD_PTR) *FixedPortion + EntrySize) >
  8049. (DWORD_PTR) *EndOfVariableData) {
  8050. return WN_MORE_DATA;
  8051. }
  8052. lpNdsObjectInfo->dwEntryId = EntryId;
  8053. lpNdsObjectInfo->dwModificationTime = ModificationTime;
  8054. lpNdsObjectInfo->dwSubordinateCount = SubordinateCount;
  8055. lpNdsObjectInfo->dwNumberOfAttributes = NumberOfAttributes;
  8056. lpNdsObjectInfo->lpAttribute = lpAttributeInfos;
  8057. //
  8058. // Update fixed entry pointer to next entry.
  8059. //
  8060. (DWORD_PTR) (*FixedPortion) += sizeof(NDS_OBJECT_INFO);
  8061. FitInBuffer = NwlibCopyStringToBuffer(
  8062. szObjectFullName,
  8063. wcslen(szObjectFullName),
  8064. (LPCWSTR) *FixedPortion,
  8065. EndOfVariableData,
  8066. &lpNdsObjectInfo->szObjectFullName );
  8067. ASSERT(FitInBuffer);
  8068. FitInBuffer = NwlibCopyStringToBuffer(
  8069. szObjectName,
  8070. wcslen(szObjectName),
  8071. (LPCWSTR) *FixedPortion,
  8072. EndOfVariableData,
  8073. &lpNdsObjectInfo->szObjectName );
  8074. ASSERT(FitInBuffer);
  8075. FitInBuffer = NwlibCopyStringToBuffer(
  8076. szClassName,
  8077. wcslen(szClassName),
  8078. (LPCWSTR) *FixedPortion,
  8079. EndOfVariableData,
  8080. &lpNdsObjectInfo->szObjectClass );
  8081. ASSERT(FitInBuffer);
  8082. if (! FitInBuffer)
  8083. return WN_MORE_DATA;
  8084. return NO_ERROR;
  8085. }
  8086. DWORD
  8087. VerifyBufferSize(
  8088. IN LPBYTE lpRawBuffer,
  8089. IN DWORD dwBufferSize,
  8090. IN DWORD dwSyntaxID,
  8091. IN DWORD dwNumberOfValues,
  8092. OUT LPDWORD lpdwLength )
  8093. {
  8094. DWORD iter;
  8095. LPBYTE lpTemp = lpRawBuffer;
  8096. *lpdwLength = 0;
  8097. for ( iter = 0; iter < dwNumberOfValues; iter++ )
  8098. {
  8099. *lpdwLength += SizeOfASN1Structure( &lpTemp, dwSyntaxID );
  8100. }
  8101. if ( *lpdwLength > dwBufferSize )
  8102. {
  8103. return ERROR_NOT_ENOUGH_MEMORY;
  8104. }
  8105. return NO_ERROR;
  8106. }
  8107. DWORD
  8108. VerifyBufferSizeForStringList(
  8109. IN DWORD dwBufferSize,
  8110. IN DWORD dwNumberOfValues,
  8111. OUT LPDWORD lpdwLength )
  8112. {
  8113. *lpdwLength = sizeof(ASN1_TYPE_6) * dwNumberOfValues;
  8114. if ( *lpdwLength > dwBufferSize )
  8115. {
  8116. return ERROR_NOT_ENOUGH_MEMORY;
  8117. }
  8118. return NO_ERROR;
  8119. }
  8120. DWORD
  8121. WriteQueryTreeToBuffer(
  8122. IN LPQUERY_TREE lpQueryTree,
  8123. IN LPNDS_BUFFER lpNdsBuffer )
  8124. {
  8125. DWORD status;
  8126. switch( lpQueryTree->dwOperation )
  8127. {
  8128. case NDS_QUERY_OR :
  8129. case NDS_QUERY_AND :
  8130. if ( lpQueryTree->lpLVal == NULL || lpQueryTree->lpRVal == NULL )
  8131. {
  8132. #if DBG
  8133. KdPrint(( "NDS32: WriteQueryTreeToBuffer was not passed a pointer to an L or R value.\n" ));
  8134. #endif
  8135. SetLastError( ERROR_INVALID_PARAMETER );
  8136. return (DWORD) UNSUCCESSFUL;
  8137. }
  8138. status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
  8139. lpNdsBuffer );
  8140. if ( status )
  8141. return status;
  8142. status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpLVal,
  8143. lpNdsBuffer );
  8144. if ( status )
  8145. return status;
  8146. status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpRVal,
  8147. lpNdsBuffer );
  8148. if ( status )
  8149. return status;
  8150. break;
  8151. case NDS_QUERY_NOT :
  8152. if ( lpQueryTree->lpLVal == NULL )
  8153. {
  8154. #if DBG
  8155. KdPrint(( "NDS32: WriteQueryTreeToBuffer was not passed a pointer to an L value.\n" ));
  8156. #endif
  8157. SetLastError( ERROR_INVALID_PARAMETER );
  8158. return (DWORD) UNSUCCESSFUL;
  8159. }
  8160. status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
  8161. lpNdsBuffer );
  8162. if ( status )
  8163. return status;
  8164. status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpLVal,
  8165. lpNdsBuffer );
  8166. if ( status )
  8167. return status;
  8168. break;
  8169. case NDS_QUERY_EQUAL :
  8170. case NDS_QUERY_GE :
  8171. case NDS_QUERY_LE :
  8172. case NDS_QUERY_APPROX :
  8173. case NDS_QUERY_PRESENT :
  8174. status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
  8175. lpNdsBuffer );
  8176. if ( status )
  8177. return status;
  8178. break;
  8179. default :
  8180. #if DBG
  8181. KdPrint(( "NDS32: WriteQueryTreeToBuffer was passed an unidentified operation - 0x%.8X.\n", lpQueryTree->dwOperation ));
  8182. #endif
  8183. SetLastError( ERROR_INVALID_PARAMETER );
  8184. return (DWORD) UNSUCCESSFUL;
  8185. }
  8186. return NO_ERROR;
  8187. }
  8188. DWORD
  8189. WriteQueryNodeToBuffer(
  8190. IN LPQUERY_NODE lpQueryNode,
  8191. IN LPNDS_BUFFER lpNdsBuffer )
  8192. {
  8193. DWORD LengthInBytes = 0;
  8194. DWORD stringLen;
  8195. LPBYTE lpTemp;
  8196. if ( lpNdsBuffer->dwRequestAvailableBytes < ONE_KB )
  8197. {
  8198. //
  8199. // Buffer to store query is getting small, need to increase
  8200. // request buffer size.
  8201. //
  8202. if ( AllocateOrIncreaseRequestBuffer( lpNdsBuffer ) != NO_ERROR )
  8203. {
  8204. #if DBG
  8205. KdPrint(( "NDS32: WriteQueryNodeToBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  8206. #endif
  8207. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  8208. return (DWORD) UNSUCCESSFUL;
  8209. }
  8210. }
  8211. lpTemp = (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData];
  8212. switch( lpQueryNode->dwOperation )
  8213. {
  8214. case NDS_QUERY_OR :
  8215. case NDS_QUERY_AND :
  8216. if ( lpQueryNode->lpLVal == NULL || lpQueryNode->lpRVal == NULL )
  8217. {
  8218. #if DBG
  8219. KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L or R value.\n" ));
  8220. #endif
  8221. SetLastError( ERROR_INVALID_PARAMETER );
  8222. return (DWORD) UNSUCCESSFUL;
  8223. }
  8224. //
  8225. // Write out operation
  8226. //
  8227. *(LPDWORD)lpTemp = lpQueryNode->dwOperation;
  8228. lpTemp += sizeof(DWORD);
  8229. LengthInBytes += sizeof(DWORD);
  8230. *(LPDWORD)lpTemp = 2; // The number of items being ANDed or ORed.
  8231. lpTemp += sizeof(DWORD);
  8232. LengthInBytes += sizeof(DWORD);
  8233. break;
  8234. case NDS_QUERY_NOT :
  8235. if ( lpQueryNode->lpLVal == NULL )
  8236. {
  8237. #if DBG
  8238. KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L value.\n" ));
  8239. #endif
  8240. SetLastError( ERROR_INVALID_PARAMETER );
  8241. return (DWORD) UNSUCCESSFUL;
  8242. }
  8243. //
  8244. // Write out operation
  8245. //
  8246. *(LPDWORD)lpTemp = lpQueryNode->dwOperation;
  8247. lpTemp += sizeof(DWORD);
  8248. LengthInBytes += sizeof(DWORD);
  8249. break;
  8250. case NDS_QUERY_EQUAL :
  8251. case NDS_QUERY_GE :
  8252. case NDS_QUERY_LE :
  8253. case NDS_QUERY_APPROX :
  8254. if ( lpQueryNode->lpLVal == NULL || lpQueryNode->lpRVal == NULL )
  8255. {
  8256. #if DBG
  8257. KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L or R value.\n" ));
  8258. #endif
  8259. SetLastError( ERROR_INVALID_PARAMETER );
  8260. return (DWORD) UNSUCCESSFUL;
  8261. }
  8262. //
  8263. // Write out operation
  8264. //
  8265. *(LPDWORD)lpTemp = 0; // Zero represents ITEM in NDS
  8266. lpTemp += sizeof(DWORD);
  8267. LengthInBytes += sizeof(DWORD);
  8268. *(LPDWORD)lpTemp = lpQueryNode->dwOperation;
  8269. lpTemp += sizeof(DWORD);
  8270. LengthInBytes += sizeof(DWORD);
  8271. switch( lpQueryNode->dwSyntaxId )
  8272. {
  8273. case NDS_SYNTAX_ID_1 :
  8274. case NDS_SYNTAX_ID_2 :
  8275. case NDS_SYNTAX_ID_3 :
  8276. case NDS_SYNTAX_ID_4 :
  8277. case NDS_SYNTAX_ID_5 :
  8278. case NDS_SYNTAX_ID_10 :
  8279. case NDS_SYNTAX_ID_20 :
  8280. //
  8281. // Write out the attribute name stored in LVal
  8282. //
  8283. stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
  8284. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8285. lpTemp += sizeof(DWORD);
  8286. LengthInBytes += sizeof(DWORD);
  8287. RtlCopyMemory( lpTemp,
  8288. lpQueryNode->lpLVal,
  8289. stringLen*sizeof(WCHAR) );
  8290. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8291. ALIGN_DWORD);
  8292. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8293. sizeof(WCHAR),
  8294. ALIGN_DWORD );
  8295. //
  8296. // Write out the attribute value stored in RVal
  8297. //
  8298. stringLen = wcslen( (LPWSTR) lpQueryNode->lpRVal );
  8299. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8300. lpTemp += sizeof(DWORD);
  8301. LengthInBytes += sizeof(DWORD);
  8302. RtlCopyMemory( lpTemp,
  8303. lpQueryNode->lpRVal,
  8304. stringLen*sizeof(WCHAR) );
  8305. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8306. ALIGN_DWORD);
  8307. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8308. sizeof(WCHAR),
  8309. ALIGN_DWORD );
  8310. break;
  8311. case NDS_SYNTAX_ID_7 :
  8312. //
  8313. // Write out the attribute name stored in LVal
  8314. //
  8315. stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
  8316. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8317. lpTemp += sizeof(DWORD);
  8318. LengthInBytes += sizeof(DWORD);
  8319. RtlCopyMemory( lpTemp,
  8320. lpQueryNode->lpLVal,
  8321. stringLen*sizeof(WCHAR) );
  8322. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8323. ALIGN_DWORD);
  8324. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8325. sizeof(WCHAR),
  8326. ALIGN_DWORD );
  8327. //
  8328. // Write out the attribute value stored in RVal
  8329. //
  8330. *(LPDWORD)lpTemp = 1; // Needs to have value 1,
  8331. // representing one byte
  8332. // even though it is padded
  8333. // out to four bytes.
  8334. lpTemp += sizeof(DWORD);
  8335. LengthInBytes += sizeof(DWORD);
  8336. *(LPDWORD)lpTemp = 0; // This clears all bits of the DWORD
  8337. *(LPBYTE)lpTemp = (BYTE) (((LPASN1_TYPE_7)
  8338. lpQueryNode->lpRVal)->Boolean);
  8339. lpTemp += sizeof(DWORD);
  8340. LengthInBytes += sizeof(DWORD);
  8341. break;
  8342. case NDS_SYNTAX_ID_8 :
  8343. case NDS_SYNTAX_ID_22 :
  8344. case NDS_SYNTAX_ID_24 :
  8345. case NDS_SYNTAX_ID_27 :
  8346. //
  8347. // Write out the attribute name stored in LVal
  8348. //
  8349. stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
  8350. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8351. lpTemp += sizeof(DWORD);
  8352. LengthInBytes += sizeof(DWORD);
  8353. RtlCopyMemory( lpTemp,
  8354. lpQueryNode->lpLVal,
  8355. stringLen*sizeof(WCHAR) );
  8356. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8357. ALIGN_DWORD);
  8358. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8359. sizeof(WCHAR),
  8360. ALIGN_DWORD );
  8361. //
  8362. // Write out the attribute value stored in RVal
  8363. //
  8364. *(LPDWORD)lpTemp = sizeof( DWORD );
  8365. lpTemp += sizeof(DWORD);
  8366. LengthInBytes += sizeof(DWORD);
  8367. *(LPDWORD)lpTemp = *( (LPDWORD) lpQueryNode->lpRVal );
  8368. lpTemp += sizeof(DWORD);
  8369. LengthInBytes += sizeof(DWORD);
  8370. break;
  8371. case NDS_SYNTAX_ID_9 :
  8372. //
  8373. // Write out the attribute name stored in LVal
  8374. //
  8375. stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
  8376. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8377. lpTemp += sizeof(DWORD);
  8378. LengthInBytes += sizeof(DWORD);
  8379. RtlCopyMemory( lpTemp,
  8380. lpQueryNode->lpLVal,
  8381. stringLen*sizeof(WCHAR) );
  8382. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8383. ALIGN_DWORD);
  8384. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8385. sizeof(WCHAR),
  8386. ALIGN_DWORD );
  8387. //
  8388. // Write out the attribute value stored in RVal
  8389. //
  8390. stringLen = ((LPASN1_TYPE_9) lpQueryNode->lpRVal)->Length;
  8391. *(LPDWORD)lpTemp = stringLen;
  8392. lpTemp += sizeof(DWORD);
  8393. LengthInBytes += sizeof(DWORD);
  8394. RtlCopyMemory( lpTemp,
  8395. &((LPASN1_TYPE_9) lpQueryNode->lpRVal)->OctetString,
  8396. stringLen );
  8397. lpTemp += ROUND_UP_COUNT( stringLen, ALIGN_DWORD);
  8398. LengthInBytes += ROUND_UP_COUNT( stringLen, ALIGN_DWORD );
  8399. break;
  8400. default :
  8401. SetLastError( ERROR_NOT_SUPPORTED );
  8402. return (DWORD) UNSUCCESSFUL;
  8403. }
  8404. break;
  8405. case NDS_QUERY_PRESENT :
  8406. if ( lpQueryNode->lpLVal == NULL )
  8407. {
  8408. #if DBG
  8409. KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L value.\n" ));
  8410. #endif
  8411. SetLastError( ERROR_INVALID_PARAMETER );
  8412. return (DWORD) UNSUCCESSFUL;
  8413. }
  8414. //
  8415. // Write out operation
  8416. //
  8417. *(LPDWORD)lpTemp = 0; // Zero represents ITEM in NDS
  8418. lpTemp += sizeof(DWORD);
  8419. LengthInBytes += sizeof(DWORD);
  8420. *(LPDWORD)lpTemp = lpQueryNode->dwOperation;
  8421. lpTemp += sizeof(DWORD);
  8422. LengthInBytes += sizeof(DWORD);
  8423. //
  8424. // Write out the attribute name stored in LVal
  8425. //
  8426. stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
  8427. *(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
  8428. lpTemp += sizeof(DWORD);
  8429. LengthInBytes += sizeof(DWORD);
  8430. RtlCopyMemory( lpTemp,
  8431. lpQueryNode->lpLVal,
  8432. stringLen*sizeof(WCHAR) );
  8433. lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
  8434. ALIGN_DWORD);
  8435. LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
  8436. sizeof(WCHAR),
  8437. ALIGN_DWORD );
  8438. break;
  8439. default :
  8440. #if DBG
  8441. KdPrint(( "NDS32: WriteQueryNodeToBuffer was passed an unidentified operation - 0x%.8X.\n", lpQueryNode->dwOperation ));
  8442. #endif
  8443. SetLastError( ERROR_INVALID_PARAMETER );
  8444. return (DWORD) UNSUCCESSFUL;
  8445. }
  8446. lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
  8447. lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
  8448. return NO_ERROR;
  8449. }
  8450. DWORD
  8451. NwNdsGetServerDN(
  8452. IN HANDLE hTree,
  8453. OUT LPWSTR szServerDN )
  8454. {
  8455. DWORD nwstatus;
  8456. DWORD status = NO_ERROR;
  8457. NTSTATUS ntstatus = STATUS_SUCCESS;
  8458. DWORD dwReplyLength;
  8459. BYTE NdsReply[NDS_BUFFER_SIZE];
  8460. LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
  8461. if ( lpNdsObject == NULL ||
  8462. lpNdsObject->Signature != NDS_SIGNATURE )
  8463. {
  8464. SetLastError( ERROR_INVALID_PARAMETER );
  8465. return (DWORD) UNSUCCESSFUL;
  8466. }
  8467. ntstatus =
  8468. FragExWithWait( lpNdsObject->NdsTree,
  8469. NETWARE_NDS_FUNCTION_GET_SERVER_ADDRESS,
  8470. NdsReply,
  8471. NDS_BUFFER_SIZE,
  8472. &dwReplyLength,
  8473. NULL );
  8474. if ( !NT_SUCCESS( ntstatus ) )
  8475. {
  8476. #if DBG
  8477. KdPrint(( "NDS32: NwNdsGetServerInfo: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
  8478. #endif
  8479. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  8480. return (DWORD) UNSUCCESSFUL;
  8481. }
  8482. ntstatus = ParseResponse( NdsReply,
  8483. dwReplyLength,
  8484. "GD",
  8485. &nwstatus );
  8486. if ( !NT_SUCCESS( ntstatus ) )
  8487. {
  8488. #if DBG
  8489. KdPrint(( "NDS32: NwNdsGetServerInfo: The get server information response was undecipherable.\n" ));
  8490. #endif
  8491. SetLastError( RtlNtStatusToDosError( ntstatus ) );
  8492. return (DWORD) UNSUCCESSFUL;
  8493. }
  8494. if ( nwstatus )
  8495. {
  8496. SetLastError( MapNetwareErrorCode( nwstatus ) );
  8497. return nwstatus;
  8498. }
  8499. else
  8500. {
  8501. LPBYTE lpByte = NdsReply;
  8502. DWORD dwStrLen = 0;
  8503. DWORD dwNumPartitions = 0;
  8504. //
  8505. // Skip past status return code ...
  8506. //
  8507. lpByte += sizeof( DWORD );
  8508. //
  8509. // Skip past the length value of the Server DN string ...
  8510. //
  8511. lpByte += sizeof( DWORD );
  8512. wcscpy( szServerDN, (LPWSTR) lpByte );
  8513. return NO_ERROR;
  8514. }
  8515. }
  8516. DWORD
  8517. AllocateOrIncreaseSyntaxBuffer(
  8518. IN LPNDS_BUFFER lpNdsBuffer )
  8519. {
  8520. if ( lpNdsBuffer->lpSyntaxBuffer )
  8521. {
  8522. LPBYTE lpTempBuffer = NULL;
  8523. //
  8524. // Need to reallocate buffer to a bigger size.
  8525. //
  8526. lpTempBuffer = (LPBYTE) LocalReAlloc(
  8527. (HLOCAL) lpNdsBuffer->lpSyntaxBuffer,
  8528. lpNdsBuffer->dwSyntaxBufferSize + FOUR_KB,
  8529. LPTR );
  8530. if ( lpTempBuffer )
  8531. {
  8532. lpNdsBuffer->lpSyntaxBuffer = lpTempBuffer;
  8533. }
  8534. else
  8535. {
  8536. lpTempBuffer = (LPBYTE) LocalAlloc( LPTR,
  8537. lpNdsBuffer->dwSyntaxBufferSize +
  8538. FOUR_KB );
  8539. if ( lpTempBuffer )
  8540. {
  8541. RtlCopyMemory( lpTempBuffer,
  8542. lpNdsBuffer->lpSyntaxBuffer,
  8543. lpNdsBuffer->dwSyntaxBufferSize );
  8544. LocalFree( lpNdsBuffer->lpSyntaxBuffer );
  8545. lpNdsBuffer->lpSyntaxBuffer = lpTempBuffer;
  8546. }
  8547. else
  8548. {
  8549. LocalFree( lpNdsBuffer->lpSyntaxBuffer );
  8550. lpNdsBuffer->lpSyntaxBuffer = NULL;
  8551. }
  8552. }
  8553. }
  8554. else
  8555. {
  8556. //
  8557. // Need to allocate a 4K byte buffer.
  8558. //
  8559. lpNdsBuffer->lpSyntaxBuffer = (LPBYTE) LocalAlloc( LPTR,
  8560. FOUR_KB );
  8561. lpNdsBuffer->dwSyntaxBufferSize = 0;
  8562. lpNdsBuffer->dwSyntaxAvailableBytes = 0;
  8563. }
  8564. if ( lpNdsBuffer->lpSyntaxBuffer == NULL )
  8565. {
  8566. #if DBG
  8567. KdPrint(( "NDS32: AllocateOrIncreaseSyntaxBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  8568. #endif
  8569. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  8570. return (DWORD) UNSUCCESSFUL;
  8571. }
  8572. lpNdsBuffer->dwSyntaxBufferSize += FOUR_KB;
  8573. lpNdsBuffer->dwSyntaxAvailableBytes += FOUR_KB;
  8574. return NO_ERROR;
  8575. }
  8576. DWORD
  8577. AllocateOrIncreaseRequestBuffer(
  8578. IN LPNDS_BUFFER lpNdsBuffer )
  8579. {
  8580. if ( lpNdsBuffer->lpRequestBuffer )
  8581. {
  8582. LPBYTE lpTempBuffer = NULL;
  8583. //
  8584. // Need to reallocate buffer to a bigger size.
  8585. //
  8586. lpTempBuffer = (LPBYTE) LocalReAlloc(
  8587. (HLOCAL) lpNdsBuffer->lpRequestBuffer,
  8588. lpNdsBuffer->dwRequestBufferSize + TWO_KB,
  8589. LPTR );
  8590. if ( lpTempBuffer )
  8591. {
  8592. lpNdsBuffer->lpRequestBuffer = lpTempBuffer;
  8593. }
  8594. else
  8595. {
  8596. lpTempBuffer = (LPBYTE) LocalAlloc( LPTR,
  8597. lpNdsBuffer->dwRequestBufferSize +
  8598. TWO_KB );
  8599. if ( lpTempBuffer )
  8600. {
  8601. RtlCopyMemory( lpTempBuffer,
  8602. lpNdsBuffer->lpRequestBuffer,
  8603. lpNdsBuffer->dwRequestBufferSize );
  8604. LocalFree( lpNdsBuffer->lpRequestBuffer );
  8605. lpNdsBuffer->lpRequestBuffer = lpTempBuffer;
  8606. }
  8607. else
  8608. {
  8609. LocalFree( lpNdsBuffer->lpRequestBuffer );
  8610. lpNdsBuffer->lpRequestBuffer = NULL;
  8611. }
  8612. }
  8613. }
  8614. else
  8615. {
  8616. //
  8617. // Need to allocate a 2K byte buffer.
  8618. //
  8619. lpNdsBuffer->lpRequestBuffer = (LPBYTE) LocalAlloc( LPTR,
  8620. TWO_KB );
  8621. lpNdsBuffer->dwRequestBufferSize = 0;
  8622. lpNdsBuffer->dwRequestAvailableBytes = 0;
  8623. }
  8624. if ( lpNdsBuffer->lpRequestBuffer == NULL )
  8625. {
  8626. #if DBG
  8627. KdPrint(( "NDS32: AllocateOrIncreaseRequestBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
  8628. #endif
  8629. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  8630. return (DWORD) UNSUCCESSFUL;
  8631. }
  8632. lpNdsBuffer->dwRequestBufferSize += TWO_KB;
  8633. lpNdsBuffer->dwRequestAvailableBytes += TWO_KB;
  8634. return NO_ERROR;
  8635. }