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.

743 lines
18 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. NtDevFcb.c
  5. Abstract:
  6. This module implements the FSD level Close, CleanUp, and FsCtl and IoCtl routines for RxDevice
  7. files. Also, the createroutine is not here; rather, it is called from CommonCreate and
  8. not called directly by the dispatch driver.
  9. Each of the pieces listed (close, cleanup, fsctl, ioctl) has its own little section of the
  10. file......complete with its own forward-prototypes and alloc pragmas
  11. Author:
  12. Joe Linn [JoeLinn] 3-aug-1994
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include <ntddnfs2.h>
  18. #include <ntddmup.h>
  19. #include "fsctlbuf.h"
  20. #include "prefix.h"
  21. #include "rxce.h"
  22. //
  23. // The local trace mask for this part of the module
  24. //
  25. #define Dbg (DEBUG_TRACE_DEVFCB)
  26. NTSTATUS
  27. RxXXXControlFileCallthru (
  28. IN PRX_CONTEXT RxContext,
  29. IN PIRP Irp
  30. );
  31. NTSTATUS
  32. RxDevFcbQueryDeviceInfo (
  33. IN PRX_CONTEXT RxContext,
  34. IN PFOBX Fobx,
  35. OUT PBOOLEAN PostToFsp,
  36. PFILE_FS_DEVICE_INFORMATION UsersBuffer,
  37. ULONG BufferSize,
  38. PULONG ReturnedLength
  39. );
  40. #ifdef ALLOC_PRAGMA
  41. #pragma alloc_text(PAGE, RxCommonDevFCBFsCtl)
  42. #pragma alloc_text(PAGE, RxXXXControlFileCallthru)
  43. #pragma alloc_text(PAGE, RxCommonDevFCBClose)
  44. #pragma alloc_text(PAGE, RxCommonDevFCBCleanup)
  45. #pragma alloc_text(PAGE, RxGetUid)
  46. #pragma alloc_text(PAGE, RxCommonDevFCBIoCtl)
  47. #pragma alloc_text(PAGE, RxCommonDevFCBQueryVolInfo)
  48. #pragma alloc_text(PAGE, RxDevFcbQueryDeviceInfo)
  49. #endif
  50. NTSTATUS
  51. RxXXXControlFileCallthru (
  52. IN PRX_CONTEXT RxContext,
  53. IN PIRP Irp
  54. )
  55. /*++
  56. Routine Description:
  57. This routine calls down to the minirdr to implement ioctl and fsctl controls that
  58. the wrapper doesn't understand. note that if there is no dispatch defined (i.e. for the
  59. wrapper's own device object) then we also set Rxcontext->Fobx to NULL so that the caller
  60. won't try to go thru lowio to get to the minirdr.
  61. Arguments:
  62. RxContext - the context of the request
  63. Irp - the current irp
  64. Return Value:
  65. RXSTATUS - The FSD status for the request include the PostRequest field....
  66. --*/
  67. {
  68. NTSTATUS Status;
  69. PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
  70. PAGED_CODE();
  71. if (RxContext->RxDeviceObject->Dispatch == NULL) {
  72. //
  73. // don't try again on lowio
  74. //
  75. RxContext->pFobx = NULL;
  76. return STATUS_INVALID_DEVICE_REQUEST;
  77. }
  78. Status = RxLowIoPopulateFsctlInfo( RxContext, Irp );
  79. if (Status != STATUS_SUCCESS) {
  80. return Status;
  81. }
  82. if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0) &&
  83. (LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL)) {
  84. return STATUS_INVALID_PARAMETER;
  85. }
  86. if ((LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0) &&
  87. (LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL)) {
  88. return STATUS_INVALID_PARAMETER;
  89. }
  90. Status = (RxContext->RxDeviceObject->Dispatch->MRxDevFcbXXXControlFile)(RxContext);
  91. if (Status != STATUS_PENDING) {
  92. Irp->IoStatus.Information = RxContext->InformationToReturn;
  93. }
  94. return Status;
  95. }
  96. NTSTATUS
  97. RxCommonDevFCBClose (
  98. IN PRX_CONTEXT RxContext,
  99. IN PIRP Irp
  100. )
  101. /*++
  102. Routine Description:
  103. This routine implements the FSD Close for a Device FCB.
  104. Arguments:
  105. RxDeviceObject - Supplies the volume device object where the
  106. file exists
  107. Irp - Supplies the Irp being processed
  108. Return Value:
  109. RXSTATUS - The FSD status for the IRP
  110. --*/
  111. {
  112. NTSTATUS Status = STATUS_SUCCESS;
  113. PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
  114. PFOBX Fobx;
  115. PFCB Fcb;
  116. NODE_TYPE_CODE TypeOfOpen;
  117. PRX_PREFIX_TABLE RxNetNameTable = RxContext->RxDeviceObject->pRxNetNameTable;
  118. PAGED_CODE();
  119. TypeOfOpen = RxDecodeFileObject( FileObject, &Fcb, &Fobx );
  120. RxDbgTrace( 0, Dbg, ("RxCommonDevFCBClose\n", 0) );
  121. RxLog(( "DevFcbClose %lx %lx\n",RxContext, FileObject ));
  122. RxWmiLog( LOG,
  123. RxCommonDevFCBClose,
  124. LOGPTR( RxContext )
  125. LOGPTR( FileObject ) );
  126. if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB) {
  127. return STATUS_INVALID_DEVICE_REQUEST;
  128. }
  129. //
  130. // deal with the device fcb
  131. //
  132. if (!Fobx) {
  133. Fcb->OpenCount -= 1;
  134. return STATUS_SUCCESS;
  135. }
  136. //
  137. // otherwise, it's a connection-type file. you have to get the lock; then case-out
  138. //
  139. RxAcquirePrefixTableLockExclusive( RxNetNameTable, TRUE );
  140. try {
  141. switch (NodeType( Fobx )) {
  142. case RDBSS_NTC_V_NETROOT:
  143. {
  144. PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
  145. VNetRoot->NumberOfOpens -= 1;
  146. RxDereferenceVNetRoot( VNetRoot, LHS_ExclusiveLockHeld );
  147. }
  148. break;
  149. default:
  150. Status = STATUS_NOT_IMPLEMENTED;
  151. }
  152. } finally {
  153. RxReleasePrefixTableLock( RxNetNameTable );
  154. }
  155. return Status;
  156. }
  157. NTSTATUS
  158. RxCommonDevFCBCleanup (
  159. IN PRX_CONTEXT RxContext,
  160. IN PIRP Irp
  161. )
  162. /*++
  163. Routine Description:
  164. This routine implements the FSD part of closing down a handle to a
  165. device FCB.
  166. Arguments:
  167. RxDeviceObject - Supplies the volume device object where the
  168. file being Cleanup exists
  169. Irp - Supplies the Irp being processed
  170. Return Value:
  171. RXSTATUS - The FSD status for the IRP
  172. --*/
  173. {
  174. NTSTATUS Status = STATUS_SUCCESS;
  175. PFILE_OBJECT FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
  176. PFOBX Fobx;
  177. PFCB Fcb;
  178. NODE_TYPE_CODE TypeOfOpen;
  179. PAGED_CODE();
  180. TypeOfOpen = RxDecodeFileObject( FileObject, &Fcb, &Fobx );
  181. RxDbgTrace( 0, Dbg, ("RxCommonFCBCleanup\n", 0) );
  182. RxLog(( "DevFcbCleanup %lx\n", RxContext, FileObject ));
  183. RxWmiLog( LOG,
  184. RxCommonDevFCBCleanup,
  185. LOGPTR( RxContext )
  186. LOGPTR( FileObject ) );
  187. if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB) {
  188. return STATUS_INVALID_DEVICE_REQUEST;
  189. }
  190. //
  191. // deal with the device fcb
  192. //
  193. if (!Fobx) {
  194. Fcb->UncleanCount -= 1;
  195. return STATUS_SUCCESS;
  196. }
  197. //
  198. // otherwise, it's a connection-type file. you have to get the lock; then case-out
  199. //
  200. RxAcquirePrefixTableLockShared( RxContext->RxDeviceObject->pRxNetNameTable, TRUE );
  201. try {
  202. Status = STATUS_SUCCESS;
  203. switch (NodeType( Fobx )) {
  204. case RDBSS_NTC_V_NETROOT:
  205. //
  206. // nothing to do
  207. //
  208. break;
  209. default:
  210. Status = STATUS_INVALID_DEVICE_REQUEST;
  211. }
  212. } finally {
  213. RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
  214. }
  215. return Status;
  216. }
  217. //
  218. // | *********************|
  219. // | | F S C T L ||
  220. // | *********************|
  221. //
  222. NTSTATUS
  223. RxCommonDevFCBFsCtl (
  224. IN PRX_CONTEXT RxContext,
  225. IN PIRP Irp
  226. )
  227. /*++
  228. Routine Description:
  229. This is the common routine for doing FileSystem control operations called
  230. by both the fsd and fsp threads
  231. Arguments:
  232. RxContext - Supplies the Irp to process and stateinfo about where we are
  233. Return Value:
  234. RXSTATUS - The return status for the operation
  235. --*/
  236. {
  237. NTSTATUS Status;
  238. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  239. PFOBX Fobx;
  240. PFCB Fcb;
  241. NODE_TYPE_CODE TypeOfOpen;
  242. ULONG FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
  243. PAGED_CODE();
  244. TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
  245. RxDbgTrace( +1, Dbg, ("RxCommonDevFCBFsCtl IrpC = %08lx\n", RxContext) );
  246. RxDbgTrace( 0, Dbg, ("MinorFunction = %08lx, ControlCode = %08lx \n",
  247. IrpSp->MinorFunction, FsControlCode) );
  248. RxLog(( "DevFcbFsCtl %lx %lx %lx\n", RxContext, IrpSp->MinorFunction, FsControlCode ));
  249. RxWmiLog( LOG,
  250. RxCommonDevFCBFsCtl,
  251. LOGPTR( RxContext )
  252. LOGUCHAR( IrpSp->MinorFunction )
  253. LOGULONG( FsControlCode ) );
  254. if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
  255. return STATUS_INVALID_DEVICE_REQUEST;
  256. }
  257. //
  258. // We know this is a file system control so we'll case on the
  259. // minor function, and call a internal worker routine to complete
  260. // the irp.
  261. //
  262. switch (IrpSp->MinorFunction) {
  263. case IRP_MN_USER_FS_REQUEST:
  264. switch (FsControlCode) {
  265. #ifdef RDBSSLOG
  266. case FSCTL_LMR_DEBUG_TRACE:
  267. //
  268. // This FSCTL is being disabled since no one uses this anymore. If
  269. // it needs to be reactivated for some reason, the appropriate
  270. // checks have to be added to make sure that the IRP->UserBuffer is
  271. // a valid address. The try/except call below won't protect against
  272. // a random kernel address being passed.
  273. //
  274. return STATUS_INVALID_DEVICE_REQUEST;
  275. //
  276. // the 2nd buffer points to the string
  277. //
  278. //
  279. // We need to try/except this call to protect against random buffers
  280. // being passed in from UserMode.
  281. //
  282. try {
  283. RxDebugControlCommand( Irp->UserBuffer );
  284. } except (EXCEPTION_EXECUTE_HANDLER) {
  285. return STATUS_INVALID_USER_BUFFER;
  286. }
  287. Status = STATUS_SUCCESS;
  288. break;
  289. #endif // RDBSSLOG
  290. default:
  291. RxDbgTrace( 0, Dbg, ("RxFsdDevFCBFsCTL unknown user request\n") );
  292. Status = RxXXXControlFileCallthru( RxContext, Irp );
  293. if ((Status == STATUS_INVALID_DEVICE_REQUEST) && (Fobx != NULL)) {
  294. RxDbgTrace( 0, Dbg, ("RxCommonDevFCBFsCtl -> Invoking Lowio for FSCTL\n") );
  295. Status = RxLowIoFsCtlShell( RxContext, Irp, Fcb, Fobx );
  296. }
  297. }
  298. break;
  299. default :
  300. RxDbgTrace( 0, Dbg, ("RxFsdDevFCBFsCTL nonuser request!!\n", 0) );
  301. Status = RxXXXControlFileCallthru( RxContext, Irp );
  302. }
  303. if (RxContext->PostRequest) {
  304. Status = RxFsdPostRequestWithResume( RxContext, RxCommonDevFCBFsCtl );
  305. }
  306. RxDbgTrace(-1, Dbg, ("RxCommonDevFCBFsCtl -> %08lx\n", Status));
  307. return Status;
  308. }
  309. //
  310. // | *********************|
  311. // | | I O C T L ||
  312. // | *********************|
  313. //
  314. NTSTATUS
  315. RxCommonDevFCBIoCtl (
  316. IN PRX_CONTEXT RxContext,
  317. IN PIRP Irp
  318. )
  319. /*++
  320. Routine Description:
  321. This is the common routine for doing FileSystem control operations called
  322. by both the fsd and fsp threads
  323. Arguments:
  324. RxContext - Supplies the Irp to process and stateinfo about where we are
  325. Return Value:
  326. RXSTATUS - The return status for the operation
  327. --*/
  328. {
  329. NTSTATUS Status;
  330. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  331. PFCB Fcb;
  332. PFOBX Fobx;
  333. NODE_TYPE_CODE TypeOfOpen;
  334. ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  335. PAGED_CODE();
  336. TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
  337. RxDbgTrace( +1, Dbg, ("RxCommonDevFCBIoCtl IrpC-%08lx\n", RxContext) );
  338. RxDbgTrace( 0, Dbg, ("ControlCode = %08lx\n", IoControlCode) );
  339. if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
  340. return STATUS_INVALID_DEVICE_REQUEST;
  341. }
  342. if (Fobx == NULL) {
  343. switch (IoControlCode) {
  344. case IOCTL_REDIR_QUERY_PATH:
  345. //
  346. // This particular IOCTL should only come to us from the MUP and
  347. // hence the requestor mode of the IRP should always be KernelMode.
  348. // If its not we return STATUS_INVALID_DEVICE_REQUEST.
  349. //
  350. if (Irp->RequestorMode != KernelMode) {
  351. Status = STATUS_INVALID_DEVICE_REQUEST;
  352. } else {
  353. Status = RxPrefixClaim( RxContext );
  354. }
  355. break;
  356. default:
  357. Status = RxXXXControlFileCallthru( RxContext, Irp );
  358. if ((Status != STATUS_PENDING) && RxContext->PostRequest) {
  359. Status = RxFsdPostRequestWithResume( RxContext, RxCommonDevFCBIoCtl );
  360. }
  361. break;
  362. }
  363. } else {
  364. Status = STATUS_INVALID_HANDLE;
  365. }
  366. RxDbgTrace( -1, Dbg, ("RxCommonDevFCBIoCtl -> %08lx\n", Status) );
  367. return Status;
  368. }
  369. //
  370. // Utility Routine
  371. //
  372. LUID
  373. RxGetUid (
  374. IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
  375. )
  376. /*++
  377. Routine Description:
  378. This routine gets the effective UID to be used for this create.
  379. Arguments:
  380. SubjectSecurityContext - Supplies the information from IrpSp.
  381. Return Value:
  382. None
  383. --*/
  384. {
  385. LUID LogonId;
  386. PAGED_CODE();
  387. RxDbgTrace(+1, Dbg, ("RxGetUid ... \n", 0));
  388. //
  389. // Use SeQuerySubjectContextToken to get the proper token in case of impersonation
  390. //
  391. SeQueryAuthenticationIdToken( SeQuerySubjectContextToken( SubjectSecurityContext ), &LogonId );
  392. RxDbgTrace( -1, Dbg, (" ->UserUidHigh/Low = %08lx %08lx\n", LogonId.HighPart, LogonId.LowPart) );
  393. return LogonId;
  394. }
  395. //
  396. // | *********************|
  397. // | | V O L I N F O ||
  398. // | *********************|
  399. //
  400. NTSTATUS
  401. RxCommonDevFCBQueryVolInfo (
  402. IN PRX_CONTEXT RxContext,
  403. IN PIRP Irp
  404. )
  405. /*++
  406. Routine Description:
  407. This is the common routine for doing FileSystem control operations called
  408. by both the fsd and fsp threads
  409. Arguments:
  410. RxContext - Supplies the Irp to process and stateinfo about where we are
  411. Return Value:
  412. NTSTATUS - The return status for the operation
  413. --*/
  414. {
  415. NTSTATUS Status;
  416. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  417. FS_INFORMATION_CLASS InformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
  418. PFCB Fcb;
  419. PFOBX Fobx;
  420. NODE_TYPE_CODE TypeOfOpen;
  421. PVOID UsersBuffer = Irp->AssociatedIrp.SystemBuffer;
  422. ULONG BufferSize = IrpSp->Parameters.QueryVolume.Length;
  423. ULONG ReturnedLength;
  424. BOOLEAN PostToFsp = FALSE;
  425. PAGED_CODE();
  426. TypeOfOpen = RxDecodeFileObject( IrpSp->FileObject, &Fcb, &Fobx );
  427. if (TypeOfOpen != RDBSS_NTC_DEVICE_FCB ) {
  428. return STATUS_INVALID_DEVICE_REQUEST;
  429. }
  430. RxDbgTrace( +1, Dbg, ("RxCommonDevFCBQueryVolInfo IrpC-%08lx\n", RxContext) );
  431. RxDbgTrace( 0, Dbg, ("ControlCode = %08lx\n", InformationClass) );
  432. RxLog(( "DevFcbQVolInfo %lx %lx\n", RxContext, InformationClass ));
  433. RxWmiLog( LOG,
  434. RxCommonDevFCBQueryVolInfo,
  435. LOGPTR( RxContext )
  436. LOGULONG( InformationClass ) );
  437. switch (InformationClass) {
  438. case FileFsDeviceInformation:
  439. Status = RxDevFcbQueryDeviceInfo( RxContext, Fobx, &PostToFsp, UsersBuffer, BufferSize, &ReturnedLength );
  440. break;
  441. default:
  442. Status = STATUS_NOT_IMPLEMENTED;
  443. };
  444. RxDbgTrace( -1, Dbg, ("RxCommonDevFCBQueryVolInfo -> %08lx\n", Status) );
  445. if ( PostToFsp ) return RxFsdPostRequestWithResume( RxContext, RxCommonDevFCBQueryVolInfo );
  446. if (Status == STATUS_SUCCESS) {
  447. Irp->IoStatus.Information = ReturnedLength;
  448. }
  449. return Status;
  450. }
  451. NTSTATUS
  452. RxDevFcbQueryDeviceInfo (
  453. IN PRX_CONTEXT RxContext,
  454. IN PFOBX Fobx,
  455. OUT PBOOLEAN PostToFsp,
  456. PFILE_FS_DEVICE_INFORMATION UsersBuffer,
  457. ULONG BufferSize,
  458. PULONG ReturnedLength
  459. )
  460. /*++
  461. Routine Description:
  462. This routine shuts down up the RDBSS filesystem...i.e. we connect to the MUP. We can only shut down
  463. if there's no netroots and if there's only one deviceFCB handle.
  464. Arguments:
  465. IN PRX_CONTEXT RxContext - Describes the Fsctl and Context....for later when i need the buffers
  466. Return Value:
  467. --*/
  468. {
  469. NTSTATUS Status;
  470. BOOLEAN Wait = BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_WAIT );
  471. BOOLEAN InFSD = !BooleanFlagOn( RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP );
  472. PAGED_CODE();
  473. RxDbgTrace(0, Dbg, ("RxDevFcbQueryDeviceInfo -> %08lx\n", 0));
  474. if (BufferSize < sizeof( FILE_FS_DEVICE_INFORMATION )) {
  475. return STATUS_BUFFER_OVERFLOW;
  476. };
  477. UsersBuffer->Characteristics = FILE_REMOTE_DEVICE;
  478. *ReturnedLength = sizeof( FILE_FS_DEVICE_INFORMATION );
  479. //
  480. // deal with the device fcb
  481. //
  482. if (!Fobx) {
  483. UsersBuffer->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
  484. return STATUS_SUCCESS;
  485. }
  486. //
  487. // otherwise, it's a connection-type file. you have to get the lock; then case-out
  488. //
  489. if (!RxAcquirePrefixTableLockShared( RxContext->RxDeviceObject->pRxNetNameTable, Wait )) {
  490. *PostToFsp = TRUE;
  491. return STATUS_PENDING;
  492. }
  493. try {
  494. Status = STATUS_SUCCESS;
  495. switch (NodeType( Fobx )) {
  496. case RDBSS_NTC_V_NETROOT:
  497. {
  498. PV_NET_ROOT VNetRoot = (PV_NET_ROOT)Fobx;
  499. PNET_ROOT NetRoot = (PNET_ROOT)VNetRoot->NetRoot;
  500. if (NetRoot->Type == NET_ROOT_PIPE) {
  501. NetRoot->DeviceType = FILE_DEVICE_NAMED_PIPE;
  502. }
  503. UsersBuffer->DeviceType = NetRoot->DeviceType;
  504. }
  505. break;
  506. default:
  507. Status = STATUS_NOT_IMPLEMENTED;
  508. }
  509. } finally {
  510. RxReleasePrefixTableLock( RxContext->RxDeviceObject->pRxNetNameTable );
  511. }
  512. return Status;
  513. }
  514.