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.

1192 lines
36 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. openclos.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to opening/
  7. closing of file/directories.
  8. Author:
  9. Balan Sethu Raman [SethuR] 7-March-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. ////
  15. //// The Bug check file id for this module
  16. ////
  17. //
  18. //#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
  19. //
  20. // The debug trace level
  21. //
  22. #define Dbg (DEBUG_TRACE_CREATE)
  23. #ifdef RX_PRIVATE_BUILD
  24. ULONG MRxProxyDbgPrintF = 1; //0; //1;
  25. #endif //ifdef RX_PRIVATE_BUILD
  26. #ifdef RX_PRIVATE_BUILD
  27. #undef IoGetTopLevelIrp
  28. #undef IoSetTopLevelIrp
  29. #endif //ifdef RX_PRIVATE_BUILD
  30. NTSTATUS
  31. MRxProxySyncIrpCompletionRoutine (
  32. IN PDEVICE_OBJECT DeviceObject,
  33. IN PIRP CalldownIrp,
  34. IN PVOID Context
  35. )
  36. /*++
  37. Routine Description:
  38. This routine is called when the calldownirp is completed.
  39. Arguments:
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP CalldownIrp,
  42. IN PVOID Context
  43. Return Value:
  44. RXSTATUS - STATUS_MORE_PROCESSING_REQUIRED
  45. --*/
  46. {
  47. PRX_CONTEXT RxContext = (PRX_CONTEXT)Context;
  48. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  49. if (CalldownIrp->PendingReturned){
  50. //pMRxProxyContext->SyncCallDownIoStatus = CalldownIrp->IoStatus;
  51. RxSignalSynchronousWaiter(RxContext);
  52. }
  53. return(STATUS_MORE_PROCESSING_REQUIRED);
  54. }
  55. //not on the stack...just in case
  56. ULONG DummyReturnedLengthForXxxInfo;
  57. NTSTATUS
  58. MRxProxySyncXxxInformation(
  59. IN OUT PRX_CONTEXT RxContext,
  60. IN UCHAR MajorFunction,
  61. IN PFILE_OBJECT FileObject,
  62. IN ULONG InformationClass,
  63. IN ULONG Length,
  64. OUT PVOID Information,
  65. OUT PULONG ReturnedLength OPTIONAL
  66. )
  67. /*++
  68. Routine Description:
  69. This routine returns the requested information about a specified file
  70. or volume. The information returned is determined by the class that
  71. is specified, and it is placed into the caller's output buffer.
  72. Arguments:
  73. FsInformationClass - Specifies the type of information which should be
  74. returned about the file/volume.
  75. Length - Supplies the length of the buffer in bytes.
  76. FsInformation - Supplies a buffer to receive the requested information
  77. returned about the file. This buffer must not be pageable and must
  78. reside in system space.
  79. ReturnedLength - Supplies a variable that is to receive the length of the
  80. information written to the buffer.
  81. FileInformation - Boolean that indicates whether the information requested
  82. is for a file or a volume.
  83. Return Value:
  84. The status returned is the final completion status of the operation.
  85. --*/
  86. {
  87. NTSTATUS Status;
  88. PIRP irp,TopIrp;
  89. PIO_STACK_LOCATION irpSp;
  90. PDEVICE_OBJECT DeviceObject;
  91. //ULONG SetFileInfoInfo;
  92. PAGED_CODE();
  93. if (ReturnedLength==NULL) {
  94. ReturnedLength = &DummyReturnedLengthForXxxInfo;
  95. }
  96. ASSERT (FileObject);
  97. DeviceObject = IoGetRelatedDeviceObject( FileObject );
  98. ASSERT (DeviceObject);
  99. //
  100. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  101. // The allocation is performed with an exception handler in case the
  102. // caller does not have enough quota to allocate the packet.
  103. //
  104. irp = IoAllocateIrp( DeviceObject->StackSize, TRUE );
  105. if (!irp) {
  106. return STATUS_INSUFFICIENT_RESOURCES;
  107. }
  108. irp->Tail.Overlay.OriginalFileObject = FileObject;
  109. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  110. irp->RequestorMode = KernelMode;
  111. //
  112. // Get a pointer to the stack location for the first driver. This will be
  113. // used to pass the original function codes and parameters.
  114. //
  115. irpSp = IoGetNextIrpStackLocation( irp );
  116. irpSp->MajorFunction = MajorFunction;
  117. irpSp->FileObject = FileObject;
  118. IoSetCompletionRoutine(irp,
  119. MRxProxySyncIrpCompletionRoutine,
  120. RxContext,
  121. TRUE,TRUE,TRUE); //call no matter what....
  122. irp->AssociatedIrp.SystemBuffer = Information;
  123. //
  124. // Copy the caller's parameters to the service-specific portion of the
  125. // IRP.
  126. //
  127. IF_DEBUG {
  128. ASSERT( (irpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION)
  129. || (irpSp->MajorFunction == IRP_MJ_SET_INFORMATION)
  130. || (irpSp->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION) );
  131. if (irpSp->MajorFunction == IRP_MJ_SET_INFORMATION) {
  132. //IF_LOUD_DOWNCALLS(MiniFileObject) {
  133. // SetFileInfoInfo = ((PFILE_END_OF_FILE_INFORMATION)Information)->EndOfFile.LowPart;
  134. //}
  135. }
  136. ASSERT(&irpSp->Parameters.QueryFile.Length == &irpSp->Parameters.SetFile.Length);
  137. ASSERT(&irpSp->Parameters.QueryFile.Length == &irpSp->Parameters.QueryVolume.Length);
  138. ASSERT(&irpSp->Parameters.QueryFile.FileInformationClass
  139. == &irpSp->Parameters.SetFile.FileInformationClass);
  140. ASSERT(&irpSp->Parameters.QueryFile.FileInformationClass
  141. == &irpSp->Parameters.QueryVolume.FsInformationClass);
  142. }
  143. irpSp->Parameters.QueryFile.Length = Length;
  144. irpSp->Parameters.QueryFile.FileInformationClass = InformationClass;
  145. //
  146. // Now simply invoke the driver at its dispatch entry with the IRP.
  147. //
  148. KeInitializeEvent( &RxContext->SyncEvent,
  149. NotificationEvent,
  150. FALSE );
  151. //LoudCallsDbgPrint("Ready to",
  152. // MiniFileObject,
  153. // irpSp->MajorFunction,
  154. // irpSp->Parameters.QueryFile.FileInformationClass,
  155. // irpSp->Parameters.QueryFile.Length,
  156. // SetFileInfoInfo,0,0
  157. // );
  158. try {
  159. TopIrp = IoGetTopLevelIrp();
  160. IoSetTopLevelIrp(NULL); //tell the underlying guy he's all clear
  161. Status = IoCallDriver(DeviceObject,irp);
  162. } finally {
  163. IoSetTopLevelIrp(TopIrp); //restore my context for unwind
  164. }
  165. //RxDbgTrace (0, Dbg, (" -->Status after iocalldriver %08lx(%08lx)\n",RxContext,Status));
  166. if (Status == (STATUS_PENDING)) {
  167. RxWaitSync(RxContext);
  168. Status = irp->IoStatus.Status;
  169. }
  170. //LoudCallsDbgPrint("Back from",
  171. // MiniFileObject,
  172. // irpSp->MajorFunction,
  173. // irpSp->Parameters.QueryFile.FileInformationClass,
  174. // irpSp->Parameters.QueryFile.Length,
  175. // SetFileInfoInfo,
  176. // Status,irp->IoStatus.Information
  177. // );
  178. if (Status==STATUS_SUCCESS) {
  179. *ReturnedLength = irp->IoStatus.Information;
  180. RxDbgTrace( 0, Dbg, ("MRxProxySyncXxxInformation(%x)Info<%x> %x bytes@%x returns %08lx/%08lx\n",
  181. RxContext,MajorFunction,
  182. Status,*ReturnedLength));
  183. }
  184. IoFreeIrp(irp);
  185. return(Status);
  186. }
  187. NTSTATUS
  188. MRxProxyShouldTryToCollapseThisOpen (
  189. IN PRX_CONTEXT RxContext
  190. )
  191. /*++
  192. Routine Description:
  193. This routine determines if the mini knows of a good reason not
  194. to try collapsing on this open. Presently, the only reason would
  195. be if this were a copychunk open.
  196. Arguments:
  197. RxContext - the RDBSS context
  198. Return Value:
  199. NTSTATUS - The return status for the operation
  200. SUCCESS --> okay to try collapse
  201. other (MORE_PROCESSING_REQUIRED) --> dont collapse
  202. --*/
  203. {
  204. NTSTATUS Status = STATUS_SUCCESS;
  205. PAGED_CODE();
  206. return Status;
  207. }
  208. VOID
  209. MRxProxyMungeBufferingIfWriteOnlyHandles (
  210. ULONG WriteOnlySrvOpenCount,
  211. PMRX_SRV_OPEN SrvOpen
  212. )
  213. /*++
  214. Routine Description:
  215. This routine modifies the buffering flags on a srvopen so that
  216. no cacheing will be allowed if there are any write-only handles
  217. to the file. CODE.IMPROVEMENT this should be inlined.
  218. Arguments:
  219. WriteOnlySrvOpenCount - the number of writeonly srvopens
  220. SrvOpen - the srvopen whose buffring flags are to be munged
  221. Return Value:
  222. RXSTATUS - The return status for the operation
  223. --*/
  224. {
  225. BOOLEAN IsLoopBack = FALSE;
  226. PMRX_SRV_CALL pSrvCall;
  227. //PSMBCEDB_SERVER_ENTRY pServerEntry;
  228. pSrvCall = SrvOpen->pVNetRoot->pNetRoot->pSrvCall;
  229. #if 0
  230. pServerEntry = SmbCeReferenceAssociatedServerEntry(pSrvCall);
  231. ASSERT(pServerEntry != NULL);
  232. IsLoopBack = pServerEntry->Server.IsLoopBack;
  233. SmbCeDereferenceServerEntry(pServerEntry);
  234. #endif
  235. if (!IsLoopBack && (WriteOnlySrvOpenCount==0)) {
  236. return;
  237. }
  238. SrvOpen->BufferingFlags &=
  239. ~( FCB_STATE_WRITECACHEING_ENABLED |
  240. FCB_STATE_FILESIZECACHEING_ENABLED |
  241. FCB_STATE_FILETIMECACHEING_ENABLED |
  242. FCB_STATE_LOCK_BUFFERING_ENABLED |
  243. FCB_STATE_READCACHEING_ENABLED |
  244. FCB_STATE_COLLAPSING_ENABLED
  245. );
  246. }
  247. ULONG MRxProxyLoudStringTableSize = 0;
  248. UNICODE_STRING MRxProxyLoudStrings[50];
  249. VOID
  250. MRxProxySetLoud(
  251. IN PBYTE Msg,
  252. IN PRX_CONTEXT RxContext,
  253. IN PUNICODE_STRING s
  254. )
  255. {
  256. ULONG i;
  257. UNICODE_STRING temp;
  258. for (i=0;i<MRxProxyLoudStringTableSize;i++) {
  259. PUNICODE_STRING t = &(MRxProxyLoudStrings[i]);
  260. ((PBYTE)temp.Buffer) = ((PBYTE)s->Buffer) + s->Length - t->Length;
  261. temp.Length = t->Length;
  262. //DbgPrint("%s %lx Comparing %wZ with %wZ from %wZ\n",Msg,t->Length,&temp,t,s);
  263. if (RtlEqualUnicodeString(&temp,t,TRUE)) {
  264. DbgPrint("%s Found %wZ from %wZ\n",Msg,t,s);
  265. RxContext->LoudCompletionString = t;
  266. break;
  267. }
  268. }
  269. }
  270. VOID
  271. MRxProxyInitializeLoudStrings(
  272. void
  273. )
  274. {
  275. RtlInitUnicodeString(&MRxProxyLoudStrings[0],L"xsync.exe");
  276. //RtlInitUnicodeString(&MRxProxyLoudStrings[1],L"calc.exe");
  277. //RtlInitUnicodeString(&MRxProxyLoudStrings[2],L"ecco.exe");
  278. MRxProxyLoudStringTableSize = 1;
  279. }
  280. #define MustBeDirectory(co) ((co) & FILE_DIRECTORY_FILE)
  281. #define MustBeFile(co) ((co) & FILE_NON_DIRECTORY_FILE)
  282. // define structures for posting of open and close calls so that they end up in the
  283. // system process.
  284. typedef
  285. NTSTATUS
  286. (*PMRX_PROXY_POSTABLE_OPERATION) (
  287. IN OUT PRX_CONTEXT RxContext
  288. );
  289. #if 0
  290. typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER {
  291. PRX_CONTEXT RxContext;
  292. union {
  293. NTSTATUS PostReturnStatus;
  294. RX_WORK_QUEUE_ITEM WorkQueueItem;
  295. };
  296. KEVENT PostEvent;
  297. } MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER;
  298. typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT {
  299. union {
  300. MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER;
  301. MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER PostedOpContext;
  302. };
  303. } MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT, *PMRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;;
  304. typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT {
  305. MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;
  306. } MRX_PROXY_POSTED_CREATE_CONTEXT, *PMRX_PROXY_POSTED_CREATE_CONTEXT;
  307. typedef struct _MRX_PROXY_POSTED_CLOSE_CONTEXT {
  308. MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;
  309. } MRX_PROXY_POSTED_CLOSE_CONTEXT, *PMRX_PROXY_POSTED_CLOSE_CONTEXT;
  310. #endif
  311. NTSTATUS
  312. MRxProxyPostOperation (
  313. IN OUT PRX_CONTEXT RxContext,
  314. IN OUT PVOID PostedOpContext,
  315. IN PMRX_PROXY_POSTABLE_OPERATION Operation
  316. )
  317. {
  318. NTSTATUS Status,PostStatus;
  319. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  320. KeInitializeEvent( &RxContext->SyncEvent,
  321. NotificationEvent,
  322. FALSE );
  323. pMRxProxyContext->PostedOpContext = PostedOpContext;
  324. IF_DEBUG {
  325. //fill the workqueue structure with deadbeef....all the better to diagnose
  326. //a failed post
  327. ULONG i;
  328. for (i=0;i+sizeof(ULONG)-1<sizeof(RxContext->WorkQueueItem);i+=sizeof(ULONG)) {
  329. PBYTE BytePtr = ((PBYTE)&RxContext->WorkQueueItem)+i;
  330. PULONG UlongPtr = (PULONG)BytePtr;
  331. *UlongPtr = 0xdeadbeef;
  332. }
  333. }
  334. PostStatus = RxPostToWorkerThread(
  335. &MRxProxyDeviceObject->RxDeviceObject,
  336. DelayedWorkQueue,
  337. &RxContext->WorkQueueItem,
  338. Operation,
  339. RxContext);
  340. ASSERT(PostStatus == STATUS_SUCCESS);
  341. RxWaitSync(RxContext);
  342. Status = pMRxProxyContext->PostedOpStatus;
  343. return(Status);
  344. }
  345. NTSTATUS
  346. MRxProxyPostedCreate (
  347. IN OUT PRX_CONTEXT RxContext
  348. )
  349. /*++
  350. Routine Description:
  351. This routine opens a file across the network
  352. Arguments:
  353. RxContext - the RDBSS context
  354. Return Value:
  355. RXSTATUS - The return status for the operation
  356. --*/
  357. {
  358. NTSTATUS Status;
  359. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  360. RxCaptureFcb;
  361. PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
  362. PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
  363. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  364. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  365. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  366. PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
  367. PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
  368. ULONG Disposition = CreateParameters->Disposition;
  369. ACCESS_MASK DesiredAccess = CreateParameters->DesiredAccess & 0x1FF;
  370. OBJECT_ATTRIBUTES ObjectAttributes;
  371. IO_STATUS_BLOCK IoStatusBlock;
  372. HANDLE handle;
  373. ULONG FilteredCreateOptions;
  374. PAGED_CODE();
  375. RxDbgTrace(+1, Dbg, ("MRxProxyPostedCreate %08lx\n", RxContext ));
  376. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  377. RxDbgTrace( 0, Dbg, (" Attempt to open %wZ\n", &(capFcb->AlreadyPrefixedName) ));
  378. MRxProxySetLoud("Create ",RxContext,&(capFcb->AlreadyPrefixedName));
  379. #if 0
  380. // we cannot have a file cached on a write only handle. so we have to behave a little
  381. // differently if this is a write-only open. remember this in the proxysrvopen
  382. if ( ((DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
  383. ((DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
  384. ) {
  385. //SetFlag(proxySrvOpen->Flags,PROXY_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
  386. //SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING;
  387. DesiredAccess |= FILE_READ_DATA;
  388. }
  389. #endif
  390. // we cannot have a file cached on a write only handle. so if write_data is
  391. // specified then so is read data
  392. if ( ((DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
  393. ((DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
  394. ) {
  395. //SetFlag(proxySrvOpen->Flags,PROXY_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
  396. //SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING;
  397. DesiredAccess |= FILE_READ_DATA;
  398. }
  399. if ( ( DesiredAccess
  400. &~ (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE) )
  401. == 0 ){
  402. SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE);
  403. }
  404. InitializeObjectAttributes(
  405. &ObjectAttributes,
  406. RemainingName,
  407. OBJ_CASE_INSENSITIVE, // !!! can we do this? probably need a flag BUGBUG
  408. 0,
  409. NULL // !!! Security BUGBUG
  410. );
  411. FilteredCreateOptions = CreateParameters->CreateOptions;
  412. if (!MustBeDirectory(FilteredCreateOptions)) {
  413. FilteredCreateOptions &= ~(FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT); //always async
  414. }
  415. FilteredCreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING;
  416. RxDbgTrace( 0, Dbg, (" ---->FilteredCreateOptions = %08lx\n", FilteredCreateOptions));
  417. RxLog(("-->FilteredOptions/oc %lx %lx",FilteredCreateOptions,capFcb->OpenCount));
  418. Status = IoCreateFile(
  419. &handle,
  420. DesiredAccess,
  421. &ObjectAttributes,
  422. &IoStatusBlock,
  423. &CreateParameters->AllocationSize,
  424. CreateParameters->FileAttributes,
  425. CreateParameters->ShareAccess,
  426. CreateParameters->Disposition,
  427. FilteredCreateOptions,
  428. RxContext->Create.EaBuffer,
  429. RxContext->Create.EaLength,
  430. CreateFileTypeNone,
  431. NULL, // extra parameters
  432. IO_NO_PARAMETER_CHECKING
  433. );
  434. if (NT_SUCCESS(Status)) {
  435. Status = ObReferenceObjectByHandle( handle,
  436. 0L,
  437. NULL,
  438. KernelMode,
  439. (PVOID *) &proxySrvOpen->UnderlyingFileObject,
  440. NULL );
  441. if (Status == STATUS_SUCCESS) {
  442. proxySrvOpen->UnderlyingHandle = handle;
  443. proxySrvOpen->UnderlyingDeviceObject = IoGetRelatedDeviceObject( proxySrvOpen->UnderlyingFileObject );
  444. } else {
  445. ZwClose(handle);
  446. }
  447. }
  448. RxDbgTrace( 0, Dbg, ("Status of underlying open %08lx\n", Status ));
  449. RxLog(("--->UnderlyingOpen %lx",Status));
  450. // DbgBreakPoint();
  451. RxDbgTrace(-1, Dbg, ("MRxProxyPostedCreate %08lx exit with status=%08lx\n", RxContext, Status ));
  452. if (NT_SUCCESS(Status)) {
  453. RxContext->Create.ReturnedCreateInformation = IoStatusBlock.Information;
  454. }
  455. pMRxProxyContext->PostedOpStatus = Status;
  456. RxSignalSynchronousWaiter(RxContext);
  457. return(STATUS_SUCCESS);
  458. }
  459. NTSTATUS
  460. MRxProxyPostedCloseHandle (
  461. IN OUT PRX_CONTEXT RxContext
  462. )
  463. /*++
  464. Routine Description:
  465. Arguments:
  466. RxContext - the RDBSS context
  467. Return Value:
  468. RXSTATUS - The return status for the operation
  469. --*/
  470. {
  471. //NTSTATUS Status;
  472. PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
  473. //RxCaptureFcb;
  474. //PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
  475. PMRX_SRV_OPEN SrvOpen = (PMRX_SRV_OPEN)(pMRxProxyContext->PostedOpContext);
  476. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  477. //HANDLE handle;
  478. PAGED_CODE();
  479. RxDbgTrace(+1, Dbg, ("MRxProxyPostedCloseHandle %08lx %08lx\n", RxContext, SrvOpen ));
  480. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  481. ZwClose(proxySrvOpen->UnderlyingHandle);
  482. RxDbgTrace(-1, Dbg, ("MRxProxyPostedCloseHandle %08lx exit\n", RxContext ));
  483. pMRxProxyContext->PostedOpStatus = STATUS_SUCCESS;
  484. RxSignalSynchronousWaiter(RxContext);
  485. return(STATUS_SUCCESS);
  486. }
  487. NTSTATUS
  488. MRxProxyCreate (
  489. IN OUT PRX_CONTEXT RxContext
  490. )
  491. /*++
  492. Routine Description:
  493. This routine opens a file across the network
  494. Arguments:
  495. RxContext - the RDBSS context
  496. Return Value:
  497. RXSTATUS - The return status for the operation
  498. --*/
  499. {
  500. NTSTATUS Status;
  501. RxCaptureFcb;
  502. PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
  503. PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
  504. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  505. BOOLEAN MustRegainExclusiveResource = FALSE;
  506. PAGED_CODE();
  507. RxDbgTrace(+1, Dbg, ("MRxProxyCreate %08lx\n", RxContext ));
  508. //do this BEFORE you drop the resource
  509. SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_COLLAPSING_DISABLED);
  510. Status = MRxProxyPostOperation ( RxContext,
  511. NULL,
  512. MRxProxyPostedCreate );
  513. //this Boolean should be passed......
  514. if (MustRegainExclusiveResource) { //this is required if we do oplock breaks
  515. RxAcquireExclusiveFcb( RxContext, capFcb );
  516. }
  517. if (NT_SUCCESS(Status)) {
  518. RX_FILE_TYPE StorageType;
  519. FILE_BASIC_INFORMATION BasicInformation;
  520. FILE_STANDARD_INFORMATION StandardInformation;
  521. NTSTATUS InfoStatus;
  522. FCB_INIT_PACKET InitPacket;
  523. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  524. StorageType = RxInferFileType(RxContext);
  525. RxDbgTrace( 0, Dbg, ("Storagetype %08lx\n", StorageType ));
  526. // if we have never obtained the characteristics, we have to get them.
  527. if ((capFcb->OpenCount == 0)
  528. || !FlagOn(capFcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET) ) {
  529. InfoStatus = MRxProxySyncXxxInformation(
  530. RxContext, //IN OUT PRX_CONTEXT RxContext,
  531. IRP_MJ_QUERY_INFORMATION, //IN UCHAR MajorFunction,
  532. proxySrvOpen->UnderlyingFileObject,//IN PFILE_OBJECT FileObject,
  533. FileBasicInformation, //IN ULONG InformationClass,
  534. sizeof(BasicInformation), //IN ULONG Length,
  535. &BasicInformation, //OUT PVOID Information,
  536. NULL); //OUT PULONG ReturnedLength OPTIONAL
  537. ASSERT (NT_SUCCESS(InfoStatus)); //BUGBUG what if not@!
  538. InfoStatus = MRxProxySyncXxxInformation(
  539. RxContext, //IN OUT PRX_CONTEXT RxContext,
  540. IRP_MJ_QUERY_INFORMATION, //IN UCHAR MajorFunction,
  541. proxySrvOpen->UnderlyingFileObject,//IN PFILE_OBJECT FileObject,
  542. FileStandardInformation, //IN ULONG InformationClass,
  543. sizeof(StandardInformation),//IN ULONG Length,
  544. &StandardInformation, //OUT PVOID Information,
  545. NULL); //OUT PULONG ReturnedLength OPTIONAL
  546. ASSERT (NT_SUCCESS(InfoStatus));
  547. if (StorageType == 0) {
  548. StorageType = StandardInformation.Directory?(FileTypeDirectory)
  549. :(FileTypeFile);
  550. RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
  551. }
  552. RxDbgTrace( 0, Dbg, ("FileSize %08lx\n", StandardInformation.EndOfFile.LowPart ));
  553. RxFinishFcbInitialization(
  554. capFcb,
  555. RDBSS_STORAGE_NTC(StorageType),
  556. RxFormInitPacket(
  557. InitPacket, //note no &
  558. &BasicInformation.FileAttributes,
  559. &StandardInformation.NumberOfLinks,
  560. &BasicInformation.CreationTime,
  561. &BasicInformation.LastAccessTime,
  562. &BasicInformation.LastWriteTime,
  563. &BasicInformation.ChangeTime,
  564. &StandardInformation.AllocationSize,
  565. &StandardInformation.EndOfFile,
  566. &StandardInformation.EndOfFile)
  567. );
  568. //if (!MRxLocalNoOplocks) MRxLocalRequestOplock(SrvOpen,MRxOplockRequestType,MRxRequestLevelII);
  569. //RxDbgTrace( 0, Dbg, ("MRxLocalCreate oplockstate =%08lx\n", localSrvOpen->OplockState ));
  570. //SrvOpen->BufferingFlags = MRxLocalTranslateStateToBufferMode[localSrvOpen->OplockState];
  571. SrvOpen->BufferingFlags |= FCB_STATE_COLLAPSING_ENABLED; //this can be turned off in the write path
  572. }
  573. }
  574. if (Status == STATUS_SUCCESS) {
  575. RxContext->pFobx = RxCreateNetFobx( RxContext, SrvOpen);
  576. if (!RxContext->pFobx) {
  577. NTSTATUS PostedCloseStatus;
  578. PostedCloseStatus = MRxProxyPostOperation(
  579. RxContext,
  580. ((PVOID)SrvOpen),
  581. MRxProxyPostedCloseHandle );
  582. ObDereferenceObject(proxySrvOpen->UnderlyingFileObject);
  583. }
  584. }
  585. //note.........collapsing IS enabled on fcb but not on any srvopen........
  586. SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHEING_ENABLED |
  587. FCB_STATE_FILESIZECACHEING_ENABLED |
  588. FCB_STATE_FILETIMECACHEING_ENABLED |
  589. FCB_STATE_WRITEBUFFERING_ENABLED |
  590. FCB_STATE_LOCK_BUFFERING_ENABLED |
  591. FCB_STATE_READBUFFERING_ENABLED |
  592. FCB_STATE_READCACHEING_ENABLED );
  593. ASSERT(Status != (STATUS_PENDING));
  594. ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
  595. RxDbgTrace(-1, Dbg, ("MRxProxyCreate %08lx exit with status=%08lx\n", RxContext, Status ));
  596. return(Status);
  597. }
  598. NTSTATUS
  599. MRxProxyCollapseOpen(
  600. IN OUT PRX_CONTEXT RxContext
  601. )
  602. /*++
  603. Routine Description:
  604. This routine collapses a open locally
  605. Arguments:
  606. RxContext - the RDBSS context
  607. Return Value:
  608. RXSTATUS - The return status for the operation
  609. --*/
  610. {
  611. NTSTATUS Status;
  612. RxCaptureFcb;
  613. //RX_BLOCK_CONDITION FinalSrvOpenCondition;
  614. PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
  615. PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
  616. PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
  617. ASSERT(FALSE);
  618. RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
  619. if (RxContext->pFobx != NULL) {
  620. ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
  621. RxContext->pFobx->OffsetOfNextEaToReturn = 1;
  622. Status = STATUS_SUCCESS;
  623. } else {
  624. Status = (STATUS_INSUFFICIENT_RESOURCES);
  625. //DbgBreakPoint();
  626. }
  627. return Status;
  628. }
  629. NTSTATUS
  630. MRxProxyComputeNewBufferingState(
  631. IN OUT PMRX_SRV_OPEN pMRxSrvOpen,
  632. IN PVOID pMRxContext,
  633. OUT PULONG pNewBufferingState)
  634. /*++
  635. Routine Description:
  636. This routine maps the PROXY specific oplock levels into the appropriate RDBSS
  637. buffering state flags
  638. Arguments:
  639. pMRxSrvOpen - the MRX SRV_OPEN extension
  640. pMRxContext - the context passed to RDBSS at Oplock indication time
  641. pNewBufferingState - the place holder for the new buffering state
  642. Return Value:
  643. Notes:
  644. --*/
  645. {
  646. //ULONG OplockLevel;
  647. ULONG NewBufferingState;
  648. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(pMRxSrvOpen);
  649. PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(pMRxSrvOpen->pFcb);
  650. ASSERT(pNewBufferingState != NULL);
  651. #if 0
  652. OplockLevel = (ULONG)pMRxContext;
  653. if (OplockLevel == PROXY_OPLOCK_LEVEL_II) {
  654. NewBufferingState = (FCB_STATE_READBUFFERING_ENABLED |
  655. FCB_STATE_READCACHEING_ENABLED);
  656. } else {
  657. NewBufferingState = 0;
  658. }
  659. #endif //0
  660. NewBufferingState = 0;
  661. pMRxSrvOpen->BufferingFlags = NewBufferingState;
  662. MRxProxyMungeBufferingIfWriteOnlyHandles(
  663. proxyFcb->WriteOnlySrvOpenCount,
  664. pMRxSrvOpen);
  665. *pNewBufferingState = pMRxSrvOpen->BufferingFlags;
  666. return STATUS_SUCCESS;
  667. }
  668. //-----------------------------------------------------------------------------------------------------
  669. //-----------------------------------------------------------------------------------------------------
  670. //-----------------------------------------------------------------------------------------------------
  671. //-----------------------------------------------------------------------------------------------------
  672. //-----------------------------------------------------------------------------------------------------
  673. //-----------------------------------------------------------------------------------------------------
  674. //-----------------------------------------------------------------------------------------------------
  675. //-----------------------------------------------------------------------------------------------------
  676. //-----------------------------------------------------------------------------------------------------
  677. //-----------------------------------------------------------------------------------------------------
  678. //-----------------------------------------------------------------------------------------------------
  679. //-----------------------------------------------------------------------------------------------------
  680. NTSTATUS
  681. MRxProxyZeroExtend(
  682. IN PRX_CONTEXT pRxContext)
  683. /*++
  684. Routine Description:
  685. This routine extends the data stream of a file system object
  686. Arguments:
  687. pRxContext - the RDBSS context
  688. Return Value:
  689. RXSTATUS - The return status for the operation
  690. --*/
  691. {
  692. return STATUS_NOT_IMPLEMENTED;
  693. }
  694. NTSTATUS
  695. MRxProxyTruncate(
  696. IN PRX_CONTEXT pRxContext)
  697. /*++
  698. Routine Description:
  699. This routine truncates the contents of a file system object
  700. Arguments:
  701. pRxContext - the RDBSS context
  702. Return Value:
  703. RXSTATUS - The return status for the operation
  704. --*/
  705. {
  706. ASSERT(!"Found a truncate");
  707. return STATUS_NOT_IMPLEMENTED;
  708. }
  709. NTSTATUS
  710. MRxProxyCleanupFobx(
  711. IN PRX_CONTEXT RxContext)
  712. /*++
  713. Routine Description:
  714. This routine cleansup a file system object...normally a noop. unless it's a pipe in which case
  715. we do the close at cleanup time and mark the file as being not open.
  716. Arguments:
  717. pRxContext - the RDBSS context
  718. Return Value:
  719. RXSTATUS - The return status for the operation
  720. --*/
  721. {
  722. NTSTATUS Status = STATUS_SUCCESS;
  723. RxCaptureFcb; RxCaptureFobx;
  724. PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
  725. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  726. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  727. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  728. //PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
  729. //PMRX_PROXY_FOBX proxyFobx = MRxProxyGetFileObjectExtension(capFobx);
  730. PAGED_CODE();
  731. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  732. ASSERT ( NodeTypeIsFcb(capFcb) );
  733. ASSERT (FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT));
  734. ASSERT (proxySrvOpen->UnderlyingFileObject);
  735. //if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) {
  736. // RxDbgTrace(-1, Dbg, ("File orphaned\n"));
  737. // return (STATUS_SUCCESS);
  738. //}
  739. //
  740. // if more fobxs are using this srvopen then just get out.
  741. // otherwise close the handle to trigger the underlying cleanup
  742. if (SrvOpen->UncleanFobxCount > 1) { return Status; }
  743. RxDbgTrace(+1, Dbg, ("MRxProxyCleanup %wZ\n", RemainingName ));
  744. RxLog(("ProxyCleanup %lx",SrvOpen));
  745. //because we only have one handle onthe file....we do nothing for each
  746. //individual handle being closed. in this way we avoid doing paging ios!
  747. //we close the handle when the final close for the fcb comes down.
  748. RxDbgTrace(-1, Dbg, ("MRxProxyCleanup exit with status=%08lx\n", Status ));
  749. return(Status);
  750. }
  751. NTSTATUS
  752. MRxProxyForcedClose(
  753. IN PMRX_SRV_OPEN pSrvOpen)
  754. /*++
  755. Routine Description:
  756. This routine closes a file system object
  757. Arguments:
  758. pSrvOpen - the instance to be closed
  759. Return Value:
  760. RXSTATUS - The return status for the operation
  761. Notes:
  762. --*/
  763. {
  764. return STATUS_NOT_IMPLEMENTED;
  765. }
  766. //-----------------------------------------------------------------------------------------------------
  767. //-----------------------------------------------------------------------------------------------------
  768. //-----------------------------------------------------------------------------------------------------
  769. //------------close close close close close close close --------------------------------
  770. //------------close close close close close close close --------------------------------
  771. //------------close close close close close close close --------------------------------
  772. //------------close close close close close close close --------------------------------
  773. //-----------------------------------------------------------------------------------------------------
  774. //-----------------------------------------------------------------------------------------------------
  775. //-----------------------------------------------------------------------------------------------------
  776. //-----------------------------------------------------------------------------------------------------
  777. //-----------------------------------------------------------------------------------------------------
  778. //-----------------------------------------------------------------------------------------------------
  779. //-----------------------------------------------------------------------------------------------------
  780. //-----------------------------------------------------------------------------------------------------
  781. //
  782. // The local debug trace level
  783. //
  784. #undef Dbg
  785. #define Dbg (DEBUG_TRACE_CLOSE)
  786. NTSTATUS
  787. MRxProxyCloseSrvOpen(
  788. IN PRX_CONTEXT RxContext
  789. )
  790. /*++
  791. Routine Description:
  792. This routine closes a file across the network
  793. Arguments:
  794. RxContext - the RDBSS context
  795. Return Value:
  796. RXSTATUS - The return status for the operation
  797. --*/
  798. {
  799. NTSTATUS Status = STATUS_SUCCESS;
  800. RxCaptureFcb;
  801. RxCaptureFobx;
  802. PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
  803. NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
  804. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  805. PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
  806. //PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
  807. //PMRX_PROXY_FOBX proxyFobx = MRxProxyGetFileObjectExtension(capFobx);
  808. //IO_STATUS_BLOCK Iosb;
  809. //PMINIRDR_OPLOCK_COMPLETION_CONTEXT cc = localSrvOpen->Mocc;
  810. //KIRQL oldIrql;
  811. //BOOLEAN OplockBreakPending;
  812. PAGED_CODE();
  813. ASSERT ( NodeTypeIsFcb(capFcb) );
  814. ASSERT ( SrvOpen->OpenCount == 0 );
  815. ASSERT (proxySrvOpen->UnderlyingFileObject);
  816. //if (capFcb->OpenCount > 0) { return STATUS_SUCCESS;}
  817. RxDbgTrace(+1, Dbg, ("MRxProxyClose %wZ\n", RemainingName ));
  818. RxLog(("ProxyClose fobx=%lx",capFobx));
  819. //if (proxySrvOpen->DeferredOpenContext != NULL) {
  820. // RxFreePool(proxySrvOpen->DeferredOpenContext);
  821. //}
  822. //if ((FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED))) {
  823. // RxDbgTrace(-1, Dbg, ("File orphan\n"));
  824. // return (STATUS_SUCCESS);
  825. //}
  826. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  827. #if 0
  828. IF WE REENABLE THIS, DONT USE IOSETINFO...USE MRxProxySyncXxxInformation INSTEAD
  829. // first we set the real filesize.....our pagingIos may have extended it
  830. // to a page boundary.........
  831. if ( NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE ) {
  832. FILE_END_OF_FILE_INFORMATION EndOfFileInformation;
  833. EndOfFileInformation.EndOfFile = capFcb->Header.FileSize;
  834. Status = IxxoSetInformation(
  835. proxySrvOpen->UnderlyingFileObject, //IN PFILE_OBJECT FileObject,
  836. FileEndOfFileInformation, //IN FILE_INFORMATION_CLASS FileInformationClass,
  837. sizeof(EndOfFileInformation), //IN ULONG Length,
  838. &EndOfFileInformation //IN PVOID FileInformation
  839. );
  840. }
  841. //if bad status....keep going anyway........
  842. #endif
  843. // next, we close our handle..........
  844. Status = MRxProxyPostOperation(
  845. RxContext,
  846. ((PVOID)SrvOpen),
  847. MRxProxyPostedCloseHandle );
  848. // then, we remove our reference..........
  849. if (proxySrvOpen->UnderlyingFileObject) {
  850. RxDbgTrace( 0, Dbg, ("ProxyClose Attempt to close %wZ\n", &(capFcb->AlreadyPrefixedName) ));
  851. //if (cc) {
  852. // ASSERTMSG("Joejoe the right way to do this would be to CANCEL!!!!!!!!",FALSE);
  853. // //since this is a force closed, we get rid of a pending break
  854. // KeAcquireSpinLock( &MrxLocalOplockSpinLock, &oldIrql );
  855. // OplockBreakPending = cc->OplockBreakPending;
  856. // if (!OplockBreakPending) {
  857. // cc->SrvOpen = NULL;
  858. // }
  859. // KeReleaseSpinLock( &MrxLocalOplockSpinLock, oldIrql );
  860. // if (!OplockBreakPending) {
  861. // //gotta lose the spinlock befoer the call
  862. // RxDereferenceSrvOpen(SrvOpen); //elim ref!
  863. // }
  864. //} else {
  865. // ASSERT (localSrvOpen->OplockState == OplockStateNone);
  866. //}
  867. RxLog(("MRxProxyClose %lx %lx",capFcb,capFobx));
  868. //DbgPrint("MRxProxyClose %lx %lx\n",capFcb,capFobx);
  869. ObDereferenceObject(proxySrvOpen->UnderlyingFileObject);
  870. proxySrvOpen->UnderlyingFileObject = NULL;
  871. }
  872. Status = STATUS_SUCCESS;
  873. RxDbgTrace(-1, Dbg, ("MRxProxyClose exit with status=%08lx\n", Status ));
  874. return(Status);
  875. }
  876.