3 * Copyright (C) 2017 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: sdk/lib/drivers/rdbsslib/rdbss.c
23 * PURPOSE: RDBSS library
24 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
27 /* INCLUDES *****************************************************************/
30 #include <pseh/pseh2.h>
38 #define RX_TOPLEVELCTX_FLAG_FROM_POOL 1
42 (NTAPI
*PRX_FSD_DISPATCH
) (
45 typedef struct _RX_FSD_DISPATCH_VECTOR
47 PRX_FSD_DISPATCH CommonRoutine
;
48 } RX_FSD_DISPATCH_VECTOR
, *PRX_FSD_DISPATCH_VECTOR
;
52 RxAcquireFileForNtCreateSection(
53 PFILE_OBJECT FileObject
);
58 PFILE_OBJECT FileObject
,
59 PDEVICE_OBJECT DeviceObject
);
62 RxAddToTopLevelIrpAllocatedContextsList(
63 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
);
89 RxCommonDevFCBCleanup(
100 PRX_CONTEXT Context
);
105 PRX_CONTEXT Context
);
109 RxCommonDevFCBQueryVolInfo(
110 PRX_CONTEXT Context
);
114 RxCommonDeviceControl(
115 PRX_CONTEXT Context
);
119 RxCommonDirectoryControl(
120 PRX_CONTEXT Context
);
124 RxCommonDispatchProblem(
125 PRX_CONTEXT Context
);
129 RxCommonFileSystemControl(
130 PRX_CONTEXT Context
);
134 RxCommonFlushBuffers(
135 PRX_CONTEXT Context
);
140 PRX_CONTEXT Context
);
145 PRX_CONTEXT Context
);
149 RxCommonQueryInformation(
150 PRX_CONTEXT Context
);
154 RxCommonQueryQuotaInformation(
155 PRX_CONTEXT Context
);
159 RxCommonQuerySecurity(
160 PRX_CONTEXT Context
);
164 RxCommonQueryVolumeInformation(
165 PRX_CONTEXT Context
);
170 PRX_CONTEXT Context
);
175 PRX_CONTEXT Context
);
179 RxCommonSetInformation(
180 PRX_CONTEXT Context
);
184 RxCommonSetQuotaInformation(
185 PRX_CONTEXT Context
);
190 PRX_CONTEXT Context
);
194 RxCommonSetVolumeInformation(
195 PRX_CONTEXT Context
);
199 RxCommonUnimplemented(
200 PRX_CONTEXT Context
);
205 PRX_CONTEXT Context
);
208 RxCopyCreateParameters(
209 IN PRX_CONTEXT RxContext
);
214 PUNICODE_STRING NetRootName
);
218 IN PRX_CONTEXT RxContext
);
222 RxFastIoCheckIfPossible(
223 PFILE_OBJECT FileObject
,
224 PLARGE_INTEGER FileOffset
,
225 ULONG Length
, BOOLEAN Wait
,
226 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
227 PIO_STATUS_BLOCK IoStatus
,
228 PDEVICE_OBJECT DeviceObject
);
232 RxFastIoDeviceControl(
233 PFILE_OBJECT FileObject
,
235 PVOID InputBuffer OPTIONAL
,
236 ULONG InputBufferLength
,
237 PVOID OutputBuffer OPTIONAL
,
238 ULONG OutputBufferLength
,
240 PIO_STATUS_BLOCK IoStatus
,
241 PDEVICE_OBJECT DeviceObject
);
246 PFILE_OBJECT FileObject
,
247 PLARGE_INTEGER FileOffset
,
252 PIO_STATUS_BLOCK IoStatus
,
253 PDEVICE_OBJECT DeviceObject
);
258 PFILE_OBJECT FileObject
,
259 PLARGE_INTEGER FileOffset
,
264 PIO_STATUS_BLOCK IoStatus
,
265 PDEVICE_OBJECT DeviceObject
);
269 PRX_CONTEXT RxContext
,
270 PUNICODE_STRING NetRootName
);
274 PRX_CONTEXT RxContext
,
275 PUNICODE_STRING FileName
,
276 PUNICODE_STRING CanonicalName
,
277 PNET_ROOT_TYPE NetRootType
);
280 RxFreeCanonicalNameBuffer(
281 PRX_CONTEXT Context
);
290 RxGetRegistryParameters(
291 IN PUNICODE_STRING RegistryPath
);
295 RxGetStringRegistryParameter(
298 OUT PUNICODE_STRING OutString
,
300 IN ULONG BufferLength
,
301 IN BOOLEAN LogFailure
);
305 RxInitializeDebugSupport(
310 RxInitializeDispatchVectors(
311 PDRIVER_OBJECT DriverObject
);
315 RxInitializeRegistrationStructures(
320 RxInitializeTopLevelIrpPackage(
326 PDRIVER_OBJECT DriverObject
,
330 RxIsThisAnRdbssTopLevelContext(
331 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
);
335 RxLowIoIoCtlShellCompletion(
336 PRX_CONTEXT RxContext
);
340 PRX_CONTEXT RxContext
);
344 RxLowIoReadShellCompletion(
345 PRX_CONTEXT RxContext
);
349 IN PRX_CONTEXT RxContext
);
353 RxLowIoWriteShellCompletion(
354 PRX_CONTEXT RxContext
);
358 PRX_CONTEXT RxContext
);
361 RxNotifyChangeDirectory(
362 PRX_CONTEXT RxContext
);
366 PRX_CONTEXT RxContext
,
367 FILE_INFORMATION_CLASS FileInfoClass
,
373 PRX_CONTEXT LocalContext
);
376 RxQueryAlternateNameInfo(
377 PRX_CONTEXT RxContext
,
378 PFILE_NAME_INFORMATION AltNameInfo
);
382 PRX_CONTEXT RxContext
,
383 PFILE_BASIC_INFORMATION BasicInfo
);
386 RxQueryCompressedInfo(
387 PRX_CONTEXT RxContext
,
388 PFILE_COMPRESSION_INFORMATION CompressionInfo
);
392 PRX_CONTEXT RxContext
);
396 PRX_CONTEXT RxContext
,
397 PFILE_EA_INFORMATION EaInfo
);
401 PRX_CONTEXT RxContext
,
402 PFILE_INTERNAL_INFORMATION InternalInfo
);
406 PRX_CONTEXT RxContext
,
407 PFILE_NAME_INFORMATION NameInfo
);
411 PRX_CONTEXT RxContext
,
412 PFILE_PIPE_INFORMATION PipeInfo
);
416 PRX_CONTEXT RxContext
,
417 PFILE_POSITION_INFORMATION PositionInfo
);
421 PRX_CONTEXT RxContext
,
422 PFILE_STANDARD_INFORMATION StandardInfo
);
426 RxReadRegistryParameters(
431 RxReleaseFileForNtCreateSection(
432 PFILE_OBJECT FileObject
);
437 PFILE_OBJECT FileObject
,
438 PDEVICE_OBJECT DeviceObject
);
441 RxRemoveOverflowEntry(
442 PRDBSS_DEVICE_OBJECT DeviceObject
,
443 WORK_QUEUE_TYPE Queue
);
446 RxSearchForCollapsibleOpen(
447 PRX_CONTEXT RxContext
,
448 ACCESS_MASK DesiredAccess
,
453 PRX_CONTEXT RxContext
);
457 PRX_CONTEXT RxContext
);
460 RxSetDispositionInfo(
461 PRX_CONTEXT RxContext
);
465 PRX_CONTEXT RxContext
);
469 PRX_CONTEXT RxContext
);
473 PRX_CONTEXT RxContext
);
477 PRX_CONTEXT RxContext
);
481 PRX_CONTEXT RxContext
);
484 RxSetupNetFileObject(
485 PRX_CONTEXT RxContext
);
489 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
493 RxUninitializeCacheMap(
494 PRX_CONTEXT RxContext
,
495 PFILE_OBJECT FileObject
,
496 PLARGE_INTEGER TruncateSize
);
501 PRDBSS_DEVICE_OBJECT DeviceObject
);
504 RxXXXControlFileCallthru(
505 PRX_CONTEXT Context
);
509 _RxAllocatePoolWithTag(
510 _In_ POOL_TYPE PoolType
,
511 _In_ SIZE_T NumberOfBytes
,
525 WCHAR RxStarForTemplate
= '*';
526 WCHAR Rx8QMdot3QM
[] = L
">>>>>>>>.>>>*";
527 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles
= FALSE
;
528 BOOLEAN DisableFlushOnCleanup
= FALSE
;
529 ULONG ReadAheadGranularity
= 1 << PAGE_SHIFT
;
530 LIST_ENTRY RxActiveContexts
;
531 NPAGED_LOOKASIDE_LIST RxContextLookasideList
;
532 FAST_MUTEX RxContextPerFileSerializationMutex
;
535 BOOLEAN RxLoudLowIoOpsEnabled
= FALSE
;
536 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
538 { RxCommonDispatchProblem
},
539 { RxCommonDispatchProblem
},
540 { RxCommonDevFCBClose
},
541 { RxCommonDispatchProblem
},
542 { RxCommonDispatchProblem
},
543 { RxCommonDispatchProblem
},
544 { RxCommonDispatchProblem
},
545 { RxCommonDispatchProblem
},
546 { RxCommonDispatchProblem
},
547 { RxCommonDispatchProblem
},
548 { RxCommonDevFCBQueryVolInfo
},
549 { RxCommonDispatchProblem
},
550 { RxCommonDispatchProblem
},
551 { RxCommonDevFCBFsCtl
},
552 { RxCommonDevFCBIoCtl
},
553 { RxCommonDevFCBIoCtl
},
554 { RxCommonDispatchProblem
},
555 { RxCommonDispatchProblem
},
556 { RxCommonDevFCBCleanup
},
557 { RxCommonDispatchProblem
},
558 { RxCommonDispatchProblem
},
559 { RxCommonDispatchProblem
},
560 { RxCommonUnimplemented
},
561 { RxCommonUnimplemented
},
562 { RxCommonUnimplemented
},
563 { RxCommonUnimplemented
},
564 { RxCommonUnimplemented
},
565 { RxCommonUnimplemented
},
567 RDBSS_EXPORTS RxExports
;
568 FAST_IO_DISPATCH RxFastIoDispatch
;
569 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject
;
570 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
573 { RxCommonUnimplemented
},
577 { RxCommonQueryInformation
},
578 { RxCommonSetInformation
},
581 { RxCommonFlushBuffers
},
582 { RxCommonQueryVolumeInformation
},
583 { RxCommonSetVolumeInformation
},
584 { RxCommonDirectoryControl
},
585 { RxCommonFileSystemControl
},
586 { RxCommonDeviceControl
},
587 { RxCommonDeviceControl
},
588 { RxCommonUnimplemented
},
589 { RxCommonLockControl
},
591 { RxCommonUnimplemented
},
592 { RxCommonQuerySecurity
},
593 { RxCommonSetSecurity
},
594 { RxCommonUnimplemented
},
595 { RxCommonUnimplemented
},
596 { RxCommonUnimplemented
},
597 { RxCommonQueryQuotaInformation
},
598 { RxCommonSetQuotaInformation
},
599 { RxCommonUnimplemented
},
601 ULONG RxFsdEntryCount
;
602 LIST_ENTRY RxIrpsList
;
603 KSPIN_LOCK RxIrpsListSpinLock
;
604 KMUTEX RxScavengerMutex
;
605 KMUTEX RxSerializationMutex
;
606 UCHAR RxSpaceForTheWrappersDeviceObject
[sizeof(*RxFileSystemDeviceObject
)];
607 KSPIN_LOCK TopLevelIrpSpinLock
;
608 LIST_ENTRY TopLevelIrpAllocatedContextsList
;
609 BOOLEAN RxForceQFIPassThrough
= FALSE
;
610 BOOLEAN RxNoAsync
= FALSE
;
612 DECLARE_CONST_UNICODE_STRING(unknownId
, L
"???");
619 #define ASSERT(exp) \
622 RxAssert(#exp, __FILE__, __LINE__, NULL); \
627 #undef RxAllocatePool
628 #undef RxAllocatePoolWithTag
631 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
632 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
633 #define RxFreePool _RxFreePool
634 #define RxFreePoolWithTag _RxFreePoolWithTag
637 /* FUNCTIONS ****************************************************************/
643 CheckForLoudOperations(
644 PRX_CONTEXT RxContext
)
648 #define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
650 /* Are loud operations enabled? */
651 if (RxLoudLowIoOpsEnabled
)
655 /* If so, the operation will be loud only if filename ends with all.scr */
656 Fcb
= (PFCB
)RxContext
->pFcb
;
657 if (RtlCompareMemory(Add2Ptr(Fcb
->PrivateAlreadyPrefixedName
.Buffer
, (Fcb
->PrivateAlreadyPrefixedName
.Length
- ALLSCR_LENGTH
)),
658 L
"all.scr", ALLSCR_LENGTH
) == ALLSCR_LENGTH
)
660 SetFlag(RxContext
->LowIoContext
.Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
);
670 __RxInitializeTopLevelIrpContext(
671 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
673 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
676 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext
, Irp
, RxDeviceObject
, Flags
);
678 RtlZeroMemory(TopLevelContext
, sizeof(RX_TOPLEVELIRP_CONTEXT
));
679 TopLevelContext
->Irp
= Irp
;
680 TopLevelContext
->Flags
= (Flags
? RX_TOPLEVELCTX_FLAG_FROM_POOL
: 0);
681 TopLevelContext
->Signature
= RX_TOPLEVELIRP_CONTEXT_SIGNATURE
;
682 TopLevelContext
->RxDeviceObject
= RxDeviceObject
;
683 TopLevelContext
->Previous
= IoGetTopLevelIrp();
684 TopLevelContext
->Thread
= PsGetCurrentThread();
686 /* We cannot add to list something that'd come from stack */
687 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
689 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext
);
697 __RxWriteReleaseResources(
698 PRX_CONTEXT RxContext
,
699 BOOLEAN ResourceOwnerSet
,
708 ASSERT(RxContext
!= NULL
);
710 Fcb
= (PFCB
)RxContext
->pFcb
;
713 /* If FCB resource was acquired, release it */
714 if (RxContext
->FcbResourceAcquired
)
716 /* Taking care of owner */
717 if (ResourceOwnerSet
)
719 RxReleaseFcbForThread(RxContext
, Fcb
, RxContext
->LowIoContext
.ResourceThreadId
);
723 RxReleaseFcb(RxContext
, Fcb
);
726 RxContext
->FcbResourceAcquired
= FALSE
;
729 /* If FCB paging resource was acquired, release it */
730 if (RxContext
->FcbPagingIoResourceAcquired
)
732 /* Taking care of owner */
733 if (ResourceOwnerSet
)
735 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, RxContext
->LowIoContext
.ResourceThreadId
);
739 RxReleasePagingIoResource(RxContext
, Fcb
);
742 /* No need to release boolean here, RxReleasePagingIoResource() takes care of it */
750 RxAddToTopLevelIrpAllocatedContextsList(
751 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
755 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext
);
757 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
758 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
760 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
761 InsertTailList(&TopLevelIrpAllocatedContextsList
, &TopLevelContext
->ListEntry
);
762 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
771 IN PRX_CONTEXT RxContext
,
776 WORK_QUEUE_TYPE Queue
;
777 PIO_STACK_LOCATION Stack
;
779 Stack
= RxContext
->CurrentIrpSp
;
780 RxContext
->PostRequest
= FALSE
;
782 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
783 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
&&
784 Stack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
786 Queue
= DelayedWorkQueue
;
787 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
);
791 Queue
= CriticalWorkQueue
;
792 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
);
795 /* Check for overflow */
796 if (Stack
->FileObject
!= NULL
)
798 KeAcquireSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
800 Queued
= InterlockedIncrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
801 /* In case of an overflow, add the new queued call to the overflow list */
804 InterlockedDecrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
805 InsertTailList(&RxFileSystemDeviceObject
->OverflowQueue
[Queue
], &RxContext
->OverflowListEntry
);
806 ++RxFileSystemDeviceObject
->OverflowQueueCount
[Queue
];
808 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
812 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
815 ExInitializeWorkItem(&RxContext
->WorkQueueItem
, RxFspDispatch
, RxContext
);
816 ExQueueWorkItem((PWORK_QUEUE_ITEM
)&RxContext
->WorkQueueItem
, Queue
);
823 RxAdjustFileTimesAndSize(
829 PFILE_OBJECT FileObject
;
830 LARGE_INTEGER CurrentTime
;
831 FILE_BASIC_INFORMATION FileBasicInfo
;
832 FILE_END_OF_FILE_INFORMATION FileEOFInfo
;
833 BOOLEAN FileModified
, SetLastChange
, SetLastAccess
, SetLastWrite
, NeedUpdate
;
837 FileObject
= Context
->CurrentIrpSp
->FileObject
;
838 /* If Cc isn't initialized, the file was not read nor written, nothing to do */
839 if (FileObject
->PrivateCacheMap
== NULL
)
845 KeQuerySystemTime(&CurrentTime
);
847 Fobx
= (PFOBX
)Context
->pFobx
;
848 /* Was the file modified? */
849 FileModified
= BooleanFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
);
850 /* We'll set last write if it was modified and user didn't update yet */
851 SetLastWrite
= FileModified
&& !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_WRITE
);
852 /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
853 SetLastAccess
= SetLastWrite
||
854 (BooleanFlagOn(FileObject
->Flags
, FO_FILE_FAST_IO_READ
) &&
855 !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_ACCESS
));
856 /* We'll set last change if it was modified and user didn't update yet */
857 SetLastChange
= FileModified
&& !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_CHANGE
);
859 /* Nothing to update? Job done */
860 if (!FileModified
&& !SetLastWrite
&& !SetLastAccess
&& !SetLastChange
)
865 Fcb
= (PFCB
)Context
->pFcb
;
866 /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
868 RtlZeroMemory(&FileBasicInfo
, sizeof(FileBasicInfo
));
870 /* Update lastwrite time if required */
874 Fcb
->LastWriteTime
.QuadPart
= CurrentTime
.QuadPart
;
875 FileBasicInfo
.LastWriteTime
.QuadPart
= CurrentTime
.QuadPart
;
878 /* Update lastaccess time if required */
882 Fcb
->LastAccessTime
.QuadPart
= CurrentTime
.QuadPart
;
883 FileBasicInfo
.LastAccessTime
.QuadPart
= CurrentTime
.QuadPart
;
886 /* Update lastchange time if required */
890 Fcb
->LastChangeTime
.QuadPart
= CurrentTime
.QuadPart
;
891 FileBasicInfo
.ChangeTime
.QuadPart
= CurrentTime
.QuadPart
;
894 /* If one of the date was modified, issue a call to mini-rdr */
897 Context
->Info
.FileInformationClass
= FileBasicInformation
;
898 Context
->Info
.Buffer
= &FileBasicInfo
;
899 Context
->Info
.Length
= sizeof(FileBasicInfo
);
901 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxSetFileInfoAtCleanup
, (Context
));
905 /* If the file was modified, update its EOF */
908 FileEOFInfo
.EndOfFile
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
910 Context
->Info
.FileInformationClass
= FileEndOfFileInformation
;
911 Context
->Info
.Buffer
= &FileEOFInfo
;
912 Context
->Info
.Length
= sizeof(FileEOFInfo
);
914 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxSetFileInfoAtCleanup
, (Context
));
923 RxAllocateCanonicalNameBuffer(
924 PRX_CONTEXT RxContext
,
925 PUNICODE_STRING CanonicalName
,
926 USHORT CanonicalLength
)
930 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext
, RxContext
->Create
.CanonicalNameBuffer
);
932 /* Context must be free of any already allocated name */
933 ASSERT(RxContext
->Create
.CanonicalNameBuffer
== NULL
);
935 /* Validate string length */
936 if (CanonicalLength
> USHRT_MAX
- 1)
938 CanonicalName
->Buffer
= NULL
;
939 return STATUS_OBJECT_PATH_INVALID
;
942 CanonicalName
->Buffer
= RxAllocatePoolWithTag(PagedPool
| POOL_COLD_ALLOCATION
, CanonicalLength
, RX_MISC_POOLTAG
);
943 if (CanonicalName
->Buffer
== NULL
)
945 return STATUS_INSUFFICIENT_RESOURCES
;
948 CanonicalName
->Length
= 0;
949 CanonicalName
->MaximumLength
= CanonicalLength
;
951 /* Set the two places - they must always be identical */
952 RxContext
->Create
.CanonicalNameBuffer
= CanonicalName
->Buffer
;
953 RxContext
->AlsoCanonicalNameBuffer
= CanonicalName
->Buffer
;
955 return STATUS_SUCCESS
;
962 RxCancelNotifyChangeDirectoryRequestsForFobx(
968 LIST_ENTRY ContextsToCancel
;
970 /* Init a list for the contexts to cancel */
971 InitializeListHead(&ContextsToCancel
);
973 /* Lock our list lock */
974 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
976 /* Now, browse all the active contexts, to find the associated ones */
977 Entry
= RxActiveContexts
.Flink
;
978 while (Entry
!= &RxActiveContexts
)
980 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
981 Entry
= Entry
->Flink
;
983 /* Not the IRP we're looking for, ignore */
984 if (Context
->MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
||
985 Context
->MinorFunction
!= IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
990 /* Not the FOBX we're looking for, ignore */
991 if ((PFOBX
)Context
->pFobx
!= Fobx
)
996 /* No cancel routine (can't be cancel, then), ignore */
997 if (Context
->MRxCancelRoutine
== NULL
)
1002 /* Mark our context as cancelled */
1003 SetFlag(Context
->Flags
, RX_CONTEXT_FLAG_CANCELLED
);
1005 /* Move it to our list */
1006 RemoveEntryList(&Context
->ContextListEntry
);
1007 InsertTailList(&ContextsToCancel
, &Context
->ContextListEntry
);
1009 InterlockedIncrement((volatile long *)&Context
->ReferenceCount
);
1012 /* Done with the contexts */
1013 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
1015 /* Now, handle all our "extracted" contexts */
1016 while (!IsListEmpty(&ContextsToCancel
))
1018 Entry
= RemoveHeadList(&ContextsToCancel
);
1019 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
1021 /* If they had an associated IRP (should be always true) */
1022 if (Context
->CurrentIrp
!= NULL
)
1024 /* Then, call cancel routine */
1025 ASSERT(Context
->MRxCancelRoutine
!= NULL
);
1026 DPRINT1("Canceling %p with %p\n", Context
, Context
->MRxCancelRoutine
);
1027 Context
->MRxCancelRoutine(Context
);
1030 /* And delete the context */
1031 RxDereferenceAndDeleteRxContext(Context
);
1039 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
1040 PV_NET_ROOT VNetRoot
,
1041 BOOLEAN ForceFilesClosed
)
1046 PRX_CONTEXT Context
;
1047 LIST_ENTRY ContextsToCancel
;
1049 /* Init a list for the contexts to cancel */
1050 InitializeListHead(&ContextsToCancel
);
1052 /* Lock our list lock */
1053 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
1055 /* Now, browse all the active contexts, to find the associated ones */
1056 Entry
= RxActiveContexts
.Flink
;
1057 while (Entry
!= &RxActiveContexts
)
1059 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
1060 Entry
= Entry
->Flink
;
1062 /* Not the IRP we're looking for, ignore */
1063 if (Context
->MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
||
1064 Context
->MinorFunction
!= IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
1069 /* Not the VNetRoot we're looking for, ignore */
1070 if (Context
->pFcb
== NULL
||
1071 (PV_NET_ROOT
)Context
->NotifyChangeDirectory
.pVNetRoot
!= VNetRoot
)
1076 /* No cancel routine (can't be cancel, then), ignore */
1077 if (Context
->MRxCancelRoutine
== NULL
)
1082 /* At that point, we found a matching context
1083 * If we're not asked to force close, then fail - it's still open
1085 if (!ForceFilesClosed
)
1087 Status
= STATUS_FILES_OPEN
;
1091 /* Mark our context as cancelled */
1092 SetFlag(Context
->Flags
, RX_CONTEXT_FLAG_CANCELLED
);
1094 /* Move it to our list */
1095 RemoveEntryList(&Context
->ContextListEntry
);
1096 InsertTailList(&ContextsToCancel
, &Context
->ContextListEntry
);
1098 InterlockedIncrement((volatile long *)&Context
->ReferenceCount
);
1101 /* Done with the contexts */
1102 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
1104 if (Status
!= STATUS_SUCCESS
)
1109 /* Now, handle all our "extracted" contexts */
1110 while (!IsListEmpty(&ContextsToCancel
))
1112 Entry
= RemoveHeadList(&ContextsToCancel
);
1113 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
1115 /* If they had an associated IRP (should be always true) */
1116 if (Context
->CurrentIrp
!= NULL
)
1118 /* Then, call cancel routine */
1119 ASSERT(Context
->MRxCancelRoutine
!= NULL
);
1120 DPRINT1("Canceling %p with %p\n", Context
, Context
->MRxCancelRoutine
);
1121 Context
->MRxCancelRoutine(Context
);
1124 /* And delete the context */
1125 RxDereferenceAndDeleteRxContext(Context
);
1134 PDEVICE_OBJECT DeviceObject
,
1144 RxCanonicalizeFileNameByServerSpecs(
1145 PRX_CONTEXT RxContext
,
1146 PUNICODE_STRING NetRootName
)
1148 USHORT NextChar
, CurChar
;
1153 /* Validate file name is not empty */
1154 MaxChars
= NetRootName
->Length
/ sizeof(WCHAR
);
1157 return STATUS_MORE_PROCESSING_REQUIRED
;
1160 /* Validate name is correct */
1161 for (NextChar
= 0, CurChar
= 0; CurChar
+ 1 < MaxChars
; NextChar
= CurChar
+ 1)
1165 for (i
= NextChar
+ 1; i
< MaxChars
; ++i
)
1167 if (NetRootName
->Buffer
[i
] == '\\' || NetRootName
->Buffer
[i
] == ':')
1174 if (CurChar
== NextChar
)
1176 if (((NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':') || NextChar
== (MaxChars
- 1)) && NetRootName
->Buffer
[NextChar
] != '.')
1183 if (CurChar
>= MaxChars
- 1)
1188 if (NetRootName
->Buffer
[CurChar
+ 1] != ':')
1190 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1195 if (NetRootName
->Buffer
[1] != ':')
1197 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1203 if ((CurChar
- NextChar
) == 1)
1205 if (NetRootName
->Buffer
[NextChar
+ 2] != '.')
1210 if (NetRootName
->Buffer
[NextChar
] == '\\' || NetRootName
->Buffer
[NextChar
] == ':' || NetRootName
->Buffer
[NextChar
] == '.')
1212 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1217 if ((CurChar
- NextChar
) != 2 || (NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':')
1218 || NetRootName
->Buffer
[NextChar
+ 1] != '.')
1223 if (NetRootName
->Buffer
[NextChar
+ 2] == '.')
1225 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1231 return STATUS_MORE_PROCESSING_REQUIRED
;
1235 RxCanonicalizeNameAndObtainNetRoot(
1236 PRX_CONTEXT RxContext
,
1237 PUNICODE_STRING FileName
,
1238 PUNICODE_STRING NetRootName
)
1241 NET_ROOT_TYPE NetRootType
;
1242 UNICODE_STRING CanonicalName
;
1246 NetRootType
= NET_ROOT_WILD
;
1248 RtlInitEmptyUnicodeString(NetRootName
, NULL
, 0);
1249 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
1251 /* if not relative opening, just handle the passed name */
1252 if (RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
== NULL
)
1254 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1255 if (!NT_SUCCESS(Status
))
1264 /* Make sure we have a valid FCB and a FOBX */
1265 Fcb
= RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext
;
1267 RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext2
== NULL
)
1269 return STATUS_INVALID_PARAMETER
;
1272 if (!NodeTypeIsFcb(Fcb
))
1274 return STATUS_INVALID_PARAMETER
;
1280 /* Get/Create the associated VNetRoot for opening */
1281 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1282 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
&&
1283 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_MAILSLOT_REPARSE
))
1285 ASSERT(CanonicalName
.Buffer
== RxContext
->Create
.CanonicalNameBuffer
);
1287 RxFreeCanonicalNameBuffer(RxContext
);
1288 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1289 if (NT_SUCCESS(Status
))
1291 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1295 /* Filename cannot contain wildcards */
1296 if (FsRtlDoesNameContainWildCards(NetRootName
))
1298 Status
= STATUS_OBJECT_NAME_INVALID
;
1301 /* Make sure file name is correct */
1302 if (NT_SUCCESS(Status
))
1304 Status
= RxCanonicalizeFileNameByServerSpecs(RxContext
, NetRootName
);
1307 /* Give the mini-redirector a chance to prepare the name */
1308 if (NT_SUCCESS(Status
) || Status
== STATUS_MORE_PROCESSING_REQUIRED
)
1310 if (RxContext
->Create
.pNetRoot
!= NULL
)
1312 NTSTATUS IgnoredStatus
;
1314 MINIRDR_CALL(IgnoredStatus
, RxContext
, RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
1315 MRxPreparseName
, (RxContext
, NetRootName
));
1316 (void)IgnoredStatus
;
1325 RxCheckFcbStructuresForAlignment(
1333 _In_ ACCESS_MASK DesiredAccess
,
1334 _In_ ULONG DesiredShareAccess
,
1335 _Inout_ PFILE_OBJECT FileObject
,
1336 _Inout_ PSHARE_ACCESS ShareAccess
,
1337 _In_ BOOLEAN Update
,
1339 _In_ PSZ wherelogtag
)
1343 RxDumpWantedAccess(where
, "", wherelogtag
, DesiredAccess
, DesiredShareAccess
);
1344 RxDumpCurrentAccess(where
, "", wherelogtag
, ShareAccess
);
1346 return IoCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
, Update
);
1353 RxCheckShareAccessPerSrvOpens(
1355 IN ACCESS_MASK DesiredAccess
,
1356 IN ULONG DesiredShareAccess
)
1359 BOOLEAN WriteAccess
;
1360 BOOLEAN DeleteAccess
;
1361 PSHARE_ACCESS ShareAccess
;
1365 ShareAccess
= &Fcb
->ShareAccessPerSrvOpens
;
1367 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess
, DesiredShareAccess
);
1368 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess
);
1370 /* Check if any access wanted */
1371 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
1372 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
1373 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
1375 if (ReadAccess
|| WriteAccess
|| DeleteAccess
)
1377 BOOLEAN SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
1378 BOOLEAN SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
1379 BOOLEAN SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
1381 /* Check whether there's a violation */
1383 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
1385 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
1387 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
1388 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
1389 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
1390 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
1392 return STATUS_SHARING_VIOLATION
;
1396 return STATUS_SUCCESS
;
1400 RxCleanupPipeQueues(
1401 PRX_CONTEXT Context
)
1410 RxCloseAssociatedSrvOpen(
1412 IN PRX_CONTEXT RxContext OPTIONAL
)
1417 BOOLEAN CloseSrvOpen
;
1418 PRX_CONTEXT LocalContext
;
1422 /* Assume SRV_OPEN is already closed */
1423 CloseSrvOpen
= FALSE
;
1424 /* If we have a FOBX, we'll have to close it */
1427 /* If the FOBX isn't closed yet */
1428 if (!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
))
1430 SrvOpen
= Fobx
->SrvOpen
;
1431 Fcb
= (PFCB
)SrvOpen
->pFcb
;
1432 /* Check whether we've to close SRV_OPEN first */
1433 if (!BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1435 CloseSrvOpen
= TRUE
;
1439 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1441 /* Not much to do */
1442 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1444 if (SrvOpen
->OpenCount
> 0)
1446 --SrvOpen
->OpenCount
;
1451 /* No need to close SRV_OPEN, so close FOBX */
1454 RxMarkFobxOnClose(Fobx
);
1456 return STATUS_SUCCESS
;
1461 /* No FOBX? No RX_CONTEXT, ok, job done! */
1462 if (RxContext
== NULL
)
1464 return STATUS_SUCCESS
;
1467 /* Get the FCB from RX_CONTEXT */
1468 Fcb
= (PFCB
)RxContext
->pFcb
;
1472 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1473 if (RxContext
== NULL
)
1475 ASSERT(Fobx
!= NULL
);
1477 LocalContext
= RxCreateRxContext(NULL
, Fcb
->RxDeviceObject
, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING
| RX_CONTEXT_FLAG_WAIT
);
1478 if (LocalContext
== NULL
)
1480 return STATUS_INSUFFICIENT_RESOURCES
;
1483 LocalContext
->MajorFunction
= 2;
1484 LocalContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
1485 LocalContext
->pFobx
= (PMRX_FOBX
)Fobx
;
1486 LocalContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)Fobx
->SrvOpen
;
1490 LocalContext
= RxContext
;
1493 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1495 /* Now, close the FOBX */
1498 RxMarkFobxOnClose(Fobx
);
1502 InterlockedDecrement((volatile long *)&Fcb
->OpenCount
);
1505 /* If not a "standard" file, SRV_OPEN can be null */
1506 if (SrvOpen
== NULL
)
1508 ASSERT((NodeType(Fcb
) == RDBSS_NTC_OPENTARGETDIR_FCB
) || (NodeType(Fcb
) == RDBSS_NTC_IPC_SHARE
) || (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
));
1509 RxDereferenceNetFcb(Fcb
);
1511 if (LocalContext
!= RxContext
)
1513 RxDereferenceAndDeleteRxContext(LocalContext
);
1516 return STATUS_SUCCESS
;
1519 /* If SRV_OPEN isn't in a good condition, nothing to close */
1520 if (SrvOpen
->Condition
!= Condition_Good
)
1522 if (LocalContext
!= RxContext
)
1524 RxDereferenceAndDeleteRxContext(LocalContext
);
1527 return STATUS_SUCCESS
;
1530 /* Decrease open count */
1531 if (SrvOpen
->OpenCount
> 0)
1533 --SrvOpen
->OpenCount
;
1536 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1537 if (SrvOpen
->OpenCount
== 1)
1539 if (!IsListEmpty(&SrvOpen
->FobxList
))
1541 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen
->FobxList
.Flink
, FOBX
, FobxQLinks
)->ScavengerFinalizationList
))
1543 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
1548 /* Nothing left, purge FCB */
1549 if (SrvOpen
->OpenCount
== 0 && RxContext
== NULL
)
1551 RxPurgeNetFcb(Fcb
, LocalContext
);
1554 /* Already closed? Job done! */
1555 SrvOpen
= Fobx
->SrvOpen
;
1556 if (SrvOpen
== NULL
||
1557 (SrvOpen
->OpenCount
!= 0 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
)) ||
1558 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1560 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1561 if (LocalContext
!= RxContext
)
1563 RxDereferenceAndDeleteRxContext(LocalContext
);
1566 return STATUS_SUCCESS
;
1569 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1571 /* Inform mini-rdr about closing */
1572 MINIRDR_CALL(Status
, LocalContext
, Fcb
->MRxDispatch
, MRxCloseSrvOpen
, (LocalContext
));
1573 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1574 Status
, RxContext
, Fobx
, Fcb
, SrvOpen
);
1576 /* And mark as such */
1577 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
);
1578 SrvOpen
->Key
= (PVOID
)-1;
1580 /* If we were delayed, we're not! */
1581 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
1583 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
1587 RxRemoveShareAccessPerSrvOpens(SrvOpen
);
1588 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
1591 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1593 /* Mark the FOBX closed as well */
1594 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1596 if (LocalContext
!= RxContext
)
1598 RxDereferenceAndDeleteRxContext(LocalContext
);
1608 RxCollapseOrCreateSrvOpen(
1609 PRX_CONTEXT RxContext
)
1616 PIO_STACK_LOCATION Stack
;
1617 ACCESS_MASK DesiredAccess
;
1618 RX_BLOCK_CONDITION FcbCondition
;
1622 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext
);
1624 Fcb
= (PFCB
)RxContext
->pFcb
;
1625 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1626 ++Fcb
->UncleanCount
;
1628 Stack
= RxContext
->CurrentIrpSp
;
1629 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
1630 ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
1632 Disposition
= RxContext
->Create
.NtCreateParameters
.Disposition
;
1634 /* Try to find a reusable SRV_OPEN */
1635 Status
= RxSearchForCollapsibleOpen(RxContext
, DesiredAccess
, ShareAccess
);
1636 if (Status
== STATUS_NOT_FOUND
)
1638 /* If none found, create one */
1639 SrvOpen
= RxCreateSrvOpen((PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
, Fcb
);
1640 if (SrvOpen
== NULL
)
1642 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1646 SrvOpen
->DesiredAccess
= DesiredAccess
;
1647 SrvOpen
->ShareAccess
= ShareAccess
;
1648 Status
= STATUS_SUCCESS
;
1651 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
1653 if (Status
!= STATUS_SUCCESS
)
1655 FcbCondition
= Condition_Bad
;
1659 RxInitiateSrvOpenKeyAssociation(SrvOpen
);
1661 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1662 RxContext
->CurrentIrp
->IoStatus
.Information
= 0xABCDEF;
1663 /* Inform the mini-rdr we're handling a create */
1664 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCreate
, (RxContext
));
1665 ASSERT(RxContext
->CurrentIrp
->IoStatus
.Information
== 0xABCDEF);
1667 DPRINT("MRxCreate returned: %x\n", Status
);
1668 if (Status
== STATUS_SUCCESS
)
1670 /* In case of overwrite, reset file size */
1671 if (Disposition
== FILE_OVERWRITE
|| Disposition
== FILE_OVERWRITE_IF
)
1673 RxAcquirePagingIoResource(RxContext
, Fcb
);
1674 Fcb
->Header
.AllocationSize
.QuadPart
= 0LL;
1675 Fcb
->Header
.FileSize
.QuadPart
= 0LL;
1676 Fcb
->Header
.ValidDataLength
.QuadPart
= 0LL;
1677 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1678 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1679 RxReleasePagingIoResource(RxContext
, Fcb
);
1683 /* Otherwise, adjust sizes */
1684 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1685 if (CcIsFileCached(RxContext
->CurrentIrpSp
->FileObject
))
1687 RxAdjustAllocationSizeforCC(Fcb
);
1689 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1693 /* Set the IoStatus with information returned by mini-rdr */
1694 RxContext
->CurrentIrp
->IoStatus
.Information
= RxContext
->Create
.ReturnedCreateInformation
;
1696 SrvOpen
->OpenStatus
= Status
;
1697 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1698 RxTransitionSrvOpen(SrvOpen
, (Status
== STATUS_SUCCESS
? Condition_Good
: Condition_Bad
));
1700 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1702 RxCompleteSrvOpenKeyAssociation(SrvOpen
);
1704 if (Status
== STATUS_SUCCESS
)
1706 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
1708 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
1710 SrvOpen
->CreateOptions
= RxContext
->Create
.NtCreateParameters
.CreateOptions
;
1711 FcbCondition
= Condition_Good
;
1715 FcbCondition
= Condition_Bad
;
1716 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1717 RxContext
->pRelevantSrvOpen
= NULL
;
1719 if (RxContext
->pFobx
!= NULL
)
1721 RxDereferenceNetFobx(RxContext
->pFobx
, LHS_ExclusiveLockHeld
);
1722 RxContext
->pFobx
= NULL
;
1727 /* Set FCB state - good or bad - depending on whether create succeed */
1728 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb
, Fcb
->Condition
);
1729 RxTransitionNetFcb(Fcb
, FcbCondition
);
1731 else if (Status
== STATUS_SUCCESS
)
1733 BOOLEAN IsGood
, ExtraOpen
;
1735 /* A reusable SRV_OPEN was found */
1736 RxContext
->CurrentIrp
->IoStatus
.Information
= FILE_OPENED
;
1739 SrvOpen
= (PSRV_OPEN
)RxContext
->pRelevantSrvOpen
;
1741 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1742 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1743 if (!StableCondition(SrvOpen
->Condition
))
1745 RxReferenceSrvOpen(SrvOpen
);
1746 ++SrvOpen
->OpenCount
;
1749 RxReleaseFcb(RxContext
, Fcb
);
1750 RxContext
->Create
.FcbAcquired
= FALSE
;
1752 RxWaitForStableSrvOpen(SrvOpen
, RxContext
);
1754 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext
, Fcb
)))
1756 RxContext
->Create
.FcbAcquired
= TRUE
;
1759 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1762 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1765 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCollapseOpen
, (RxContext
));
1767 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1771 Status
= SrvOpen
->OpenStatus
;
1776 --SrvOpen
->OpenCount
;
1777 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1781 --Fcb
->UncleanCount
;
1783 DPRINT("Status: %x\n", Status
);
1793 PRX_CONTEXT Context
)
1795 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1801 PFILE_OBJECT FileObject
;
1802 LARGE_INTEGER TruncateSize
;
1803 PLARGE_INTEGER TruncateSizePtr
;
1804 BOOLEAN NeedPurge
, FcbTableAcquired
, OneLeft
, IsFile
, FcbAcquired
, LeftForDelete
;
1808 Fcb
= (PFCB
)Context
->pFcb
;
1809 Fobx
= (PFOBX
)Context
->pFobx
;
1810 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context
, Fobx
, Fcb
);
1812 /* File system closing, it's OK */
1815 if (Fcb
->UncleanCount
> 0)
1817 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1820 return STATUS_SUCCESS
;
1823 /* Check we have a correct FCB type */
1824 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&&
1825 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&&
1826 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1827 NodeType(Fcb
) != RDBSS_NTC_SPOOLFILE
)
1829 DPRINT1("Invalid Fcb type for %p\n", Fcb
);
1830 RxBugCheck(Fcb
->Header
.NodeTypeCode
, 0, 0);
1833 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1834 ASSERT(!BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
));
1836 RxMarkFobxOnCleanup(Fobx
, &NeedPurge
);
1838 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1839 if (!NT_SUCCESS(Status
))
1846 Fobx
->AssociatedFileObject
= NULL
;
1848 /* In case SRV_OPEN used is part of FCB */
1849 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_SRVOPEN_USED
))
1851 ASSERT(Fcb
->UncleanCount
!= 0);
1852 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1854 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1856 --Fcb
->UncachedUncleanCount
;
1859 /* Inform mini-rdr */
1860 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1862 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1863 --Fobx
->SrvOpen
->UncleanFobxCount
;
1865 RxUninitializeCacheMap(Context
, FileObject
, NULL
);
1867 RxReleaseFcb(Context
, Fcb
);
1869 return STATUS_SUCCESS
;
1872 /* Report the fact that file could be set as delete on close */
1873 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
1875 SetFlag(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
1878 /* Cancel any pending notification */
1879 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx
);
1881 /* Backup open count before we start playing with it */
1882 OpenCount
= Fcb
->ShareAccess
.OpenCount
;
1884 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
1885 FcbTableAcquired
= FALSE
;
1886 LeftForDelete
= FALSE
;
1887 OneLeft
= (Fcb
->UncleanCount
== 1);
1891 /* Unclean count and delete on close? Verify whether we're the one */
1892 if (OneLeft
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
))
1894 if (RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, FALSE
))
1896 FcbTableAcquired
= TRUE
;
1900 RxReleaseFcb(Context
, Fcb
);
1902 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
1904 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1905 if (Status
!= STATUS_SUCCESS
)
1907 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1911 FcbTableAcquired
= TRUE
;
1914 /* That means we'll perform the delete on close! */
1915 if (Fcb
->UncleanCount
== 1)
1917 LeftForDelete
= TRUE
;
1921 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1922 FcbTableAcquired
= FALSE
;
1927 TruncateSizePtr
= NULL
;
1928 /* Handle cleanup for pipes and printers */
1929 if (NetRoot
->Type
== NET_ROOT_PIPE
|| NetRoot
->Type
== NET_ROOT_PRINT
)
1931 RxCleanupPipeQueues(Context
);
1933 /* Handle cleanup for files */
1934 else if (NetRoot
->Type
== NET_ROOT_DISK
|| NetRoot
->Type
== NET_ROOT_WILD
)
1936 Context
->LowIoContext
.Flags
|= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS
;
1937 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
1940 FsRtlFastUnlockAll(&Fcb
->Specific
.Fcb
.FileLock
, FileObject
, RxGetRequestorProcess(Context
), Context
);
1942 /* If there are still locks to release, proceed */
1943 if (Context
->LowIoContext
.ParamsFor
.Locks
.LockList
!= NULL
)
1945 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_UNLOCK_MULTIPLE
);
1946 Context
->LowIoContext
.ParamsFor
.Locks
.Flags
= 0;
1947 Status
= RxLowIoLockControlShell(Context
);
1950 /* Fix times and size */
1951 RxAdjustFileTimesAndSize(Context
);
1953 /* If we're the only one left... */
1956 /* And if we're supposed to delete on close */
1959 /* Update the sizes */
1960 RxAcquirePagingIoResource(Context
, Fcb
);
1961 Fcb
->Header
.FileSize
.QuadPart
= 0;
1962 Fcb
->Header
.ValidDataLength
.QuadPart
= 0;
1963 RxReleasePagingIoResource(Context
, Fcb
);
1965 /* Otherwise, call the mini-rdr to adjust sizes */
1968 /* File got grown up, fill with zeroes */
1969 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
1970 (Fcb
->Header
.ValidDataLength
.QuadPart
< Fcb
->Header
.FileSize
.QuadPart
))
1972 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxZeroExtend
, (Context
));
1973 Fcb
->Header
.ValidDataLength
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1976 /* File was truncated, let mini-rdr proceed */
1977 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
))
1979 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxTruncate
, (Context
));
1980 ClearFlag(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
);
1982 /* Keep track of file change for Cc uninit */
1983 TruncateSize
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1984 TruncateSizePtr
= &TruncateSize
;
1989 /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
1997 /* Otherwise, try to see whether we can purge */
2000 NeedPurge
= (OneLeft
&& (LeftForDelete
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
)));
2007 /* We have to still be there! */
2008 ASSERT(Fcb
->UncleanCount
!= 0);
2009 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
2011 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
2013 --Fcb
->UncachedUncleanCount
;
2016 /* Inform mini-rdr about ongoing cleanup */
2017 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
2019 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
2020 --Fobx
->SrvOpen
->UncleanFobxCount
;
2023 if (DisableFlushOnCleanup
)
2025 /* Only if we're the last standing */
2026 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
&&
2027 Fcb
->UncleanCount
== Fcb
->UncachedUncleanCount
)
2029 DPRINT("Flushing %p due to last cached handle cleanup\n", Context
);
2030 RxFlushFcbInSystemCache(Fcb
, TRUE
);
2036 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
2038 DPRINT("Flushing %p on cleanup\n", Context
);
2039 RxFlushFcbInSystemCache(Fcb
, TRUE
);
2043 /* If only remaining uncached & unclean, then flush and purge */
2044 if (!BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
2046 if (Fcb
->UncachedUncleanCount
!= 0)
2048 if (Fcb
->UncachedUncleanCount
== Fcb
->UncleanCount
&&
2049 Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
2051 DPRINT("Flushing FCB in system cache for %p\n", Context
);
2052 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
2057 /* If purge required, and not about to delete, flush */
2058 if (!LeftForDelete
&& NeedPurge
)
2060 DPRINT("Flushing FCB in system cache for %p\n", Context
);
2061 RxFlushFcbInSystemCache(Fcb
, TRUE
);
2064 /* If it was a file, drop cache */
2067 DPRINT("Uninit cache map for file\n");
2068 RxUninitializeCacheMap(Context
, FileObject
, TruncateSizePtr
);
2071 /* If that's the one left for deletion, or if it needs purge, flush */
2072 if (LeftForDelete
|| NeedPurge
)
2074 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, !LeftForDelete
);
2075 /* If that's for deletion, also remove from FCB table */
2078 RxRemoveNameNetFcb(Fcb
);
2079 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
2080 FcbTableAcquired
= FALSE
;
2084 /* Remove any share access */
2085 if (OpenCount
!= 0 && NetRoot
->Type
== NET_ROOT_DISK
)
2087 RxRemoveShareAccess(FileObject
, &Fcb
->ShareAccess
, "Cleanup the share access", "ClnUpShr");
2090 /* In case there's caching, on a file, and we were asked to drop collapsing, handle it */
2091 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
&& BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DISABLE_COLLAPSING
) &&
2092 RxWriteCacheingAllowed(Fcb
, Fobx
->pSrvOpen
))
2094 NTSTATUS InternalStatus
;
2095 PRX_CONTEXT InternalContext
;
2097 /* If we can properly set EOF, there's no need to drop collapsing, try to do it */
2098 InternalStatus
= STATUS_UNSUCCESSFUL
;
2099 InternalContext
= RxCreateRxContext(Context
->CurrentIrp
,
2100 Fcb
->RxDeviceObject
,
2101 RX_CONTEXT_FLAG_WAIT
| RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING
);
2102 if (InternalContext
!= NULL
)
2104 FILE_END_OF_FILE_INFORMATION FileEOF
;
2106 InternalStatus
= STATUS_SUCCESS
;
2108 /* Initialize the context for file information set */
2109 InternalContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
2110 InternalContext
->pFobx
= (PMRX_FOBX
)Fobx
;
2111 InternalContext
->pRelevantSrvOpen
= Fobx
->pSrvOpen
;
2113 /* Get EOF from the FCB */
2114 FileEOF
.EndOfFile
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
2115 InternalContext
->Info
.FileInformationClass
= FileEndOfFileInformation
;
2116 InternalContext
->Info
.Buffer
= &FileEOF
;
2117 InternalContext
->Info
.Length
= sizeof(FileEOF
);
2119 /* Call the mini-rdr */
2120 MINIRDR_CALL_THROUGH(InternalStatus
, Fcb
->MRxDispatch
, MRxSetFileInfo
, (InternalContext
));
2123 RxDereferenceAndDeleteRxContext(InternalContext
);
2126 /* We tried, so, clean the FOBX flag */
2127 ClearFlag(Fobx
->Flags
, FOBX_FLAG_DISABLE_COLLAPSING
);
2128 /* If it failed, then, disable collapsing on the FCB */
2129 if (!NT_SUCCESS(InternalStatus
))
2131 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
2136 SetFlag(FileObject
->Flags
, FO_CLEANUP_COMPLETE
);
2138 FcbAcquired
= FALSE
;
2139 RxReleaseFcb(Context
, Fcb
);
2145 RxReleaseFcb(Context
, Fcb
);
2148 if (FcbTableAcquired
)
2150 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
2156 #undef BugCheckFileId
2162 PRX_CONTEXT Context
)
2164 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
2168 PFILE_OBJECT FileObject
;
2169 BOOLEAN DereferenceFobx
, AcquiredFcb
;
2173 Fcb
= (PFCB
)Context
->pFcb
;
2174 Fobx
= (PFOBX
)Context
->pFobx
;
2175 FileObject
= Context
->CurrentIrpSp
->FileObject
;
2176 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context
, Fobx
, Fcb
, FileObject
);
2178 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2179 if (!NT_SUCCESS(Status
))
2189 /* Check our FCB type is expected */
2190 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
2191 (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
|| (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
&&
2192 (NodeType(Fcb
) < RDBSS_NTC_SPOOLFILE
|| NodeType(Fcb
) > RDBSS_NTC_OPENTARGETDIR_FCB
))))
2194 RxBugCheck(NodeType(Fcb
), 0, 0);
2197 RxReferenceNetFcb(Fcb
);
2199 DereferenceFobx
= FALSE
;
2200 /* If we're not closing FS */
2206 SrvOpen
= (PSRV_OPEN
)Fobx
->pSrvOpen
;
2207 SrvCall
= (PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
;
2208 /* Handle delayed close */
2209 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
2211 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
| FCB_STATE_ORPHANED
))
2213 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
))
2215 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx
, SrvOpen
);
2217 if (SrvOpen
->OpenCount
== 1 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_COLLAPSING_DISABLED
))
2219 if (InterlockedIncrement(&SrvCall
->NumberOfCloseDelayedFiles
) >= SrvCall
->MaximumNumberOfCloseDelayedFiles
)
2221 InterlockedDecrement(&SrvCall
->NumberOfCloseDelayedFiles
);
2225 DereferenceFobx
= TRUE
;
2226 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
2233 /* If we reach maximum of delayed close/or if there are no delayed close */
2234 if (!DereferenceFobx
)
2238 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
2239 if (NetRoot
->Type
!= NET_ROOT_PRINT
)
2241 /* Delete if asked */
2242 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
2244 RxScavengeRelatedFobxs(Fcb
);
2245 RxSynchronizeWithScavenger(Context
);
2247 RxReleaseFcb(Context
, Fcb
);
2249 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
2250 RxOrphanThisFcb(Fcb
);
2251 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
2253 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2254 ASSERT(NT_SUCCESS(Status
));
2259 RxMarkFobxOnClose(Fobx
);
2262 if (DereferenceFobx
)
2264 ASSERT(Fobx
!= NULL
);
2265 RxDereferenceNetFobx(Fobx
, LHS_SharedLockHeld
);
2269 RxCloseAssociatedSrvOpen(Fobx
, Context
);
2272 RxDereferenceNetFobx(Fobx
, LHS_ExclusiveLockHeld
);
2276 Freed
= RxDereferenceAndFinalizeNetFcb(Fcb
, Context
, FALSE
, FALSE
);
2277 AcquiredFcb
= !Freed
;
2279 FileObject
->FsContext
= (PVOID
)-1;
2283 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
2287 RxReleaseFcb(Context
, Fcb
);
2288 AcquiredFcb
= FALSE
;
2293 if (_SEH2_AbnormalTermination())
2297 RxReleaseFcb(Context
, Fcb
);
2302 ASSERT(!AcquiredFcb
);
2307 DPRINT("Status: %x\n", Status
);
2309 #undef BugCheckFileId
2318 PRX_CONTEXT Context
)
2322 PFILE_OBJECT FileObject
;
2323 PIO_STACK_LOCATION Stack
;
2327 DPRINT("RxCommonCreate(%p)\n", Context
);
2329 Irp
= Context
->CurrentIrp
;
2330 Stack
= Context
->CurrentIrpSp
;
2331 FileObject
= Stack
->FileObject
;
2333 /* Check whether that's a device opening */
2334 if (FileObject
->FileName
.Length
== 0 && FileObject
->RelatedFileObject
== NULL
)
2336 FileObject
->FsContext
= &RxDeviceFCB
;
2337 FileObject
->FsContext2
= NULL
;
2339 ++RxDeviceFCB
.NodeReferenceCount
;
2340 ++RxDeviceFCB
.OpenCount
;
2342 Irp
->IoStatus
.Information
= FILE_OPENED
;
2343 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject
, Context
->RxDeviceObject
, &Context
->RxDeviceObject
->DeviceName
);
2345 Status
= STATUS_SUCCESS
;
2349 PFCB RelatedFcb
= NULL
;
2351 /* Make sure caller is consistent */
2352 if (FlagOn(Stack
->Parameters
.Create
.Options
, FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
) ==
2353 (FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
))
2355 DPRINT1("Create.Options: %x\n", Stack
->Parameters
.Create
.Options
);
2356 return STATUS_INVALID_PARAMETER
;
2359 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
2360 Context
, FileObject
, Stack
->Parameters
.Create
.Options
, Stack
->Flags
, Stack
->Parameters
.Create
.FileAttributes
,
2361 Stack
->Parameters
.Create
.ShareAccess
, Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
2362 DPRINT("FileName: %wZ\n", &FileObject
->FileName
);
2364 if (FileObject
->RelatedFileObject
!= NULL
)
2366 RelatedFcb
= FileObject
->RelatedFileObject
->FsContext
;
2367 DPRINT("Rel FO: %p, path: %wZ\n", FileObject
->RelatedFileObject
, RelatedFcb
->FcbTableEntry
.Path
);
2370 /* Going to rename? */
2371 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
2373 DPRINT("TargetDir!\n");
2376 /* Copy create parameters to the context */
2377 RxCopyCreateParameters(Context
);
2379 /* If the caller wants to establish a connection, go ahead */
2380 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_CREATE_TREE_CONNECTION
))
2382 Status
= RxCreateTreeConnect(Context
);
2386 /* Validate file name */
2387 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2388 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2389 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2391 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2392 RtlMoveMemory(&FileObject
->FileName
.Buffer
[0], &FileObject
->FileName
.Buffer
[1],
2393 FileObject
->FileName
.Length
);
2395 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2396 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2397 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2399 return STATUS_OBJECT_NAME_INVALID
;
2403 /* Attempt to open the file */
2406 UNICODE_STRING NetRootName
;
2408 /* Strip last \ if required */
2409 if (FileObject
->FileName
.Length
!= 0 &&
2410 FileObject
->FileName
.Buffer
[FileObject
->FileName
.Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
2412 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NON_DIRECTORY_FILE
))
2414 return STATUS_OBJECT_NAME_INVALID
;
2417 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2418 Context
->Create
.Flags
|= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
;
2421 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
))
2423 FileObject
->Flags
|= FO_WRITE_THROUGH
;
2426 /* Get the associated net root to opening */
2427 Status
= RxCanonicalizeNameAndObtainNetRoot(Context
, &FileObject
->FileName
, &NetRootName
);
2428 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
2433 /* And attempt to open */
2434 Status
= RxCreateFromNetRoot(Context
, &NetRootName
);
2435 if (Status
== STATUS_SHARING_VIOLATION
)
2437 ASSERT(!BooleanFlagOn(Context
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_REPARSE
));
2439 /* If that happens for file creation, fail for real */
2440 if (Context
->Create
.NtCreateParameters
.Disposition
== FILE_CREATE
)
2442 Status
= STATUS_OBJECT_NAME_COLLISION
;
2446 /* Otherwise, if possible, attempt to scavenger current FOBX
2447 * to check whether a dormant FOBX is the reason for sharing violation
2449 if (Context
->Create
.TryForScavengingOnSharingViolation
&&
2450 !Context
->Create
.ScavengingAlreadyTried
)
2452 /* Only doable with a VNetRoot */
2453 if (Context
->Create
.pVNetRoot
!= NULL
)
2455 PV_NET_ROOT VNetRoot
;
2456 NT_CREATE_PARAMETERS SavedParameters
;
2458 /* Save create parameters */
2459 RtlCopyMemory(&SavedParameters
, &Context
->Create
.NtCreateParameters
, sizeof(NT_CREATE_PARAMETERS
));
2461 /* Reference the VNetRoot for the scavenging time */
2462 VNetRoot
= (PV_NET_ROOT
)Context
->Create
.pVNetRoot
;
2463 RxReferenceVNetRoot(VNetRoot
);
2465 /* Prepare the RX_CONTEXT for reuse */
2466 RxpPrepareCreateContextForReuse(Context
);
2467 RxReinitializeContext(Context
);
2469 /* Copy what we saved */
2470 RtlCopyMemory(&Context
->Create
.NtCreateParameters
, &SavedParameters
, sizeof(NT_CREATE_PARAMETERS
));
2472 /* And recopy what can be */
2473 RxCopyCreateParameters(Context
);
2475 /* And start purging, then scavenging FOBX */
2476 RxPurgeRelatedFobxs((PNET_ROOT
)VNetRoot
->pNetRoot
, Context
,
2477 DONT_ATTEMPT_FINALIZE_ON_PURGE
, NULL
);
2478 RxScavengeFobxsForNetRoot((PNET_ROOT
)VNetRoot
->pNetRoot
,
2481 /* Ask for a second round */
2482 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
2484 /* Keep track we already scavenged */
2485 Context
->Create
.ScavengingAlreadyTried
= TRUE
;
2487 /* Reference our SRV_CALL for CBS handling */
2488 RxReferenceSrvCall(VNetRoot
->pNetRoot
->pSrvCall
);
2489 RxpProcessChangeBufferingStateRequests((PSRV_CALL
)VNetRoot
->pNetRoot
->pSrvCall
, FALSE
);
2491 /* Drop our extra reference */
2492 RxDereferenceVNetRoot(VNetRoot
, LHS_LockNotHeld
);
2497 else if (Status
== STATUS_REPARSE
)
2499 Context
->CurrentIrp
->IoStatus
.Information
= 0;
2503 ASSERT(!BooleanFlagOn(Context
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_REPARSE
));
2506 while (Status
== STATUS_MORE_PROCESSING_REQUIRED
);
2509 if (Status
== STATUS_RETRY
)
2511 RxpPrepareCreateContextForReuse(Context
);
2513 ASSERT(Status
!= STATUS_PENDING
);
2516 DPRINT("Status: %lx\n", Status
);
2525 RxCommonDevFCBCleanup(
2526 PRX_CONTEXT Context
)
2533 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context
);
2535 Fcb
= Context
->pFcb
;
2536 Status
= STATUS_SUCCESS
;
2537 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2539 /* Our FOBX if set, has to be a VNetRoot */
2540 if (Context
->pFobx
!= NULL
)
2542 RxAcquirePrefixTableLockShared(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2543 if (Context
->pFobx
->NodeTypeCode
!= RDBSS_NTC_V_NETROOT
)
2545 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2547 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2551 --Fcb
->UncleanCount
;
2562 RxCommonDevFCBClose(
2563 PRX_CONTEXT Context
)
2567 PMRX_V_NET_ROOT NetRoot
;
2571 DPRINT("RxCommonDevFCBClose(%p)\n", Context
);
2573 Fcb
= Context
->pFcb
;
2574 NetRoot
= (PMRX_V_NET_ROOT
)Context
->pFobx
;
2575 Status
= STATUS_SUCCESS
;
2576 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2578 /* Our FOBX if set, has to be a VNetRoot */
2579 if (NetRoot
!= NULL
)
2581 RxAcquirePrefixTableLockExclusive(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2582 if (NetRoot
->NodeTypeCode
== RDBSS_NTC_V_NETROOT
)
2584 --NetRoot
->NumberOfOpens
;
2585 RxDereferenceVNetRoot(NetRoot
, LHS_ExclusiveLockHeld
);
2589 Status
= STATUS_NOT_IMPLEMENTED
;
2591 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2603 RxCommonDevFCBFsCtl(
2604 PRX_CONTEXT Context
)
2607 return STATUS_NOT_IMPLEMENTED
;
2615 RxCommonDevFCBIoCtl(
2616 PRX_CONTEXT Context
)
2622 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context
);
2624 if (Context
->pFobx
!= NULL
)
2626 return STATUS_INVALID_HANDLE
;
2629 /* Is that a prefix claim from MUP? */
2630 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2632 return RxPrefixClaim(Context
);
2635 /* Otherwise, pass through the mini-rdr */
2636 Status
= RxXXXControlFileCallthru(Context
);
2637 if (Status
!= STATUS_PENDING
)
2639 if (Context
->PostRequest
)
2641 Context
->ResumeRoutine
= RxCommonDevFCBIoCtl
;
2642 Status
= RxFsdPostRequest(Context
);
2646 DPRINT("Status: %lx\n", Status
);
2652 RxCommonDevFCBQueryVolInfo(
2653 PRX_CONTEXT Context
)
2656 return STATUS_NOT_IMPLEMENTED
;
2664 RxCommonDeviceControl(
2665 PRX_CONTEXT Context
)
2671 /* Prefix claim is only allowed for device, not files */
2672 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2674 return STATUS_INVALID_DEVICE_REQUEST
;
2677 /* Submit to mini-rdr */
2678 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_IOCTL
);
2679 Status
= RxLowIoSubmit(Context
, RxLowIoIoCtlShellCompletion
);
2680 if (Status
== STATUS_PENDING
)
2682 RxDereferenceAndDeleteRxContext_Real(Context
);
2693 RxCommonDirectoryControl(
2694 PRX_CONTEXT Context
)
2699 PIO_STACK_LOCATION Stack
;
2703 Fcb
= (PFCB
)Context
->pFcb
;
2704 Fobx
= (PFOBX
)Context
->pFobx
;
2705 Stack
= Context
->CurrentIrpSp
;
2706 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context
, Fobx
, Fcb
, Stack
->MinorFunction
);
2708 /* Call the appropriate helper */
2709 if (Stack
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
)
2711 Status
= RxQueryDirectory(Context
);
2713 else if (Stack
->MinorFunction
== IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
2715 Status
= RxNotifyChangeDirectory(Context
);
2716 if (Status
== STATUS_PENDING
)
2718 RxDereferenceAndDeleteRxContext_Real(Context
);
2723 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2731 RxCommonDispatchProblem(
2732 PRX_CONTEXT Context
)
2735 return STATUS_NOT_IMPLEMENTED
;
2740 RxCommonFileSystemControl(
2741 PRX_CONTEXT Context
)
2745 PIO_STACK_LOCATION Stack
;
2749 Irp
= Context
->CurrentIrp
;
2750 Stack
= Context
->CurrentIrpSp
;
2751 ControlCode
= Stack
->Parameters
.FileSystemControl
.FsControlCode
;
2753 DPRINT1("RxCommonFileSystemControl: %p, %p, %d, %lx\n", Context
, Irp
, Stack
->MinorFunction
, ControlCode
);
2756 return STATUS_NOT_IMPLEMENTED
;
2761 RxCommonFlushBuffers(
2762 PRX_CONTEXT Context
)
2765 return STATUS_NOT_IMPLEMENTED
;
2770 RxCommonLockControl(
2771 PRX_CONTEXT Context
)
2774 return STATUS_NOT_IMPLEMENTED
;
2780 PRX_CONTEXT Context
)
2783 return STATUS_NOT_IMPLEMENTED
;
2791 RxCommonQueryInformation(
2792 PRX_CONTEXT Context
)
2794 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2795 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2796 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2803 PIO_STACK_LOCATION Stack
;
2804 FILE_INFORMATION_CLASS FileInfoClass
;
2808 Fcb
= (PFCB
)Context
->pFcb
;
2809 Fobx
= (PFOBX
)Context
->pFobx
;
2810 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2812 Irp
= Context
->CurrentIrp
;
2813 Stack
= Context
->CurrentIrpSp
;
2814 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp
->AssociatedIrp
.SystemBuffer
,
2815 Stack
->Parameters
.QueryFile
.Length
, Stack
->Parameters
.QueryFile
.FileInformationClass
);
2817 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2818 FileInfoClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
2825 /* Get a writable buffer */
2826 Buffer
= RxMapSystemBuffer(Context
);
2829 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2833 RtlZeroMemory(Buffer
, Context
->Info
.Length
);
2835 /* Validate file type */
2836 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
)
2838 if (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
2840 Status
= STATUS_INVALID_PARAMETER
;
2843 else if (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
)
2845 if (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
)
2847 Status
= STATUS_NOT_IMPLEMENTED
;
2851 Status
= STATUS_INVALID_PARAMETER
;
2858 /* Acquire the right lock */
2859 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
2860 FileInfoClass
!= FileNameInformation
)
2862 if (FileInfoClass
== FileCompressionInformation
)
2864 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2868 Status
= RxAcquireSharedFcb(Context
, Fcb
);
2871 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2873 Status
= STATUS_PENDING
;
2876 else if (!NT_SUCCESS(Status
))
2884 /* Dispatch to the right helper */
2885 switch (FileInfoClass
)
2887 case FileBasicInformation
:
2888 Status
= RxQueryBasicInfo(Context
, Buffer
);
2891 case FileStandardInformation
:
2892 Status
= RxQueryStandardInfo(Context
, Buffer
);
2895 case FileInternalInformation
:
2896 Status
= RxQueryInternalInfo(Context
, Buffer
);
2899 case FileEaInformation
:
2900 Status
= RxQueryEaInfo(Context
, Buffer
);
2903 case FileNameInformation
:
2904 Status
= RxQueryNameInfo(Context
, Buffer
);
2907 case FileAllInformation
:
2908 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo
);
2909 if (!NT_SUCCESS(Status
))
2914 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
), RxQueryStandardInfo
);
2915 if (!NT_SUCCESS(Status
))
2920 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2921 sizeof(FILE_STANDARD_INFORMATION
), RxQueryInternalInfo
);
2922 if (!NT_SUCCESS(Status
))
2927 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2928 sizeof(FILE_STANDARD_INFORMATION
) +
2929 sizeof(FILE_INTERNAL_INFORMATION
), RxQueryEaInfo
);
2930 if (!NT_SUCCESS(Status
))
2935 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2936 sizeof(FILE_STANDARD_INFORMATION
) +
2937 sizeof(FILE_INTERNAL_INFORMATION
) +
2938 sizeof(FILE_EA_INFORMATION
), RxQueryPositionInfo
);
2939 if (!NT_SUCCESS(Status
))
2944 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2945 sizeof(FILE_STANDARD_INFORMATION
) +
2946 sizeof(FILE_INTERNAL_INFORMATION
) +
2947 sizeof(FILE_EA_INFORMATION
) +
2948 sizeof(FILE_POSITION_INFORMATION
), RxQueryNameInfo
);
2951 case FileAlternateNameInformation
:
2952 Status
= RxQueryAlternateNameInfo(Context
, Buffer
);
2955 case FilePipeInformation
:
2956 case FilePipeLocalInformation
:
2957 case FilePipeRemoteInformation
:
2958 Status
= RxQueryPipeInfo(Context
, Buffer
);
2961 case FileCompressionInformation
:
2962 Status
= RxQueryCompressedInfo(Context
, Buffer
);
2966 Context
->IoStatusBlock
.Status
= RxpQueryInfoMiniRdr(Context
, FileInfoClass
, Buffer
);
2967 Status
= Context
->IoStatusBlock
.Status
;
2971 if (Context
->Info
.Length
< 0)
2973 Status
= STATUS_BUFFER_OVERFLOW
;
2974 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2977 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryFile
.Length
- Context
->Info
.Length
;
2983 RxReleaseFcb(Context
, Fcb
);
2988 DPRINT("Status: %x\n", Status
);
2991 #undef SET_SIZE_AND_QUERY
2996 RxCommonQueryQuotaInformation(
2997 PRX_CONTEXT Context
)
3000 return STATUS_NOT_IMPLEMENTED
;
3005 RxCommonQuerySecurity(
3006 PRX_CONTEXT Context
)
3009 return STATUS_NOT_IMPLEMENTED
;
3017 RxCommonQueryVolumeInformation(
3018 PRX_CONTEXT Context
)
3024 PIO_STACK_LOCATION Stack
;
3028 Fcb
= (PFCB
)Context
->pFcb
;
3029 Fobx
= (PFOBX
)Context
->pFobx
;
3031 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
3033 Irp
= Context
->CurrentIrp
;
3034 Stack
= Context
->CurrentIrpSp
;
3035 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack
->Parameters
.QueryVolume
.Length
,
3036 Stack
->Parameters
.QueryVolume
.FsInformationClass
, Irp
->AssociatedIrp
.SystemBuffer
);
3038 Context
->Info
.FsInformationClass
= Stack
->Parameters
.QueryVolume
.FsInformationClass
;
3039 Context
->Info
.Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
3040 Context
->Info
.Length
= Stack
->Parameters
.QueryVolume
.Length
;
3042 /* Forward to mini-rdr */
3043 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxQueryVolumeInfo
, (Context
));
3045 /* Post request if mini-rdr asked to */
3046 if (Context
->PostRequest
)
3048 Status
= RxFsdPostRequest(Context
);
3052 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryVolume
.Length
- Context
->Info
.Length
;
3055 DPRINT("Status: %x\n", Status
);
3062 PRX_CONTEXT RxContext
)
3070 PFILE_OBJECT FileObject
;
3071 LARGE_INTEGER ByteOffset
;
3072 PIO_STACK_LOCATION Stack
;
3073 PLOWIO_CONTEXT LowIoContext
;
3074 PRDBSS_DEVICE_OBJECT RxDeviceObject
;
3075 ULONG ReadLength
, CapturedRxContextSerialNumber
= RxContext
->SerialNumber
;
3076 BOOLEAN CanWait
, PagingIo
, NoCache
, Sync
, PostRequest
, IsPipe
, ReadCachingEnabled
, ReadCachingDisabled
, InFsp
, OwnerSet
;
3080 Fcb
= (PFCB
)RxContext
->pFcb
;
3081 Fobx
= (PFOBX
)RxContext
->pFobx
;
3082 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext
, Fobx
, Fcb
);
3084 /* Get some parameters */
3085 Irp
= RxContext
->CurrentIrp
;
3086 Stack
= RxContext
->CurrentIrpSp
;
3087 CanWait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
3088 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
3089 NoCache
= BooleanFlagOn(Irp
->Flags
, IRP_NOCACHE
);
3090 Sync
= !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
3091 InFsp
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
);
3092 ReadLength
= Stack
->Parameters
.Read
.Length
;
3093 ByteOffset
.QuadPart
= Stack
->Parameters
.Read
.ByteOffset
.QuadPart
;
3094 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength
, ByteOffset
.QuadPart
,
3095 (CanWait
? "CW" : "!CW"), (PagingIo
? "PI" : "!PI"), (NoCache
? "NC" : "!NC"), (Sync
? "S" : "!S"));
3097 RxItsTheSameContext();
3099 Irp
->IoStatus
.Information
= 0;
3101 /* Should the read be loud - so far, it's just ignored on ReactOS:
3102 * s/DPRINT/DPRINT1/g will make it loud
3104 LowIoContext
= &RxContext
->LowIoContext
;
3105 CheckForLoudOperations(RxContext
);
3106 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
))
3108 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
3109 ByteOffset
, ReadLength
,
3110 Fcb
, Fcb
->Header
.ValidDataLength
, Fcb
->Header
.FileSize
, Fcb
->Header
.AllocationSize
);
3113 RxDeviceObject
= RxContext
->RxDeviceObject
;
3115 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
) && Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
3117 InterlockedIncrement((volatile long *)&RxDeviceObject
->ReadOperations
);
3119 if (ByteOffset
.QuadPart
!= Fobx
->Specific
.DiskFile
.PredictedReadOffset
)
3121 InterlockedIncrement((volatile long *)&RxDeviceObject
->RandomReadOperations
);
3123 Fobx
->Specific
.DiskFile
.PredictedReadOffset
= ByteOffset
.QuadPart
+ ReadLength
;
3127 ExInterlockedAddLargeStatistic(&RxDeviceObject
->PagingReadBytesRequested
, ReadLength
);
3131 ExInterlockedAddLargeStatistic(&RxDeviceObject
->NonPagingReadBytesRequested
, ReadLength
);
3135 ExInterlockedAddLargeStatistic(&RxDeviceObject
->CacheReadBytesRequested
, ReadLength
);
3139 /* A pagefile cannot be a pipe */
3140 IsPipe
= Fcb
->NetRoot
->Type
== NET_ROOT_PIPE
;
3141 if (IsPipe
&& PagingIo
)
3143 return STATUS_INVALID_DEVICE_REQUEST
;
3146 /* Null-length read is no-op */
3147 if (ReadLength
== 0)
3149 return STATUS_SUCCESS
;
3152 /* Validate FCB type */
3153 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&& NodeType(Fcb
) != RDBSS_NTC_VOLUME_FCB
)
3155 return STATUS_INVALID_DEVICE_REQUEST
;
3158 /* Init the lowio context for possible forward */
3159 RxInitializeLowIoContext(LowIoContext
, LOWIO_OP_READ
);
3161 PostRequest
= FALSE
;
3162 ReadCachingDisabled
= FALSE
;
3164 ReadCachingEnabled
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3165 FileObject
= Stack
->FileObject
;
3166 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
3171 /* If no caching, make sure current Cc data have been flushed */
3172 if (!PagingIo
&& NoCache
&& !ReadCachingEnabled
&& FileObject
->SectionObjectPointer
!= NULL
)
3174 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
3175 if (Status
== STATUS_LOCK_NOT_GRANTED
)
3180 else if (Status
!= STATUS_SUCCESS
)
3185 ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, TRUE
);
3186 CcFlushCache(FileObject
->SectionObjectPointer
, &ByteOffset
, ReadLength
, &Irp
->IoStatus
);
3187 RxReleasePagingIoResource(RxContext
, Fcb
);
3189 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
3194 RxAcquirePagingIoResource(RxContext
, Fcb
);
3195 RxReleasePagingIoResource(RxContext
, Fcb
);
3198 /* Acquire the appropriate lock */
3199 if (PagingIo
&& !ReadCachingEnabled
)
3203 if (!ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, CanWait
))
3211 LowIoContext
->Resource
= Fcb
->Header
.PagingIoResource
;
3216 if (!ReadCachingEnabled
)
3218 if (!CanWait
&& NoCache
)
3220 Status
= RxAcquireSharedFcbWaitForEx(RxContext
, Fcb
);
3221 if (Status
== STATUS_LOCK_NOT_GRANTED
)
3223 DPRINT1("RdAsyLNG %x\n", RxContext
);
3227 if (Status
!= STATUS_SUCCESS
)
3229 DPRINT1("RdAsyOthr %x\n", RxContext
);
3233 if (RxIsFcbAcquiredShared(Fcb
) <= 0xF000)
3235 LowIoContext
->Resource
= Fcb
->Header
.Resource
;
3245 Status
= RxAcquireSharedFcb(RxContext
, Fcb
);
3246 if (Status
== STATUS_LOCK_NOT_GRANTED
)
3251 else if (Status
!= STATUS_SUCCESS
)
3259 RxItsTheSameContext();
3261 ReadCachingDisabled
= (ReadCachingEnabled
== FALSE
);
3267 RxGetFileSizeWithLock(Fcb
, &FileSize
);
3269 /* Make sure FLOCK doesn't conflict */
3272 if (!FsRtlCheckLockForReadAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
3274 Status
= STATUS_FILE_LOCK_CONFLICT
;
3279 /* Validate byteoffset vs length */
3280 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
3282 if (ByteOffset
.QuadPart
>= FileSize
)
3284 Status
= STATUS_END_OF_FILE
;
3288 if (ReadLength
> FileSize
- ByteOffset
.QuadPart
)
3290 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
3295 if (!PagingIo
&& !NoCache
&& ReadCachingEnabled
&&
3296 !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
))
3298 /* File was not cached yet, do it */
3299 if (FileObject
->PrivateCacheMap
== NULL
)
3301 if (BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
))
3303 Status
= STATUS_FILE_CLOSED
;
3307 RxAdjustAllocationSizeforCC(Fcb
);
3309 CcInitializeCacheMap(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
3310 FALSE
, &RxData
.CacheManagerCallbacks
, Fcb
);
3312 if (BooleanFlagOn(Fcb
->MRxDispatch
->MRxFlags
, RDBSS_NO_DEFERRED_CACHE_READAHEAD
))
3314 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
3318 CcSetAdditionalCacheAttributes(FileObject
, TRUE
, FALSE
);
3319 SetFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3322 CcSetReadAheadGranularity(FileObject
, NetRoot
->DiskParameters
.ReadAheadGranularity
);
3325 /* This should never happen - fix your RDR */
3326 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
3331 CcMdlRead(FileObject
, &ByteOffset
, ReadLength
, &Irp
->MdlAddress
, &Irp
->IoStatus
);
3332 Status
= Irp
->IoStatus
.Status
;
3333 ASSERT(NT_SUCCESS(Status
));
3338 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3339 if (SystemBuffer
== NULL
)
3341 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3345 SetFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3347 RxItsTheSameContext();
3349 /* Perform the read */
3350 if (!CcCopyRead(FileObject
, &ByteOffset
, ReadLength
, CanWait
, SystemBuffer
, &Irp
->IoStatus
))
3352 if (!ReadCachingEnabled
)
3354 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3357 RxItsTheSameContext();
3363 if (!ReadCachingEnabled
)
3365 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3368 Status
= Irp
->IoStatus
.Status
;
3369 ASSERT(NT_SUCCESS(Status
));
3374 /* Validate the reading */
3375 if (FileObject
->PrivateCacheMap
!= NULL
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) &&
3376 ByteOffset
.QuadPart
>= 4096)
3378 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
3379 ClearFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3382 /* If it's consistent, forward to mini-rdr */
3383 if (Fcb
->CachedNetRootType
!= NET_ROOT_DISK
|| BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) ||
3384 ByteOffset
.QuadPart
< Fcb
->Header
.ValidDataLength
.QuadPart
)
3386 LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
= ReadLength
;
3387 LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
= ByteOffset
.QuadPart
;
3389 RxItsTheSameContext();
3391 if (InFsp
&& ReadCachingDisabled
)
3393 ExSetResourceOwnerPointer((PagingIo
? Fcb
->Header
.PagingIoResource
: Fcb
->Header
.Resource
),
3394 (PVOID
)((ULONG_PTR
)RxContext
| 3));
3398 Status
= RxLowIoReadShell(RxContext
);
3400 RxItsTheSameContext();
3404 if (ByteOffset
.QuadPart
> FileSize
)
3407 Irp
->IoStatus
.Information
= ReadLength
;
3411 if (ByteOffset
.QuadPart
+ ReadLength
> FileSize
)
3413 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
3416 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3417 RtlZeroMemory(SystemBuffer
, ReadLength
);
3418 Irp
->IoStatus
.Information
= ReadLength
;
3424 RxItsTheSameContext();
3426 /* Post if required */
3429 InterlockedIncrement((volatile long *)&RxContext
->ReferenceCount
);
3430 Status
= RxFsdPostRequest(RxContext
);
3434 /* Update FO in case of sync IO */
3435 if (!IsPipe
&& !PagingIo
)
3437 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
3439 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
3444 /* Set FastIo if read was a success */
3445 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
3447 if (!IsPipe
&& !PagingIo
)
3449 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
3453 /* In case we're done (not expected any further processing */
3454 if (_SEH2_AbnormalTermination() || Status
!= STATUS_PENDING
|| PostRequest
)
3456 /* Release everything that can be */
3457 if (ReadCachingDisabled
)
3463 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3467 RxReleasePagingIoResource(RxContext
, Fcb
);
3474 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3478 RxReleaseFcb(RxContext
, Fcb
);
3483 /* Dereference/Delete context */
3486 RxDereferenceAndDeleteRxContext(RxContext
);
3490 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
3492 RxResumeBlockedOperations_Serially(RxContext
, &Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
3496 /* We cannot return more than asked */
3497 if (Status
== STATUS_SUCCESS
)
3499 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
3506 RxDereferenceAndDeleteRxContext(RxContext
);
3517 PRX_CONTEXT Context
)
3520 return STATUS_NOT_IMPLEMENTED
;
3528 RxCommonSetInformation(
3529 PRX_CONTEXT Context
)
3536 PIO_STACK_LOCATION Stack
;
3537 FILE_INFORMATION_CLASS Class
;
3538 BOOLEAN CanWait
, FcbTableAcquired
, FcbAcquired
;
3542 Fcb
= (PFCB
)Context
->pFcb
;
3543 Fobx
= (PFOBX
)Context
->pFobx
;
3544 DPRINT("RxCommonSetInformation(%p), FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
3546 Irp
= Context
->CurrentIrp
;
3547 Stack
= Context
->CurrentIrpSp
;
3548 Class
= Stack
->Parameters
.SetFile
.FileInformationClass
;
3549 DPRINT("Buffer: %p, Length: %lx, Class: %ld, ReplaceIfExists: %d\n",
3550 Irp
->AssociatedIrp
.SystemBuffer
, Stack
->Parameters
.SetFile
.Length
,
3551 Class
, Stack
->Parameters
.SetFile
.ReplaceIfExists
);
3553 Status
= STATUS_SUCCESS
;
3554 CanWait
= BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_WAIT
);
3555 FcbTableAcquired
= FALSE
;
3556 FcbAcquired
= FALSE
;
3557 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
3559 #define _SEH2_TRY_RETURN(S) S; goto try_exit
3563 /* Valide the node type first */
3564 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
3565 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
3567 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
3569 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
))
3571 Status
= STATUS_SUCCESS
;
3574 else if (NodeType(Fcb
) != RDBSS_NTC_SPOOLFILE
)
3576 if (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
)
3578 _SEH2_TRY_RETURN(Status
= STATUS_NOT_IMPLEMENTED
);
3582 DPRINT1("Illegal type of file provided: %x\n", NodeType(Fcb
));
3583 _SEH2_TRY_RETURN(Status
= STATUS_INVALID_PARAMETER
);
3588 /* We don't autorize advance operation */
3589 if (Class
== FileEndOfFileInformation
&& Stack
->Parameters
.SetFile
.AdvanceOnly
)
3591 DPRINT1("Not allowed\n");
3593 _SEH2_TRY_RETURN(Status
= STATUS_SUCCESS
);
3596 /* For these to classes, we'll have to deal with the FCB table (removal)
3597 * We thus need the exclusive FCB table lock
3599 if (Class
== FileDispositionInformation
|| Class
== FileRenameInformation
)
3601 RxPurgeRelatedFobxs(NetRoot
, Context
, TRUE
, Fcb
);
3602 RxScavengeFobxsForNetRoot(NetRoot
, Fcb
, TRUE
);
3604 if (!RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, CanWait
))
3606 Context
->PostRequest
= TRUE
;
3607 _SEH2_TRY_RETURN(Status
= STATUS_PENDING
);
3610 FcbTableAcquired
= TRUE
;
3613 /* Finally, if not paging file, we need exclusive FCB lock */
3614 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
))
3616 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
3617 if (Status
== STATUS_LOCK_NOT_GRANTED
)
3619 Context
->PostRequest
= TRUE
;
3620 _SEH2_TRY_RETURN(Status
= STATUS_SUCCESS
);
3622 else if (Status
!= STATUS_SUCCESS
)
3630 Status
= STATUS_SUCCESS
;
3632 /* And now, perform the job! */
3635 case FileBasicInformation
:
3636 Status
= RxSetBasicInfo(Context
);
3639 case FileDispositionInformation
:
3641 PFILE_DISPOSITION_INFORMATION FDI
;
3643 /* Check whether user wants deletion */
3644 FDI
= Irp
->AssociatedIrp
.SystemBuffer
;
3645 if (FDI
->DeleteFile
)
3647 /* If so, check whether it's doable */
3648 if (!MmFlushImageSection(&Fcb
->NonPaged
->SectionObjectPointers
, MmFlushForDelete
))
3650 Status
= STATUS_CANNOT_DELETE
;
3653 /* And if doable, already remove from FCB table */
3654 if (Status
== STATUS_SUCCESS
)
3656 ASSERT(FcbAcquired
&& FcbTableAcquired
);
3657 RxRemoveNameNetFcb(Fcb
);
3659 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3660 FcbTableAcquired
= FALSE
;
3664 /* If it succeed, perform the operation */
3665 if (Status
== STATUS_SUCCESS
)
3667 Status
= RxSetDispositionInfo(Context
);
3673 case FilePositionInformation
:
3674 Status
= RxSetPositionInfo(Context
);
3677 case FileAllocationInformation
:
3678 Status
= RxSetAllocationInfo(Context
);
3681 case FileEndOfFileInformation
:
3682 Status
= RxSetEndOfFileInfo(Context
);
3685 case FilePipeInformation
:
3686 case FilePipeLocalInformation
:
3687 case FilePipeRemoteInformation
:
3688 Status
= RxSetPipeInfo(Context
);
3691 case FileRenameInformation
:
3692 case FileLinkInformation
:
3693 case FileMoveClusterInformation
:
3694 /* If we can wait, try to perform the operation right now */
3697 /* Of course, collapsing is not doable anymore, file is
3698 * in an inbetween state
3700 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
3702 /* Set the information */
3703 Status
= RxSetRenameInfo(Context
);
3704 /* If it succeed, drop the current entry from FCB table */
3705 if (Status
== STATUS_SUCCESS
&& Class
== FileRenameInformation
)
3707 ASSERT(FcbAcquired
&& FcbTableAcquired
);
3708 RxRemoveNameNetFcb(Fcb
);
3710 _SEH2_TRY_RETURN(Status
);
3712 /* Can't wait? Post for async retry */
3715 Status
= RxFsdPostRequest(Context
);
3716 _SEH2_TRY_RETURN(Status
);
3720 case FileValidDataLengthInformation
:
3721 if (!MmCanFileBeTruncated(&Fcb
->NonPaged
->SectionObjectPointers
, NULL
))
3723 Status
= STATUS_USER_MAPPED_FILE
;
3727 case FileShortNameInformation
:
3728 Status
= RxSetSimpleInfo(Context
);
3732 DPRINT1("Insupported class: %x\n", Class
);
3733 Status
= STATUS_INVALID_PARAMETER
;
3739 /* If mini-rdr was OK and wants a re-post on this, do it */
3740 if (Status
== STATUS_SUCCESS
)
3742 if (Context
->PostRequest
)
3744 Status
= RxFsdPostRequest(Context
);
3750 /* Release any acquired lock */
3753 RxReleaseFcb(Context
, Fcb
);
3756 if (FcbTableAcquired
)
3758 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3763 #undef _SEH2_TRY_RETURN
3770 RxCommonSetQuotaInformation(
3771 PRX_CONTEXT Context
)
3774 return STATUS_NOT_IMPLEMENTED
;
3779 RxCommonSetSecurity(
3780 PRX_CONTEXT Context
)
3783 return STATUS_NOT_IMPLEMENTED
;
3788 RxCommonSetVolumeInformation(
3789 PRX_CONTEXT Context
)
3792 return STATUS_NOT_IMPLEMENTED
;
3797 RxCommonUnimplemented(
3798 PRX_CONTEXT Context
)
3801 return STATUS_NOT_IMPLEMENTED
;
3807 PRX_CONTEXT RxContext
)
3815 PFILE_OBJECT FileObject
;
3816 PIO_STACK_LOCATION Stack
;
3817 LARGE_INTEGER ByteOffset
;
3818 NODE_TYPE_CODE NodeTypeCode
;
3819 PLOWIO_CONTEXT LowIoContext
;
3820 PRDBSS_DEVICE_OBJECT RxDeviceObject
;
3821 ULONG WriteLength
, CapturedRxContextSerialNumber
= RxContext
->SerialNumber
;
3822 LONGLONG FileSize
, ValidDataLength
, InitialFileSize
, InitialValidDataLength
;
3823 BOOLEAN CanWait
, PagingIo
, NoCache
, Sync
, NormalFile
, WriteToEof
, IsPipe
, NoPreposting
, InFsp
, RecursiveWriteThrough
, CalledByLazyWriter
, SwitchBackToAsync
, ExtendingFile
, ExtendingValidData
, UnwindOutstandingAsync
, ResourceOwnerSet
, PostIrp
, ContextReferenced
;
3827 Fcb
= (PFCB
)RxContext
->pFcb
;
3828 NodeTypeCode
= NodeType(Fcb
);
3829 /* Validate FCB type */
3830 if (NodeTypeCode
!= RDBSS_NTC_STORAGE_TYPE_FILE
&& NodeTypeCode
!= RDBSS_NTC_VOLUME_FCB
&&
3831 NodeTypeCode
!= RDBSS_NTC_SPOOLFILE
&& NodeTypeCode
!= RDBSS_NTC_MAILSLOT
)
3833 return STATUS_INVALID_DEVICE_REQUEST
;
3836 /* We'll write to file, keep track of it */
3837 Fcb
->IsFileWritten
= TRUE
;
3839 Stack
= RxContext
->CurrentIrpSp
;
3840 /* Set write through if asked */
3841 if (BooleanFlagOn(Stack
->Flags
, SL_WRITE_THROUGH
))
3843 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
);
3846 Fobx
= (PFOBX
)RxContext
->pFobx
;
3847 DPRINT("RxCommonWrite(%p) FOBX: %p, FCB: %p\n", RxContext
, Fobx
, Fcb
);
3849 /* Get some parameters */
3850 Irp
= RxContext
->CurrentIrp
;
3851 NoPreposting
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
);
3852 InFsp
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
);
3853 CanWait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
3854 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
3855 NoCache
= BooleanFlagOn(Irp
->Flags
, IRP_NOCACHE
);
3856 Sync
= !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
3857 WriteLength
= Stack
->Parameters
.Write
.Length
;
3858 ByteOffset
.QuadPart
= Stack
->Parameters
.Write
.ByteOffset
.QuadPart
;
3859 DPRINT("Writing: %lx@%I64x %s %s %s %s\n", WriteLength
, ByteOffset
.QuadPart
,
3860 (CanWait
? "CW" : "!CW"), (PagingIo
? "PI" : "!PI"), (NoCache
? "NC" : "!NC"), (Sync
? "S" : "!S"));
3862 RxItsTheSameContext();
3864 RxContext
->FcbResourceAcquired
= FALSE
;
3865 RxContext
->FcbPagingIoResourceAcquired
= FALSE
;
3867 LowIoContext
= &RxContext
->LowIoContext
;
3868 CheckForLoudOperations(RxContext
);
3869 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
))
3871 DPRINT("LoudWrite %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
3872 ByteOffset
, WriteLength
,
3873 Fcb
, Fcb
->Header
.ValidDataLength
, Fcb
->Header
.FileSize
, Fcb
->Header
.AllocationSize
);
3876 RxDeviceObject
= RxContext
->RxDeviceObject
;
3878 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
) && Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
3880 InterlockedIncrement((volatile long *)&RxDeviceObject
->WriteOperations
);
3882 if (ByteOffset
.QuadPart
!= Fobx
->Specific
.DiskFile
.PredictedWriteOffset
)
3884 InterlockedIncrement((volatile long *)&RxDeviceObject
->RandomWriteOperations
);
3886 Fobx
->Specific
.DiskFile
.PredictedWriteOffset
= ByteOffset
.QuadPart
+ WriteLength
;
3890 ExInterlockedAddLargeStatistic(&RxDeviceObject
->PagingWriteBytesRequested
, WriteLength
);
3894 ExInterlockedAddLargeStatistic(&RxDeviceObject
->NonPagingWriteBytesRequested
, WriteLength
);
3898 ExInterlockedAddLargeStatistic(&RxDeviceObject
->CacheWriteBytesRequested
, WriteLength
);
3902 NetRoot
= (PNET_ROOT
)Fcb
->NetRoot
;
3903 IsPipe
= (NetRoot
->Type
== NET_ROOT_PIPE
);
3904 /* Keep track for normal writes */
3905 if (NetRoot
->Type
== NET_ROOT_DISK
|| NetRoot
->Type
== NET_ROOT_WILD
)
3914 /* Zero-length write is immediate success */
3915 if (NormalFile
&& WriteLength
== 0)
3917 return STATUS_SUCCESS
;
3920 /* Check whether we have input data */
3921 if (Irp
->UserBuffer
== NULL
&& Irp
->MdlAddress
== NULL
)
3923 return STATUS_INVALID_PARAMETER
;
3926 /* Are we writting to EOF? */
3927 WriteToEof
= ((ByteOffset
.LowPart
== FILE_WRITE_TO_END_OF_FILE
) && (ByteOffset
.HighPart
== -1));
3928 /* FIXME: validate length/offset */
3930 /* Get our SRV_OPEN in case of normal write */
3933 SrvOpen
= (PSRV_OPEN
)Fobx
->pSrvOpen
;
3940 FileObject
= Stack
->FileObject
;
3942 /* If we have caching enabled, check whether we have to defer write */
3945 if (RxWriteCacheingAllowed(Fcb
, SrvOpen
))
3947 if (!CcCanIWrite(FileObject
, WriteLength
,
3948 (CanWait
&& !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
)),
3949 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_DEFERRED_WRITE
)))
3953 Retrying
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_DEFERRED_WRITE
);
3955 RxPrePostIrp(RxContext
, Irp
);
3957 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_DEFERRED_WRITE
);
3959 CcDeferWrite(FileObject
, (PCC_POST_DEFERRED_WRITE
)RxAddToWorkque
, RxContext
, Irp
, WriteLength
, Retrying
);
3961 return STATUS_PENDING
;
3966 /* Initialize the low IO context for write */
3967 RxInitializeLowIoContext(LowIoContext
, LOWIO_OP_WRITE
);
3969 /* Initialize our (many) booleans */
3970 RecursiveWriteThrough
= FALSE
;
3971 CalledByLazyWriter
= FALSE
;
3972 SwitchBackToAsync
= FALSE
;
3973 ExtendingFile
= FALSE
;
3974 ExtendingValidData
= FALSE
;
3975 UnwindOutstandingAsync
= FALSE
;
3976 ResourceOwnerSet
= FALSE
;
3978 ContextReferenced
= FALSE
;
3980 #define _SEH2_TRY_RETURN(S) S; goto try_exit
3984 /* No volume FCB here! */
3985 ASSERT((NodeTypeCode
== RDBSS_NTC_STORAGE_TYPE_FILE
) ||
3986 (NodeTypeCode
== RDBSS_NTC_SPOOLFILE
) ||
3987 (NodeTypeCode
== RDBSS_NTC_MAILSLOT
));
3989 /* Writing to EOF on a paging file is non sense */
3990 ASSERT(!(WriteToEof
&& PagingIo
));
3992 RxItsTheSameContext();
3994 /* Start locking stuff */
3995 if (!PagingIo
&& !NoPreposting
)
3997 /* If it's already acquired, all fine */
3998 if (RxContext
->FcbResourceAcquired
)
4004 /* Otherwise, try to acquire shared (excepted for pipes) */
4007 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4010 (!NoCache
&& RxWriteCacheingAllowed(Fcb
, SrvOpen
)))
4012 Status
= RxAcquireSharedFcb(RxContext
, Fcb
);
4016 Status
= RxAcquireSharedFcbWaitForEx(RxContext
, Fcb
);
4019 /* We'll post IRP to retry */
4020 if (Status
== STATUS_LOCK_NOT_GRANTED
)
4023 DPRINT1("Failed to acquire lock!\n");
4024 _SEH2_TRY_RETURN(Status
);
4027 /* We'll just fail */
4028 if (Status
!= STATUS_SUCCESS
)
4030 _SEH2_TRY_RETURN(Status
);
4033 /* Resource acquired */
4034 RxContext
->FcbResourceAcquired
= TRUE
;
4037 /* At that point, resource is acquired */
4040 ASSERT(RxContext
->FcbResourceAcquired
);
4046 /* Now, check whether we have to promote shared lock */
4047 if (NodeTypeCode
== RDBSS_NTC_STORAGE_TYPE_FILE
&& Fobx
!= NULL
)
4049 IsDormant
= BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_MARKED_AS_DORMANT
);
4056 /* We're writing beyond VDL, we'll need an exclusive lock if not dormant */
4057 if (RxIsFcbAcquiredShared(Fcb
) &&
4058 ByteOffset
.QuadPart
+ WriteLength
> Fcb
->Header
.ValidDataLength
.QuadPart
)
4062 RxReleaseFcb(RxContext
, Fcb
);
4063 RxContext
->FcbResourceAcquired
= FALSE
;
4065 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4066 if (Status
== STATUS_LOCK_NOT_GRANTED
)
4069 DPRINT1("Failed to acquire lock!\n");
4070 _SEH2_TRY_RETURN(Status
);
4073 if (Status
!= STATUS_SUCCESS
)
4075 _SEH2_TRY_RETURN(Status
);
4078 RxContext
->FcbResourceAcquired
= TRUE
;
4082 /* If we're writing in VDL, or if we're dormant, shared lock is enough */
4083 if (ByteOffset
.QuadPart
+ WriteLength
<= Fcb
->Header
.ValidDataLength
.QuadPart
||
4086 if (RxIsFcbAcquiredExclusive(Fcb
))
4088 RxConvertToSharedFcb(RxContext
, Fcb
);
4093 /* We're extending file, disable collapsing */
4094 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
4096 DPRINT("Disabling collapsing\n");
4098 if (NodeTypeCode
== RDBSS_NTC_STORAGE_TYPE_FILE
&& Fobx
!= NULL
)
4100 SetFlag(Fobx
->Flags
, FOBX_FLAG_DISABLE_COLLAPSING
);
4104 ASSERT(RxContext
->FcbResourceAcquired
);
4107 /* Keep track of the acquired resource */
4108 LowIoContext
->Resource
= Fcb
->Header
.Resource
;
4115 /* Lock the paging resource */
4116 RxAcquirePagingIoResourceShared(RxContext
, Fcb
, TRUE
);
4118 /* Keep track of the acquired resource */
4119 LowIoContext
->Resource
= Fcb
->Header
.PagingIoResource
;
4125 _SEH2_TRY_RETURN(Status
= STATUS_NOT_IMPLEMENTED
);
4128 /* If it's a non cached write, or if caching is disallowed */
4129 if (NoCache
|| !RxWriteCacheingAllowed(Fcb
, SrvOpen
))
4131 /* If cache was previously enabled, we'll have to flush before writing */
4132 if (!PagingIo
&& Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
4134 LARGE_INTEGER FlushOffset
;
4137 ASSERT(RxIsFcbAcquiredExclusive(Fcb
) || RxIsFcbAcquiredShared(Fcb
));
4139 /* If shared, we'll have to relock exclusive */
4140 if (!RxIsFcbAcquiredExclusive(Fcb
))
4142 /* Release and retry exclusive */
4143 RxReleaseFcb(RxContext
, Fcb
);
4144 RxContext
->FcbResourceAcquired
= FALSE
;
4146 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4147 if (Status
== STATUS_LOCK_NOT_GRANTED
)
4150 DPRINT1("Failed to acquire lock for flush!\n");
4151 _SEH2_TRY_RETURN(Status
);
4154 if (Status
!= STATUS_SUCCESS
)
4156 _SEH2_TRY_RETURN(Status
);
4159 RxContext
->FcbResourceAcquired
= TRUE
;
4162 /* Get the length to flush */
4165 RxGetFileSizeWithLock(Fcb
, &FlushOffset
.QuadPart
);
4169 FlushOffset
.QuadPart
= ByteOffset
.QuadPart
;
4172 /* Perform the flushing */
4173 RxAcquirePagingIoResource(RxContext
, Fcb
);
4174 CcFlushCache(&Fcb
->NonPaged
->SectionObjectPointers
, &FlushOffset
,
4175 WriteLength
, &Irp
->IoStatus
);
4176 RxReleasePagingIoResource(RxContext
, Fcb
);
4178 /* Cannot continue if flushing failed */
4179 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
4181 _SEH2_TRY_RETURN(Status
= Irp
->IoStatus
.Status
);
4185 RxAcquirePagingIoResource(RxContext
, Fcb
);
4186 RxReleasePagingIoResource(RxContext
, Fcb
);
4189 CcPurgeCacheSection(&Fcb
->NonPaged
->SectionObjectPointers
,
4190 &FlushOffset
, WriteLength
, FALSE
);
4194 /* If not paging IO, check if write is allowed */
4197 if (!FsRtlCheckLockForWriteAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
4199 _SEH2_TRY_RETURN(Status
= STATUS_FILE_LOCK_CONFLICT
);
4203 /* Get file sizes */
4204 ValidDataLength
= Fcb
->Header
.ValidDataLength
.QuadPart
;
4205 RxGetFileSizeWithLock(Fcb
, &FileSize
);
4206 ASSERT(ValidDataLength
<= FileSize
);
4208 /* If paging IO, we cannot write past file size
4209 * so fix write length if needed
4213 if (ByteOffset
.QuadPart
>= FileSize
)
4215 _SEH2_TRY_RETURN(Status
= STATUS_SUCCESS
);
4218 if (WriteLength
> FileSize
- ByteOffset
.QuadPart
)
4220 WriteLength
= FileSize
- ByteOffset
.QuadPart
;
4224 /* If we're being called by the lazywrite */
4225 if (Fcb
->Specific
.Fcb
.LazyWriteThread
== PsGetCurrentThread())
4227 CalledByLazyWriter
= TRUE
;
4229 /* Fail if we're beyong VDL */
4230 if (BooleanFlagOn(Fcb
->Header
.Flags
, FSRTL_FLAG_USER_MAPPED_FILE
))
4232 if ((ByteOffset
.QuadPart
+ WriteLength
> ValidDataLength
) &&
4233 (ByteOffset
.QuadPart
< FileSize
))
4235 if (ByteOffset
.QuadPart
+ WriteLength
> ((ValidDataLength
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1)))
4237 _SEH2_TRY_RETURN(Status
= STATUS_FILE_LOCK_CONFLICT
);
4243 /* If that's a recursive synchronous page write */
4244 if (BooleanFlagOn(Irp
->Flags
, IRP_SYNCHRONOUS_PAGING_IO
) &&
4245 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
))
4249 /* Check the top level IRP on the FastIO path */
4250 TopIrp
= RxGetTopIrpIfRdbssIrp();
4251 if (TopIrp
!= NULL
&& (ULONG_PTR
)TopIrp
> FSRTL_FAST_IO_TOP_LEVEL_IRP
)
4253 PIO_STACK_LOCATION IrpStack
;
4255 ASSERT(NodeType(TopIrp
) == IO_TYPE_IRP
);
4257 /* If the top level IRP was a cached write for this file, keep track */
4258 IrpStack
= IoGetCurrentIrpStackLocation(TopIrp
);
4259 if (IrpStack
->MajorFunction
== IRP_MJ_WRITE
&&
4260 IrpStack
->FileObject
->FsContext
== FileObject
->FsContext
)
4262 RecursiveWriteThrough
= TRUE
;
4263 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
);
4268 /* Now, deal with file size and VDL */
4269 if (!CalledByLazyWriter
&& !RecursiveWriteThrough
&&
4270 (WriteToEof
|| ByteOffset
.QuadPart
+ WriteLength
> ValidDataLength
))
4272 /* Not sync? Let's make it sync, just the time we extended */
4276 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
4277 ClearFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
4280 /* Keep track we'll have to switch back to async */
4283 SwitchBackToAsync
= TRUE
;
4287 /* Release all the locks */
4288 RxWriteReleaseResources(RxContext
, 0);
4290 /* Acquire exclusive */
4291 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4292 if (Status
== STATUS_LOCK_NOT_GRANTED
)
4295 DPRINT1("Failed to acquire lock for extension!\n");
4296 _SEH2_TRY_RETURN(Status
);
4299 if (Status
!= STATUS_SUCCESS
)
4301 _SEH2_TRY_RETURN(Status
);
4304 RxContext
->FcbResourceAcquired
= TRUE
;
4306 RxItsTheSameContext();
4308 /* Get the sizes again, to be sure they didn't change in the meantime */
4309 ValidDataLength
= Fcb
->Header
.ValidDataLength
.QuadPart
;
4310 RxGetFileSizeWithLock(Fcb
, &FileSize
);
4311 ASSERT(ValidDataLength
<= FileSize
);
4313 /* Check we can switch back to async? */
4314 if ((SwitchBackToAsync
&& Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
) ||
4315 (ByteOffset
.QuadPart
+ WriteLength
> FileSize
) || RxNoAsync
)
4317 SwitchBackToAsync
= FALSE
;
4320 /* If paging IO, check we don't try to extend the file */
4323 if (ByteOffset
.QuadPart
>= FileSize
)
4325 _SEH2_TRY_RETURN(Status
= STATUS_SUCCESS
);
4328 if (WriteLength
> FileSize
- ByteOffset
.QuadPart
)
4330 WriteLength
= FileSize
- ByteOffset
.QuadPart
;
4335 /* Save our initial sizes for potential rollback */
4336 InitialFileSize
= FileSize
;
4337 InitialValidDataLength
= ValidDataLength
;
4338 /* If writing to EOF, update byte offset with file size */
4341 ByteOffset
.QuadPart
= FileSize
;
4344 /* Check again whether we're allowed to write */
4347 if (!FsRtlCheckLockForWriteAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
4349 _SEH2_TRY_RETURN(Status
= STATUS_FILE_LOCK_CONFLICT
);
4352 /* Do we have to extend? */
4353 if (NormalFile
&& (ByteOffset
.QuadPart
+ WriteLength
> FileSize
))
4355 DPRINT("Need to extend file\n");
4356 ExtendingFile
= TRUE
;
4357 SetFlag(LowIoContext
->ParamsFor
.ReadWrite
.Flags
, LOWIO_READWRITEFLAG_EXTENDING_FILESIZE
);
4361 /* Let's start to extend */
4364 /* If we're past allocating, inform mini-rdr */
4365 FileSize
= ByteOffset
.QuadPart
+ WriteLength
;
4366 if (FileSize
> Fcb
->Header
.AllocationSize
.QuadPart
)
4368 LARGE_INTEGER NewAllocationSize
;
4370 DPRINT("Extending %p\n", RxContext
);
4374 C_ASSERT(sizeof(LONGLONG
) == sizeof(LARGE_INTEGER
));
4375 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxExtendForNonCache
,
4376 (RxContext
, (PLARGE_INTEGER
)&FileSize
, &NewAllocationSize
));
4380 C_ASSERT(sizeof(LONGLONG
) == sizeof(LARGE_INTEGER
));
4381 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxExtendForCache
,
4382 (RxContext
, (PLARGE_INTEGER
)&FileSize
, &NewAllocationSize
));
4385 if (!NT_SUCCESS(Status
))
4387 _SEH2_TRY_RETURN(Status
);
4390 if (FileSize
> NewAllocationSize
.QuadPart
)
4392 NewAllocationSize
.QuadPart
= FileSize
;
4395 /* And update FCB */
4396 Fcb
->Header
.AllocationSize
.QuadPart
= NewAllocationSize
.QuadPart
;
4399 /* Set the new sizes */
4400 RxSetFileSizeWithLock(Fcb
, &FileSize
);
4401 RxAdjustAllocationSizeforCC(Fcb
);
4404 if (CcIsFileCached(FileObject
))
4406 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
4410 /* Do we have to extend VDL? */
4411 if (!CalledByLazyWriter
&& !RecursiveWriteThrough
)
4413 if (WriteToEof
|| ByteOffset
.QuadPart
+ WriteLength
> ValidDataLength
)
4415 ExtendingValidData
= TRUE
;
4416 SetFlag(LowIoContext
->ParamsFor
.ReadWrite
.Flags
, LOWIO_READWRITEFLAG_EXTENDING_VDL
);
4420 /* If none cached write */
4421 if (PagingIo
|| NoCache
|| !RxWriteCacheingAllowed(Fcb
, SrvOpen
))
4423 /* Switch back to async, if asked to */
4424 if (SwitchBackToAsync
)
4429 ClearFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
4430 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
4433 /* If not synchronous, keep track of writes to be finished */
4436 if (Fcb
->NonPaged
->OutstandingAsyncEvent
== NULL
)
4438 Fcb
->NonPaged
->OutstandingAsyncEvent
= &Fcb
->NonPaged
->TheActualEvent
;
4439 KeInitializeEvent(Fcb
->NonPaged
->OutstandingAsyncEvent
,
4440 NotificationEvent
, FALSE
);
4443 if (ExInterlockedAddUlong(&Fcb
->NonPaged
->OutstandingAsyncWrites
,
4445 &RxStrucSupSpinLock
) == 0)
4447 KeResetEvent(Fcb
->NonPaged
->OutstandingAsyncEvent
);
4450 UnwindOutstandingAsync
= TRUE
;
4451 LowIoContext
->ParamsFor
.ReadWrite
.NonPagedFcb
= Fcb
->NonPaged
;
4454 /* Set our LOWIO_CONTEXT information */
4455 LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
= ByteOffset
.QuadPart
;
4456 LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
= WriteLength
;
4458 RxItsTheSameContext();
4460 /* We have to be locked */
4461 ASSERT(RxContext
->FcbResourceAcquired
|| RxContext
->FcbPagingIoResourceAcquired
);
4463 /* Update thread ID if we're in FSP */
4466 LowIoContext
->ResourceThreadId
= (ULONG_PTR
)RxContext
| 3;
4468 if (RxContext
->FcbResourceAcquired
)
4470 ExSetResourceOwnerPointer(Fcb
->Header
.Resource
, (PVOID
)((ULONG_PTR
)RxContext
| 3));
4473 if (RxContext
->FcbPagingIoResourceAcquired
)
4475 ExSetResourceOwnerPointer(Fcb
->Header
.PagingIoResource
, (PVOID
)((ULONG_PTR
)RxContext
| 3));
4478 ResourceOwnerSet
= TRUE
;
4481 /* And perform the write */
4482 Status
= RxLowIoWriteShell(RxContext
);
4484 RxItsTheSameContext();
4486 /* Not outstanding write anymore */
4487 if (UnwindOutstandingAsync
&& Status
== STATUS_PENDING
)
4489 UnwindOutstandingAsync
= FALSE
;
4495 /* If cache wasn't enabled yet, do it */
4496 if (FileObject
->PrivateCacheMap
== NULL
)
4498 if (BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
))
4500 _SEH2_TRY_RETURN(Status
= STATUS_FILE_CLOSED
);
4503 RxAdjustAllocationSizeforCC(Fcb
);
4505 CcInitializeCacheMap(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
4506 FALSE
, &RxData
.CacheManagerCallbacks
, Fcb
);
4508 CcSetReadAheadGranularity(FileObject
, NetRoot
->DiskParameters
.ReadAheadGranularity
);
4511 /* If that's a MDL backed write */
4512 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
4514 /* Shouldn't happen */
4518 /* Perform it, though */
4519 CcPrepareMdlWrite(FileObject
, &ByteOffset
, WriteLength
,
4520 &Irp
->MdlAddress
, &Irp
->IoStatus
);
4522 Status
= Irp
->IoStatus
.Status
;
4527 ULONG BreakpointsSave
;
4529 /* Map the user buffer */
4530 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
4531 if (SystemBuffer
== NULL
)
4533 _SEH2_TRY_RETURN(Status
= STATUS_INSUFFICIENT_RESOURCES
);
4536 RxSaveAndSetExceptionNoBreakpointFlag(RxContext
, BreakpointsSave
);
4538 RxItsTheSameContext();
4540 /* And deal with Cc */
4541 if (!CcCopyWrite(FileObject
, &ByteOffset
, WriteLength
, CanWait
,
4544 RxRestoreExceptionNoBreakpointFlag(RxContext
, BreakpointsSave
);
4546 RxItsTheSameContext();
4548 DPRINT1("CcCopyWrite failed for: %p %I64d %d %lx\n",
4549 FileObject
, Fcb
->Header
.FileSize
.QuadPart
, WriteLength
, Status
);
4555 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
4556 Irp
->IoStatus
.Information
= WriteLength
;
4558 RxRestoreExceptionNoBreakpointFlag(RxContext
, BreakpointsSave
);
4560 RxItsTheSameContext();
4562 DPRINT("CcCopyWrite succeed for: %p %I64d %d %lx\n",
4563 FileObject
, Fcb
->Header
.FileSize
.QuadPart
, WriteLength
, Status
);
4570 /* If we've to post the IRP */
4573 /* Reset the file size if required */
4574 if (ExtendingFile
&& !IsPipe
)
4576 ASSERT(RxWriteCacheingAllowed(Fcb
, SrvOpen
));
4577 ASSERT(Fcb
->Header
.PagingIoResource
!= NULL
);
4579 RxAcquirePagingIoResource(RxContext
, Fcb
);
4580 RxSetFileSizeWithLock(Fcb
, &InitialFileSize
);
4581 RxReleasePagingIoResource(RxContext
, Fcb
);
4583 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
4585 *CcGetFileSizePointer(FileObject
) = Fcb
->Header
.FileSize
;
4589 InterlockedIncrement((volatile long *)&RxContext
->ReferenceCount
);
4590 ContextReferenced
= TRUE
;
4593 ASSERT(!ResourceOwnerSet
);
4594 RxWriteReleaseResources(RxContext
, ResourceOwnerSet
);
4596 #ifdef RDBSS_TRACKER
4597 ASSERT(RxContext
->AcquireReleaseFcbTrackerX
== 0);
4600 /* And post the request */
4601 Status
= RxFsdPostRequest(RxContext
);
4607 /* Update FILE_OBJECT if synchronous write succeed */
4610 if (NT_SUCCESS(Status
) && BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
4612 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
4616 /* If write succeed, ,also update FILE_OBJECT flags */
4617 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
4619 /* File was modified */
4622 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
4625 /* If was even extended */
4628 SetFlag(FileObject
->Flags
, FO_FILE_SIZE_CHANGED
);
4631 /* If VDL was extended, update FCB and inform Cc */
4632 if (ExtendingValidData
)
4634 LONGLONG LastOffset
;
4636 LastOffset
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
4637 if (FileSize
< LastOffset
)
4639 LastOffset
= FileSize
;
4642 Fcb
->Header
.ValidDataLength
.QuadPart
= LastOffset
;
4644 if (NoCache
&& CcIsFileCached(FileObject
))
4646 CcSetFileSizes(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
4655 /* Finally, if we failed while extension was required */
4656 if (_SEH2_AbnormalTermination() && (ExtendingFile
|| ExtendingValidData
))
4661 ASSERT(Fcb
->Header
.PagingIoResource
!= NULL
);
4663 RxAcquirePagingIoResource(RxContext
, Fcb
);
4664 RxSetFileSizeWithLock(Fcb
, &InitialFileSize
);
4665 Fcb
->Header
.ValidDataLength
.QuadPart
= InitialValidDataLength
;
4666 RxReleasePagingIoResource(RxContext
, Fcb
);
4668 if (FileObject
->SectionObjectPointer
->SharedCacheMap
!= NULL
)
4670 *CcGetFileSizePointer(FileObject
) = Fcb
->Header
.FileSize
;
4675 /* One async write less */
4676 if (UnwindOutstandingAsync
)
4680 ExInterlockedAddUlong(&Fcb
->NonPaged
->OutstandingAsyncWrites
, -1, &RxStrucSupSpinLock
);
4681 KeSetEvent(Fcb
->NonPaged
->OutstandingAsyncEvent
, IO_NO_INCREMENT
, FALSE
);
4684 /* And now, cleanup everything */
4685 if (_SEH2_AbnormalTermination() || Status
!= STATUS_PENDING
|| PostIrp
)
4687 /* If we didn't post, release every lock (for posting, it's already done) */
4690 RxWriteReleaseResources(RxContext
, ResourceOwnerSet
);
4693 /* If the context was referenced - posting, dereference it */
4694 if (ContextReferenced
)
4696 RxDereferenceAndDeleteRxContext(RxContext
);
4699 /* If that's a pipe operation, resume any blocked one */
4702 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
4704 RxResumeBlockedOperations_Serially(RxContext
, &Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
4708 /* Sanity check for write */
4709 if (Status
== STATUS_SUCCESS
)
4711 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Write
.Length
);
4714 /* Just dereference our context */
4718 RxDereferenceAndDeleteRxContext(RxContext
);
4723 #undef _SEH2_TRY_RETURN
4734 IN PRX_CONTEXT RxContext
)
4737 PFILE_OBJECT FileObject
;
4738 PIO_STACK_LOCATION Stack
;
4740 #define BugCheckFileId RDBSS_BUG_CHECK_CACHESUP
4744 Irp
= RxContext
->CurrentIrp
;
4745 Stack
= RxContext
->CurrentIrpSp
;
4746 FileObject
= Stack
->FileObject
;
4748 /* We can only complete for IRP_MJ_READ and IRP_MJ_WRITE */
4749 switch (RxContext
->MajorFunction
)
4751 /* Call the Cc function */
4753 CcMdlReadComplete(FileObject
, Irp
->MdlAddress
);
4757 /* If here, we can wait */
4758 ASSERT(BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
));
4760 /* Call the Cc function */
4761 CcMdlWriteComplete(FileObject
, &Stack
->Parameters
.Write
.ByteOffset
, Irp
->MdlAddress
);
4763 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
4767 DPRINT1("Invalid major for RxCompleteMdl: %d\n", RxContext
->MajorFunction
);
4768 RxBugCheck(RxContext
->MajorFunction
, 0, 0);
4773 Irp
->MdlAddress
= NULL
;
4775 /* And complete the IRP */
4776 RxCompleteRequest(RxContext
, STATUS_SUCCESS
);
4778 #undef BugCheckFileId
4780 return STATUS_SUCCESS
;
4787 RxCopyCreateParameters(
4788 IN PRX_CONTEXT RxContext
)
4792 PFILE_OBJECT FileObject
;
4793 PIO_STACK_LOCATION Stack
;
4794 PDFS_NAME_CONTEXT DfsNameContext
;
4795 PIO_SECURITY_CONTEXT SecurityContext
;
4797 Irp
= RxContext
->CurrentIrp
;
4798 Stack
= RxContext
->CurrentIrpSp
;
4799 FileObject
= Stack
->FileObject
;
4800 SecurityContext
= Stack
->Parameters
.Create
.SecurityContext
;
4802 RxContext
->Create
.NtCreateParameters
.SecurityContext
= SecurityContext
;
4803 if (SecurityContext
->AccessState
!= NULL
&& SecurityContext
->AccessState
->SecurityDescriptor
!= NULL
)
4805 RxContext
->Create
.SdLength
= RtlLengthSecurityDescriptor(SecurityContext
->AccessState
->SecurityDescriptor
);
4806 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext
->Create
.NtCreateParameters
.SecurityContext
,
4807 RxContext
->Create
.SdLength
);
4809 if (SecurityContext
->SecurityQos
!= NULL
)
4811 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityContext
->SecurityQos
->ImpersonationLevel
;
4815 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityImpersonation
;
4817 RxContext
->Create
.NtCreateParameters
.DesiredAccess
= SecurityContext
->DesiredAccess
;
4819 RxContext
->Create
.NtCreateParameters
.AllocationSize
.QuadPart
= Irp
->Overlay
.AllocationSize
.QuadPart
;
4820 RxContext
->Create
.NtCreateParameters
.FileAttributes
= Stack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
;
4821 RxContext
->Create
.NtCreateParameters
.ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
4822 RxContext
->Create
.NtCreateParameters
.Disposition
= (Stack
->Parameters
.Create
.Options
>> 24) & 0x000000FF;
4823 RxContext
->Create
.NtCreateParameters
.CreateOptions
= Stack
->Parameters
.Create
.Options
& 0xFFFFFF;
4825 DfsContext
= FileObject
->FsContext2
;
4826 DfsNameContext
= FileObject
->FsContext
;
4827 RxContext
->Create
.NtCreateParameters
.DfsContext
= DfsContext
;
4828 RxContext
->Create
.NtCreateParameters
.DfsNameContext
= DfsNameContext
;
4829 ASSERT(DfsContext
== NULL
|| DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) ||
4830 DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) ||
4831 DfsContext
== UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT
) ||
4832 DfsContext
== UIntToPtr(DFS_USER_NAME_CONTEXT
));
4833 ASSERT(DfsNameContext
== NULL
|| DfsNameContext
->NameContextType
== DFS_OPEN_CONTEXT
||
4834 DfsNameContext
->NameContextType
== DFS_DOWNLEVEL_OPEN_CONTEXT
||
4835 DfsNameContext
->NameContextType
== DFS_CSCAGENT_NAME_CONTEXT
||
4836 DfsNameContext
->NameContextType
== DFS_USER_NAME_CONTEXT
);
4837 FileObject
->FsContext2
= NULL
;
4838 FileObject
->FsContext
= NULL
;
4840 RxContext
->pFcb
= NULL
;
4841 RxContext
->Create
.ReturnedCreateInformation
= 0;
4843 /* if we stripped last \, it has to be a directory! */
4844 if (BooleanFlagOn(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
))
4846 SetFlag(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DIRECTORY_FILE
);
4849 RxContext
->Create
.EaLength
= Stack
->Parameters
.Create
.EaLength
;
4850 if (RxContext
->Create
.EaLength
== 0)
4852 RxContext
->Create
.EaBuffer
= NULL
;
4856 RxContext
->Create
.EaBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
4857 DPRINT("EA Buffer: %p, Length: %lx\n", Irp
->AssociatedIrp
.SystemBuffer
, RxContext
->Create
.EaLength
);
4862 RxCreateFromNetRoot(
4863 PRX_CONTEXT Context
,
4864 PUNICODE_STRING NetRootName
)
4869 PFILE_OBJECT FileObject
;
4870 PIO_STACK_LOCATION Stack
;
4871 ACCESS_MASK DesiredAccess
;
4872 USHORT DesiredShareAccess
;
4876 /* Validate that the context is consistent */
4877 if (Context
->Create
.pNetRoot
== NULL
)
4879 return STATUS_BAD_NETWORK_PATH
;
4882 NetRoot
= (PNET_ROOT
)Context
->Create
.pNetRoot
;
4883 if (Context
->RxDeviceObject
!= NetRoot
->pSrvCall
->RxDeviceObject
)
4885 return STATUS_BAD_NETWORK_PATH
;
4888 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) &&
4889 !BooleanFlagOn(NetRoot
->pSrvCall
->Flags
, SRVCALL_FLAG_DFS_AWARE_SERVER
))
4891 return STATUS_DFS_UNAVAILABLE
;
4894 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
4895 BooleanFlagOn(NetRoot
->Flags
, NETROOT_FLAG_DFS_AWARE_NETROOT
))
4897 return STATUS_OBJECT_TYPE_MISMATCH
;
4900 Stack
= Context
->CurrentIrpSp
;
4901 DesiredShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
4902 if (NetRoot
->Type
== NET_ROOT_PRINT
)
4904 DesiredShareAccess
= FILE_SHARE_VALID_FLAGS
;
4907 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
4909 /* We don't support renaming yet */
4910 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
4913 return STATUS_NOT_IMPLEMENTED
;
4916 /* Try to find (or create) the FCB for the file */
4917 Status
= RxFindOrCreateFcb(Context
, NetRootName
);
4918 Fcb
= (PFCB
)Context
->pFcb
;
4921 ASSERT(!NT_SUCCESS(Status
));
4923 if (!NT_SUCCESS(Status
) || Fcb
== NULL
)
4928 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_CREATE_MAILSLOT
))
4930 Fcb
->Header
.NodeTypeCode
= RDBSS_NTC_MAILSLOT
;
4934 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
4937 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
4938 if (NT_SUCCESS(Status
))
4940 RxTransitionNetFcb(Fcb
, Condition_Good
);
4941 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb
, Fcb
->Condition
);
4943 RxSetupNetFileObject(Context
);
4944 return STATUS_SUCCESS
;
4948 FileObject
= Stack
->FileObject
;
4949 /* Check SA for conflict */
4950 if (Fcb
->OpenCount
> 0)
4952 Status
= RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
4953 &Fcb
->ShareAccess
, FALSE
, "early check per useropens", "EarlyPerUO");
4954 if (!NT_SUCCESS(Status
))
4956 RxDereferenceNetFcb(Fcb
);
4961 if (BooleanFlagOn(Context
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
) &&
4962 !BooleanFlagOn(Context
->Create
.NtCreateParameters
.DesiredAccess
, ~SYNCHRONIZE
))
4969 /* Find a SRV_OPEN that suits the opening */
4970 Status
= RxCollapseOrCreateSrvOpen(Context
);
4971 if (Status
== STATUS_SUCCESS
)
4976 SrvOpen
= (PSRV_OPEN
)Context
->pRelevantSrvOpen
;
4977 Fobx
= (PFOBX
)Context
->pFobx
;
4978 /* There are already opens, check for conflict */
4979 if (Fcb
->OpenCount
!= 0)
4981 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
,
4982 FileObject
, &Fcb
->ShareAccess
,
4983 FALSE
, "second check per useropens",
4986 ++SrvOpen
->UncleanFobxCount
;
4987 RxDereferenceNetFobx(Fobx
, LHS_LockNotHeld
);
4994 if (NetRoot
->Type
!= NET_ROOT_PIPE
)
4996 RxSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
4997 &Fcb
->ShareAccess
, "initial shareaccess setup", "InitShrAcc");
5001 RxSetupNetFileObject(Context
);
5003 /* No conflict? Set up SA */
5004 if (Fcb
->OpenCount
!= 0 && NetRoot
->Type
!= NET_ROOT_PIPE
)
5006 RxUpdateShareAccess(FileObject
, &Fcb
->ShareAccess
, "update share access", "UpdShrAcc");
5009 ++Fcb
->UncleanCount
;
5010 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
5012 ++Fcb
->UncachedUncleanCount
;
5015 if (SrvOpen
->UncleanFobxCount
== 0 && Fcb
->UncleanCount
== 1 &&
5016 !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE
))
5018 RxChangeBufferingState(SrvOpen
, NULL
, FALSE
);
5021 /* No pending close, we're active */
5022 ClearFlag(Fcb
->FcbState
, FCB_STATE_DELAY_CLOSE
);
5025 ++SrvOpen
->UncleanFobxCount
;
5026 ++SrvOpen
->OpenCount
;
5027 SrvOpen
->ulFileSizeVersion
= Fcb
->ulFileSizeVersion
;
5029 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NO_INTERMEDIATE_BUFFERING
))
5031 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
);
5032 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
);
5034 ClearFlag(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
);
5035 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
5037 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, TRUE
, TRUE
);
5040 /* Now, update SA for the SRV_OPEN */
5041 RxUpdateShareAccessPerSrvOpens(SrvOpen
);
5043 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
5045 SetFlag(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
);
5048 /* Update the FOBX info */
5051 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
5053 SetFlag(FileObject
->Flags
, FO_NAMED_PIPE
);
5056 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PRINT
||
5057 Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
5059 Fobx
->PipeHandleInformation
= &Fobx
->Specific
.NamedPipe
.PipeHandleInformation
;
5061 Fobx
->Specific
.NamedPipe
.CollectDataTime
.QuadPart
= 0;
5062 Fobx
->Specific
.NamedPipe
.CollectDataSize
= Context
->Create
.pNetRoot
->NamedPipeParameters
.DataCollectionSize
;
5064 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.TypeOfPipe
= Context
->Create
.PipeType
;
5065 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.ReadMode
= Context
->Create
.PipeReadMode
;
5066 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.CompletionMode
= Context
->Create
.PipeCompletionMode
;
5068 InitializeListHead(&Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
5069 InitializeListHead(&Fobx
->Specific
.NamedPipe
.WriteSerializationQueue
);
5073 Status
= STATUS_SUCCESS
;
5078 if (Fcb
->OpenCount
== 0)
5080 if (Context
->Create
.FcbAcquired
)
5082 Context
->Create
.FcbAcquired
= (RxDereferenceAndFinalizeNetFcb(Fcb
,
5086 if (!Context
->Create
.FcbAcquired
)
5088 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
5094 RxDereferenceNetFcb(Fcb
);
5106 RxCreateTreeConnect(
5107 IN PRX_CONTEXT RxContext
)
5110 PV_NET_ROOT VNetRoot
;
5111 PFILE_OBJECT FileObject
;
5112 PIO_STACK_LOCATION Stack
;
5113 NET_ROOT_TYPE NetRootType
;
5114 UNICODE_STRING CanonicalName
, RemainingName
;
5118 Stack
= RxContext
->CurrentIrpSp
;
5119 FileObject
= Stack
->FileObject
;
5121 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
5122 /* As long as we don't know connection type, mark it wild */
5123 NetRootType
= NET_ROOT_WILD
;
5124 /* Get the type by parsing the name */
5125 Status
= RxFirstCanonicalize(RxContext
, &FileObject
->FileName
, &CanonicalName
, &NetRootType
);
5126 if (!NT_SUCCESS(Status
))
5131 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
5132 RxContext
->Create
.TreeConnectOpenDeferred
= FALSE
;
5133 RtlInitEmptyUnicodeString(&RxContext
->Create
.TransportName
, NULL
, 0);
5134 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserName
, NULL
, 0);
5135 RtlInitEmptyUnicodeString(&RxContext
->Create
.Password
, NULL
, 0);
5136 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserDomainName
, NULL
, 0);
5138 /* We don't handle EA - they come from DFS, don't care */
5139 if (Stack
->Parameters
.Create
.EaLength
> 0)
5144 /* Mount if required */
5145 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
5146 if (Status
== STATUS_NETWORK_CREDENTIAL_CONFLICT
)
5148 RxScavengeVNetRoots(RxContext
->RxDeviceObject
);
5149 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
5152 if (!NT_SUCCESS(Status
))
5157 /* Validate the rest of the name with mini-rdr */
5158 if (RemainingName
.Length
> 0)
5160 MINIRDR_CALL(Status
, RxContext
,
5161 RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
5162 MRxIsValidDirectory
, (RxContext
, &RemainingName
));
5165 if (!NT_SUCCESS(Status
))
5170 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
5171 RxReferenceVNetRoot(VNetRoot
);
5172 if (InterlockedCompareExchange(&VNetRoot
->AdditionalReferenceForDeleteFsctlTaken
, 1, 0) != 0)
5174 RxDereferenceVNetRoot(VNetRoot
, LHS_LockNotHeld
);
5177 FileObject
->FsContext
= &RxDeviceFCB
;
5178 FileObject
->FsContext2
= VNetRoot
;
5180 VNetRoot
->ConstructionStatus
= STATUS_SUCCESS
;
5181 ++VNetRoot
->NumberOfOpens
;
5183 /* Create is over - clear context */
5184 RxContext
->Create
.pSrvCall
= NULL
;
5185 RxContext
->Create
.pNetRoot
= NULL
;
5186 RxContext
->Create
.pVNetRoot
= NULL
;
5193 RxDebugControlCommand(
5194 _In_ PSTR ControlString
)
5202 IN PDRIVER_OBJECT DriverObject
,
5203 IN PUNICODE_STRING RegistryPath
)
5206 USHORT i
, State
= 0;
5208 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject
, RegistryPath
);
5212 RxCheckFcbStructuresForAlignment();
5214 RtlZeroMemory(&RxData
, sizeof(RxData
));
5215 RxData
.NodeTypeCode
= RDBSS_NTC_DATA_HEADER
;
5216 RxData
.NodeByteSize
= sizeof(RxData
);
5217 RxData
.DriverObject
= DriverObject
;
5219 RtlZeroMemory(&RxDeviceFCB
, sizeof(RxDeviceFCB
));
5220 RxDeviceFCB
.spacer
.NodeTypeCode
= RDBSS_NTC_DEVICE_FCB
;
5221 RxDeviceFCB
.spacer
.NodeByteSize
= sizeof(RxDeviceFCB
);
5223 KeInitializeSpinLock(&RxStrucSupSpinLock
);
5224 RxExports
.pRxStrucSupSpinLock
= &RxStrucSupSpinLock
;
5226 RxInitializeDebugSupport();
5228 RxFileSystemDeviceObject
= (PRDBSS_DEVICE_OBJECT
)&RxSpaceForTheWrappersDeviceObject
;
5229 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject
, sizeof(RxSpaceForTheWrappersDeviceObject
));
5234 RxGetRegistryParameters(RegistryPath
);
5235 RxReadRegistryParameters();
5237 Status
= RxInitializeRegistrationStructures();
5238 if (!NT_SUCCESS(Status
))
5244 RxInitializeDispatcher();
5246 ExInitializeNPagedLookasideList(&RxContextLookasideList
, RxAllocatePoolWithTag
, RxFreePool
, 0, sizeof(RX_CONTEXT
), RX_IRPC_POOLTAG
, 4);
5248 InitializeListHead(&RxIrpsList
);
5249 KeInitializeSpinLock(&RxIrpsListSpinLock
);
5251 InitializeListHead(&RxActiveContexts
);
5252 InitializeListHead(&RxSrvCalldownList
);
5254 ExInitializeFastMutex(&RxContextPerFileSerializationMutex
);
5255 ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex
);
5256 KeInitializeMutex(&RxScavengerMutex
, 1);
5257 KeInitializeMutex(&RxSerializationMutex
, 1);
5259 for (i
= 0; i
< RxMaximumWorkQueue
; ++i
)
5261 RxFileSystemDeviceObject
->PostedRequestCount
[i
] = 0;
5262 RxFileSystemDeviceObject
->OverflowQueueCount
[i
] = 0;
5263 InitializeListHead(&RxFileSystemDeviceObject
->OverflowQueue
[i
]);
5266 KeInitializeSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
);
5268 RxInitializeDispatchVectors(DriverObject
);
5270 ExInitializeResourceLite(&RxData
.Resource
);
5271 RxData
.OurProcess
= IoGetCurrentProcess();
5273 RxInitializeRxTimer();
5277 if (!NT_SUCCESS(Status
))
5279 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BC4, Status
);
5280 RxInitUnwind(DriverObject
, State
);
5284 /* There are still bits to init - be consider it's fine for now */
5287 return STATUS_NOT_IMPLEMENTED
;
5289 return STATUS_SUCCESS
;
5297 RxDumpCurrentAccess(
5300 _In_ PSZ wherelogtag
,
5301 _In_ PSHARE_ACCESS ShareAccess
)
5313 _In_ PSZ wherelogtag
,
5314 _In_ ACCESS_MASK DesiredAccess
,
5315 _In_ ULONG DesiredShareAccess
)
5325 RxFastIoCheckIfPossible(
5326 PFILE_OBJECT FileObject
,
5327 PLARGE_INTEGER FileOffset
,
5328 ULONG Length
, BOOLEAN Wait
,
5329 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
5330 PIO_STATUS_BLOCK IoStatus
,
5331 PDEVICE_OBJECT DeviceObject
)
5335 LARGE_INTEGER LargeLength
;
5339 /* Get the FCB to validate it */
5340 Fcb
= FileObject
->FsContext
;
5341 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
)
5343 DPRINT1("Not a file, FastIO not possible!\n");
5347 if (FileObject
->DeletePending
)
5349 DPRINT1("File delete pending\n");
5353 /* If there's a pending write operation, deny fast operation */
5354 if (Fcb
->NonPaged
->OutstandingAsyncWrites
!= 0)
5356 DPRINT1("Write operations to be completed\n");
5360 /* Deny read on orphaned node */
5361 SrvOpen
= (PSRV_OPEN
)((PFOBX
)FileObject
->FsContext2
)->pSrvOpen
;
5362 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
5364 DPRINT1("SRV_OPEN orphaned\n");
5368 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
5370 DPRINT1("FCB orphaned\n");
5374 /* If there's a buffering state change pending, deny fast operation (it might change
5377 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
))
5379 DPRINT1("Buffering change pending\n");
5383 /* File got renamed/deleted, deny operation */
5384 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_DELETED
) ||
5385 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_RENAMED
))
5387 DPRINT1("File renamed/deleted\n");
5391 /* Process pending change buffering state operations */
5392 FsRtlEnterFileSystem();
5393 RxProcessChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
5394 FsRtlExitFileSystem();
5396 LargeLength
.QuadPart
= Length
;
5398 /* If operation to come is a read operation */
5399 if (CheckForReadOperation
)
5401 /* Check that read cache is enabled */
5402 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
5404 DPRINT1("Read caching disabled\n");
5408 /* Check whether there's a lock conflict */
5409 if (!FsRtlFastCheckLockForRead(&Fcb
->Specific
.Fcb
.FileLock
,
5414 PsGetCurrentProcess()))
5416 DPRINT1("FsRtlFastCheckLockForRead failed\n");
5423 /* Check that write cache is enabled */
5424 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
))
5426 DPRINT1("Write caching disabled\n");
5430 /* Check whether there's a lock conflict */
5431 if (!FsRtlFastCheckLockForWrite(&Fcb
->Specific
.Fcb
.FileLock
,
5436 PsGetCurrentProcess()))
5438 DPRINT1("FsRtlFastCheckLockForWrite failed\n");
5447 RxFastIoDeviceControl(
5448 PFILE_OBJECT FileObject
,
5450 PVOID InputBuffer OPTIONAL
,
5451 ULONG InputBufferLength
,
5452 PVOID OutputBuffer OPTIONAL
,
5453 ULONG OutputBufferLength
,
5454 ULONG IoControlCode
,
5455 PIO_STATUS_BLOCK IoStatus
,
5456 PDEVICE_OBJECT DeviceObject
)
5458 /* Only supported IOCTL */
5459 if (IoControlCode
== IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
)
5476 PFILE_OBJECT FileObject
,
5477 PLARGE_INTEGER FileOffset
,
5482 PIO_STATUS_BLOCK IoStatus
,
5483 PDEVICE_OBJECT DeviceObject
)
5486 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
5490 DPRINT("RxFastIoRead: %p (%p, %p)\n", FileObject
, FileObject
->FsContext
,
5491 FileObject
->FsContext2
);
5492 DPRINT("Reading %ld at %I64x\n", Length
, FileOffset
->QuadPart
);
5494 /* Prepare a TLI context */
5495 ASSERT(RxIsThisTheTopLevelIrp(NULL
));
5496 RxInitializeTopLevelIrpContext(&TopLevelContext
, (PIRP
)FSRTL_FAST_IO_TOP_LEVEL_IRP
,
5497 (PRDBSS_DEVICE_OBJECT
)DeviceObject
);
5499 Ret
= FsRtlCopyRead2(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
,
5500 IoStatus
, DeviceObject
, &TopLevelContext
);
5503 DPRINT("Read OK\n");
5507 DPRINT1("Read failed!\n");
5519 PFILE_OBJECT FileObject
,
5520 PLARGE_INTEGER FileOffset
,
5525 PIO_STATUS_BLOCK IoStatus
,
5526 PDEVICE_OBJECT DeviceObject
)
5530 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
5534 Fobx
= (PFOBX
)FileObject
->FsContext2
;
5535 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_BAD_HANDLE
))
5540 DPRINT("RxFastIoWrite: %p (%p, %p)\n", FileObject
, FileObject
->FsContext
,
5541 FileObject
->FsContext2
);
5542 DPRINT("Writing %ld at %I64x\n", Length
, FileOffset
->QuadPart
);
5544 /* Prepare a TLI context */
5545 ASSERT(RxIsThisTheTopLevelIrp(NULL
));
5546 RxInitializeTopLevelIrpContext(&TopLevelContext
, (PIRP
)FSRTL_FAST_IO_TOP_LEVEL_IRP
,
5547 (PRDBSS_DEVICE_OBJECT
)DeviceObject
);
5549 Ret
= FsRtlCopyWrite2(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
,
5550 IoStatus
, DeviceObject
, &TopLevelContext
);
5553 DPRINT("Write OK\n");
5557 DPRINT1("Write failed!\n");
5565 PRX_CONTEXT RxContext
,
5566 PUNICODE_STRING NetRootName
)
5572 PV_NET_ROOT VNetRoot
;
5573 BOOLEAN TableAcquired
, AcquiredExclusive
;
5577 NetRoot
= (PNET_ROOT
)RxContext
->Create
.pNetRoot
;
5578 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
5579 ASSERT(NetRoot
== VNetRoot
->NetRoot
);
5581 Status
= STATUS_SUCCESS
;
5582 AcquiredExclusive
= FALSE
;
5584 RxAcquireFcbTableLockShared(&NetRoot
->FcbTable
, TRUE
);
5585 TableAcquired
= TRUE
;
5586 Version
= NetRoot
->FcbTable
.Version
;
5588 /* Look for a cached FCB */
5589 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
5592 DPRINT("RxFcbTableLookupFcb returned NULL fcb for %wZ\n", NetRootName
);
5596 DPRINT("FCB found for %wZ\n", &Fcb
->FcbTableEntry
.Path
);
5597 /* If FCB was to be orphaned, consider it as not suitable */
5598 if (Fcb
->fShouldBeOrphaned
)
5600 RxDereferenceNetFcb(Fcb
);
5601 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
5603 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
5604 TableAcquired
= TRUE
;
5605 AcquiredExclusive
= TRUE
;
5607 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
5608 if (Fcb
!= NULL
&& Fcb
->fShouldBeOrphaned
)
5610 RxOrphanThisFcb(Fcb
);
5611 RxDereferenceNetFcb(Fcb
);
5617 /* If FCB was not found or is not covering full path, prepare for more work */
5618 if (Fcb
== NULL
|| Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
5622 DPRINT1("FCB was found and it's not covering the whole path: %wZ - %wZ\n", &Fcb
->FcbTableEntry
.Path
, NetRootName
);
5625 if (!AcquiredExclusive
)
5627 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
5628 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
5629 TableAcquired
= TRUE
;
5632 /* If FCB table was updated in between, re-attempt a lookup */
5633 if (NetRoot
->FcbTable
.Version
!= Version
)
5635 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
5636 if (Fcb
!= NULL
&& Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
5643 /* Allocate the FCB */
5648 Fcb
= RxCreateNetFcb(RxContext
, VNetRoot
, NetRootName
);
5651 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5655 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5656 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
5662 if (_SEH2_AbnormalTermination())
5664 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
5665 TableAcquired
= FALSE
;
5669 RxTransitionNetFcb(Fcb
, Condition_Bad
);
5671 ExAcquireResourceExclusiveLite(Fcb
->Header
.Resource
, TRUE
);
5672 if (RxDereferenceAndFinalizeNetFcb(Fcb
, NULL
, FALSE
, FALSE
) != 0)
5674 ExReleaseResourceLite(Fcb
->Header
.Resource
);
5683 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
5686 if (!NT_SUCCESS(Status
))
5691 RxContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
5692 DPRINT("FCB %p is in condition %lx\n", Fcb
, Fcb
->Condition
);
5694 if (!RxContext
->Create
.FcbAcquired
)
5696 RxWaitForStableNetFcb(Fcb
, RxContext
);
5697 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5698 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
5705 RxFirstCanonicalize(
5706 PRX_CONTEXT RxContext
,
5707 PUNICODE_STRING FileName
,
5708 PUNICODE_STRING CanonicalName
,
5709 PNET_ROOT_TYPE NetRootType
)
5713 BOOLEAN UncName
, PrependString
, IsSpecial
;
5714 USHORT CanonicalLength
;
5715 UNICODE_STRING SessionIdString
;
5716 WCHAR SessionIdBuffer
[16];
5720 Type
= NET_ROOT_WILD
;
5721 PrependString
= FALSE
;
5724 Status
= STATUS_SUCCESS
;
5726 /* Name has to contain at least \\ */
5727 if (FileName
->Length
< 2 * sizeof(WCHAR
))
5729 return STATUS_OBJECT_NAME_INVALID
;
5732 /* First easy check, is that a path with a name? */
5733 CanonicalLength
= FileName
->Length
;
5734 if (FileName
->Length
> 5 * sizeof(WCHAR
))
5736 if (FileName
->Buffer
[0] == '\\' && FileName
->Buffer
[1] == ';')
5738 if (FileName
->Buffer
[3] == ':')
5740 Type
= NET_ROOT_DISK
;
5744 Type
= NET_ROOT_PRINT
;
5749 /* Nope, attempt deeper parsing */
5750 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
&& FileName
->Buffer
[1] != ';')
5753 PWSTR FirstSlash
, EndOfString
;
5755 SetFlag(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_UNC_NAME
);
5758 /* The lack of drive letter will be replaced by session ID */
5759 SessionId
= RxGetSessionId(RxContext
->CurrentIrpSp
);
5760 RtlInitEmptyUnicodeString(&SessionIdString
, SessionIdBuffer
, sizeof(SessionIdBuffer
));
5761 RtlIntegerToUnicodeString(SessionId
, 10, &SessionIdString
);
5763 EndOfString
= Add2Ptr(FileName
->Buffer
, FileName
->Length
);
5764 for (FirstSlash
= &FileName
->Buffer
[1]; FirstSlash
!= EndOfString
; ++FirstSlash
)
5766 if (*FirstSlash
== OBJ_NAME_PATH_SEPARATOR
)
5772 if (EndOfString
- FirstSlash
<= sizeof(WCHAR
))
5774 Status
= STATUS_OBJECT_NAME_INVALID
;
5779 DPRINT1("WARNING: Assuming not special + disk!\n");
5780 Type
= NET_ROOT_DISK
;
5781 Status
= STATUS_SUCCESS
;
5782 //Status = STATUS_NOT_IMPLEMENTED;
5783 /* Should be check against IPC, mailslot, and so on */
5787 /* Update net root type with our deduced one */
5788 *NetRootType
= Type
;
5789 DPRINT("Returning type: %x\n", Type
);
5791 if (!NT_SUCCESS(Status
))
5796 /* Do we have to prepend session ID? */
5801 PrependString
= TRUE
;
5802 CanonicalLength
+= SessionIdString
.Length
+ 3 * sizeof(WCHAR
);
5806 /* If not UNC path, we should preprend stuff */
5807 if (!PrependString
&& !IsSpecial
&& FileName
->Buffer
[0] != '\\')
5809 return STATUS_OBJECT_PATH_INVALID
;
5812 /* Allocate the buffer */
5813 Status
= RxAllocateCanonicalNameBuffer(RxContext
, CanonicalName
, CanonicalLength
);
5814 if (!NT_SUCCESS(Status
))
5819 /* We don't support that case, we always return disk */
5822 ASSERT(CanonicalName
->Length
== CanonicalLength
);
5824 Status
= STATUS_NOT_IMPLEMENTED
;
5828 /* If we have to prepend, go ahead */
5831 CanonicalName
->Buffer
[0] = '\\';
5832 CanonicalName
->Buffer
[1] = ';';
5833 CanonicalName
->Buffer
[2] = ':';
5834 CanonicalName
->Length
= 3 * sizeof(WCHAR
);
5835 RtlAppendUnicodeStringToString(CanonicalName
, &SessionIdString
);
5836 RtlAppendUnicodeStringToString(CanonicalName
, FileName
);
5838 DPRINT1("CanonicalName: %wZ\n", CanonicalName
);
5840 /* Otherwise, that's a simple copy */
5843 RtlCopyUnicodeString(CanonicalName
, FileName
);
5854 RxFreeCanonicalNameBuffer(
5855 PRX_CONTEXT Context
)
5857 /* These two buffers are always the same */
5858 ASSERT(Context
->Create
.CanonicalNameBuffer
== Context
->AlsoCanonicalNameBuffer
);
5860 if (Context
->Create
.CanonicalNameBuffer
!= NULL
)
5862 RxFreePoolWithTag(Context
->Create
.CanonicalNameBuffer
, RX_MISC_POOLTAG
);
5863 Context
->Create
.CanonicalNameBuffer
= NULL
;
5864 Context
->AlsoCanonicalNameBuffer
= NULL
;
5867 ASSERT(Context
->AlsoCanonicalNameBuffer
== NULL
);
5871 RxFsdCommonDispatch(
5872 PRX_FSD_DISPATCH_VECTOR DispatchVector
,
5873 UCHAR MajorFunction
,
5874 PIO_STACK_LOCATION Stack
,
5875 PFILE_OBJECT FileObject
,
5877 PRDBSS_DEVICE_OBJECT RxDeviceObject
)
5881 PRX_CONTEXT Context
;
5882 UCHAR MinorFunction
;
5883 PFILE_OBJECT StackFileObject
;
5884 PRX_FSD_DISPATCH DispatchFunc
;
5885 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
5886 BOOLEAN TopLevel
, Closing
, PassToDriver
, SetCancelRoutine
, PostRequest
, CanWait
;
5888 Status
= STATUS_SUCCESS
;
5890 DPRINT("RxFsdCommonDispatch(%p, %d, %p, %p, %p, %p)\n", DispatchVector
, MajorFunction
, Stack
, FileObject
, Irp
, RxDeviceObject
);
5892 FsRtlEnterFileSystem();
5894 TopLevel
= RxTryToBecomeTheTopLevelIrp(&TopLevelContext
, Irp
, RxDeviceObject
, FALSE
);
5900 PostRequest
= FALSE
;
5901 SetCancelRoutine
= TRUE
;
5902 MinorFunction
= Stack
->MinorFunction
;
5904 switch (MajorFunction
)
5906 case IRP_MJ_FILE_SYSTEM_CONTROL
:
5907 if (FileObject
!= NULL
)
5909 CanWait
= IoIsOperationSynchronous(Irp
);
5919 case IRP_MJ_QUERY_INFORMATION
:
5920 case IRP_MJ_SET_INFORMATION
:
5921 case IRP_MJ_QUERY_EA
:
5923 case IRP_MJ_FLUSH_BUFFERS
:
5924 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
5925 case IRP_MJ_SET_VOLUME_INFORMATION
:
5926 case IRP_MJ_DIRECTORY_CONTROL
:
5927 case IRP_MJ_DEVICE_CONTROL
:
5928 case IRP_MJ_LOCK_CONTROL
:
5929 case IRP_MJ_QUERY_SECURITY
:
5930 case IRP_MJ_SET_SECURITY
:
5931 CanWait
= IoIsOperationSynchronous(Irp
);
5935 case IRP_MJ_CLEANUP
:
5937 SetCancelRoutine
= FALSE
;
5944 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
5945 /* Should we stop it right now, or mini-rdr deserves to know? */
5946 PassToDriver
= TRUE
;
5947 if (RxGetRdbssState(RxDeviceObject
) != RDBSS_STARTABLE
)
5949 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& !Closing
)
5951 PassToDriver
= FALSE
;
5952 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
5953 DPRINT1("Not started!\n");
5958 if (DispatchVector
!= RxDeviceFCBVector
&& (FileObject
->FileName
.Length
!= 0 || FileObject
->RelatedFileObject
!= NULL
))
5960 PassToDriver
= FALSE
;
5961 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
5962 DPRINT1("Not started!\n");
5965 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
5967 StackFileObject
= Stack
->FileObject
;
5968 /* Make sure we don't deal with orphaned stuff */
5969 if (StackFileObject
!= NULL
&& StackFileObject
->FsContext
!= NULL
)
5971 if (StackFileObject
->FsContext2
!= UIntToPtr(DFS_OPEN_CONTEXT
) &&
5972 StackFileObject
->FsContext2
!= UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
5973 StackFileObject
->FsContext
!= &RxDeviceFCB
)
5978 Fcb
= StackFileObject
->FsContext
;
5979 Fobx
= StackFileObject
->FsContext2
;
5981 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
) ||
5982 BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
5986 PassToDriver
= TRUE
;
5990 PassToDriver
= FALSE
;
5991 Status
= STATUS_UNEXPECTED_NETWORK_ERROR
;
5992 DPRINT1("Operation on orphaned FCB: %p\n", Fcb
);
5998 /* Did we receive a close request whereas we're stopping? */
5999 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& Closing
)
6003 Fcb
= StackFileObject
->FsContext
;
6005 DPRINT1("Close received after stop\n");
6006 DPRINT1("Irp: %p %d:%d FO: %p FCB: %p\n",
6007 Irp
, Stack
->MajorFunction
, Stack
->MinorFunction
, StackFileObject
, Fcb
);
6009 if (Fcb
!= NULL
&& Fcb
!= &RxDeviceFCB
&&
6012 DPRINT1("OpenCount: %ld, UncleanCount: %ld, Name: %wZ\n",
6013 Fcb
->OpenCount
, Fcb
->UncleanCount
, &Fcb
->FcbTableEntry
.Path
);
6017 /* Should we stop the whole thing now? */
6020 if (MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
|| MinorFunction
!= IRP_MN_REMOVE_DEVICE
)
6022 IoMarkIrpPending(Irp
);
6023 Irp
->IoStatus
.Status
= Status
;
6024 Irp
->IoStatus
.Information
= 0;
6025 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
6026 Status
= STATUS_PENDING
;
6030 Irp
->IoStatus
.Status
= Status
;
6031 Irp
->IoStatus
.Information
= 0;
6032 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
6038 /* No? Allocate a context to deal with the mini-rdr */
6039 Context
= RxCreateRxContext(Irp
, RxDeviceObject
, (CanWait
? RX_CONTEXT_FLAG_WAIT
: 0));
6040 if (Context
== NULL
)
6042 Status
= STATUS_INSUFFICIENT_RESOURCES
;
6043 RxCompleteRequest_Real(RxNull
, Irp
, STATUS_INSUFFICIENT_RESOURCES
);
6047 /* Set cancel routine if required */
6048 if (SetCancelRoutine
)
6050 IoAcquireCancelSpinLock(&OldIrql
);
6051 IoSetCancelRoutine(Irp
, RxCancelRoutine
);
6055 IoAcquireCancelSpinLock(&OldIrql
);
6056 IoSetCancelRoutine(Irp
, NULL
);
6058 IoReleaseCancelSpinLock(OldIrql
);
6060 ASSERT(MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
6062 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
6063 Irp
->IoStatus
.Information
= 0;
6064 /* Get the dispatch routine */
6065 DispatchFunc
= DispatchVector
[MajorFunction
].CommonRoutine
;
6067 if (MajorFunction
== IRP_MJ_READ
|| MajorFunction
== IRP_MJ_WRITE
)
6069 /* Handle the complete MDL case */
6070 if (BooleanFlagOn(MinorFunction
, IRP_MN_COMPLETE
))
6072 DispatchFunc
= RxCompleteMdl
;
6076 /* Do we have to post request? */
6077 if (BooleanFlagOn(MinorFunction
, IRP_MN_DPC
))
6083 /* Our read function needs stack, make sure we won't overflow,
6084 * otherwise, post the request
6086 if (MajorFunction
== IRP_MJ_READ
)
6088 if (IoGetRemainingStackSize() < 0xE00)
6090 Context
->PendingReturned
= TRUE
;
6091 Status
= RxPostStackOverflowRead(Context
);
6092 if (Status
!= STATUS_PENDING
)
6094 Context
->PendingReturned
= FALSE
;
6095 RxCompleteAsynchronousRequest(Context
, Status
);
6105 Context
->ResumeRoutine
= DispatchFunc
;
6106 /* There's a dispatch routine? Time to dispatch! */
6107 if (DispatchFunc
!= NULL
)
6109 Context
->PendingReturned
= TRUE
;
6112 Status
= RxFsdPostRequest(Context
);
6116 /* Retry as long as we have */
6119 Status
= DispatchFunc(Context
);
6121 while (Status
== STATUS_RETRY
);
6123 if (Status
== STATUS_PENDING
)
6128 /* Sanity check: did someone mess with our context? */
6129 if (Context
->CurrentIrp
!= Irp
|| Context
->CurrentIrpSp
!= Stack
||
6130 Context
->MajorFunction
!= MajorFunction
|| Stack
->MinorFunction
!= MinorFunction
)
6132 DPRINT1("RX_CONTEXT %p has been contaminated!\n", Context
);
6133 DPRINT1("->CurrentIrp %p %p\n", Context
->CurrentIrp
, Irp
);
6134 DPRINT1("->CurrentIrpSp %p %p\n", Context
->CurrentIrpSp
, Stack
);
6135 DPRINT1("->MajorFunction %d %d\n", Context
->MajorFunction
, MajorFunction
);
6136 DPRINT1("->MinorFunction %d %d\n", Context
->MinorFunction
, MinorFunction
);
6138 Context
->PendingReturned
= FALSE
;
6139 Status
= RxCompleteAsynchronousRequest(Context
, Status
);
6144 Status
= STATUS_NOT_IMPLEMENTED
;
6151 RxUnwindTopLevelIrp(&TopLevelContext
);
6154 FsRtlExitFileSystem();
6158 DPRINT("RxFsdDispatch, Status: %lx\n", Status
);
6168 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6172 PIO_STACK_LOCATION Stack
;
6173 PRX_FSD_DISPATCH_VECTOR DispatchVector
;
6177 DPRINT("RxFsdDispatch(%p, %p)\n", RxDeviceObject
, Irp
);
6179 Stack
= IoGetCurrentIrpStackLocation(Irp
);
6181 /* Dispatch easy case */
6182 if (Stack
->MajorFunction
== IRP_MJ_SYSTEM_CONTROL
)
6184 return RxSystemControl(RxDeviceObject
, Irp
);
6187 /* Bail out broken cases */
6188 if (Stack
->MajorFunction
== IRP_MJ_CREATE_MAILSLOT
||
6189 Stack
->MajorFunction
== IRP_MJ_CREATE_NAMED_PIPE
)
6191 IoMarkIrpPending(Irp
);
6192 Irp
->IoStatus
.Information
= 0;
6193 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_INVALID
;
6194 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
6195 return STATUS_PENDING
;
6198 /* Immediately handle create */
6199 if (Stack
->MajorFunction
== IRP_MJ_CREATE
)
6201 return RxFsdCommonDispatch(&RxFsdDispatchVector
[0], Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
6204 /* If not a creation, we must have at least a FO with a FCB */
6205 if (Stack
->FileObject
== NULL
|| Stack
->FileObject
->FsContext
== NULL
)
6207 IoMarkIrpPending(Irp
);
6208 Irp
->IoStatus
.Information
= 0;
6209 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
6210 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
6211 return STATUS_PENDING
;
6214 /* Set the dispatch vector if required */
6215 Fcb
= Stack
->FileObject
->FsContext
;
6216 if (!NodeTypeIsFcb(Fcb
) || Fcb
->PrivateDispatchVector
== NULL
)
6218 DispatchVector
= &RxFsdDispatchVector
[0];
6222 DispatchVector
= Fcb
->PrivateDispatchVector
;
6225 /* Device cannot accept such requests */
6226 if (RxDeviceObject
== RxFileSystemDeviceObject
)
6228 IoMarkIrpPending(Irp
);
6229 Irp
->IoStatus
.Information
= 0;
6230 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
6231 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
6232 return STATUS_PENDING
;
6235 /* Dispatch for real! */
6236 return RxFsdCommonDispatch(DispatchVector
, Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
6244 IN PRX_CONTEXT RxContext
)
6246 /* Initialize posting if required */
6247 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
6249 RxPrePostIrp(RxContext
, RxContext
->CurrentIrp
);
6252 DPRINT("Posting MN: %d, Ctxt: %p, IRP: %p, Thrd: %lx #%lx\n",
6253 RxContext
->MinorFunction
, RxContext
,
6254 RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
6255 RxContext
->SerialNumber
);
6257 RxAddToWorkque(RxContext
, RxContext
->CurrentIrp
);
6258 return STATUS_PENDING
;
6270 WORK_QUEUE_TYPE Queue
;
6271 PRDBSS_DEVICE_OBJECT VolumeDO
;
6272 PRX_CONTEXT RxContext
, EntryContext
;
6276 RxContext
= Context
;
6277 EntryContext
= Context
;
6278 /* Save IRQL at entry for later checking */
6279 EntryIrql
= KeGetCurrentIrql();
6281 /* No FO, deal with device */
6282 if (RxContext
->CurrentIrpSp
->FileObject
!= NULL
)
6284 VolumeDO
= RxFileSystemDeviceObject
;
6291 /* Which queue to used for delayed? */
6292 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
))
6294 Queue
= DelayedWorkQueue
;
6298 ASSERT(BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
6299 Queue
= CriticalWorkQueue
;
6306 BOOLEAN RecursiveCall
;
6307 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
6309 ASSERT(RxContext
->MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
6310 ASSERT(!RxContext
->PostRequest
);
6312 RxContext
->LastExecutionThread
= PsGetCurrentThread();
6313 SetFlag(RxContext
->Flags
, (RX_CONTEXT_FLAG_IN_FSP
| RX_CONTEXT_FLAG_WAIT
));
6315 DPRINT("Dispatch: MN: %d, Ctxt: %p, IRP: %p, THRD: %lx #%lx\n", RxContext
->MinorFunction
,
6316 RxContext
, RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
6317 RxContext
->SerialNumber
);
6319 Irp
= RxContext
->CurrentIrp
;
6321 FsRtlEnterFileSystem();
6323 RecursiveCall
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
);
6324 RxTryToBecomeTheTopLevelIrp(&TopLevelContext
,
6325 (RecursiveCall
? (PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
: RxContext
->CurrentIrp
),
6326 RxContext
->RxDeviceObject
, TRUE
);
6328 ASSERT(RxContext
->ResumeRoutine
!= NULL
);
6330 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_DPC
) && Irp
->Tail
.Overlay
.Thread
== NULL
)
6332 ASSERT((RxContext
->MajorFunction
== IRP_MJ_WRITE
) || (RxContext
->MajorFunction
== IRP_MJ_READ
));
6333 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
6336 /* Call the resume routine */
6341 NoComplete
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_COMPLETE_FROM_FSP
);
6343 Status
= RxContext
->ResumeRoutine(RxContext
);
6344 if (!NoComplete
&& Status
!= STATUS_PENDING
)
6346 if (Status
!= STATUS_RETRY
)
6348 Status
= RxCompleteRequest(RxContext
, Status
);
6352 while (Status
== STATUS_RETRY
);
6354 RxUnwindTopLevelIrp(&TopLevelContext
);
6355 FsRtlExitFileSystem();
6357 if (VolumeDO
!= NULL
)
6359 RxContext
= RxRemoveOverflowEntry(VolumeDO
, Queue
);
6365 } while (RxContext
!= NULL
);
6367 /* Did we mess with IRQL? */
6368 if (KeGetCurrentIrql() >= APC_LEVEL
)
6370 DPRINT1("High IRQL for Ctxt %p, on entry: %x\n", EntryContext
, EntryIrql
);
6378 RxGetNetworkProviderPriority(
6379 PUNICODE_STRING DeviceName
)
6390 RxGetRegistryParameters(
6391 IN PUNICODE_STRING RegistryPath
)
6395 UCHAR Buffer
[0x400];
6396 HANDLE DriverHandle
, KeyHandle
;
6397 UNICODE_STRING KeyName
, OutString
;
6398 OBJECT_ATTRIBUTES ObjectAttributes
;
6402 InitializeObjectAttributes(&ObjectAttributes
, RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
6403 Status
= ZwOpenKey(&DriverHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
6404 if (!NT_SUCCESS(Status
))
6409 RtlInitUnicodeString(&KeyName
, L
"Parameters");
6410 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, DriverHandle
, FALSE
);
6411 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
6412 if (NT_SUCCESS(Status
))
6414 /* The only parameter we deal with is InitialDebugString */
6415 RxGetStringRegistryParameter(KeyHandle
, L
"InitialDebugString", &OutString
, Buffer
, sizeof(Buffer
), 0);
6416 if (OutString
.Length
!= 0 && OutString
.Length
< 0x140)
6421 Read
= OutString
.Buffer
;
6422 Write
= (PSTR
)OutString
.Buffer
;
6423 for (i
= 0; i
< OutString
.Length
; ++i
)
6431 /* Which is a string we'll just write out */
6432 DPRINT("InitialDebugString read from registry: '%s'\n", OutString
.Buffer
);
6433 RxDebugControlCommand((PSTR
)OutString
.Buffer
);
6439 ZwClose(DriverHandle
);
6447 IN PIO_STACK_LOCATION IrpSp
)
6450 PACCESS_TOKEN Token
;
6451 PIO_SECURITY_CONTEXT SecurityContext
;
6455 /* If that's not a prefix claim, not an open request, session id will be 0 */
6456 if (IrpSp
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
|| IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_REDIR_QUERY_PATH
)
6458 if (IrpSp
->MajorFunction
!= IRP_MJ_CREATE
|| IrpSp
->Parameters
.Create
.SecurityContext
== NULL
)
6463 SecurityContext
= IrpSp
->Parameters
.Create
.SecurityContext
;
6467 SecurityContext
= ((PQUERY_PATH_REQUEST
)IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
)->SecurityContext
;
6470 /* Query the session id */
6471 Token
= SeQuerySubjectContextToken(&SecurityContext
->AccessState
->SubjectSecurityContext
);
6472 SeQuerySessionIdToken(Token
, &SessionId
);
6482 RxGetStringRegistryParameter(
6483 IN HANDLE KeyHandle
,
6485 OUT PUNICODE_STRING OutString
,
6487 IN ULONG BufferLength
,
6488 IN BOOLEAN LogFailure
)
6492 UNICODE_STRING KeyString
;
6496 RtlInitUnicodeString(&KeyString
, KeyName
);
6497 Status
= ZwQueryValueKey(KeyHandle
, &KeyString
, KeyValuePartialInformation
, Buffer
, BufferLength
, &ResultLength
);
6498 OutString
->Length
= 0;
6499 OutString
->Buffer
= 0;
6500 if (!NT_SUCCESS(Status
))
6504 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BD3, Status
);
6510 OutString
->Buffer
= (PWSTR
)(((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->Data
);
6511 OutString
->Length
= ((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->DataLength
- sizeof(UNICODE_NULL
);
6512 OutString
->MaximumLength
= OutString
->Length
;
6514 return STATUS_SUCCESS
;
6520 PRDBSS_DEVICE_OBJECT
6521 RxGetTopDeviceObjectIfRdbssIrp(
6525 PRDBSS_DEVICE_OBJECT TopDevice
= NULL
;
6527 TopLevelIrp
= IoGetTopLevelIrp();
6528 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
6530 TopDevice
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->RxDeviceObject
;
6540 RxGetTopIrpIfRdbssIrp(
6544 PRX_TOPLEVELIRP_CONTEXT TopLevel
;
6546 TopLevel
= (PRX_TOPLEVELIRP_CONTEXT
)IoGetTopLevelIrp();
6547 if (RxIsThisAnRdbssTopLevelContext(TopLevel
))
6549 Irp
= TopLevel
->Irp
;
6560 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
6563 PACCESS_TOKEN Token
;
6567 Token
= SeQuerySubjectContextToken(SubjectSecurityContext
);
6568 SeQueryAuthenticationIdToken(Token
, &Luid
);
6575 RxIndicateChangeOfBufferingStateForSrvOpen(
6576 PMRX_SRV_CALL SrvCall
,
6577 PMRX_SRV_OPEN SrvOpen
,
6586 RxInitializeDebugSupport(
6597 RxInitializeDispatchVectors(
6598 PDRIVER_OBJECT DriverObject
)
6604 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; ++i
)
6606 DriverObject
->MajorFunction
[i
] = (PDRIVER_DISPATCH
)RxFsdDispatch
;
6609 RxDeviceFCB
.PrivateDispatchVector
= RxDeviceFCBVector
;
6610 ASSERT(RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
6611 ASSERT(RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
6613 DriverObject
->FastIoDispatch
= &RxFastIoDispatch
;
6614 RxFastIoDispatch
.SizeOfFastIoDispatch
= sizeof(RxFastIoDispatch
);
6615 RxFastIoDispatch
.FastIoCheckIfPossible
= RxFastIoCheckIfPossible
;
6616 RxFastIoDispatch
.FastIoRead
= RxFastIoRead
;
6617 RxFastIoDispatch
.FastIoWrite
= RxFastIoWrite
;
6618 RxFastIoDispatch
.FastIoQueryBasicInfo
= NULL
;
6619 RxFastIoDispatch
.FastIoQueryStandardInfo
= NULL
;
6620 RxFastIoDispatch
.FastIoLock
= NULL
;
6621 RxFastIoDispatch
.FastIoUnlockSingle
= NULL
;
6622 RxFastIoDispatch
.FastIoUnlockAll
= NULL
;
6623 RxFastIoDispatch
.FastIoUnlockAllByKey
= NULL
;
6624 RxFastIoDispatch
.FastIoDeviceControl
= RxFastIoDeviceControl
;
6625 RxFastIoDispatch
.AcquireFileForNtCreateSection
= RxAcquireFileForNtCreateSection
;
6626 RxFastIoDispatch
.ReleaseFileForNtCreateSection
= RxReleaseFileForNtCreateSection
;
6627 RxFastIoDispatch
.AcquireForCcFlush
= RxAcquireForCcFlush
;
6628 RxFastIoDispatch
.ReleaseForCcFlush
= RxReleaseForCcFlush
;
6630 RxInitializeTopLevelIrpPackage();
6632 RxData
.CacheManagerCallbacks
.AcquireForLazyWrite
= RxAcquireFcbForLazyWrite
;
6633 RxData
.CacheManagerCallbacks
.ReleaseFromLazyWrite
= RxReleaseFcbFromLazyWrite
;
6634 RxData
.CacheManagerCallbacks
.AcquireForReadAhead
= RxAcquireFcbForReadAhead
;
6635 RxData
.CacheManagerCallbacks
.ReleaseFromReadAhead
= RxReleaseFcbFromReadAhead
;
6637 RxData
.CacheManagerNoOpCallbacks
.AcquireForLazyWrite
= RxNoOpAcquire
;
6638 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromLazyWrite
= RxNoOpRelease
;
6639 RxData
.CacheManagerNoOpCallbacks
.AcquireForReadAhead
= RxNoOpAcquire
;
6640 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromReadAhead
= RxNoOpRelease
;
6649 return STATUS_NOT_IMPLEMENTED
;
6656 RxInitializeMinirdrDispatchTable(
6657 IN PDRIVER_OBJECT DriverObject
)
6667 RxInitializeRegistrationStructures(
6672 ExInitializeFastMutex(&RxData
.MinirdrRegistrationMutex
);
6673 RxData
.NumberOfMinirdrsRegistered
= 0;
6674 RxData
.NumberOfMinirdrsStarted
= 0;
6675 InitializeListHead(&RxData
.RegisteredMiniRdrs
);
6677 return STATUS_SUCCESS
;
6685 RxInitializeTopLevelIrpPackage(
6688 KeInitializeSpinLock(&TopLevelIrpSpinLock
);
6689 InitializeListHead(&TopLevelIrpAllocatedContextsList
);
6695 PDRIVER_OBJECT DriverObject
,
6705 RxIsMemberOfTopLevelIrpAllocatedContextsList(
6706 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6709 PLIST_ENTRY NextEntry
;
6710 BOOLEAN Found
= FALSE
;
6711 PRX_TOPLEVELIRP_CONTEXT ListContext
;
6713 /* Browse all the allocated TLC to find ours */
6714 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
6715 for (NextEntry
= TopLevelIrpAllocatedContextsList
.Flink
;
6716 NextEntry
!= &TopLevelIrpAllocatedContextsList
;
6717 NextEntry
= NextEntry
->Flink
)
6719 ListContext
= CONTAINING_RECORD(NextEntry
, RX_TOPLEVELIRP_CONTEXT
, ListEntry
);
6720 ASSERT(ListContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6721 ASSERT(BooleanFlagOn(ListContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6724 if (ListContext
== TopLevelContext
)
6730 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
6744 /* No associated SRV_OPEN, it's OK to purge */
6745 if (IsListEmpty(&Fcb
->SrvOpenList
))
6750 /* Only allow to purge if all the associated SRV_OPEN
6751 * - have no outstanding opens ongoing
6752 * - have only read attribute set
6754 for (Entry
= Fcb
->SrvOpenList
.Flink
;
6755 Entry
!= &Fcb
->SrvOpenList
;
6756 Entry
= Entry
->Flink
)
6760 SrvOpen
= CONTAINING_RECORD(Entry
, SRV_OPEN
, SrvOpenQLinks
);
6762 /* Failing previous needs, don't allow purge */
6763 if (SrvOpen
->UncleanFobxCount
!= 0 ||
6764 (SrvOpen
->DesiredAccess
& 0xFFEFFFFF) != FILE_READ_ATTRIBUTES
)
6770 /* All correct, allow purge */
6778 RxIsThisAnRdbssTopLevelContext(
6779 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6781 ULONG_PTR StackTop
, StackBottom
;
6783 /* Bail out for flags */
6784 if ((ULONG_PTR
)TopLevelContext
<= FSRTL_FAST_IO_TOP_LEVEL_IRP
)
6789 /* Is our provided TLC allocated on stack? */
6790 IoGetStackLimits(&StackTop
, &StackBottom
);
6791 if ((ULONG_PTR
)TopLevelContext
<= StackBottom
- sizeof(RX_TOPLEVELIRP_CONTEXT
) &&
6792 (ULONG_PTR
)TopLevelContext
>= StackTop
)
6794 /* Yes, so check whether it's really a TLC by checking alignement & signature */
6795 if (!BooleanFlagOn((ULONG_PTR
)TopLevelContext
, 0x3) && TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
)
6803 /* No, use the helper function */
6804 return RxIsMemberOfTopLevelIrpAllocatedContextsList(TopLevelContext
);
6811 RxIsThisTheTopLevelIrp(
6816 /* When we put oursleves as top level, we set TLC as 'IRP', so look for it */
6817 TopLevelIrp
= IoGetTopLevelIrp();
6818 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
6820 TopLevelIrp
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->Irp
;
6823 return (TopLevelIrp
== Irp
);
6828 RxLockOperationCompletion(
6833 return STATUS_NOT_IMPLEMENTED
;
6842 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
6843 IN PUNICODE_STRING OriginatorId
,
6848 PUNICODE_STRING Originator
= OriginatorId
;
6849 LARGE_INTEGER LargeLine
;
6851 /* Set optional parameters */
6852 LargeLine
.QuadPart
= Line
;
6853 if (OriginatorId
== NULL
|| OriginatorId
->Length
== 0)
6855 Originator
= (PUNICODE_STRING
)&unknownId
;
6859 RxLogEventWithAnnotation(DeviceObject
, EventId
, Status
, &LargeLine
, sizeof(LargeLine
), Originator
, 1);
6864 RxLogEventWithAnnotation(
6865 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
6868 IN PVOID DataBuffer
,
6869 IN USHORT DataBufferLength
,
6870 IN PUNICODE_STRING Annotation
,
6871 IN ULONG AnnotationCount
)
6879 PRX_CONTEXT RxContext
)
6882 return STATUS_NOT_IMPLEMENTED
;
6890 RxLowIoIoCtlShellCompletion(
6891 PRX_CONTEXT RxContext
)
6898 DPRINT("RxLowIoIoCtlShellCompletion(%p)\n", RxContext
);
6900 Irp
= RxContext
->CurrentIrp
;
6901 Status
= RxContext
->IoStatusBlock
.Status
;
6903 /* Set information and status */
6904 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
)
6906 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
6909 Irp
->IoStatus
.Status
= Status
;
6915 RxLowIoLockControlShell(
6916 IN PRX_CONTEXT RxContext
)
6919 return STATUS_NOT_IMPLEMENTED
;
6927 RxLowIoNotifyChangeDirectoryCompletion(
6928 PRX_CONTEXT RxContext
)
6932 DPRINT("Completing NCD with: %lx, %lx\n", RxContext
->IoStatusBlock
.Status
, RxContext
->IoStatusBlock
.Information
);
6934 /* Just copy back the IO_STATUS to the IRP */
6935 RxSetIoStatusStatus(RxContext
, RxContext
->IoStatusBlock
.Status
);
6936 RxSetIoStatusInfo(RxContext
, RxContext
->IoStatusBlock
.Information
);
6938 return RxContext
->IoStatusBlock
.Status
;
6946 PRX_CONTEXT RxContext
)
6953 DPRINT("RxLowIoReadShell(%p)\n", RxContext
);
6955 Fcb
= (PFCB
)RxContext
->pFcb
;
6956 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
6958 return STATUS_MORE_PROCESSING_REQUIRED
;
6961 /* Always update stats for disks */
6962 if (Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
6964 ExInterlockedAddLargeStatistic(&RxContext
->RxDeviceObject
->NetworkReadBytesRequested
, RxContext
->LowIoContext
.ParamsFor
.ReadWrite
.ByteCount
);
6967 /* And forward the read to the mini-rdr */
6968 Status
= RxLowIoSubmit(RxContext
, RxLowIoReadShellCompletion
);
6969 DPRINT("RxLowIoReadShell(%p), Status: %lx\n", RxContext
, Status
);
6976 RxLowIoReadShellCompletion(
6977 PRX_CONTEXT RxContext
)
6982 BOOLEAN PagingIo
, IsPipe
;
6983 PIO_STACK_LOCATION Stack
;
6984 PLOWIO_CONTEXT LowIoContext
;
6988 DPRINT("RxLowIoReadShellCompletion(%p)\n", RxContext
);
6990 Status
= RxContext
->IoStatusBlock
.Status
;
6991 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext
, Status
, RxContext
->IoStatusBlock
.Information
);
6993 Irp
= RxContext
->CurrentIrp
;
6994 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
6996 /* Set IRP information from the RX_CONTEXT status block */
6997 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
6999 /* Fixup status for paging file if nothing was read */
7002 if (NT_SUCCESS(Status
) && RxContext
->IoStatusBlock
.Information
== 0)
7004 Status
= STATUS_END_OF_FILE
;
7008 LowIoContext
= &RxContext
->LowIoContext
;
7009 ASSERT(RxLowIoIsBufferLocked(LowIoContext
));
7011 /* Check broken cases that should never happen */
7012 Fcb
= (PFCB
)RxContext
->pFcb
;
7013 if (Status
== STATUS_FILE_LOCK_CONFLICT
)
7015 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_THIS_READ_ENLARGED
))
7018 return STATUS_RETRY
;
7021 else if (Status
== STATUS_SUCCESS
)
7023 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
))
7025 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
) ||
7026 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
))
7032 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
7038 /* Readahead should go through Cc and not finish here */
7039 ASSERT(!BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_READAHEAD
));
7041 /* If it's sync, RxCommonRead will finish the work - nothing to do here */
7042 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_SYNCCALL
))
7047 Stack
= RxContext
->CurrentIrpSp
;
7048 IsPipe
= BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
);
7049 /* Release lock if required */
7052 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
7056 /* Set FastIo if read was a success */
7057 if (NT_SUCCESS(Status
) && !IsPipe
)
7059 SetFlag(Stack
->FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
7062 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
7064 RxResumeBlockedOperations_Serially(RxContext
, &((PFOBX
)RxContext
->pFobx
)->Specific
.NamedPipe
.ReadSerializationQueue
);
7068 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
7077 /* Final sanity checks */
7078 ASSERT(Status
!= STATUS_RETRY
);
7079 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
7080 ASSERT(RxContext
->MajorFunction
== IRP_MJ_READ
);
7090 IN PRX_CONTEXT RxContext
)
7097 DPRINT("RxLowIoWriteShell(%p)\n", RxContext
);
7099 Fcb
= (PFCB
)RxContext
->pFcb
;
7101 ASSERT(!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
) &&
7102 !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
));
7104 /* Always update stats for disks */
7105 if (Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
7107 ExInterlockedAddLargeStatistic(&RxContext
->RxDeviceObject
->NetworkWriteBytesRequested
, RxContext
->LowIoContext
.ParamsFor
.ReadWrite
.ByteCount
);
7110 /* And forward the write to the mini-rdr */
7111 Status
= RxLowIoSubmit(RxContext
, RxLowIoWriteShellCompletion
);
7112 DPRINT("RxLowIoWriteShell(%p), Status: %lx\n", RxContext
, Status
);
7119 RxLowIoWriteShellCompletion(
7120 PRX_CONTEXT RxContext
)
7126 PLOWIO_CONTEXT LowIoContext
;
7130 DPRINT("RxLowIoWriteShellCompletion(%p)\n", RxContext
);
7132 Status
= RxContext
->IoStatusBlock
.Status
;
7133 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext
, Status
, RxContext
->IoStatusBlock
.Information
);
7135 Irp
= RxContext
->CurrentIrp
;
7137 /* Set IRP information from the RX_CONTEXT status block */
7138 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
7140 LowIoContext
= &RxContext
->LowIoContext
;
7141 ASSERT(RxLowIoIsBufferLocked(LowIoContext
));
7143 /* Perform a few sanity checks */
7144 Fcb
= (PFCB
)RxContext
->pFcb
;
7145 if (Status
== STATUS_SUCCESS
)
7147 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_THIS_IO_BUFFERED
))
7149 ASSERT(!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
) &&
7150 !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
));
7153 ASSERT(!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
));
7156 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
7157 if (Status
!= STATUS_SUCCESS
&& PagingIo
)
7159 DPRINT1("Paging IO failed %p (%p) %lx\n", Fcb
, Fcb
->NetRoot
, Status
);
7162 /* In case of async call, perform last bits not done in RxCommonWrite */
7163 if (!BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_SYNCCALL
))
7165 PFILE_OBJECT FileObject
;
7166 PIO_STACK_LOCATION Stack
;
7168 /* We only succeed if we wrote what was asked for */
7169 if (NT_SUCCESS(Status
) && !BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
))
7171 ASSERT(Irp
->IoStatus
.Information
== LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
);
7174 /* If write succeed, ,also update FILE_OBJECT flags */
7175 Stack
= RxContext
->CurrentIrpSp
;
7176 FileObject
= Stack
->FileObject
;
7179 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
7182 if (BooleanFlagOn(LowIoContext
->ParamsFor
.ReadWrite
.Flags
, LOWIO_READWRITEFLAG_EXTENDING_FILESIZE
))
7184 SetFlag(FileObject
->Flags
, FO_FILE_SIZE_CHANGED
);
7187 /* If VDL was extended, fix attributes */
7188 if (BooleanFlagOn(LowIoContext
->ParamsFor
.ReadWrite
.Flags
, LOWIO_READWRITEFLAG_EXTENDING_VDL
))
7190 LONGLONG LastOffset
, FileSize
;
7192 LastOffset
= LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
+
7193 Irp
->IoStatus
.Information
;
7194 RxGetFileSizeWithLock(Fcb
, &FileSize
);
7196 if (FileSize
< LastOffset
)
7198 LastOffset
= FileSize
;
7201 Fcb
->Header
.ValidDataLength
.QuadPart
= LastOffset
;
7204 /* One less outstanding write */
7205 if (!BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
7207 PNON_PAGED_FCB NonPagedFcb
;
7209 NonPagedFcb
= LowIoContext
->ParamsFor
.ReadWrite
.NonPagedFcb
;
7210 if (NonPagedFcb
!= NULL
)
7212 if (ExInterlockedAddUlong(&NonPagedFcb
->OutstandingAsyncWrites
,
7213 -1, &RxStrucSupSpinLock
) == 1)
7215 KeSetEvent(NonPagedFcb
->OutstandingAsyncEvent
, IO_NO_INCREMENT
, FALSE
);
7220 /* Release paging resource if acquired */
7221 if (RxContext
->FcbPagingIoResourceAcquired
)
7223 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
7226 /* Resume blocked operations for pipes */
7227 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
7229 RxResumeBlockedOperations_Serially(RxContext
,
7230 &((PFOBX
)RxContext
->pFobx
)->Specific
.NamedPipe
.WriteSerializationQueue
);
7234 /* And release FCB only for files */
7235 if (RxContext
->FcbResourceAcquired
)
7237 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
7241 /* Final sanity checks */
7242 ASSERT(Status
!= STATUS_RETRY
);
7243 ASSERT((Status
!= STATUS_SUCCESS
) || (Irp
->IoStatus
.Information
<= Stack
->Parameters
.Write
.Length
));
7244 ASSERT(RxContext
->MajorFunction
== IRP_MJ_WRITE
);
7246 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
))
7259 RxNotifyChangeDirectory(
7260 PRX_CONTEXT RxContext
)
7264 PIO_STACK_LOCATION Stack
;
7268 /* The IRP can abviously wait */
7269 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
7271 /* Initialize its lowio */
7272 RxInitializeLowIoContext(&RxContext
->LowIoContext
, LOWIO_OP_NOTIFY_CHANGE_DIRECTORY
);
7276 /* Lock user buffer */
7277 Stack
= RxContext
->CurrentIrpSp
;
7278 RxLockUserBuffer(RxContext
, IoWriteAccess
, Stack
->Parameters
.NotifyDirectory
.Length
);
7280 /* Copy parameters from IO_STACK */
7281 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.WatchTree
= BooleanFlagOn(Stack
->Flags
, SL_WATCH_TREE
);
7282 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.CompletionFilter
= Stack
->Parameters
.NotifyDirectory
.CompletionFilter
;
7283 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.NotificationBufferLength
= Stack
->Parameters
.NotifyDirectory
.Length
;
7285 /* If we have an associated MDL */
7286 Irp
= RxContext
->CurrentIrp
;
7287 if (Irp
->MdlAddress
!= NULL
)
7289 /* Then, call mini-rdr */
7290 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.pNotificationBuffer
= MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
7291 if (RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.pNotificationBuffer
!= NULL
)
7293 Status
= RxLowIoSubmit(RxContext
, RxLowIoNotifyChangeDirectoryCompletion
);
7297 Status
= STATUS_INSUFFICIENT_RESOURCES
;
7302 Status
= STATUS_INVALID_PARAMETER
;
7315 RxPostStackOverflowRead (
7316 IN PRX_CONTEXT RxContext
)
7321 return STATUS_NOT_IMPLEMENTED
;
7328 RxpPrepareCreateContextForReuse(
7329 PRX_CONTEXT RxContext
)
7331 /* Reuse can only happen for open operations (STATUS_RETRY) */
7332 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
7334 /* Release the FCB if it was acquired */
7335 if (RxContext
->Create
.FcbAcquired
)
7337 RxReleaseFcb(RxContext
, RxContext
->pFcb
);
7338 RxContext
->Create
.FcbAcquired
= FALSE
;
7341 /* Free the canonical name */
7342 RxFreeCanonicalNameBuffer(RxContext
);
7344 /* If we have a VNetRoot associated */
7345 if (RxContext
->Create
.pVNetRoot
!= NULL
|| RxContext
->Create
.NetNamePrefixEntry
!= NULL
)
7347 /* Remove our link and thus, dereference the VNetRoot */
7348 RxpAcquirePrefixTableLockShared(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
, TRUE
);
7349 if (RxContext
->Create
.pVNetRoot
!= NULL
)
7351 RxDereferenceVNetRoot(RxContext
->Create
.pVNetRoot
, TRUE
);
7352 RxContext
->Create
.pVNetRoot
= NULL
;
7354 RxpReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
7357 DPRINT("RxContext: %p prepared for reuse\n", RxContext
);
7364 RxpQueryInfoMiniRdr(
7365 PRX_CONTEXT RxContext
,
7366 FILE_INFORMATION_CLASS FileInfoClass
,
7372 Fcb
= (PFCB
)RxContext
->pFcb
;
7374 /* Set the RX_CONTEXT */
7375 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
7376 RxContext
->Info
.Buffer
= Buffer
;
7379 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryFileInfo
, (RxContext
));
7389 IN PRX_CONTEXT RxContext
)
7393 NET_ROOT_TYPE NetRootType
;
7394 UNICODE_STRING CanonicalName
, FileName
, NetRootName
;
7398 Irp
= RxContext
->CurrentIrp
;
7400 /* This has to come from MUP */
7401 if (Irp
->RequestorMode
== UserMode
)
7403 return STATUS_INVALID_DEVICE_REQUEST
;
7406 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
7408 PQUERY_PATH_REQUEST QueryRequest
;
7410 /* Get parameters */
7411 QueryRequest
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
7413 /* Don't overflow allocation */
7414 if (QueryRequest
->PathNameLength
>= MAXUSHORT
- 1)
7416 return STATUS_INVALID_DEVICE_REQUEST
;
7419 /* Forcefully rewrite IRP MJ */
7420 RxContext
->MajorFunction
= IRP_MJ_CREATE
;
7422 /* Fake canon name */
7423 RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
= RxAllocatePoolWithTag(NonPagedPool
, QueryRequest
->PathNameLength
, RX_MISC_POOLTAG
);
7424 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
== NULL
)
7426 Status
= STATUS_INSUFFICIENT_RESOURCES
;
7430 /* Copy the prefix to look for */
7431 RtlCopyMemory(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, &QueryRequest
->FilePathName
[0], QueryRequest
->PathNameLength
);
7432 RxContext
->PrefixClaim
.SuppliedPathName
.Length
= QueryRequest
->PathNameLength
;
7433 RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
= QueryRequest
->PathNameLength
;
7435 /* Zero the create parameters */
7436 RtlZeroMemory(&RxContext
->Create
.NtCreateParameters
,
7437 FIELD_OFFSET(RX_CONTEXT
, AlsoCanonicalNameBuffer
) - FIELD_OFFSET(RX_CONTEXT
, Create
.NtCreateParameters
));
7438 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
7439 RxContext
->Create
.NtCreateParameters
.SecurityContext
= QueryRequest
->SecurityContext
;
7443 /* If not devcontrol, it comes from open, name was already copied */
7444 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
7445 ASSERT(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
);
7448 /* Canonilize name */
7449 NetRootType
= NET_ROOT_WILD
;
7450 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
7451 FileName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
7452 FileName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
7453 FileName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
7454 NetRootName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
7455 NetRootName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
7456 NetRootName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
7457 Status
= RxFirstCanonicalize(RxContext
, &FileName
, &CanonicalName
, &NetRootType
);
7458 /* It went fine, attempt to establish a connection (that way we know whether the prefix is accepted) */
7459 if (NT_SUCCESS(Status
))
7461 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &NetRootName
);
7463 if (Status
== STATUS_PENDING
)
7468 if (NT_SUCCESS(Status
))
7470 PQUERY_PATH_RESPONSE QueryResponse
;
7472 /* We accept the length that was canon (minus netroot) */
7473 QueryResponse
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
7474 QueryResponse
->LengthAccepted
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
- NetRootName
.Length
;
7478 /* If we reach that point with MJ, reset everything and make IRP being a device control */
7479 if (RxContext
->MajorFunction
== IRP_MJ_CREATE
)
7481 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
)
7483 RxFreePoolWithTag(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, RX_MISC_POOLTAG
);
7486 RxpPrepareCreateContextForReuse(RxContext
);
7488 RxContext
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
7496 RxPrepareToReparseSymbolicLink(
7497 PRX_CONTEXT RxContext
,
7498 BOOLEAN SymbolicLinkEmbeddedInOldPath
,
7499 PUNICODE_STRING NewPath
,
7500 BOOLEAN NewPathIsAbsolute
,
7501 PBOOLEAN ReparseRequired
)
7504 return STATUS_NOT_IMPLEMENTED
;
7515 LOCK_OPERATION Lock
;
7516 PIO_STACK_LOCATION Stack
;
7517 PRX_CONTEXT RxContext
= Context
;
7519 /* NULL IRP is no option */
7525 /* Check whether preparation was really needed */
7526 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
7530 /* Mark the context as prepared */
7531 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
);
7533 /* Just lock the user buffer, with the correct length, depending on the MJ */
7534 Lock
= IoReadAccess
;
7535 Stack
= RxContext
->CurrentIrpSp
;
7536 if (RxContext
->MajorFunction
== IRP_MJ_READ
|| RxContext
->MajorFunction
== IRP_MJ_WRITE
)
7538 if (!BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
7540 if (RxContext
->MajorFunction
== IRP_MJ_READ
)
7542 Lock
= IoWriteAccess
;
7544 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.Read
.Length
);
7549 if ((RxContext
->MajorFunction
== IRP_MJ_DIRECTORY_CONTROL
&& RxContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) ||
7550 RxContext
->MajorFunction
== IRP_MJ_QUERY_EA
)
7552 Lock
= IoWriteAccess
;
7553 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.QueryDirectory
.Length
);
7555 else if (RxContext
->MajorFunction
== IRP_MJ_SET_EA
)
7557 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.SetEa
.Length
);
7561 /* As it will be posted (async), mark the IRP pending */
7562 IoMarkIrpPending(Irp
);
7570 PRX_CONTEXT RxContext
,
7571 FILE_INFORMATION_CLASS Class
)
7576 /* Initialize parameters in RX_CONTEXT */
7577 RxContext
->Info
.FileInformationClass
= Class
;
7578 RxContext
->Info
.Buffer
= RxContext
->CurrentIrp
->AssociatedIrp
.SystemBuffer
;
7579 RxContext
->Info
.Length
= RxContext
->CurrentIrpSp
->Parameters
.SetFile
.Length
;
7581 /* And call mini-rdr */
7582 Fcb
= (PFCB
)RxContext
->pFcb
;
7583 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxSetFileInfo
, (RxContext
));
7590 RxpUnregisterMinirdr(
7591 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
)
7602 PRX_CONTEXT LocalContext
)
7609 MmFlushImageSection(&Fcb
->NonPaged
->SectionObjectPointers
, MmFlushForWrite
);
7611 /* And force close */
7612 RxReleaseFcb(NULL
, Fcb
);
7613 MmForceSectionClosed(&Fcb
->NonPaged
->SectionObjectPointers
, TRUE
);
7614 Status
= RxAcquireExclusiveFcb(NULL
, Fcb
);
7615 ASSERT(Status
== STATUS_SUCCESS
);
7619 RxQueryAlternateNameInfo(
7620 PRX_CONTEXT RxContext
,
7621 PFILE_NAME_INFORMATION AltNameInfo
)
7624 return STATUS_NOT_IMPLEMENTED
;
7632 PRX_CONTEXT RxContext
,
7633 PFILE_BASIC_INFORMATION BasicInfo
)
7637 DPRINT("RxQueryBasicInfo(%p, %p)\n", RxContext
, BasicInfo
);
7639 /* Simply zero and forward to mini-rdr */
7640 RtlZeroMemory(BasicInfo
, sizeof(FILE_BASIC_INFORMATION
));
7641 return RxpQueryInfoMiniRdr(RxContext
, FileBasicInformation
, BasicInfo
);
7645 RxQueryCompressedInfo(
7646 PRX_CONTEXT RxContext
,
7647 PFILE_COMPRESSION_INFORMATION CompressionInfo
)
7650 return STATUS_NOT_IMPLEMENTED
;
7658 PRX_CONTEXT RxContext
)
7665 BOOLEAN LockNotGranted
;
7666 ULONG Length
, FileIndex
;
7667 PUNICODE_STRING FileName
;
7668 PIO_STACK_LOCATION Stack
;
7669 FILE_INFORMATION_CLASS FileInfoClass
;
7673 DPRINT("RxQueryDirectory(%p)\n", RxContext
);
7675 /* Get parameters */
7676 Stack
= RxContext
->CurrentIrpSp
;
7677 Length
= Stack
->Parameters
.QueryDirectory
.Length
;
7678 FileName
= Stack
->Parameters
.QueryDirectory
.FileName
;
7679 FileInfoClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
7680 DPRINT("Wait: %d, Length: %ld, FileName: %p, Class: %d\n",
7681 FlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
), Length
,
7682 FileName
, FileInfoClass
);
7684 Irp
= RxContext
->CurrentIrp
;
7685 Flags
= Stack
->Flags
;
7686 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
7687 DPRINT("Index: %d, Buffer: %p, Flags: %x\n", FileIndex
, Irp
->UserBuffer
, Flags
);
7689 if (FileName
!= NULL
)
7691 DPRINT("FileName: %wZ\n", FileName
);
7694 /* No FOBX: not a standard file/directory */
7695 Fobx
= (PFOBX
)RxContext
->pFobx
;
7698 return STATUS_OBJECT_NAME_INVALID
;
7701 /* We can only deal with a disk */
7702 Fcb
= (PFCB
)RxContext
->pFcb
;
7703 if (Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
7705 DPRINT1("Not a disk! %x\n", Fcb
->pNetRoot
->Type
);
7706 return STATUS_INVALID_DEVICE_REQUEST
;
7709 /* Setup RX_CONTEXT related fields */
7710 RxContext
->QueryDirectory
.FileIndex
= FileIndex
;
7711 RxContext
->QueryDirectory
.RestartScan
= BooleanFlagOn(Flags
, SL_RESTART_SCAN
);
7712 RxContext
->QueryDirectory
.ReturnSingleEntry
= BooleanFlagOn(Flags
, SL_RETURN_SINGLE_ENTRY
);
7713 RxContext
->QueryDirectory
.IndexSpecified
= BooleanFlagOn(Flags
, SL_INDEX_SPECIFIED
);
7714 RxContext
->QueryDirectory
.InitialQuery
= (Fobx
->UnicodeQueryTemplate
.Buffer
== NULL
) && !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
7716 /* We don't support (yet?) a specific index being set */
7717 if (RxContext
->QueryDirectory
.IndexSpecified
)
7719 return STATUS_NOT_IMPLEMENTED
;
7722 /* Try to lock FCB */
7723 LockNotGranted
= TRUE
;
7724 if (RxContext
->QueryDirectory
.InitialQuery
)
7726 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
7727 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
7729 if (!NT_SUCCESS(Status
))
7734 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
7736 RxContext
->QueryDirectory
.InitialQuery
= FALSE
;
7737 RxConvertToSharedFcb(RxContext
, Fcb
);
7740 LockNotGranted
= FALSE
;
7745 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
7746 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
7748 if (!NT_SUCCESS(Status
))
7753 LockNotGranted
= FALSE
;
7757 /* If it failed, post request */
7760 return RxFsdPostRequest(RxContext
);
7763 /* This cannot be done on a orphaned directory */
7764 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
7766 RxReleaseFcb(RxContext
, Fcb
);
7767 return STATUS_FILE_CLOSED
;
7773 if (!RxContext
->QueryDirectory
.IndexSpecified
&& RxContext
->QueryDirectory
.RestartScan
)
7775 RxContext
->QueryDirectory
.FileIndex
= 0;
7778 /* Assume success */
7779 Status
= STATUS_SUCCESS
;
7780 /* If initial query, prepare FOBX */
7781 if (RxContext
->QueryDirectory
.InitialQuery
)
7783 /* We cannot have a template already! */
7784 ASSERT(!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
));
7786 /* If we have a file name and a correct one, duplicate it in the FOBX */
7787 if (FileName
!= NULL
&& FileName
->Length
!= 0 && FileName
->Buffer
!= NULL
&&
7788 (FileName
->Length
!= sizeof(WCHAR
) || FileName
->Buffer
[0] != '*') &&
7789 (FileName
->Length
!= 12 * sizeof(WCHAR
) ||
7790 RtlCompareMemory(FileName
->Buffer
, Rx8QMdot3QM
, 12 * sizeof(WCHAR
)) != 12 * sizeof(WCHAR
)))
7792 Fobx
->ContainsWildCards
= FsRtlDoesNameContainWildCards(FileName
);
7794 Fobx
->UnicodeQueryTemplate
.Buffer
= RxAllocatePoolWithTag(PagedPool
, FileName
->Length
, RX_DIRCTL_POOLTAG
);
7795 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
7797 /* UNICODE_STRING; length has to be even */
7798 if ((FileName
->Length
& 1) != 0)
7800 Status
= STATUS_INVALID_PARAMETER
;
7801 RxFreePoolWithTag(Fobx
->UnicodeQueryTemplate
.Buffer
, RX_DIRCTL_POOLTAG
);
7805 Fobx
->UnicodeQueryTemplate
.Length
= FileName
->Length
;
7806 Fobx
->UnicodeQueryTemplate
.MaximumLength
= FileName
->Length
;
7807 RtlMoveMemory(Fobx
->UnicodeQueryTemplate
.Buffer
, FileName
->Buffer
, FileName
->Length
);
7809 SetFlag(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
);
7814 Status
= STATUS_INSUFFICIENT_RESOURCES
;
7817 /* No name specified, or a match all wildcard? Match everything */
7820 Fobx
->ContainsWildCards
= TRUE
;
7822 Fobx
->UnicodeQueryTemplate
.Buffer
= &RxStarForTemplate
;
7823 Fobx
->UnicodeQueryTemplate
.Length
= sizeof(WCHAR
);
7824 Fobx
->UnicodeQueryTemplate
.MaximumLength
= sizeof(WCHAR
);
7826 SetFlag(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
7829 /* No need for exclusive any longer */
7830 if (NT_SUCCESS(Status
))
7832 RxConvertToSharedFcb(RxContext
, Fcb
);
7836 /* Lock user buffer and forward to mini-rdr */
7837 if (NT_SUCCESS(Status
))
7839 RxLockUserBuffer(RxContext
, IoModifyAccess
, Length
);
7840 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
7841 RxContext
->Info
.Buffer
= RxNewMapUserBuffer(RxContext
);
7842 RxContext
->Info
.Length
= Length
;
7844 if (RxContext
->Info
.Buffer
!= NULL
)
7846 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryDirectory
, (RxContext
));
7849 /* Post if mini-rdr asks to */
7850 if (RxContext
->PostRequest
)
7852 RxFsdPostRequest(RxContext
);
7856 Irp
->IoStatus
.Information
= Length
- RxContext
->Info
.LengthRemaining
;
7862 RxReleaseFcb(RxContext
, Fcb
);
7871 PRX_CONTEXT RxContext
,
7872 PFILE_EA_INFORMATION EaInfo
)
7875 return STATUS_NOT_IMPLEMENTED
;
7879 RxQueryInternalInfo(
7880 PRX_CONTEXT RxContext
,
7881 PFILE_INTERNAL_INFORMATION InternalInfo
)
7884 return STATUS_NOT_IMPLEMENTED
;
7889 PRX_CONTEXT RxContext
,
7890 PFILE_NAME_INFORMATION NameInfo
)
7893 return STATUS_NOT_IMPLEMENTED
;
7898 PRX_CONTEXT RxContext
,
7899 PFILE_PIPE_INFORMATION PipeInfo
)
7902 return STATUS_NOT_IMPLEMENTED
;
7906 RxQueryPositionInfo(
7907 PRX_CONTEXT RxContext
,
7908 PFILE_POSITION_INFORMATION PositionInfo
)
7911 return STATUS_NOT_IMPLEMENTED
;
7918 RxQueryStandardInfo(
7919 PRX_CONTEXT RxContext
,
7920 PFILE_STANDARD_INFORMATION StandardInfo
)
7928 DPRINT("RxQueryStandardInfo(%p, %p)\n", RxContext
, StandardInfo
);
7930 /* Zero output buffer */
7931 RtlZeroMemory(StandardInfo
, sizeof(FILE_STANDARD_INFORMATION
));
7933 Fcb
= (PFCB
)RxContext
->pFcb
;
7934 Fobx
= (PFOBX
)RxContext
->pFobx
;
7935 /* If not a standard file type, or opened for backup, immediately forward to mini-rdr */
7936 if ((NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&& NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
) ||
7937 BooleanFlagOn(Fobx
->pSrvOpen
->CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
7939 return RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
7942 /* Otherwise, fill what we can already */
7943 Status
= STATUS_SUCCESS
;
7944 StandardInfo
->NumberOfLinks
= Fcb
->NumberOfLinks
;
7945 StandardInfo
->DeletePending
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
7946 StandardInfo
->Directory
= (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY
);
7947 if (StandardInfo
->NumberOfLinks
== 0)
7949 StandardInfo
->NumberOfLinks
= 1;
7952 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
7954 StandardInfo
->AllocationSize
.QuadPart
= Fcb
->Header
.AllocationSize
.QuadPart
;
7955 RxGetFileSizeWithLock(Fcb
, &StandardInfo
->EndOfFile
.QuadPart
);
7958 /* If we are asked to forcefully forward to mini-rdr or if size isn't cached, do it */
7959 if (RxForceQFIPassThrough
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILESIZECACHEING_ENABLED
))
7961 Status
= RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
7965 RxContext
->IoStatusBlock
.Information
-= sizeof(FILE_STANDARD_INFORMATION
);
7976 RxReadRegistryParameters(
7983 UNICODE_STRING KeyName
, ParamName
;
7984 OBJECT_ATTRIBUTES ObjectAttributes
;
7985 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
7989 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters");
7990 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
7991 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
7992 if (!NT_SUCCESS(Status
))
7997 PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
;
7998 RtlInitUnicodeString(&ParamName
, L
"DisableByteRangeLockingOnReadOnlyFiles");
7999 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
8000 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
8002 DisableByteRangeLockingOnReadOnlyFiles
= (*(PULONG
)PartialInfo
->Data
!= 0);
8005 RtlInitUnicodeString(&ParamName
, L
"ReadAheadGranularity");
8006 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
8007 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
8009 ULONG Granularity
= *(PULONG
)PartialInfo
->Data
;
8011 if (Granularity
> 16)
8016 ReadAheadGranularity
= Granularity
<< PAGE_SHIFT
;
8019 RtlInitUnicodeString(&ParamName
, L
"DisableFlushOnCleanup");
8020 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
8021 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
8023 DisableFlushOnCleanup
= (*(PULONG
)PartialInfo
->Data
!= 0);
8035 OUT PRDBSS_DEVICE_OBJECT
*DeviceObject
,
8036 IN OUT PDRIVER_OBJECT DriverObject
,
8037 IN PMINIRDR_DISPATCH MrdrDispatch
,
8039 IN PUNICODE_STRING DeviceName
,
8040 IN ULONG DeviceExtensionSize
,
8041 IN DEVICE_TYPE DeviceType
,
8042 IN ULONG DeviceCharacteristics
)
8045 PRDBSS_DEVICE_OBJECT RDBSSDevice
;
8051 return STATUS_INVALID_PARAMETER
;
8054 /* Create device object with provided parameters */
8055 Status
= IoCreateDevice(DriverObject
,
8056 DeviceExtensionSize
+ sizeof(RDBSS_DEVICE_OBJECT
),
8059 DeviceCharacteristics
,
8061 (PDEVICE_OBJECT
*)&RDBSSDevice
);
8062 if (!NT_SUCCESS(Status
))
8067 if (!RxData
.DriverObject
)
8069 return STATUS_UNSUCCESSFUL
;
8072 /* Initialize our DO extension */
8073 RDBSSDevice
->RDBSSDeviceObject
= NULL
;
8074 ++RxFileSystemDeviceObject
->ReferenceCount
;
8075 *DeviceObject
= RDBSSDevice
;
8076 RDBSSDevice
->RdbssExports
= &RxExports
;
8077 RDBSSDevice
->Dispatch
= MrdrDispatch
;
8078 RDBSSDevice
->RegistrationControls
= Controls
;
8079 RDBSSDevice
->DeviceName
= *DeviceName
;
8080 RDBSSDevice
->RegisterUncProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS
);
8081 RDBSSDevice
->RegisterMailSlotProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS
);
8082 InitializeListHead(&RDBSSDevice
->OverflowQueue
[0]);
8083 InitializeListHead(&RDBSSDevice
->OverflowQueue
[1]);
8084 InitializeListHead(&RDBSSDevice
->OverflowQueue
[2]);
8085 KeInitializeSpinLock(&RDBSSDevice
->OverflowQueueSpinLock
);
8086 RDBSSDevice
->NetworkProviderPriority
= RxGetNetworkProviderPriority(DeviceName
);
8088 DPRINT("Registered MiniRdr %wZ (prio: %x)\n", DeviceName
, RDBSSDevice
->NetworkProviderPriority
);
8090 ExAcquireFastMutex(&RxData
.MinirdrRegistrationMutex
);
8091 InsertTailList(&RxData
.RegisteredMiniRdrs
, &RDBSSDevice
->MiniRdrListLinks
);
8092 ExReleaseFastMutex(&RxData
.MinirdrRegistrationMutex
);
8094 /* Unless mini-rdr explicitly asked not to, initialize dispatch table */
8095 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH
))
8097 RxInitializeMinirdrDispatchTable(DriverObject
);
8100 /* Unless mini-rdr explicitly asked not to, initialize prefix scavenger */
8101 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER
))
8103 LARGE_INTEGER ScavengerTimeLimit
;
8105 RDBSSDevice
->pRxNetNameTable
= &RDBSSDevice
->RxNetNameTableInDeviceObject
;
8106 RxInitializePrefixTable(RDBSSDevice
->pRxNetNameTable
, 0, FALSE
);
8107 RDBSSDevice
->RxNetNameTableInDeviceObject
.IsNetNameTable
= TRUE
;
8108 ScavengerTimeLimit
.QuadPart
= MrdrDispatch
->ScavengerTimeout
* 10000000LL;
8109 RDBSSDevice
->pRdbssScavenger
= &RDBSSDevice
->RdbssScavengerInDeviceObject
;
8110 RxInitializeRdbssScavenger(RDBSSDevice
->pRdbssScavenger
, ScavengerTimeLimit
);
8113 RDBSSDevice
->pAsynchronousRequestsCompletionEvent
= NULL
;
8115 return STATUS_SUCCESS
;
8122 RxRemoveFromTopLevelIrpAllocatedContextsList(
8123 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
8127 /* Make sure this is a TLC and that it was allocated (otherwise, it is not in the list */
8128 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
8129 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
8131 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
8132 RemoveEntryList(&TopLevelContext
->ListEntry
);
8133 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
8140 RxRemoveOverflowEntry(
8141 PRDBSS_DEVICE_OBJECT DeviceObject
,
8142 WORK_QUEUE_TYPE Queue
)
8145 PRX_CONTEXT Context
;
8147 KeAcquireSpinLock(&DeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
8148 if (DeviceObject
->OverflowQueueCount
[Queue
] <= 0)
8150 /* No entries left, nothing to return */
8151 InterlockedDecrement(&DeviceObject
->PostedRequestCount
[Queue
]);
8158 /* Decrement count */
8159 --DeviceObject
->OverflowQueueCount
[Queue
];
8162 Entry
= RemoveHeadList(&DeviceObject
->OverflowQueue
[Queue
]);
8163 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, OverflowListEntry
);
8164 ClearFlag(Context
->Flags
, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
| RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
8165 Context
->OverflowListEntry
.Flink
= NULL
;
8167 KeReleaseSpinLock(&DeviceObject
->OverflowQueueSpinLock
, OldIrql
);
8176 RxRemoveShareAccess(
8177 _Inout_ PFILE_OBJECT FileObject
,
8178 _Inout_ PSHARE_ACCESS ShareAccess
,
8180 _In_ PSZ wherelogtag
)
8184 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
8185 IoRemoveShareAccess(FileObject
, ShareAccess
);
8186 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
8193 RxRemoveShareAccessPerSrvOpens(
8194 IN OUT PSRV_OPEN SrvOpen
)
8196 ACCESS_MASK DesiredAccess
;
8198 BOOLEAN WriteAccess
;
8199 BOOLEAN DeleteAccess
;
8203 /* Get access that were granted to SRV_OPEN */
8204 DesiredAccess
= SrvOpen
->DesiredAccess
;
8205 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
8206 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
8207 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
8209 /* If any, drop them */
8210 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
8213 BOOLEAN SharedWrite
;
8214 BOOLEAN SharedDelete
;
8215 ULONG DesiredShareAccess
;
8216 PSHARE_ACCESS ShareAccess
;
8218 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
8219 DesiredShareAccess
= SrvOpen
->ShareAccess
;
8221 ShareAccess
->Readers
-= ReadAccess
;
8222 ShareAccess
->Writers
-= WriteAccess
;
8223 ShareAccess
->Deleters
-= DeleteAccess
;
8225 ShareAccess
->OpenCount
--;
8227 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
8228 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
8229 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
8230 ShareAccess
->SharedRead
-= SharedRead
;
8231 ShareAccess
->SharedWrite
-= SharedWrite
;
8232 ShareAccess
->SharedDelete
-= SharedDelete
;
8237 RxSearchForCollapsibleOpen(
8238 PRX_CONTEXT RxContext
,
8239 ACCESS_MASK DesiredAccess
,
8244 PLIST_ENTRY ListEntry
;
8245 BOOLEAN ShouldTry
, Purged
, Scavenged
;
8249 DPRINT("RxSearchForCollapsibleOpen(%p, %x, %x)\n", RxContext
, DesiredAccess
, ShareAccess
);
8251 Fcb
= (PFCB
)RxContext
->pFcb
;
8253 /* If we're asked to open for backup, don't allow SRV_OPEN reuse */
8254 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
8256 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
8258 RxScavengeRelatedFobxs(Fcb
);
8259 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
8261 return STATUS_NOT_FOUND
;
8264 /* If basic open, ask the mini-rdr if we should try to collapse */
8265 if (RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN
||
8266 RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN_IF
)
8270 if (Fcb
->MRxDispatch
!= NULL
)
8272 ASSERT(RxContext
->pRelevantSrvOpen
== NULL
);
8273 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
8275 ShouldTry
= NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
));
8283 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
))
8288 /* If we shouldn't try, ask the caller to allocate a new SRV_OPEN */
8291 if (NT_SUCCESS(RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
)))
8293 return STATUS_NOT_FOUND
;
8296 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
8298 RxScavengeRelatedFobxs(Fcb
);
8299 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
8301 return STATUS_NOT_FOUND
;
8304 /* Only collapse for matching NET_ROOT & disks */
8305 if (Fcb
->pNetRoot
!= RxContext
->Create
.pNetRoot
||
8306 Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
8308 return STATUS_NOT_FOUND
;
8313 Status
= STATUS_NOT_FOUND
;
8315 /* Browse all our SRV_OPEN to find the matching one */
8316 for (ListEntry
= Fcb
->SrvOpenList
.Flink
;
8317 ListEntry
!= &Fcb
->SrvOpenList
;
8318 ListEntry
= ListEntry
->Flink
)
8322 SrvOpen
= CONTAINING_RECORD(ListEntry
, SRV_OPEN
, SrvOpenQLinks
);
8323 /* Not the same VNET_ROOT, move to the next one */
8324 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
8326 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
8330 /* Is there a sharing violation? */
8331 if (SrvOpen
->DesiredAccess
!= DesiredAccess
|| SrvOpen
->ShareAccess
!= ShareAccess
||
8332 BooleanFlagOn(SrvOpen
->Flags
, (SRVOPEN_FLAG_CLOSED
| SRVOPEN_FLAG_COLLAPSING_DISABLED
| SRVOPEN_FLAG_FILE_DELETED
| SRVOPEN_FLAG_FILE_RENAMED
)))
8334 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
8336 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
8340 /* Check against the SRV_OPEN */
8341 Status
= RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
);
8342 if (!NT_SUCCESS(Status
))
8349 /* Don't allow collaspse for reparse point opening */
8350 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
^ SrvOpen
->CreateOptions
, FILE_OPEN_REPARSE_POINT
))
8354 Status
= STATUS_NOT_FOUND
;
8358 /* Not readonly? Or bytereange lock disabled? Try to collapse! */
8359 if (DisableByteRangeLockingOnReadOnlyFiles
|| !BooleanFlagOn(SrvOpen
->pFcb
->Attributes
, FILE_ATTRIBUTE_READONLY
))
8361 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
8363 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
8364 if (NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
)))
8366 /* Is close delayed - great reuse*/
8367 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
8369 DPRINT("Delayed close successfull, reusing %p\n", SrvOpen
);
8370 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
8371 ClearFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
8374 return STATUS_SUCCESS
;
8377 Status
= STATUS_NOT_FOUND
;
8382 /* We browse the whole list and didn't find any matching? NOT_FOUND */
8383 if (ListEntry
== &Fcb
->SrvOpenList
)
8385 Status
= STATUS_NOT_FOUND
;
8388 /* Only required access: read attributes? Don't reuse */
8389 if ((DesiredAccess
& 0xFFEFFFFF) == FILE_READ_ATTRIBUTES
)
8391 return STATUS_NOT_FOUND
;
8394 /* Not found? Scavenge and retry to look for collaspile SRV_OPEN */
8397 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
8399 RxScavengeRelatedFobxs(Fcb
);
8403 /* Not found? Purgeable? Purge and retry to look for collaspile SRV_OPEN */
8404 if (!Purged
&& RxIsOkToPurgeFcb(Fcb
))
8406 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
8411 /* If sharing violation, keep track of it */
8412 if (Status
== STATUS_SHARING_VIOLATION
)
8414 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
8417 DPRINT("Status: %x\n", Status
);
8422 RxSetAllocationInfo(
8423 PRX_CONTEXT RxContext
)
8426 return STATUS_NOT_IMPLEMENTED
;
8434 PRX_CONTEXT RxContext
)
8440 #define FILE_ATTRIBUTE_VOLUME 0x8
8441 #define VALID_FILE_ATTRIBUTES ( \
8442 FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
8443 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_VOLUME | \
8444 FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DEVICE | \
8445 FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | \
8446 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED | \
8447 FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | \
8448 FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_INTEGRITY_STREAM)
8449 #define VALID_DIR_ATTRIBUTES (VALID_FILE_ATTRIBUTES | FILE_ATTRIBUTE_DIRECTORY)
8451 /* First of all, call the mini-rdr */
8452 Status
= RxpSetInfoMiniRdr(RxContext
, FileBasicInformation
);
8453 /* If it succeed, perform last bits */
8454 if (NT_SUCCESS(Status
))
8459 PFILE_OBJECT FileObject
;
8460 ULONG Attributes
, CleanAttr
;
8461 PFILE_BASIC_INFORMATION BasicInfo
;
8463 Fcb
= (PFCB
)RxContext
->pFcb
;
8464 Fobx
= (PFOBX
)RxContext
->pFobx
;
8465 Irp
= RxContext
->CurrentIrp
;
8466 BasicInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
8467 FileObject
= RxContext
->CurrentIrpSp
->FileObject
;
8469 /* If caller provided flags, handle the change */
8470 Attributes
= BasicInfo
->FileAttributes
;
8471 if (Attributes
!= 0)
8473 /* Clean our flags first, with only stuff we support */
8474 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
8476 CleanAttr
= (Attributes
& VALID_DIR_ATTRIBUTES
) | FILE_ATTRIBUTE_DIRECTORY
;
8480 CleanAttr
= Attributes
& VALID_FILE_ATTRIBUTES
;
8483 /* Handle the temporary mark (set/unset depending on caller) */
8484 if (BooleanFlagOn(Attributes
, FILE_ATTRIBUTE_TEMPORARY
))
8486 SetFlag(Fcb
->FcbState
, FCB_STATE_TEMPORARY
);
8487 SetFlag(FileObject
->Flags
, FO_TEMPORARY_FILE
);
8491 ClearFlag(Fcb
->FcbState
, FCB_STATE_TEMPORARY
);
8492 ClearFlag(FileObject
->Flags
, FO_TEMPORARY_FILE
);
8495 /* And set new attributes */
8496 Fcb
->Attributes
= CleanAttr
;
8499 /* If caller provided a creation time, set it */
8500 if (BasicInfo
->CreationTime
.QuadPart
!= 0LL)
8502 Fcb
->CreationTime
.QuadPart
= BasicInfo
->CreationTime
.QuadPart
;
8503 SetFlag(Fobx
->Flags
, FOBX_FLAG_USER_SET_CREATION
);
8506 /* If caller provided a last access time, set it */
8507 if (BasicInfo
->LastAccessTime
.QuadPart
!= 0LL)
8509 Fcb
->LastAccessTime
.QuadPart
= BasicInfo
->LastAccessTime
.QuadPart
;
8510 SetFlag(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_ACCESS
);
8513 /* If caller provided a last write time, set it */
8514 if (BasicInfo
->LastWriteTime
.QuadPart
!= 0LL)
8516 Fcb
->LastWriteTime
.QuadPart
= BasicInfo
->LastWriteTime
.QuadPart
;
8517 SetFlag(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_WRITE
);
8520 /* If caller provided a last change time, set it */
8521 if (BasicInfo
->ChangeTime
.QuadPart
!= 0LL)
8523 Fcb
->LastChangeTime
.QuadPart
= BasicInfo
->ChangeTime
.QuadPart
;
8524 SetFlag(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_CHANGE
);
8533 RxSetDispositionInfo(
8534 PRX_CONTEXT RxContext
)
8537 return STATUS_NOT_IMPLEMENTED
;
8542 PRX_CONTEXT RxContext
)
8545 return STATUS_NOT_IMPLEMENTED
;
8550 PRX_CONTEXT RxContext
)
8553 return STATUS_NOT_IMPLEMENTED
;
8558 PRX_CONTEXT RxContext
)
8561 return STATUS_NOT_IMPLEMENTED
;
8566 PRX_CONTEXT RxContext
)
8569 return STATUS_NOT_IMPLEMENTED
;
8577 _In_ ACCESS_MASK DesiredAccess
,
8578 _In_ ULONG DesiredShareAccess
,
8579 _Inout_ PFILE_OBJECT FileObject
,
8580 _Out_ PSHARE_ACCESS ShareAccess
,
8582 _In_ PSZ wherelogtag
)
8586 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
8587 IoSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
);
8588 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
8593 PRX_CONTEXT RxContext
)
8596 return STATUS_NOT_IMPLEMENTED
;
8603 RxSetupNetFileObject(
8604 PRX_CONTEXT RxContext
)
8608 PFILE_OBJECT FileObject
;
8609 PIO_STACK_LOCATION Stack
;
8613 /* Assert FOBX is FOBX or NULL */
8614 Fobx
= (PFOBX
)RxContext
->pFobx
;
8615 ASSERT((Fobx
== NULL
) || (NodeType(Fobx
) == RDBSS_NTC_FOBX
));
8617 Fcb
= (PFCB
)RxContext
->pFcb
;
8618 Stack
= RxContext
->CurrentIrpSp
;
8619 FileObject
= Stack
->FileObject
;
8620 /* If it's temporary mark FO as such */
8621 if (Fcb
!= NULL
&& NodeType(Fcb
) != RDBSS_NTC_VCB
&&
8622 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TEMPORARY
))
8624 if (FileObject
== NULL
)
8629 FileObject
->Flags
|= FO_TEMPORARY_FILE
;
8632 /* No FO, nothing to setup */
8633 if (FileObject
== NULL
)
8638 /* Assign FCB & CCB (FOBX) to FO */
8639 FileObject
->FsContext
= Fcb
;
8640 FileObject
->FsContext2
= Fobx
;
8643 ULONG_PTR StackTop
, StackBottom
;
8645 /* If FO is allocated on pool, keep track of it */
8646 IoGetStackLimits(&StackTop
, &StackBottom
);
8647 if ((ULONG_PTR
)FileObject
<= StackBottom
|| (ULONG_PTR
)FileObject
>= StackTop
)
8649 Fobx
->AssociatedFileObject
= FileObject
;
8653 Fobx
->AssociatedFileObject
= NULL
;
8656 /* Make sure to mark FOBX if it's a DFS open */
8657 if (RxContext
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
))
8659 SetFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
8663 ClearFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
8667 /* Set Cc pointers */
8668 FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
8670 /* Update access state */
8671 if (Stack
->Parameters
.Create
.SecurityContext
!= NULL
)
8673 PACCESS_STATE AccessState
;
8675 AccessState
= Stack
->Parameters
.Create
.SecurityContext
->AccessState
;
8676 AccessState
->PreviouslyGrantedAccess
|= AccessState
->RemainingDesiredAccess
;
8677 AccessState
->RemainingDesiredAccess
= 0;
8687 IN PRX_CONTEXT RxContext
,
8688 OUT PBOOLEAN PostToFsp
)
8691 BOOLEAN Wait
, AlreadyStarted
;
8692 PRDBSS_DEVICE_OBJECT DeviceObject
;
8694 /* If we've not been post, then, do it */
8695 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
))
8697 SECURITY_SUBJECT_CONTEXT SubjectContext
;
8699 SeCaptureSubjectContext(&SubjectContext
);
8700 RxContext
->FsdUid
= RxGetUid(&SubjectContext
);
8701 SeReleaseSubjectContext(&SubjectContext
);
8704 return STATUS_PENDING
;
8707 /* Acquire all the required locks */
8708 Wait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
8709 if (!ExAcquireResourceExclusiveLite(&RxData
.Resource
, Wait
))
8712 return STATUS_PENDING
;
8715 if (!RxAcquirePrefixTableLockExclusive(RxContext
->RxDeviceObject
->pRxNetNameTable
, Wait
))
8717 ExReleaseResourceLite(&RxData
.Resource
);
8719 return STATUS_PENDING
;
8722 AlreadyStarted
= FALSE
;
8723 DeviceObject
= RxContext
->RxDeviceObject
;
8726 /* MUP handle set, means already registered */
8727 if (DeviceObject
->MupHandle
!= NULL
)
8729 AlreadyStarted
= TRUE
;
8730 Status
= STATUS_REDIRECTOR_STARTED
;
8734 /* If we're asked to register to MUP, then do it */
8735 Status
= STATUS_SUCCESS
;
8736 if (DeviceObject
->RegisterUncProvider
)
8738 Status
= FsRtlRegisterUncProvider(&DeviceObject
->MupHandle
,
8739 &DeviceObject
->DeviceName
,
8740 DeviceObject
->RegisterMailSlotProvider
);
8742 if (!NT_SUCCESS(Status
))
8744 DeviceObject
->MupHandle
= NULL
;
8748 /* Register as file system */
8749 IoRegisterFileSystem(&DeviceObject
->DeviceObject
);
8750 DeviceObject
->RegisteredAsFileSystem
= TRUE
;
8752 /* Inform mini-rdr it has to start */
8753 MINIRDR_CALL(Status
, RxContext
, DeviceObject
->Dispatch
, MRxStart
, (RxContext
, DeviceObject
));
8754 if (NT_SUCCESS(Status
))
8756 ++DeviceObject
->StartStopContext
.Version
;
8757 RxSetRdbssState(DeviceObject
, RDBSS_STARTED
);
8758 InterlockedExchangeAdd(&RxData
.NumberOfMinirdrsStarted
, 1);
8760 Status
= RxInitializeMRxDispatcher(DeviceObject
);
8765 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status
))
8767 if (!AlreadyStarted
)
8769 RxUnstart(RxContext
, DeviceObject
);
8773 RxReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
);
8774 ExReleaseResourceLite(&RxData
.Resource
);
8784 IN PRX_CONTEXT RxContext
,
8785 OUT PBOOLEAN PostToFsp
)
8788 return STATUS_NOT_IMPLEMENTED
;
8793 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
8797 return STATUS_NOT_IMPLEMENTED
;
8804 RxTryToBecomeTheTopLevelIrp(
8805 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
8807 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
8808 IN BOOLEAN ForceTopLevel
8811 BOOLEAN FromPool
= FALSE
;
8815 /* If not top level, and not have to be, quit */
8816 if (IoGetTopLevelIrp() && !ForceTopLevel
)
8821 /* If not TLC provider, allocate one */
8822 if (TopLevelContext
== NULL
)
8824 TopLevelContext
= RxAllocatePoolWithTag(NonPagedPool
, sizeof(RX_TOPLEVELIRP_CONTEXT
), RX_TLC_POOLTAG
);
8825 if (TopLevelContext
== NULL
)
8834 __RxInitializeTopLevelIrpContext(TopLevelContext
, Irp
, RxDeviceObject
, FromPool
);
8836 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
8839 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
8842 /* Make it top level IRP */
8843 IoSetTopLevelIrp((PIRP
)TopLevelContext
);
8851 RxUpdateShareAccess(
8852 _Inout_ PFILE_OBJECT FileObject
,
8853 _Inout_ PSHARE_ACCESS ShareAccess
,
8855 _In_ PSZ wherelogtag
)
8859 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
8860 IoUpdateShareAccess(FileObject
, ShareAccess
);
8861 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
8868 RxUninitializeCacheMap(
8869 PRX_CONTEXT RxContext
,
8870 PFILE_OBJECT FileObject
,
8871 PLARGE_INTEGER TruncateSize
)
8875 CACHE_UNINITIALIZE_EVENT UninitEvent
;
8879 Fcb
= FileObject
->FsContext
;
8880 ASSERT(NodeTypeIsFcb(Fcb
));
8881 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
8883 KeInitializeEvent(&UninitEvent
.Event
, SynchronizationEvent
, FALSE
);
8884 CcUninitializeCacheMap(FileObject
, TruncateSize
, &UninitEvent
);
8886 /* Always release the FCB before waiting for the uninit event */
8887 RxReleaseFcb(RxContext
, Fcb
);
8889 KeWaitForSingleObject(&UninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
8891 /* Re-acquire it afterwards */
8892 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
8893 ASSERT(NT_SUCCESS(Status
));
8899 IN PDRIVER_OBJECT DriverObject
)
8908 IN PFILE_LOCK_INFO LockInfo
)
8915 PRX_CONTEXT Context
,
8916 PRDBSS_DEVICE_OBJECT DeviceObject
)
8925 RxUnwindTopLevelIrp(
8926 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
8928 DPRINT("RxUnwindTopLevelIrp(%p)\n", TopLevelContext
);
8930 /* No TLC provided? Ask the system for ours! */
8931 if (TopLevelContext
== NULL
)
8933 TopLevelContext
= (PRX_TOPLEVELIRP_CONTEXT
)IoGetTopLevelIrp();
8934 if (TopLevelContext
== NULL
)
8939 /* In that case, just assert it's really ours */
8940 ASSERT(RxIsThisAnRdbssTopLevelContext(TopLevelContext
));
8941 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
8944 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
8945 ASSERT(TopLevelContext
->Thread
== PsGetCurrentThread());
8946 /* Restore the previous top level IRP */
8947 IoSetTopLevelIrp(TopLevelContext
->Previous
);
8948 /* If TLC was allocated from pool, remove it from list and release it */
8949 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
8951 RxRemoveFromTopLevelIrpAllocatedContextsList(TopLevelContext
);
8952 RxFreePoolWithTag(TopLevelContext
, RX_TLC_POOLTAG
);
8960 RxUpdateShareAccessPerSrvOpens(
8961 IN PSRV_OPEN SrvOpen
)
8963 ACCESS_MASK DesiredAccess
;
8965 BOOLEAN WriteAccess
;
8966 BOOLEAN DeleteAccess
;
8970 /* If already updated, no need to continue */
8971 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
))
8976 /* Check if any access wanted */
8977 DesiredAccess
= SrvOpen
->DesiredAccess
;
8978 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
8979 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
8980 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
8982 /* In that case, update it */
8983 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
8986 BOOLEAN SharedWrite
;
8987 BOOLEAN SharedDelete
;
8988 ULONG DesiredShareAccess
;
8989 PSHARE_ACCESS ShareAccess
;
8991 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
8992 DesiredShareAccess
= SrvOpen
->ShareAccess
;
8994 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
8995 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
8996 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
8998 ShareAccess
->OpenCount
++;
9000 ShareAccess
->Readers
+= ReadAccess
;
9001 ShareAccess
->Writers
+= WriteAccess
;
9002 ShareAccess
->Deleters
+= DeleteAccess
;
9003 ShareAccess
->SharedRead
+= SharedRead
;
9004 ShareAccess
->SharedWrite
+= SharedWrite
;
9005 ShareAccess
->SharedDelete
+= SharedDelete
;
9008 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
);
9015 RxXXXControlFileCallthru(
9016 PRX_CONTEXT Context
)
9022 DPRINT("RxXXXControlFileCallthru(%p)\n", Context
);
9024 /* No dispatch table? Nothing to dispatch */
9025 if (Context
->RxDeviceObject
->Dispatch
== NULL
)
9027 Context
->pFobx
= NULL
;
9028 return STATUS_INVALID_DEVICE_REQUEST
;
9031 /* Init the lowio context */
9032 Status
= RxLowIoPopulateFsctlInfo(Context
);
9033 if (!NT_SUCCESS(Status
))
9038 /* Check whether we're consistent: a length means a buffer */
9039 if ((Context
->LowIoContext
.ParamsFor
.FsCtl
.InputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pInputBuffer
== NULL
) ||
9040 (Context
->LowIoContext
.ParamsFor
.FsCtl
.OutputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pOutputBuffer
== NULL
))
9042 return STATUS_INVALID_PARAMETER
;
9045 /* Forward the call to the mini-rdr */
9046 DPRINT("Calling: %p\n", Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile
);
9047 Status
= Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile(Context
);
9048 if (Status
!= STATUS_PENDING
)
9050 Context
->CurrentIrp
->IoStatus
.Information
= Context
->InformationToReturn
;
9053 DPRINT("RxXXXControlFileCallthru: %x, %ld\n", Context
->CurrentIrp
->IoStatus
.Status
, Context
->CurrentIrp
->IoStatus
.Information
);