Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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