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.

5323 lines
144 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 Dfs.
  9. //
  10. // Functions:
  11. // DfsFsdFileSystemControl
  12. // DfsFspFileSystemControl
  13. // DfsCommonFileSystemControl, local
  14. // DfsUserFsctl, local
  15. // DfsOplockRequest, local
  16. // DfsFsctrlDefineLogicalRoot - Define a new logical root
  17. // DfsFsctrlUndefineLogicalRoot - Undefine an existing root
  18. // DfsFsctrlGetLogicalRootPrefix - Retrieve prefix that logical
  19. // root maps to.
  20. // DfsFsctrlGetConnectedResources -
  21. // DfsFsctrlDefineProvider - Define a file service provider
  22. // DfsFsctrlGetServerName - Get name of server given prefix
  23. // DfsFsctrlReadMem - return an internal data struct (debug)
  24. // DfsCompleteMountRequest - Completion routine for mount IRP
  25. // DfsCompleteLoadFsRequest - Completion routine for Load FS IRP
  26. // DfsFsctrlGetPkt
  27. // DfsFsctrlGetPktEntryState
  28. // DfsGetEntryStateSize - local
  29. // DfsGetEntryStateMarshall - local
  30. // DfsFsctrlSetPktEntryState
  31. // DfsSetPktEntryActive
  32. // DfsSetPktEntryTimeout
  33. //
  34. //-----------------------------------------------------------------------------
  35. #include "dfsprocs.h"
  36. #include "creds.h"
  37. #include "dnr.h"
  38. #include "know.h"
  39. #include "fsctrl.h"
  40. #include "mupwml.h"
  41. #ifdef TERMSRV
  42. NTKERNELAPI
  43. NTSTATUS
  44. IoGetRequestorSessionId(
  45. IN PIRP Irp,
  46. OUT PULONG pSessionId
  47. );
  48. #endif
  49. //
  50. // The local debug trace level
  51. //
  52. #define Dbg (DEBUG_TRACE_FSCTRL)
  53. //
  54. // Local procedure prototypes
  55. //
  56. NTSTATUS
  57. DfsCommonFileSystemControl (
  58. IN PDEVICE_OBJECT DeviceObject,
  59. IN PIRP_CONTEXT IrpContext,
  60. IN PIRP Irp
  61. );
  62. NTSTATUS
  63. DfsUserFsctl (
  64. IN PIRP_CONTEXT IrpContext,
  65. IN PIRP Irp
  66. );
  67. NTSTATUS
  68. DfsOplockRequest (
  69. IN PIRP_CONTEXT IrpContext,
  70. IN PIRP Irp
  71. );
  72. NTSTATUS
  73. DfsFsctrlDefineLogicalRoot (
  74. IN PIRP_CONTEXT IrpContext,
  75. IN PIRP Irp,
  76. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  77. IN ULONG InputBufferLength
  78. );
  79. NTSTATUS
  80. DfsFsctrlDefineRootCredentials(
  81. IN PIRP_CONTEXT IrpContext,
  82. IN PIRP Irp,
  83. IN PUCHAR InputBuffer,
  84. IN ULONG InputBufferLength);
  85. NTSTATUS
  86. DfsFsctrlUndefineLogicalRoot (
  87. IN PIRP_CONTEXT IrpContext,
  88. IN PIRP Irp,
  89. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  90. IN ULONG InputBufferLength
  91. );
  92. NTSTATUS
  93. DfsFsctrlGetLogicalRootPrefix (
  94. IN PIRP_CONTEXT IrpContext,
  95. IN PIRP Irp,
  96. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  97. IN ULONG InputBufferLength,
  98. IN OUT PUCHAR OutputBuffer,
  99. IN ULONG OutputBufferLength);
  100. NTSTATUS
  101. DfsFsctrlGetConnectedResources(
  102. IN PIRP_CONTEXT IrpContext,
  103. IN PIRP Irp,
  104. IN PUCHAR InputBuffer,
  105. IN ULONG cbInput,
  106. IN PUCHAR OutputBuffer,
  107. IN ULONG OutputBufferLength);
  108. NTSTATUS
  109. DfsFsctrlGetServerName(
  110. IN PIRP_CONTEXT IrpContext,
  111. IN PIRP Irp,
  112. IN PUCHAR InputBuffer,
  113. IN ULONG InputBufferLength,
  114. IN PUCHAR OutputBuffer,
  115. IN ULONG OutputBufferLength);
  116. NTSTATUS
  117. DfsFsctrlReadMem (
  118. IN PIRP_CONTEXT IrpContext,
  119. IN PIRP Irp,
  120. IN PFILE_DFS_READ_MEM Request,
  121. IN ULONG InputBufferLength,
  122. IN OUT PUCHAR OutputBuffer,
  123. IN ULONG OutputBufferLength
  124. );
  125. NTSTATUS
  126. DfsFsctrlGetPktEntryState(
  127. IN PIRP_CONTEXT IrpContext,
  128. IN PIRP Irp,
  129. IN PUCHAR InputBuffer,
  130. IN ULONG cbInput,
  131. IN PUCHAR OutputBuffer,
  132. IN ULONG OutputBufferLength);
  133. NTSTATUS
  134. DfsFsctrlGetPkt(
  135. IN PIRP_CONTEXT IrpContext,
  136. IN PIRP Irp,
  137. IN PUCHAR OutputBuffer,
  138. IN ULONG OutputBufferLength);
  139. NTSTATUS
  140. DfsGetEntryStateSize(
  141. IN ULONG Level,
  142. IN PUNICODE_STRING ServerName,
  143. IN PUNICODE_STRING ShareName,
  144. IN PDFS_PKT_ENTRY pktEntry,
  145. IN PULONG pcbOutBuffer);
  146. NTSTATUS
  147. DfsGetEntryStateMarshall(
  148. IN ULONG Level,
  149. IN PUNICODE_STRING ServerName,
  150. IN PUNICODE_STRING ShareName,
  151. IN PDFS_PKT_ENTRY pktEntry,
  152. IN PBYTE OutputBuffer,
  153. IN ULONG cbOutBuffer);
  154. NTSTATUS
  155. DfsFsctrlSetPktEntryState(
  156. IN PIRP_CONTEXT IrpContext,
  157. IN PIRP Irp,
  158. IN PUCHAR InputBuffer,
  159. IN ULONG cbInput);
  160. NTSTATUS
  161. DfsFsctrlGetSpcTable(
  162. IN PIRP_CONTEXT IrpContext,
  163. IN PIRP Irp,
  164. IN PUCHAR InputBuffer,
  165. IN ULONG InputBufferLength,
  166. IN PUCHAR OutputBuffer,
  167. IN ULONG OutputBufferLength);
  168. NTSTATUS
  169. DfsSetPktEntryActive(
  170. IN PUNICODE_STRING ServerName,
  171. IN PUNICODE_STRING ShareName,
  172. IN PDFS_PKT_ENTRY pktEntry,
  173. IN DWORD State);
  174. NTSTATUS
  175. DfsSetPktEntryTimeout(
  176. IN PDFS_PKT_ENTRY pktEntry,
  177. IN ULONG Timeout);
  178. NTSTATUS
  179. DfsGetPktSize(
  180. OUT PULONG pSize);
  181. NTSTATUS
  182. DfsGetPktMarshall(
  183. IN PBYTE Buffer,
  184. IN ULONG Size);
  185. NTSTATUS
  186. DfsGetSpcTableNames(
  187. PIRP Irp,
  188. PUCHAR OutputBuffer,
  189. ULONG OutputBufferLength);
  190. NTSTATUS
  191. DfsExpSpcTableName(
  192. LPWSTR SpcName,
  193. PIRP Irp,
  194. PUCHAR OutputBuffer,
  195. ULONG OutputBufferLength);
  196. NTSTATUS
  197. DfsGetSpcDcInfo(
  198. PIRP Irp,
  199. PUCHAR OutputBuffer,
  200. ULONG OutputBufferLength);
  201. NTSTATUS
  202. DfsFsctrlSpcSetDc(
  203. IN PIRP_CONTEXT IrpContext,
  204. IN PIRP Irp,
  205. IN PUCHAR InputBuffer,
  206. IN ULONG cbInput);
  207. NTSTATUS
  208. DfsTreeConnectGetConnectionInfo(
  209. IN PDFS_SERVICE Service,
  210. IN PDFS_CREDENTIALS Creds,
  211. IN OUT PUCHAR OutputBuffer,
  212. IN ULONG OutputBufferLength,
  213. OUT PULONG InfoLen);
  214. NTSTATUS
  215. DfsFsctrlGetConnectionPerfInfo(
  216. IN PIRP_CONTEXT IrpContext,
  217. IN PIRP Irp,
  218. IN PUCHAR InputBuffer,
  219. IN ULONG InputBufferLength,
  220. IN OUT PUCHAR OutputBuffer,
  221. IN ULONG OutputBufferLength);
  222. NTSTATUS
  223. DfsFsctrlCscServerOffline(
  224. IN PIRP_CONTEXT IrpContext,
  225. IN PIRP Irp,
  226. IN PUCHAR InputBuffer,
  227. IN ULONG InputBufferLength,
  228. IN OUT PUCHAR OutputBuffer,
  229. IN ULONG OutputBufferLength);
  230. NTSTATUS
  231. DfsFsctrlCscServerOnline(
  232. IN PIRP_CONTEXT IrpContext,
  233. IN PIRP Irp,
  234. IN PUCHAR InputBuffer,
  235. IN ULONG InputBufferLength,
  236. IN OUT PUCHAR OutputBuffer,
  237. IN ULONG OutputBufferLength);
  238. NTSTATUS
  239. DfsFsctrlSpcRefresh (
  240. IN PIRP_CONTEXT IrpContext,
  241. IN PIRP Irp,
  242. IN PUCHAR InputBuffer,
  243. IN ULONG InputBufferLength);
  244. VOID
  245. MupGetDebugFlags(VOID);
  246. VOID
  247. DfsGetEventLogValue(VOID);
  248. VOID
  249. DfsStopDfs();
  250. void
  251. DfsDumpBuf(
  252. PCHAR cp,
  253. ULONG len
  254. );
  255. BOOLEAN
  256. DfspIsSpecialShare(
  257. PUNICODE_STRING ShareName);
  258. BOOLEAN
  259. DfspIsSysVolShare(
  260. PUNICODE_STRING ShareName);
  261. extern
  262. BOOLEAN DfsIsSpecialName( PUNICODE_STRING pName);
  263. #define UNICODE_STRING_STRUCT(s) \
  264. {sizeof(s) - sizeof(WCHAR), sizeof(s) - sizeof(WCHAR), (s)}
  265. static UNICODE_STRING SpecialShares[] = {
  266. UNICODE_STRING_STRUCT(L"PIPE"),
  267. UNICODE_STRING_STRUCT(L"IPC$"),
  268. UNICODE_STRING_STRUCT(L"ADMIN$"),
  269. UNICODE_STRING_STRUCT(L"MAILSLOT")
  270. };
  271. static UNICODE_STRING SysVolShares[] = {
  272. UNICODE_STRING_STRUCT(L"SYSVOL"),
  273. UNICODE_STRING_STRUCT(L"NETLOGON")
  274. };
  275. #ifdef ALLOC_PRAGMA
  276. #pragma alloc_text( PAGE, DfsFsdFileSystemControl )
  277. #pragma alloc_text( PAGE, DfsFspFileSystemControl )
  278. #pragma alloc_text( PAGE, DfsCommonFileSystemControl )
  279. #pragma alloc_text( PAGE, DfsUserFsctl )
  280. #pragma alloc_text( PAGE, DfsFsctrlIsThisADfsPath )
  281. #pragma alloc_text( PAGE, DfsOplockRequest )
  282. #pragma alloc_text( PAGE, DfsFsctrlDefineLogicalRoot )
  283. #pragma alloc_text( PAGE, DfsFsctrlDefineRootCredentials )
  284. #pragma alloc_text( PAGE, DfsFsctrlUndefineLogicalRoot )
  285. #pragma alloc_text( PAGE, DfsFsctrlGetLogicalRootPrefix )
  286. #pragma alloc_text( PAGE, DfsFsctrlGetConnectedResources )
  287. #pragma alloc_text( PAGE, DfsFsctrlGetServerName )
  288. #pragma alloc_text( PAGE, DfsFsctrlReadMem )
  289. #pragma alloc_text( PAGE, DfsStopDfs )
  290. #pragma alloc_text( PAGE, DfspIsSpecialShare )
  291. #pragma alloc_text( PAGE, DfspIsSysVolShare )
  292. #pragma alloc_text( PAGE, DfsFsctrlGetPkt )
  293. #pragma alloc_text( PAGE, DfsFsctrlGetPktEntryState )
  294. #pragma alloc_text( PAGE, DfsGetEntryStateSize )
  295. #pragma alloc_text( PAGE, DfsGetEntryStateMarshall )
  296. #pragma alloc_text( PAGE, DfsFsctrlSetPktEntryState )
  297. #pragma alloc_text( PAGE, DfsSetPktEntryActive )
  298. #pragma alloc_text( PAGE, DfsSetPktEntryTimeout )
  299. #pragma alloc_text( PAGE, DfsGetPktSize )
  300. #pragma alloc_text( PAGE, DfsGetPktMarshall )
  301. #pragma alloc_text( PAGE, DfsFsctrlGetSpcTable )
  302. #pragma alloc_text( PAGE, DfsGetSpcTableNames )
  303. #pragma alloc_text( PAGE, DfsExpSpcTableName )
  304. #pragma alloc_text( PAGE, DfsGetSpcDcInfo )
  305. #pragma alloc_text( PAGE, DfsFsctrlSpcSetDc )
  306. #pragma alloc_text( PAGE, DfsTreeConnectGetConnectionInfo)
  307. #pragma alloc_text( PAGE, DfsFsctrlGetConnectionPerfInfo)
  308. #pragma alloc_text( PAGE, DfsFsctrlCscServerOffline)
  309. #pragma alloc_text( PAGE, DfsFsctrlCscServerOnline)
  310. #pragma alloc_text( PAGE, DfsFsctrlSpcRefresh)
  311. #endif // ALLOC_PRAGMA
  312. //+-------------------------------------------------------------------
  313. //
  314. // Function: DfsFsdFileSystemControl, public
  315. //
  316. // Synopsis: This routine implements the FSD part of FileSystem
  317. // control operations
  318. //
  319. // Arguments: [DeviceObject] -- Supplies the volume device object
  320. // where the file exists
  321. // [Irp] -- Supplies the Irp being processed
  322. //
  323. // Returns: [NTSTATUS] -- The FSD status for the IRP
  324. //
  325. //--------------------------------------------------------------------
  326. NTSTATUS
  327. DfsFsdFileSystemControl (
  328. IN PDEVICE_OBJECT DeviceObject,
  329. IN PIRP Irp
  330. ) {
  331. BOOLEAN Wait;
  332. NTSTATUS Status;
  333. PIRP_CONTEXT IrpContext = NULL;
  334. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  335. ULONG FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  336. DfsDbgTrace(+1, Dbg, "DfsFsdFileSystemControl\n", 0);
  337. //
  338. // Call the common FileSystem Control routine, with blocking allowed
  339. // if synchronous. This opeation needs to special case the mount
  340. // and verify suboperations because we know they are allowed to block.
  341. // We identify these suboperations by looking at the file object field
  342. // and seeing if it's null.
  343. //
  344. if (IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {
  345. Wait = TRUE;
  346. } else {
  347. Wait = CanFsdWait( Irp );
  348. }
  349. FsRtlEnterFileSystem();
  350. try {
  351. IrpContext = DfsCreateIrpContext( Irp, Wait );
  352. if (IrpContext == NULL)
  353. ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
  354. Status = DfsCommonFileSystemControl( DeviceObject, IrpContext, Irp );
  355. } except( DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
  356. //
  357. // We had some trouble trying to perform the requested
  358. // operation, so we'll abort the I/O request with
  359. // the error status that we get back from the
  360. // execption code
  361. //
  362. Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
  363. }
  364. FsRtlExitFileSystem();
  365. //
  366. // And return to our caller
  367. //
  368. DfsDbgTrace(-1, Dbg, "DfsFsdFileSystemControl -> %08lx\n", ULongToPtr(Status));
  369. return Status;
  370. }
  371. //+-------------------------------------------------------------------
  372. //
  373. // Function: DfsFspFileSystemControl, public
  374. //
  375. // Synopsis: This routine implements the FSP part of the file system
  376. // control operations
  377. //
  378. // Arguments: [Irp] -- Supplies the Irp being processed
  379. //
  380. // Returns: Nothing.
  381. //
  382. //--------------------------------------------------------------------
  383. VOID
  384. DfsFspFileSystemControl (
  385. IN PIRP_CONTEXT IrpContext,
  386. IN PIRP Irp
  387. ) {
  388. DfsDbgTrace(+1, Dbg, "DfsFspFileSystemControl\n", 0);
  389. //
  390. // Call the common FileSystem Control routine.
  391. //
  392. DfsCommonFileSystemControl( NULL, IrpContext, Irp );
  393. //
  394. // And return to our caller
  395. //
  396. DfsDbgTrace(-1, Dbg, "DfsFspFileSystemControl -> VOID\n", 0 );
  397. return;
  398. }
  399. //+-------------------------------------------------------------------
  400. //
  401. // Function: DfsCommonFileSystemControl, local
  402. //
  403. // Synopsis: This is the common routine for doing FileSystem control
  404. // operations called by both the FSD and FSP threads
  405. //
  406. // Arguments: [DeviceObject] -- The one used to enter our FSD Routine
  407. // [IrpContext] -- Context associated with the Irp
  408. // [Irp] -- Supplies the Irp to process
  409. //
  410. // Returns: NTSTATUS - The return status for the operation
  411. //--------------------------------------------------------------------
  412. NTSTATUS
  413. DfsCommonFileSystemControl (
  414. IN PDEVICE_OBJECT DeviceObject,
  415. IN PIRP_CONTEXT IrpContext,
  416. IN PIRP Irp
  417. ) {
  418. NTSTATUS Status;
  419. PIO_STACK_LOCATION IrpSp, NextIrpSp;
  420. ULONG FsControlCode;
  421. PFILE_OBJECT FileObject;
  422. //
  423. // Get a pointer to the current Irp stack location
  424. //
  425. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  426. FileObject = IrpSp->FileObject;
  427. DfsDbgTrace(+1, Dbg, "DfsCommonFileSystemControl\n", 0);
  428. DfsDbgTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  429. DfsDbgTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);
  430. //
  431. // We know this is a file system control so we'll case on the
  432. // minor function, and call a internal worker routine to complete
  433. // the irp.
  434. //
  435. switch (IrpSp->MinorFunction) {
  436. case IRP_MN_USER_FS_REQUEST:
  437. FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  438. //
  439. // If the DFS FSCTL is issued via a device that is not the DFS
  440. // file system device object, then reject the request.
  441. //
  442. if ((IS_DFS_CTL_CODE(FsControlCode) == 0) ||
  443. (DeviceObject == DfsData.FileSysDeviceObject)) {
  444. Status = DfsUserFsctl( IrpContext, Irp );
  445. }
  446. else {
  447. DfsDbgTrace(0, Dbg, "Invalid Device object for FS control %08lx\n",
  448. DeviceObject);
  449. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
  450. Status = STATUS_INVALID_DEVICE_REQUEST;
  451. }
  452. break;
  453. case IRP_MN_MOUNT_VOLUME:
  454. case IRP_MN_VERIFY_VOLUME:
  455. //
  456. // We are processing a MOUNT/VERIFY request being directed to our
  457. // our File System Device Object. We don't directly support
  458. // disk volumes, so we simply reject.
  459. //
  460. ASSERT(DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM);
  461. Status = STATUS_NOT_SUPPORTED;
  462. DfsCompleteRequest( IrpContext, Irp, Status );
  463. break;
  464. default:
  465. {
  466. PDFS_FCB Fcb;
  467. PDFS_VCB Vcb;
  468. if (DfsDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb) != RedirectedFileOpen) {
  469. DfsDbgTrace(0, Dbg, "Invalid FS Control Minor Function %08lx\n",
  470. IrpSp->MinorFunction);
  471. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
  472. Status = STATUS_INVALID_DEVICE_REQUEST;
  473. }
  474. else {
  475. //
  476. // Copy the stack from one to the next...
  477. //
  478. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  479. (*NextIrpSp) = (*IrpSp);
  480. IoSetCompletionRoutine( Irp,
  481. NULL,
  482. NULL,
  483. FALSE,
  484. FALSE,
  485. FALSE);
  486. //
  487. // Call to the real device for the file object.
  488. //
  489. Status = IoCallDriver( Fcb->TargetDevice, Irp );
  490. MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonFileSystemControl_Error_IoCallDriver,
  491. LOGSTATUS(Status)
  492. LOGPTR(Irp)
  493. LOGPTR(FileObject)
  494. LOGPTR(DeviceObject));
  495. //
  496. // The IRP will be completed by the called driver. We have
  497. // no need for the IrpContext in the completion routine.
  498. //
  499. DfsDeleteIrpContext(IrpContext);
  500. IrpContext = NULL;
  501. Irp = NULL;
  502. }
  503. break;
  504. }
  505. }
  506. DfsDbgTrace(-1, Dbg, "DfsCommonFileSystemControl -> %08lx\n", ULongToPtr(Status) );
  507. return Status;
  508. }
  509. //+-------------------------------------------------------------------
  510. //
  511. // Function: DfsUserFsctl, local
  512. //
  513. // Synopsis: This is the common routine for implementing the user's
  514. // requests made through NtFsControlFile.
  515. //
  516. // Arguments: [Irp] -- Supplies the Irp being processed
  517. //
  518. // Returns: NTSTATUS - The return status for the operation
  519. //
  520. //--------------------------------------------------------------------
  521. NTSTATUS
  522. DfsUserFsctl (
  523. IN PIRP_CONTEXT IrpContext,
  524. IN PIRP Irp
  525. ) {
  526. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  527. PFILE_OBJECT FileObject = IrpSp->FileObject;
  528. PIO_STACK_LOCATION NextIrpSp;
  529. NTSTATUS Status;
  530. ULONG FsControlCode;
  531. ULONG cbOutput;
  532. ULONG cbInput;
  533. PUCHAR InputBuffer;
  534. PUCHAR OutputBuffer;
  535. PDFS_FCB Fcb;
  536. PDFS_VCB DfsVcb;
  537. #ifdef TERMSRV
  538. ULONG SessionID;
  539. #endif
  540. //
  541. // Just in case some-one (cough) forgets about it...
  542. // ...zero information status now!
  543. //
  544. Irp->IoStatus.Information = 0L;
  545. FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  546. cbInput = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  547. cbOutput = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  548. DfsDbgTrace(+1, Dbg, "DfsUserFsctl: Entered\n", 0);
  549. DfsDbgTrace( 0, Dbg, "DfsUserFsctl: Cntrl Code -> %08lx\n", ULongToPtr(FsControlCode) );
  550. DfsDbgTrace( 0, Dbg, "DfsUserFsctl: cbInput -> %08lx\n", ULongToPtr(cbInput) );
  551. DfsDbgTrace( 0, Dbg, "DfsUserFsctl: cbOutput -> %08lx\n", ULongToPtr(cbOutput) );
  552. //
  553. // All DFS FsControlCodes use METHOD_BUFFERED, so the SystemBuffer
  554. // is used for both the input and output.
  555. //
  556. InputBuffer = OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
  557. DfsDbgTrace( 0, Dbg, "DfsUserFsctl: InputBuffer -> %08lx\n", InputBuffer);
  558. DfsDbgTrace( 0, Dbg, "DfsUserFsctl: UserBuffer -> %08lx\n", Irp->UserBuffer);
  559. //
  560. // Case on the control code.
  561. //
  562. switch ( FsControlCode ) {
  563. case FSCTL_REQUEST_OPLOCK_LEVEL_1:
  564. case FSCTL_REQUEST_OPLOCK_LEVEL_2:
  565. case FSCTL_REQUEST_BATCH_OPLOCK:
  566. case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
  567. case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
  568. case FSCTL_OPLOCK_BREAK_NOTIFY:
  569. Status = DfsOplockRequest( IrpContext, Irp );
  570. break;
  571. case FSCTL_DISMOUNT_VOLUME:
  572. Status = STATUS_NOT_SUPPORTED;
  573. DfsCompleteRequest(IrpContext, Irp, Status);
  574. break;
  575. case FSCTL_DFS_GET_VERSION:
  576. if (OutputBuffer != NULL &&
  577. cbOutput >= sizeof(DFS_GET_VERSION_ARG)) {
  578. PDFS_GET_VERSION_ARG parg =
  579. (PDFS_GET_VERSION_ARG) OutputBuffer;
  580. parg->Version = 1;
  581. Status = STATUS_SUCCESS;
  582. Irp->IoStatus.Information = sizeof(DFS_GET_VERSION_ARG);
  583. } else {
  584. Status = STATUS_INVALID_PARAMETER;
  585. }
  586. DfsCompleteRequest(IrpContext, Irp, Status);
  587. break;
  588. case FSCTL_DFS_STOP_DFS:
  589. DfsStopDfs();
  590. Status = STATUS_SUCCESS;
  591. DfsCompleteRequest(IrpContext, Irp, Status);
  592. break;
  593. case FSCTL_DFS_IS_ROOT:
  594. Status = STATUS_INVALID_DOMAIN_ROLE;
  595. DfsCompleteRequest(IrpContext, Irp, Status);
  596. break;
  597. case FSCTL_DFS_IS_VALID_PREFIX: {
  598. PDFS_IS_VALID_PREFIX_ARG PrefixArg;
  599. UNICODE_STRING fileName, pathName;
  600. PrefixArg = (PDFS_IS_VALID_PREFIX_ARG)InputBuffer;
  601. if (cbInput < sizeof(DFS_IS_VALID_PREFIX_ARG)
  602. ||
  603. (ULONG)(FIELD_OFFSET(DFS_IS_VALID_PREFIX_ARG,RemoteName) +
  604. PrefixArg->RemoteNameLen) > cbInput
  605. ) {
  606. Status = STATUS_INVALID_PARAMETER;
  607. DfsCompleteRequest(IrpContext, Irp, Status);
  608. break;
  609. }
  610. //
  611. // Reject negative and odd RemoteNameLen's
  612. //
  613. if (PrefixArg->RemoteNameLen < 0
  614. ||
  615. (PrefixArg->RemoteNameLen & 0x1) != 0
  616. ) {
  617. Status = STATUS_INVALID_PARAMETER;
  618. DfsCompleteRequest(IrpContext, Irp, Status);
  619. break;
  620. }
  621. fileName.Length = PrefixArg->RemoteNameLen;
  622. fileName.MaximumLength = (USHORT) PrefixArg->RemoteNameLen;
  623. fileName.Buffer = (PWCHAR) PrefixArg->RemoteName;
  624. try {
  625. Status = DfsFsctrlIsThisADfsPath(
  626. &fileName,
  627. PrefixArg->CSCAgentCreate,
  628. &pathName );
  629. } except (EXCEPTION_EXECUTE_HANDLER) {
  630. Status = STATUS_INVALID_PARAMETER;
  631. }
  632. DfsCompleteRequest(IrpContext, Irp, Status);
  633. }
  634. break;
  635. case FSCTL_DFS_IS_VALID_LOGICAL_ROOT:
  636. if (cbInput == sizeof(WCHAR)) {
  637. UNICODE_STRING logRootName, Remaining;
  638. WCHAR buffer[3];
  639. PDFS_VCB RootVcb;
  640. LUID LogonID;
  641. buffer[0] = *((PWCHAR) InputBuffer);
  642. buffer[1] = UNICODE_DRIVE_SEP;
  643. buffer[2] = UNICODE_PATH_SEP;
  644. logRootName.Length = sizeof(buffer);
  645. logRootName.MaximumLength = sizeof(buffer);
  646. logRootName.Buffer = buffer;
  647. DfsGetLogonId(&LogonID);
  648. #ifdef TERMSRV
  649. Status = IoGetRequestorSessionId(Irp, &SessionID);
  650. if (NT_SUCCESS(Status)) {
  651. Status = DfsFindLogicalRoot(&logRootName, SessionID, &LogonID, &RootVcb, &Remaining);
  652. }
  653. #else
  654. Status = DfsFindLogicalRoot(&logRootName, &LogonID, &RootVcb, &Remaining);
  655. #endif
  656. if (!NT_SUCCESS(Status)) {
  657. DfsDbgTrace(0, Dbg, "Logical root not found!\n", 0);
  658. Status = STATUS_NO_SUCH_DEVICE;
  659. }
  660. } else {
  661. Status = STATUS_INVALID_PARAMETER;
  662. }
  663. DfsCompleteRequest(IrpContext, Irp, Status);
  664. break;
  665. case FSCTL_DFS_PKT_SET_DC_NAME:
  666. Status = DfsFsctrlSetDCName(IrpContext,
  667. Irp,
  668. InputBuffer,
  669. cbInput);
  670. break;
  671. case FSCTL_DFS_PKT_SET_DOMAINNAMEFLAT:
  672. Status = DfsFsctrlSetDomainNameFlat(IrpContext,
  673. Irp,
  674. InputBuffer,
  675. cbInput);
  676. break;
  677. case FSCTL_DFS_PKT_SET_DOMAINNAMEDNS:
  678. Status = DfsFsctrlSetDomainNameDns(IrpContext,
  679. Irp,
  680. InputBuffer,
  681. cbInput);
  682. break;
  683. case FSCTL_DFS_DEFINE_LOGICAL_ROOT:
  684. Status = DfsFsctrlDefineLogicalRoot( IrpContext, Irp,
  685. (PFILE_DFS_DEF_ROOT_BUFFER)InputBuffer, cbInput);
  686. break;
  687. case FSCTL_DFS_DELETE_LOGICAL_ROOT:
  688. Status = DfsFsctrlUndefineLogicalRoot( IrpContext, Irp,
  689. (PFILE_DFS_DEF_ROOT_BUFFER)InputBuffer, cbInput);
  690. break;
  691. case FSCTL_DFS_GET_LOGICAL_ROOT_PREFIX:
  692. Status = DfsFsctrlGetLogicalRootPrefix( IrpContext, Irp,
  693. (PFILE_DFS_DEF_ROOT_BUFFER)InputBuffer, cbInput,
  694. (PUCHAR)OutputBuffer, cbOutput);
  695. break;
  696. case FSCTL_DFS_GET_CONNECTED_RESOURCES:
  697. Status = DfsFsctrlGetConnectedResources(IrpContext,
  698. Irp,
  699. InputBuffer,
  700. cbInput,
  701. OutputBuffer,
  702. cbOutput);
  703. break;
  704. case FSCTL_DFS_DEFINE_ROOT_CREDENTIALS:
  705. Status = DfsFsctrlDefineRootCredentials(
  706. IrpContext,
  707. Irp,
  708. InputBuffer,
  709. cbInput);
  710. break;
  711. case FSCTL_DFS_GET_SERVER_NAME:
  712. Status = DfsFsctrlGetServerName(IrpContext,
  713. Irp,
  714. InputBuffer,
  715. cbInput,
  716. OutputBuffer,
  717. cbOutput);
  718. break;
  719. case FSCTL_DFS_SET_PKT_ENTRY_TIMEOUT:
  720. if (cbInput == sizeof(ULONG)) {
  721. DfsData.Pkt.EntryTimeToLive = *(PULONG) InputBuffer;
  722. Status = STATUS_SUCCESS;
  723. } else {
  724. Status = STATUS_INVALID_PARAMETER;
  725. }
  726. DfsCompleteRequest(IrpContext, Irp, Status);
  727. break;
  728. case FSCTL_DFS_PKT_FLUSH_CACHE:
  729. Status = PktFsctrlFlushCache(IrpContext, Irp,
  730. InputBuffer, cbInput
  731. );
  732. break;
  733. case FSCTL_DFS_PKT_FLUSH_SPC_CACHE:
  734. Status = PktFsctrlFlushSpcCache(IrpContext, Irp,
  735. InputBuffer, cbInput
  736. );
  737. break;
  738. case FSCTL_DFS_GET_PKT_ENTRY_STATE:
  739. Status = DfsFsctrlGetPktEntryState(IrpContext,
  740. Irp,
  741. InputBuffer,
  742. cbInput,
  743. OutputBuffer,
  744. cbOutput);
  745. break;
  746. case FSCTL_DFS_SET_PKT_ENTRY_STATE:
  747. Status = DfsFsctrlSetPktEntryState(IrpContext,
  748. Irp,
  749. InputBuffer,
  750. cbInput);
  751. break;
  752. case FSCTL_DFS_GET_PKT:
  753. Status = DfsFsctrlGetPkt(IrpContext,
  754. Irp,
  755. OutputBuffer,
  756. cbOutput);
  757. break;
  758. case FSCTL_DFS_GET_SPC_TABLE:
  759. Status = DfsFsctrlGetSpcTable(IrpContext,
  760. Irp,
  761. InputBuffer,
  762. cbInput,
  763. OutputBuffer,
  764. cbOutput);
  765. break;
  766. case FSCTL_DFS_SPECIAL_SET_DC:
  767. Status = DfsFsctrlSpcSetDc(IrpContext,
  768. Irp,
  769. InputBuffer,
  770. cbInput);
  771. break;
  772. case FSCTL_DFS_REREAD_REGISTRY:
  773. DfsGetEventLogValue();
  774. #if DBG
  775. MupGetDebugFlags();
  776. #endif // DBG
  777. Status = STATUS_SUCCESS;
  778. DfsCompleteRequest(IrpContext, Irp, Status);
  779. break;
  780. #if DBG
  781. case FSCTL_DFS_INTERNAL_READ_MEM:
  782. Status = DfsFsctrlReadMem( IrpContext, Irp,
  783. (PFILE_DFS_READ_MEM)InputBuffer, cbInput,
  784. OutputBuffer, cbOutput );
  785. break;
  786. case FSCTL_DFS_DBG_BREAK:
  787. DbgBreakPoint();
  788. Status = STATUS_SUCCESS;
  789. DfsCompleteRequest(IrpContext, Irp, Status);
  790. break;
  791. case FSCTL_DFS_DBG_FLAGS:
  792. if (cbInput >= sizeof(ULONG))
  793. DfsDebugTraceLevel = * ((PULONG) InputBuffer);
  794. Status = STATUS_SUCCESS;
  795. DfsCompleteRequest(IrpContext, Irp, Status);
  796. break;
  797. case FSCTL_DFS_VERBOSE_FLAGS:
  798. if (cbInput >= sizeof(ULONG))
  799. MupVerbose = * ((PULONG) InputBuffer);
  800. Status = STATUS_SUCCESS;
  801. DfsCompleteRequest(IrpContext, Irp, Status);
  802. break;
  803. case FSCTL_DFS_EVENTLOG_FLAGS:
  804. if (cbInput >= sizeof(ULONG))
  805. DfsEventLog = * ((PULONG) InputBuffer);
  806. Status = STATUS_SUCCESS;
  807. DfsCompleteRequest(IrpContext, Irp, Status);
  808. break;
  809. #endif // DBG
  810. case FSCTL_DFS_GET_CONNECTION_PERF_INFO:
  811. Status = DfsFsctrlGetConnectionPerfInfo(IrpContext,
  812. Irp,
  813. InputBuffer,
  814. cbInput,
  815. OutputBuffer,
  816. cbOutput);
  817. break;
  818. case FSCTL_DFS_CSC_SERVER_OFFLINE:
  819. Status = DfsFsctrlCscServerOffline(IrpContext,
  820. Irp,
  821. InputBuffer,
  822. cbInput,
  823. OutputBuffer,
  824. cbOutput);
  825. break;
  826. case FSCTL_DFS_CSC_SERVER_ONLINE:
  827. Status = DfsFsctrlCscServerOnline(IrpContext,
  828. Irp,
  829. InputBuffer,
  830. cbInput,
  831. OutputBuffer,
  832. cbOutput);
  833. break;
  834. case FSCTL_DFS_SPC_REFRESH:
  835. Status = DfsFsctrlSpcRefresh(IrpContext,
  836. Irp,
  837. InputBuffer,
  838. cbInput);
  839. break;
  840. default:
  841. //
  842. // It is not a recognized DFS fsctrl. If it is for a redirected
  843. // file, just pass it along to the underlying file system.
  844. //
  845. if (
  846. (IS_DFS_CTL_CODE(FsControlCode))
  847. ||
  848. (DfsDecodeFileObject( IrpSp->FileObject, &DfsVcb, &Fcb) != RedirectedFileOpen)
  849. ) {
  850. DfsDbgTrace(0, Dbg, "Dfs: Invalid FS control code -> %08lx\n", ULongToPtr(FsControlCode) );
  851. DfsCompleteRequest( IrpContext, Irp, STATUS_NOT_SUPPORTED);
  852. Status = STATUS_NOT_SUPPORTED;
  853. break;
  854. }
  855. //
  856. // Copy the stack from one to the next...
  857. //
  858. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  859. (*NextIrpSp) = (*IrpSp);
  860. IoSetCompletionRoutine( Irp,
  861. NULL,
  862. NULL,
  863. FALSE,
  864. FALSE,
  865. FALSE);
  866. //
  867. // Call to the real device for the file object.
  868. //
  869. Status = IoCallDriver( Fcb->TargetDevice, Irp );
  870. MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsUserFsctl_Error_IoCallDriver,
  871. LOGSTATUS(Status)
  872. LOGPTR(Irp)
  873. LOGPTR(FileObject));
  874. //
  875. // The IRP will be completed by the called driver. We have
  876. // no need for the IrpContext in the completion routine.
  877. //
  878. DfsDeleteIrpContext(IrpContext);
  879. IrpContext = NULL;
  880. Irp = NULL;
  881. break;
  882. }
  883. DfsDbgTrace(-1, Dbg, "DfsUserFsctl: Exit -> %08lx\n", ULongToPtr(Status) );
  884. return Status;
  885. }
  886. //+-------------------------------------------------------------------------
  887. //
  888. // Function: DfsOplockRequest, local
  889. //
  890. // Synopsis: DfsOplockRequest will process an oplock request.
  891. //
  892. // Arguments: [IrpContext] -
  893. // [Irp] -
  894. //
  895. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  896. // STATUS_OPLOCK_NOT_GRANTED if the oplock is refuesed
  897. //
  898. //
  899. //--------------------------------------------------------------------------
  900. NTSTATUS
  901. DfsOplockRequest (
  902. IN PIRP_CONTEXT IrpContext,
  903. IN PIRP Irp
  904. ) {
  905. NTSTATUS Status;
  906. ULONG FsControlCode;
  907. PDFS_FCB Fcb;
  908. PDFS_VCB Vcb;
  909. TYPE_OF_OPEN TypeOfOpen;
  910. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  911. PFILE_OBJECT FileObject = IrpSp->FileObject;
  912. PIO_STACK_LOCATION NextIrpSp;
  913. BOOLEAN AcquiredVcb = FALSE;
  914. //
  915. // Save some references to make our life a little easier
  916. //
  917. FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  918. DfsDbgTrace(+1, Dbg, "DfsOplockRequest...\n", 0);
  919. DfsDbgTrace( 0, Dbg, "FsControlCode = %08lx\n", ULongToPtr(FsControlCode) );
  920. //
  921. // We only permit oplock requests on files.
  922. //
  923. if ((TypeOfOpen = DfsDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb))
  924. != RedirectedFileOpen) {
  925. //
  926. // A bit bizarre that someone wants to oplock a device object, but
  927. // hey, if it makes them happy...
  928. //
  929. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  930. DfsDbgTrace(-1, Dbg, "DfsOplockRequest -> STATUS_INVALID_PARAMETER\n", 0);
  931. return STATUS_INVALID_PARAMETER;
  932. } else {
  933. //
  934. // RedirectedFileOpen - we pass the buck to the underlying FS.
  935. //
  936. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  937. (*NextIrpSp) = (*IrpSp);
  938. IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
  939. //
  940. // ...and call the next device
  941. //
  942. Status = IoCallDriver( Fcb->TargetDevice, Irp );
  943. MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsOplockRequest_Error_IoCallDriver,
  944. LOGSTATUS(Status)
  945. LOGPTR(Irp)
  946. LOGPTR(FileObject));
  947. DfsDeleteIrpContext( IrpContext );
  948. return(Status);
  949. }
  950. }
  951. //+----------------------------------------------------------------------------
  952. //
  953. // Function: DfsStopDfs, local
  954. //
  955. // Synopsis: "Stops" the Dfs client - causes Dfs to release all references
  956. // to provider device objects.
  957. //
  958. // Arguments: None
  959. //
  960. // Returns: Nothing
  961. //
  962. //-----------------------------------------------------------------------------
  963. VOID
  964. DfsStopDfs()
  965. {
  966. ULONG i;
  967. PDFS_PKT_ENTRY pktEntry;
  968. PDFS_VCB Vcb;
  969. ExAcquireResourceExclusiveLite( &DfsData.Pkt.Resource, TRUE );
  970. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  971. //
  972. // Lets go through and release any opens to server IPC$ shares and
  973. // provider device objects.
  974. //
  975. for (pktEntry = PktFirstEntry(&DfsData.Pkt);
  976. pktEntry != NULL;
  977. pktEntry = PktNextEntry(&DfsData.Pkt, pktEntry)) {
  978. for (i = 0; i < pktEntry->Info.ServiceCount; i++) {
  979. if (pktEntry->Info.ServiceList[i].ConnFile != NULL) {
  980. ObDereferenceObject(
  981. pktEntry->Info.ServiceList[i].ConnFile);
  982. pktEntry->Info.ServiceList[i].ConnFile = NULL;
  983. }
  984. if (pktEntry->Info.ServiceList[i].pMachEntry->AuthConn != NULL) {
  985. ObDereferenceObject(
  986. pktEntry->Info.ServiceList[i].pMachEntry->AuthConn);
  987. pktEntry->Info.ServiceList[i].pMachEntry->AuthConn = NULL;
  988. pktEntry->Info.ServiceList[i].pMachEntry->Credentials->RefCount--;
  989. pktEntry->Info.ServiceList[i].pMachEntry->Credentials = NULL;
  990. }
  991. //
  992. // We are going to be closing all references to provider device
  993. // objects. So, clear the service's pointer to its provider.
  994. //
  995. pktEntry->Info.ServiceList[i].pProvider = NULL;
  996. }
  997. }
  998. for (i = 0; i < (ULONG) DfsData.cProvider; i++) {
  999. if (DfsData.pProvider[i].FileObject != NULL) {
  1000. ObDereferenceObject( DfsData.pProvider[i].FileObject );
  1001. DfsData.pProvider[i].FileObject = NULL;
  1002. ASSERT( DfsData.pProvider[i].DeviceObject != NULL );
  1003. ObDereferenceObject( DfsData.pProvider[i].DeviceObject );
  1004. DfsData.pProvider[i].DeviceObject = NULL;
  1005. }
  1006. }
  1007. ExReleaseResourceLite( &DfsData.Resource );
  1008. ExReleaseResourceLite( &DfsData.Pkt.Resource );
  1009. }
  1010. //+----------------------------------------------------------------------------
  1011. //
  1012. // Function: DfsFsctrlIsThisADfsPath, local
  1013. //
  1014. // Synopsis: Determines whether a given path is a Dfs path or not.
  1015. // The general algorithm is:
  1016. //
  1017. // - Do a prefix lookup in the Pkt. If an entry is found, it's
  1018. // a Dfs path.
  1019. // - Ask the Dfs service whether this is a domain based Dfs
  1020. // path. If so, it's a Dfs path.
  1021. // - Finally, do an ZwCreateFile on the path name (assuming
  1022. // it's a Dfs path). If it succeeds, it's a Dfs path.
  1023. //
  1024. // Arguments: [filePath] - Name of entire file
  1025. // [pathName] - If this is a Dfs path, this will return the
  1026. // component of filePath that was a Dfs path name (ie, the
  1027. // entry path of the Dfs volume that holds the file). The
  1028. // buffer will point to the same buffer as filePath, so
  1029. // nothing is allocated.
  1030. //
  1031. // Returns: [STATUS_SUCCESS] -- filePath is a Dfs path.
  1032. //
  1033. // [STATUS_BAD_NETWORK_PATH] -- filePath is not a Dfs path.
  1034. //
  1035. //-----------------------------------------------------------------------------
  1036. NTSTATUS
  1037. DfsFsctrlIsThisADfsPath(
  1038. IN PUNICODE_STRING filePath,
  1039. IN BOOLEAN CSCAgentCreate,
  1040. OUT PUNICODE_STRING pathName)
  1041. {
  1042. NTSTATUS status;
  1043. PDFS_PKT pkt;
  1044. PDFS_PKT_ENTRY pktEntry;
  1045. UNICODE_STRING dfsRootName, shareName, remPath;
  1046. UNICODE_STRING RootShareName;
  1047. USHORT i, j;
  1048. BOOLEAN pktLocked;
  1049. PDFS_SPECIAL_ENTRY pSpecialEntry;
  1050. LARGE_INTEGER StartTime;
  1051. LARGE_INTEGER EndTime;
  1052. KeQuerySystemTime(&StartTime);
  1053. DfsDbgTrace(+1, Dbg, "DfsFsctrlIsThisADfsPath: Entered %wZ\n", filePath);
  1054. #if DBG
  1055. if (MupVerbose) {
  1056. KeQuerySystemTime(&EndTime);
  1057. DbgPrint("[%d] DfsFsctrlIsThisADfsPath: Entered %wZ\n",
  1058. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)),
  1059. filePath);
  1060. }
  1061. #endif
  1062. //
  1063. // Only proceed if the first character is a backslash.
  1064. //
  1065. if (filePath->Buffer[0] != UNICODE_PATH_SEP) {
  1066. status = STATUS_BAD_NETWORK_PATH;
  1067. DfsDbgTrace(-1, Dbg, "filePath does not begin with backslash\n", 0);
  1068. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Error_PathDoesNotBeginWithBackSlash,
  1069. LOGSTATUS(status));
  1070. return( status );
  1071. }
  1072. //
  1073. // Find the second component in the name.
  1074. //
  1075. for (i = 1;
  1076. i < filePath->Length/sizeof(WCHAR) &&
  1077. filePath->Buffer[i] != UNICODE_PATH_SEP;
  1078. i++) {
  1079. NOTHING;
  1080. }
  1081. if (i >= filePath->Length/sizeof(WCHAR)) {
  1082. status = STATUS_BAD_NETWORK_PATH;
  1083. DfsDbgTrace(-1, Dbg, "Did not find second backslash\n", 0);
  1084. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Error_DidNotFindSecondBackSlash,
  1085. LOGSTATUS(status));
  1086. return( status );
  1087. }
  1088. status = DfspIsRootOnline(filePath, CSCAgentCreate);
  1089. if (!NT_SUCCESS(status)) {
  1090. return STATUS_BAD_NETWORK_PATH;
  1091. }
  1092. dfsRootName.Length = (i-1) * sizeof(WCHAR);
  1093. dfsRootName.MaximumLength = dfsRootName.Length;
  1094. dfsRootName.Buffer = &filePath->Buffer[1];
  1095. if (dfsRootName.Length == 0) {
  1096. status = STATUS_BAD_NETWORK_PATH;
  1097. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Error_DfsRootNameHasZeroLength,
  1098. LOGSTATUS(status));
  1099. return( status );
  1100. }
  1101. //
  1102. // Figure out the share name
  1103. //
  1104. for (j = i+1;
  1105. j < filePath->Length/sizeof(WCHAR) &&
  1106. filePath->Buffer[j] != UNICODE_PATH_SEP;
  1107. j++) {
  1108. NOTHING;
  1109. }
  1110. shareName.Length = (j - i - 1) * sizeof(WCHAR);
  1111. shareName.MaximumLength = shareName.Length;
  1112. shareName.Buffer = &filePath->Buffer[i+1];
  1113. if (shareName.Length == 0) {
  1114. status = STATUS_BAD_NETWORK_PATH;
  1115. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Error_ShareNameHasZeroLength,
  1116. LOGSTATUS(status));
  1117. return( status );
  1118. }
  1119. if (DfspIsSpecialShare(&shareName)) {
  1120. status = STATUS_BAD_NETWORK_PATH;
  1121. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Error_DfspIsSpecialShare_FALSE,
  1122. LOGUSTR(shareName)
  1123. LOGSTATUS(status));
  1124. return( status );
  1125. }
  1126. //
  1127. // For our purposes we only need to check the \\server\share part of the
  1128. // filePath presented. Any longer matches will be handled in the dnr loop -
  1129. // we don't care about junction points below the root at this stage.
  1130. //
  1131. RootShareName.Buffer = filePath->Buffer;
  1132. RootShareName.Length = j * sizeof(WCHAR);
  1133. RootShareName.MaximumLength = filePath->MaximumLength;
  1134. #if DBG
  1135. if (MupVerbose)
  1136. DbgPrint(" RootShareName=[%wZ]\n", &RootShareName);
  1137. #endif
  1138. //
  1139. // First, do a prefix lookup. If we find an entry, it's a Dfs path
  1140. //
  1141. pkt = _GetPkt();
  1142. PktAcquireShared( TRUE, &pktLocked );
  1143. pktEntry = PktLookupEntryByPrefix( pkt, &RootShareName, &remPath );
  1144. if (pktEntry != NULL && pktEntry->ExpireTime > 0) {
  1145. DfsDbgTrace(-1, Dbg, "Found pkt entry %08lx\n", pktEntry);
  1146. pathName->Length = RootShareName.Length - remPath.Length;
  1147. pathName->MaximumLength = pathName->Length;
  1148. pathName->Buffer = RootShareName.Buffer;
  1149. PktRelease();
  1150. #if DBG
  1151. if (MupVerbose) {
  1152. KeQuerySystemTime(&EndTime);
  1153. DbgPrint("[%d] DfsFsctrlIsThisADfsPath(1): exit STATUS_SUCCESS\n",
  1154. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)));
  1155. }
  1156. #endif
  1157. return( STATUS_SUCCESS );
  1158. }
  1159. #if DBG
  1160. if (MupVerbose) {
  1161. if (pktEntry == NULL)
  1162. DbgPrint(" No pkt entry found.\n");
  1163. else
  1164. DbgPrint(" Stale pkt entry 0x%x ExpireTime=%d\n", pktEntry, pktEntry->ExpireTime);
  1165. }
  1166. #endif
  1167. PktRelease();
  1168. //
  1169. // Nothing in the Pkt, check (by getting a referral) is this is a dfs
  1170. //
  1171. status = PktCreateDomainEntry( &dfsRootName, &shareName, CSCAgentCreate );
  1172. if (NT_SUCCESS(status)) {
  1173. pathName->Length = sizeof(UNICODE_PATH_SEP) + dfsRootName.Length;
  1174. pathName->MaximumLength = pathName->Length;
  1175. pathName->Buffer = RootShareName.Buffer;
  1176. DfsDbgTrace(-1, Dbg, "Domain/Machine Dfs name %wZ\n", pathName );
  1177. #if DBG
  1178. if (MupVerbose) {
  1179. KeQuerySystemTime(&EndTime);
  1180. DbgPrint("[%d] DfsFsctrlIsThisADfsPath(2): exit STATUS_SUCCESS\n",
  1181. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)));
  1182. }
  1183. #endif
  1184. return( STATUS_SUCCESS );
  1185. }
  1186. #if DBG
  1187. if (MupVerbose) {
  1188. KeQuerySystemTime(&EndTime);
  1189. DbgPrint(" [%d] PktCreateDomainEntry() returned 0x%x\n",
  1190. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)),
  1191. status);
  1192. }
  1193. #endif
  1194. //
  1195. // Failed getting referral - see if we have a stale one.
  1196. //
  1197. PktAcquireShared( TRUE, &pktLocked );
  1198. pktEntry = PktLookupEntryByPrefix( pkt, &RootShareName, &remPath );
  1199. if (pktEntry != NULL) {
  1200. #if DBG
  1201. if (MupVerbose)
  1202. DbgPrint(" Found stale pkt entry %08lx - adding 15 sec to it\n", pktEntry);
  1203. #endif
  1204. DfsDbgTrace(-1, Dbg, "Found pkt entry %08lx\n", pktEntry);
  1205. pathName->Length = RootShareName.Length - remPath.Length;
  1206. pathName->MaximumLength = pathName->Length;
  1207. pathName->Buffer = RootShareName.Buffer;
  1208. if (pktEntry->ExpireTime <= 0) {
  1209. pktEntry->ExpireTime = 15;
  1210. pktEntry->TimeToLive = 15;
  1211. }
  1212. PktRelease();
  1213. #if DBG
  1214. if (MupVerbose) {
  1215. KeQuerySystemTime(&EndTime);
  1216. DbgPrint("[%d] DfsFsctrlIsThisADfsPath(3): exit STATUS_SUCCESS\n",
  1217. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)));
  1218. }
  1219. #endif
  1220. return( STATUS_SUCCESS );
  1221. }
  1222. PktRelease();
  1223. if (DfspIsSysVolShare(&shareName)) {
  1224. #if DBG
  1225. if (MupVerbose)
  1226. DbgPrint(" Trying as sysvol\n");
  1227. #endif
  1228. status = PktExpandSpecialName(&dfsRootName, &pSpecialEntry);
  1229. if (NT_SUCCESS(status)) {
  1230. InterlockedDecrement(&pSpecialEntry->UseCount);
  1231. #if DBG
  1232. if (MupVerbose) {
  1233. KeQuerySystemTime(&EndTime);
  1234. DbgPrint("[%d] DfsFsctrlIsThisADfsPath(SYSVOL): exit STATUS_SUCCESS\n",
  1235. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)));
  1236. }
  1237. #endif
  1238. return STATUS_SUCCESS;
  1239. }
  1240. }
  1241. if (DfsIsSpecialName(&dfsRootName)) {
  1242. status = STATUS_SUCCESS;
  1243. return status;
  1244. }
  1245. DfsDbgTrace(-1, Dbg, "Not A Dfs path\n", 0);
  1246. #if DBG
  1247. if (MupVerbose) {
  1248. KeQuerySystemTime(&EndTime);
  1249. DbgPrint("[%d] DfsFsctrlIsThisADfsPath: exit STATUS_BAD_NETWORK_PATH\n",
  1250. (ULONG)((EndTime.QuadPart - StartTime.QuadPart)/(10 * 1000)));
  1251. }
  1252. #endif
  1253. status = STATUS_BAD_NETWORK_PATH;
  1254. MUP_TRACE_HIGH(ERROR, DfsFsctrlIsThisADfsPath_Exit_NotADfsPath,
  1255. LOGSTATUS(status));
  1256. return( STATUS_BAD_NETWORK_PATH );
  1257. }
  1258. //+----------------------------------------------------------------------------
  1259. //
  1260. // Function: DfspIsSpecialShare, local
  1261. //
  1262. // Synopsis: Sees if a share name is a special share.
  1263. //
  1264. // Arguments: [ShareName] -- Name of share to test.
  1265. //
  1266. // Returns: TRUE if special, FALSE otherwise.
  1267. //
  1268. //-----------------------------------------------------------------------------
  1269. BOOLEAN
  1270. DfspIsSpecialShare(
  1271. PUNICODE_STRING ShareName)
  1272. {
  1273. ULONG i;
  1274. BOOLEAN fSpecial = FALSE;
  1275. for (i = 0;
  1276. (i < (sizeof(SpecialShares) / sizeof(SpecialShares[0]))) &&
  1277. !fSpecial;
  1278. i++) {
  1279. if (SpecialShares[i].Length == ShareName->Length) {
  1280. if (_wcsnicmp(
  1281. SpecialShares[i].Buffer,
  1282. ShareName->Buffer,
  1283. ShareName->Length/sizeof(WCHAR)) == 0) {
  1284. fSpecial = TRUE;
  1285. }
  1286. }
  1287. }
  1288. return( fSpecial );
  1289. }
  1290. //+----------------------------------------------------------------------------
  1291. //
  1292. // Function: DfspIsSysVolShare, local
  1293. //
  1294. // Synopsis: Sees if a share name is a sysvol share.
  1295. //
  1296. // Arguments: [ShareName] -- Name of share to test.
  1297. //
  1298. // Returns: TRUE if special, FALSE otherwise.
  1299. //
  1300. //-----------------------------------------------------------------------------
  1301. BOOLEAN
  1302. DfspIsSysVolShare(
  1303. PUNICODE_STRING ShareName)
  1304. {
  1305. ULONG i;
  1306. BOOLEAN fSpecial = FALSE;
  1307. for (i = 0;
  1308. (i < (sizeof(SysVolShares) / sizeof(SysVolShares[0]))) &&
  1309. !fSpecial;
  1310. i++) {
  1311. if (SysVolShares[i].Length == ShareName->Length) {
  1312. if (_wcsnicmp(
  1313. SysVolShares[i].Buffer,
  1314. ShareName->Buffer,
  1315. ShareName->Length/sizeof(WCHAR)) == 0) {
  1316. fSpecial = TRUE;
  1317. }
  1318. }
  1319. }
  1320. return( fSpecial );
  1321. }
  1322. //+-------------------------------------------------------------------------
  1323. //
  1324. // Function: DfsFsctrlDefineLogicalRoot, local
  1325. //
  1326. // Synopsis: DfsFsctrlDefineLogicalRoot will create a new logical root structure.
  1327. //
  1328. // Arguments: [IrpContext] -
  1329. // [Irp] -
  1330. // [pDlrParam] -- Pointer to a FILE_DFS_DEF_ROOT_BUFFER,
  1331. // giving the name of the logical root to be created.
  1332. // [InputBufferLength] -- Size of InputBuffer
  1333. //
  1334. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  1335. //
  1336. // Notes: This routine needs to be called from the FSP thread,
  1337. // since IoCreateDevice (called from DfsInitializeLogicalRoot)
  1338. // will fail if PreviousMode != KernelMode.
  1339. //
  1340. //--------------------------------------------------------------------------
  1341. NTSTATUS
  1342. DfsFsctrlDefineLogicalRoot (
  1343. IN PIRP_CONTEXT IrpContext,
  1344. IN PIRP Irp,
  1345. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  1346. IN ULONG InputBufferLength
  1347. ) {
  1348. NTSTATUS Status;
  1349. UNICODE_STRING ustrPrefix;
  1350. BOOLEAN pktLocked;
  1351. PWCHAR wCp;
  1352. PCHAR InputBufferEnd = (PCHAR)pDlrParam + InputBufferLength;
  1353. ULONG i;
  1354. LUID LogonID;
  1355. #ifdef TERMSRV
  1356. ULONG SessionID;
  1357. #endif
  1358. DfsDbgTrace(+1, Dbg, "DfsFsctrlDefineLogicalRoot...\n", 0);
  1359. //
  1360. // Reference the input buffer and make sure it's large enough
  1361. //
  1362. if (InputBufferLength < sizeof (FILE_DFS_DEF_ROOT_BUFFER)) {
  1363. DfsDbgTrace(0, Dbg, "Input buffer is too small\n", 0);
  1364. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  1365. Status = STATUS_INVALID_PARAMETER;
  1366. DfsDbgTrace(-1, Dbg, "DfsFsctrlDefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1367. return Status;
  1368. }
  1369. //
  1370. // Verify there's a null someplace in the LogicalRoot buffer
  1371. //
  1372. for (i = 0; i < MAX_LOGICAL_ROOT_NAME && pDlrParam->LogicalRoot[i]; i++)
  1373. NOTHING;
  1374. if (i >= MAX_LOGICAL_ROOT_NAME) {
  1375. Status = STATUS_INVALID_PARAMETER;
  1376. DfsCompleteRequest( IrpContext, Irp, Status );
  1377. DfsDbgTrace(-1, Dbg, "DfsFsctrlDefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1378. return Status;
  1379. }
  1380. //
  1381. // Verify there's a null someplace in the RootPrefix buffer
  1382. //
  1383. for (wCp = &pDlrParam->RootPrefix[0]; wCp < (PWCHAR)InputBufferEnd && *wCp; wCp++) {
  1384. NOTHING;
  1385. }
  1386. if (wCp >= (PWCHAR)InputBufferEnd) {
  1387. Status = STATUS_INVALID_PARAMETER;
  1388. DfsCompleteRequest( IrpContext, Irp, Status );
  1389. DfsDbgTrace(-1, Dbg, "DfsFsctrlDefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1390. return Status;
  1391. }
  1392. //
  1393. // We can insert logical roots only from the FSP, because IoCreateDevice
  1394. // will fail if previous mode != Kernel mode.
  1395. //
  1396. if ((IrpContext->Flags & IRP_CONTEXT_FLAG_IN_FSD) != 0) {
  1397. DfsDbgTrace(0, Dbg, "DfsFsctrlDefineLogicalRoot: Posting to FSP\n", 0);
  1398. Status = DfsFsdPostRequest( IrpContext, Irp );
  1399. DfsDbgTrace(-1, Dbg, "DfsFsctrlDefineLogicalRoot: Exit -> %08lx\n", ULongToPtr(Status) );
  1400. return(Status);
  1401. }
  1402. //
  1403. // Since we are going to muck with DfsData's VcbQueue, we acquire it
  1404. // exclusively.
  1405. //
  1406. RtlInitUnicodeString(&ustrPrefix, pDlrParam->RootPrefix);
  1407. PktAcquireExclusive( TRUE, &pktLocked );
  1408. ExAcquireResourceExclusiveLite(&DfsData.Resource, TRUE);
  1409. Status = DfsGetLogonId(&LogonID);
  1410. #ifdef TERMSRV
  1411. Status = IoGetRequestorSessionId(Irp, &SessionID);
  1412. if( NT_SUCCESS( Status ) ) {
  1413. Status =
  1414. DfsInitializeLogicalRoot(
  1415. (PWSTR) pDlrParam->LogicalRoot,
  1416. &ustrPrefix,
  1417. NULL,
  1418. 0,
  1419. SessionID,
  1420. &LogonID );
  1421. }
  1422. #else // TERMSRV
  1423. Status = DfsInitializeLogicalRoot(
  1424. (PWSTR) pDlrParam->LogicalRoot,
  1425. &ustrPrefix,
  1426. NULL,
  1427. 0,
  1428. &LogonID );
  1429. #endif // TERMSRV
  1430. ExReleaseResourceLite(&DfsData.Resource);
  1431. PktRelease();
  1432. DfsCompleteRequest(IrpContext, Irp, Status);
  1433. DfsDbgTrace(-1, Dbg, "DfsFsctrlDefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1434. return Status;
  1435. }
  1436. //+----------------------------------------------------------------------------
  1437. //
  1438. // Function: DfsFsctrlUndefineLogicalRoot
  1439. //
  1440. // Synopsis: Deletes an existing logical root structure.
  1441. //
  1442. // Arguments: [IrpContext] --
  1443. // [Irp] --
  1444. // [pDlrParam] -- The LogicalRoot field of this structure will
  1445. // contain the name of the logical root to be deleted.
  1446. // [InputBufferLength] -- Length of pDlrParam
  1447. //
  1448. // Returns: Yes ;-)
  1449. //
  1450. //-----------------------------------------------------------------------------
  1451. NTSTATUS
  1452. DfsFsctrlUndefineLogicalRoot (
  1453. IN PIRP_CONTEXT IrpContext,
  1454. IN PIRP Irp,
  1455. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  1456. IN ULONG InputBufferLength)
  1457. {
  1458. NTSTATUS Status;
  1459. BOOLEAN pktLocked;
  1460. ULONG i;
  1461. PWCHAR wCp;
  1462. PCHAR InputBufferEnd = (PCHAR)pDlrParam + InputBufferLength;
  1463. LUID LogonID ;
  1464. #ifdef TERMSRV
  1465. ULONG SessionID;
  1466. #endif
  1467. DfsDbgTrace(+1, Dbg, "DfsFsctrlUndefineLogicalRoot...\n", 0);
  1468. //
  1469. // Reference the input buffer and make sure it's large enough
  1470. //
  1471. if (InputBufferLength < sizeof (FILE_DFS_DEF_ROOT_BUFFER)) {
  1472. DfsDbgTrace(0, Dbg, "Input buffer is too small\n", 0);
  1473. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  1474. Status = STATUS_INVALID_PARAMETER;
  1475. DfsDbgTrace(-1, Dbg, "DfsFsctrlUndefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1476. return Status;
  1477. }
  1478. DfsGetLogonId( &LogonID );
  1479. //
  1480. // Verify there's a null someplace in the LogicalRoot buffer
  1481. //
  1482. for (i = 0; i < MAX_LOGICAL_ROOT_NAME && pDlrParam->LogicalRoot[i]; i++)
  1483. NOTHING;
  1484. if (i >= MAX_LOGICAL_ROOT_NAME) {
  1485. Status = STATUS_INVALID_PARAMETER;
  1486. DfsCompleteRequest( IrpContext, Irp, Status );
  1487. DfsDbgTrace(-1, Dbg, "DfsFsctrlUndefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1488. return Status;
  1489. }
  1490. if (pDlrParam->LogicalRoot[0] == UNICODE_NULL) {
  1491. //
  1492. // Verify there's a null someplace in the RootPrefix buffer
  1493. //
  1494. for (wCp = &pDlrParam->RootPrefix[0]; wCp < (PWCHAR)InputBufferEnd && *wCp; wCp++) {
  1495. NOTHING;
  1496. }
  1497. if (wCp >= (PWCHAR)InputBufferEnd) {
  1498. Status = STATUS_INVALID_PARAMETER;
  1499. DfsCompleteRequest( IrpContext, Irp, Status );
  1500. DfsDbgTrace(-1, Dbg, "DfsFsctrlUnDefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1501. return Status;
  1502. }
  1503. }
  1504. #ifdef TERMSRV
  1505. if ( !NT_SUCCESS(IoGetRequestorSessionId(Irp, &SessionID)) ) {
  1506. Status = STATUS_INVALID_PARAMETER;
  1507. DfsCompleteRequest( IrpContext, Irp, Status );
  1508. DfsDbgTrace(-1, Dbg, "DfsFsctrlUndefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1509. return Status;
  1510. }
  1511. #endif
  1512. //
  1513. // We can remove logical roots only from the FSP
  1514. //
  1515. if (pDlrParam->LogicalRoot[0] != UNICODE_NULL) {
  1516. DfsDbgTrace(0, Dbg, "Deleting root [%ws]\n", pDlrParam->LogicalRoot);
  1517. #ifdef TERMSRV
  1518. Status =
  1519. DfsDeleteLogicalRoot(
  1520. (PWSTR) pDlrParam->LogicalRoot,
  1521. pDlrParam->fForce,
  1522. SessionID,
  1523. &LogonID );
  1524. #else // TERMSRV
  1525. Status = DfsDeleteLogicalRoot(
  1526. (PWSTR) pDlrParam->LogicalRoot,
  1527. pDlrParam->fForce,
  1528. &LogonID);
  1529. #endif // TERMSRV
  1530. DfsDbgTrace(0, Dbg, "DfsDeleteLogicalRoot returned %08lx\n", ULongToPtr(Status) );
  1531. } else {
  1532. UNICODE_STRING name;
  1533. RtlInitUnicodeString(&name, pDlrParam->RootPrefix);
  1534. DfsDbgTrace(0, Dbg, "Deleting connection to [%wZ]\n", &name);
  1535. #ifdef TERMSRV
  1536. Status = DfsDeleteDevlessRoot(
  1537. &name,
  1538. SessionID,
  1539. &LogonID );
  1540. #else // TERMSRV
  1541. Status = DfsDeleteDevlessRoot(
  1542. &name,
  1543. &LogonID);
  1544. #endif // TERMSRV
  1545. }
  1546. DfsCompleteRequest(IrpContext, Irp, Status);
  1547. DfsDbgTrace(-1, Dbg, "DfsFsctrlUndefineLogicalRoot -> %08lx\n", ULongToPtr(Status) );
  1548. return Status;
  1549. }
  1550. //+----------------------------------------------------------------------------
  1551. //
  1552. // Function: DfsFsctrlGetLogicalRootPrefix
  1553. //
  1554. // Synopsis:
  1555. //
  1556. // Arguments:
  1557. //
  1558. // Returns:
  1559. //
  1560. //-----------------------------------------------------------------------------
  1561. NTSTATUS
  1562. DfsFsctrlGetLogicalRootPrefix (
  1563. IN PIRP_CONTEXT IrpContext,
  1564. IN PIRP Irp,
  1565. IN PFILE_DFS_DEF_ROOT_BUFFER pDlrParam,
  1566. IN ULONG InputBufferLength,
  1567. IN OUT PUCHAR OutputBuffer,
  1568. IN ULONG OutputBufferLength)
  1569. {
  1570. NTSTATUS Status;
  1571. UNICODE_STRING RootPath, Remaining;
  1572. PDFS_VCB Vcb;
  1573. WCHAR RootBuffer[MAX_LOGICAL_ROOT_NAME + 2];
  1574. BOOLEAN bAcquired = FALSE;
  1575. ULONG i;
  1576. USHORT PrefixLength;
  1577. LUID LogonID;
  1578. #ifdef TERMSRV
  1579. ULONG SessionID;
  1580. #endif
  1581. DfsDbgTrace(+1, Dbg, "DfsFsctrlGetLogicalRootPrefix...\n", 0);
  1582. //
  1583. // Reference the input buffer and make sure it's large enough
  1584. //
  1585. if (InputBufferLength < sizeof (FILE_DFS_DEF_ROOT_BUFFER)) {
  1586. DfsDbgTrace(0, Dbg, "Input buffer is too small\n", 0);
  1587. Status = STATUS_INVALID_PARAMETER;
  1588. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetLogicalRootPrefix -> %08lx\n", ULongToPtr(Status) );
  1589. goto Cleanup;
  1590. }
  1591. //
  1592. // Verify there's a null someplace in the buffer
  1593. //
  1594. for (i = 0; i < MAX_LOGICAL_ROOT_NAME && pDlrParam->LogicalRoot[i]; i++)
  1595. NOTHING;
  1596. if (i >= MAX_LOGICAL_ROOT_NAME) {
  1597. Status = STATUS_INVALID_PARAMETER;
  1598. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetLogicalRootPrefix -> %08lx\n", ULongToPtr(Status) );
  1599. goto Cleanup;
  1600. }
  1601. RootPath.Buffer = RootBuffer;
  1602. RootPath.Length = 0;
  1603. RootPath.MaximumLength = sizeof RootBuffer;
  1604. Status = DfspLogRootNameToPath(pDlrParam->LogicalRoot, &RootPath);
  1605. if (!NT_SUCCESS(Status)) {
  1606. DfsDbgTrace(0, Dbg, "Input name is too big\n", 0);
  1607. Status = STATUS_INVALID_PARAMETER;
  1608. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetLogicalRootPrefix -> %08lx\n", ULongToPtr(Status) );
  1609. goto Cleanup;
  1610. }
  1611. bAcquired = ExAcquireResourceSharedLite(&DfsData.Resource, TRUE);
  1612. DfsGetLogonId(&LogonID);
  1613. #ifdef TERMSRV
  1614. Status = IoGetRequestorSessionId(Irp, &SessionID);
  1615. if( NT_SUCCESS( Status ) ) {
  1616. Status = DfsFindLogicalRoot( &RootPath, SessionID, &LogonID, &Vcb, &Remaining);
  1617. }
  1618. #else // TERMSRV
  1619. Status = DfsFindLogicalRoot(&RootPath, &LogonID, &Vcb, &Remaining);
  1620. #endif // TERMSRV
  1621. if (!NT_SUCCESS(Status)) {
  1622. DfsDbgTrace(0, Dbg, "Logical root not found!\n", 0);
  1623. Status = STATUS_NO_SUCH_DEVICE;
  1624. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetLogicalRootPrefix -> %08lx\n", ULongToPtr(Status) );
  1625. goto Cleanup;
  1626. }
  1627. PrefixLength = Vcb->LogRootPrefix.Length;
  1628. if ((PrefixLength + sizeof(UNICODE_NULL)) > OutputBufferLength) {
  1629. //
  1630. // Return required length in IoStatus.Information.
  1631. //
  1632. RETURN_BUFFER_SIZE( PrefixLength + sizeof(UNICODE_NULL), Status );
  1633. DfsDbgTrace(0, Dbg, "Output buffer too small\n", 0);
  1634. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetLogicalRootPrefix -> %08lx\n", ULongToPtr(Status) );
  1635. goto Cleanup;
  1636. }
  1637. //
  1638. // All ok, copy prefix and get out.
  1639. //
  1640. if (PrefixLength > 0) {
  1641. RtlMoveMemory(
  1642. OutputBuffer,
  1643. Vcb->LogRootPrefix.Buffer,
  1644. PrefixLength);
  1645. }
  1646. ((PWCHAR) OutputBuffer)[PrefixLength/sizeof(WCHAR)] = UNICODE_NULL;
  1647. Irp->IoStatus.Information = Vcb->LogRootPrefix.Length + sizeof(UNICODE_NULL);
  1648. Status = STATUS_SUCCESS;
  1649. Cleanup:
  1650. if (bAcquired) {
  1651. ExReleaseResourceLite(&DfsData.Resource);
  1652. }
  1653. DfsCompleteRequest(IrpContext, Irp, Status);
  1654. return(Status);
  1655. }
  1656. //+----------------------------------------------------------------------------
  1657. //
  1658. // Function: DfsFsctrlGetConnectedResources
  1659. //
  1660. // Synopsis: Returns LPNETRESOURCE structures for each Logical Root,
  1661. // starting from the logical root indicated in the InputBuffer
  1662. // and including as many as will fit in OutputBuffer.
  1663. //
  1664. // Arguments:
  1665. //
  1666. // Returns:
  1667. //
  1668. //-----------------------------------------------------------------------------
  1669. NTSTATUS
  1670. DfsFsctrlGetConnectedResources(
  1671. IN PIRP_CONTEXT IrpContext,
  1672. IN PIRP Irp,
  1673. IN PUCHAR InputBuffer,
  1674. IN ULONG InputBufferLength,
  1675. IN PUCHAR OutputBuffer,
  1676. IN ULONG OutputBufferLength)
  1677. {
  1678. NTSTATUS Status = STATUS_SUCCESS;
  1679. PLIST_ENTRY Link;
  1680. PDFS_DEVLESS_ROOT pDrt;
  1681. PDFS_VCB pVcb;
  1682. ULONG count = 0;
  1683. ULONG remLen;
  1684. ULONG skipNum;
  1685. ULONG DFS_UNALIGNED *retCnt;
  1686. UNICODE_STRING providerName;
  1687. PUCHAR buf = OutputBuffer;
  1688. BOOLEAN providerNameAllocated;
  1689. LUID LogonID;
  1690. ULONG ResourceSize;
  1691. #ifdef TERMSRV
  1692. ULONG SessionID;
  1693. #endif
  1694. STD_FSCTRL_PROLOGUE(DfsFsctrlGetConnectedResources, TRUE, TRUE, FALSE);
  1695. #ifdef TERMSRV
  1696. //
  1697. // Get SessionID of this request first.
  1698. //
  1699. Status = IoGetRequestorSessionId(Irp, &SessionID);
  1700. if( !NT_SUCCESS(Status) ) {
  1701. Status = STATUS_INVALID_PARAMETER;
  1702. DfsCompleteRequest( IrpContext, Irp, Status );
  1703. DfsDbgTrace(-1,Dbg,
  1704. "DfsFsctrlGetConnectedResources: Exit->%08lx\n", ULongToPtr(Status) );
  1705. return Status;
  1706. }
  1707. #endif
  1708. if (OutputBufferLength < sizeof(ULONG)) {
  1709. Status = STATUS_BUFFER_TOO_SMALL;
  1710. DfsCompleteRequest( IrpContext, Irp, Status );
  1711. DfsDbgTrace(-1,Dbg,
  1712. "DfsFsctrlGetConnectedResources: Exit->%08lx\n", ULongToPtr(Status) );
  1713. return( Status );
  1714. }
  1715. if (InputBufferLength < sizeof(DWORD)) {
  1716. Status = STATUS_INVALID_PARAMETER;
  1717. DfsCompleteRequest( IrpContext, Irp, Status );
  1718. DfsDbgTrace(-1,Dbg,
  1719. "DfsFsctrlGetConnectedResources: Exit->%08lx\n", ULongToPtr(Status) );
  1720. return Status;
  1721. }
  1722. if (InputBufferLength == sizeof(DWORD)) {
  1723. skipNum = *((ULONG *) InputBuffer);
  1724. providerName.Length = sizeof(DFS_PROVIDER_NAME) - sizeof(UNICODE_NULL);
  1725. providerName.MaximumLength = sizeof(DFS_PROVIDER_NAME);
  1726. providerName.Buffer = DFS_PROVIDER_NAME;
  1727. providerNameAllocated = FALSE;
  1728. } else {
  1729. skipNum = 0;
  1730. providerName.Length =
  1731. (USHORT) (InputBufferLength - sizeof(UNICODE_NULL));
  1732. providerName.MaximumLength = (USHORT) InputBufferLength;
  1733. providerName.Buffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, ' puM');
  1734. if (providerName.Buffer != NULL) {
  1735. providerNameAllocated = TRUE;
  1736. RtlCopyMemory(
  1737. providerName.Buffer,
  1738. InputBuffer,
  1739. InputBufferLength);
  1740. } else {
  1741. Status = STATUS_INSUFFICIENT_RESOURCES;
  1742. DfsCompleteRequest( IrpContext, Irp, Status );
  1743. DfsDbgTrace(-1,Dbg,
  1744. "DfsFsctrlGetConnectedResources: Exit->%08lx\n", ULongToPtr(Status) );
  1745. return Status;
  1746. }
  1747. }
  1748. RtlZeroMemory(OutputBuffer, OutputBufferLength);
  1749. remLen = OutputBufferLength-sizeof(ULONG);
  1750. retCnt = (ULONG *) (OutputBuffer + remLen);
  1751. DfsGetLogonId(&LogonID);
  1752. ExAcquireResourceSharedLite(&DfsData.Resource, TRUE);
  1753. //
  1754. // First get the device-less connections
  1755. //
  1756. for (Link = DfsData.DrtQueue.Flink;
  1757. Link != &DfsData.DrtQueue;
  1758. Link = Link->Flink ) {
  1759. pDrt = CONTAINING_RECORD( Link, DFS_DEVLESS_ROOT, DrtLinks );
  1760. #ifdef TERMSRV
  1761. if( (SessionID != INVALID_SESSIONID) &&
  1762. (SessionID == pDrt->SessionID) &&
  1763. RtlEqualLuid(&pDrt->LogonID, &LogonID) ) {
  1764. #else // TERMSRV
  1765. if ( RtlEqualLuid(&pDrt->LogonID, &LogonID) ) {
  1766. #endif
  1767. if (skipNum > 0) {
  1768. skipNum--;
  1769. } else {
  1770. //
  1771. // Report devices for this session only
  1772. //
  1773. Status = DfsGetResourceFromDevlessRoot(
  1774. Irp,
  1775. pDrt,
  1776. &providerName,
  1777. OutputBuffer,
  1778. buf,
  1779. &remLen,
  1780. &ResourceSize);
  1781. if (!NT_SUCCESS(Status))
  1782. break;
  1783. buf = buf + ResourceSize;
  1784. count++;
  1785. }
  1786. }
  1787. }
  1788. //
  1789. // Next, get the Device connections
  1790. //
  1791. if (NT_SUCCESS(Status)) {
  1792. for (Link = DfsData.VcbQueue.Flink;
  1793. Link != &DfsData.VcbQueue;
  1794. Link = Link->Flink ) {
  1795. pVcb = CONTAINING_RECORD( Link, DFS_VCB, VcbLinks );
  1796. #ifdef TERMSRV
  1797. if( (pVcb->LogicalRoot.Length == sizeof(WCHAR)) &&
  1798. (SessionID != INVALID_SESSIONID) &&
  1799. (SessionID == pVcb->SessionID) &&
  1800. RtlEqualLuid(&pVcb->LogonID, &LogonID) ) {
  1801. #else // TERMSRV
  1802. if ((pVcb->LogicalRoot.Length == sizeof(WCHAR)) &&
  1803. RtlEqualLuid(&pVcb->LogonID, &LogonID) ) {
  1804. #endif
  1805. if (skipNum > 0) {
  1806. skipNum--;
  1807. } else {
  1808. Status = DfsGetResourceFromVcb(
  1809. Irp,
  1810. pVcb,
  1811. &providerName,
  1812. OutputBuffer,
  1813. buf,
  1814. &remLen,
  1815. &ResourceSize);
  1816. if (!NT_SUCCESS(Status))
  1817. break;
  1818. buf = buf + ResourceSize;
  1819. count++;
  1820. }
  1821. }
  1822. }
  1823. }
  1824. if (!NT_SUCCESS(Status)) {
  1825. //
  1826. // Now if we did not get atleast one in, then we need to return
  1827. // required size which is in remLen.
  1828. //
  1829. if (count == 0) {
  1830. // the + sizeof(ULONG) is for cnt size
  1831. RETURN_BUFFER_SIZE( remLen + sizeof(ULONG), Status );
  1832. DfsDbgTrace(0, Dbg, "Output buffer too small\n", 0);
  1833. } else if (Status == STATUS_BUFFER_OVERFLOW) {
  1834. *retCnt = count;
  1835. Irp->IoStatus.Information = OutputBufferLength;
  1836. DfsDbgTrace(0, Dbg, "Could not fill in all RESOURCE structs \n", 0);
  1837. } else {
  1838. //
  1839. // Dont know why we should get any other error code.
  1840. //
  1841. ASSERT(Status == STATUS_BUFFER_OVERFLOW);
  1842. }
  1843. } else {
  1844. //
  1845. // Everything went smoothly.
  1846. //
  1847. DfsDbgTrace(0, Dbg, "Succeeded in getting all Resources \n", 0);
  1848. *retCnt = count;
  1849. Irp->IoStatus.Information = OutputBufferLength;
  1850. }
  1851. if (providerNameAllocated == TRUE) {
  1852. ExFreePool(providerName.Buffer);
  1853. }
  1854. ExReleaseResourceLite(&DfsData.Resource);
  1855. DfsCompleteRequest( IrpContext, Irp, Status );
  1856. DfsDbgTrace(-1,Dbg,"DfsFsctrlGetConnectedResources: Exit->%08lx\n", ULongToPtr(Status) );
  1857. return Status;
  1858. }
  1859. //+----------------------------------------------------------------------------
  1860. //
  1861. // Function: DfsFsctrlDefineRootCredentials
  1862. //
  1863. // Synopsis: Creates a new logical root, a new user credential record, or
  1864. // both.
  1865. //
  1866. // Arguments:
  1867. //
  1868. // Returns:
  1869. //
  1870. //-----------------------------------------------------------------------------
  1871. NTSTATUS
  1872. DfsFsctrlDefineRootCredentials(
  1873. IN PIRP_CONTEXT IrpContext,
  1874. IN PIRP Irp,
  1875. IN PUCHAR InputBuffer,
  1876. IN ULONG InputBufferLength)
  1877. {
  1878. NTSTATUS status = STATUS_SUCCESS;
  1879. PFILE_DFS_DEF_ROOT_CREDENTIALS def;
  1880. PDFS_CREDENTIALS creds = NULL;
  1881. ULONG prefixIndex;
  1882. UNICODE_STRING prefix;
  1883. BOOLEAN deviceless = FALSE;
  1884. LUID LogonID;
  1885. #ifdef TERMSRV
  1886. ULONG SessionID;
  1887. #endif
  1888. //
  1889. // We must do this from the FSP because IoCreateDevice will fail if
  1890. // PreviousMode != KernelMode
  1891. //
  1892. STD_FSCTRL_PROLOGUE(DfsFsctrlDefineRootCredentials, TRUE, FALSE, FALSE);
  1893. //
  1894. // Validate our parameters, best we can.
  1895. //
  1896. if (InputBufferLength < sizeof(FILE_DFS_DEF_ROOT_CREDENTIALS)) {
  1897. status = STATUS_INVALID_PARAMETER;
  1898. DfsCompleteRequest( IrpContext, Irp, status );
  1899. DfsDbgTrace(-1,Dbg,"DfsFsctrlDefineRootCredentials: Exit->%08lx\n", ULongToPtr(status) );
  1900. return status;
  1901. }
  1902. def = (PFILE_DFS_DEF_ROOT_CREDENTIALS) InputBuffer;
  1903. prefixIndex = (def->DomainNameLen +
  1904. def->UserNameLen +
  1905. def->PasswordLen +
  1906. def->ServerNameLen +
  1907. def->ShareNameLen) / sizeof(WCHAR);
  1908. prefix.MaximumLength = prefix.Length = def->RootPrefixLen;
  1909. prefix.Buffer = &def->Buffer[ prefixIndex ];
  1910. if (
  1911. !UNICODESTRING_IS_VALID(prefix, InputBuffer, InputBufferLength)
  1912. ||
  1913. (prefix.Length < (4 * sizeof(WCHAR)))
  1914. ||
  1915. (prefix.Buffer[0] != UNICODE_PATH_SEP)
  1916. ) {
  1917. status = STATUS_INVALID_PARAMETER;
  1918. DfsCompleteRequest( IrpContext, Irp, status );
  1919. DfsDbgTrace(-1,Dbg,"DfsFsctrlDefineRootCredentials: Exit->%08lx\n", ULongToPtr(status) );
  1920. return status;
  1921. }
  1922. deviceless = (BOOLEAN) (def->LogicalRoot[0] == UNICODE_NULL);
  1923. #ifdef TERMSRV
  1924. if (NT_SUCCESS(status)) {
  1925. status = IoGetRequestorSessionId(Irp, &SessionID);
  1926. if (!NT_SUCCESS(status) ) {
  1927. status = STATUS_INVALID_PARAMETER;
  1928. }
  1929. }
  1930. #endif
  1931. //
  1932. // Now get the LogonID.
  1933. //
  1934. if (NT_SUCCESS(status)) {
  1935. status = DfsGetLogonId(&LogonID);
  1936. }
  1937. //
  1938. // First, create the credentials.
  1939. //
  1940. if (NT_SUCCESS(status)) {
  1941. #ifdef TERMSRV
  1942. status = DfsCreateCredentials(def,
  1943. InputBufferLength,
  1944. SessionID,
  1945. &LogonID,
  1946. &creds );
  1947. #else // TERMSRV
  1948. status = DfsCreateCredentials(def,
  1949. InputBufferLength,
  1950. &LogonID,
  1951. &creds );
  1952. #endif // TERMSRV
  1953. if (NT_SUCCESS(status)) {
  1954. //
  1955. // Verify the credentials if the username, domainname, or
  1956. // password are not null
  1957. //
  1958. if ((def->DomainNameLen > 0) ||
  1959. (def->UserNameLen > 0) ||
  1960. (def->PasswordLen > 0)) {
  1961. status = DfsVerifyCredentials( &prefix, creds );
  1962. }
  1963. if (NT_SUCCESS(status)) {
  1964. PDFS_CREDENTIALS existingCreds;
  1965. status = DfsInsertCredentials( &creds, deviceless );
  1966. if (status == STATUS_OBJECT_NAME_COLLISION) {
  1967. status = STATUS_SUCCESS;
  1968. }
  1969. }
  1970. if (!NT_SUCCESS(status))
  1971. DfsFreeCredentials( creds );
  1972. }
  1973. }
  1974. //
  1975. // Next, try and create the logical root, if specified
  1976. //
  1977. if (NT_SUCCESS(status)) {
  1978. BOOLEAN pktLocked;
  1979. PktAcquireExclusive( TRUE, &pktLocked );
  1980. ExAcquireResourceExclusiveLite(&DfsData.Resource, TRUE);
  1981. if (!deviceless) {
  1982. USHORT VcbStateFlags = 0;
  1983. if (def->CSCAgentCreate) {
  1984. VcbStateFlags |= VCB_STATE_CSCAGENT_VOLUME;
  1985. }
  1986. #ifdef TERMSRV
  1987. status = DfsInitializeLogicalRoot(
  1988. (PWSTR) def->LogicalRoot,
  1989. &prefix,
  1990. creds,
  1991. VcbStateFlags,
  1992. SessionID,
  1993. &LogonID );
  1994. #else // TERMSRV
  1995. status = DfsInitializeLogicalRoot(
  1996. (PWSTR) def->LogicalRoot,
  1997. &prefix,
  1998. creds,
  1999. VcbStateFlags,
  2000. &LogonID );
  2001. #endif // TERMSRV
  2002. }
  2003. else {
  2004. #ifdef TERMSRV
  2005. status = DfsInitializeDevlessRoot(
  2006. &prefix,
  2007. creds,
  2008. SessionID,
  2009. &LogonID );
  2010. #else // TERMSRV
  2011. status = DfsInitializeDevlessRoot(
  2012. &prefix,
  2013. creds,
  2014. &LogonID );
  2015. #endif // TERMSRV
  2016. }
  2017. if (status != STATUS_SUCCESS) {
  2018. DfsDeleteCredentials( creds );
  2019. }
  2020. ExReleaseResourceLite(&DfsData.Resource);
  2021. PktRelease();
  2022. }
  2023. DfsCompleteRequest( IrpContext, Irp, status );
  2024. DfsDbgTrace(-1,Dbg,"DfsFsctrlDefineRootCredentials: Exit->%08lx\n", ULongToPtr(status) );
  2025. return status;
  2026. }
  2027. //+----------------------------------------------------------------------------
  2028. //
  2029. // Function: DfsFsctrlGetServerName
  2030. //
  2031. // Synopsis: Given a Prefix in Dfs namespace it gets a server name for
  2032. // it.
  2033. //
  2034. // Arguments:
  2035. //
  2036. // Returns:
  2037. //
  2038. //-----------------------------------------------------------------------------
  2039. NTSTATUS
  2040. DfsFsctrlGetServerName(
  2041. IN PIRP_CONTEXT IrpContext,
  2042. IN PIRP Irp,
  2043. IN PUCHAR InputBuffer,
  2044. IN ULONG InputBufferLength,
  2045. IN PUCHAR OutputBuffer,
  2046. IN ULONG OutputBufferLength)
  2047. {
  2048. NTSTATUS status = STATUS_SUCCESS;
  2049. PDFS_PKT pkt;
  2050. PDFS_PKT_ENTRY pEntry;
  2051. UNICODE_STRING ustrPrefix, RemainingPath;
  2052. PWCHAR pwch;
  2053. PDFS_SERVICE pService;
  2054. ULONG cbSizeRequired = 0;
  2055. BOOLEAN pktLocked;
  2056. PWCHAR wCp = (PWCHAR) InputBuffer;
  2057. ULONG i;
  2058. STD_FSCTRL_PROLOGUE(DfsFsctrlGetServerName, TRUE, TRUE, FALSE);
  2059. if (InputBufferLength < 2 * sizeof(WCHAR)
  2060. ||
  2061. wCp[0] != UNICODE_PATH_SEP
  2062. ) {
  2063. status = STATUS_INVALID_PARAMETER;
  2064. DfsCompleteRequest( IrpContext, Irp, status );
  2065. return status;
  2066. }
  2067. ustrPrefix.Length = (USHORT) InputBufferLength;
  2068. ustrPrefix.MaximumLength = (USHORT) InputBufferLength;
  2069. ustrPrefix.Buffer = (PWCHAR) InputBuffer;
  2070. if (ustrPrefix.Buffer[0] == UNICODE_PATH_SEP &&
  2071. ustrPrefix.Buffer[1] == UNICODE_PATH_SEP) {
  2072. ustrPrefix.Buffer++;
  2073. ustrPrefix.Length -= sizeof(WCHAR);
  2074. }
  2075. if (ustrPrefix.Buffer[ ustrPrefix.Length/sizeof(WCHAR) - 1]
  2076. == UNICODE_NULL) {
  2077. ustrPrefix.Length -= sizeof(WCHAR);
  2078. }
  2079. pkt = _GetPkt();
  2080. PktAcquireExclusive(TRUE, &pktLocked);
  2081. pEntry = PktLookupEntryByPrefix(pkt,
  2082. &ustrPrefix,
  2083. &RemainingPath);
  2084. if (pEntry == NULL) {
  2085. status = STATUS_OBJECT_NAME_NOT_FOUND;
  2086. } else {
  2087. if (pEntry->ActiveService != NULL) {
  2088. pService = pEntry->ActiveService;
  2089. } else if (pEntry->Info.ServiceCount == 0) {
  2090. pService = NULL;
  2091. } else {
  2092. pService = pEntry->Info.ServiceList;
  2093. }
  2094. if (pService != NULL) {
  2095. cbSizeRequired = sizeof(UNICODE_PATH_SEP) +
  2096. pService->Address.Length +
  2097. sizeof(UNICODE_PATH_SEP) +
  2098. RemainingPath.Length +
  2099. sizeof(UNICODE_NULL);
  2100. if (OutputBufferLength < cbSizeRequired) {
  2101. RETURN_BUFFER_SIZE(cbSizeRequired, status);
  2102. } else {
  2103. PWCHAR pwszPath, pwszAddr, pwszRemainingPath;
  2104. ULONG cwAddr;
  2105. //
  2106. // The code below is simply constructing a string of the form
  2107. // \<pService->Address>\RemainingPath. However, due to the
  2108. // fact that InputBuffer and OutputBuffer actually point to
  2109. // the same piece of memory, RemainingPath.Buffer points into
  2110. // a spot in the *OUTPUT* buffer. Hence, we first have to
  2111. // move the RemainingPath to its proper place in the
  2112. // OutputBuffer, and then stuff in the pService->Address,
  2113. // instead of the much more natural method of constructing the
  2114. // string left to right.
  2115. //
  2116. pwszPath = (PWCHAR) OutputBuffer;
  2117. pwszAddr = pService->Address.Buffer;
  2118. cwAddr = pService->Address.Length / sizeof(WCHAR);
  2119. if (cwAddr > 0 && pwszAddr[cwAddr-1] == UNICODE_PATH_SEP)
  2120. cwAddr--;
  2121. pwszRemainingPath = &pwszPath[ 1 + cwAddr ];
  2122. if (RemainingPath.Length > 0) {
  2123. if (RemainingPath.Buffer[0] != UNICODE_PATH_SEP) {
  2124. pwszRemainingPath++;
  2125. }
  2126. RtlMoveMemory(
  2127. pwszRemainingPath,
  2128. RemainingPath.Buffer,
  2129. RemainingPath.Length);
  2130. pwszRemainingPath[-1] = UNICODE_PATH_SEP;
  2131. }
  2132. pwszRemainingPath[RemainingPath.Length/sizeof(WCHAR)] = UNICODE_NULL;
  2133. RtlCopyMemory(
  2134. &pwszPath[1],
  2135. pwszAddr,
  2136. cwAddr * sizeof(WCHAR));
  2137. pwszPath[0] = UNICODE_PATH_SEP;
  2138. Irp->IoStatus.Information = cbSizeRequired;
  2139. }
  2140. } else {
  2141. status = STATUS_OBJECT_NAME_NOT_FOUND;
  2142. }
  2143. }
  2144. PktRelease();
  2145. DfsCompleteRequest( IrpContext, Irp, status );
  2146. DfsDbgTrace(-1,Dbg,"DfsFsctrlGetServerName: Exit->%08lx\n", ULongToPtr(status) );
  2147. return status;
  2148. }
  2149. //+----------------------------------------------------------------------------
  2150. //
  2151. // Function: DfsFsctrlGetPktEntryState
  2152. //
  2153. // Synopsis: Given a Prefix in Dfs namespace it gets a list of servers
  2154. // for it. (DFS_INFO_X calls).
  2155. //
  2156. // Arguments:
  2157. //
  2158. // Returns:
  2159. //
  2160. //-----------------------------------------------------------------------------
  2161. NTSTATUS
  2162. DfsFsctrlGetPktEntryState(
  2163. IN PIRP_CONTEXT IrpContext,
  2164. IN PIRP Irp,
  2165. IN PUCHAR InputBuffer,
  2166. IN ULONG InputBufferLength,
  2167. IN PUCHAR OutputBuffer,
  2168. IN ULONG OutputBufferLength)
  2169. {
  2170. NTSTATUS NtStatus = STATUS_SUCCESS;
  2171. PDFS_GET_PKT_ENTRY_STATE_ARG arg;
  2172. PDFS_SERVICE pService;
  2173. UNICODE_STRING DfsEntryPath;
  2174. UNICODE_STRING ServerName;
  2175. UNICODE_STRING ShareName;
  2176. UNICODE_STRING remPath;
  2177. PDFS_PKT pkt;
  2178. PDFS_PKT_ENTRY pktEntry;
  2179. BOOLEAN pktLocked = FALSE;
  2180. ULONG cbOutBuffer;
  2181. ULONG Level;
  2182. PCHAR cp;
  2183. PUCHAR InBuffer = NULL;
  2184. DfsDbgTrace(+1, Dbg, "DfsFsctrlGetPktEntryState\n", 0);
  2185. STD_FSCTRL_PROLOGUE(DfsFsctrlGetPktEntryState, TRUE, TRUE, FALSE);
  2186. if (InputBufferLength < sizeof(DFS_GET_PKT_ENTRY_STATE_ARG)) {
  2187. DfsDbgTrace( 0, Dbg, "Input buffer too small\n", 0);
  2188. NtStatus = STATUS_INVALID_PARAMETER;
  2189. Irp->IoStatus.Information = 0;
  2190. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  2191. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetPktEntryState -> %08lx\n", ULongToPtr(NtStatus) );
  2192. return( NtStatus );
  2193. }
  2194. //
  2195. // Dup the buffer - we're going to construct UNICODE strings that point into
  2196. // the buffer, and the buffer is also the output buffer, so we don't want to
  2197. // overwrite those strings as we build the output buffer.
  2198. //
  2199. InBuffer = ExAllocatePoolWithTag(PagedPool, InputBufferLength, ' puM');
  2200. if (InBuffer) {
  2201. try {
  2202. RtlCopyMemory(InBuffer, InputBuffer, InputBufferLength);
  2203. } except (EXCEPTION_EXECUTE_HANDLER) {
  2204. NtStatus = GetExceptionCode();
  2205. }
  2206. } else {
  2207. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  2208. }
  2209. //
  2210. // Check args that don't need to be unmarshalled.
  2211. //
  2212. if (NT_SUCCESS(NtStatus)) {
  2213. arg = (PDFS_GET_PKT_ENTRY_STATE_ARG) InBuffer;
  2214. if (!(arg->Level >= 1 && arg->Level <= 4) ||
  2215. (arg->ServerNameLen == 0 && arg->ShareNameLen != 0)) {
  2216. NtStatus = STATUS_INVALID_PARAMETER;
  2217. }
  2218. //
  2219. // All the path lengths have to add up. Eventhough these are signed values,
  2220. // ie. SHORTs, they can't be negative.
  2221. //
  2222. if (arg->DfsEntryPathLen < 0 ||
  2223. arg->ServerNameLen < 0 ||
  2224. arg->ShareNameLen < 0 ||
  2225. ((ULONG) (arg->DfsEntryPathLen + arg->ServerNameLen + arg->ShareNameLen) >
  2226. InputBufferLength)) {
  2227. NtStatus = STATUS_INVALID_PARAMETER;
  2228. }
  2229. }
  2230. //
  2231. // Unmarshall the strings
  2232. //
  2233. if (NT_SUCCESS(NtStatus)) {
  2234. try {
  2235. Level = arg->Level;
  2236. DfsEntryPath.Length = DfsEntryPath.MaximumLength = arg->DfsEntryPathLen;
  2237. DfsEntryPath.Buffer = arg->Buffer;
  2238. DfsDbgTrace( 0, Dbg, "\tDfsName=%wZ\n", &DfsEntryPath);
  2239. RtlInitUnicodeString(&ServerName, NULL);
  2240. RtlInitUnicodeString(&ShareName, NULL);
  2241. if (arg->ServerNameLen) {
  2242. cp = (PCHAR)arg->Buffer + arg->DfsEntryPathLen;
  2243. ServerName.Buffer = (WCHAR *)cp;
  2244. ServerName.Length = ServerName.MaximumLength = arg->ServerNameLen;
  2245. cp += arg->ServerNameLen;
  2246. }
  2247. if (arg->ShareNameLen) {
  2248. ShareName.Buffer = (WCHAR *)cp;
  2249. ShareName.Length = ShareName.MaximumLength = arg->ShareNameLen;
  2250. DfsDbgTrace( 0, Dbg, "\tServerName=%wZ\n", &ServerName);
  2251. DfsDbgTrace( 0, Dbg, "\tShareName=%wZ\n", &ShareName);
  2252. }
  2253. DfsDbgTrace( 0, Dbg, "\tLevel=%d\n", ULongToPtr(arg->Level) );
  2254. DfsDbgTrace( 0, Dbg, "\tOutputBufferLength=0x%x\n", ULongToPtr(OutputBufferLength) );
  2255. } except (EXCEPTION_EXECUTE_HANDLER) {
  2256. NtStatus = GetExceptionCode();
  2257. }
  2258. }
  2259. if (NT_SUCCESS(NtStatus)) {
  2260. //
  2261. // Do a prefix lookup. If we find an entry, it's a Dfs path
  2262. //
  2263. pkt = _GetPkt();
  2264. PktAcquireShared( TRUE, &pktLocked );
  2265. pktEntry = PktLookupEntryByPrefix( pkt, &DfsEntryPath, &remPath );
  2266. if (pktEntry != NULL) {
  2267. DfsDbgTrace( 0, Dbg, "\tFound pkt entry %08lx\n", pktEntry);
  2268. //
  2269. // Calculate the needed output buffer size
  2270. //
  2271. NtStatus = DfsGetEntryStateSize(Level,
  2272. &ServerName,
  2273. &ShareName,
  2274. pktEntry,
  2275. &cbOutBuffer);
  2276. //
  2277. // Let user know if it's too small
  2278. //
  2279. if (OutputBufferLength < cbOutBuffer) {
  2280. RETURN_BUFFER_SIZE(cbOutBuffer, NtStatus);
  2281. }
  2282. } else {
  2283. NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  2284. }
  2285. }
  2286. if (NtStatus == STATUS_SUCCESS) {
  2287. //
  2288. // Args are ok, and it fits - marshall the data
  2289. //
  2290. NtStatus = DfsGetEntryStateMarshall(Level,
  2291. &ServerName,
  2292. &ShareName,
  2293. pktEntry,
  2294. OutputBuffer,
  2295. cbOutBuffer);
  2296. Irp->IoStatus.Information = cbOutBuffer;
  2297. }
  2298. //
  2299. // Release any locks taken, and free any memory allocated.
  2300. //
  2301. if (pktLocked) {
  2302. PktRelease();
  2303. }
  2304. if (InBuffer) {
  2305. ExFreePool(InBuffer);
  2306. }
  2307. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  2308. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetPktEntryState -> %08lx\n", ULongToPtr(NtStatus) );
  2309. return( NtStatus );
  2310. }
  2311. //+----------------------------------------------------------------------------
  2312. //
  2313. // Function: DfsGetEntryStateSize
  2314. //
  2315. // Synopsis: Helper routine for DfsFsctrlGetPktEntryState
  2316. // Calculates output buffer size.
  2317. //
  2318. // Arguments:
  2319. //
  2320. // Returns:
  2321. //
  2322. //-----------------------------------------------------------------------------
  2323. NTSTATUS
  2324. DfsGetEntryStateSize(
  2325. ULONG Level,
  2326. PUNICODE_STRING ServerName,
  2327. PUNICODE_STRING ShareName,
  2328. PDFS_PKT_ENTRY pktEntry,
  2329. PULONG pcbOutBuffer)
  2330. {
  2331. UNICODE_STRING Server;
  2332. UNICODE_STRING Share;
  2333. PDFS_SERVICE pService;
  2334. ULONG Size;
  2335. ULONG NumServices;
  2336. ULONG i;
  2337. DfsDbgTrace(+1, Dbg, "DfsGetEntryStateSize\n", 0);
  2338. //
  2339. // Calculate the needed output buffer size
  2340. //
  2341. Size = pktEntry->Id.Prefix.Length + // Len of EntryPath
  2342. sizeof(WCHAR); // ... with null
  2343. switch (Level) {
  2344. case 4:
  2345. Size += sizeof(DFS_INFO_4);
  2346. break;
  2347. case 3:
  2348. Size += sizeof(DFS_INFO_3);
  2349. break;
  2350. case 2:
  2351. Size += sizeof(DFS_INFO_2);
  2352. break;
  2353. case 1:
  2354. Size += sizeof(DFS_INFO_1);
  2355. break;
  2356. }
  2357. //
  2358. // For Level 3 & 4, add the size of any storages that
  2359. // match the ServerName/ShareName passed in.
  2360. //
  2361. NumServices = pktEntry->Info.ServiceCount;
  2362. if (Level == 3 || Level == 4) {
  2363. for (i = 0; i < NumServices; i++) {
  2364. UNICODE_STRING uStr;
  2365. USHORT m, n;
  2366. pService = &pktEntry->Info.ServiceList[i];
  2367. DfsDbgTrace( 0, Dbg, "Examining %wZ\n", &pService->Address);
  2368. //
  2369. // We want to work with the \Server\Share part of the address only,
  2370. // so count up to 3 backslashes, then stop.
  2371. //
  2372. uStr = pService->Address;
  2373. for (m = n = 0; m < uStr.Length/sizeof(WCHAR) && n < 3; m++) {
  2374. if (uStr.Buffer[m] == UNICODE_PATH_SEP) {
  2375. n++;
  2376. }
  2377. }
  2378. uStr.Length = (n >= 3) ? (m-1) * sizeof(WCHAR) : m * sizeof(WCHAR);
  2379. //
  2380. // Tease apart the address (of form \Server\Share into Server and Share
  2381. //
  2382. RemoveLastComponent(&uStr, &Server);
  2383. //
  2384. // Remove leading & trailing '\'
  2385. //
  2386. Server.Length -= 2* sizeof(WCHAR);
  2387. Server.MaximumLength -= 2* sizeof(WCHAR);
  2388. Server.Buffer++;
  2389. //
  2390. // And figure out Share
  2391. //
  2392. Share.Buffer = Server.Buffer + (Server.Length / sizeof(WCHAR)) + 1;
  2393. Share.Length = pService->Address.Length - (Server.Length + 2 * sizeof(WCHAR));
  2394. Share.MaximumLength = Share.Length;
  2395. DfsDbgTrace( 0, Dbg, "DfsGetEntryStateSize: Server=%wZ\n", &Server);
  2396. DfsDbgTrace( 0, Dbg, " Share=%wZ\n", &Share);
  2397. if ((ServerName->Length && RtlCompareUnicodeString(ServerName, &Server, TRUE))
  2398. ||
  2399. (ShareName->Length && RtlCompareUnicodeString(ShareName, &Share, TRUE))) {
  2400. continue;
  2401. }
  2402. Size += sizeof(DFS_STORAGE_INFO) +
  2403. pService->Address.Length +
  2404. sizeof(WCHAR);
  2405. }
  2406. }
  2407. DfsDbgTrace( 0, Dbg, "Size=0x%x\n", ULongToPtr(Size) );
  2408. *pcbOutBuffer = Size;
  2409. DfsDbgTrace(-1, Dbg, "DfsGetEntryStateSize -> %08lx\n", STATUS_SUCCESS );
  2410. return (STATUS_SUCCESS);
  2411. }
  2412. //+----------------------------------------------------------------------------
  2413. //
  2414. // Function: DfsGetEntryStateMarshall
  2415. //
  2416. // Synopsis: Helper routine for DfsFsctrlGetPktEntryState
  2417. // Marshalls the output buffer
  2418. //
  2419. // Arguments:
  2420. //
  2421. // Returns:
  2422. //
  2423. //-----------------------------------------------------------------------------
  2424. NTSTATUS
  2425. DfsGetEntryStateMarshall(
  2426. ULONG Level,
  2427. PUNICODE_STRING ServerName,
  2428. PUNICODE_STRING ShareName,
  2429. PDFS_PKT_ENTRY pktEntry,
  2430. PBYTE OutputBuffer,
  2431. ULONG cbOutBuffer)
  2432. {
  2433. NTSTATUS NtStatus = STATUS_SUCCESS;
  2434. ULONG iStr;
  2435. ULONG i;
  2436. PDFS_INFO_4 pDfsInfo4;
  2437. PDFS_INFO_3 pDfsInfo3;
  2438. PDFS_STORAGE_INFO pDfsStorageInfo;
  2439. PDFS_SERVICE pService;
  2440. ULONG NumStorageInfo;
  2441. UNICODE_STRING Server;
  2442. UNICODE_STRING Share;
  2443. DfsDbgTrace(+1, Dbg, "DfsGetEntryStateMarshall\n", 0);
  2444. try {
  2445. RtlZeroMemory(OutputBuffer, cbOutBuffer);
  2446. pDfsInfo4 = (PDFS_INFO_4) OutputBuffer;
  2447. pDfsInfo3 = (PDFS_INFO_3) OutputBuffer;
  2448. //
  2449. // iStr will be used to place unicode strings into the buffer
  2450. // starting at the end, working backwards
  2451. //
  2452. iStr = cbOutBuffer;
  2453. //
  2454. // LPWSTR's are stored as offsets into the buffer - the NetDfsXXX calls
  2455. // fix them up.
  2456. //
  2457. iStr -= pktEntry->Id.Prefix.Length + sizeof(WCHAR);
  2458. RtlCopyMemory(&OutputBuffer[iStr],
  2459. pktEntry->Id.Prefix.Buffer,
  2460. pktEntry->Id.Prefix.Length);
  2461. //
  2462. // This could could be much more clever, as the DFS_INFO_X structs
  2463. // are similar, but I've gone for clarity over cleverness. (jharper)
  2464. //
  2465. switch (Level) {
  2466. case 4:
  2467. pDfsInfo4->EntryPath = (WCHAR*) ULongToPtr(iStr);
  2468. pDfsInfo4->Comment = NULL;
  2469. pDfsInfo4->State = DFS_VOLUME_STATE_OK;
  2470. pDfsInfo4->Timeout = pktEntry->TimeToLive;
  2471. pDfsInfo4->Guid = pktEntry->Id.Uid;
  2472. pDfsInfo4->NumberOfStorages = pktEntry->Info.ServiceCount;
  2473. pDfsStorageInfo = (PDFS_STORAGE_INFO)(pDfsInfo4 + 1);
  2474. pDfsInfo4->Storage = (PDFS_STORAGE_INFO)((PCHAR)pDfsStorageInfo - OutputBuffer);
  2475. break;
  2476. case 3:
  2477. pDfsInfo3->EntryPath = (WCHAR*) ULongToPtr(iStr);
  2478. pDfsInfo3->Comment = NULL;
  2479. pDfsInfo3->State = DFS_VOLUME_STATE_OK;
  2480. pDfsInfo3->NumberOfStorages = pktEntry->Info.ServiceCount;
  2481. pDfsStorageInfo = (PDFS_STORAGE_INFO)(pDfsInfo3 + 1);
  2482. pDfsInfo3->Storage = (PDFS_STORAGE_INFO)((PCHAR)pDfsStorageInfo - OutputBuffer);
  2483. break;
  2484. case 2:
  2485. pDfsInfo3->EntryPath = (WCHAR*) ULongToPtr(iStr);
  2486. pDfsInfo3->Comment = NULL;
  2487. pDfsInfo3->State = DFS_VOLUME_STATE_OK;
  2488. pDfsInfo3->NumberOfStorages = pktEntry->Info.ServiceCount;
  2489. break;
  2490. case 1:
  2491. pDfsInfo3->EntryPath = (WCHAR*) ULongToPtr(iStr);
  2492. break;
  2493. }
  2494. //
  2495. // For Level 3 & 4 we now walk the services and load State,
  2496. // ServerName and ShareName. With the complication that if the user
  2497. // specified ServerName and/or ShareName, we must match on those, too.
  2498. //
  2499. if (Level == 3 || Level == 4) {
  2500. NumStorageInfo = 0;
  2501. for (i = 0; i < pktEntry->Info.ServiceCount; i++) {
  2502. LPWSTR wp;
  2503. UNICODE_STRING uStr;
  2504. USHORT m, n;
  2505. pService = &pktEntry->Info.ServiceList[i];
  2506. DfsDbgTrace( 0, Dbg, "Examining %wZ\n", &pService->Address);
  2507. //
  2508. // We want to work with the \Server\Share part of the address only,
  2509. // so count up to 3 backslashes, then stop.
  2510. //
  2511. uStr = pService->Address;
  2512. for (m = n = 0; m < uStr.Length/sizeof(WCHAR) && n < 3; m++) {
  2513. if (uStr.Buffer[m] == UNICODE_PATH_SEP) {
  2514. n++;
  2515. }
  2516. }
  2517. uStr.Length = (n >= 3) ? (m-1) * sizeof(WCHAR) : m * sizeof(WCHAR);
  2518. //
  2519. // Tease apart the address (of form \Server\Share) into Server
  2520. // (Handles a dfs-link like \server\share\dir1\dir2)
  2521. //
  2522. RemoveLastComponent(&uStr, &Server);
  2523. //
  2524. // Remove leading & trailing '\'s
  2525. //
  2526. Server.Length -= 2* sizeof(WCHAR);
  2527. Server.MaximumLength = Server.Length;
  2528. Server.Buffer++;
  2529. //
  2530. // And figure out Share (which will be everything after the server)
  2531. //
  2532. Share.Buffer = Server.Buffer + (Server.Length / sizeof(WCHAR)) + 1;
  2533. Share.Length = pService->Address.Length - (Server.Length + 2 * sizeof(WCHAR));
  2534. Share.MaximumLength = Share.Length;
  2535. DfsDbgTrace( 0, Dbg, "DfsGetEntryStateSize: Server=%wZ\n", &Server);
  2536. DfsDbgTrace( 0, Dbg, " Share=%wZ\n", &Share);
  2537. //
  2538. // If ServerName or ShareName are specified, then they must match
  2539. //
  2540. if (
  2541. (ServerName->Length && RtlCompareUnicodeString(ServerName, &Server, TRUE))
  2542. ||
  2543. (ShareName->Length && RtlCompareUnicodeString(ShareName, &Share, TRUE))
  2544. ) {
  2545. continue;
  2546. }
  2547. //
  2548. // Online or Offline?
  2549. //
  2550. if (pService->Type & DFS_SERVICE_TYPE_OFFLINE) {
  2551. pDfsStorageInfo->State = DFS_STORAGE_STATE_OFFLINE;
  2552. } else {
  2553. pDfsStorageInfo->State = DFS_STORAGE_STATE_ONLINE;
  2554. }
  2555. //
  2556. // Active?
  2557. //
  2558. if (pService == pktEntry->ActiveService) {
  2559. pDfsStorageInfo->State |= DFS_STORAGE_STATE_ACTIVE;
  2560. }
  2561. //
  2562. // Sever name
  2563. //
  2564. iStr -= Server.Length + sizeof(WCHAR);
  2565. RtlCopyMemory(&OutputBuffer[iStr],
  2566. Server.Buffer,
  2567. Server.Length);
  2568. pDfsStorageInfo->ServerName = (WCHAR*) ULongToPtr(iStr);
  2569. //
  2570. // Share name
  2571. //
  2572. iStr -= Share.Length + sizeof(WCHAR);
  2573. RtlCopyMemory(&OutputBuffer[iStr],
  2574. Share.Buffer,
  2575. Share.Length);
  2576. pDfsStorageInfo->ShareName = (WCHAR*) ULongToPtr(iStr);
  2577. pDfsStorageInfo++;
  2578. NumStorageInfo++;
  2579. }
  2580. //
  2581. // Finally, adjust the # entries we loaded into the buffer
  2582. //
  2583. switch (Level) {
  2584. case 4:
  2585. pDfsInfo4->NumberOfStorages = NumStorageInfo;
  2586. break;
  2587. case 3:
  2588. pDfsInfo3->NumberOfStorages = NumStorageInfo;
  2589. break;
  2590. }
  2591. }
  2592. } except (EXCEPTION_EXECUTE_HANDLER) {
  2593. NtStatus = STATUS_SUCCESS; // Per Arg Validation Spec
  2594. }
  2595. DfsDbgTrace(-1, Dbg, "DfsGetEntryStateMarshall -> %08lx\n", ULongToPtr(NtStatus) );
  2596. return (NtStatus);
  2597. }
  2598. //+----------------------------------------------------------------------------
  2599. //
  2600. // Function: DfsFsctrlSetPktEntryState
  2601. //
  2602. // Synopsis: Given a Prefix in Dfs namespace it sets the Timeout or the State
  2603. // of an alternate. (DFS_INFO_X calls).
  2604. //
  2605. // Arguments:
  2606. //
  2607. // Returns:
  2608. //
  2609. //-----------------------------------------------------------------------------
  2610. NTSTATUS
  2611. DfsFsctrlSetPktEntryState(
  2612. IN PIRP_CONTEXT IrpContext,
  2613. IN PIRP Irp,
  2614. IN PUCHAR InputBuffer,
  2615. IN ULONG InputBufferLength)
  2616. {
  2617. NTSTATUS NtStatus = STATUS_SUCCESS;
  2618. PDFS_SET_PKT_ENTRY_STATE_ARG arg;
  2619. PDFS_SERVICE pService;
  2620. UNICODE_STRING DfsEntryPath;
  2621. UNICODE_STRING ServerName;
  2622. UNICODE_STRING ShareName;
  2623. UNICODE_STRING remPath;
  2624. PDFS_PKT pkt;
  2625. PDFS_PKT_ENTRY pktEntry;
  2626. BOOLEAN pktLocked = FALSE;
  2627. ULONG cbOutBuffer;
  2628. ULONG Level;
  2629. ULONG State;
  2630. ULONG Timeout;
  2631. PCHAR cp;
  2632. DfsDbgTrace(+1, Dbg, "DfsFsctrlSetPktEntryState\n", 0);
  2633. STD_FSCTRL_PROLOGUE(DfsFsctrlSetPktEntryState, TRUE, FALSE, FALSE);
  2634. if (InputBufferLength < sizeof(DFS_SET_PKT_ENTRY_STATE_ARG)) {
  2635. DfsDbgTrace( 0, Dbg, "Input buffer too small\n", 0);
  2636. NtStatus = STATUS_INVALID_PARAMETER;
  2637. Irp->IoStatus.Information = 0;
  2638. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  2639. DfsDbgTrace(-1, Dbg, "DfsFsctrlSetPktEntryState exit 0x%x\n", ULongToPtr(NtStatus) );
  2640. return( NtStatus );
  2641. }
  2642. //
  2643. // Check args that don't need to be unmarshalled.
  2644. //
  2645. if (NT_SUCCESS(NtStatus)) {
  2646. arg = (PDFS_SET_PKT_ENTRY_STATE_ARG) InputBuffer;
  2647. Level = arg->Level;
  2648. //
  2649. // Check for valid Level
  2650. //
  2651. // Level 101 requires that both be present
  2652. // Level 102 ignores ServerName and ShareName
  2653. //
  2654. switch (Level) {
  2655. case 101:
  2656. State = arg->State;
  2657. if (State != DFS_STORAGE_STATE_ACTIVE ||
  2658. arg->ServerNameLen == 0 ||
  2659. arg->ShareNameLen == 0) {
  2660. NtStatus = STATUS_INVALID_PARAMETER;
  2661. }
  2662. break;
  2663. case 102:
  2664. Timeout = arg->Timeout;
  2665. break;
  2666. default:
  2667. NtStatus = STATUS_INVALID_PARAMETER;
  2668. }
  2669. }
  2670. //
  2671. // Unmarshall the strings
  2672. //
  2673. if (NT_SUCCESS(NtStatus)) {
  2674. try {
  2675. DfsEntryPath.Length = DfsEntryPath.MaximumLength = arg->DfsEntryPathLen;
  2676. DfsEntryPath.Buffer = arg->Buffer;
  2677. DfsDbgTrace( 0, Dbg, "\tDfsName=%wZ\n", &DfsEntryPath);
  2678. RtlInitUnicodeString(&ServerName, NULL);
  2679. RtlInitUnicodeString(&ShareName, NULL);
  2680. if (arg->ServerNameLen) {
  2681. cp = (PCHAR)arg->Buffer + arg->DfsEntryPathLen;
  2682. ServerName.Buffer = (WCHAR *)cp;
  2683. ServerName.Length = ServerName.MaximumLength = arg->ServerNameLen;
  2684. DfsDbgTrace( 0, Dbg, "\tServerName=%wZ\n", &ServerName);
  2685. }
  2686. if (arg->ShareNameLen) {
  2687. cp = (PCHAR)arg->Buffer + arg->DfsEntryPathLen + arg->ServerNameLen;
  2688. ShareName.Buffer = (WCHAR *)cp;
  2689. ShareName.Length = ShareName.MaximumLength = arg->ShareNameLen;
  2690. DfsDbgTrace( 0, Dbg, "\tShareName=%wZ\n", &ShareName);
  2691. }
  2692. DfsDbgTrace( 0, Dbg, "\tLevel=%d\n", ULongToPtr(arg->Level) );
  2693. } except (EXCEPTION_EXECUTE_HANDLER) {
  2694. NtStatus = GetExceptionCode();
  2695. }
  2696. }
  2697. //
  2698. // Do a prefix lookup. If we find an entry, it's a Dfs path
  2699. //
  2700. if (NT_SUCCESS(NtStatus)) {
  2701. pkt = _GetPkt();
  2702. PktAcquireExclusive( TRUE, &pktLocked );
  2703. pktEntry = PktLookupEntryByPrefix( pkt, &DfsEntryPath, &remPath );
  2704. if (pktEntry != NULL) {
  2705. DfsDbgTrace( 0, Dbg, "\tFound pkt entry %08lx\n", pktEntry);
  2706. } else {
  2707. NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  2708. }
  2709. }
  2710. if (NT_SUCCESS(NtStatus)) {
  2711. //
  2712. // Args are ok - do the work
  2713. //
  2714. switch (Level) {
  2715. case 101:
  2716. NtStatus = DfsSetPktEntryActive(
  2717. &ServerName,
  2718. &ShareName,
  2719. pktEntry,
  2720. State);
  2721. break;
  2722. case 102:
  2723. NtStatus = DfsSetPktEntryTimeout(pktEntry,
  2724. Timeout);
  2725. break;
  2726. }
  2727. Irp->IoStatus.Information = 0;
  2728. }
  2729. //
  2730. // Release any locks taken, and free any memory allocated.
  2731. //
  2732. if (pktLocked) {
  2733. PktRelease();
  2734. }
  2735. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  2736. DfsDbgTrace(-1, Dbg, "DfsFsctrlSetPktEntryState exit 0x%x\n", ULongToPtr(NtStatus) );
  2737. return( NtStatus );
  2738. }
  2739. //+-------------------------------------------------------------------------
  2740. //
  2741. // Function: RemoveFirstComponent, public
  2742. //
  2743. // Synopsis: Removes the first component of the string passed.
  2744. //
  2745. // Arguments: [Prefix] -- The prefix whose first component is to be returned.
  2746. // [newPrefix] -- The first component.
  2747. //
  2748. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  2749. //
  2750. // Notes: On return, the newPrefix points to the same memory buffer
  2751. // as Prefix.
  2752. //
  2753. //--------------------------------------------------------------------------
  2754. void
  2755. RemoveFirstComponent(
  2756. PUNICODE_STRING Prefix,
  2757. PUNICODE_STRING newPrefix
  2758. )
  2759. {
  2760. PWCHAR pwch;
  2761. USHORT i=sizeof(WCHAR);
  2762. *newPrefix = *Prefix;
  2763. pwch = newPrefix->Buffer;
  2764. pwch ++; //skip the first slash
  2765. while ((*pwch != UNICODE_PATH_SEP) && ((pwch - newPrefix->Buffer) != Prefix->Length)) {
  2766. i += sizeof(WCHAR);
  2767. pwch++;
  2768. }
  2769. newPrefix->Length = i + sizeof(WCHAR);
  2770. }
  2771. //+----------------------------------------------------------------------------
  2772. //
  2773. // Function: DfsSetPktEntryActive
  2774. //
  2775. // Synopsis: Helper for DfsFsctrlSetPktEntryState
  2776. //
  2777. // Arguments:
  2778. //
  2779. // Returns:
  2780. //
  2781. //-----------------------------------------------------------------------------
  2782. NTSTATUS
  2783. DfsSetPktEntryActive(
  2784. PUNICODE_STRING ServerName,
  2785. PUNICODE_STRING ShareName,
  2786. PDFS_PKT_ENTRY pktEntry,
  2787. DWORD State)
  2788. {
  2789. UNICODE_STRING Server;
  2790. UNICODE_STRING Share;
  2791. PDFS_SERVICE pService;
  2792. NTSTATUS NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  2793. ULONG i;
  2794. DfsDbgTrace(+1, Dbg, "DfsSetPktEntryActive\n", 0);
  2795. for (i = 0; i < pktEntry->Info.ServiceCount && NtStatus != STATUS_SUCCESS; i++) {
  2796. LPWSTR wp;
  2797. pService = &pktEntry->Info.ServiceList[i];
  2798. DfsDbgTrace( 0, Dbg, "Examining %wZ\n", &pService->Address);
  2799. //
  2800. // Tease apart the address (of form \Server\Share) into Server and Share
  2801. //
  2802. RemoveFirstComponent(&pService->Address, &Server);
  2803. //
  2804. // Remove leading & trailing '\'s
  2805. //
  2806. Server.Length -= 2* sizeof(WCHAR);
  2807. Server.MaximumLength = Server.Length;
  2808. Server.Buffer++;
  2809. //
  2810. // And figure out Share
  2811. //
  2812. Share.Buffer = Server.Buffer + (Server.Length / sizeof(WCHAR)) + 1;
  2813. Share.Length = pService->Address.Length - (Server.Length + 2 * sizeof(WCHAR));
  2814. Share.MaximumLength = Share.Length;
  2815. //
  2816. // If ServerName or ShareName don't match, then move on to the next service
  2817. //
  2818. if (
  2819. RtlCompareUnicodeString(ServerName, &Server, TRUE)
  2820. ||
  2821. RtlCompareUnicodeString(ShareName, &Share, TRUE)
  2822. ) {
  2823. continue;
  2824. }
  2825. DfsDbgTrace( 0, Dbg, "DfsSetPktEntryActive: Server=%wZ\n", &Server);
  2826. DfsDbgTrace( 0, Dbg, " Share=%wZ\n", &Share);
  2827. //
  2828. // Make this the active share
  2829. //
  2830. pktEntry->ActiveService = pService;
  2831. NtStatus = STATUS_SUCCESS;
  2832. }
  2833. DfsDbgTrace(-1, Dbg, "DfsSetPktEntryActive -> %08lx\n", ULongToPtr(NtStatus) );
  2834. return NtStatus;
  2835. }
  2836. //+----------------------------------------------------------------------------
  2837. //
  2838. // Function: DfsSetPktEntryTimeout
  2839. //
  2840. // Synopsis: Helper for DfsFsctrlSetPktEntryState
  2841. //
  2842. // Arguments:
  2843. //
  2844. // Returns:
  2845. //
  2846. //-----------------------------------------------------------------------------
  2847. NTSTATUS
  2848. DfsSetPktEntryTimeout(
  2849. PDFS_PKT_ENTRY pktEntry,
  2850. ULONG Timeout)
  2851. {
  2852. DfsDbgTrace(+1, Dbg, "DfsSetPktEntryTimeout\n", 0);
  2853. pktEntry->ExpireTime = pktEntry->TimeToLive = Timeout;
  2854. DfsDbgTrace(-1, Dbg, "DfsSetPktEntryTimeout -> %08lx\n", STATUS_SUCCESS );
  2855. return STATUS_SUCCESS;
  2856. }
  2857. //+----------------------------------------------------------------------------
  2858. //
  2859. // Function: DfsFsctrlGetPkt
  2860. //
  2861. // Synopsis: Returns the current (cached Pkt)
  2862. //
  2863. // Arguments:
  2864. //
  2865. // Returns:
  2866. //
  2867. //-----------------------------------------------------------------------------
  2868. NTSTATUS
  2869. DfsFsctrlGetPkt(
  2870. IN PIRP_CONTEXT IrpContext,
  2871. IN PIRP Irp,
  2872. IN PUCHAR OutputBuffer,
  2873. IN ULONG OutputBufferLength)
  2874. {
  2875. NTSTATUS NtStatus = STATUS_SUCCESS;
  2876. PDFS_PKT pkt;
  2877. BOOLEAN pktLocked = FALSE;
  2878. ULONG cbOutBuffer;
  2879. DfsDbgTrace(+1, Dbg, "DfsFsctrlGetPktEntryState\n", 0);
  2880. STD_FSCTRL_PROLOGUE(DfsFsctrlGetPkt, FALSE, TRUE, FALSE);
  2881. pkt = _GetPkt();
  2882. PktAcquireShared( TRUE, &pktLocked );
  2883. //
  2884. // Calculate the needed output buffer size
  2885. //
  2886. NtStatus = DfsGetPktSize(&cbOutBuffer);
  2887. //
  2888. // Let user know if it's too small
  2889. //
  2890. if (OutputBufferLength < cbOutBuffer) {
  2891. RETURN_BUFFER_SIZE(cbOutBuffer, NtStatus);
  2892. }
  2893. if (NtStatus == STATUS_SUCCESS) {
  2894. //
  2895. // Args are ok, and it fits - marshall the data
  2896. //
  2897. NtStatus = DfsGetPktMarshall(OutputBuffer, cbOutBuffer);
  2898. Irp->IoStatus.Information = cbOutBuffer;
  2899. }
  2900. //
  2901. // Release any locks taken, and free any memory allocated.
  2902. //
  2903. if (pktLocked) {
  2904. PktRelease();
  2905. }
  2906. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  2907. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetPkt -> %08lx\n", ULongToPtr(NtStatus) );
  2908. return( NtStatus );
  2909. }
  2910. //+----------------------------------------------------------------------------
  2911. //
  2912. // Function: DfsGetPktSize, private
  2913. //
  2914. // Synopsis: Calculates the size needed to return the Pkt. Helper for
  2915. // DfsFsctrlGetPkt().
  2916. //
  2917. //-----------------------------------------------------------------------------
  2918. NTSTATUS
  2919. DfsGetPktSize(
  2920. PULONG pSize)
  2921. {
  2922. ULONG EntryCount = 0;
  2923. ULONG i;
  2924. ULONG Size = 0;
  2925. PDFS_PKT_ENTRY pPktEntry;
  2926. PDFS_PKT pkt = _GetPkt();
  2927. //
  2928. // Walk the linked list of Pkt entries
  2929. //
  2930. for ( pPktEntry = PktFirstEntry(pkt);
  2931. pPktEntry != NULL;
  2932. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  2933. //
  2934. // Space for the Prefix and ShortPrefix, including a UNICODE_NULL
  2935. //
  2936. Size += pPktEntry->Id.Prefix.Length + sizeof(WCHAR);
  2937. Size += pPktEntry->Id.ShortPrefix.Length + sizeof(WCHAR);
  2938. //
  2939. // Space for an array of pointers to DFS_PKT_ADDRESS_OBJECTS
  2940. //
  2941. Size += sizeof(PDFS_PKT_ADDRESS_OBJECT) * pPktEntry->Info.ServiceCount;
  2942. //
  2943. // Space for the ServerShare address, plus a UNICODE_NULL, plus the state
  2944. //
  2945. for (i = 0; i < pPktEntry->Info.ServiceCount; i++) {
  2946. Size += sizeof(USHORT) + pPktEntry->Info.ServiceList[i].Address.Length + sizeof(WCHAR);
  2947. }
  2948. EntryCount++;
  2949. }
  2950. //
  2951. // Space for the DFS_PKT_ARG, which will have EntryCount objects on the end
  2952. //
  2953. Size += FIELD_OFFSET(DFS_GET_PKT_ARG, EntryObject[EntryCount]);
  2954. //
  2955. // Make sure the size is a multiple of the size of a PDFS_PKT_ADDRESS_OBJECT, as that is what
  2956. // will be at the end of the buffer
  2957. //
  2958. while ((Size & (sizeof(PDFS_PKT_ADDRESS_OBJECT)-1)) != 0) {
  2959. Size++;
  2960. }
  2961. *pSize = Size;
  2962. return STATUS_SUCCESS;
  2963. }
  2964. //+----------------------------------------------------------------------------
  2965. //
  2966. // Function: DfsGetPktMarshall, private
  2967. //
  2968. // Synopsis: Marshalls the Pkt. Helper for DfsFsctrlGetPkt().
  2969. //
  2970. //-----------------------------------------------------------------------------
  2971. NTSTATUS
  2972. DfsGetPktMarshall(
  2973. PBYTE Buffer,
  2974. ULONG Size)
  2975. {
  2976. ULONG EntryCount = 0;
  2977. ULONG i;
  2978. ULONG j;
  2979. ULONG Type;
  2980. PCHAR pCh;
  2981. PDFS_PKT_ENTRY pPktEntry;
  2982. PDFS_GET_PKT_ARG pPktArg;
  2983. PDFS_PKT pkt = _GetPkt();
  2984. //
  2985. // This will be a two-pass operation, the first pass will calculate how
  2986. // much room for the LPWSTR arrays at the end of the buffer, then the
  2987. // second pass will put the strings into place, too.
  2988. //
  2989. RtlZeroMemory(Buffer,Size);
  2990. //
  2991. // Point to the end of the buffer
  2992. //
  2993. pCh = (PCHAR)(Buffer + Size);
  2994. pPktArg = (PDFS_GET_PKT_ARG)Buffer;
  2995. for ( pPktEntry = PktFirstEntry(pkt);
  2996. pPktEntry != NULL;
  2997. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  2998. //
  2999. // Space for an array of pointers to DFS_PKT_ADDRESS_OBJECTS
  3000. //
  3001. pCh -= sizeof(PDFS_PKT_ADDRESS_OBJECT) * pPktEntry->Info.ServiceCount;
  3002. pPktArg->EntryObject[EntryCount].Address = (PDFS_PKT_ADDRESS_OBJECT *)pCh;
  3003. EntryCount++;
  3004. }
  3005. //
  3006. // Now marshall
  3007. //
  3008. EntryCount = 0;
  3009. for ( pPktEntry = PktFirstEntry(pkt);
  3010. pPktEntry != NULL;
  3011. pPktEntry = PktNextEntry(pkt, pPktEntry)) {
  3012. pCh -= pPktEntry->Id.Prefix.Length + sizeof(WCHAR);
  3013. pPktArg->EntryObject[EntryCount].Prefix = (LPWSTR)pCh;
  3014. RtlCopyMemory(
  3015. pPktArg->EntryObject[EntryCount].Prefix,
  3016. pPktEntry->Id.Prefix.Buffer,
  3017. pPktEntry->Id.Prefix.Length);
  3018. pCh -= pPktEntry->Id.ShortPrefix.Length + sizeof(WCHAR);
  3019. pPktArg->EntryObject[EntryCount].ShortPrefix = (LPWSTR)pCh;
  3020. RtlCopyMemory(
  3021. pPktArg->EntryObject[EntryCount].ShortPrefix,
  3022. pPktEntry->Id.ShortPrefix.Buffer,
  3023. pPktEntry->Id.ShortPrefix.Length);
  3024. pPktArg->EntryObject[EntryCount].Type = pPktEntry->Type;
  3025. pPktArg->EntryObject[EntryCount].USN = pPktEntry->USN;
  3026. pPktArg->EntryObject[EntryCount].ExpireTime = pPktEntry->ExpireTime;
  3027. pPktArg->EntryObject[EntryCount].UseCount = pPktEntry->UseCount;
  3028. pPktArg->EntryObject[EntryCount].Uid = pPktEntry->Id.Uid;
  3029. pPktArg->EntryObject[EntryCount].ServiceCount = pPktEntry->Info.ServiceCount;
  3030. for (i = 0; i < pPktEntry->Info.ServiceCount; i++) {
  3031. Type = pPktEntry->Info.ServiceList[i].Type;
  3032. pCh -= sizeof(USHORT) + pPktEntry->Info.ServiceList[i].Address.Length + sizeof(WCHAR);
  3033. pPktArg->EntryObject[EntryCount].Address[i] = (PDFS_PKT_ADDRESS_OBJECT)pCh;
  3034. pPktArg->EntryObject[EntryCount].Address[i]->State = (USHORT)Type;
  3035. if (pPktEntry->ActiveService == &pPktEntry->Info.ServiceList[i]) {
  3036. pPktArg->EntryObject[EntryCount].Address[i]->State |= DFS_SERVICE_TYPE_ACTIVE;
  3037. }
  3038. RtlCopyMemory(
  3039. &pPktArg->EntryObject[EntryCount].Address[i]->ServerShare[0],
  3040. pPktEntry->Info.ServiceList[i].Address.Buffer,
  3041. pPktEntry->Info.ServiceList[i].Address.Length);
  3042. }
  3043. EntryCount++;
  3044. }
  3045. pPktArg->EntryCount = EntryCount;
  3046. //
  3047. // Convert all the pointers to relative offsets
  3048. //
  3049. for (i = 0; i < pPktArg->EntryCount; i++) {
  3050. for (j = 0; j < pPktArg->EntryObject[i].ServiceCount; j++) {
  3051. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Address[j], Buffer);
  3052. }
  3053. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Prefix, Buffer);
  3054. POINTER_TO_OFFSET(pPktArg->EntryObject[i].ShortPrefix, Buffer);
  3055. POINTER_TO_OFFSET(pPktArg->EntryObject[i].Address, Buffer);
  3056. }
  3057. return STATUS_SUCCESS;
  3058. }
  3059. //+----------------------------------------------------------------------------
  3060. //
  3061. // Function: DfsFsctrlGetSpcTable
  3062. //
  3063. // Synopsis: Given a NULL string, it returns a list of all the domains
  3064. // Given a non-NULL string, it returns a list of DC's in that domain
  3065. // (if the name is a domain name). Similar to a special referral request.
  3066. //
  3067. // Arguments:
  3068. //
  3069. // Returns:
  3070. //
  3071. //-----------------------------------------------------------------------------
  3072. NTSTATUS
  3073. DfsFsctrlGetSpcTable(
  3074. IN PIRP_CONTEXT IrpContext,
  3075. IN PIRP Irp,
  3076. IN PUCHAR InputBuffer,
  3077. IN ULONG InputBufferLength,
  3078. IN PUCHAR OutputBuffer,
  3079. IN ULONG OutputBufferLength)
  3080. {
  3081. NTSTATUS NtStatus = STATUS_SUCCESS;
  3082. LPWSTR SpcName;
  3083. ULONG i;
  3084. DfsDbgTrace(+1, Dbg, "DfsFsctrlGetSpcTable\n", 0);
  3085. STD_FSCTRL_PROLOGUE(DfsFsctrlGetSpcTable, TRUE, TRUE, FALSE);
  3086. SpcName = (WCHAR *)InputBuffer;
  3087. //
  3088. // Verify there's a null someplace in the buffer
  3089. //
  3090. for (i = 0; i < InputBufferLength/sizeof(WCHAR) && SpcName[i]; i++)
  3091. NOTHING;
  3092. if (i >= InputBufferLength/sizeof(WCHAR)) {
  3093. NtStatus = STATUS_INVALID_PARAMETER;
  3094. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3095. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetSpcTable -> %08lx\n", ULongToPtr(NtStatus) );
  3096. return NtStatus;
  3097. }
  3098. DfsDbgTrace(0, Dbg, "SpcName=[%ws]\n", SpcName);
  3099. if (wcslen(SpcName) == 0) {
  3100. //
  3101. // return all the domain names
  3102. //
  3103. NtStatus = DfsGetSpcTableNames(
  3104. Irp,
  3105. OutputBuffer,
  3106. OutputBufferLength);
  3107. } else if (wcslen(SpcName) == 1 && *SpcName == L'*') {
  3108. //
  3109. // Return DC Info
  3110. //
  3111. NtStatus = DfsGetSpcDcInfo(
  3112. Irp,
  3113. OutputBuffer,
  3114. OutputBufferLength);
  3115. } else {
  3116. //
  3117. // Expand the one name
  3118. //
  3119. NtStatus = DfsExpSpcTableName(
  3120. SpcName,
  3121. Irp,
  3122. OutputBuffer,
  3123. OutputBufferLength);
  3124. }
  3125. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3126. DfsDbgTrace(-1, Dbg, "DfsFsctrlGetSpcTable -> %08lx\n", ULongToPtr(NtStatus) );
  3127. return( NtStatus );
  3128. }
  3129. //+----------------------------------------------------------------------------
  3130. //
  3131. // Function: DfsGetspcTableNames, private
  3132. //
  3133. // Synopsis: Marshalls the spc table (Names). Helper for DfsFsctrlGetSpcTable().
  3134. //
  3135. //-----------------------------------------------------------------------------
  3136. NTSTATUS
  3137. DfsGetSpcTableNames(
  3138. PIRP Irp,
  3139. PUCHAR OutputBuffer,
  3140. ULONG OutputBufferLength)
  3141. {
  3142. PDFS_SPECIAL_ENTRY pSpecialEntry;
  3143. PDFS_SPECIAL_TABLE pSpecialTable;
  3144. PDFS_PKT Pkt;
  3145. WCHAR *wCp;
  3146. ULONG Size;
  3147. ULONG i;
  3148. BOOLEAN pktLocked;
  3149. NTSTATUS Status;
  3150. RtlZeroMemory(OutputBuffer, OutputBufferLength);
  3151. Pkt = _GetPkt();
  3152. pSpecialTable = &Pkt->SpecialTable;
  3153. PktAcquireShared(TRUE, &pktLocked);
  3154. Size = sizeof(UNICODE_NULL);
  3155. pSpecialEntry = CONTAINING_RECORD(
  3156. pSpecialTable->SpecialEntryList.Flink,
  3157. DFS_SPECIAL_ENTRY,
  3158. Link);
  3159. for (i = 0; i < pSpecialTable->SpecialEntryCount; i++) {
  3160. Size += pSpecialEntry->SpecialName.Length +
  3161. sizeof(UNICODE_NULL) +
  3162. sizeof(WCHAR);
  3163. pSpecialEntry = CONTAINING_RECORD(
  3164. pSpecialEntry->Link.Flink,
  3165. DFS_SPECIAL_ENTRY,
  3166. Link);
  3167. }
  3168. if (Size > OutputBufferLength) {
  3169. RETURN_BUFFER_SIZE(Size, Status)
  3170. PktRelease();
  3171. return Status;
  3172. }
  3173. wCp = (WCHAR *)OutputBuffer;
  3174. pSpecialEntry = CONTAINING_RECORD(
  3175. pSpecialTable->SpecialEntryList.Flink,
  3176. DFS_SPECIAL_ENTRY,
  3177. Link);
  3178. for (i = 0; i < pSpecialTable->SpecialEntryCount; i++) {
  3179. *wCp++ = pSpecialEntry->NeedsExpansion == TRUE ? L'-' : '+';
  3180. RtlCopyMemory(
  3181. wCp,
  3182. pSpecialEntry->SpecialName.Buffer,
  3183. pSpecialEntry->SpecialName.Length);
  3184. wCp += pSpecialEntry->SpecialName.Length/sizeof(WCHAR);
  3185. *wCp++ = UNICODE_NULL;
  3186. pSpecialEntry = CONTAINING_RECORD(
  3187. pSpecialEntry->Link.Flink,
  3188. DFS_SPECIAL_ENTRY,
  3189. Link);
  3190. }
  3191. *wCp++ = UNICODE_NULL;
  3192. PktRelease();
  3193. Irp->IoStatus.Information = Size;
  3194. return STATUS_SUCCESS;
  3195. }
  3196. //+----------------------------------------------------------------------------
  3197. //
  3198. // Function: DfsGetSpcDcInfo, private
  3199. //
  3200. // Synopsis: Marshalls DC Info w.r.t. the special name table
  3201. //
  3202. //-----------------------------------------------------------------------------
  3203. NTSTATUS
  3204. DfsGetSpcDcInfo(
  3205. PIRP Irp,
  3206. PUCHAR OutputBuffer,
  3207. ULONG OutputBufferLength)
  3208. {
  3209. NTSTATUS Status = STATUS_SUCCESS;
  3210. BOOLEAN pktLocked;
  3211. PDFS_PKT Pkt;
  3212. WCHAR *wCp;
  3213. ULONG Size;
  3214. Pkt = _GetPkt();
  3215. PktAcquireShared(TRUE, &pktLocked);
  3216. RtlZeroMemory(OutputBuffer, OutputBufferLength);
  3217. Size = sizeof(UNICODE_NULL);
  3218. Size += Pkt->DCName.Length +
  3219. sizeof(UNICODE_NULL) +
  3220. sizeof(WCHAR);
  3221. Size += Pkt->DomainNameFlat.Length +
  3222. sizeof(UNICODE_NULL) +
  3223. sizeof(WCHAR);
  3224. Size += Pkt->DomainNameDns.Length +
  3225. sizeof(UNICODE_NULL) +
  3226. sizeof(WCHAR);
  3227. if (Size > OutputBufferLength) {
  3228. RETURN_BUFFER_SIZE(Size, Status)
  3229. PktRelease();
  3230. return Status;
  3231. }
  3232. wCp = (WCHAR *)OutputBuffer;
  3233. *wCp++ = L'*';
  3234. RtlCopyMemory(
  3235. wCp,
  3236. Pkt->DCName.Buffer,
  3237. Pkt->DCName.Length);
  3238. wCp += Pkt->DCName.Length/sizeof(WCHAR);
  3239. *wCp++ = UNICODE_NULL;
  3240. *wCp++ = L'*';
  3241. RtlCopyMemory(
  3242. wCp,
  3243. Pkt->DomainNameFlat.Buffer,
  3244. Pkt->DomainNameFlat.Length);
  3245. wCp += Pkt->DomainNameFlat.Length/sizeof(WCHAR);
  3246. *wCp++ = UNICODE_NULL;
  3247. *wCp++ = L'*';
  3248. RtlCopyMemory(
  3249. wCp,
  3250. Pkt->DomainNameDns.Buffer,
  3251. Pkt->DomainNameDns.Length);
  3252. wCp += Pkt->DomainNameDns.Length/sizeof(WCHAR);
  3253. *wCp++ = UNICODE_NULL;
  3254. *wCp++ = UNICODE_NULL;
  3255. PktRelease();
  3256. Irp->IoStatus.Information = Size;
  3257. return STATUS_SUCCESS;
  3258. }
  3259. //+----------------------------------------------------------------------------
  3260. //
  3261. // Function: DfsExpSpcTableName, private
  3262. //
  3263. // Synopsis: Marshalls the spc table (1 expansion). Helper for DfsFsctrlGetSpcTable().
  3264. //
  3265. //-----------------------------------------------------------------------------
  3266. NTSTATUS
  3267. DfsExpSpcTableName(
  3268. LPWSTR SpcName,
  3269. PIRP Irp,
  3270. PUCHAR OutputBuffer,
  3271. ULONG OutputBufferLength)
  3272. {
  3273. PDFS_SPECIAL_ENTRY pSpcEntry = NULL;
  3274. UNICODE_STRING Name;
  3275. NTSTATUS Status = STATUS_SUCCESS;
  3276. WCHAR *wCp;
  3277. ULONG Size;
  3278. ULONG i;
  3279. RtlInitUnicodeString(&Name, SpcName);
  3280. Status = PktExpandSpecialName(&Name, &pSpcEntry);
  3281. if (!NT_SUCCESS(Status)) {
  3282. return Status;
  3283. }
  3284. RtlZeroMemory(OutputBuffer, OutputBufferLength);
  3285. Size = sizeof(UNICODE_NULL);
  3286. for (i = 0; i < pSpcEntry->ExpandedCount; i++) {
  3287. Size += pSpcEntry->ExpandedNames[i].ExpandedName.Length +
  3288. sizeof(UNICODE_NULL) +
  3289. sizeof(WCHAR);
  3290. }
  3291. if (Size > OutputBufferLength) {
  3292. RETURN_BUFFER_SIZE(Size, Status)
  3293. InterlockedDecrement(&pSpcEntry->UseCount);
  3294. return Status;
  3295. }
  3296. wCp = (WCHAR *)OutputBuffer;
  3297. for (i = 0; i < pSpcEntry->ExpandedCount; i++) {
  3298. *wCp++ = i == pSpcEntry->Active ? L'+' : L'-';
  3299. RtlCopyMemory(
  3300. wCp,
  3301. pSpcEntry->ExpandedNames[i].ExpandedName.Buffer,
  3302. pSpcEntry->ExpandedNames[i].ExpandedName.Length);
  3303. wCp += pSpcEntry->ExpandedNames[i].ExpandedName.Length/sizeof(WCHAR);
  3304. *wCp++ = UNICODE_NULL;
  3305. }
  3306. *wCp++ = UNICODE_NULL;
  3307. InterlockedDecrement(&pSpcEntry->UseCount);
  3308. Irp->IoStatus.Information = Size;
  3309. return STATUS_SUCCESS;
  3310. }
  3311. //+----------------------------------------------------------------------------
  3312. //
  3313. // Function: DfsFsctrlSpcSetDc
  3314. //
  3315. // Synopsis: Given a special name and a dc name, it makes the DC in that special
  3316. // list the 'active' DC.
  3317. //
  3318. // Arguments:
  3319. //
  3320. // Returns:
  3321. //
  3322. //-----------------------------------------------------------------------------
  3323. NTSTATUS
  3324. DfsFsctrlSpcSetDc(
  3325. IN PIRP_CONTEXT IrpContext,
  3326. IN PIRP Irp,
  3327. IN PUCHAR InputBuffer,
  3328. IN ULONG InputBufferLength)
  3329. {
  3330. NTSTATUS NtStatus = STATUS_SUCCESS;
  3331. PDFS_SPECIAL_SET_DC_INPUT_ARG arg = (PDFS_SPECIAL_SET_DC_INPUT_ARG) InputBuffer;
  3332. DfsDbgTrace(+1, Dbg, "DfsFsctrlSpcSetDc\n", 0);
  3333. STD_FSCTRL_PROLOGUE(DfsFsctrlSpcSetDc, TRUE, FALSE, FALSE);
  3334. //
  3335. // Check the input args
  3336. //
  3337. if (InputBufferLength < sizeof(DFS_SPECIAL_SET_DC_INPUT_ARG)) {
  3338. NtStatus = STATUS_INVALID_PARAMETER;
  3339. goto exit_with_status;
  3340. }
  3341. OFFSET_TO_POINTER(arg->SpecialName.Buffer, arg);
  3342. if (!UNICODESTRING_IS_VALID(arg->SpecialName, InputBuffer, InputBufferLength)) {
  3343. NtStatus = STATUS_INVALID_PARAMETER;
  3344. goto exit_with_status;
  3345. }
  3346. OFFSET_TO_POINTER(arg->DcName.Buffer, arg);
  3347. if (!UNICODESTRING_IS_VALID(arg->DcName, InputBuffer, InputBufferLength)) {
  3348. NtStatus = STATUS_INVALID_PARAMETER;
  3349. goto exit_with_status;
  3350. }
  3351. NtStatus = PktpSetActiveSpcService(
  3352. &arg->SpecialName,
  3353. &arg->DcName,
  3354. TRUE);
  3355. exit_with_status:
  3356. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3357. DfsDbgTrace(-1, Dbg, "DfsFsctrlSpcSetDc -> %08lx\n", ULongToPtr(NtStatus) );
  3358. return( NtStatus );
  3359. }
  3360. #if DBG
  3361. //+-------------------------------------------------------------------------
  3362. //
  3363. // Function: DfsFsctrlReadMem, local
  3364. //
  3365. // Synopsis: DfsFsctrlReadMem is a debugging function which will return
  3366. // the contents of a chunk of kernel space memory
  3367. //
  3368. // Arguments: [IrpContext] -
  3369. // [Irp] -
  3370. // [Request] -- Pointer to a FILE_DFS_READ_MEM struct,
  3371. // giving the description of the data to be returned.
  3372. // [InputBufferLength] -- Size of InputBuffer
  3373. // [OutputBuffer] -- User's output buffer, in which the
  3374. // data structure will be returned.
  3375. // [OutputBufferLength] -- Size of OutputBuffer
  3376. //
  3377. // Returns: NTSTATUS - STATUS_SUCCESS if no error.
  3378. //
  3379. // Notes: Available in DBG builds only.
  3380. //
  3381. //--------------------------------------------------------------------------
  3382. NTSTATUS
  3383. DfsFsctrlReadMem (
  3384. IN PIRP_CONTEXT IrpContext,
  3385. IN PIRP Irp,
  3386. IN PFILE_DFS_READ_MEM Request,
  3387. IN ULONG InputBufferLength,
  3388. IN OUT PUCHAR OutputBuffer,
  3389. IN ULONG OutputBufferLength
  3390. ) {
  3391. NTSTATUS Status;
  3392. PUCHAR ReadBuffer;
  3393. ULONG ReadLength;
  3394. DfsDbgTrace(+1, Dbg, "DfsFsctrlReadMem...\n", 0);
  3395. if (InputBufferLength != sizeof (FILE_DFS_READ_MEM)) {
  3396. DfsDbgTrace(0, Dbg, "Input buffer is wrong size\n", 0);
  3397. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  3398. Status = STATUS_INVALID_PARAMETER;
  3399. DfsDbgTrace(-1, Dbg, "DfsFsctrlReadMem -> %08lx\n", ULongToPtr(Status) );
  3400. return Status;
  3401. }
  3402. ReadBuffer = (PUCHAR) Request->Address;
  3403. ReadLength = (ULONG) Request->Length;
  3404. //
  3405. // Special case ReadBuffer == 0 and ReadLength == 0 - means return the
  3406. // address of DfsData
  3407. //
  3408. if (ReadLength == 0 && ReadBuffer == 0) {
  3409. if (OutputBufferLength < sizeof(ULONG_PTR)) {
  3410. DfsDbgTrace(0, Dbg, "Output buffer is too small\n", 0);
  3411. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  3412. Status = STATUS_INVALID_PARAMETER;
  3413. DfsDbgTrace(-1, Dbg, "DfsFsctrlReadMem -> %08lx\n", ULongToPtr(Status) );
  3414. return Status;
  3415. } else {
  3416. *(PULONG_PTR) OutputBuffer = (ULONG_PTR) &DfsData;
  3417. Irp->IoStatus.Information = sizeof(ULONG);
  3418. Irp->IoStatus.Status = Status = STATUS_SUCCESS;
  3419. DfsCompleteRequest( IrpContext, Irp, Status );
  3420. return Status;
  3421. }
  3422. }
  3423. //
  3424. // Normal case, read data from the address specified in input buffer
  3425. //
  3426. if (ReadLength > OutputBufferLength) {
  3427. DfsDbgTrace(0, Dbg, "Output buffer is smaller than requested size\n", 0);
  3428. DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  3429. Status = STATUS_INVALID_PARAMETER;
  3430. DfsDbgTrace(-1, Dbg, "DfsFsctrlReadMem -> %08lx\n", ULongToPtr(Status) );
  3431. return Status;
  3432. }
  3433. try {
  3434. RtlMoveMemory( OutputBuffer, ReadBuffer, ReadLength );
  3435. Irp->IoStatus.Information = ReadLength;
  3436. Irp->IoStatus.Status = Status = STATUS_SUCCESS;
  3437. } except(EXCEPTION_EXECUTE_HANDLER) {
  3438. Status = STATUS_INVALID_USER_BUFFER;
  3439. }
  3440. DfsCompleteRequest(IrpContext, Irp, Status);
  3441. DfsDbgTrace(-1, Dbg, "DfsFsctrlReadMem -> %08lx\n", ULongToPtr(Status) );
  3442. return Status;
  3443. }
  3444. void
  3445. DfsDumpBuf(PCHAR cp, ULONG len)
  3446. {
  3447. ULONG i, j, c;
  3448. for (i = 0; i < len; i += 16) {
  3449. DbgPrint("%08x ", i);
  3450. for (j = 0; j < 16; j++) {
  3451. c = i+j < len ? cp[i+j] & 0xff : ' ';
  3452. DbgPrint("%02x ", c);
  3453. if (j == 7)
  3454. DbgPrint(" ");
  3455. }
  3456. DbgPrint(" ");
  3457. for (j = 0; j < 16; j++) {
  3458. c = i+j < len ? cp[i+j] & 0xff : ' ';
  3459. if (c < ' ' || c > '~')
  3460. c = '.';
  3461. DbgPrint("%c", c);
  3462. if (j == 7)
  3463. DbgPrint("|");
  3464. }
  3465. DbgPrint("\n");
  3466. }
  3467. }
  3468. #endif // DBG
  3469. //+----------------------------------------------------------------------------
  3470. //
  3471. // Function: DfsCaptureCredentials
  3472. //
  3473. // Synopsis: Captures the credentials to use... similar to DnrCaptureCred..
  3474. //
  3475. // Arguments: Irp and Filename.
  3476. //
  3477. // Returns: Credentials
  3478. //
  3479. //-----------------------------------------------------------------------------
  3480. PDFS_CREDENTIALS
  3481. DfsCaptureCredentials(
  3482. IN PIRP Irp,
  3483. IN PUNICODE_STRING FileName)
  3484. {
  3485. #ifdef TERMSRV
  3486. NTSTATUS Status;
  3487. ULONG SessionID;
  3488. #endif // TERMSRV
  3489. LUID LogonID;
  3490. PDFS_CREDENTIALS creds;
  3491. DfsDbgTrace(+1, Dbg, "DfsCaptureCredentials: Enter [%wZ] \n", FileName);
  3492. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  3493. DfsGetLogonId( &LogonID );
  3494. #ifdef TERMSRV
  3495. Status = IoGetRequestorSessionId( Irp, & SessionID );
  3496. if( NT_SUCCESS( Status ) ) {
  3497. creds = DfsLookupCredentials( FileName, SessionID, &LogonID );
  3498. }
  3499. else {
  3500. creds = NULL;
  3501. }
  3502. #else // TERMSRV
  3503. creds = DfsLookupCredentials( FileName, &LogonID );
  3504. #endif // TERMSRV
  3505. if (creds != NULL)
  3506. creds->RefCount++;
  3507. ExReleaseResourceLite( &DfsData.Resource );
  3508. DfsDbgTrace(-1, Dbg, "DfsCaptureCredentials: Exit. Creds %x\n", creds);
  3509. return creds;
  3510. }
  3511. //+----------------------------------------------------------------------------
  3512. //
  3513. // Function: DfsReleaseCredentials
  3514. //
  3515. // Synopsis: Releases the credentials supplied.
  3516. //
  3517. // Arguments: Credentials
  3518. //
  3519. // Returns: Nothing
  3520. //
  3521. //-----------------------------------------------------------------------------
  3522. VOID
  3523. DfsReleaseCredentials(
  3524. IN PDFS_CREDENTIALS Creds )
  3525. {
  3526. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  3527. if (Creds != NULL)
  3528. Creds->RefCount--;
  3529. ExReleaseResourceLite( &DfsData.Resource );
  3530. }
  3531. //+-------------------------------------------------------------------
  3532. //
  3533. // Function: DfsFsctrlGetConnectionPerfInfo, public
  3534. //
  3535. // Synopsis: This routine implements the functionality to get the
  3536. // performance information of an opened connection.
  3537. //
  3538. // Returns: [NTSTATUS] -- The completion status.
  3539. //
  3540. //--------------------------------------------------------------------
  3541. NTSTATUS
  3542. DfsFsctrlGetConnectionPerfInfo(
  3543. IN PIRP_CONTEXT IrpContext,
  3544. IN PIRP Irp,
  3545. IN PUCHAR InputBuffer,
  3546. IN ULONG InputBufferLength,
  3547. IN OUT PUCHAR OutputBuffer,
  3548. IN ULONG OutputBufferLength)
  3549. {
  3550. UNICODE_STRING Prefix;
  3551. NTSTATUS status = STATUS_SUCCESS;
  3552. UNICODE_STRING remPath, shareName;
  3553. PDFS_PKT pkt;
  3554. PDFS_PKT_ENTRY pktEntry;
  3555. PDFS_SERVICE service;
  3556. ULONG i, USN;
  3557. BOOLEAN pktLocked, fRetry;
  3558. PDFS_CREDENTIALS Creds;
  3559. ULONG InfoLen;
  3560. PUCHAR BufToUse;
  3561. UNICODE_STRING UsePrefix;
  3562. BufToUse = Irp->UserBuffer;
  3563. //
  3564. // try to use the User's buffer here. The underlying call sets up
  3565. // pointers to unicode strings within the output buffer, and passing
  3566. // a kernel buffer and copying it out to the user would not produce
  3567. // the intended results.
  3568. //
  3569. if (BufToUse!= NULL) {
  3570. try {
  3571. ProbeForWrite(BufToUse,OutputBufferLength,sizeof(UCHAR));
  3572. } except(EXCEPTION_EXECUTE_HANDLER) {
  3573. status = STATUS_INVALID_PARAMETER;
  3574. }
  3575. }
  3576. else {
  3577. status = STATUS_INVALID_PARAMETER;
  3578. }
  3579. if (NT_SUCCESS(status)) {
  3580. if ( (InputBufferLength > 0) &&
  3581. (InputBufferLength < MAXUSHORT) &&
  3582. ((InputBufferLength & 0x1) == 0) ) {
  3583. Prefix.MaximumLength = (USHORT)(InputBufferLength);
  3584. Prefix.Buffer = (PWCHAR) InputBuffer;
  3585. Prefix.Length = Prefix.MaximumLength;
  3586. }
  3587. else {
  3588. status = STATUS_INVALID_PARAMETER;
  3589. }
  3590. }
  3591. if (NT_SUCCESS(status)) {
  3592. Creds = DfsCaptureCredentials (Irp, &Prefix);
  3593. DfsDbgTrace(+1, Dbg, "GetConnPerfInfo entered %wZ\n", &Prefix);
  3594. DfsDbgTrace(0, Dbg, "GetConnPerfInfo creds=0x%x\n", Creds);
  3595. DfsGetServerShare( &UsePrefix, &Prefix);
  3596. pkt = _GetPkt();
  3597. PktAcquireShared( TRUE, &pktLocked );
  3598. do {
  3599. fRetry = FALSE;
  3600. pktEntry = PktLookupEntryByPrefix( pkt, &UsePrefix, &remPath );
  3601. if (pktEntry != NULL) {
  3602. InterlockedIncrement(&pktEntry->UseCount);
  3603. USN = pktEntry->USN;
  3604. status = STATUS_BAD_NETWORK_PATH;
  3605. for (i = 0; i < pktEntry->Info.ServiceCount; i++) {
  3606. service = &pktEntry->Info.ServiceList[i];
  3607. try {
  3608. status = DfsTreeConnectGetConnectionInfo(
  3609. service,
  3610. Creds,
  3611. BufToUse,
  3612. OutputBufferLength,
  3613. &InfoLen);
  3614. }
  3615. except(EXCEPTION_EXECUTE_HANDLER) {
  3616. status = STATUS_INVALID_PARAMETER;
  3617. }
  3618. //
  3619. // If tree connect succeeded, we are done.
  3620. //
  3621. if (NT_SUCCESS(status))
  3622. break;
  3623. //
  3624. // If tree connect failed with an "interesting error" like
  3625. // STATUS_ACCESS_DENIED, we are done.
  3626. //
  3627. if (!ReplIsRecoverableError(status))
  3628. break;
  3629. //
  3630. // Tree connect failed because of an error like host not
  3631. // reachable. In that case, we want to go on to the next
  3632. // server in the list. But before we do that, we have to see
  3633. // if the pkt changed on us while we were off doing the tree
  3634. // connect.
  3635. //
  3636. if (USN != pktEntry->USN) {
  3637. fRetry = TRUE;
  3638. break;
  3639. }
  3640. }
  3641. InterlockedDecrement(&pktEntry->UseCount);
  3642. } else {
  3643. status = STATUS_BAD_NETWORK_PATH;
  3644. }
  3645. } while ( fRetry );
  3646. PktRelease();
  3647. DfsReleaseCredentials(Creds);
  3648. //
  3649. // Dont put the InfoLen here... we already have the information in the
  3650. // the user buffer, and dont want a copyout of kernel to user.
  3651. //
  3652. }
  3653. Irp->IoStatus.Information = 0;
  3654. DfsCompleteRequest(IrpContext, Irp, status);
  3655. DfsDbgTrace(-1, Dbg, "GetConnPerfInfo Done, Status %x\n", ULongToPtr(status) );
  3656. return( status );
  3657. }
  3658. //+-------------------------------------------------------------------
  3659. //
  3660. // Function: DfsTreeConnecGetConnectionInfo, private
  3661. //
  3662. // Synopsis: This routine calls into the provider with FSCTL_LMR
  3663. // fsctl. Only lanman supports this fsctl, and if the provider
  3664. // is lanman, we get our information buffer filled in.
  3665. //
  3666. // Returns: [NTSTATUS] -- The completion status.
  3667. //
  3668. //--------------------------------------------------------------------
  3669. NTSTATUS
  3670. DfsTreeConnectGetConnectionInfo(
  3671. IN PDFS_SERVICE Service,
  3672. IN PDFS_CREDENTIALS Creds,
  3673. IN OUT PUCHAR OutputBuffer,
  3674. IN ULONG OutputBufferLength,
  3675. OUT PULONG InfoLen)
  3676. {
  3677. NTSTATUS status;
  3678. NTSTATUS ObjectRefStatus;
  3679. UNICODE_STRING shareName;
  3680. HANDLE treeHandle;
  3681. OBJECT_ATTRIBUTES objectAttributes;
  3682. IO_STATUS_BLOCK ioStatusBlock;
  3683. BOOLEAN pktLocked;
  3684. USHORT i, k;
  3685. *InfoLen = 0;
  3686. DfsDbgTrace(+1, Dbg, "DfsTreeConnectGetInfo entered creds %x\n", Creds);
  3687. ASSERT( PKT_LOCKED_FOR_SHARED_ACCESS() );
  3688. //
  3689. // Compute the share name...
  3690. //
  3691. if (Service->pProvider != NULL &&
  3692. Service->pProvider->DeviceName.Buffer != NULL &&
  3693. Service->pProvider->DeviceName.Length > 0) {
  3694. //
  3695. // We have a provider already - use it
  3696. //
  3697. shareName.MaximumLength =
  3698. Service->pProvider->DeviceName.Length +
  3699. Service->Address.Length;
  3700. } else {
  3701. //
  3702. // We don't have a provider yet - give it to the mup to find one
  3703. //
  3704. shareName.MaximumLength =
  3705. sizeof(DD_NFS_DEVICE_NAME_U) +
  3706. Service->Address.Length;
  3707. }
  3708. shareName.Buffer = ExAllocatePoolWithTag(PagedPool, shareName.MaximumLength, ' puM');
  3709. if (shareName.Buffer != NULL) {
  3710. //
  3711. // If we have a cached connection to the IPC$ share of this server,
  3712. // close it or it might conflict with the credentials supplied here.
  3713. //
  3714. if (Service->ConnFile != NULL) {
  3715. ExAcquireResourceExclusiveLite(&DfsData.Resource, TRUE);
  3716. if (Service->ConnFile != NULL)
  3717. DfsCloseConnection(Service);
  3718. ExReleaseResourceLite(&DfsData.Resource);
  3719. }
  3720. //
  3721. // Now, build the share name to tree connect to.
  3722. //
  3723. shareName.Length = 0;
  3724. if (Service->pProvider != NULL &&
  3725. Service->pProvider->DeviceName.Buffer != NULL &&
  3726. Service->pProvider->DeviceName.Length > 0) {
  3727. //
  3728. // We have a provider already - use it
  3729. //
  3730. RtlAppendUnicodeToString(
  3731. &shareName,
  3732. Service->pProvider->DeviceName.Buffer);
  3733. } else {
  3734. //
  3735. // We don't have a provider yet - give it to the mup to find one
  3736. //
  3737. RtlAppendUnicodeToString(
  3738. &shareName,
  3739. DD_NFS_DEVICE_NAME_U);
  3740. }
  3741. RtlAppendUnicodeStringToString(&shareName, &Service->Address);
  3742. //
  3743. // One can only do tree connects to server\share. So, in case
  3744. // pService->Address refers to something deeper than the share,
  3745. // make sure we setup a tree-conn only to server\share. Note that
  3746. // by now, shareName is of the form
  3747. // \Device\LanmanRedirector\server\share<\path>. So, count up to
  3748. // 4 slashes and terminate the share name there.
  3749. //
  3750. for (i = 0, k = 0;
  3751. i < shareName.Length/sizeof(WCHAR) && k < 5;
  3752. i++) {
  3753. if (shareName.Buffer[i] == UNICODE_PATH_SEP)
  3754. k++;
  3755. }
  3756. shareName.Length = i * sizeof(WCHAR);
  3757. if (k == 5)
  3758. shareName.Length -= sizeof(WCHAR);
  3759. InitializeObjectAttributes(
  3760. &objectAttributes,
  3761. &shareName,
  3762. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  3763. NULL,
  3764. NULL);
  3765. //
  3766. // Release the Pkt before going over the net...
  3767. //
  3768. PktRelease();
  3769. status = ZwCreateFile(
  3770. &treeHandle,
  3771. SYNCHRONIZE,
  3772. &objectAttributes,
  3773. &ioStatusBlock,
  3774. NULL,
  3775. FILE_ATTRIBUTE_NORMAL,
  3776. FILE_SHARE_READ |
  3777. FILE_SHARE_WRITE |
  3778. FILE_SHARE_DELETE,
  3779. FILE_OPEN_IF,
  3780. FILE_CREATE_TREE_CONNECTION |
  3781. FILE_SYNCHRONOUS_IO_NONALERT,
  3782. (PVOID) (Creds) ? Creds->EaBuffer : NULL,
  3783. (Creds) ? Creds->EaLength : 0);
  3784. if (NT_SUCCESS(status)) {
  3785. PFILE_OBJECT fileObject;
  3786. LMR_REQUEST_PACKET request;
  3787. DfsGetLogonId(&request.LogonId);
  3788. request.Type = GetConnectionInfo;
  3789. request.Version = REQUEST_PACKET_VERSION;
  3790. request.Level = 3;
  3791. status = ZwFsControlFile(
  3792. treeHandle,
  3793. NULL,
  3794. NULL,
  3795. NULL,
  3796. &ioStatusBlock,
  3797. FSCTL_LMR_GET_CONNECTION_INFO,
  3798. (LPVOID)&request,
  3799. sizeof(request),
  3800. OutputBuffer,
  3801. OutputBufferLength);
  3802. if (NT_SUCCESS(status)) {
  3803. *InfoLen = (ULONG)ioStatusBlock.Information;
  3804. }
  3805. //
  3806. // 426184, need to check return code for errors.
  3807. //
  3808. ObjectRefStatus = ObReferenceObjectByHandle(
  3809. treeHandle,
  3810. 0,
  3811. NULL,
  3812. KernelMode,
  3813. &fileObject,
  3814. NULL);
  3815. ZwClose( treeHandle );
  3816. if (NT_SUCCESS(ObjectRefStatus)) {
  3817. DfsDeleteTreeConnection( fileObject, USE_FORCE );
  3818. }
  3819. }
  3820. ExFreePool( shareName.Buffer );
  3821. PktAcquireShared( TRUE, &pktLocked );
  3822. } else {
  3823. status = STATUS_INSUFFICIENT_RESOURCES;
  3824. }
  3825. DfsDbgTrace(-1, Dbg, "DfsTreeConnectGetInfo exit: Status %x\n", ULongToPtr(status) );
  3826. return( status );
  3827. }
  3828. //+-------------------------------------------------------------------
  3829. //
  3830. // Function: DfsFsctrlCscServerOffline, public
  3831. //
  3832. // Synopsis: This routine implements the functionality to mark a server
  3833. // as offline.
  3834. //
  3835. // Returns: [NTSTATUS] -- The completion status.
  3836. //
  3837. //--------------------------------------------------------------------
  3838. NTSTATUS
  3839. DfsFsctrlCscServerOffline(
  3840. IN PIRP_CONTEXT IrpContext,
  3841. IN PIRP Irp,
  3842. IN PUCHAR InputBuffer,
  3843. IN ULONG InputBufferLength,
  3844. IN OUT PUCHAR OutputBuffer,
  3845. IN ULONG OutputBufferLength)
  3846. {
  3847. UNICODE_STRING ServerName;
  3848. LPWSTR Name;
  3849. ULONG i, j;
  3850. NTSTATUS NtStatus;
  3851. DfsDbgTrace(+1, Dbg, "DfsFsctrlCscServerOffline -> %ws\n", (WCHAR *)InputBuffer);
  3852. if(InputBuffer == NULL) {
  3853. NtStatus = STATUS_INVALID_PARAMETER;
  3854. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3855. return NtStatus;
  3856. }
  3857. Name = (WCHAR *)InputBuffer;
  3858. for (i = 0; i < InputBufferLength/sizeof(WCHAR) && (Name[i] == UNICODE_PATH_SEP); i++)
  3859. NOTHING;
  3860. for (j = i; j < InputBufferLength/sizeof(WCHAR) && (Name[j] != UNICODE_PATH_SEP); j++)
  3861. NOTHING;
  3862. ServerName.Buffer = &Name[i];
  3863. ServerName.MaximumLength = ServerName.Length = (USHORT)(j - i) * sizeof(WCHAR);
  3864. NtStatus = DfspMarkServerOffline(&ServerName);
  3865. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3866. DfsDbgTrace(-1, Dbg, "DfsFsctrlCscServerOffline -> %08lx\n", ULongToPtr(NtStatus) );
  3867. return NtStatus;
  3868. }
  3869. //+-------------------------------------------------------------------
  3870. //
  3871. // Function: DfsFsctrlCscServerOnline, public
  3872. //
  3873. // Synopsis: This routine implements the functionality to mark a server
  3874. // as online.
  3875. //
  3876. // Returns: [NTSTATUS] -- The completion status.
  3877. //
  3878. //--------------------------------------------------------------------
  3879. NTSTATUS
  3880. DfsFsctrlCscServerOnline(
  3881. IN PIRP_CONTEXT IrpContext,
  3882. IN PIRP Irp,
  3883. IN PUCHAR InputBuffer,
  3884. IN ULONG InputBufferLength,
  3885. IN OUT PUCHAR OutputBuffer,
  3886. IN ULONG OutputBufferLength)
  3887. {
  3888. UNICODE_STRING ServerName;
  3889. LPWSTR Name;
  3890. ULONG i, j;
  3891. NTSTATUS NtStatus;
  3892. DfsDbgTrace(+1, Dbg, "DfsFsctrlCscServerOnline -> %ws\n", (WCHAR *)InputBuffer);
  3893. if(InputBuffer == NULL) {
  3894. NtStatus = STATUS_INVALID_PARAMETER;
  3895. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3896. return NtStatus;
  3897. }
  3898. Name = (WCHAR *)InputBuffer;
  3899. for (i = 0; i < InputBufferLength/sizeof(WCHAR) && (Name[i] == UNICODE_PATH_SEP); i++)
  3900. NOTHING;
  3901. for (j = i; j < InputBufferLength/sizeof(WCHAR) && (Name[j] != UNICODE_PATH_SEP); j++)
  3902. NOTHING;
  3903. ServerName.Buffer = &Name[i];
  3904. ServerName.MaximumLength = ServerName.Length = (USHORT)(j - i) * sizeof(WCHAR);
  3905. NtStatus = DfspMarkServerOnline(&ServerName);
  3906. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  3907. DfsDbgTrace(-1, Dbg, "DfsFsctrlCscServerOnline -> %08lx\n", ULongToPtr(NtStatus) );
  3908. return NtStatus;
  3909. }
  3910. //+-------------------------------------------------------------------
  3911. //
  3912. // Function: DfsFsctrlSpcRefresh, public
  3913. //
  3914. // Synopsis: This routine implements the functionality to update the
  3915. // special table with a list of trusted domains, based on
  3916. // the passed in domainname and dcname.
  3917. //
  3918. // Returns: [NTSTATUS] -- The completion status.
  3919. //
  3920. //--------------------------------------------------------------------
  3921. #if defined (_WIN64)
  3922. // 32 bit structure for handling spcrefresh from 32 bit client
  3923. typedef struct _DFS_SPC_REFRESH_INFO32 {
  3924. ULONG EventType;
  3925. WORD * POINTER_32 DomainName; // Name of domain
  3926. WORD * POINTER_32 DCName; // Path of the share
  3927. } DFS_SPC_REFRESH_INFO32, *PDFS_SPC_REFRESH_INFO32;
  3928. #endif /* _WIN64 */
  3929. NTSTATUS
  3930. DfsFsctrlSpcRefresh (
  3931. IN PIRP_CONTEXT IrpContext,
  3932. IN PIRP Irp,
  3933. IN PUCHAR InputBuffer,
  3934. IN ULONG InputBufferLength
  3935. ) {
  3936. NTSTATUS NtStatus = STATUS_SUCCESS;
  3937. UNICODE_STRING DomainName;
  3938. UNICODE_STRING DCName;
  3939. ULONG NameLen, i;
  3940. LPWSTR Name, BufferEnd;
  3941. DFS_SPC_REFRESH_INFO Param;
  3942. PDFS_SPC_REFRESH_INFO pParam;
  3943. DfsDbgTrace(+1, Dbg, "DfsFsctrlSpcRefresh\n", 0);
  3944. STD_FSCTRL_PROLOGUE(DfsFsctrlSpcRefresh, TRUE, FALSE, FALSE);
  3945. pParam = (PDFS_SPC_REFRESH_INFO) InputBuffer;
  3946. #if defined (_WIN64)
  3947. if (IoIs32bitProcess(Irp)) {
  3948. PDFS_SPC_REFRESH_INFO32 pParam32;
  3949. pParam32 = (PDFS_SPC_REFRESH_INFO32) InputBuffer;
  3950. if (InputBufferLength < sizeof(DFS_SPC_REFRESH_INFO32)) {
  3951. NtStatus = STATUS_INVALID_PARAMETER;
  3952. goto exit_with_status;
  3953. }
  3954. Param.EventType = pParam32->EventType;
  3955. Param.DomainName = (WCHAR *)(((ULONG_PTR)pParam32) + (ULONG)pParam32->DomainName);
  3956. Param.DCName = (WCHAR *)(((ULONG_PTR)pParam32) + (ULONG)pParam32->DCName);
  3957. pParam = &Param;
  3958. }
  3959. else {
  3960. #endif
  3961. if (InputBufferLength < sizeof(DFS_SPC_REFRESH_INFO)) {
  3962. NtStatus = STATUS_INVALID_PARAMETER;
  3963. goto exit_with_status;
  3964. }
  3965. OFFSET_TO_POINTER(pParam->DomainName, pParam);
  3966. OFFSET_TO_POINTER(pParam->DCName, pParam);
  3967. #if defined (_WIN64)
  3968. }
  3969. #endif
  3970. if (pParam->EventType != 0) {
  3971. NtStatus = STATUS_INVALID_PARAMETER;
  3972. goto exit_with_status;
  3973. }
  3974. //
  3975. // If either string is not within the input buffer, error.
  3976. //
  3977. if ((POINTER_IN_BUFFER(pParam->DomainName, sizeof(WCHAR),
  3978. InputBuffer, InputBufferLength) == 0) ||
  3979. (POINTER_IN_BUFFER(pParam->DomainName, sizeof(WCHAR),
  3980. InputBuffer, InputBufferLength) == 0)) {
  3981. NtStatus = STATUS_INVALID_PARAMETER;
  3982. goto exit_with_status;
  3983. }
  3984. //
  3985. // make sure the strings are valid.
  3986. //
  3987. BufferEnd = (LPWSTR)(InputBuffer + InputBufferLength);
  3988. NameLen = (ULONG)(BufferEnd - pParam->DomainName);
  3989. Name = pParam->DomainName;
  3990. // Strip off leading slashes.
  3991. for (i = 0; i < NameLen; i++) {
  3992. if (*Name != UNICODE_PATH_SEP) {
  3993. break;
  3994. }
  3995. Name++;
  3996. }
  3997. NameLen -= (ULONG)(Name - pParam->DomainName);
  3998. for (i = 0; i < NameLen && Name[i]; i++)
  3999. NOTHING;
  4000. if ((i >= NameLen) || (i >= MAXUSHORT)) {
  4001. NtStatus = STATUS_INVALID_PARAMETER;
  4002. goto exit_with_status;
  4003. }
  4004. RtlInitUnicodeString(&DomainName, Name);
  4005. NameLen = (ULONG)(BufferEnd - pParam->DCName);
  4006. Name = pParam->DCName;
  4007. // Strip off leading slashes.
  4008. for (i = 0; i < NameLen; i++) {
  4009. if (*Name != UNICODE_PATH_SEP) {
  4010. break;
  4011. }
  4012. Name++;
  4013. }
  4014. NameLen -= (ULONG)(Name - pParam->DCName);
  4015. for (i = 0; i < NameLen && Name[i]; i++)
  4016. NOTHING;
  4017. if ((i >= NameLen) || (i >= MAXUSHORT)) {
  4018. NtStatus = STATUS_INVALID_PARAMETER;
  4019. goto exit_with_status;
  4020. }
  4021. RtlInitUnicodeString(&DCName, Name);
  4022. NtStatus = PktpUpdateSpecialTable(
  4023. &DomainName,
  4024. &DCName);
  4025. exit_with_status:
  4026. DfsCompleteRequest( IrpContext, Irp, NtStatus );
  4027. DfsDbgTrace(-1, Dbg, "DfsFsctrlSpcRefresh -> %08lx\n", ULongToPtr(NtStatus) );
  4028. return( NtStatus );
  4029. }