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.

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