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

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