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.

1842 lines
48 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: fsctrl.c
  6. //
  7. // Contents:
  8. // This module implements the File System Control routines for Dsfs called
  9. // by the dispatch driver.
  10. //
  11. // Functions:
  12. // DfsFsdFileSystemControl
  13. // DfsFspFileSystemControl
  14. // DfsCommonFileSystemControl, local
  15. // DfsUserFsctl, local
  16. // DfsInsertProvider - Helper routine for DfsFsctrlDefineProvider
  17. // DfsFsctrlReadCtrs - Read the Dfs driver perfmon counters
  18. // DfsFsctrlGetServerName - Get name of server given prefix
  19. // DfsFsctrlReadStruct - return an internal data struct (debug build only)
  20. // DfsFsctrlReadMem - return internal memory (debug build only)
  21. // DfsCompleteMountRequest - Completion routine for mount IRP
  22. // DfsCompleteLoadFsRequest - Completion routine for Load FS IRP
  23. //
  24. //-----------------------------------------------------------------------------
  25. #include "dfsprocs.h"
  26. #include "attach.h"
  27. #include "registry.h"
  28. #include "regkeys.h"
  29. #include "know.h"
  30. #include "localvol.h"
  31. #include "lvolinit.h"
  32. #include "fsctrl.h"
  33. #include "sitesup.h"
  34. #include "ipsup.h"
  35. #include "spcsup.h"
  36. #include "dfslpc.h"
  37. #include "dfswml.h"
  38. //
  39. // The local debug trace level
  40. //
  41. #define Dbg (DEBUG_TRACE_FSCTRL)
  42. //
  43. // Local procedure prototypes
  44. //
  45. NTSTATUS
  46. DfsCommonFileSystemControl (
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp
  49. );
  50. NTSTATUS
  51. DfsUserFsctl (
  52. IN PIRP Irp
  53. );
  54. NTSTATUS
  55. DfsFsctrlStartDfs(
  56. IN PIRP Irp);
  57. VOID DfsSetMachineState();
  58. NTSTATUS
  59. DfsFsctrlGetServerName(
  60. IN PIRP Irp,
  61. IN PUCHAR InputBuffer,
  62. IN ULONG InputBufferLength,
  63. IN PUCHAR OutputBuffer,
  64. IN ULONG OutputBufferLength);
  65. #if DBG
  66. NTSTATUS
  67. DfsFsctrlReadStruct (
  68. IN PIRP Irp,
  69. IN PFILE_DFS_READ_STRUCT_PARAM pRsParam,
  70. IN ULONG InputBufferLength,
  71. IN OUT PUCHAR OutputBuffer,
  72. IN ULONG OutputBufferLength
  73. );
  74. NTSTATUS
  75. DfsFsctrlReadMem (
  76. IN PIRP Irp,
  77. IN PFILE_DFS_READ_MEM Request,
  78. IN ULONG InputBufferLength,
  79. IN OUT PUCHAR OutputBuffer,
  80. IN ULONG OutputBufferLength
  81. );
  82. #endif
  83. NTSTATUS
  84. DfsCompleteMountRequest(
  85. IN PDEVICE_OBJECT DeviceObject,
  86. IN PIRP Irp,
  87. IN PVOID Context
  88. );
  89. NTSTATUS
  90. DfsCompleteLoadFsRequest(
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN PIRP Irp,
  93. IN PVOID Context
  94. );
  95. NTSTATUS
  96. DfsFsctrlGetPkt(
  97. IN PIRP Irp,
  98. IN PUCHAR OutputBuffer,
  99. IN ULONG OutputBufferLength);
  100. NTSTATUS
  101. DfsGetPktSize(
  102. OUT PULONG pSize);
  103. NTSTATUS
  104. DfsGetPktMarshall(
  105. IN PBYTE Buffer,
  106. IN ULONG Size);
  107. #if DBG
  108. VOID
  109. DfsGetDebugFlags(void);
  110. #endif
  111. VOID
  112. DfsGetEventLogValue(VOID);
  113. #ifdef ALLOC_PRAGMA
  114. #pragma alloc_text( PAGE, DfsFsdFileSystemControl )
  115. #pragma alloc_text( PAGE, DfsCommonFileSystemControl )
  116. #pragma alloc_text( PAGE, DfsUserFsctl )
  117. #pragma alloc_text( PAGE, DfsSetMachineState)
  118. #pragma alloc_text( PAGE, DfsInsertProvider )
  119. #pragma alloc_text( PAGE, DfsFsctrlGetServerName )
  120. #pragma alloc_text( PAGE, DfspStringInBuffer)
  121. #pragma alloc_text( PAGE, DfsFsctrlGetPkt)
  122. #pragma alloc_text( PAGE, DfsGetPktSize)
  123. #pragma alloc_text( PAGE, DfsGetPktMarshall)
  124. #if DBG
  125. #pragma alloc_text( PAGE, DfsFsctrlReadStruct )
  126. #pragma alloc_text( PAGE, DfsFsctrlReadMem )
  127. #endif // DBG
  128. //
  129. // The following routines cannot be paged because they are completion
  130. // routines which can be called at raised IRQL
  131. //
  132. // DfsCompleteMountRequest
  133. // DfsCompleteLoadFsRequest
  134. //
  135. #endif // ALLOC_PRAGMA
  136. //+-------------------------------------------------------------------
  137. //
  138. // Function: DfsFsdFileSystemControl, public
  139. //
  140. // Synopsis: This routine implements the FSD part of FileSystem
  141. // control operations
  142. //
  143. // Arguments: [DeviceObject] -- Supplies the volume device object
  144. // where the file exists
  145. // [Irp] -- Supplies the Irp being processed
  146. //
  147. // Returns: [NTSTATUS] -- The FSD status for the IRP
  148. //
  149. //--------------------------------------------------------------------
  150. NTSTATUS
  151. DfsFsdFileSystemControl (
  152. IN PDEVICE_OBJECT DeviceObject,
  153. IN PIRP Irp
  154. ) {
  155. BOOLEAN Wait;
  156. NTSTATUS Status;
  157. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  158. PFILE_OBJECT FileObject = IrpSp->FileObject;
  159. DebugTrace(+1, Dbg, "DfsFsdFileSystemControl\n", 0);
  160. DFS_TRACE_HIGH(TRACE_IRP, DfsFsdFileSystemControl_Entry,
  161. LOGPTR(FileObject)
  162. LOGPTR(Irp));
  163. //
  164. // Call the common FileSystem Control routine, with blocking allowed
  165. // if synchronous. This opeation needs to special case the mount
  166. // and verify suboperations because we know they are allowed to block.
  167. // We identify these suboperations by looking at the file object field
  168. // and seeing if it's null.
  169. //
  170. if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {
  171. Wait = TRUE;
  172. } else {
  173. Wait = CanFsdWait( Irp );
  174. }
  175. FsRtlEnterFileSystem();
  176. try {
  177. Status = DfsCommonFileSystemControl( DeviceObject, Irp );
  178. } except( DfsExceptionFilter( GetExceptionCode(), GetExceptionInformation() )) {
  179. //
  180. // We had some trouble trying to perform the requested
  181. // operation, so we'll abort the I/O request with
  182. // the error status that we get back from the
  183. // execption code
  184. //
  185. Status = DfsProcessException( Irp, GetExceptionCode() );
  186. }
  187. FsRtlExitFileSystem();
  188. //
  189. // And return to our caller
  190. //
  191. DebugTrace(-1, Dbg, "DfsFsdFileSystemControl -> %08lx\n", ULongToPtr( Status ));
  192. DFS_TRACE_HIGH(TRACE_IRP, DfsFsdFileSystemControl_Exit,
  193. LOGSTATUS(Status)
  194. LOGPTR(FileObject)
  195. LOGPTR(Irp));
  196. return Status;
  197. }
  198. //+-------------------------------------------------------------------
  199. //
  200. // Function: DfsCommonFileSystemControl, local
  201. //
  202. // Synopsis: This is the common routine for doing FileSystem control
  203. // operations called by both the FSD and FSP threads
  204. //
  205. // Arguments: [DeviceObject] -- The one used to enter our FSD Routine
  206. // [Irp] -- Supplies the Irp to process
  207. //
  208. // Returns: NTSTATUS - The return status for the operation
  209. //--------------------------------------------------------------------
  210. NTSTATUS
  211. DfsCommonFileSystemControl (
  212. IN PDEVICE_OBJECT DeviceObject,
  213. IN PIRP Irp
  214. ) {
  215. NTSTATUS Status;
  216. PIO_STACK_LOCATION IrpSp, NextIrpSp;
  217. PFILE_OBJECT FileObject;
  218. ULONG FsControlCode;
  219. //
  220. // Get a pointer to the current Irp stack location
  221. //
  222. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  223. FileObject = IrpSp->FileObject;
  224. DFS_TRACE_LOW(TRACE_IRP, DfsCommonFileSystemControl_Entry,
  225. LOGPTR(FileObject)
  226. LOGPTR(Irp));
  227. FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  228. DebugTrace(+1, Dbg, "DfsCommonFileSystemControl\n", 0);
  229. DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  230. DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);
  231. //
  232. // We know this is a file system control so we'll case on the
  233. // minor function, and call a internal worker routine to complete
  234. // the irp.
  235. //
  236. switch (IrpSp->MinorFunction) {
  237. case IRP_MN_USER_FS_REQUEST:
  238. //
  239. // If the FSCTL is issued via a device that is not
  240. // the DFS file system device object, then reject the request.
  241. //
  242. if (IS_DFS_CTL_CODE( FsControlCode )) {
  243. if (DeviceObject == DfsData.FileSysDeviceObject) {
  244. Status = DfsUserFsctl( Irp );
  245. }
  246. else {
  247. DebugTrace(0, Dbg,"Dfs Fsctrl from invalid device object!\n", 0);
  248. Status = STATUS_INVALID_DEVICE_REQUEST;
  249. DFS_TRACE_HIGH(ERROR, DfsCommonFileSystemControl_Error_FsctrlFromInvalidDeviceObj,
  250. LOGPTR(Irp)
  251. LOGPTR(FileObject)
  252. LOGSTATUS(Status));
  253. DfsCompleteRequest( Irp, Status );
  254. }
  255. } else if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME ||
  256. DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {
  257. Status = DfsVolumePassThrough(DeviceObject, Irp);
  258. DebugTrace(0, Dbg, "Pass through user fsctrl -> %08lx\n", ULongToPtr( Status ) );
  259. } else {
  260. DebugTrace(0, Dbg, "Non Dfs Fsctrl code to Dfs File System Object!\n", 0);
  261. Status = STATUS_INVALID_DEVICE_REQUEST;
  262. DfsCompleteRequest( Irp, Status );
  263. }
  264. break;
  265. case IRP_MN_MOUNT_VOLUME:
  266. case IRP_MN_VERIFY_VOLUME:
  267. ASSERT( DeviceObject != NULL );
  268. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  269. Status = DfsVolumePassThrough(DeviceObject, Irp);
  270. DebugTrace(0, Dbg, "Pass through user fsctrl -> %08lx\n", ULongToPtr( Status ) );
  271. } else if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {
  272. //
  273. // We are processing a MOUNT/VERIFY request being directed to
  274. // another File System to which we have attached our own
  275. // Attach File System Object. We setup a completion routine
  276. // and forward the request.
  277. //
  278. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  279. (*NextIrpSp) = (*IrpSp);
  280. IoSetCompletionRoutine(
  281. Irp,
  282. DfsCompleteMountRequest,
  283. NULL,
  284. TRUE,
  285. TRUE,
  286. TRUE);
  287. //
  288. // We want to pass the real device to the underlying file system
  289. // so it can do its mount. See the comment in
  290. // DfsCompleteMountRequest.
  291. //
  292. IrpSp->Parameters.MountVolume.DeviceObject =
  293. IrpSp->Parameters.MountVolume.Vpb->RealDevice;
  294. //
  295. // Call the underlying file system via its file system device
  296. //
  297. Status = IoCallDriver(
  298. ((PDFS_ATTACH_FILE_SYSTEM_OBJECT)
  299. DeviceObject)->TargetDevice,
  300. Irp );
  301. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonFileSystemControl_Error_Vol_IoCallDriver,
  302. LOGSTATUS(Status)
  303. LOGPTR(FileObject)
  304. LOGPTR(Irp));
  305. } else {
  306. //
  307. // We are processing a MOUNT/VERIFY request being directed to our
  308. // our File System Device Object. We don't directly support
  309. // disk volumes, so we simply reject.
  310. //
  311. ASSERT(DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM);
  312. Status = STATUS_NOT_SUPPORTED;
  313. DfsCompleteRequest( Irp, Status );
  314. }
  315. break;
  316. case IRP_MN_LOAD_FILE_SYSTEM:
  317. //
  318. // This is a "load file system" fsctrl being sent to a file system
  319. // recognizer to which we are attached. We first detach from the
  320. // recognizer (so it can delete itself), then setup a completion
  321. // routine and forward the request.
  322. //
  323. ASSERT( DeviceObject != NULL );
  324. IoDetachDevice(
  325. ((PDFS_ATTACH_FILE_SYSTEM_OBJECT) DeviceObject)->TargetDevice);
  326. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  327. (*NextIrpSp) = (*IrpSp);
  328. IoSetCompletionRoutine(
  329. Irp,
  330. DfsCompleteLoadFsRequest,
  331. NULL,
  332. TRUE,
  333. TRUE,
  334. TRUE);
  335. Status = IoCallDriver(
  336. ((PDFS_ATTACH_FILE_SYSTEM_OBJECT)
  337. DeviceObject)->TargetDevice,
  338. Irp );
  339. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonFileSystemControl_Error_FS_IoCallDriver,
  340. LOGSTATUS(Status)
  341. LOGPTR(FileObject)
  342. LOGPTR(Irp));
  343. break;
  344. default:
  345. //
  346. // Pass through all the rest we dont care about.
  347. //
  348. DebugTrace(0, Dbg, "Unknown FS Control Minor Function %08lx\n",
  349. IrpSp->MinorFunction);
  350. Status = DfsVolumePassThrough(DeviceObject, Irp);
  351. break;
  352. }
  353. DebugTrace(-1, Dbg, "DfsCommonFileSystemControl -> %08lx\n", ULongToPtr( Status ));
  354. DFS_TRACE_LOW(TRACE_IRP, DfsCommonFileSystemControl_Exit,
  355. LOGSTATUS(Status)
  356. LOGPTR(FileObject)
  357. LOGPTR(Irp));
  358. return Status;
  359. }
  360. //+----------------------------------------------------------------------------
  361. //
  362. // Function: DfsCompleteMountRequest, local
  363. //
  364. // Synopsis: Completion routine for a MOUNT fsctrl that was passed through
  365. // to the underlying File System Device Object.
  366. //
  367. // This routine will simply see if the MOUNT succeeded. If it
  368. // did, this routine will call DfsReattachToMountedVolume so
  369. // any local volumes which were disabled by the unmount will be
  370. // enabled again.
  371. //
  372. // Arguments: [DeviceObject] -- Our Attached File System Object.
  373. // [Irp] -- The MOUNT fsctrl IRP.
  374. // [Context] -- Unused
  375. //
  376. // Returns: [STATUS_SUCCESS] -- Always.
  377. //
  378. //-----------------------------------------------------------------------------
  379. NTSTATUS
  380. DfsCompleteMountRequest(
  381. IN PDEVICE_OBJECT DeviceObject,
  382. IN PIRP Irp,
  383. IN PVOID Context)
  384. {
  385. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  386. PDEVICE_OBJECT targetDevice;
  387. PVPB vpb;
  388. //
  389. // Determine whether or not the request was successful and act accordingly.
  390. //
  391. DebugTrace(+1, Dbg,
  392. "DfsCompleteMountRequest: Entered %08lx\n", ULongToPtr( Irp->IoStatus.Status ));
  393. if (NT_SUCCESS( Irp->IoStatus.Status )) {
  394. //
  395. // Note that the VPB must be picked up from the target device object
  396. // in case the file system did a remount of a previous volume, in
  397. // which case it has replaced the VPB passed in as the target with
  398. // a previously mounted VPB. Note also that in the mount dispatch
  399. // routine, this driver *replaced* the DeviceObject pointer with a
  400. // pointer to the real device, not the device that the file system
  401. // was supposed to talk to, since this driver does not care.
  402. //
  403. vpb = irpSp->Parameters.MountVolume.DeviceObject->Vpb;
  404. targetDevice = IoGetAttachedDevice( vpb->DeviceObject );
  405. DebugTrace(0, Dbg, "Target Device %08lx\n", targetDevice);
  406. DfsReattachToMountedVolume( targetDevice, vpb );
  407. }
  408. //
  409. // If pending was returned, then propogate it to the caller.
  410. //
  411. if (Irp->PendingReturned) {
  412. IoMarkIrpPending( Irp );
  413. }
  414. DebugTrace(-1, Dbg, "DfsCompleteMountRequest: Exited\n", 0);
  415. return( STATUS_SUCCESS );
  416. }
  417. //+----------------------------------------------------------------------------
  418. //
  419. // Function: DfsCompleteLoadFsRequest, local
  420. //
  421. // Synopsis: Completion routine for a LOAD_FILE_SYSTEM fsctrl Irp. If
  422. // the load did not succeed, this routine simply reattaches our
  423. // Attached File System Object to the recognizer. If the load
  424. // succeeds, this routine arranges to delete the Attached File
  425. // System Object that was originally attached to the recognizer.
  426. //
  427. // Arguments: [DeviceObject] -- Attached File System Object.
  428. // [Irp] -- The LOAD_FILE_SYSTEM Fsctrl Irp.
  429. // [Context] -- Unused.
  430. //
  431. // Returns: [STATUS_SUCCESS] -- Always.
  432. //
  433. //-----------------------------------------------------------------------------
  434. NTSTATUS
  435. DfsCompleteLoadFsRequest(
  436. IN PDEVICE_OBJECT DeviceObject,
  437. IN PIRP Irp,
  438. IN PVOID Context)
  439. {
  440. if (NT_SUCCESS(Irp->IoStatus.Status)) {
  441. RemoveEntryList(
  442. &((PDFS_ATTACH_FILE_SYSTEM_OBJECT) DeviceObject)->FsoLinks);
  443. //
  444. // Due to refcounting done by the IO Subsystem, there's no way to
  445. // delete the DeviceObject.
  446. //
  447. } else {
  448. IoAttachDeviceByPointer(
  449. DeviceObject,
  450. ((PDFS_ATTACH_FILE_SYSTEM_OBJECT) DeviceObject)->TargetDevice);
  451. }
  452. //
  453. // If pending was returned, then propogate it to the caller
  454. //
  455. if (Irp->PendingReturned) {
  456. IoMarkIrpPending( Irp );
  457. }
  458. return( STATUS_SUCCESS );
  459. }
  460. //+-------------------------------------------------------------------
  461. //
  462. // Function: DfsUserFsctl, local
  463. //
  464. // Synopsis: This is the common routine for implementing the user's
  465. // requests made through NtFsControlFile.
  466. //
  467. // Arguments: [Irp] -- Supplies the Irp being processed
  468. //
  469. // Returns: NTSTATUS - The return status for the operation
  470. //
  471. //--------------------------------------------------------------------
  472. NTSTATUS
  473. DfsUserFsctl (
  474. IN PIRP Irp
  475. ) {
  476. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  477. PIO_STACK_LOCATION NextIrpSp;
  478. NTSTATUS Status;
  479. ULONG FsControlCode;
  480. ULONG cbOutput;
  481. ULONG cbInput;
  482. PUCHAR InputBuffer;
  483. PUCHAR OutputBuffer;
  484. //
  485. // Just in case some-one (cough) forgets about it...
  486. // ...zero information status now!
  487. //
  488. Irp->IoStatus.Information = 0L;
  489. FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  490. cbInput = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  491. cbOutput = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  492. DebugTrace(+1, Dbg, "DfsUserFsctl: Entered\n", 0);
  493. DebugTrace( 0, Dbg, "DfsUserFsctl: Cntrl Code -> %08lx\n", ULongToPtr( FsControlCode ));
  494. DebugTrace( 0, Dbg, "DfsUserFsctl: cbInput -> %08lx\n", ULongToPtr( cbInput ));
  495. DebugTrace( 0, Dbg, "DfsUserFsctl: cbOutput -> %08lx\n", ULongToPtr( cbOutput ));
  496. //
  497. // All DFS FsControlCodes use METHOD_BUFFERED, so the SystemBuffer
  498. // is used for both the input and output.
  499. //
  500. InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
  501. DebugTrace( 0, Dbg, "DfsUserFsctl: InputBuffer -> %08lx\n", InputBuffer);
  502. DebugTrace( 0, Dbg, "DfsUserFsctl: UserBuffer -> %08lx\n", Irp->UserBuffer);
  503. //
  504. // Case on the control code.
  505. //
  506. switch ( FsControlCode ) {
  507. case FSCTL_REQUEST_OPLOCK_LEVEL_1:
  508. case FSCTL_REQUEST_OPLOCK_LEVEL_2:
  509. case FSCTL_REQUEST_BATCH_OPLOCK:
  510. case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
  511. case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
  512. case FSCTL_OPLOCK_BREAK_NOTIFY:
  513. case FSCTL_DFS_READ_METERS:
  514. case FSCTL_SRV_DFSSRV_IPADDR:
  515. Status = STATUS_INVALID_DEVICE_REQUEST;
  516. DfsCompleteRequest( Irp, Status );
  517. break;
  518. case FSCTL_DISMOUNT_VOLUME:
  519. Status = STATUS_NOT_SUPPORTED;
  520. DfsCompleteRequest( Irp, Status );
  521. break;
  522. case FSCTL_DFS_GET_VERSION:
  523. if (OutputBuffer != NULL &&
  524. cbOutput >= sizeof(DFS_GET_VERSION_ARG)) {
  525. PDFS_GET_VERSION_ARG parg =
  526. (PDFS_GET_VERSION_ARG) OutputBuffer;
  527. parg->Version = 1;
  528. Status = STATUS_SUCCESS;
  529. Irp->IoStatus.Information = sizeof(DFS_GET_VERSION_ARG);
  530. } else {
  531. Status = STATUS_INVALID_PARAMETER;
  532. }
  533. DfsCompleteRequest(Irp, Status);
  534. break;
  535. case FSCTL_DFS_IS_ROOT:
  536. if (DfsData.MachineState == DFS_UNKNOWN) {
  537. DfsSetMachineState();
  538. }
  539. if (DfsData.MachineState == DFS_ROOT_SERVER) {
  540. Status = STATUS_SUCCESS;
  541. } else {
  542. Status = STATUS_INVALID_DOMAIN_ROLE;
  543. }
  544. DfsCompleteRequest(Irp, Status);
  545. break;
  546. case FSCTL_DFS_ISDC:
  547. DfsData.IsDC = TRUE;
  548. Status = STATUS_SUCCESS;
  549. DfsCompleteRequest(Irp, Status);
  550. break;
  551. case FSCTL_DFS_ISNOTDC:
  552. DfsData.IsDC = FALSE;
  553. Status = STATUS_SUCCESS;
  554. DfsCompleteRequest(Irp, Status);
  555. break;
  556. case FSCTL_DFS_GET_ENTRY_TYPE:
  557. Status = DfsFsctrlGetEntryType(
  558. Irp,
  559. InputBuffer,
  560. cbInput,
  561. OutputBuffer,
  562. cbOutput);
  563. break;
  564. case FSCTL_DFS_MODIFY_PREFIX:
  565. Status = DfsFsctrlModifyLocalVolPrefix(
  566. Irp,
  567. InputBuffer,
  568. cbInput
  569. );
  570. break;
  571. case FSCTL_DFS_CREATE_EXIT_POINT:
  572. Status = DfsFsctrlCreateExitPoint(
  573. Irp,
  574. InputBuffer,
  575. cbInput,
  576. OutputBuffer,
  577. cbOutput
  578. );
  579. break;
  580. case FSCTL_DFS_DELETE_EXIT_POINT:
  581. Status = DfsFsctrlDeleteExitPoint(
  582. Irp,
  583. InputBuffer,
  584. cbInput
  585. );
  586. break;
  587. case FSCTL_DFS_START_DFS:
  588. DfsGetEventLogValue();
  589. #if DBG
  590. DfsGetDebugFlags();
  591. #endif // DBG
  592. Status = DfsFsctrlStartDfs(
  593. Irp);
  594. if (DfsData.MachineState == DFS_UNKNOWN) {
  595. DfsSetMachineState();
  596. }
  597. //
  598. // Try to validate our local partitions with a DC
  599. //
  600. break;
  601. case FSCTL_DFS_STOP_DFS:
  602. DfsGetEventLogValue();
  603. #if DBG
  604. DfsGetDebugFlags();
  605. #endif // DBG
  606. Status = DfsFsctrlStopDfs(
  607. Irp
  608. );
  609. break;
  610. case FSCTL_DFS_RESET_PKT:
  611. Status = DfsFsctrlResetPkt(
  612. Irp
  613. );
  614. break;
  615. case FSCTL_DFS_MARK_STALE_PKT_ENTRIES:
  616. Status = DfsFsctrlMarkStalePktEntries(
  617. Irp
  618. );
  619. break;
  620. case FSCTL_DFS_FLUSH_STALE_PKT_ENTRIES:
  621. Status = DfsFsctrlFlushStalePktEntries(
  622. Irp
  623. );
  624. break;
  625. case FSCTL_DFS_INIT_LOCAL_PARTITIONS:
  626. DfsInitLocalPartitions();
  627. Status = STATUS_SUCCESS;
  628. DfsCompleteRequest( Irp, Status);
  629. break;
  630. case FSCTL_DFS_CREATE_LOCAL_PARTITION:
  631. Status = DfsFsctrlCreateLocalPartition(
  632. Irp,
  633. InputBuffer,
  634. cbInput
  635. );
  636. break;
  637. case FSCTL_DFS_CREATE_SITE_INFO:
  638. Status = DfsFsctrlCreateSiteInfo(
  639. Irp,
  640. InputBuffer,
  641. cbInput
  642. );
  643. break;
  644. case FSCTL_DFS_DELETE_SITE_INFO:
  645. Status = DfsFsctrlDeleteSiteInfo(
  646. Irp,
  647. InputBuffer,
  648. cbInput
  649. );
  650. break;
  651. case FSCTL_DFS_CREATE_IP_INFO:
  652. Status = DfsFsctrlCreateIpInfo(
  653. Irp,
  654. InputBuffer,
  655. cbInput
  656. );
  657. break;
  658. case FSCTL_DFS_DELETE_IP_INFO:
  659. Status = DfsFsctrlDeleteIpInfo(
  660. Irp,
  661. InputBuffer,
  662. cbInput
  663. );
  664. break;
  665. case FSCTL_DFS_CREATE_SPECIAL_INFO:
  666. Status = DfsFsctrlCreateSpcInfo(
  667. DfsData.SpcHashTable,
  668. Irp,
  669. InputBuffer,
  670. cbInput
  671. );
  672. break;
  673. case FSCTL_DFS_DELETE_SPECIAL_INFO:
  674. Status = DfsFsctrlDeleteSpcInfo(
  675. DfsData.SpcHashTable,
  676. Irp,
  677. InputBuffer,
  678. cbInput
  679. );
  680. break;
  681. case FSCTL_DFS_CREATE_FTDFS_INFO:
  682. Status = DfsFsctrlCreateSpcInfo(
  683. DfsData.FtDfsHashTable,
  684. Irp,
  685. InputBuffer,
  686. cbInput
  687. );
  688. break;
  689. case FSCTL_DFS_DELETE_FTDFS_INFO:
  690. Status = DfsFsctrlDeleteSpcInfo(
  691. DfsData.FtDfsHashTable,
  692. Irp,
  693. InputBuffer,
  694. cbInput
  695. );
  696. break;
  697. case FSCTL_DFS_DELETE_LOCAL_PARTITION:
  698. Status = DfsFsctrlDeleteLocalPartition(
  699. Irp,
  700. InputBuffer,
  701. cbInput
  702. );
  703. break;
  704. case FSCTL_DFS_SET_LOCAL_VOLUME_STATE:
  705. Status = DfsFsctrlSetVolumeState(
  706. Irp,
  707. InputBuffer,
  708. cbInput);
  709. break;
  710. case FSCTL_DFS_SET_SERVICE_STATE:
  711. Status = DfsFsctrlSetServiceState(
  712. Irp,
  713. InputBuffer,
  714. cbInput);
  715. break;
  716. case FSCTL_DFS_DC_SET_VOLUME_STATE:
  717. Status = DfsFsctrlDCSetVolumeState(
  718. Irp,
  719. InputBuffer,
  720. cbInput);
  721. break;
  722. case FSCTL_DFS_SET_VOLUME_TIMEOUT:
  723. Status = DfsFsctrlSetVolumeTimeout(
  724. Irp,
  725. InputBuffer,
  726. cbInput);
  727. break;
  728. case FSCTL_DFS_IS_CHILDNAME_LEGAL:
  729. Status = PktFsctrlIsChildnameLegal(
  730. Irp,
  731. InputBuffer,
  732. cbInput);
  733. break;
  734. case FSCTL_DFS_PKT_CREATE_ENTRY:
  735. Status = PktFsctrlCreateEntry(
  736. Irp,
  737. InputBuffer,
  738. cbInput
  739. );
  740. break;
  741. case FSCTL_DFS_PKT_CREATE_SUBORDINATE_ENTRY:
  742. Status = PktFsctrlCreateSubordinateEntry(
  743. Irp,
  744. InputBuffer,
  745. cbInput
  746. );
  747. break;
  748. case FSCTL_DFS_PKT_DESTROY_ENTRY:
  749. Status = PktFsctrlDestroyEntry(
  750. Irp,
  751. InputBuffer,
  752. cbInput
  753. );
  754. break;
  755. case FSCTL_DFS_PKT_SET_RELATION_INFO:
  756. Status = PktFsctrlSetRelationInfo(
  757. Irp,
  758. InputBuffer,
  759. cbInput
  760. );
  761. break;
  762. case FSCTL_DFS_PKT_GET_RELATION_INFO:
  763. Status = PktFsctrlGetRelationInfo(
  764. Irp,
  765. InputBuffer,
  766. cbInput,
  767. OutputBuffer,
  768. cbOutput
  769. );
  770. break;
  771. case FSCTL_DFS_GET_SERVER_INFO:
  772. Status = DfsFsctrlGetServerInfo(
  773. Irp,
  774. InputBuffer,
  775. cbInput,
  776. OutputBuffer,
  777. cbOutput);
  778. break;
  779. case FSCTL_DFS_SET_SERVER_INFO:
  780. Status = PktFsctrlSetServerInfo(
  781. Irp,
  782. InputBuffer,
  783. cbInput);
  784. break;
  785. case FSCTL_DFS_CHECK_STGID_IN_USE:
  786. Status = DfsFsctrlCheckStgIdInUse(
  787. Irp,
  788. InputBuffer,
  789. cbInput,
  790. OutputBuffer,
  791. cbOutput);
  792. break;
  793. case FSCTL_DFS_VERIFY_LOCAL_VOLUME_KNOWLEDGE:
  794. Status = PktFsctrlVerifyLocalVolumeKnowledge(
  795. Irp,
  796. InputBuffer,
  797. cbInput
  798. );
  799. break;
  800. case FSCTL_DFS_PRUNE_LOCAL_PARTITION:
  801. Status = PktFsctrlPruneLocalVolume(
  802. Irp,
  803. InputBuffer,
  804. cbInput);
  805. break;
  806. case FSCTL_DFS_FIX_LOCAL_VOLUME:
  807. Status = DfsFsctrlFixLocalVolumeKnowledge(Irp,
  808. InputBuffer,
  809. cbInput);
  810. break;
  811. case FSCTL_DFS_GET_SERVER_NAME:
  812. Status = DfsFsctrlGetServerName(Irp,
  813. InputBuffer,
  814. cbInput,
  815. OutputBuffer,
  816. cbOutput);
  817. break;
  818. case FSCTL_SRV_DFSSRV_CONNECT:
  819. Status = PktFsctrlDfsSrvConnect(Irp,
  820. InputBuffer,
  821. cbInput);
  822. break;
  823. case FSCTL_DFS_GET_PKT:
  824. Status = DfsFsctrlGetPkt(Irp,
  825. OutputBuffer,
  826. cbOutput);
  827. break;
  828. case FSCTL_DFS_GET_NEXT_LONG_DOMAIN_NAME:
  829. Status = DfsFsctrlGetDomainToRefresh(Irp,
  830. OutputBuffer,
  831. cbOutput);
  832. break;
  833. case FSCTL_DFS_REREAD_REGISTRY:
  834. DfsGetEventLogValue();
  835. #if DBG
  836. DfsGetDebugFlags();
  837. DbgPrint("DfsDebugTraceLevel=0x%x\n", DfsDebugTraceLevel);
  838. DbgPrint("DfsEventLog=0x%x\n", DfsEventLog);
  839. #endif // DBG
  840. DfspGetMaxReferrals();
  841. Status = STATUS_SUCCESS;
  842. DfsCompleteRequest(Irp, Status);
  843. break;
  844. #if DBG
  845. case FSCTL_DFS_PKT_FLUSH_CACHE:
  846. Status = PktFsctrlFlushCache(Irp, InputBuffer, cbInput);
  847. break;
  848. case FSCTL_DFS_DBG_BREAK:
  849. DbgBreakPoint();
  850. Status = STATUS_SUCCESS;
  851. DfsCompleteRequest(Irp, Status);
  852. break;
  853. case FSCTL_DFS_DBG_FLAGS:
  854. DfsDebugTraceLevel = * ((PULONG) InputBuffer);
  855. Status = STATUS_SUCCESS;
  856. DfsCompleteRequest(Irp, Status);
  857. break;
  858. case FSCTL_DFS_SHUFFLE_ENTRY:
  859. Status = PktFsctrlShufflePktEntry(
  860. Irp,
  861. InputBuffer,
  862. cbInput);
  863. break;
  864. case FSCTL_DFS_INTERNAL_READ_MEM:
  865. Status = DfsFsctrlReadMem(
  866. Irp,
  867. (PFILE_DFS_READ_MEM)InputBuffer,
  868. cbInput,
  869. OutputBuffer,
  870. cbOutput );
  871. break;
  872. case FSCTL_DFS_INTERNAL_READSTRUCT:
  873. Status = DfsFsctrlReadStruct(
  874. Irp,
  875. (PFILE_DFS_READ_STRUCT_PARAM)InputBuffer,
  876. cbInput,
  877. OutputBuffer,
  878. cbOutput );
  879. break;
  880. #endif // DBG
  881. default:
  882. //
  883. // This is not a recognized DFS fsctrl.
  884. //
  885. Status = STATUS_INVALID_PARAMETER;
  886. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  887. break;
  888. }
  889. DebugTrace(-1, Dbg, "DfsUserFsctl: Exit -> %08lx\n", ULongToPtr( Status ) );
  890. return Status;
  891. }
  892. //+----------------------------------------------------------------------------
  893. //
  894. // Function: DfsFsctrlStartDfs
  895. //
  896. // Synopsis: Sets the state of the Dfs driver so that it will start
  897. // receiving open requests.
  898. //
  899. // Arguments: [Irp] --
  900. //
  901. // Returns: [STATUS_SUCCESS] -- Successfully set the state to started.
  902. //
  903. // [STATUS_UNSUCCESSFUL] -- An error occured trying to set the
  904. // state of Dfs to started. This is most likely because
  905. // of a failure to register with the MUP.
  906. //
  907. //-----------------------------------------------------------------------------
  908. NTSTATUS
  909. DfsFsctrlStartDfs(
  910. IN PIRP Irp)
  911. {
  912. NTSTATUS status;
  913. UNICODE_STRING dfsRootDeviceName;
  914. STD_FSCTRL_PROLOGUE("DfsFsctrlStartDfs", FALSE, FALSE);
  915. RtlInitUnicodeString(&dfsRootDeviceName, DFS_DEVICE_ROOT);
  916. DfsSetMachineState();
  917. DfsData.OperationalState = DFS_STATE_STARTED;
  918. status = STATUS_SUCCESS;
  919. DebugTrace(-1, Dbg, "DfsFsctrlStartDfs - returning %08lx\n", ULongToPtr( status ));
  920. DfsCompleteRequest(Irp, status);
  921. return( status );
  922. }
  923. //+----------------------------------------------------------------------------
  924. //
  925. // Function: DfsSetMachineState
  926. //
  927. // Synopsis: Gets the machine state from the registry and sets it in
  928. // DfsData structure.
  929. //
  930. // Arguments: None
  931. //
  932. // Returns: Nothing
  933. //
  934. //-----------------------------------------------------------------------------
  935. VOID DfsSetMachineState()
  936. {
  937. NTSTATUS Status;
  938. DebugTrace(+1, Dbg, "DfsSetMachineState - Entered\n", 0);
  939. Status = KRegSetRoot( wszRegRootVolumes );
  940. if (NT_SUCCESS(Status)) {
  941. DebugTrace(0, Dbg, "Found volumes dir %ws\n", wszRegRootVolumes );
  942. DfsData.MachineState = DFS_ROOT_SERVER;
  943. KRegCloseRoot();
  944. } else if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
  945. Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  946. //
  947. // We default to DFS_CLIENT. When we later try to initialize local
  948. // volumes, if we do have any, we'll upgrade ourselves to
  949. // DFS_SERVER
  950. //
  951. DfsData.MachineState = DFS_CLIENT;
  952. Status = STATUS_SUCCESS;
  953. } else {
  954. DebugTrace(0, Dbg, "Error %08lx opening volumes dir!\n", ULongToPtr( Status ) );
  955. DfsData.MachineState = DFS_UNKNOWN;
  956. }
  957. DebugTrace(-1, Dbg, "DfsSetMachineState - Exited!\n", 0);
  958. }
  959. //+----------------------------------------------------------------------------
  960. //
  961. // Function: DfsInsertProvider
  962. //
  963. // Synopsis: Given a provider name, id, and capability, will add a new or
  964. // overwrite an existing provider definition.
  965. //
  966. // Arguments:
  967. //
  968. // Returns:
  969. //
  970. //-----------------------------------------------------------------------------
  971. NTSTATUS DfsInsertProvider(
  972. IN PUNICODE_STRING ProviderName,
  973. IN ULONG fProvCapability,
  974. IN ULONG eProviderId)
  975. {
  976. PPROVIDER_DEF pProv = DfsData.pProvider;
  977. int iProv;
  978. //
  979. // Find a free provider structure, or overwrite an existing one.
  980. //
  981. for (iProv = 0; iProv < DfsData.cProvider; iProv++, pProv++) {
  982. if (pProv->eProviderId == eProviderId)
  983. break;
  984. }
  985. if (iProv >= DfsData.maxProvider) {
  986. ASSERT(iProv >= DfsData.maxProvider && "Out of provider structs");
  987. return(STATUS_INSUFFICIENT_RESOURCES);
  988. }
  989. if (iProv < DfsData.cProvider) {
  990. //
  991. // Decrement reference counts on saved objects
  992. //
  993. if (pProv->FileObject)
  994. ObDereferenceObject(pProv->FileObject);
  995. if (pProv->DeviceObject)
  996. ObDereferenceObject(pProv->DeviceObject);
  997. if (pProv->DeviceName.Buffer)
  998. ExFreePool(pProv->DeviceName.Buffer);
  999. }
  1000. pProv->FileObject = NULL;
  1001. pProv->DeviceObject = NULL;
  1002. pProv->eProviderId = (USHORT) eProviderId;
  1003. pProv->fProvCapability = (USHORT) fProvCapability;
  1004. pProv->DeviceName = *ProviderName;
  1005. if (iProv == DfsData.cProvider) {
  1006. DfsData.cProvider++;
  1007. }
  1008. return(STATUS_SUCCESS);
  1009. }
  1010. //+----------------------------------------------------------------------------
  1011. //
  1012. // Function: DfsFsctrlGetServerName
  1013. //
  1014. // Synopsis: Given a Prefix in Dfs namespace it gets a server name for
  1015. // it.
  1016. //
  1017. // Arguments:
  1018. //
  1019. // Returns:
  1020. //
  1021. //-----------------------------------------------------------------------------
  1022. NTSTATUS
  1023. DfsFsctrlGetServerName(
  1024. IN PIRP Irp,
  1025. IN PUCHAR InputBuffer,
  1026. IN ULONG InputBufferLength,
  1027. IN PUCHAR OutputBuffer,
  1028. IN ULONG OutputBufferLength)
  1029. {
  1030. NTSTATUS status = STATUS_SUCCESS;
  1031. PDFS_PKT pkt;
  1032. PWCHAR pwchServer = (PWCHAR) OutputBuffer;
  1033. ULONG cChServer = 0;
  1034. ULONG MaxAllowed;
  1035. PDFS_PKT_ENTRY pEntry;
  1036. PWCHAR pwszPrefix = (PWCHAR) InputBuffer;
  1037. UNICODE_STRING ustrPrefix, RemainingPath;
  1038. PDFS_SERVICE pService;
  1039. PWCHAR pwch;
  1040. ULONG i;
  1041. STD_FSCTRL_PROLOGUE(DfsFsctrlGetServerName, TRUE, TRUE);
  1042. DebugTrace(+1,Dbg,"DfsFsctrlGetServerName()\n", 0);
  1043. //
  1044. // InputBuffer is a WCHAR. Check that the buffer is of even size, and
  1045. // has at least one character in it.
  1046. //
  1047. if (InputBufferLength < sizeof(WCHAR) || (InputBufferLength & 0x1) != 0) {
  1048. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  1049. status = STATUS_INVALID_PARAMETER;
  1050. return status;
  1051. }
  1052. //
  1053. // Confirm there's a UNICODE NULL in there somewhere.
  1054. //
  1055. for (i = 0; i < InputBufferLength / sizeof(WCHAR); i++) {
  1056. if (pwszPrefix[i] == UNICODE_NULL) {
  1057. break;
  1058. }
  1059. }
  1060. if (i >= InputBufferLength / sizeof(WCHAR)) {
  1061. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  1062. status = STATUS_INVALID_PARAMETER;
  1063. return status;
  1064. }
  1065. //
  1066. // Need to be able to put at least a UNICODE_NULL in the output buffer
  1067. //
  1068. if (OutputBufferLength >= sizeof(WCHAR)) {
  1069. MaxAllowed = OutputBufferLength/sizeof(WCHAR) - 1;
  1070. } else {
  1071. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  1072. status = STATUS_INVALID_PARAMETER;
  1073. return status;
  1074. }
  1075. //
  1076. // Found a UNICODE_NULL in the buffer, so off we go...
  1077. //
  1078. RtlInitUnicodeString(&ustrPrefix, pwszPrefix);
  1079. pkt = _GetPkt();
  1080. PktAcquireExclusive(pkt, TRUE);
  1081. pEntry = PktLookupEntryByPrefix(pkt,
  1082. &ustrPrefix,
  1083. &RemainingPath);
  1084. if (pEntry == NULL) {
  1085. status = STATUS_OBJECT_NAME_NOT_FOUND;
  1086. } else {
  1087. //
  1088. // If there is a local service then return a NULL string.
  1089. //
  1090. if (pEntry->LocalService != NULL) {
  1091. *pwchServer = UNICODE_NULL;
  1092. cChServer = 1;
  1093. } else {
  1094. if (pEntry->ActiveService != NULL) {
  1095. pService = pEntry->ActiveService;
  1096. } else if (pEntry->Info.ServiceCount == 0) {
  1097. pService = NULL;
  1098. } else {
  1099. //
  1100. // Take first service.
  1101. //
  1102. pService = pEntry->Info.ServiceList;
  1103. }
  1104. if (pService != NULL) {
  1105. pwch = pService->Address.Buffer;
  1106. ASSERT(*pwch == L'\\');
  1107. pwch++;
  1108. while (*pwch != L'\\') {
  1109. *pwchServer++ = *pwch++;
  1110. if (++cChServer >= MaxAllowed) {
  1111. break;
  1112. }
  1113. }
  1114. *pwchServer = UNICODE_NULL;
  1115. DebugTrace(0, Dbg, "SERVERName Created %ws\n", pwchServer);
  1116. } else {
  1117. DebugTrace(0, Dbg, "No Service Exists for %ws\n", pwszPrefix);
  1118. status = DFS_STATUS_NO_SUCH_ENTRY;
  1119. }
  1120. }
  1121. }
  1122. PktRelease(pkt);
  1123. Irp->IoStatus.Information = cChServer * sizeof(WCHAR);
  1124. DfsCompleteRequest( Irp, status );
  1125. DebugTrace(-1,Dbg,"DfsFsctrlGetServerName: Exit->%08lx\n", ULongToPtr( status ));
  1126. return status;
  1127. }
  1128. //+----------------------------------------------------------------------------
  1129. //
  1130. // Function: DfspValidateString, private
  1131. //
  1132. // Synopsis: Check that a LPWSTR lies within a buffer.
  1133. //
  1134. // Arguments: [pwszString] -- pointer to string
  1135. //
  1136. // Returns: TRUE - string lies within buffer
  1137. // FALSE - bad alignment or string doesn't lie within buffer
  1138. //
  1139. //-----------------------------------------------------------------------------
  1140. BOOLEAN
  1141. DfspStringInBuffer(LPWSTR pwszString, PVOID Buffer, ULONG BufferLen)
  1142. {
  1143. PCHAR BufferEnd = (PCHAR)Buffer + BufferLen;
  1144. PWCHAR wcp;
  1145. //
  1146. // Buffer has to be large enough to at least contain a UNICODE_NULL
  1147. // The buffer has to be aligned correctly
  1148. // The start of the string has to lie within the buffer
  1149. //
  1150. if (BufferLen < sizeof(WCHAR) ||
  1151. !ALIGNMENT_IS_VALID(Buffer, PWCHAR) ||
  1152. !POINTER_IS_VALID(pwszString, Buffer, BufferLen)
  1153. ) {
  1154. return FALSE;
  1155. }
  1156. //
  1157. // Scan the string and be sure we find a UNICODE_NULL within the buffer
  1158. //
  1159. for (wcp = pwszString; (PCHAR)wcp < BufferEnd; wcp++) {
  1160. if (*wcp == UNICODE_NULL) {
  1161. break;
  1162. }
  1163. }
  1164. if ((PCHAR)wcp >= BufferEnd) {
  1165. return FALSE;
  1166. }
  1167. //
  1168. // Looks good!!
  1169. //
  1170. return TRUE;
  1171. }
  1172. //+----------------------------------------------------------------------------
  1173. //
  1174. // Function: DfsFsctrlGetPkt
  1175. //
  1176. // Synopsis: Returns the current (cached Pkt)
  1177. //
  1178. // Arguments:
  1179. //
  1180. // Returns:
  1181. //
  1182. //-----------------------------------------------------------------------------
  1183. NTSTATUS
  1184. DfsFsctrlGetPkt(
  1185. IN PIRP Irp,
  1186. IN PUCHAR OutputBuffer,
  1187. IN ULONG OutputBufferLength)
  1188. {
  1189. NTSTATUS NtStatus = STATUS_SUCCESS;
  1190. PDFS_PKT pkt;
  1191. BOOLEAN pktLocked = FALSE;
  1192. ULONG cbOutBuffer;
  1193. DebugTrace(+1, Dbg, "DfsFsctrlGetPkt\n", 0);
  1194. STD_FSCTRL_PROLOGUE("DfsFsctrlGetPkt", FALSE, TRUE);
  1195. pkt = _GetPkt();
  1196. PktAcquireShared( pkt, TRUE );
  1197. //
  1198. // Calculate the needed output buffer size
  1199. //
  1200. NtStatus = DfsGetPktSize(&cbOutBuffer);
  1201. //
  1202. // Let user know if it's too small
  1203. //
  1204. if (OutputBufferLength < cbOutBuffer) {
  1205. RETURN_BUFFER_SIZE(cbOutBuffer, NtStatus);
  1206. }
  1207. if (NT_SUCCESS(NtStatus)) {
  1208. //
  1209. // Args are ok, and it fits - marshall the data
  1210. //
  1211. NtStatus = DfsGetPktMarshall(OutputBuffer, cbOutBuffer);
  1212. Irp->IoStatus.Information = cbOutBuffer;
  1213. }
  1214. PktRelease(pkt);
  1215. DfsCompleteRequest( Irp, NtStatus );
  1216. DebugTrace(-1, Dbg, "DfsFsctrlGetPkt -> %08lx\n", ULongToPtr( NtStatus ) );
  1217. return( NtStatus );
  1218. }
  1219. //+----------------------------------------------------------------------------
  1220. //
  1221. // Function: DfsGetPktSize, private
  1222. //
  1223. // Synopsis: Calculates the size needed to return the Pkt. Helper for
  1224. // DfsFsctrlGetPkt().
  1225. //
  1226. //-----------------------------------------------------------------------------
  1227. NTSTATUS
  1228. DfsGetPktSize(
  1229. PULONG pSize)
  1230. {
  1231. ULONG EntryCount = 0;
  1232. ULONG i;
  1233. ULONG Size = 0;
  1234. PDFS_PKT_ENTRY pPktEntry;
  1235. PDFS_PKT pkt = _GetPkt();
  1236. //
  1237. // Walk the linked list of Pkt entries
  1238. //
  1239. for ( pPktEntry = PktFirstEntry(pkt);
  1240. pPktEntry != NULL;
  1241. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  1242. //
  1243. // Space for the Prefix and ShortPrefix, including a UNICODE_NULL
  1244. //
  1245. Size += pPktEntry->Id.Prefix.Length + sizeof(WCHAR);
  1246. Size += pPktEntry->Id.ShortPrefix.Length + sizeof(WCHAR);
  1247. //
  1248. // Space for an array of pointers to DFS_PKT_ADDRESS_OBJECTS
  1249. //
  1250. Size += sizeof(PDFS_PKT_ADDRESS_OBJECT) * pPktEntry->Info.ServiceCount;
  1251. //
  1252. // Space for the ServerShare address, plus a UNICODE_NULL, plus the state
  1253. //
  1254. for (i = 0; i < pPktEntry->Info.ServiceCount; i++) {
  1255. Size += sizeof(USHORT) + pPktEntry->Info.ServiceList[i].Address.Length + sizeof(WCHAR);
  1256. }
  1257. EntryCount++;
  1258. }
  1259. //
  1260. // Space for the DFS_PKT_ARG, which will have EntryCount objects on the end
  1261. //
  1262. Size += FIELD_OFFSET(DFS_GET_PKT_ARG, EntryObject[EntryCount]);
  1263. //
  1264. // Make sure the size is a multiple of the size of a PDFS_PKT_ADDRESS_OBJECT, as that is what
  1265. // will be at the end of the buffer
  1266. //
  1267. while ((Size & (sizeof(PDFS_PKT_ADDRESS_OBJECT)-1)) != 0) {
  1268. Size++;
  1269. }
  1270. *pSize = Size;
  1271. return STATUS_SUCCESS;
  1272. }
  1273. //+----------------------------------------------------------------------------
  1274. //
  1275. // Function: DfsGetPktMarshall, private
  1276. //
  1277. // Synopsis: Marshalls the Pkt. Helper for DfsFsctrlGetPkt().
  1278. //
  1279. //-----------------------------------------------------------------------------
  1280. NTSTATUS
  1281. DfsGetPktMarshall(
  1282. PBYTE Buffer,
  1283. ULONG Size)
  1284. {
  1285. ULONG EntryCount = 0;
  1286. ULONG i;
  1287. ULONG j;
  1288. ULONG Type;
  1289. PCHAR pCh;
  1290. PDFS_PKT_ENTRY pPktEntry;
  1291. PDFS_GET_PKT_ARG pPktArg;
  1292. PDFS_PKT pkt = _GetPkt();
  1293. //
  1294. // This will be a two-pass operation, the first pass will calculate how
  1295. // much room for the LPWSTR arrays at the end of the buffer, then the
  1296. // second pass will put the strings into place, too.
  1297. //
  1298. RtlZeroMemory(Buffer,Size);
  1299. //
  1300. // Point to the end of the buffer
  1301. //
  1302. pCh = (PCHAR)(Buffer + Size);
  1303. pPktArg = (PDFS_GET_PKT_ARG)Buffer;
  1304. for ( pPktEntry = PktFirstEntry(pkt);
  1305. pPktEntry != NULL;
  1306. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  1307. //
  1308. // Space for an array of pointers to DFS_PKT_ADDRESS_OBJECTS
  1309. //
  1310. pCh -= sizeof(PDFS_PKT_ADDRESS_OBJECT) * pPktEntry->Info.ServiceCount;
  1311. pPktArg->EntryObject[EntryCount].Address = (PDFS_PKT_ADDRESS_OBJECT *)pCh;
  1312. EntryCount++;
  1313. }
  1314. //
  1315. // Now marshall
  1316. //
  1317. EntryCount = 0;
  1318. for ( pPktEntry = PktFirstEntry(pkt);
  1319. pPktEntry != NULL;
  1320. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  1321. pCh -= pPktEntry->Id.Prefix.Length + sizeof(WCHAR);
  1322. pPktArg->EntryObject[EntryCount].Prefix = (LPWSTR)pCh;
  1323. RtlCopyMemory(
  1324. pPktArg->EntryObject[EntryCount].Prefix,
  1325. pPktEntry->Id.Prefix.Buffer,
  1326. pPktEntry->Id.Prefix.Length);
  1327. pCh -= pPktEntry->Id.ShortPrefix.Length + sizeof(WCHAR);
  1328. pPktArg->EntryObject[EntryCount].ShortPrefix = (LPWSTR)pCh;
  1329. RtlCopyMemory(
  1330. pPktArg->EntryObject[EntryCount].ShortPrefix,
  1331. pPktEntry->Id.ShortPrefix.Buffer,
  1332. pPktEntry->Id.ShortPrefix.Length);
  1333. pPktArg->EntryObject[EntryCount].Type = pPktEntry->Type;
  1334. pPktArg->EntryObject[EntryCount].USN = pPktEntry->USN;
  1335. pPktArg->EntryObject[EntryCount].ExpireTime = pPktEntry->ExpireTime;
  1336. pPktArg->EntryObject[EntryCount].UseCount = pPktEntry->UseCount;
  1337. pPktArg->EntryObject[EntryCount].Uid = pPktEntry->Id.Uid;
  1338. pPktArg->EntryObject[EntryCount].ServiceCount = pPktEntry->Info.ServiceCount;
  1339. for (i = 0; i < pPktEntry->Info.ServiceCount; i++) {
  1340. Type = pPktEntry->Info.ServiceList[i].Type;
  1341. pCh -= sizeof(USHORT) + pPktEntry->Info.ServiceList[i].Address.Length + sizeof(WCHAR);
  1342. pPktArg->EntryObject[EntryCount].Address[i] = (PDFS_PKT_ADDRESS_OBJECT)pCh;
  1343. pPktArg->EntryObject[EntryCount].Address[i]->State = (USHORT)Type;
  1344. RtlCopyMemory(
  1345. &pPktArg->EntryObject[EntryCount].Address[i]->ServerShare[0],
  1346. pPktEntry->Info.ServiceList[i].Address.Buffer,
  1347. pPktEntry->Info.ServiceList[i].Address.Length);
  1348. }
  1349. EntryCount++;
  1350. }
  1351. pPktArg->EntryCount = EntryCount;
  1352. //
  1353. // Convert all the pointers to relative offsets
  1354. //
  1355. for (i = 0; i < pPktArg->EntryCount; i++) {
  1356. for (j = 0; j < pPktArg->EntryObject[i].ServiceCount; j++) {
  1357. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Address[j], Buffer);
  1358. }
  1359. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Prefix, Buffer);
  1360. POINTER_TO_OFFSET(pPktArg->EntryObject[i].ShortPrefix, Buffer);
  1361. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Address, Buffer);
  1362. }
  1363. return STATUS_SUCCESS;
  1364. }
  1365. #if DBG
  1366. //+-------------------------------------------------------------------------
  1367. //
  1368. // Function: DfsFsctrlReadMem, local
  1369. //
  1370. // Synopsis: DfsFsctrlReadMem is a debugging function which will return
  1371. // the contents of a chunk of kernel space memory
  1372. //
  1373. // Arguments: [IrpContext] -
  1374. // [Irp] -
  1375. // [Request] -- Pointer to a FILE_DFS_READ_MEM struct,
  1376. // giving the description of the data to be returned.
  1377. // [InputBufferLength] -- Size of InputBuffer
  1378. // [OutputBuffer] -- User's output buffer, in which the
  1379. // data structure will be returned.
  1380. // [OutputBufferLength] -- Size of OutputBuffer
  1381. //
  1382. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  1383. //
  1384. // Notes: Available in DBG builds only.
  1385. //
  1386. //--------------------------------------------------------------------------
  1387. NTSTATUS
  1388. DfsFsctrlReadMem (
  1389. IN PIRP Irp,
  1390. IN PFILE_DFS_READ_MEM Request,
  1391. IN ULONG InputBufferLength,
  1392. IN OUT PUCHAR OutputBuffer,
  1393. IN ULONG OutputBufferLength
  1394. ) {
  1395. NTSTATUS Status;
  1396. PUCHAR ReadBuffer;
  1397. ULONG ReadLength;
  1398. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  1399. return STATUS_INVALID_PARAMETER;
  1400. }
  1401. //+-------------------------------------------------------------------------
  1402. //
  1403. // Function: DfsFsctrlReadStruct, local
  1404. //
  1405. // Synopsis: DfsFsctrlReadStruct is a debugging function which will return
  1406. // structures associated with the Dfs Server.
  1407. //
  1408. // Arguments: [Irp] -
  1409. // [InputBuffer] -- Pointer to a FILE_DFS_READ_STRUCT_PARAM,
  1410. // giving the description of the data structure to be
  1411. // returned.
  1412. // [InputBufferLength] -- Size of InputBuffer
  1413. // [OutputBuffer] -- User's output buffer, in which the
  1414. // data structure will be returned.
  1415. // [OutputBufferLength] -- Size of OutputBuffer
  1416. //
  1417. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  1418. //
  1419. // Notes: Available in DBG builds only.
  1420. //
  1421. //--------------------------------------------------------------------------
  1422. NTSTATUS
  1423. DfsFsctrlReadStruct (
  1424. IN PIRP Irp,
  1425. IN PFILE_DFS_READ_STRUCT_PARAM pRsParam,
  1426. IN ULONG InputBufferLength,
  1427. IN OUT PUCHAR OutputBuffer,
  1428. IN ULONG OutputBufferLength
  1429. ) {
  1430. NTSTATUS Status;
  1431. NODE_TYPE_CODE NodeTypeCode;
  1432. PUCHAR ReadBuffer;
  1433. ULONG ReadLength;
  1434. DfsCompleteRequest( Irp, STATUS_INVALID_PARAMETER );
  1435. return STATUS_INVALID_PARAMETER;
  1436. }
  1437. #endif