Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1813 lines
43 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. NdsLib32.c
  5. Abstract:
  6. This module implements the exposed user-mode link to
  7. Netware NDS support in the Netware redirector. For
  8. more comments, see ndslib32.h.
  9. Author:
  10. Cory West [CoryWest] 23-Feb-1995
  11. --*/
  12. #include <procs.h>
  13. //#include <nwapilyr.h>
  14. NTSTATUS
  15. NwNdsOpenGenericHandle(
  16. IN PUNICODE_STRING puNdsTree,
  17. OUT LPDWORD lpdwHandleType,
  18. OUT PHANDLE phNwRdrHandle
  19. ) {
  20. NTSTATUS ntstatus, OpenStatus;
  21. IO_STATUS_BLOCK IoStatusBlock;
  22. OBJECT_ATTRIBUTES ObjectAttributes;
  23. ACCESS_MASK DesiredAccess = SYNCHRONIZE | FILE_LIST_DIRECTORY;
  24. WCHAR DevicePreamble[] = L"\\Device\\Nwrdr\\";
  25. UINT PreambleLength = 14;
  26. WCHAR NameStr[128];
  27. UNICODE_STRING uOpenName;
  28. UINT i;
  29. PNWR_NDS_REQUEST_PACKET Rrp;
  30. BYTE RrpData[1024];
  31. //
  32. // Prepare the open name.
  33. //
  34. uOpenName.MaximumLength = sizeof( NameStr );
  35. for ( i = 0; i < PreambleLength ; i++ )
  36. NameStr[i] = DevicePreamble[i];
  37. try {
  38. for ( i = 0 ; i < ( puNdsTree->Length / sizeof( WCHAR ) ) ; i++ ) {
  39. NameStr[i + PreambleLength] = puNdsTree->Buffer[i];
  40. }
  41. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  42. return STATUS_INVALID_PARAMETER;
  43. }
  44. uOpenName.Length = (USHORT)(( i * sizeof( WCHAR ) ) +
  45. ( PreambleLength * sizeof( WCHAR ) ));
  46. uOpenName.Buffer = NameStr;
  47. //
  48. // Set up the object attributes.
  49. //
  50. InitializeObjectAttributes(
  51. &ObjectAttributes,
  52. &uOpenName,
  53. OBJ_CASE_INSENSITIVE,
  54. NULL,
  55. NULL );
  56. //
  57. // Make the compiler happy about variable initialization.
  58. //
  59. RtlZeroMemory( &IoStatusBlock, sizeof( IO_STATUS_BLOCK ) );
  60. ntstatus = NtOpenFile(
  61. phNwRdrHandle,
  62. DesiredAccess,
  63. &ObjectAttributes,
  64. &IoStatusBlock,
  65. FILE_SHARE_VALID_FLAGS,
  66. FILE_SYNCHRONOUS_IO_NONALERT
  67. );
  68. if ( !NT_SUCCESS(ntstatus) )
  69. return ntstatus;
  70. OpenStatus = IoStatusBlock.Status;
  71. //
  72. // Verify that this is a tree handle, not a server handle.
  73. //
  74. Rrp = (PNWR_NDS_REQUEST_PACKET)RrpData;
  75. Rrp->Version = 0;
  76. RtlCopyMemory( &(Rrp->Parameters).VerifyTree,
  77. puNdsTree,
  78. sizeof( UNICODE_STRING ) );
  79. RtlCopyMemory( (BYTE *)(&(Rrp->Parameters).VerifyTree) + sizeof( UNICODE_STRING ),
  80. puNdsTree->Buffer,
  81. puNdsTree->Length );
  82. try {
  83. ntstatus = NtFsControlFile( *phNwRdrHandle,
  84. NULL,
  85. NULL,
  86. NULL,
  87. &IoStatusBlock,
  88. FSCTL_NWR_NDS_VERIFY_TREE,
  89. (PVOID) Rrp,
  90. sizeof( NWR_NDS_REQUEST_PACKET ) + puNdsTree->Length,
  91. NULL,
  92. 0 );
  93. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  94. ntstatus = GetExceptionCode();
  95. goto CloseAndExit2;
  96. }
  97. if ( !NT_SUCCESS( ntstatus ))
  98. {
  99. *lpdwHandleType = HANDLE_TYPE_NCP_SERVER;
  100. }
  101. else
  102. {
  103. *lpdwHandleType = HANDLE_TYPE_NDS_TREE;
  104. }
  105. return OpenStatus;
  106. CloseAndExit2:
  107. NtClose( *phNwRdrHandle );
  108. *phNwRdrHandle = NULL;
  109. return ntstatus;
  110. }
  111. NTSTATUS
  112. NwNdsSetTreeContext (
  113. IN HANDLE hNdsRdr,
  114. IN PUNICODE_STRING puTree,
  115. IN PUNICODE_STRING puContext
  116. )
  117. /*+++
  118. This sets the current context in the requested tree.
  119. ---*/
  120. {
  121. NTSTATUS ntstatus;
  122. IO_STATUS_BLOCK IoStatusBlock;
  123. PNWR_NDS_REQUEST_PACKET Rrp;
  124. DWORD RrpSize;
  125. BYTE *CurrentString;
  126. //
  127. // Set up the request.
  128. //
  129. RrpSize = sizeof( NWR_NDS_REQUEST_PACKET ) +
  130. puTree->Length +
  131. puContext->Length;
  132. Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
  133. if ( !Rrp ) {
  134. return STATUS_INSUFFICIENT_RESOURCES;
  135. }
  136. try {
  137. (Rrp->Parameters).SetContext.TreeNameLen = puTree->Length;
  138. (Rrp->Parameters).SetContext.ContextLen = puContext->Length;
  139. CurrentString = (BYTE *)(Rrp->Parameters).SetContext.TreeAndContextString;
  140. RtlCopyMemory( CurrentString, puTree->Buffer, puTree->Length );
  141. CurrentString += puTree->Length;
  142. RtlCopyMemory( CurrentString, puContext->Buffer, puContext->Length );
  143. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  144. ntstatus = STATUS_INVALID_PARAMETER;
  145. goto ExitWithCleanup;
  146. }
  147. try {
  148. ntstatus = NtFsControlFile( hNdsRdr,
  149. NULL,
  150. NULL,
  151. NULL,
  152. &IoStatusBlock,
  153. FSCTL_NWR_NDS_SETCONTEXT,
  154. (PVOID) Rrp,
  155. RrpSize,
  156. NULL,
  157. 0 );
  158. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  159. ntstatus = GetExceptionCode();
  160. goto ExitWithCleanup;
  161. }
  162. ExitWithCleanup:
  163. LocalFree( Rrp );
  164. return ntstatus;
  165. }
  166. NTSTATUS
  167. NwNdsGetTreeContext (
  168. IN HANDLE hNdsRdr,
  169. IN PUNICODE_STRING puTree,
  170. OUT PUNICODE_STRING puContext
  171. )
  172. /*+++
  173. This gets the current context of the requested tree.
  174. ---*/
  175. {
  176. NTSTATUS ntstatus;
  177. IO_STATUS_BLOCK IoStatusBlock;
  178. PNWR_NDS_REQUEST_PACKET Rrp;
  179. DWORD RrpSize;
  180. //
  181. // Set up the request.
  182. //
  183. RrpSize = sizeof( NWR_NDS_REQUEST_PACKET ) + puTree->Length;
  184. Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
  185. if ( !Rrp ) {
  186. return STATUS_INSUFFICIENT_RESOURCES;
  187. }
  188. try {
  189. (Rrp->Parameters).GetContext.TreeNameLen = puTree->Length;
  190. RtlCopyMemory( (BYTE *)(Rrp->Parameters).GetContext.TreeNameString,
  191. puTree->Buffer,
  192. puTree->Length );
  193. (Rrp->Parameters).GetContext.Context.MaximumLength = puContext->MaximumLength;
  194. (Rrp->Parameters).GetContext.Context.Length = 0;
  195. (Rrp->Parameters).GetContext.Context.Buffer = puContext->Buffer;
  196. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  197. ntstatus = STATUS_INVALID_PARAMETER;
  198. goto ExitWithCleanup;
  199. }
  200. try {
  201. ntstatus = NtFsControlFile( hNdsRdr,
  202. NULL,
  203. NULL,
  204. NULL,
  205. &IoStatusBlock,
  206. FSCTL_NWR_NDS_GETCONTEXT,
  207. (PVOID) Rrp,
  208. RrpSize,
  209. NULL,
  210. 0 );
  211. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  212. ntstatus = GetExceptionCode();
  213. goto ExitWithCleanup;
  214. }
  215. //
  216. // Copy out the length; the buffer has already been written.
  217. //
  218. puContext->Length = (Rrp->Parameters).GetContext.Context.Length;
  219. ExitWithCleanup:
  220. LocalFree( Rrp );
  221. return ntstatus;
  222. }
  223. NTSTATUS
  224. NwNdsIsNdsConnection (
  225. IN HANDLE hNdsRdr,
  226. OUT BOOL * pfIsNds,
  227. OUT PUNICODE_STRING puTree
  228. )
  229. /*+++
  230. This tests the current connection handle to see if it is one that is
  231. connected to a server in an NDS tree. If so, the name of the tree is
  232. put into puTree.
  233. ---*/
  234. {
  235. NTSTATUS ntstatus;
  236. IO_STATUS_BLOCK IoStatusBlock;
  237. PCONN_DETAILS2 Rrp;
  238. DWORD RrpSize;
  239. *pfIsNds = FALSE;
  240. //
  241. // Set up the request.
  242. //
  243. RrpSize = sizeof( CONN_DETAILS2 );
  244. Rrp = LocalAlloc( LMEM_ZEROINIT, RrpSize );
  245. if ( !Rrp )
  246. return STATUS_INSUFFICIENT_RESOURCES;
  247. try
  248. {
  249. ntstatus = NtFsControlFile( hNdsRdr,
  250. NULL,
  251. NULL,
  252. NULL,
  253. &IoStatusBlock,
  254. FSCTL_NWR_GET_CONN_DETAILS2,
  255. NULL,
  256. 0,
  257. (PVOID) Rrp,
  258. RrpSize );
  259. }
  260. except ( EXCEPTION_EXECUTE_HANDLER )
  261. {
  262. ntstatus = GetExceptionCode();
  263. goto ExitWithCleanup;
  264. }
  265. if ( ntstatus == STATUS_SUCCESS )
  266. {
  267. if ( Rrp->fNds )
  268. {
  269. puTree->Length = (USHORT) wcslen( Rrp->NdsTreeName );
  270. if ( puTree->MaximumLength >= puTree->Length )
  271. wcscpy( puTree->Buffer, Rrp->NdsTreeName );
  272. else
  273. puTree->Length = 0;
  274. *pfIsNds = TRUE;
  275. }
  276. }
  277. ExitWithCleanup:
  278. LocalFree( Rrp );
  279. return ntstatus;
  280. }
  281. NTSTATUS
  282. NwNdsList (
  283. IN HANDLE hNdsTree,
  284. IN DWORD dwObjectId,
  285. OUT DWORD *dwIterHandle,
  286. OUT BYTE *pbReplyBuf,
  287. IN DWORD dwReplyBufLen
  288. ) {
  289. NTSTATUS Status;
  290. IO_STATUS_BLOCK IoStatusBlock;
  291. PNWR_NDS_REQUEST_PACKET Rrp;
  292. PNDS_RESPONSE_SUBORDINATE_LIST Rsp;
  293. DWORD dwRspBufferLen;
  294. BYTE RrpData[256];
  295. BYTE RspData[1024];
  296. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  297. Rrp->Parameters.ListSubordinates.ObjectId = dwObjectId;
  298. Rrp->Parameters.ListSubordinates.IterHandle = *dwIterHandle;
  299. if ( dwReplyBufLen != 0 &&
  300. pbReplyBuf != NULL ) {
  301. Rsp = ( PNDS_RESPONSE_SUBORDINATE_LIST ) pbReplyBuf;
  302. dwRspBufferLen = dwReplyBufLen;
  303. } else {
  304. Rsp = ( PNDS_RESPONSE_SUBORDINATE_LIST ) RspData;
  305. dwRspBufferLen = 1024;
  306. }
  307. try {
  308. Status = NtFsControlFile( hNdsTree,
  309. NULL,
  310. NULL,
  311. NULL,
  312. &IoStatusBlock,
  313. FSCTL_NWR_NDS_LIST_SUBS,
  314. (PVOID) Rrp,
  315. sizeof( NWR_NDS_REQUEST_PACKET ),
  316. (PVOID) Rsp,
  317. dwRspBufferLen );
  318. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  319. return GetExceptionCode();
  320. }
  321. if ( Status == STATUS_SUCCESS )
  322. {
  323. *dwIterHandle = Rsp->IterationHandle;
  324. }
  325. return Status;
  326. }
  327. NTSTATUS
  328. NwNdsReadObjectInfo(
  329. IN HANDLE hNdsTree,
  330. IN DWORD dwObjectId,
  331. OUT BYTE *pbRawReply,
  332. IN DWORD dwReplyBufLen
  333. )
  334. {
  335. NTSTATUS Status;
  336. IO_STATUS_BLOCK IoStatusBlock;
  337. PNWR_NDS_REQUEST_PACKET Rrp;
  338. PNDS_RESPONSE_GET_OBJECT_INFO Rsp;
  339. DWORD dwRspBufferLen;
  340. BYTE RrpData[256];
  341. BYTE RspData[1024];
  342. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  343. Rrp->Parameters.GetObjectInfo.ObjectId = dwObjectId;
  344. if ( dwReplyBufLen != 0 &&
  345. pbRawReply != NULL ) {
  346. Rsp = ( PNDS_RESPONSE_GET_OBJECT_INFO ) pbRawReply;
  347. dwRspBufferLen = dwReplyBufLen;
  348. } else {
  349. Rsp = ( PNDS_RESPONSE_GET_OBJECT_INFO ) RspData;
  350. dwRspBufferLen = 1024;
  351. }
  352. try {
  353. Status = NtFsControlFile( hNdsTree,
  354. NULL,
  355. NULL,
  356. NULL,
  357. &IoStatusBlock,
  358. FSCTL_NWR_NDS_READ_INFO,
  359. (PVOID) Rrp,
  360. sizeof( NWR_NDS_REQUEST_PACKET ),
  361. (PVOID) Rsp,
  362. dwRspBufferLen );
  363. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  364. return GetExceptionCode();
  365. }
  366. return Status;
  367. }
  368. NTSTATUS
  369. NwNdsReadAttribute (
  370. IN HANDLE hNdsTree,
  371. IN DWORD dwObjectId,
  372. IN DWORD *dwIterHandle,
  373. IN PUNICODE_STRING puAttrName,
  374. OUT BYTE *pbReplyBuf,
  375. IN DWORD dwReplyBufLen
  376. ) {
  377. NTSTATUS ntstatus;
  378. IO_STATUS_BLOCK IoStatusBlock;
  379. PNWR_NDS_REQUEST_PACKET Rrp;
  380. PNDS_RESPONSE_READ_ATTRIBUTE Rsp = ( PNDS_RESPONSE_READ_ATTRIBUTE )
  381. pbReplyBuf;
  382. DWORD dwAttributeNameLen;
  383. BYTE RrpData[1024];
  384. //
  385. // Check the incoming buffer.
  386. //
  387. if ( !dwReplyBufLen || !Rsp )
  388. {
  389. return STATUS_INVALID_PARAMETER;
  390. }
  391. //
  392. // Set up the request.
  393. //
  394. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  395. RtlZeroMemory( Rrp, 1024 );
  396. (Rrp->Parameters).ReadAttribute.ObjectId = dwObjectId;
  397. (Rrp->Parameters).ReadAttribute.IterHandle = *dwIterHandle;
  398. //
  399. // Nds strings are NULL terminated; watch the size.
  400. //
  401. dwAttributeNameLen = puAttrName->Length + sizeof( WCHAR );
  402. (Rrp->Parameters).ReadAttribute.AttributeNameLength = dwAttributeNameLen;
  403. try {
  404. //
  405. // But don't try to copy more than the user gave us.
  406. //
  407. memcpy( (Rrp->Parameters).ReadAttribute.AttributeName,
  408. puAttrName->Buffer,
  409. puAttrName->Length );
  410. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  411. return STATUS_INVALID_PARAMETER;
  412. }
  413. //
  414. // Send the request to the Redirector FSD.
  415. //
  416. try {
  417. ntstatus = NtFsControlFile( hNdsTree,
  418. NULL,
  419. NULL,
  420. NULL,
  421. &IoStatusBlock,
  422. FSCTL_NWR_NDS_READ_ATTR,
  423. (PVOID) Rrp,
  424. sizeof( NWR_NDS_REQUEST_PACKET ) + dwAttributeNameLen,
  425. (PVOID) Rsp,
  426. dwReplyBufLen );
  427. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  428. return GetExceptionCode();
  429. }
  430. if ( ntstatus == STATUS_SUCCESS )
  431. {
  432. *dwIterHandle = Rsp->IterationHandle;
  433. }
  434. //
  435. // There's no buffer post processing on this one.
  436. //
  437. return ntstatus;
  438. }
  439. NTSTATUS
  440. NwNdsOpenStream (
  441. IN HANDLE hNdsTree,
  442. IN DWORD dwObjectId,
  443. IN PUNICODE_STRING puStreamName,
  444. IN DWORD dwOpenFlags,
  445. OUT DWORD *pdwFileLength
  446. ) {
  447. NTSTATUS ntstatus;
  448. IO_STATUS_BLOCK IoStatusBlock;
  449. PNWR_NDS_REQUEST_PACKET Rrp;
  450. BYTE RrpData[1024];
  451. //
  452. // Set up the request.
  453. //
  454. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  455. RtlZeroMemory( Rrp, 1024 );
  456. (Rrp->Parameters).OpenStream.StreamAccess = dwOpenFlags;
  457. (Rrp->Parameters).OpenStream.ObjectOid = dwObjectId;
  458. (Rrp->Parameters).OpenStream.StreamName.Length = puStreamName->Length;
  459. (Rrp->Parameters).OpenStream.StreamName.MaximumLength =
  460. sizeof( RrpData ) - sizeof( (Rrp->Parameters).OpenStream );
  461. (Rrp->Parameters).OpenStream.StreamName.Buffer =
  462. (Rrp->Parameters).OpenStream.StreamNameString;
  463. //
  464. // Make sure we're not trashing memory.
  465. //
  466. if ( (Rrp->Parameters).OpenStream.StreamName.Length >
  467. (Rrp->Parameters).OpenStream.StreamName.MaximumLength ) {
  468. return STATUS_INVALID_PARAMETER;
  469. }
  470. try {
  471. //
  472. // But don't try to copy more than the user gave us.
  473. //
  474. memcpy( (Rrp->Parameters).OpenStream.StreamNameString,
  475. puStreamName->Buffer,
  476. puStreamName->Length );
  477. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  478. return STATUS_INVALID_PARAMETER;
  479. }
  480. //
  481. // Send the request to the Redirector FSD.
  482. //
  483. try {
  484. ntstatus = NtFsControlFile( hNdsTree,
  485. NULL,
  486. NULL,
  487. NULL,
  488. &IoStatusBlock,
  489. FSCTL_NWR_NDS_OPEN_STREAM,
  490. (PVOID) Rrp,
  491. sizeof( NWR_NDS_REQUEST_PACKET ) + puStreamName->Length,
  492. NULL,
  493. 0 );
  494. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  495. return GetExceptionCode();
  496. }
  497. if ( pdwFileLength ) {
  498. *pdwFileLength = (Rrp->Parameters).OpenStream.FileLength;
  499. }
  500. return ntstatus;
  501. }
  502. NTSTATUS
  503. NwNdsGetQueueInformation(
  504. IN HANDLE hNdsTree,
  505. IN PUNICODE_STRING puQueueName,
  506. OUT PUNICODE_STRING puHostServer,
  507. OUT PDWORD pdwQueueId
  508. ) {
  509. NTSTATUS ntstatus;
  510. IO_STATUS_BLOCK IoStatusBlock;
  511. PNWR_NDS_REQUEST_PACKET Rrp;
  512. BYTE RrpData[1024];
  513. //
  514. // Set up the request.
  515. //
  516. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  517. RtlZeroMemory( Rrp, sizeof( RrpData ) );
  518. if ( puQueueName ) {
  519. (Rrp->Parameters).GetQueueInfo.QueueName.Length = puQueueName->Length;
  520. (Rrp->Parameters).GetQueueInfo.QueueName.MaximumLength = puQueueName->MaximumLength;
  521. (Rrp->Parameters).GetQueueInfo.QueueName.Buffer = puQueueName->Buffer;
  522. }
  523. if ( puHostServer ) {
  524. (Rrp->Parameters).GetQueueInfo.HostServer.Length = 0;
  525. (Rrp->Parameters).GetQueueInfo.HostServer.MaximumLength = puHostServer->MaximumLength;
  526. (Rrp->Parameters).GetQueueInfo.HostServer.Buffer = puHostServer->Buffer;
  527. }
  528. //
  529. // Send the request to the Redirector FSD.
  530. //
  531. try {
  532. ntstatus = NtFsControlFile( hNdsTree,
  533. NULL,
  534. NULL,
  535. NULL,
  536. &IoStatusBlock,
  537. FSCTL_NWR_NDS_GET_QUEUE_INFO,
  538. (PVOID) Rrp,
  539. sizeof( NWR_NDS_REQUEST_PACKET ),
  540. NULL,
  541. 0 );
  542. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  543. return GetExceptionCode();
  544. }
  545. if ( NT_SUCCESS( ntstatus ) ) {
  546. if ( pdwQueueId ) {
  547. *pdwQueueId = (Rrp->Parameters).GetQueueInfo.QueueId;
  548. }
  549. puHostServer->Length = (Rrp->Parameters).GetQueueInfo.HostServer.Length;
  550. }
  551. return ntstatus;
  552. }
  553. NTSTATUS
  554. NwNdsGetVolumeInformation(
  555. IN HANDLE hNdsTree,
  556. IN PUNICODE_STRING puVolumeName,
  557. OUT PUNICODE_STRING puHostServer,
  558. OUT PUNICODE_STRING puHostVolume
  559. ) {
  560. NTSTATUS ntstatus;
  561. IO_STATUS_BLOCK IoStatusBlock;
  562. PNWR_NDS_REQUEST_PACKET Rrp;
  563. DWORD RequestSize;
  564. BYTE RrpData[1024];
  565. BYTE ReplyData[1024];
  566. PBYTE NameStr;
  567. //
  568. // Set up the request.
  569. //
  570. Rrp = (PNWR_NDS_REQUEST_PACKET) RrpData;
  571. RtlZeroMemory( Rrp, sizeof( RrpData ) );
  572. if ( !puVolumeName ||
  573. puVolumeName->Length > MAX_NDS_NAME_SIZE ||
  574. !puHostServer ||
  575. !puHostVolume ) {
  576. return STATUS_INVALID_PARAMETER;
  577. }
  578. try {
  579. (Rrp->Parameters).GetVolumeInfo.VolumeNameLen = puVolumeName->Length;
  580. RtlCopyMemory( &((Rrp->Parameters).GetVolumeInfo.VolumeName[0]),
  581. puVolumeName->Buffer,
  582. puVolumeName->Length );
  583. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  584. return STATUS_INVALID_PARAMETER;
  585. }
  586. //
  587. // Send the request to the Redirector FSD.
  588. //
  589. RequestSize = sizeof( NWR_NDS_REQUEST_PACKET ) +
  590. (Rrp->Parameters).GetVolumeInfo.VolumeNameLen;
  591. try {
  592. ntstatus = NtFsControlFile( hNdsTree,
  593. NULL,
  594. NULL,
  595. NULL,
  596. &IoStatusBlock,
  597. FSCTL_NWR_NDS_GET_VOLUME_INFO,
  598. (PVOID) Rrp,
  599. RequestSize,
  600. ReplyData,
  601. sizeof( ReplyData ) );
  602. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  603. return GetExceptionCode();
  604. }
  605. if ( NT_SUCCESS( ntstatus ) ) {
  606. try {
  607. if ( ( puHostServer->MaximumLength < (Rrp->Parameters).GetVolumeInfo.ServerNameLen ) ||
  608. ( puHostVolume->MaximumLength < (Rrp->Parameters).GetVolumeInfo.TargetVolNameLen ) ) {
  609. return STATUS_BUFFER_TOO_SMALL;
  610. }
  611. puHostServer->Length = (USHORT)(Rrp->Parameters).GetVolumeInfo.ServerNameLen;
  612. puHostVolume->Length = (USHORT)(Rrp->Parameters).GetVolumeInfo.TargetVolNameLen;
  613. NameStr = &ReplyData[0];
  614. RtlCopyMemory( puHostServer->Buffer, NameStr, puHostServer->Length );
  615. NameStr += puHostServer->Length;
  616. RtlCopyMemory( puHostVolume->Buffer, NameStr, puHostVolume->Length );
  617. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  618. return STATUS_INVALID_PARAMETER;
  619. }
  620. }
  621. return ntstatus;
  622. }
  623. //
  624. // User mode fragment exchange.
  625. //
  626. int
  627. _cdecl
  628. FormatBuf(
  629. char *buf,
  630. int bufLen,
  631. const char *format,
  632. va_list args
  633. );
  634. int
  635. _cdecl
  636. CalculateBuf(
  637. const char *format,
  638. va_list args
  639. );
  640. int
  641. _cdecl
  642. FormatBuf(
  643. char *buf,
  644. int bufLen,
  645. const char *format,
  646. va_list args
  647. )
  648. /*
  649. Routine Description:
  650. Formats a buffer according to supplied the format string.
  651. FormatString - Supplies an ANSI string which describes how to
  652. convert from the input arguments into NCP request fields, and
  653. from the NCP response fields into the output arguments.
  654. Field types, request/response:
  655. 'b' byte ( byte / byte* )
  656. 'w' hi-lo word ( word / word* )
  657. 'd' hi-lo dword ( dword / dword* )
  658. 'W' lo-hi word ( word / word*)
  659. 'D' lo-hi dword ( dword / dword*)
  660. '-' zero/skip byte ( void )
  661. '=' zero/skip word ( void )
  662. ._. zero/skip string ( word )
  663. 'p' pstring ( char* )
  664. 'c' cstring ( char* )
  665. 'C' cstring followed skip word ( char*, word )
  666. 'V' sized NDS value ( byte *, dword / byte **, dword *)
  667. 'S' p unicode string copy as NDS_STRING (UNICODE_STRING *)
  668. 's' cstring copy as NDS_STRING (char* / char *, word)
  669. 'r' raw bytes ( byte*, word )
  670. 'u' p unicode string ( UNICODE_STRING * )
  671. 'U' p uppercase string( UNICODE_STRING * )
  672. Routine Arguments:
  673. char *buf - destination buffer.
  674. int buflen - length of the destination buffer.
  675. char *format - format string.
  676. args - args to the format string.
  677. Implementation Notes:
  678. This comes verbatim from kernel mode.
  679. */
  680. {
  681. ULONG ix;
  682. NTSTATUS status;
  683. const char *z = format;
  684. //
  685. // Convert the input arguments into request packet.
  686. //
  687. ix = 0;
  688. while ( *z )
  689. {
  690. switch ( *z )
  691. {
  692. case '=':
  693. buf[ix++] = 0;
  694. case '-':
  695. buf[ix++] = 0;
  696. break;
  697. case '_':
  698. {
  699. WORD l = va_arg ( args, WORD );
  700. if (ix + (ULONG)l > (ULONG)bufLen)
  701. {
  702. goto ErrorExit;
  703. }
  704. while ( l-- )
  705. buf[ix++] = 0;
  706. break;
  707. }
  708. case 'b':
  709. buf[ix++] = va_arg ( args, BYTE );
  710. break;
  711. case 'w':
  712. {
  713. WORD w = va_arg ( args, WORD );
  714. buf[ix++] = (BYTE) (w >> 8);
  715. buf[ix++] = (BYTE) (w >> 0);
  716. break;
  717. }
  718. case 'd':
  719. {
  720. DWORD d = va_arg ( args, DWORD );
  721. buf[ix++] = (BYTE) (d >> 24);
  722. buf[ix++] = (BYTE) (d >> 16);
  723. buf[ix++] = (BYTE) (d >> 8);
  724. buf[ix++] = (BYTE) (d >> 0);
  725. break;
  726. }
  727. case 'W':
  728. {
  729. WORD w = va_arg(args, WORD);
  730. (* (WORD *)&buf[ix]) = w;
  731. ix += 2;
  732. break;
  733. }
  734. case 'D':
  735. {
  736. DWORD d = va_arg (args, DWORD);
  737. (* (DWORD *)&buf[ix]) = d;
  738. ix += 4;
  739. break;
  740. }
  741. case 'c':
  742. {
  743. char* c = va_arg ( args, char* );
  744. WORD l = (WORD)strlen( c );
  745. if (ix + (ULONG)l > (ULONG)bufLen)
  746. {
  747. goto ErrorExit;
  748. }
  749. RtlCopyMemory( &buf[ix], c, l+1 );
  750. ix += l + 1;
  751. break;
  752. }
  753. case 'C':
  754. {
  755. char* c = va_arg ( args, char* );
  756. WORD l = va_arg ( args, WORD );
  757. WORD len = strlen( c ) + 1;
  758. if (ix + (ULONG)l > (ULONG)bufLen)
  759. {
  760. goto ErrorExit;
  761. }
  762. RtlCopyMemory( &buf[ix], c, len > l? l : len);
  763. ix += l;
  764. buf[ix-1] = 0;
  765. break;
  766. }
  767. case 'p':
  768. {
  769. char* c = va_arg ( args, char* );
  770. BYTE l = (BYTE)strlen( c );
  771. if (ix + (ULONG)l +1 > (ULONG)bufLen)
  772. {
  773. goto ErrorExit;
  774. }
  775. buf[ix++] = l;
  776. RtlCopyMemory( &buf[ix], c, l );
  777. ix += l;
  778. break;
  779. }
  780. case 'u':
  781. {
  782. PUNICODE_STRING pUString = va_arg ( args, PUNICODE_STRING );
  783. OEM_STRING OemString;
  784. ULONG Length;
  785. //
  786. // Calculate required string length, excluding trailing NUL.
  787. //
  788. Length = RtlUnicodeStringToOemSize( pUString ) - 1;
  789. ASSERT( Length < 0x100 );
  790. if ( ix + Length > (ULONG)bufLen ) {
  791. goto ErrorExit;
  792. }
  793. buf[ix++] = (UCHAR)Length;
  794. OemString.Buffer = &buf[ix];
  795. OemString.MaximumLength = (USHORT)Length + 1;
  796. status = RtlUnicodeStringToOemString( &OemString, pUString, FALSE );
  797. ASSERT( NT_SUCCESS( status ));
  798. ix += (USHORT)Length;
  799. break;
  800. }
  801. case 'S':
  802. {
  803. PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
  804. ULONG Length, rLength;
  805. Length = pUString->Length;
  806. if (ix + Length + sizeof(Length) + sizeof( WCHAR ) > (ULONG)bufLen) {
  807. goto ErrorExit;
  808. }
  809. //
  810. // The VLM client uses the rounded up length and it seems to
  811. // make a difference! Also, don't forget that NDS strings have
  812. // to be NULL terminated.
  813. //
  814. rLength = ROUNDUP4(Length + sizeof( WCHAR ));
  815. *((DWORD *)&buf[ix]) = rLength;
  816. ix += 4;
  817. RtlCopyMemory(&buf[ix], pUString->Buffer, Length);
  818. ix += Length;
  819. rLength -= Length;
  820. RtlFillMemory( &buf[ix], rLength, '\0' );
  821. ix += rLength;
  822. break;
  823. }
  824. case 's':
  825. {
  826. PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
  827. ULONG Length, rLength;
  828. Length = pUString->Length;
  829. if (ix + Length + sizeof(Length) + sizeof( WCHAR ) > (ULONG)bufLen) {
  830. // DebugTrace( 0, Dbg, "FormatBuf: case 's' request buffer too small.\n", 0 );
  831. goto ErrorExit;
  832. }
  833. //
  834. // Don't use the padded size here, only the NDS null terminator.
  835. //
  836. rLength = Length + sizeof( WCHAR );
  837. *((DWORD *)&buf[ix]) = rLength;
  838. ix += 4;
  839. RtlCopyMemory(&buf[ix], pUString->Buffer, Length);
  840. ix += Length;
  841. rLength -= Length;
  842. RtlFillMemory( &buf[ix], rLength, '\0' );
  843. ix += rLength;
  844. break;
  845. }
  846. case 'V':
  847. {
  848. // too similar to 'S' - should be combined
  849. BYTE* b = va_arg ( args, BYTE* );
  850. DWORD l = va_arg ( args, DWORD );
  851. if ( ix + l + sizeof(DWORD) > (ULONG)
  852. bufLen )
  853. {
  854. goto ErrorExit;
  855. }
  856. *((DWORD *)&buf[ix]) = l;
  857. ix += sizeof(DWORD);
  858. RtlCopyMemory( &buf[ix], b, l );
  859. l = ROUNDUP4(l);
  860. ix += l;
  861. break;
  862. }
  863. case 'r':
  864. {
  865. BYTE* b = va_arg ( args, BYTE* );
  866. WORD l = va_arg ( args, WORD );
  867. if ( b == NULL || l == 0 )
  868. {
  869. break;
  870. }
  871. if ( ix + l > (ULONG)bufLen )
  872. {
  873. goto ErrorExit;
  874. }
  875. RtlCopyMemory( &buf[ix], b, l );
  876. ix += l;
  877. break;
  878. }
  879. default:
  880. ;
  881. }
  882. if ( ix > (ULONG)bufLen )
  883. {
  884. goto ErrorExit;
  885. }
  886. z++;
  887. }
  888. return(ix);
  889. ErrorExit:
  890. return 0;
  891. }
  892. int
  893. _cdecl
  894. CalculateBuf(
  895. const char *format,
  896. va_list args
  897. )
  898. /*
  899. Routine Description:
  900. This routine calculates the buffer size needed to hold a request.
  901. FormatString - Supplies an ANSI string which describes how to
  902. convert from the input arguments into NCP request fields, and
  903. from the NCP response fields into the output arguments.
  904. Field types, request/response:
  905. 'b' byte ( byte / byte* )
  906. 'w' hi-lo word ( word / word* )
  907. 'd' hi-lo dword ( dword / dword* )
  908. 'W' lo-hi word ( word / word*)
  909. 'D' lo-hi dword ( dword / dword*)
  910. '-' zero/skip byte ( void )
  911. '=' zero/skip word ( void )
  912. ._. zero/skip string ( word )
  913. 'p' pstring ( char* )
  914. 'c' cstring ( char* )
  915. 'C' cstring followed skip word ( char*, word )
  916. 'V' sized NDS value ( byte *, dword / byte **, dword *)
  917. 'S' p unicode string copy as NDS_STRING (UNICODE_STRING *)
  918. 's' cstring copy as NDS_STRING (char* / char *, word)
  919. 'r' raw bytes ( byte*, word )
  920. 'u' p unicode string ( UNICODE_STRING * )
  921. 'U' p uppercase string( UNICODE_STRING * )
  922. Routine Arguments:
  923. char *format - format string.
  924. args - args to the format string.
  925. Implementation Notes:
  926. This comes verbatim from kernel mode.
  927. */
  928. {
  929. ULONG ix;
  930. const char *z = format;
  931. //
  932. // Convert the input arguments into request packet.
  933. //
  934. ix = 0;
  935. while ( *z )
  936. {
  937. switch ( *z )
  938. {
  939. case '=':
  940. ix++;
  941. case '-':
  942. ix++;
  943. break;
  944. case '_':
  945. {
  946. WORD l = va_arg ( args, WORD );
  947. ix += l;
  948. break;
  949. }
  950. case 'b':
  951. {
  952. char b = va_arg ( args, BYTE );
  953. ix++;
  954. break;
  955. }
  956. case 'w':
  957. {
  958. WORD w = va_arg ( args, WORD );
  959. ix += 2;
  960. break;
  961. }
  962. case 'd':
  963. {
  964. DWORD d = va_arg ( args, DWORD );
  965. ix += 4;
  966. break;
  967. }
  968. case 'W':
  969. {
  970. WORD w = va_arg(args, WORD);
  971. ix += 2;
  972. break;
  973. }
  974. case 'D':
  975. {
  976. DWORD d = va_arg (args, DWORD);
  977. ix += 4;
  978. break;
  979. }
  980. case 'c':
  981. {
  982. char* c = va_arg ( args, char* );
  983. WORD l = (WORD)strlen( c );
  984. ix += l + 1;
  985. break;
  986. }
  987. case 'C':
  988. {
  989. char* c = va_arg ( args, char* );
  990. WORD l = va_arg ( args, WORD );
  991. WORD len = strlen( c ) + 1;
  992. ix += l;
  993. break;
  994. }
  995. case 'p':
  996. {
  997. char* c = va_arg ( args, char* );
  998. BYTE l = (BYTE)strlen( c );
  999. ix++;
  1000. ix += l;
  1001. break;
  1002. }
  1003. case 'u':
  1004. {
  1005. PUNICODE_STRING pUString = va_arg ( args, PUNICODE_STRING );
  1006. OEM_STRING OemString;
  1007. ULONG Length;
  1008. //
  1009. // Calculate required string length, excluding trailing NUL.
  1010. //
  1011. Length = RtlUnicodeStringToOemSize( pUString ) - 1;
  1012. ASSERT( Length < 0x100 );
  1013. ix++;
  1014. ix += (USHORT)Length;
  1015. break;
  1016. }
  1017. case 'S':
  1018. {
  1019. PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
  1020. ULONG Length, rLength;
  1021. Length = pUString->Length;
  1022. //
  1023. // The VLM client uses the rounded up length and it seems to
  1024. // make a difference! Also, don't forget that NDS strings have
  1025. // to be NULL terminated.
  1026. //
  1027. rLength = ROUNDUP4(Length + sizeof( WCHAR ));
  1028. ix += 4;
  1029. ix += Length;
  1030. rLength -= Length;
  1031. ix += rLength;
  1032. break;
  1033. }
  1034. case 's':
  1035. {
  1036. PUNICODE_STRING pUString = va_arg (args, PUNICODE_STRING);
  1037. ULONG Length, rLength;
  1038. Length = pUString->Length;
  1039. //
  1040. // Don't use the padded size here, only the NDS null terminator.
  1041. //
  1042. rLength = Length + sizeof( WCHAR );
  1043. ix += 4;
  1044. ix += Length;
  1045. rLength -= Length;
  1046. ix += rLength;
  1047. break;
  1048. }
  1049. case 'V':
  1050. {
  1051. // too similar to 'S' - should be combined
  1052. BYTE* b = va_arg ( args, BYTE* );
  1053. DWORD l = va_arg ( args, DWORD );
  1054. ix += sizeof(DWORD);
  1055. l = ROUNDUP4(l);
  1056. ix += l;
  1057. break;
  1058. }
  1059. case 'r':
  1060. {
  1061. BYTE* b = va_arg ( args, BYTE* );
  1062. WORD l = va_arg ( args, WORD );
  1063. if ( b == NULL || l == 0 )
  1064. {
  1065. break;
  1066. }
  1067. ix += l;
  1068. break;
  1069. }
  1070. default:
  1071. ;
  1072. }
  1073. z++;
  1074. }
  1075. return(ix);
  1076. }
  1077. NTSTATUS
  1078. _cdecl
  1079. ParseResponse(
  1080. PUCHAR Response,
  1081. ULONG ResponseLength,
  1082. char* FormatString,
  1083. ... // format specific parameters
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. This routine parse an NCP response.
  1088. Packet types:
  1089. 'G' Generic packet ( )
  1090. Field types, request/response:
  1091. 'b' byte ( byte* )
  1092. 'w' hi-lo word ( word* )
  1093. 'x' ordered word ( word* )
  1094. 'd' hi-lo dword ( dword* )
  1095. 'e' ordered dword ( dword* )
  1096. '-' zero/skip byte ( void )
  1097. '=' zero/skip word ( void )
  1098. ._. zero/skip string ( word )
  1099. 'p' pstring ( char* )
  1100. 'c' cstring ( char* )
  1101. 'r' raw bytes ( byte*, word )
  1102. Added 3/29/95 by CoryWest:
  1103. 'W' lo-hi word ( word / word*)
  1104. 'D' lo-hi dword ( dword / dword*)
  1105. 'S' unicode string copy as NDS_STRING (UNICODE_STRING *)
  1106. 'T' terminal unicode string copy as NDS_STRING (UNICODE_STRING *)
  1107. 't' terminal unicode string with the nds null copied
  1108. as NDS_STRING (UNICODE_STRING *) (for GetUseName)
  1109. Return Value:
  1110. STATUS - Success or failure, depending on the response.
  1111. --*/
  1112. {
  1113. NTSTATUS Status = STATUS_SUCCESS;
  1114. PCHAR FormatByte;
  1115. va_list Arguments;
  1116. ULONG Length = 0;
  1117. va_start( Arguments, FormatString );
  1118. //
  1119. // User mode parse response handles only generic packets.
  1120. //
  1121. if ( *FormatString != 'G' ) {
  1122. return STATUS_INVALID_PARAMETER;
  1123. }
  1124. FormatByte = FormatString + 1;
  1125. while ( *FormatByte ) {
  1126. switch ( *FormatByte ) {
  1127. case '-':
  1128. Length += 1;
  1129. break;
  1130. case '=':
  1131. Length += 2;
  1132. break;
  1133. case '_':
  1134. {
  1135. WORD l = va_arg ( Arguments, WORD );
  1136. Length += l;
  1137. break;
  1138. }
  1139. case 'b':
  1140. {
  1141. BYTE* b = va_arg ( Arguments, BYTE* );
  1142. *b = Response[Length++];
  1143. break;
  1144. }
  1145. case 'w':
  1146. {
  1147. BYTE* b = va_arg ( Arguments, BYTE* );
  1148. b[1] = Response[Length++];
  1149. b[0] = Response[Length++];
  1150. break;
  1151. }
  1152. case 'x':
  1153. {
  1154. WORD* w = va_arg ( Arguments, WORD* );
  1155. *w = *(WORD UNALIGNED *)&Response[Length];
  1156. Length += 2;
  1157. break;
  1158. }
  1159. case 'd':
  1160. {
  1161. BYTE* b = va_arg ( Arguments, BYTE* );
  1162. b[3] = Response[Length++];
  1163. b[2] = Response[Length++];
  1164. b[1] = Response[Length++];
  1165. b[0] = Response[Length++];
  1166. break;
  1167. }
  1168. case 'e':
  1169. {
  1170. DWORD UNALIGNED * d = va_arg ( Arguments, DWORD* );
  1171. *d = *(DWORD UNALIGNED *)&Response[Length];
  1172. Length += 4;
  1173. break;
  1174. }
  1175. case 'c':
  1176. {
  1177. char* c = va_arg ( Arguments, char* );
  1178. WORD l = (WORD)strlen( &Response[Length] );
  1179. memcpy ( c, &Response[Length], l+1 );
  1180. Length += l+1;
  1181. break;
  1182. }
  1183. case 'p':
  1184. {
  1185. char* c = va_arg ( Arguments, char* );
  1186. BYTE l = Response[Length++];
  1187. memcpy ( c, &Response[Length], l );
  1188. c[l+1] = 0;
  1189. break;
  1190. }
  1191. case 'r':
  1192. {
  1193. BYTE* b = va_arg ( Arguments, BYTE* );
  1194. WORD l = va_arg ( Arguments, WORD );
  1195. RtlCopyMemory( b, &Response[Length], l );
  1196. Length += l;
  1197. break;
  1198. }
  1199. case 'W':
  1200. {
  1201. WORD *w = va_arg ( Arguments, WORD* );
  1202. *w = (* (WORD *)&Response[Length]);
  1203. Length += 2;
  1204. break;
  1205. }
  1206. case 'D':
  1207. {
  1208. DWORD *d = va_arg ( Arguments, DWORD* );
  1209. *d = (* (DWORD *)&Response[Length]);
  1210. Length += 4;
  1211. break;
  1212. }
  1213. case 'S':
  1214. {
  1215. PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
  1216. USHORT strl;
  1217. if (pU) {
  1218. strl = (USHORT)(* (DWORD *)&Response[Length]);
  1219. //
  1220. // Don't count the null terminator that is part of
  1221. // Novell's counted unicode string.
  1222. //
  1223. pU->Length = strl - sizeof( WCHAR );
  1224. Length += 4;
  1225. RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
  1226. Length += ROUNDUP4(strl);
  1227. } else {
  1228. //
  1229. // Skip over the string since we don't want it.
  1230. //
  1231. Length += ROUNDUP4((* (DWORD *)&Response[Length] ));
  1232. Length += 4;
  1233. }
  1234. break;
  1235. }
  1236. case 's':
  1237. {
  1238. PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
  1239. USHORT strl;
  1240. if (pU) {
  1241. strl = (USHORT)(* (DWORD *)&Response[Length]);
  1242. pU->Length = strl;
  1243. Length += 4;
  1244. RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
  1245. Length += ROUNDUP4(strl);
  1246. } else {
  1247. //
  1248. // Skip over the string since we don't want it.
  1249. //
  1250. Length += ROUNDUP4((* (DWORD *)&Response[Length] ));
  1251. Length += 4;
  1252. }
  1253. break;
  1254. }
  1255. case 'T':
  1256. {
  1257. PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
  1258. USHORT strl;
  1259. if (pU) {
  1260. strl = (USHORT)(* (DWORD *)&Response[Length] );
  1261. strl -= sizeof( WCHAR ); // Don't count the NULL from NDS.
  1262. if ( strl <= pU->MaximumLength ) {
  1263. pU->Length = strl;
  1264. Length += 4;
  1265. RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
  1266. //
  1267. // No need to advance the pointers since this is
  1268. // specifically a termination case!
  1269. //
  1270. } else {
  1271. pU->Length = 0;
  1272. }
  1273. }
  1274. break;
  1275. }
  1276. case 't':
  1277. {
  1278. PUNICODE_STRING pU = va_arg( Arguments, PUNICODE_STRING );
  1279. USHORT strl;
  1280. if (pU) {
  1281. strl = (USHORT)(* (DWORD *)&Response[Length] );
  1282. if ( strl <= pU->MaximumLength ) {
  1283. pU->Length = strl;
  1284. Length += 4;
  1285. RtlCopyMemory( pU->Buffer, &Response[Length], pU->Length );
  1286. //
  1287. // No need to advance the pointers since this is
  1288. // specifically a termination case!
  1289. //
  1290. } else {
  1291. pU->Length = 0;
  1292. }
  1293. }
  1294. break;
  1295. }
  1296. }
  1297. if ( Length > ResponseLength ) {
  1298. return( STATUS_INVALID_PARAMETER );
  1299. }
  1300. FormatByte++;
  1301. }
  1302. va_end( Arguments );
  1303. return( Status );
  1304. }
  1305. NTSTATUS
  1306. NwNdsChangePassword(
  1307. IN HANDLE hNwRdr,
  1308. IN PUNICODE_STRING puTreeName,
  1309. IN PUNICODE_STRING puUserName,
  1310. IN PUNICODE_STRING puCurrentPassword,
  1311. IN PUNICODE_STRING puNewPassword
  1312. ) {
  1313. NTSTATUS Status;
  1314. PNWR_NDS_REQUEST_PACKET pNdsRequest;
  1315. DWORD dwRequestLength;
  1316. PBYTE CurrentString;
  1317. IO_STATUS_BLOCK IoStatusBlock;
  1318. //
  1319. // Allocate the request.
  1320. //
  1321. dwRequestLength = sizeof( NWR_NDS_REQUEST_PACKET ) +
  1322. puTreeName->Length +
  1323. puUserName->Length +
  1324. puCurrentPassword->Length +
  1325. puNewPassword->Length;
  1326. pNdsRequest = LocalAlloc( LMEM_ZEROINIT, dwRequestLength );
  1327. if ( !pNdsRequest) {
  1328. return STATUS_INSUFFICIENT_RESOURCES;
  1329. }
  1330. //
  1331. // Copy the parameters into the request buffer.
  1332. //
  1333. try {
  1334. (pNdsRequest->Parameters).ChangePass.NdsTreeNameLength =
  1335. puTreeName->Length;
  1336. (pNdsRequest->Parameters).ChangePass.UserNameLength =
  1337. puUserName->Length;
  1338. (pNdsRequest->Parameters).ChangePass.CurrentPasswordLength =
  1339. puCurrentPassword->Length;
  1340. (pNdsRequest->Parameters).ChangePass.NewPasswordLength =
  1341. puNewPassword->Length;
  1342. CurrentString = ( PBYTE ) &((pNdsRequest->Parameters).ChangePass.StringBuffer[0]);
  1343. RtlCopyMemory( CurrentString, puTreeName->Buffer, puTreeName->Length );
  1344. CurrentString += puTreeName->Length;
  1345. RtlCopyMemory( CurrentString, puUserName->Buffer, puUserName->Length );
  1346. CurrentString += puUserName->Length;
  1347. RtlCopyMemory( CurrentString, puCurrentPassword->Buffer, puCurrentPassword->Length );
  1348. CurrentString += puCurrentPassword->Length;
  1349. RtlCopyMemory( CurrentString, puNewPassword->Buffer, puNewPassword->Length );
  1350. Status = NtFsControlFile( hNwRdr,
  1351. NULL,
  1352. NULL,
  1353. NULL,
  1354. &IoStatusBlock,
  1355. FSCTL_NWR_NDS_CHANGE_PASS,
  1356. (PVOID) pNdsRequest,
  1357. dwRequestLength,
  1358. NULL,
  1359. 0 );
  1360. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  1361. Status = STATUS_INVALID_PARAMETER;
  1362. }
  1363. LocalFree( pNdsRequest );
  1364. return Status;
  1365. }