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 PRX_CONTEXT RxContext
);
352 RxNotifyChangeDirectory(
353 PRX_CONTEXT RxContext
);
357 PRX_CONTEXT RxContext
,
358 FILE_INFORMATION_CLASS FileInfoClass
,
364 PRX_CONTEXT LocalContext
);
367 RxQueryAlternateNameInfo(
368 PRX_CONTEXT RxContext
,
369 PFILE_NAME_INFORMATION AltNameInfo
);
373 PRX_CONTEXT RxContext
,
374 PFILE_BASIC_INFORMATION BasicInfo
);
377 RxQueryCompressedInfo(
378 PRX_CONTEXT RxContext
,
379 PFILE_COMPRESSION_INFORMATION CompressionInfo
);
383 PRX_CONTEXT RxContext
);
387 PRX_CONTEXT RxContext
,
388 PFILE_EA_INFORMATION EaInfo
);
392 PRX_CONTEXT RxContext
,
393 PFILE_INTERNAL_INFORMATION InternalInfo
);
397 PRX_CONTEXT RxContext
,
398 PFILE_NAME_INFORMATION NameInfo
);
402 PRX_CONTEXT RxContext
,
403 PFILE_PIPE_INFORMATION PipeInfo
);
407 PRX_CONTEXT RxContext
,
408 PFILE_POSITION_INFORMATION PositionInfo
);
412 PRX_CONTEXT RxContext
,
413 PFILE_STANDARD_INFORMATION StandardInfo
);
417 RxReadRegistryParameters(
422 RxReleaseFileForNtCreateSection(
423 PFILE_OBJECT FileObject
);
428 PFILE_OBJECT FileObject
,
429 PDEVICE_OBJECT DeviceObject
);
432 RxRemoveOverflowEntry(
433 PRDBSS_DEVICE_OBJECT DeviceObject
,
434 WORK_QUEUE_TYPE Queue
);
437 RxSearchForCollapsibleOpen(
438 PRX_CONTEXT RxContext
,
439 ACCESS_MASK DesiredAccess
,
443 RxSetupNetFileObject(
444 PRX_CONTEXT RxContext
);
448 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
452 RxUninitializeCacheMap(
453 PRX_CONTEXT RxContext
,
454 PFILE_OBJECT FileObject
,
455 PLARGE_INTEGER TruncateSize
);
460 PRDBSS_DEVICE_OBJECT DeviceObject
);
463 RxXXXControlFileCallthru(
464 PRX_CONTEXT Context
);
468 _RxAllocatePoolWithTag(
469 _In_ POOL_TYPE PoolType
,
470 _In_ SIZE_T NumberOfBytes
,
484 WCHAR RxStarForTemplate
= '*';
485 WCHAR Rx8QMdot3QM
[] = L
">>>>>>>>.>>>*";
486 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles
= FALSE
;
487 BOOLEAN DisableFlushOnCleanup
= FALSE
;
488 ULONG ReadAheadGranularity
= 1 << PAGE_SHIFT
;
489 LIST_ENTRY RxActiveContexts
;
490 NPAGED_LOOKASIDE_LIST RxContextLookasideList
;
491 FAST_MUTEX RxContextPerFileSerializationMutex
;
494 BOOLEAN RxLoudLowIoOpsEnabled
= FALSE
;
495 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
497 { RxCommonDispatchProblem
},
498 { RxCommonDispatchProblem
},
499 { RxCommonDevFCBClose
},
500 { RxCommonDispatchProblem
},
501 { RxCommonDispatchProblem
},
502 { RxCommonDispatchProblem
},
503 { RxCommonDispatchProblem
},
504 { RxCommonDispatchProblem
},
505 { RxCommonDispatchProblem
},
506 { RxCommonDispatchProblem
},
507 { RxCommonDevFCBQueryVolInfo
},
508 { RxCommonDispatchProblem
},
509 { RxCommonDispatchProblem
},
510 { RxCommonDevFCBFsCtl
},
511 { RxCommonDevFCBIoCtl
},
512 { RxCommonDevFCBIoCtl
},
513 { RxCommonDispatchProblem
},
514 { RxCommonDispatchProblem
},
515 { RxCommonDevFCBCleanup
},
516 { RxCommonDispatchProblem
},
517 { RxCommonDispatchProblem
},
518 { RxCommonDispatchProblem
},
519 { RxCommonUnimplemented
},
520 { RxCommonUnimplemented
},
521 { RxCommonUnimplemented
},
522 { RxCommonUnimplemented
},
523 { RxCommonUnimplemented
},
524 { RxCommonUnimplemented
},
526 RDBSS_EXPORTS RxExports
;
527 FAST_IO_DISPATCH RxFastIoDispatch
;
528 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject
;
529 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
532 { RxCommonUnimplemented
},
536 { RxCommonQueryInformation
},
537 { RxCommonSetInformation
},
540 { RxCommonFlushBuffers
},
541 { RxCommonQueryVolumeInformation
},
542 { RxCommonSetVolumeInformation
},
543 { RxCommonDirectoryControl
},
544 { RxCommonFileSystemControl
},
545 { RxCommonDeviceControl
},
546 { RxCommonDeviceControl
},
547 { RxCommonUnimplemented
},
548 { RxCommonLockControl
},
550 { RxCommonUnimplemented
},
551 { RxCommonQuerySecurity
},
552 { RxCommonSetSecurity
},
553 { RxCommonUnimplemented
},
554 { RxCommonUnimplemented
},
555 { RxCommonUnimplemented
},
556 { RxCommonQueryQuotaInformation
},
557 { RxCommonSetQuotaInformation
},
558 { RxCommonUnimplemented
},
560 ULONG RxFsdEntryCount
;
561 LIST_ENTRY RxIrpsList
;
562 KSPIN_LOCK RxIrpsListSpinLock
;
563 KMUTEX RxScavengerMutex
;
564 KMUTEX RxSerializationMutex
;
565 UCHAR RxSpaceForTheWrappersDeviceObject
[sizeof(*RxFileSystemDeviceObject
)];
566 KSPIN_LOCK TopLevelIrpSpinLock
;
567 LIST_ENTRY TopLevelIrpAllocatedContextsList
;
568 BOOLEAN RxForceQFIPassThrough
= FALSE
;
570 DECLARE_CONST_UNICODE_STRING(unknownId
, L
"???");
577 #define ASSERT(exp) \
580 RxAssert(#exp, __FILE__, __LINE__, NULL); \
585 #undef RxAllocatePool
586 #undef RxAllocatePoolWithTag
589 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
590 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
591 #define RxFreePool _RxFreePool
592 #define RxFreePoolWithTag _RxFreePoolWithTag
595 /* FUNCTIONS ****************************************************************/
601 CheckForLoudOperations(
602 PRX_CONTEXT RxContext
)
606 #define ALLSCR_LENGTH (sizeof(L"all.scr") - sizeof(UNICODE_NULL))
608 /* Are loud operations enabled? */
609 if (RxLoudLowIoOpsEnabled
)
613 /* If so, the operation will be loud only if filename ends with all.scr */
614 Fcb
= (PFCB
)RxContext
->pFcb
;
615 if (RtlCompareMemory(Add2Ptr(Fcb
->PrivateAlreadyPrefixedName
.Buffer
, (Fcb
->PrivateAlreadyPrefixedName
.Length
- ALLSCR_LENGTH
)),
616 L
"all.scr", ALLSCR_LENGTH
) == ALLSCR_LENGTH
)
618 SetFlag(RxContext
->LowIoContext
.Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
);
628 __RxInitializeTopLevelIrpContext(
629 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
631 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
634 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext
, Irp
, RxDeviceObject
, Flags
);
636 RtlZeroMemory(TopLevelContext
, sizeof(RX_TOPLEVELIRP_CONTEXT
));
637 TopLevelContext
->Irp
= Irp
;
638 TopLevelContext
->Flags
= (Flags
? RX_TOPLEVELCTX_FLAG_FROM_POOL
: 0);
639 TopLevelContext
->Signature
= RX_TOPLEVELIRP_CONTEXT_SIGNATURE
;
640 TopLevelContext
->RxDeviceObject
= RxDeviceObject
;
641 TopLevelContext
->Previous
= IoGetTopLevelIrp();
642 TopLevelContext
->Thread
= PsGetCurrentThread();
644 /* We cannot add to list something that'd come from stack */
645 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
647 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext
);
653 RxAcquireExclusiveFcbResourceInMRx(
654 _Inout_ PMRX_FCB Fcb
)
657 return STATUS_NOT_IMPLEMENTED
;
662 RxAcquireFcbForLazyWrite(
672 RxAcquireFcbForReadAhead(
682 RxAcquireFileForNtCreateSection(
683 PFILE_OBJECT FileObject
)
691 PFILE_OBJECT FileObject
,
692 PDEVICE_OBJECT DeviceObject
)
695 return STATUS_NOT_IMPLEMENTED
;
702 RxAddToTopLevelIrpAllocatedContextsList(
703 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
707 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext
);
709 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
710 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
712 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
713 InsertTailList(&TopLevelIrpAllocatedContextsList
, &TopLevelContext
->ListEntry
);
714 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
722 IN PRX_CONTEXT RxContext
,
727 WORK_QUEUE_TYPE Queue
;
728 PIO_STACK_LOCATION Stack
;
730 Stack
= RxContext
->CurrentIrpSp
;
731 RxContext
->PostRequest
= FALSE
;
733 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
734 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
&&
735 Stack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
737 Queue
= DelayedWorkQueue
;
738 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
);
742 Queue
= CriticalWorkQueue
;
743 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
);
746 /* Check for overflow */
747 if (Stack
->FileObject
!= NULL
)
749 KeAcquireSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
751 Queued
= InterlockedIncrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
752 /* In case of an overflow, add the new queued call to the overflow list */
755 InterlockedDecrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
756 InsertTailList(&RxFileSystemDeviceObject
->OverflowQueue
[Queue
], &RxContext
->OverflowListEntry
);
757 ++RxFileSystemDeviceObject
->OverflowQueueCount
[Queue
];
759 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
763 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
766 ExInitializeWorkItem(&RxContext
->WorkQueueItem
, RxFspDispatch
, RxContext
);
767 ExQueueWorkItem((PWORK_QUEUE_ITEM
)&RxContext
->WorkQueueItem
, Queue
);
774 RxAdjustFileTimesAndSize(
780 PFILE_OBJECT FileObject
;
781 LARGE_INTEGER CurrentTime
;
782 FILE_BASIC_INFORMATION FileBasicInfo
;
783 FILE_END_OF_FILE_INFORMATION FileEOFInfo
;
784 BOOLEAN FileModified
, SetLastChange
, SetLastAccess
, SetLastWrite
, NeedUpdate
;
788 FileObject
= Context
->CurrentIrpSp
->FileObject
;
789 /* If Cc isn't initialized, the file was not read nor written, nothing to do */
790 if (FileObject
->PrivateCacheMap
== NULL
)
796 KeQuerySystemTime(&CurrentTime
);
798 Fobx
= (PFOBX
)Context
->pFobx
;
799 /* Was the file modified? */
800 FileModified
= BooleanFlagOn(FileObject
->Flags
, FO_FILE_MODIFIED
);
801 /* We'll set last write if it was modified and user didn't update yet */
802 SetLastWrite
= FileModified
&& !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_WRITE
);
803 /* File was accessed if: written or read (fastio), we'll update last access if user didn't */
804 SetLastAccess
= SetLastWrite
||
805 (BooleanFlagOn(FileObject
->Flags
, FO_FILE_FAST_IO_READ
) &&
806 !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_ACCESS
));
807 /* We'll set last change if it was modified and user didn't update yet */
808 SetLastChange
= FileModified
&& !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_USER_SET_LAST_CHANGE
);
810 /* Nothing to update? Job done */
811 if (!FileModified
&& !SetLastWrite
&& !SetLastAccess
&& !SetLastChange
)
816 Fcb
= (PFCB
)Context
->pFcb
;
817 /* By default, we won't issue any MRxSetFileInfoAtCleanup call */
819 RtlZeroMemory(&FileBasicInfo
, sizeof(FileBasicInfo
));
821 /* Update lastwrite time if required */
825 Fcb
->LastWriteTime
.QuadPart
= CurrentTime
.QuadPart
;
826 FileBasicInfo
.LastWriteTime
.QuadPart
= CurrentTime
.QuadPart
;
829 /* Update lastaccess time if required */
833 Fcb
->LastAccessTime
.QuadPart
= CurrentTime
.QuadPart
;
834 FileBasicInfo
.LastAccessTime
.QuadPart
= CurrentTime
.QuadPart
;
837 /* Update lastchange time if required */
841 Fcb
->LastChangeTime
.QuadPart
= CurrentTime
.QuadPart
;
842 FileBasicInfo
.ChangeTime
.QuadPart
= CurrentTime
.QuadPart
;
845 /* If one of the date was modified, issue a call to mini-rdr */
848 Context
->Info
.FileInformationClass
= FileBasicInformation
;
849 Context
->Info
.Buffer
= &FileBasicInfo
;
850 Context
->Info
.Length
= sizeof(FileBasicInfo
);
852 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxSetFileInfoAtCleanup
, (Context
));
856 /* If the file was modified, update its EOF */
859 FileEOFInfo
.EndOfFile
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
861 Context
->Info
.FileInformationClass
= FileEndOfFileInformation
;
862 Context
->Info
.Buffer
= &FileEOFInfo
;
863 Context
->Info
.Length
= sizeof(FileEOFInfo
);
865 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxSetFileInfoAtCleanup
, (Context
));
874 RxAllocateCanonicalNameBuffer(
875 PRX_CONTEXT RxContext
,
876 PUNICODE_STRING CanonicalName
,
877 USHORT CanonicalLength
)
881 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext
, RxContext
->Create
.CanonicalNameBuffer
);
883 /* Context must be free of any already allocated name */
884 ASSERT(RxContext
->Create
.CanonicalNameBuffer
== NULL
);
886 /* Validate string length */
887 if (CanonicalLength
> USHRT_MAX
- 1)
889 CanonicalName
->Buffer
= NULL
;
890 return STATUS_OBJECT_PATH_INVALID
;
893 CanonicalName
->Buffer
= RxAllocatePoolWithTag(PagedPool
| POOL_COLD_ALLOCATION
, CanonicalLength
, RX_MISC_POOLTAG
);
894 if (CanonicalName
->Buffer
== NULL
)
896 return STATUS_INSUFFICIENT_RESOURCES
;
899 CanonicalName
->Length
= 0;
900 CanonicalName
->MaximumLength
= CanonicalLength
;
902 /* Set the two places - they must always be identical */
903 RxContext
->Create
.CanonicalNameBuffer
= CanonicalName
->Buffer
;
904 RxContext
->AlsoCanonicalNameBuffer
= CanonicalName
->Buffer
;
906 return STATUS_SUCCESS
;
910 RxCancelNotifyChangeDirectoryRequestsForFobx(
920 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
921 PV_NET_ROOT VNetRoot
,
922 BOOLEAN ForceFilesClosed
)
928 LIST_ENTRY ContextsToCancel
;
930 /* Init a list for the contexts to cancel */
931 InitializeListHead(&ContextsToCancel
);
933 /* Lock our list lock */
934 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
936 /* Now, browse all the active contexts, to find the associated ones */
937 Entry
= RxActiveContexts
.Flink
;
938 while (Entry
!= &RxActiveContexts
)
940 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
941 Entry
= Entry
->Flink
;
943 /* Not the IRP we're looking for, ignore */
944 if (Context
->MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
||
945 Context
->MinorFunction
!= IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
950 /* Not the VNetRoot we're looking for, ignore */
951 if (Context
->pFcb
== NULL
||
952 (PV_NET_ROOT
)Context
->NotifyChangeDirectory
.pVNetRoot
!= VNetRoot
)
957 /* No cancel routine (can't be cancel, then), ignore */
958 if (Context
->MRxCancelRoutine
== NULL
)
963 /* At that point, we found a matching context
964 * If we're not asked to force close, then fail - it's still open
966 if (!ForceFilesClosed
)
968 Status
= STATUS_FILES_OPEN
;
972 /* Mark our context as cancelled */
973 SetFlag(Context
->Flags
, RX_CONTEXT_FLAG_CANCELLED
);
975 /* Move it to our list */
976 RemoveEntryList(&Context
->ContextListEntry
);
977 InsertTailList(&ContextsToCancel
, &Context
->ContextListEntry
);
979 InterlockedIncrement((volatile long *)&Context
->ReferenceCount
);
982 /* Done with the contexts */
983 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
985 if (Status
!= STATUS_SUCCESS
)
990 /* Now, handle all our "extracted" contexts */
991 while (!IsListEmpty(&ContextsToCancel
))
993 Entry
= RemoveHeadList(&ContextsToCancel
);
994 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, ContextListEntry
);
996 /* If they had an associated IRP (should be always true) */
997 if (Context
->CurrentIrp
!= NULL
)
999 /* Then, call cancel routine */
1000 ASSERT(Context
->MRxCancelRoutine
!= NULL
);
1001 DPRINT1("Canceling %p with %p\n", Context
, Context
->MRxCancelRoutine
);
1002 Context
->MRxCancelRoutine(Context
);
1005 /* And delete the context */
1006 RxDereferenceAndDeleteRxContext(Context
);
1015 PDEVICE_OBJECT DeviceObject
,
1025 RxCanonicalizeFileNameByServerSpecs(
1026 PRX_CONTEXT RxContext
,
1027 PUNICODE_STRING NetRootName
)
1029 USHORT NextChar
, CurChar
;
1034 /* Validate file name is not empty */
1035 MaxChars
= NetRootName
->Length
/ sizeof(WCHAR
);
1038 return STATUS_MORE_PROCESSING_REQUIRED
;
1041 /* Validate name is correct */
1042 for (NextChar
= 0, CurChar
= 0; CurChar
+ 1 < MaxChars
; NextChar
= CurChar
+ 1)
1046 for (i
= NextChar
+ 1; i
< MaxChars
; ++i
)
1048 if (NetRootName
->Buffer
[i
] == '\\' || NetRootName
->Buffer
[i
] == ':')
1055 if (CurChar
== NextChar
)
1057 if (((NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':') || NextChar
== (MaxChars
- 1)) && NetRootName
->Buffer
[NextChar
] != '.')
1064 if (CurChar
>= MaxChars
- 1)
1069 if (NetRootName
->Buffer
[CurChar
+ 1] != ':')
1071 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1076 if (NetRootName
->Buffer
[1] != ':')
1078 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1084 if ((CurChar
- NextChar
) == 1)
1086 if (NetRootName
->Buffer
[NextChar
+ 2] != '.')
1091 if (NetRootName
->Buffer
[NextChar
] == '\\' || NetRootName
->Buffer
[NextChar
] == ':' || NetRootName
->Buffer
[NextChar
] == '.')
1093 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1098 if ((CurChar
- NextChar
) != 2 || (NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':')
1099 || NetRootName
->Buffer
[NextChar
+ 1] != '.')
1104 if (NetRootName
->Buffer
[NextChar
+ 2] == '.')
1106 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1112 return STATUS_MORE_PROCESSING_REQUIRED
;
1116 RxCanonicalizeNameAndObtainNetRoot(
1117 PRX_CONTEXT RxContext
,
1118 PUNICODE_STRING FileName
,
1119 PUNICODE_STRING NetRootName
)
1122 NET_ROOT_TYPE NetRootType
;
1123 UNICODE_STRING CanonicalName
;
1127 NetRootType
= NET_ROOT_WILD
;
1129 RtlInitEmptyUnicodeString(NetRootName
, NULL
, 0);
1130 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
1132 /* if not relative opening, just handle the passed name */
1133 if (RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
== NULL
)
1135 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1136 if (!NT_SUCCESS(Status
))
1145 /* Make sure we have a valid FCB and a FOBX */
1146 Fcb
= RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext
;
1148 RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext2
== NULL
)
1150 return STATUS_INVALID_PARAMETER
;
1153 if (!NodeTypeIsFcb(Fcb
))
1155 return STATUS_INVALID_PARAMETER
;
1161 /* Get/Create the associated VNetRoot for opening */
1162 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1163 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
&&
1164 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_MAILSLOT_REPARSE
))
1166 ASSERT(CanonicalName
.Buffer
== RxContext
->Create
.CanonicalNameBuffer
);
1168 RxFreeCanonicalNameBuffer(RxContext
);
1169 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1170 if (NT_SUCCESS(Status
))
1172 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1176 /* Filename cannot contain wildcards */
1177 if (FsRtlDoesNameContainWildCards(NetRootName
))
1179 Status
= STATUS_OBJECT_NAME_INVALID
;
1182 /* Make sure file name is correct */
1183 if (NT_SUCCESS(Status
))
1185 Status
= RxCanonicalizeFileNameByServerSpecs(RxContext
, NetRootName
);
1188 /* Give the mini-redirector a chance to prepare the name */
1189 if (NT_SUCCESS(Status
) || Status
== STATUS_MORE_PROCESSING_REQUIRED
)
1191 if (RxContext
->Create
.pNetRoot
!= NULL
)
1193 NTSTATUS IgnoredStatus
;
1195 MINIRDR_CALL(IgnoredStatus
, RxContext
, RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
1196 MRxPreparseName
, (RxContext
, NetRootName
));
1197 (void)IgnoredStatus
;
1206 RxCheckFcbStructuresForAlignment(
1214 _In_ ACCESS_MASK DesiredAccess
,
1215 _In_ ULONG DesiredShareAccess
,
1216 _Inout_ PFILE_OBJECT FileObject
,
1217 _Inout_ PSHARE_ACCESS ShareAccess
,
1218 _In_ BOOLEAN Update
,
1220 _In_ PSZ wherelogtag
)
1224 RxDumpWantedAccess(where
, "", wherelogtag
, DesiredAccess
, DesiredShareAccess
);
1225 RxDumpCurrentAccess(where
, "", wherelogtag
, ShareAccess
);
1227 return IoCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
, Update
);
1234 RxCheckShareAccessPerSrvOpens(
1236 IN ACCESS_MASK DesiredAccess
,
1237 IN ULONG DesiredShareAccess
)
1240 BOOLEAN WriteAccess
;
1241 BOOLEAN DeleteAccess
;
1242 PSHARE_ACCESS ShareAccess
;
1246 ShareAccess
= &Fcb
->ShareAccessPerSrvOpens
;
1248 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess
, DesiredShareAccess
);
1249 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess
);
1251 /* Check if any access wanted */
1252 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
1253 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
1254 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
1256 if (ReadAccess
|| WriteAccess
|| DeleteAccess
)
1258 BOOLEAN SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
1259 BOOLEAN SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
1260 BOOLEAN SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
1262 /* Check whether there's a violation */
1264 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
1266 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
1268 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
1269 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
1270 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
1271 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
1273 return STATUS_SHARING_VIOLATION
;
1277 return STATUS_SUCCESS
;
1281 RxCleanupPipeQueues(
1282 PRX_CONTEXT Context
)
1291 RxCloseAssociatedSrvOpen(
1293 IN PRX_CONTEXT RxContext OPTIONAL
)
1298 BOOLEAN CloseSrvOpen
;
1299 PRX_CONTEXT LocalContext
;
1303 /* Assume SRV_OPEN is already closed */
1304 CloseSrvOpen
= FALSE
;
1305 /* If we have a FOBX, we'll have to close it */
1308 /* If the FOBX isn't closed yet */
1309 if (!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
))
1311 SrvOpen
= Fobx
->SrvOpen
;
1312 Fcb
= (PFCB
)SrvOpen
->pFcb
;
1313 /* Check whether we've to close SRV_OPEN first */
1314 if (!BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1316 CloseSrvOpen
= TRUE
;
1320 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1322 /* Not much to do */
1323 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1325 if (SrvOpen
->OpenCount
> 0)
1327 --SrvOpen
->OpenCount
;
1332 /* No need to close SRV_OPEN, so close FOBX */
1335 RxMarkFobxOnClose(Fobx
);
1337 return STATUS_SUCCESS
;
1342 /* No FOBX? No RX_CONTEXT, ok, job done! */
1343 if (RxContext
== NULL
)
1345 return STATUS_SUCCESS
;
1348 /* Get the FCB from RX_CONTEXT */
1349 Fcb
= (PFCB
)RxContext
->pFcb
;
1353 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1354 if (RxContext
== NULL
)
1356 ASSERT(Fobx
!= NULL
);
1358 LocalContext
= RxCreateRxContext(NULL
, Fcb
->RxDeviceObject
, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING
| RX_CONTEXT_FLAG_WAIT
);
1359 if (LocalContext
== NULL
)
1361 return STATUS_INSUFFICIENT_RESOURCES
;
1364 LocalContext
->MajorFunction
= 2;
1365 LocalContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
1366 LocalContext
->pFobx
= (PMRX_FOBX
)Fobx
;
1367 LocalContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)Fobx
->SrvOpen
;
1371 LocalContext
= RxContext
;
1374 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1376 /* Now, close the FOBX */
1379 RxMarkFobxOnClose(Fobx
);
1383 InterlockedDecrement((volatile long *)&Fcb
->OpenCount
);
1386 /* If not a "standard" file, SRV_OPEN can be null */
1387 if (SrvOpen
== NULL
)
1389 ASSERT((NodeType(Fcb
) == RDBSS_NTC_OPENTARGETDIR_FCB
) || (NodeType(Fcb
) == RDBSS_NTC_IPC_SHARE
) || (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
));
1390 RxDereferenceNetFcb(Fcb
);
1392 if (LocalContext
!= RxContext
)
1394 RxDereferenceAndDeleteRxContext(LocalContext
);
1397 return STATUS_SUCCESS
;
1400 /* If SRV_OPEN isn't in a good condition, nothing to close */
1401 if (SrvOpen
->Condition
!= Condition_Good
)
1403 if (LocalContext
!= RxContext
)
1405 RxDereferenceAndDeleteRxContext(LocalContext
);
1408 return STATUS_SUCCESS
;
1411 /* Decrease open count */
1412 if (SrvOpen
->OpenCount
> 0)
1414 --SrvOpen
->OpenCount
;
1417 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1418 if (SrvOpen
->OpenCount
== 1)
1420 if (!IsListEmpty(&SrvOpen
->FobxList
))
1422 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen
->FobxList
.Flink
, FOBX
, FobxQLinks
)->ScavengerFinalizationList
))
1424 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
1429 /* Nothing left, purge FCB */
1430 if (SrvOpen
->OpenCount
== 0 && RxContext
== NULL
)
1432 RxPurgeNetFcb(Fcb
, LocalContext
);
1435 /* Already closed? Job done! */
1436 SrvOpen
= Fobx
->SrvOpen
;
1437 if (SrvOpen
== NULL
||
1438 (SrvOpen
->OpenCount
!= 0 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
)) ||
1439 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1441 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1442 if (LocalContext
!= RxContext
)
1444 RxDereferenceAndDeleteRxContext(LocalContext
);
1447 return STATUS_SUCCESS
;
1450 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1452 /* Inform mini-rdr about closing */
1453 MINIRDR_CALL(Status
, LocalContext
, Fcb
->MRxDispatch
, MRxCloseSrvOpen
, (LocalContext
));
1454 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1455 Status
, RxContext
, Fobx
, Fcb
, SrvOpen
);
1457 /* And mark as such */
1458 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
);
1459 SrvOpen
->Key
= (PVOID
)-1;
1461 /* If we were delayed, we're not! */
1462 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
1464 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
1468 RxRemoveShareAccessPerSrvOpens(SrvOpen
);
1469 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
1472 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1474 /* Mark the FOBX closed as well */
1475 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1477 if (LocalContext
!= RxContext
)
1479 RxDereferenceAndDeleteRxContext(LocalContext
);
1489 RxCollapseOrCreateSrvOpen(
1490 PRX_CONTEXT RxContext
)
1497 PIO_STACK_LOCATION Stack
;
1498 ACCESS_MASK DesiredAccess
;
1499 RX_BLOCK_CONDITION FcbCondition
;
1503 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext
);
1505 Fcb
= (PFCB
)RxContext
->pFcb
;
1506 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1507 ++Fcb
->UncleanCount
;
1509 Stack
= RxContext
->CurrentIrpSp
;
1510 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
1511 ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
1513 Disposition
= RxContext
->Create
.NtCreateParameters
.Disposition
;
1515 /* Try to find a reusable SRV_OPEN */
1516 Status
= RxSearchForCollapsibleOpen(RxContext
, DesiredAccess
, ShareAccess
);
1517 if (Status
== STATUS_NOT_FOUND
)
1519 /* If none found, create one */
1520 SrvOpen
= RxCreateSrvOpen((PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
, Fcb
);
1521 if (SrvOpen
== NULL
)
1523 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1527 SrvOpen
->DesiredAccess
= DesiredAccess
;
1528 SrvOpen
->ShareAccess
= ShareAccess
;
1529 Status
= STATUS_SUCCESS
;
1532 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
1534 if (Status
!= STATUS_SUCCESS
)
1536 FcbCondition
= Condition_Bad
;
1540 RxInitiateSrvOpenKeyAssociation(SrvOpen
);
1542 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1543 RxContext
->CurrentIrp
->IoStatus
.Information
= 0xABCDEF;
1544 /* Inform the mini-rdr we're handling a create */
1545 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCreate
, (RxContext
));
1546 ASSERT(RxContext
->CurrentIrp
->IoStatus
.Information
== 0xABCDEF);
1548 DPRINT("MRxCreate returned: %x\n", Status
);
1549 if (Status
== STATUS_SUCCESS
)
1551 /* In case of overwrite, reset file size */
1552 if (Disposition
== FILE_OVERWRITE
|| Disposition
== FILE_OVERWRITE_IF
)
1554 RxAcquirePagingIoResource(RxContext
, Fcb
);
1555 Fcb
->Header
.AllocationSize
.QuadPart
= 0LL;
1556 Fcb
->Header
.FileSize
.QuadPart
= 0LL;
1557 Fcb
->Header
.ValidDataLength
.QuadPart
= 0LL;
1558 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1559 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1560 RxReleasePagingIoResource(RxContext
, Fcb
);
1564 /* Otherwise, adjust sizes */
1565 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1566 if (CcIsFileCached(RxContext
->CurrentIrpSp
->FileObject
))
1568 RxAdjustAllocationSizeforCC(Fcb
);
1570 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1574 /* Set the IoStatus with information returned by mini-rdr */
1575 RxContext
->CurrentIrp
->IoStatus
.Information
= RxContext
->Create
.ReturnedCreateInformation
;
1577 SrvOpen
->OpenStatus
= Status
;
1578 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1579 RxTransitionSrvOpen(SrvOpen
, (Status
== STATUS_SUCCESS
? Condition_Good
: Condition_Bad
));
1581 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1583 RxCompleteSrvOpenKeyAssociation(SrvOpen
);
1585 if (Status
== STATUS_SUCCESS
)
1587 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
1589 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
1591 SrvOpen
->CreateOptions
= RxContext
->Create
.NtCreateParameters
.CreateOptions
;
1592 FcbCondition
= Condition_Good
;
1596 FcbCondition
= Condition_Bad
;
1597 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1598 RxContext
->pRelevantSrvOpen
= NULL
;
1600 if (RxContext
->pFobx
!= NULL
)
1602 RxDereferenceNetFobx(RxContext
->pFobx
, LHS_ExclusiveLockHeld
);
1603 RxContext
->pFobx
= NULL
;
1608 /* Set FCB state - good or bad - depending on whether create succeed */
1609 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb
, Fcb
->Condition
);
1610 RxTransitionNetFcb(Fcb
, FcbCondition
);
1612 else if (Status
== STATUS_SUCCESS
)
1614 BOOLEAN IsGood
, ExtraOpen
;
1616 /* A reusable SRV_OPEN was found */
1617 RxContext
->CurrentIrp
->IoStatus
.Information
= FILE_OPENED
;
1620 SrvOpen
= (PSRV_OPEN
)RxContext
->pRelevantSrvOpen
;
1622 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1623 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1624 if (!StableCondition(SrvOpen
->Condition
))
1626 RxReferenceSrvOpen(SrvOpen
);
1627 ++SrvOpen
->OpenCount
;
1630 RxReleaseFcb(RxContext
, Fcb
);
1631 RxContext
->Create
.FcbAcquired
= FALSE
;
1633 RxWaitForStableSrvOpen(SrvOpen
, RxContext
);
1635 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext
, Fcb
)))
1637 RxContext
->Create
.FcbAcquired
= TRUE
;
1640 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1643 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1646 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCollapseOpen
, (RxContext
));
1648 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1652 Status
= SrvOpen
->OpenStatus
;
1657 --SrvOpen
->OpenCount
;
1658 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1662 --Fcb
->UncleanCount
;
1664 DPRINT("Status: %x\n", Status
);
1671 PRX_CONTEXT Context
)
1673 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1679 PFILE_OBJECT FileObject
;
1680 LARGE_INTEGER TruncateSize
;
1681 PLARGE_INTEGER TruncateSizePtr
;
1682 BOOLEAN NeedPurge
, FcbTableAcquired
, OneLeft
, IsFile
, FcbAcquired
, LeftForDelete
;
1686 Fcb
= (PFCB
)Context
->pFcb
;
1687 Fobx
= (PFOBX
)Context
->pFobx
;
1688 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context
, Fobx
, Fcb
);
1690 /* File system closing, it's OK */
1693 if (Fcb
->UncleanCount
> 0)
1695 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1698 return STATUS_SUCCESS
;
1701 /* Check we have a correct FCB type */
1702 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&&
1703 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&&
1704 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1705 NodeType(Fcb
) != RDBSS_NTC_SPOOLFILE
)
1707 DPRINT1("Invalid Fcb type for %p\n", Fcb
);
1708 RxBugCheck(Fcb
->Header
.NodeTypeCode
, 0, 0);
1711 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1712 ASSERT(!BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
));
1714 RxMarkFobxOnCleanup(Fobx
, &NeedPurge
);
1716 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1717 if (!NT_SUCCESS(Status
))
1724 Fobx
->AssociatedFileObject
= NULL
;
1726 /* In case SRV_OPEN used is part of FCB */
1727 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_SRVOPEN_USED
))
1729 ASSERT(Fcb
->UncleanCount
!= 0);
1730 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1732 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1734 --Fcb
->UncachedUncleanCount
;
1737 /* Inform mini-rdr */
1738 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1740 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1741 --Fobx
->SrvOpen
->UncleanFobxCount
;
1743 RxUninitializeCacheMap(Context
, FileObject
, NULL
);
1745 RxReleaseFcb(Context
, Fcb
);
1747 return STATUS_SUCCESS
;
1750 /* Report the fact that file could be set as delete on close */
1751 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
1753 SetFlag(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
1756 /* Cancel any pending notification */
1757 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx
);
1759 /* Backup open count before we start playing with it */
1760 OpenCount
= Fcb
->ShareAccess
.OpenCount
;
1762 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
1763 FcbTableAcquired
= FALSE
;
1764 LeftForDelete
= FALSE
;
1765 OneLeft
= (Fcb
->UncleanCount
== 1);
1769 /* Unclean count and delete on close? Verify whether we're the one */
1770 if (OneLeft
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
))
1772 if (RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, FALSE
))
1774 FcbTableAcquired
= TRUE
;
1778 RxReleaseFcb(Context
, Fcb
);
1780 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
1782 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1783 if (Status
!= STATUS_SUCCESS
)
1785 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1789 FcbTableAcquired
= TRUE
;
1792 /* That means we'll perform the delete on close! */
1793 if (Fcb
->UncleanCount
== 1)
1795 LeftForDelete
= TRUE
;
1799 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1800 FcbTableAcquired
= FALSE
;
1805 TruncateSizePtr
= NULL
;
1806 /* Handle cleanup for pipes and printers */
1807 if (NetRoot
->Type
== NET_ROOT_PIPE
|| NetRoot
->Type
== NET_ROOT_PRINT
)
1809 RxCleanupPipeQueues(Context
);
1811 /* Handle cleanup for files */
1812 else if (NetRoot
->Type
== NET_ROOT_DISK
|| NetRoot
->Type
== NET_ROOT_WILD
)
1814 Context
->LowIoContext
.Flags
|= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS
;
1815 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
1818 FsRtlFastUnlockAll(&Fcb
->Specific
.Fcb
.FileLock
, FileObject
, RxGetRequestorProcess(Context
), Context
);
1820 /* If there are still locks to release, proceed */
1821 if (Context
->LowIoContext
.ParamsFor
.Locks
.LockList
!= NULL
)
1823 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_UNLOCK_MULTIPLE
);
1824 Context
->LowIoContext
.ParamsFor
.Locks
.Flags
= 0;
1825 Status
= RxLowIoLockControlShell(Context
);
1828 /* Fix times and size */
1829 RxAdjustFileTimesAndSize(Context
);
1831 /* If we're the only one left... */
1834 /* And if we're supposed to delete on close */
1837 /* Update the sizes */
1838 RxAcquirePagingIoResource(Context
, Fcb
);
1839 Fcb
->Header
.FileSize
.QuadPart
= 0;
1840 Fcb
->Header
.ValidDataLength
.QuadPart
= 0;
1841 RxReleasePagingIoResource(Context
, Fcb
);
1843 /* Otherwise, call the mini-rdr to adjust sizes */
1846 /* File got grown up, fill with zeroes */
1847 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
1848 (Fcb
->Header
.ValidDataLength
.QuadPart
< Fcb
->Header
.FileSize
.QuadPart
))
1850 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxZeroExtend
, (Context
));
1851 Fcb
->Header
.ValidDataLength
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1854 /* File was truncated, let mini-rdr proceed */
1855 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
))
1857 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxTruncate
, (Context
));
1858 ClearFlag(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
);
1860 /* Keep track of file change for Cc uninit */
1861 TruncateSize
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1862 TruncateSizePtr
= &TruncateSize
;
1867 /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
1875 /* Otherwise, try to see whether we can purge */
1878 NeedPurge
= (OneLeft
&& (LeftForDelete
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
)));
1885 /* We have to still be there! */
1886 ASSERT(Fcb
->UncleanCount
!= 0);
1887 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1889 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1891 --Fcb
->UncachedUncleanCount
;
1894 /* Inform mini-rdr about ongoing cleanup */
1895 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1897 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1898 --Fobx
->SrvOpen
->UncleanFobxCount
;
1901 if (DisableFlushOnCleanup
)
1903 /* Only if we're the last standing */
1904 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
&&
1905 Fcb
->UncleanCount
== Fcb
->UncachedUncleanCount
)
1907 DPRINT("Flushing %p due to last cached handle cleanup\n", Context
);
1908 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1914 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
1916 DPRINT("Flushing %p on cleanup\n", Context
);
1917 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1921 /* If only remaining uncached & unclean, then flush and purge */
1922 if (!BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1924 if (Fcb
->UncachedUncleanCount
!= 0)
1926 if (Fcb
->UncachedUncleanCount
== Fcb
->UncleanCount
&&
1927 Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
1929 DPRINT("Flushing FCB in system cache for %p\n", Context
);
1930 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
1935 /* If purge required, and not about to delete, flush */
1936 if (!LeftForDelete
&& NeedPurge
)
1938 DPRINT("Flushing FCB in system cache for %p\n", Context
);
1939 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1942 /* If it was a file, drop cache */
1945 DPRINT("Uninit cache map for file\n");
1946 RxUninitializeCacheMap(Context
, FileObject
, TruncateSizePtr
);
1949 /* If that's the one left for deletion, or if it needs purge, flush */
1950 if (LeftForDelete
|| NeedPurge
)
1952 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, !LeftForDelete
);
1953 /* If that's for deletion, also remove from FCB table */
1956 RxRemoveNameNetFcb(Fcb
);
1957 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1958 FcbTableAcquired
= FALSE
;
1962 /* Remove any share access */
1963 if (OpenCount
!= 0 && NetRoot
->Type
== NET_ROOT_DISK
)
1965 RxRemoveShareAccess(FileObject
, &Fcb
->ShareAccess
, "Cleanup the share access", "ClnUpShr");
1968 /* In case there's caching, on a file, update file metadata */
1969 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
&& BooleanFlagOn(Fobx
->Flags
, 0x20000000) &&
1970 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
) && !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
))
1976 SetFlag(FileObject
->Flags
, FO_CLEANUP_COMPLETE
);
1978 FcbAcquired
= FALSE
;
1979 RxReleaseFcb(Context
, Fcb
);
1985 RxReleaseFcb(Context
, Fcb
);
1988 if (FcbTableAcquired
)
1990 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1996 #undef BugCheckFileId
2002 PRX_CONTEXT Context
)
2004 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
2008 PFILE_OBJECT FileObject
;
2009 BOOLEAN DereferenceFobx
, AcquiredFcb
;
2013 Fcb
= (PFCB
)Context
->pFcb
;
2014 Fobx
= (PFOBX
)Context
->pFobx
;
2015 FileObject
= Context
->CurrentIrpSp
->FileObject
;
2016 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context
, Fobx
, Fcb
, FileObject
);
2018 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2019 if (!NT_SUCCESS(Status
))
2029 /* Check our FCB type is expected */
2030 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
2031 (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
|| (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
&&
2032 (NodeType(Fcb
) < RDBSS_NTC_SPOOLFILE
|| NodeType(Fcb
) > RDBSS_NTC_OPENTARGETDIR_FCB
))))
2034 RxBugCheck(NodeType(Fcb
), 0, 0);
2037 RxReferenceNetFcb(Fcb
);
2039 DereferenceFobx
= FALSE
;
2040 /* If we're not closing FS */
2046 SrvOpen
= (PSRV_OPEN
)Fobx
->pSrvOpen
;
2047 SrvCall
= (PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
;
2048 /* Handle delayed close */
2049 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
2051 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
| FCB_STATE_ORPHANED
))
2053 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
))
2055 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx
, SrvOpen
);
2057 if (SrvOpen
->OpenCount
== 1 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_COLLAPSING_DISABLED
))
2059 if (InterlockedIncrement(&SrvCall
->NumberOfCloseDelayedFiles
) >= SrvCall
->MaximumNumberOfCloseDelayedFiles
)
2061 InterlockedDecrement(&SrvCall
->NumberOfCloseDelayedFiles
);
2065 DereferenceFobx
= TRUE
;
2066 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
2073 /* If we reach maximum of delayed close/or if there are no delayed close */
2074 if (!DereferenceFobx
)
2078 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
2079 if (NetRoot
->Type
!= NET_ROOT_PRINT
)
2081 /* Delete if asked */
2082 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
2084 RxScavengeRelatedFobxs(Fcb
);
2085 RxSynchronizeWithScavenger(Context
);
2087 RxReleaseFcb(Context
, Fcb
);
2089 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
2090 RxOrphanThisFcb(Fcb
);
2091 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
2093 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2094 ASSERT(NT_SUCCESS(Status
));
2099 RxMarkFobxOnClose(Fobx
);
2102 if (DereferenceFobx
)
2104 ASSERT(Fobx
!= NULL
);
2105 RxDereferenceNetFobx(Fobx
, LHS_SharedLockHeld
);
2109 RxCloseAssociatedSrvOpen(Fobx
, Context
);
2112 RxDereferenceNetFobx(Fobx
, LHS_ExclusiveLockHeld
);
2116 Freed
= RxDereferenceAndFinalizeNetFcb(Fcb
, Context
, FALSE
, FALSE
);
2117 AcquiredFcb
= !Freed
;
2119 FileObject
->FsContext
= (PVOID
)-1;
2123 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
2127 RxReleaseFcb(Context
, Fcb
);
2128 AcquiredFcb
= FALSE
;
2133 if (_SEH2_AbnormalTermination())
2137 RxReleaseFcb(Context
, Fcb
);
2142 ASSERT(!AcquiredFcb
);
2147 DPRINT("Status: %x\n", Status
);
2149 #undef BugCheckFileId
2155 PRX_CONTEXT Context
)
2159 PFILE_OBJECT FileObject
;
2160 PIO_STACK_LOCATION Stack
;
2164 DPRINT("RxCommonCreate(%p)\n", Context
);
2166 Irp
= Context
->CurrentIrp
;
2167 Stack
= Context
->CurrentIrpSp
;
2168 FileObject
= Stack
->FileObject
;
2170 /* Check whether that's a device opening */
2171 if (FileObject
->FileName
.Length
== 0 && FileObject
->RelatedFileObject
== NULL
)
2173 FileObject
->FsContext
= &RxDeviceFCB
;
2174 FileObject
->FsContext2
= NULL
;
2176 ++RxDeviceFCB
.NodeReferenceCount
;
2177 ++RxDeviceFCB
.OpenCount
;
2179 Irp
->IoStatus
.Information
= FILE_OPENED
;
2180 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject
, Context
->RxDeviceObject
, &Context
->RxDeviceObject
->DeviceName
);
2182 Status
= STATUS_SUCCESS
;
2186 PFCB RelatedFcb
= NULL
;
2188 /* Make sure caller is consistent */
2189 if (FlagOn(Stack
->Parameters
.Create
.Options
, FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
) ==
2190 (FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
))
2192 DPRINT1("Create.Options: %x\n", Stack
->Parameters
.Create
.Options
);
2193 return STATUS_INVALID_PARAMETER
;
2196 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
2197 Context
, FileObject
, Stack
->Parameters
.Create
.Options
, Stack
->Flags
, Stack
->Parameters
.Create
.FileAttributes
,
2198 Stack
->Parameters
.Create
.ShareAccess
, Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
2199 DPRINT("FileName: %wZ\n", &FileObject
->FileName
);
2201 if (FileObject
->RelatedFileObject
!= NULL
)
2203 RelatedFcb
= FileObject
->RelatedFileObject
->FsContext
;
2204 DPRINT("Rel FO: %p, path: %wZ\n", FileObject
->RelatedFileObject
, RelatedFcb
->FcbTableEntry
.Path
);
2207 /* Going to rename? */
2208 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
2210 DPRINT("TargetDir!\n");
2213 /* Copy create parameters to the context */
2214 RxCopyCreateParameters(Context
);
2216 /* If the caller wants to establish a connection, go ahead */
2217 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_CREATE_TREE_CONNECTION
))
2219 Status
= RxCreateTreeConnect(Context
);
2223 /* Validate file name */
2224 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2225 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2226 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2228 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2229 RtlMoveMemory(&FileObject
->FileName
.Buffer
[0], &FileObject
->FileName
.Buffer
[1],
2230 FileObject
->FileName
.Length
);
2232 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2233 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2234 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2236 return STATUS_OBJECT_NAME_INVALID
;
2240 /* Attempt to open the file */
2243 UNICODE_STRING NetRootName
;
2245 /* Strip last \ if required */
2246 if (FileObject
->FileName
.Length
!= 0 &&
2247 FileObject
->FileName
.Buffer
[FileObject
->FileName
.Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
2249 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NON_DIRECTORY_FILE
))
2251 return STATUS_OBJECT_NAME_INVALID
;
2254 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2255 Context
->Create
.Flags
|= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
;
2258 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
))
2260 FileObject
->Flags
|= FO_WRITE_THROUGH
;
2263 /* Get the associated net root to opening */
2264 Status
= RxCanonicalizeNameAndObtainNetRoot(Context
, &FileObject
->FileName
, &NetRootName
);
2265 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
2270 /* And attempt to open */
2271 Status
= RxCreateFromNetRoot(Context
, &NetRootName
);
2272 if (Status
== STATUS_SHARING_VIOLATION
)
2276 else if (Status
== STATUS_REPARSE
)
2278 Context
->CurrentIrp
->IoStatus
.Information
= 0;
2282 ASSERT(!BooleanFlagOn(Context
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_REPARSE
));
2285 while (Status
== STATUS_MORE_PROCESSING_REQUIRED
);
2288 if (Status
== STATUS_RETRY
)
2290 RxpPrepareCreateContextForReuse(Context
);
2292 ASSERT(Status
!= STATUS_PENDING
);
2295 DPRINT("Status: %lx\n", Status
);
2304 RxCommonDevFCBCleanup(
2305 PRX_CONTEXT Context
)
2312 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context
);
2314 Fcb
= Context
->pFcb
;
2315 Status
= STATUS_SUCCESS
;
2316 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2318 /* Our FOBX if set, has to be a VNetRoot */
2319 if (Context
->pFobx
!= NULL
)
2321 RxAcquirePrefixTableLockShared(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2322 if (Context
->pFobx
->NodeTypeCode
!= RDBSS_NTC_V_NETROOT
)
2324 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2326 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2330 --Fcb
->UncleanCount
;
2341 RxCommonDevFCBClose(
2342 PRX_CONTEXT Context
)
2346 PMRX_V_NET_ROOT NetRoot
;
2350 DPRINT("RxCommonDevFCBClose(%p)\n", Context
);
2352 Fcb
= Context
->pFcb
;
2353 NetRoot
= (PMRX_V_NET_ROOT
)Context
->pFobx
;
2354 Status
= STATUS_SUCCESS
;
2355 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2357 /* Our FOBX if set, has to be a VNetRoot */
2358 if (NetRoot
!= NULL
)
2360 RxAcquirePrefixTableLockExclusive(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2361 if (NetRoot
->NodeTypeCode
== RDBSS_NTC_V_NETROOT
)
2363 --NetRoot
->NumberOfOpens
;
2364 RxDereferenceVNetRoot(NetRoot
, LHS_ExclusiveLockHeld
);
2368 Status
= STATUS_NOT_IMPLEMENTED
;
2370 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2382 RxCommonDevFCBFsCtl(
2383 PRX_CONTEXT Context
)
2386 return STATUS_NOT_IMPLEMENTED
;
2394 RxCommonDevFCBIoCtl(
2395 PRX_CONTEXT Context
)
2401 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context
);
2403 if (Context
->pFobx
!= NULL
)
2405 return STATUS_INVALID_HANDLE
;
2408 /* Is that a prefix claim from MUP? */
2409 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2411 return RxPrefixClaim(Context
);
2414 /* Otherwise, pass through the mini-rdr */
2415 Status
= RxXXXControlFileCallthru(Context
);
2416 if (Status
!= STATUS_PENDING
)
2418 if (Context
->PostRequest
)
2420 Context
->ResumeRoutine
= RxCommonDevFCBIoCtl
;
2421 Status
= RxFsdPostRequest(Context
);
2425 DPRINT("Status: %lx\n", Status
);
2431 RxCommonDevFCBQueryVolInfo(
2432 PRX_CONTEXT Context
)
2435 return STATUS_NOT_IMPLEMENTED
;
2443 RxCommonDeviceControl(
2444 PRX_CONTEXT Context
)
2450 /* Prefix claim is only allowed for device, not files */
2451 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2453 return STATUS_INVALID_DEVICE_REQUEST
;
2456 /* Submit to mini-rdr */
2457 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_IOCTL
);
2458 Status
= RxLowIoSubmit(Context
, RxLowIoIoCtlShellCompletion
);
2459 if (Status
== STATUS_PENDING
)
2461 RxDereferenceAndDeleteRxContext_Real(Context
);
2472 RxCommonDirectoryControl(
2473 PRX_CONTEXT Context
)
2478 PIO_STACK_LOCATION Stack
;
2482 Fcb
= (PFCB
)Context
->pFcb
;
2483 Fobx
= (PFOBX
)Context
->pFobx
;
2484 Stack
= Context
->CurrentIrpSp
;
2485 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context
, Fobx
, Fcb
, Stack
->MinorFunction
);
2487 /* Call the appropriate helper */
2488 if (Stack
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
)
2490 Status
= RxQueryDirectory(Context
);
2492 else if (Stack
->MinorFunction
== IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
2494 Status
= RxNotifyChangeDirectory(Context
);
2495 if (Status
== STATUS_PENDING
)
2497 RxDereferenceAndDeleteRxContext_Real(Context
);
2502 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2510 RxCommonDispatchProblem(
2511 PRX_CONTEXT Context
)
2514 return STATUS_NOT_IMPLEMENTED
;
2519 RxCommonFileSystemControl(
2520 PRX_CONTEXT Context
)
2523 return STATUS_NOT_IMPLEMENTED
;
2528 RxCommonFlushBuffers(
2529 PRX_CONTEXT Context
)
2532 return STATUS_NOT_IMPLEMENTED
;
2537 RxCommonLockControl(
2538 PRX_CONTEXT Context
)
2541 return STATUS_NOT_IMPLEMENTED
;
2547 PRX_CONTEXT Context
)
2550 return STATUS_NOT_IMPLEMENTED
;
2558 RxCommonQueryInformation(
2559 PRX_CONTEXT Context
)
2561 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2562 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2563 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2570 PIO_STACK_LOCATION Stack
;
2571 FILE_INFORMATION_CLASS FileInfoClass
;
2575 Fcb
= (PFCB
)Context
->pFcb
;
2576 Fobx
= (PFOBX
)Context
->pFobx
;
2577 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2579 Irp
= Context
->CurrentIrp
;
2580 Stack
= Context
->CurrentIrpSp
;
2581 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp
->AssociatedIrp
.SystemBuffer
,
2582 Stack
->Parameters
.QueryFile
.Length
, Stack
->Parameters
.QueryFile
.FileInformationClass
);
2584 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2585 FileInfoClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
2592 /* Get a writable buffer */
2593 Buffer
= RxMapSystemBuffer(Context
);
2596 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2600 RtlZeroMemory(Buffer
, Context
->Info
.Length
);
2602 /* Validate file type */
2603 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
)
2605 if (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
2607 Status
= STATUS_INVALID_PARAMETER
;
2610 else if (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
)
2612 if (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
)
2614 Status
= STATUS_NOT_IMPLEMENTED
;
2618 Status
= STATUS_INVALID_PARAMETER
;
2625 /* Acquire the right lock */
2626 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
2627 FileInfoClass
!= FileNameInformation
)
2629 if (FileInfoClass
== FileCompressionInformation
)
2631 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2635 Status
= RxAcquireSharedFcb(Context
, Fcb
);
2638 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2640 Status
= STATUS_PENDING
;
2643 else if (!NT_SUCCESS(Status
))
2651 /* Dispatch to the right helper */
2652 switch (FileInfoClass
)
2654 case FileBasicInformation
:
2655 Status
= RxQueryBasicInfo(Context
, Buffer
);
2658 case FileStandardInformation
:
2659 Status
= RxQueryStandardInfo(Context
, Buffer
);
2662 case FileInternalInformation
:
2663 Status
= RxQueryInternalInfo(Context
, Buffer
);
2666 case FileEaInformation
:
2667 Status
= RxQueryEaInfo(Context
, Buffer
);
2670 case FileNameInformation
:
2671 Status
= RxQueryNameInfo(Context
, Buffer
);
2674 case FileAllInformation
:
2675 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo
);
2676 if (!NT_SUCCESS(Status
))
2681 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
), RxQueryStandardInfo
);
2682 if (!NT_SUCCESS(Status
))
2687 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2688 sizeof(FILE_STANDARD_INFORMATION
), RxQueryInternalInfo
);
2689 if (!NT_SUCCESS(Status
))
2694 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2695 sizeof(FILE_STANDARD_INFORMATION
) +
2696 sizeof(FILE_INTERNAL_INFORMATION
), RxQueryEaInfo
);
2697 if (!NT_SUCCESS(Status
))
2702 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2703 sizeof(FILE_STANDARD_INFORMATION
) +
2704 sizeof(FILE_INTERNAL_INFORMATION
) +
2705 sizeof(FILE_EA_INFORMATION
), RxQueryPositionInfo
);
2706 if (!NT_SUCCESS(Status
))
2711 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2712 sizeof(FILE_STANDARD_INFORMATION
) +
2713 sizeof(FILE_INTERNAL_INFORMATION
) +
2714 sizeof(FILE_EA_INFORMATION
) +
2715 sizeof(FILE_POSITION_INFORMATION
), RxQueryNameInfo
);
2718 case FileAlternateNameInformation
:
2719 Status
= RxQueryAlternateNameInfo(Context
, Buffer
);
2722 case FilePipeInformation
:
2723 case FilePipeLocalInformation
:
2724 case FilePipeRemoteInformation
:
2725 Status
= RxQueryPipeInfo(Context
, Buffer
);
2728 case FileCompressionInformation
:
2729 Status
= RxQueryCompressedInfo(Context
, Buffer
);
2733 Context
->IoStatusBlock
.Status
= RxpQueryInfoMiniRdr(Context
, FileInfoClass
, Buffer
);
2734 Status
= Context
->IoStatusBlock
.Status
;
2738 if (Context
->Info
.Length
< 0)
2740 Status
= STATUS_BUFFER_OVERFLOW
;
2741 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2744 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryFile
.Length
- Context
->Info
.Length
;
2750 RxReleaseFcb(Context
, Fcb
);
2755 DPRINT("Status: %x\n", Status
);
2758 #undef SET_SIZE_AND_QUERY
2763 RxCommonQueryQuotaInformation(
2764 PRX_CONTEXT Context
)
2767 return STATUS_NOT_IMPLEMENTED
;
2772 RxCommonQuerySecurity(
2773 PRX_CONTEXT Context
)
2776 return STATUS_NOT_IMPLEMENTED
;
2784 RxCommonQueryVolumeInformation(
2785 PRX_CONTEXT Context
)
2791 PIO_STACK_LOCATION Stack
;
2795 Fcb
= (PFCB
)Context
->pFcb
;
2796 Fobx
= (PFOBX
)Context
->pFobx
;
2798 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2800 Irp
= Context
->CurrentIrp
;
2801 Stack
= Context
->CurrentIrpSp
;
2802 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack
->Parameters
.QueryVolume
.Length
,
2803 Stack
->Parameters
.QueryVolume
.FsInformationClass
, Irp
->AssociatedIrp
.SystemBuffer
);
2805 Context
->Info
.FsInformationClass
= Stack
->Parameters
.QueryVolume
.FsInformationClass
;
2806 Context
->Info
.Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2807 Context
->Info
.Length
= Stack
->Parameters
.QueryVolume
.Length
;
2809 /* Forward to mini-rdr */
2810 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxQueryVolumeInfo
, (Context
));
2812 /* Post request if mini-rdr asked to */
2813 if (Context
->PostRequest
)
2815 Status
= RxFsdPostRequest(Context
);
2819 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryVolume
.Length
- Context
->Info
.Length
;
2822 DPRINT("Status: %x\n", Status
);
2829 PRX_CONTEXT RxContext
)
2837 PFILE_OBJECT FileObject
;
2838 LARGE_INTEGER ByteOffset
;
2839 PIO_STACK_LOCATION Stack
;
2840 PLOWIO_CONTEXT LowIoContext
;
2841 PRDBSS_DEVICE_OBJECT RxDeviceObject
;
2842 ULONG ReadLength
, CapturedRxContextSerialNumber
= RxContext
->SerialNumber
;
2843 BOOLEAN CanWait
, PagingIo
, NoCache
, Sync
, PostRequest
, IsPipe
, ReadCachingEnabled
, ReadCachingDisabled
, InFsp
, OwnerSet
;
2847 Fcb
= (PFCB
)RxContext
->pFcb
;
2848 Fobx
= (PFOBX
)RxContext
->pFobx
;
2849 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext
, Fobx
, Fcb
);
2851 /* Get some parameters */
2852 Irp
= RxContext
->CurrentIrp
;
2853 Stack
= RxContext
->CurrentIrpSp
;
2854 CanWait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
2855 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
2856 NoCache
= BooleanFlagOn(Irp
->Flags
, IRP_NOCACHE
);
2857 Sync
= !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
2858 InFsp
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
);
2859 ReadLength
= Stack
->Parameters
.Read
.Length
;
2860 ByteOffset
.QuadPart
= Stack
->Parameters
.Read
.ByteOffset
.QuadPart
;
2861 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength
, ByteOffset
.QuadPart
,
2862 (CanWait
? "CW" : "!CW"), (PagingIo
? "PI" : "!PI"), (NoCache
? "NC" : "!NC"), (Sync
? "S" : "!S"));
2864 RxItsTheSameContext();
2866 Irp
->IoStatus
.Information
= 0;
2868 /* Should the read be loud - so far, it's just ignored on ReactOS:
2869 * s/DPRINT/DPRINT1/g will make it loud
2871 LowIoContext
= &RxContext
->LowIoContext
;
2872 CheckForLoudOperations(RxContext
);
2873 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
))
2875 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2876 ByteOffset
, ReadLength
,
2877 Fcb
, Fcb
->Header
.ValidDataLength
, Fcb
->Header
.FileSize
, Fcb
->Header
.AllocationSize
);
2880 RxDeviceObject
= RxContext
->RxDeviceObject
;
2882 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
) && Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
2884 InterlockedIncrement((volatile long *)&RxDeviceObject
->ReadOperations
);
2886 if (ByteOffset
.QuadPart
!= Fobx
->Specific
.DiskFile
.PredictedReadOffset
)
2888 InterlockedIncrement((volatile long *)&RxDeviceObject
->RandomReadOperations
);
2890 Fobx
->Specific
.DiskFile
.PredictedReadOffset
= ByteOffset
.QuadPart
+ ReadLength
;
2894 ExInterlockedAddLargeStatistic(&RxDeviceObject
->PagingReadBytesRequested
, ReadLength
);
2898 ExInterlockedAddLargeStatistic(&RxDeviceObject
->NonPagingReadBytesRequested
, ReadLength
);
2902 ExInterlockedAddLargeStatistic(&RxDeviceObject
->CacheReadBytesRequested
, ReadLength
);
2906 /* A pagefile cannot be a pipe */
2907 IsPipe
= Fcb
->NetRoot
->Type
== NET_ROOT_PIPE
;
2908 if (IsPipe
&& PagingIo
)
2910 return STATUS_INVALID_DEVICE_REQUEST
;
2913 /* Null-length read is no-op */
2914 if (ReadLength
== 0)
2916 return STATUS_SUCCESS
;
2919 /* Validate FCB type */
2920 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&& NodeType(Fcb
) != RDBSS_NTC_VOLUME_FCB
)
2922 return STATUS_INVALID_DEVICE_REQUEST
;
2925 /* Init the lowio context for possible forward */
2926 RxInitializeLowIoContext(LowIoContext
, LOWIO_OP_READ
);
2928 PostRequest
= FALSE
;
2929 ReadCachingDisabled
= FALSE
;
2931 ReadCachingEnabled
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2932 FileObject
= Stack
->FileObject
;
2933 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
2938 /* If no caching, make sure current Cc data have been flushed */
2939 if (!PagingIo
&& NoCache
&& !ReadCachingEnabled
&& FileObject
->SectionObjectPointer
!= NULL
)
2941 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
2942 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2947 else if (Status
!= STATUS_SUCCESS
)
2952 ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, TRUE
);
2953 CcFlushCache(FileObject
->SectionObjectPointer
, &ByteOffset
, ReadLength
, &Irp
->IoStatus
);
2954 RxReleasePagingIoResource(RxContext
, Fcb
);
2956 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
2961 RxAcquirePagingIoResource(RxContext
, Fcb
);
2962 RxReleasePagingIoResource(RxContext
, Fcb
);
2965 /* Acquire the appropriate lock */
2966 if (PagingIo
&& !ReadCachingEnabled
)
2970 if (!ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, CanWait
))
2978 LowIoContext
->Resource
= Fcb
->Header
.PagingIoResource
;
2983 if (!ReadCachingEnabled
)
2985 if (!CanWait
&& NoCache
)
2987 Status
= RxAcquireSharedFcbWaitForEx(RxContext
, Fcb
);
2988 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2990 DPRINT1("RdAsyLNG %x\n", RxContext
);
2994 if (Status
!= STATUS_SUCCESS
)
2996 DPRINT1("RdAsyOthr %x\n", RxContext
);
3000 if (RxIsFcbAcquiredShared(Fcb
) <= 0xF000)
3002 LowIoContext
->Resource
= Fcb
->Header
.Resource
;
3012 Status
= RxAcquireSharedFcb(RxContext
, Fcb
);
3013 if (Status
== STATUS_LOCK_NOT_GRANTED
)
3018 else if (Status
!= STATUS_SUCCESS
)
3026 RxItsTheSameContext();
3028 ReadCachingDisabled
= (ReadCachingEnabled
== FALSE
);
3034 RxGetFileSizeWithLock(Fcb
, &FileSize
);
3036 /* Make sure FLOCK doesn't conflict */
3039 if (!FsRtlCheckLockForReadAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
3041 Status
= STATUS_FILE_LOCK_CONFLICT
;
3046 /* Validate byteoffset vs length */
3047 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
3049 if (ByteOffset
.QuadPart
>= FileSize
)
3051 Status
= STATUS_END_OF_FILE
;
3055 if (ReadLength
> FileSize
- ByteOffset
.QuadPart
)
3057 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
3062 if (!PagingIo
&& !NoCache
&& ReadCachingEnabled
&&
3063 !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
))
3065 /* File was not cached yet, do it */
3066 if (FileObject
->PrivateCacheMap
== NULL
)
3068 if (BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
))
3070 Status
= STATUS_FILE_CLOSED
;
3074 RxAdjustAllocationSizeforCC(Fcb
);
3076 CcInitializeCacheMap(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
3077 FALSE
, &RxData
.CacheManagerCallbacks
, Fcb
);
3079 if (BooleanFlagOn(Fcb
->MRxDispatch
->MRxFlags
, RDBSS_NO_DEFERRED_CACHE_READAHEAD
))
3081 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
3085 CcSetAdditionalCacheAttributes(FileObject
, TRUE
, FALSE
);
3086 SetFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3089 CcSetReadAheadGranularity(FileObject
, NetRoot
->DiskParameters
.ReadAheadGranularity
);
3092 /* This should never happen - fix your RDR */
3093 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
3098 CcMdlRead(FileObject
, &ByteOffset
, ReadLength
, &Irp
->MdlAddress
, &Irp
->IoStatus
);
3099 Status
= Irp
->IoStatus
.Status
;
3100 ASSERT(NT_SUCCESS(Status
));
3105 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3106 if (SystemBuffer
== NULL
)
3108 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3112 SetFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3114 RxItsTheSameContext();
3116 /* Perform the read */
3117 if (!CcCopyRead(FileObject
, &ByteOffset
, ReadLength
, CanWait
, SystemBuffer
, &Irp
->IoStatus
))
3119 if (!ReadCachingEnabled
)
3121 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3124 RxItsTheSameContext();
3130 if (!ReadCachingEnabled
)
3132 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3135 Status
= Irp
->IoStatus
.Status
;
3136 ASSERT(NT_SUCCESS(Status
));
3141 /* Validate the reading */
3142 if (FileObject
->PrivateCacheMap
!= NULL
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) &&
3143 ByteOffset
.QuadPart
>= 4096)
3145 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
3146 ClearFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3149 /* If it's consistent, forward to mini-rdr */
3150 if (Fcb
->CachedNetRootType
!= NET_ROOT_DISK
|| BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) ||
3151 ByteOffset
.QuadPart
< Fcb
->Header
.ValidDataLength
.QuadPart
)
3153 LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
= ReadLength
;
3154 LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
= ByteOffset
.QuadPart
;
3156 RxItsTheSameContext();
3158 if (InFsp
&& ReadCachingDisabled
)
3160 ExSetResourceOwnerPointer((PagingIo
? Fcb
->Header
.PagingIoResource
: Fcb
->Header
.Resource
),
3161 (PVOID
)((ULONG_PTR
)RxContext
| 3));
3165 Status
= RxLowIoReadShell(RxContext
);
3167 RxItsTheSameContext();
3171 if (ByteOffset
.QuadPart
> FileSize
)
3174 Irp
->IoStatus
.Information
= ReadLength
;
3178 if (ByteOffset
.QuadPart
+ ReadLength
> FileSize
)
3180 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
3183 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3184 RtlZeroMemory(SystemBuffer
, ReadLength
);
3185 Irp
->IoStatus
.Information
= ReadLength
;
3191 RxItsTheSameContext();
3193 /* Post if required */
3196 InterlockedIncrement((volatile long *)&RxContext
->ReferenceCount
);
3197 Status
= RxFsdPostRequest(RxContext
);
3201 /* Update FO in case of sync IO */
3202 if (!IsPipe
&& !PagingIo
)
3204 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
3206 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
3211 /* Set FastIo if read was a success */
3212 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
3214 if (!IsPipe
&& !PagingIo
)
3216 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
3220 /* In case we're done (not expected any further processing */
3221 if (_SEH2_AbnormalTermination() || Status
!= STATUS_PENDING
|| PostRequest
)
3223 /* Release everything that can be */
3224 if (ReadCachingDisabled
)
3230 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3234 RxReleasePagingIoResource(RxContext
, Fcb
);
3241 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3245 RxReleaseFcb(RxContext
, Fcb
);
3250 /* Dereference/Delete context */
3253 RxDereferenceAndDeleteRxContext(RxContext
);
3257 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
3259 RxResumeBlockedOperations_Serially(RxContext
, &Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
3263 /* We cannot return more than asked */
3264 if (Status
== STATUS_SUCCESS
)
3266 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
3273 RxDereferenceAndDeleteRxContext(RxContext
);
3284 PRX_CONTEXT Context
)
3287 return STATUS_NOT_IMPLEMENTED
;
3292 RxCommonSetInformation(
3293 PRX_CONTEXT Context
)
3296 return STATUS_NOT_IMPLEMENTED
;
3301 RxCommonSetQuotaInformation(
3302 PRX_CONTEXT Context
)
3305 return STATUS_NOT_IMPLEMENTED
;
3310 RxCommonSetSecurity(
3311 PRX_CONTEXT Context
)
3314 return STATUS_NOT_IMPLEMENTED
;
3319 RxCommonSetVolumeInformation(
3320 PRX_CONTEXT Context
)
3323 return STATUS_NOT_IMPLEMENTED
;
3328 RxCommonUnimplemented(
3329 PRX_CONTEXT Context
)
3332 return STATUS_NOT_IMPLEMENTED
;
3338 PRX_CONTEXT Context
)
3341 return STATUS_NOT_IMPLEMENTED
;
3347 IN PRX_CONTEXT RxContext
)
3352 return STATUS_NOT_IMPLEMENTED
;
3359 RxCopyCreateParameters(
3360 IN PRX_CONTEXT RxContext
)
3364 PFILE_OBJECT FileObject
;
3365 PIO_STACK_LOCATION Stack
;
3366 PDFS_NAME_CONTEXT DfsNameContext
;
3367 PIO_SECURITY_CONTEXT SecurityContext
;
3369 Irp
= RxContext
->CurrentIrp
;
3370 Stack
= RxContext
->CurrentIrpSp
;
3371 FileObject
= Stack
->FileObject
;
3372 SecurityContext
= Stack
->Parameters
.Create
.SecurityContext
;
3374 RxContext
->Create
.NtCreateParameters
.SecurityContext
= SecurityContext
;
3375 if (SecurityContext
->AccessState
!= NULL
&& SecurityContext
->AccessState
->SecurityDescriptor
!= NULL
)
3377 RxContext
->Create
.SdLength
= RtlLengthSecurityDescriptor(SecurityContext
->AccessState
->SecurityDescriptor
);
3378 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext
->Create
.NtCreateParameters
.SecurityContext
,
3379 RxContext
->Create
.SdLength
);
3381 if (SecurityContext
->SecurityQos
!= NULL
)
3383 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityContext
->SecurityQos
->ImpersonationLevel
;
3387 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityImpersonation
;
3389 RxContext
->Create
.NtCreateParameters
.DesiredAccess
= SecurityContext
->DesiredAccess
;
3391 RxContext
->Create
.NtCreateParameters
.AllocationSize
.QuadPart
= Irp
->Overlay
.AllocationSize
.QuadPart
;
3392 RxContext
->Create
.NtCreateParameters
.FileAttributes
= Stack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
;
3393 RxContext
->Create
.NtCreateParameters
.ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
3394 RxContext
->Create
.NtCreateParameters
.Disposition
= (Stack
->Parameters
.Create
.Options
>> 24) & 0x000000FF;
3395 RxContext
->Create
.NtCreateParameters
.CreateOptions
= Stack
->Parameters
.Create
.Options
& 0xFFFFFF;
3397 DfsContext
= FileObject
->FsContext2
;
3398 DfsNameContext
= FileObject
->FsContext
;
3399 RxContext
->Create
.NtCreateParameters
.DfsContext
= DfsContext
;
3400 RxContext
->Create
.NtCreateParameters
.DfsNameContext
= DfsNameContext
;
3401 ASSERT(DfsContext
== NULL
|| DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) ||
3402 DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) ||
3403 DfsContext
== UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT
) ||
3404 DfsContext
== UIntToPtr(DFS_USER_NAME_CONTEXT
));
3405 ASSERT(DfsNameContext
== NULL
|| DfsNameContext
->NameContextType
== DFS_OPEN_CONTEXT
||
3406 DfsNameContext
->NameContextType
== DFS_DOWNLEVEL_OPEN_CONTEXT
||
3407 DfsNameContext
->NameContextType
== DFS_CSCAGENT_NAME_CONTEXT
||
3408 DfsNameContext
->NameContextType
== DFS_USER_NAME_CONTEXT
);
3409 FileObject
->FsContext2
= NULL
;
3410 FileObject
->FsContext
= NULL
;
3412 RxContext
->pFcb
= NULL
;
3413 RxContext
->Create
.ReturnedCreateInformation
= 0;
3415 /* if we stripped last \, it has to be a directory! */
3416 if (BooleanFlagOn(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
))
3418 SetFlag(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DIRECTORY_FILE
);
3421 RxContext
->Create
.EaLength
= Stack
->Parameters
.Create
.EaLength
;
3422 if (RxContext
->Create
.EaLength
== 0)
3424 RxContext
->Create
.EaBuffer
= NULL
;
3428 RxContext
->Create
.EaBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
3429 DPRINT("EA Buffer: %p, Length: %lx\n", Irp
->AssociatedIrp
.SystemBuffer
, RxContext
->Create
.EaLength
);
3434 RxCreateFromNetRoot(
3435 PRX_CONTEXT Context
,
3436 PUNICODE_STRING NetRootName
)
3441 PFILE_OBJECT FileObject
;
3442 PIO_STACK_LOCATION Stack
;
3443 ACCESS_MASK DesiredAccess
;
3444 USHORT DesiredShareAccess
;
3448 /* Validate that the context is consistent */
3449 if (Context
->Create
.pNetRoot
== NULL
)
3451 return STATUS_BAD_NETWORK_PATH
;
3454 NetRoot
= (PNET_ROOT
)Context
->Create
.pNetRoot
;
3455 if (Context
->RxDeviceObject
!= NetRoot
->pSrvCall
->RxDeviceObject
)
3457 return STATUS_BAD_NETWORK_PATH
;
3460 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) &&
3461 !BooleanFlagOn(NetRoot
->pSrvCall
->Flags
, SRVCALL_FLAG_DFS_AWARE_SERVER
))
3463 return STATUS_DFS_UNAVAILABLE
;
3466 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
3467 BooleanFlagOn(NetRoot
->Flags
, NETROOT_FLAG_DFS_AWARE_NETROOT
))
3469 return STATUS_OBJECT_TYPE_MISMATCH
;
3472 Stack
= Context
->CurrentIrpSp
;
3473 DesiredShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
3474 if (NetRoot
->Type
== NET_ROOT_PRINT
)
3476 DesiredShareAccess
= FILE_SHARE_VALID_FLAGS
;
3479 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
3481 /* We don't support renaming yet */
3482 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
3485 return STATUS_NOT_IMPLEMENTED
;
3488 /* Try to find (or create) the FCB for the file */
3489 Status
= RxFindOrCreateFcb(Context
, NetRootName
);
3490 Fcb
= (PFCB
)Context
->pFcb
;
3493 ASSERT(!NT_SUCCESS(Status
));
3495 if (!NT_SUCCESS(Status
) || Fcb
== NULL
)
3500 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_CREATE_MAILSLOT
))
3502 Fcb
->Header
.NodeTypeCode
= RDBSS_NTC_MAILSLOT
;
3506 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
3509 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
3510 if (NT_SUCCESS(Status
))
3512 RxTransitionNetFcb(Fcb
, Condition_Good
);
3513 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb
, Fcb
->Condition
);
3515 RxSetupNetFileObject(Context
);
3516 return STATUS_SUCCESS
;
3520 FileObject
= Stack
->FileObject
;
3521 /* Check SA for conflict */
3522 if (Fcb
->OpenCount
> 0)
3524 Status
= RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
3525 &Fcb
->ShareAccess
, FALSE
, "early check per useropens", "EarlyPerUO");
3526 if (!NT_SUCCESS(Status
))
3528 RxDereferenceNetFcb(Fcb
);
3533 if (BooleanFlagOn(Context
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
) &&
3534 !BooleanFlagOn(Context
->Create
.NtCreateParameters
.DesiredAccess
, ~SYNCHRONIZE
))
3541 /* Find a SRV_OPEN that suits the opening */
3542 Status
= RxCollapseOrCreateSrvOpen(Context
);
3543 if (Status
== STATUS_SUCCESS
)
3548 SrvOpen
= (PSRV_OPEN
)Context
->pRelevantSrvOpen
;
3549 Fobx
= (PFOBX
)Context
->pFobx
;
3550 /* There are already opens, check for conflict */
3551 if (Fcb
->OpenCount
!= 0)
3553 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
,
3554 FileObject
, &Fcb
->ShareAccess
,
3555 FALSE
, "second check per useropens",
3558 ++SrvOpen
->UncleanFobxCount
;
3559 RxDereferenceNetFobx(Fobx
, LHS_LockNotHeld
);
3566 if (NetRoot
->Type
!= NET_ROOT_PIPE
)
3568 RxSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
3569 &Fcb
->ShareAccess
, "initial shareaccess setup", "InitShrAcc");
3573 RxSetupNetFileObject(Context
);
3575 /* No conflict? Set up SA */
3576 if (Fcb
->OpenCount
!= 0 && NetRoot
->Type
!= NET_ROOT_PIPE
)
3578 RxUpdateShareAccess(FileObject
, &Fcb
->ShareAccess
, "update share access", "UpdShrAcc");
3581 ++Fcb
->UncleanCount
;
3582 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
3584 ++Fcb
->UncachedUncleanCount
;
3587 if (SrvOpen
->UncleanFobxCount
== 0 && Fcb
->UncleanCount
== 1 &&
3588 !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE
))
3590 RxChangeBufferingState(SrvOpen
, NULL
, FALSE
);
3593 /* No pending close, we're active */
3594 ClearFlag(Fcb
->FcbState
, FCB_STATE_DELAY_CLOSE
);
3597 ++SrvOpen
->UncleanFobxCount
;
3598 ++SrvOpen
->OpenCount
;
3599 SrvOpen
->ulFileSizeVersion
= Fcb
->ulFileSizeVersion
;
3601 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NO_INTERMEDIATE_BUFFERING
))
3603 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
);
3604 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
);
3606 ClearFlag(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
);
3607 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3609 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, TRUE
, TRUE
);
3612 /* Now, update SA for the SRV_OPEN */
3613 RxUpdateShareAccessPerSrvOpens(SrvOpen
);
3615 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
3617 SetFlag(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
);
3620 /* Update the FOBX info */
3623 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
3625 SetFlag(FileObject
->Flags
, FO_NAMED_PIPE
);
3628 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PRINT
||
3629 Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
3631 Fobx
->PipeHandleInformation
= &Fobx
->Specific
.NamedPipe
.PipeHandleInformation
;
3633 Fobx
->Specific
.NamedPipe
.CollectDataTime
.QuadPart
= 0;
3634 Fobx
->Specific
.NamedPipe
.CollectDataSize
= Context
->Create
.pNetRoot
->NamedPipeParameters
.DataCollectionSize
;
3636 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.TypeOfPipe
= Context
->Create
.PipeType
;
3637 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.ReadMode
= Context
->Create
.PipeReadMode
;
3638 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.CompletionMode
= Context
->Create
.PipeCompletionMode
;
3640 InitializeListHead(&Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
3641 InitializeListHead(&Fobx
->Specific
.NamedPipe
.WriteSerializationQueue
);
3645 Status
= STATUS_SUCCESS
;
3650 if (Fcb
->OpenCount
== 0)
3652 if (Context
->Create
.FcbAcquired
)
3654 Context
->Create
.FcbAcquired
= (RxDereferenceAndFinalizeNetFcb(Fcb
,
3658 if (!Context
->Create
.FcbAcquired
)
3660 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
3666 RxDereferenceNetFcb(Fcb
);
3678 RxCreateTreeConnect(
3679 IN PRX_CONTEXT RxContext
)
3682 PV_NET_ROOT VNetRoot
;
3683 PFILE_OBJECT FileObject
;
3684 PIO_STACK_LOCATION Stack
;
3685 NET_ROOT_TYPE NetRootType
;
3686 UNICODE_STRING CanonicalName
, RemainingName
;
3690 Stack
= RxContext
->CurrentIrpSp
;
3691 FileObject
= Stack
->FileObject
;
3693 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
3694 /* As long as we don't know connection type, mark it wild */
3695 NetRootType
= NET_ROOT_WILD
;
3696 /* Get the type by parsing the name */
3697 Status
= RxFirstCanonicalize(RxContext
, &FileObject
->FileName
, &CanonicalName
, &NetRootType
);
3698 if (!NT_SUCCESS(Status
))
3703 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
3704 RxContext
->Create
.TreeConnectOpenDeferred
= FALSE
;
3705 RtlInitEmptyUnicodeString(&RxContext
->Create
.TransportName
, NULL
, 0);
3706 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserName
, NULL
, 0);
3707 RtlInitEmptyUnicodeString(&RxContext
->Create
.Password
, NULL
, 0);
3708 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserDomainName
, NULL
, 0);
3710 /* We don't handle EA - they come from DFS, don't care */
3711 if (Stack
->Parameters
.Create
.EaLength
> 0)
3716 /* Mount if required */
3717 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3718 if (Status
== STATUS_NETWORK_CREDENTIAL_CONFLICT
)
3720 RxScavengeVNetRoots(RxContext
->RxDeviceObject
);
3721 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3724 if (!NT_SUCCESS(Status
))
3729 /* Validate the rest of the name with mini-rdr */
3730 if (RemainingName
.Length
> 0)
3732 MINIRDR_CALL(Status
, RxContext
,
3733 RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
3734 MRxIsValidDirectory
, (RxContext
, &RemainingName
));
3737 if (!NT_SUCCESS(Status
))
3742 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
3743 RxReferenceVNetRoot(VNetRoot
);
3744 if (InterlockedCompareExchange(&VNetRoot
->AdditionalReferenceForDeleteFsctlTaken
, 1, 0) != 0)
3746 RxDereferenceVNetRoot(VNetRoot
, LHS_LockNotHeld
);
3749 FileObject
->FsContext
= &RxDeviceFCB
;
3750 FileObject
->FsContext2
= VNetRoot
;
3752 VNetRoot
->ConstructionStatus
= STATUS_SUCCESS
;
3753 ++VNetRoot
->NumberOfOpens
;
3755 /* Create is over - clear context */
3756 RxContext
->Create
.pSrvCall
= NULL
;
3757 RxContext
->Create
.pNetRoot
= NULL
;
3758 RxContext
->Create
.pVNetRoot
= NULL
;
3765 RxDebugControlCommand(
3766 _In_ PSTR ControlString
)
3774 IN PDRIVER_OBJECT DriverObject
,
3775 IN PUNICODE_STRING RegistryPath
)
3778 USHORT i
, State
= 0;
3780 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject
, RegistryPath
);
3784 RxCheckFcbStructuresForAlignment();
3786 RtlZeroMemory(&RxData
, sizeof(RxData
));
3787 RxData
.NodeTypeCode
= RDBSS_NTC_DATA_HEADER
;
3788 RxData
.NodeByteSize
= sizeof(RxData
);
3789 RxData
.DriverObject
= DriverObject
;
3791 RtlZeroMemory(&RxDeviceFCB
, sizeof(RxDeviceFCB
));
3792 RxDeviceFCB
.spacer
.NodeTypeCode
= RDBSS_NTC_DEVICE_FCB
;
3793 RxDeviceFCB
.spacer
.NodeByteSize
= sizeof(RxDeviceFCB
);
3795 KeInitializeSpinLock(&RxStrucSupSpinLock
);
3796 RxExports
.pRxStrucSupSpinLock
= &RxStrucSupSpinLock
;
3798 RxInitializeDebugSupport();
3800 RxFileSystemDeviceObject
= (PRDBSS_DEVICE_OBJECT
)&RxSpaceForTheWrappersDeviceObject
;
3801 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject
, sizeof(RxSpaceForTheWrappersDeviceObject
));
3806 RxGetRegistryParameters(RegistryPath
);
3807 RxReadRegistryParameters();
3809 Status
= RxInitializeRegistrationStructures();
3810 if (!NT_SUCCESS(Status
))
3816 RxInitializeDispatcher();
3818 ExInitializeNPagedLookasideList(&RxContextLookasideList
, RxAllocatePoolWithTag
, RxFreePool
, 0, sizeof(RX_CONTEXT
), RX_IRPC_POOLTAG
, 4);
3820 InitializeListHead(&RxIrpsList
);
3821 KeInitializeSpinLock(&RxIrpsListSpinLock
);
3823 InitializeListHead(&RxActiveContexts
);
3824 InitializeListHead(&RxSrvCalldownList
);
3826 ExInitializeFastMutex(&RxContextPerFileSerializationMutex
);
3827 ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex
);
3828 KeInitializeMutex(&RxScavengerMutex
, 1);
3829 KeInitializeMutex(&RxSerializationMutex
, 1);
3831 for (i
= 0; i
< RxMaximumWorkQueue
; ++i
)
3833 RxFileSystemDeviceObject
->PostedRequestCount
[i
] = 0;
3834 RxFileSystemDeviceObject
->OverflowQueueCount
[i
] = 0;
3835 InitializeListHead(&RxFileSystemDeviceObject
->OverflowQueue
[i
]);
3838 KeInitializeSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
);
3840 RxInitializeDispatchVectors(DriverObject
);
3842 ExInitializeResourceLite(&RxData
.Resource
);
3843 RxData
.OurProcess
= IoGetCurrentProcess();
3845 RxInitializeRxTimer();
3849 if (!NT_SUCCESS(Status
))
3851 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BC4, Status
);
3852 RxInitUnwind(DriverObject
, State
);
3856 /* There are still bits to init - be consider it's fine for now */
3859 return STATUS_NOT_IMPLEMENTED
;
3861 return STATUS_SUCCESS
;
3869 RxDumpCurrentAccess(
3872 _In_ PSZ wherelogtag
,
3873 _In_ PSHARE_ACCESS ShareAccess
)
3885 _In_ PSZ wherelogtag
,
3886 _In_ ACCESS_MASK DesiredAccess
,
3887 _In_ ULONG DesiredShareAccess
)
3894 RxFastIoCheckIfPossible(
3895 PFILE_OBJECT FileObject
,
3896 PLARGE_INTEGER FileOffset
,
3897 ULONG Length
, BOOLEAN Wait
,
3898 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
3899 PIO_STATUS_BLOCK IoStatus
,
3900 PDEVICE_OBJECT DeviceObject
)
3907 /* Get the FCB to validate it */
3908 Fcb
= FileObject
->FsContext
;
3909 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
)
3911 DPRINT1("Not a file, FastIO not possible!\n");
3915 if (FileObject
->DeletePending
)
3917 DPRINT1("File delete pending\n");
3921 /* If there's a pending write operation, deny fast operation */
3922 if (Fcb
->NonPaged
->OutstandingAsyncWrites
!= 0)
3924 DPRINT1("Write operations to be completed\n");
3928 /* Deny read on orphaned node */
3929 SrvOpen
= (PSRV_OPEN
)((PFOBX
)FileObject
->FsContext2
)->pSrvOpen
;
3930 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
3932 DPRINT1("SRV_OPEN orphaned\n");
3936 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
3938 DPRINT1("FCB orphaned\n");
3942 /* If there's a buffering state change pending, deny fast operation (it might change
3945 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
))
3947 DPRINT1("Buffering change pending\n");
3951 /* File got renamed/deleted, deny operation */
3952 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_DELETED
) ||
3953 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_RENAMED
))
3955 DPRINT1("File renamed/deleted\n");
3959 /* Process pending change buffering state operations */
3960 FsRtlEnterFileSystem();
3961 RxProcessChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
3962 FsRtlExitFileSystem();
3964 /* If operation to come is a read operation */
3965 if (CheckForReadOperation
)
3967 LARGE_INTEGER LargeLength
;
3969 /* Check that read cache is enabled */
3970 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
3972 DPRINT1("Read caching disabled\n");
3976 /* Check whether there's a lock conflict */
3977 LargeLength
.QuadPart
= Length
;
3978 if (!FsRtlFastCheckLockForRead(&Fcb
->Specific
.Fcb
.FileLock
,
3983 PsGetCurrentProcess()))
3985 DPRINT1("FsRtlFastCheckLockForRead failed\n");
3998 RxFastIoDeviceControl(
3999 PFILE_OBJECT FileObject
,
4001 PVOID InputBuffer OPTIONAL
,
4002 ULONG InputBufferLength
,
4003 PVOID OutputBuffer OPTIONAL
,
4004 ULONG OutputBufferLength
,
4005 ULONG IoControlCode
,
4006 PIO_STATUS_BLOCK IoStatus
,
4007 PDEVICE_OBJECT DeviceObject
)
4009 /* Only supported IOCTL */
4010 if (IoControlCode
== IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
)
4027 PFILE_OBJECT FileObject
,
4028 PLARGE_INTEGER FileOffset
,
4033 PIO_STATUS_BLOCK IoStatus
,
4034 PDEVICE_OBJECT DeviceObject
)
4037 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4041 DPRINT("RxFastIoRead: %p (%p, %p)\n", FileObject
, FileObject
->FsContext
,
4042 FileObject
->FsContext2
);
4043 DPRINT("Reading %ld at %I64x\n", Length
, FileOffset
->QuadPart
);
4045 /* Prepare a TLI context */
4046 ASSERT(RxIsThisTheTopLevelIrp(NULL
));
4047 RxInitializeTopLevelIrpContext(&TopLevelContext
, (PIRP
)FSRTL_FAST_IO_TOP_LEVEL_IRP
,
4048 (PRDBSS_DEVICE_OBJECT
)DeviceObject
);
4050 Ret
= FsRtlCopyRead2(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
,
4051 IoStatus
, DeviceObject
, &TopLevelContext
);
4054 DPRINT("Read OK\n");
4058 DPRINT1("Read failed!\n");
4067 PFILE_OBJECT FileObject
,
4068 PLARGE_INTEGER FileOffset
,
4073 PIO_STATUS_BLOCK IoStatus
,
4074 PDEVICE_OBJECT DeviceObject
)
4082 PRX_CONTEXT RxContext
,
4083 PUNICODE_STRING NetRootName
)
4089 PV_NET_ROOT VNetRoot
;
4090 BOOLEAN TableAcquired
, AcquiredExclusive
;
4094 NetRoot
= (PNET_ROOT
)RxContext
->Create
.pNetRoot
;
4095 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
4096 ASSERT(NetRoot
== VNetRoot
->NetRoot
);
4098 Status
= STATUS_SUCCESS
;
4099 AcquiredExclusive
= FALSE
;
4101 RxAcquireFcbTableLockShared(&NetRoot
->FcbTable
, TRUE
);
4102 TableAcquired
= TRUE
;
4103 Version
= NetRoot
->FcbTable
.Version
;
4105 /* Look for a cached FCB */
4106 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4109 DPRINT("RxFcbTableLookupFcb returned NULL fcb for %wZ\n", NetRootName
);
4113 DPRINT("FCB found for %wZ\n", &Fcb
->FcbTableEntry
.Path
);
4114 /* If FCB was to be orphaned, consider it as not suitable */
4115 if (Fcb
->fShouldBeOrphaned
)
4117 RxDereferenceNetFcb(Fcb
);
4118 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4120 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
4121 TableAcquired
= TRUE
;
4122 AcquiredExclusive
= TRUE
;
4124 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4125 if (Fcb
!= NULL
&& Fcb
->fShouldBeOrphaned
)
4127 RxOrphanThisFcb(Fcb
);
4128 RxDereferenceNetFcb(Fcb
);
4134 /* If FCB was not found or is not covering full path, prepare for more work */
4135 if (Fcb
== NULL
|| Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
4137 if (!AcquiredExclusive
)
4139 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4140 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
4141 TableAcquired
= TRUE
;
4144 /* If FCB table was updated in between, re-attempt a lookup */
4145 if (NetRoot
->FcbTable
.Version
!= Version
)
4147 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4148 if (Fcb
!= NULL
&& Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
4155 /* Allocate the FCB */
4160 Fcb
= RxCreateNetFcb(RxContext
, VNetRoot
, NetRootName
);
4163 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4167 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4168 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
4174 if (_SEH2_AbnormalTermination())
4176 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4177 TableAcquired
= FALSE
;
4181 RxTransitionNetFcb(Fcb
, Condition_Bad
);
4183 ExAcquireResourceExclusiveLite(Fcb
->Header
.Resource
, TRUE
);
4184 if (RxDereferenceAndFinalizeNetFcb(Fcb
, NULL
, FALSE
, FALSE
) != 0)
4186 ExReleaseResourceLite(Fcb
->Header
.Resource
);
4195 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4198 if (!NT_SUCCESS(Status
))
4203 RxContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
4204 DPRINT("FCB %p is in condition %lx\n", Fcb
, Fcb
->Condition
);
4206 if (!RxContext
->Create
.FcbAcquired
)
4208 RxWaitForStableNetFcb(Fcb
, RxContext
);
4209 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4210 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
4217 RxFirstCanonicalize(
4218 PRX_CONTEXT RxContext
,
4219 PUNICODE_STRING FileName
,
4220 PUNICODE_STRING CanonicalName
,
4221 PNET_ROOT_TYPE NetRootType
)
4225 BOOLEAN UncName
, PrependString
, IsSpecial
;
4226 USHORT CanonicalLength
;
4227 UNICODE_STRING SessionIdString
;
4228 WCHAR SessionIdBuffer
[16];
4232 Type
= NET_ROOT_WILD
;
4233 PrependString
= FALSE
;
4236 Status
= STATUS_SUCCESS
;
4238 /* Name has to contain at least \\ */
4239 if (FileName
->Length
< 2 * sizeof(WCHAR
))
4241 return STATUS_OBJECT_NAME_INVALID
;
4244 /* First easy check, is that a path with a name? */
4245 CanonicalLength
= FileName
->Length
;
4246 if (FileName
->Length
> 5 * sizeof(WCHAR
))
4248 if (FileName
->Buffer
[0] == '\\' && FileName
->Buffer
[1] == ';')
4250 if (FileName
->Buffer
[3] == ':')
4252 Type
= NET_ROOT_DISK
;
4256 Type
= NET_ROOT_PRINT
;
4261 /* Nope, attempt deeper parsing */
4262 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
&& FileName
->Buffer
[1] != ';')
4265 PWSTR FirstSlash
, EndOfString
;
4267 SetFlag(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_UNC_NAME
);
4270 /* The lack of drive letter will be replaced by session ID */
4271 SessionId
= RxGetSessionId(RxContext
->CurrentIrpSp
);
4272 RtlInitEmptyUnicodeString(&SessionIdString
, SessionIdBuffer
, sizeof(SessionIdBuffer
));
4273 RtlIntegerToUnicodeString(SessionId
, 10, &SessionIdString
);
4275 EndOfString
= Add2Ptr(FileName
->Buffer
, FileName
->Length
);
4276 for (FirstSlash
= &FileName
->Buffer
[1]; FirstSlash
!= EndOfString
; ++FirstSlash
)
4278 if (*FirstSlash
== OBJ_NAME_PATH_SEPARATOR
)
4284 if (EndOfString
- FirstSlash
<= sizeof(WCHAR
))
4286 Status
= STATUS_OBJECT_NAME_INVALID
;
4291 DPRINT1("WARNING: Assuming not special + disk!\n");
4292 Type
= NET_ROOT_DISK
;
4293 Status
= STATUS_SUCCESS
;
4294 //Status = STATUS_NOT_IMPLEMENTED;
4295 /* Should be check against IPC, mailslot, and so on */
4299 /* Update net root type with our deduced one */
4300 *NetRootType
= Type
;
4301 DPRINT("Returning type: %x\n", Type
);
4303 if (!NT_SUCCESS(Status
))
4308 /* Do we have to prepend session ID? */
4313 PrependString
= TRUE
;
4314 CanonicalLength
+= SessionIdString
.Length
+ 3 * sizeof(WCHAR
);
4318 /* If not UNC path, we should preprend stuff */
4319 if (!PrependString
&& !IsSpecial
&& FileName
->Buffer
[0] != '\\')
4321 return STATUS_OBJECT_PATH_INVALID
;
4324 /* Allocate the buffer */
4325 Status
= RxAllocateCanonicalNameBuffer(RxContext
, CanonicalName
, CanonicalLength
);
4326 if (!NT_SUCCESS(Status
))
4331 /* We don't support that case, we always return disk */
4334 ASSERT(CanonicalName
->Length
== CanonicalLength
);
4336 Status
= STATUS_NOT_IMPLEMENTED
;
4340 /* If we have to prepend, go ahead */
4343 CanonicalName
->Buffer
[0] = '\\';
4344 CanonicalName
->Buffer
[1] = ';';
4345 CanonicalName
->Buffer
[2] = ':';
4346 CanonicalName
->Length
= 3 * sizeof(WCHAR
);
4347 RtlAppendUnicodeStringToString(CanonicalName
, &SessionIdString
);
4348 RtlAppendUnicodeStringToString(CanonicalName
, FileName
);
4350 DPRINT1("CanonicalName: %wZ\n", CanonicalName
);
4352 /* Otherwise, that's a simple copy */
4355 RtlCopyUnicodeString(CanonicalName
, FileName
);
4366 RxFreeCanonicalNameBuffer(
4367 PRX_CONTEXT Context
)
4369 /* These two buffers are always the same */
4370 ASSERT(Context
->Create
.CanonicalNameBuffer
== Context
->AlsoCanonicalNameBuffer
);
4372 if (Context
->Create
.CanonicalNameBuffer
!= NULL
)
4374 RxFreePoolWithTag(Context
->Create
.CanonicalNameBuffer
, RX_MISC_POOLTAG
);
4375 Context
->Create
.CanonicalNameBuffer
= NULL
;
4376 Context
->AlsoCanonicalNameBuffer
= NULL
;
4379 ASSERT(Context
->AlsoCanonicalNameBuffer
== NULL
);
4383 RxFsdCommonDispatch(
4384 PRX_FSD_DISPATCH_VECTOR DispatchVector
,
4385 UCHAR MajorFunction
,
4386 PIO_STACK_LOCATION Stack
,
4387 PFILE_OBJECT FileObject
,
4389 PRDBSS_DEVICE_OBJECT RxDeviceObject
)
4393 PRX_CONTEXT Context
;
4394 UCHAR MinorFunction
;
4395 PFILE_OBJECT StackFileObject
;
4396 PRX_FSD_DISPATCH DispatchFunc
;
4397 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4398 BOOLEAN TopLevel
, Closing
, PassToDriver
, SetCancelRoutine
, PostRequest
, CanWait
;
4400 Status
= STATUS_SUCCESS
;
4402 DPRINT("RxFsdCommonDispatch(%p, %d, %p, %p, %p, %p)\n", DispatchVector
, MajorFunction
, Stack
, FileObject
, Irp
, RxDeviceObject
);
4404 FsRtlEnterFileSystem();
4406 TopLevel
= RxTryToBecomeTheTopLevelIrp(&TopLevelContext
, Irp
, RxDeviceObject
, FALSE
);
4412 PostRequest
= FALSE
;
4413 SetCancelRoutine
= TRUE
;
4414 MinorFunction
= Stack
->MinorFunction
;
4416 switch (MajorFunction
)
4418 case IRP_MJ_FILE_SYSTEM_CONTROL
:
4419 if (FileObject
!= NULL
)
4421 CanWait
= IoIsOperationSynchronous(Irp
);
4431 case IRP_MJ_QUERY_INFORMATION
:
4432 case IRP_MJ_SET_INFORMATION
:
4433 case IRP_MJ_QUERY_EA
:
4435 case IRP_MJ_FLUSH_BUFFERS
:
4436 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
4437 case IRP_MJ_SET_VOLUME_INFORMATION
:
4438 case IRP_MJ_DIRECTORY_CONTROL
:
4439 case IRP_MJ_DEVICE_CONTROL
:
4440 case IRP_MJ_LOCK_CONTROL
:
4441 case IRP_MJ_QUERY_SECURITY
:
4442 case IRP_MJ_SET_SECURITY
:
4443 CanWait
= IoIsOperationSynchronous(Irp
);
4447 case IRP_MJ_CLEANUP
:
4449 SetCancelRoutine
= FALSE
;
4456 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
4457 /* Should we stop it right now, or mini-rdr deserves to know? */
4458 PassToDriver
= TRUE
;
4459 if (RxGetRdbssState(RxDeviceObject
) != RDBSS_STARTABLE
)
4461 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& !Closing
)
4463 PassToDriver
= FALSE
;
4464 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
4465 DPRINT1("Not started!\n");
4470 if (DispatchVector
!= RxDeviceFCBVector
&& (FileObject
->FileName
.Length
!= 0 || FileObject
->RelatedFileObject
!= NULL
))
4472 PassToDriver
= FALSE
;
4473 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
4474 DPRINT1("Not started!\n");
4477 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
4479 StackFileObject
= Stack
->FileObject
;
4480 /* Make sure we don't deal with orphaned stuff */
4481 if (StackFileObject
!= NULL
&& StackFileObject
->FsContext
!= NULL
)
4483 if (StackFileObject
->FsContext2
!= UIntToPtr(DFS_OPEN_CONTEXT
) &&
4484 StackFileObject
->FsContext2
!= UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
4485 StackFileObject
->FsContext
!= &RxDeviceFCB
)
4490 Fcb
= StackFileObject
->FsContext
;
4491 Fobx
= StackFileObject
->FsContext2
;
4493 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
) ||
4494 BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
4498 PassToDriver
= TRUE
;
4502 PassToDriver
= FALSE
;
4503 Status
= STATUS_UNEXPECTED_NETWORK_ERROR
;
4504 DPRINT1("Operation on orphaned FCB: %p\n", Fcb
);
4510 /* Did we receive a close request whereas we're stopping? */
4511 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& Closing
)
4515 Fcb
= StackFileObject
->FsContext
;
4517 DPRINT1("Close received after stop\n");
4518 DPRINT1("Irp: %p %d:%d FO: %p FCB: %p\n",
4519 Irp
, Stack
->MajorFunction
, Stack
->MinorFunction
, StackFileObject
, Fcb
);
4521 if (Fcb
!= NULL
&& Fcb
!= &RxDeviceFCB
&&
4524 DPRINT1("OpenCount: %ld, UncleanCount: %ld, Name: %wZ\n",
4525 Fcb
->OpenCount
, Fcb
->UncleanCount
, &Fcb
->FcbTableEntry
.Path
);
4529 /* Should we stop the whole thing now? */
4532 if (MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
|| MinorFunction
!= IRP_MN_REMOVE_DEVICE
)
4534 IoMarkIrpPending(Irp
);
4535 Irp
->IoStatus
.Status
= Status
;
4536 Irp
->IoStatus
.Information
= 0;
4537 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4538 Status
= STATUS_PENDING
;
4542 Irp
->IoStatus
.Status
= Status
;
4543 Irp
->IoStatus
.Information
= 0;
4544 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4550 /* No? Allocate a context to deal with the mini-rdr */
4551 Context
= RxCreateRxContext(Irp
, RxDeviceObject
, (CanWait
? RX_CONTEXT_FLAG_WAIT
: 0));
4552 if (Context
== NULL
)
4554 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4555 RxCompleteRequest_Real(RxNull
, Irp
, STATUS_INSUFFICIENT_RESOURCES
);
4559 /* Set cancel routine if required */
4560 if (SetCancelRoutine
)
4562 IoAcquireCancelSpinLock(&OldIrql
);
4563 IoSetCancelRoutine(Irp
, RxCancelRoutine
);
4567 IoAcquireCancelSpinLock(&OldIrql
);
4568 IoSetCancelRoutine(Irp
, NULL
);
4570 IoReleaseCancelSpinLock(OldIrql
);
4572 ASSERT(MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
4574 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
4575 Irp
->IoStatus
.Information
= 0;
4576 /* Get the dispatch routine */
4577 DispatchFunc
= DispatchVector
[MajorFunction
].CommonRoutine
;
4579 if (MajorFunction
== IRP_MJ_READ
|| MajorFunction
== IRP_MJ_WRITE
)
4581 /* Handle the complete MDL case */
4582 if (BooleanFlagOn(MinorFunction
, IRP_MN_COMPLETE
))
4584 DispatchFunc
= RxCompleteMdl
;
4588 /* Do we have to post request? */
4589 if (BooleanFlagOn(MinorFunction
, IRP_MN_DPC
))
4595 /* Our read function needs stack, make sure we won't overflow,
4596 * otherwise, post the request
4598 if (MajorFunction
== IRP_MJ_READ
)
4600 if (IoGetRemainingStackSize() < 0xE00)
4602 Context
->PendingReturned
= TRUE
;
4603 Status
= RxPostStackOverflowRead(Context
);
4604 if (Status
!= STATUS_PENDING
)
4606 Context
->PendingReturned
= FALSE
;
4607 RxCompleteAsynchronousRequest(Context
, Status
);
4617 Context
->ResumeRoutine
= DispatchFunc
;
4618 /* There's a dispatch routine? Time to dispatch! */
4619 if (DispatchFunc
!= NULL
)
4621 Context
->PendingReturned
= TRUE
;
4624 Status
= RxFsdPostRequest(Context
);
4628 /* Retry as long as we have */
4631 Status
= DispatchFunc(Context
);
4633 while (Status
== STATUS_RETRY
);
4635 if (Status
== STATUS_PENDING
)
4640 /* Sanity check: did someone mess with our context? */
4641 if (Context
->CurrentIrp
!= Irp
|| Context
->CurrentIrpSp
!= Stack
||
4642 Context
->MajorFunction
!= MajorFunction
|| Stack
->MinorFunction
!= MinorFunction
)
4644 DPRINT1("RX_CONTEXT %p has been contaminated!\n", Context
);
4645 DPRINT1("->CurrentIrp %p %p\n", Context
->CurrentIrp
, Irp
);
4646 DPRINT1("->CurrentIrpSp %p %p\n", Context
->CurrentIrpSp
, Stack
);
4647 DPRINT1("->MajorFunction %d %d\n", Context
->MajorFunction
, MajorFunction
);
4648 DPRINT1("->MinorFunction %d %d\n", Context
->MinorFunction
, MinorFunction
);
4650 Context
->PendingReturned
= FALSE
;
4651 Status
= RxCompleteAsynchronousRequest(Context
, Status
);
4656 Status
= STATUS_NOT_IMPLEMENTED
;
4663 RxUnwindTopLevelIrp(&TopLevelContext
);
4666 FsRtlExitFileSystem();
4670 DPRINT("RxFsdDispatch, Status: %lx\n", Status
);
4680 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
4684 PIO_STACK_LOCATION Stack
;
4685 PRX_FSD_DISPATCH_VECTOR DispatchVector
;
4689 DPRINT("RxFsdDispatch(%p, %p)\n", RxDeviceObject
, Irp
);
4691 Stack
= IoGetCurrentIrpStackLocation(Irp
);
4693 /* Dispatch easy case */
4694 if (Stack
->MajorFunction
== IRP_MJ_SYSTEM_CONTROL
)
4696 return RxSystemControl(RxDeviceObject
, Irp
);
4699 /* Bail out broken cases */
4700 if (Stack
->MajorFunction
== IRP_MJ_CREATE_MAILSLOT
||
4701 Stack
->MajorFunction
== IRP_MJ_CREATE_NAMED_PIPE
)
4703 IoMarkIrpPending(Irp
);
4704 Irp
->IoStatus
.Information
= 0;
4705 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_INVALID
;
4706 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4707 return STATUS_PENDING
;
4710 /* Immediately handle create */
4711 if (Stack
->MajorFunction
== IRP_MJ_CREATE
)
4713 return RxFsdCommonDispatch(&RxFsdDispatchVector
[0], Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
4716 /* If not a creation, we must have at least a FO with a FCB */
4717 if (Stack
->FileObject
== NULL
|| Stack
->FileObject
->FsContext
== NULL
)
4719 IoMarkIrpPending(Irp
);
4720 Irp
->IoStatus
.Information
= 0;
4721 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
4722 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4723 return STATUS_PENDING
;
4726 /* Set the dispatch vector if required */
4727 Fcb
= Stack
->FileObject
->FsContext
;
4728 if (!NodeTypeIsFcb(Fcb
) || Fcb
->PrivateDispatchVector
== NULL
)
4730 DispatchVector
= &RxFsdDispatchVector
[0];
4734 DispatchVector
= Fcb
->PrivateDispatchVector
;
4737 /* Device cannot accept such requests */
4738 if (RxDeviceObject
== RxFileSystemDeviceObject
)
4740 IoMarkIrpPending(Irp
);
4741 Irp
->IoStatus
.Information
= 0;
4742 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
4743 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4744 return STATUS_PENDING
;
4747 /* Dispatch for real! */
4748 return RxFsdCommonDispatch(DispatchVector
, Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
4756 IN PRX_CONTEXT RxContext
)
4758 /* Initialize posting if required */
4759 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
4761 RxPrePostIrp(RxContext
, RxContext
->CurrentIrp
);
4764 DPRINT("Posting MN: %d, Ctxt: %p, IRP: %p, Thrd: %lx #%lx\n",
4765 RxContext
->MinorFunction
, RxContext
,
4766 RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
4767 RxContext
->SerialNumber
);
4769 RxAddToWorkque(RxContext
, RxContext
->CurrentIrp
);
4770 return STATUS_PENDING
;
4782 WORK_QUEUE_TYPE Queue
;
4783 PRDBSS_DEVICE_OBJECT VolumeDO
;
4784 PRX_CONTEXT RxContext
, EntryContext
;
4788 RxContext
= Context
;
4789 EntryContext
= Context
;
4790 /* Save IRQL at entry for later checking */
4791 EntryIrql
= KeGetCurrentIrql();
4793 /* No FO, deal with device */
4794 if (RxContext
->CurrentIrpSp
->FileObject
!= NULL
)
4796 VolumeDO
= RxFileSystemDeviceObject
;
4803 /* Which queue to used for delayed? */
4804 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
))
4806 Queue
= DelayedWorkQueue
;
4810 ASSERT(BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
4811 Queue
= CriticalWorkQueue
;
4818 BOOLEAN RecursiveCall
;
4819 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4821 ASSERT(RxContext
->MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
4822 ASSERT(!RxContext
->PostRequest
);
4824 RxContext
->LastExecutionThread
= PsGetCurrentThread();
4825 SetFlag(RxContext
->Flags
, (RX_CONTEXT_FLAG_IN_FSP
| RX_CONTEXT_FLAG_WAIT
));
4827 DPRINT("Dispatch: MN: %d, Ctxt: %p, IRP: %p, THRD: %lx #%lx", RxContext
->MinorFunction
,
4828 RxContext
, RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
4829 RxContext
->SerialNumber
);
4831 Irp
= RxContext
->CurrentIrp
;
4833 FsRtlEnterFileSystem();
4835 RecursiveCall
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
);
4836 RxTryToBecomeTheTopLevelIrp(&TopLevelContext
,
4837 (RecursiveCall
? (PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
: RxContext
->CurrentIrp
),
4838 RxContext
->RxDeviceObject
, TRUE
);
4840 ASSERT(RxContext
->ResumeRoutine
!= NULL
);
4842 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_DPC
) && Irp
->Tail
.Overlay
.Thread
== NULL
)
4844 ASSERT((RxContext
->MajorFunction
== IRP_MJ_WRITE
) || (RxContext
->MajorFunction
== IRP_MJ_READ
));
4845 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4848 /* Call the resume routine */
4853 NoComplete
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_COMPLETE_FROM_FSP
);
4855 Status
= RxContext
->ResumeRoutine(RxContext
);
4856 if (!NoComplete
&& Status
!= STATUS_PENDING
)
4858 if (Status
!= STATUS_RETRY
)
4860 Status
= RxCompleteRequest(RxContext
, Status
);
4864 while (Status
== STATUS_RETRY
);
4866 RxUnwindTopLevelIrp(&TopLevelContext
);
4867 FsRtlExitFileSystem();
4869 if (VolumeDO
!= NULL
)
4871 RxContext
= RxRemoveOverflowEntry(VolumeDO
, Queue
);
4877 } while (RxContext
!= NULL
);
4879 /* Did we mess with IRQL? */
4880 if (KeGetCurrentIrql() >= APC_LEVEL
)
4882 DPRINT1("High IRQL for Ctxt %p, on entry: %x\n", EntryContext
, EntryIrql
);
4890 RxGetNetworkProviderPriority(
4891 PUNICODE_STRING DeviceName
)
4902 RxGetRegistryParameters(
4903 IN PUNICODE_STRING RegistryPath
)
4907 UCHAR Buffer
[0x400];
4908 HANDLE DriverHandle
, KeyHandle
;
4909 UNICODE_STRING KeyName
, OutString
;
4910 OBJECT_ATTRIBUTES ObjectAttributes
;
4914 InitializeObjectAttributes(&ObjectAttributes
, RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
4915 Status
= ZwOpenKey(&DriverHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4916 if (!NT_SUCCESS(Status
))
4921 RtlInitUnicodeString(&KeyName
, L
"Parameters");
4922 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, DriverHandle
, FALSE
);
4923 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4924 if (NT_SUCCESS(Status
))
4926 /* The only parameter we deal with is InitialDebugString */
4927 RxGetStringRegistryParameter(KeyHandle
, L
"InitialDebugString", &OutString
, Buffer
, sizeof(Buffer
), 0);
4928 if (OutString
.Length
!= 0 && OutString
.Length
< 0x140)
4933 Read
= OutString
.Buffer
;
4934 Write
= (PSTR
)OutString
.Buffer
;
4935 for (i
= 0; i
< OutString
.Length
; ++i
)
4943 /* Which is a string we'll just write out */
4944 DPRINT("InitialDebugString read from registry: '%s'\n", OutString
.Buffer
);
4945 RxDebugControlCommand((PSTR
)OutString
.Buffer
);
4951 ZwClose(DriverHandle
);
4959 IN PIO_STACK_LOCATION IrpSp
)
4962 PACCESS_TOKEN Token
;
4963 PIO_SECURITY_CONTEXT SecurityContext
;
4967 /* If that's not a prefix claim, not an open request, session id will be 0 */
4968 if (IrpSp
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
|| IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_REDIR_QUERY_PATH
)
4970 if (IrpSp
->MajorFunction
!= IRP_MJ_CREATE
|| IrpSp
->Parameters
.Create
.SecurityContext
== NULL
)
4975 SecurityContext
= IrpSp
->Parameters
.Create
.SecurityContext
;
4979 SecurityContext
= ((PQUERY_PATH_REQUEST
)IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
)->SecurityContext
;
4982 /* Query the session id */
4983 Token
= SeQuerySubjectContextToken(&SecurityContext
->AccessState
->SubjectSecurityContext
);
4984 SeQuerySessionIdToken(Token
, &SessionId
);
4994 RxGetStringRegistryParameter(
4995 IN HANDLE KeyHandle
,
4997 OUT PUNICODE_STRING OutString
,
4999 IN ULONG BufferLength
,
5000 IN BOOLEAN LogFailure
)
5004 UNICODE_STRING KeyString
;
5008 RtlInitUnicodeString(&KeyString
, KeyName
);
5009 Status
= ZwQueryValueKey(KeyHandle
, &KeyString
, KeyValuePartialInformation
, Buffer
, BufferLength
, &ResultLength
);
5010 OutString
->Length
= 0;
5011 OutString
->Buffer
= 0;
5012 if (!NT_SUCCESS(Status
))
5016 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BD3, Status
);
5022 OutString
->Buffer
= (PWSTR
)(((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->Data
);
5023 OutString
->Length
= ((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->DataLength
- sizeof(UNICODE_NULL
);
5024 OutString
->MaximumLength
= OutString
->Length
;
5026 return STATUS_SUCCESS
;
5032 PRDBSS_DEVICE_OBJECT
5033 RxGetTopDeviceObjectIfRdbssIrp(
5037 PRDBSS_DEVICE_OBJECT TopDevice
= NULL
;
5039 TopLevelIrp
= IoGetTopLevelIrp();
5040 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
5042 TopDevice
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->RxDeviceObject
;
5053 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
5056 PACCESS_TOKEN Token
;
5060 Token
= SeQuerySubjectContextToken(SubjectSecurityContext
);
5061 SeQueryAuthenticationIdToken(Token
, &Luid
);
5068 RxIndicateChangeOfBufferingStateForSrvOpen(
5069 PMRX_SRV_CALL SrvCall
,
5070 PMRX_SRV_OPEN SrvOpen
,
5079 RxInitializeDebugSupport(
5090 RxInitializeDispatchVectors(
5091 PDRIVER_OBJECT DriverObject
)
5097 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; ++i
)
5099 DriverObject
->MajorFunction
[i
] = (PDRIVER_DISPATCH
)RxFsdDispatch
;
5102 RxDeviceFCB
.PrivateDispatchVector
= RxDeviceFCBVector
;
5103 ASSERT(RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
5104 ASSERT(RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
5106 DriverObject
->FastIoDispatch
= &RxFastIoDispatch
;
5107 RxFastIoDispatch
.SizeOfFastIoDispatch
= sizeof(RxFastIoDispatch
);
5108 RxFastIoDispatch
.FastIoCheckIfPossible
= RxFastIoCheckIfPossible
;
5109 RxFastIoDispatch
.FastIoRead
= RxFastIoRead
;
5110 RxFastIoDispatch
.FastIoWrite
= RxFastIoWrite
;
5111 RxFastIoDispatch
.FastIoQueryBasicInfo
= NULL
;
5112 RxFastIoDispatch
.FastIoQueryStandardInfo
= NULL
;
5113 RxFastIoDispatch
.FastIoLock
= NULL
;
5114 RxFastIoDispatch
.FastIoUnlockSingle
= NULL
;
5115 RxFastIoDispatch
.FastIoUnlockAll
= NULL
;
5116 RxFastIoDispatch
.FastIoUnlockAllByKey
= NULL
;
5117 RxFastIoDispatch
.FastIoDeviceControl
= RxFastIoDeviceControl
;
5118 RxFastIoDispatch
.AcquireFileForNtCreateSection
= RxAcquireFileForNtCreateSection
;
5119 RxFastIoDispatch
.ReleaseFileForNtCreateSection
= RxReleaseFileForNtCreateSection
;
5120 RxFastIoDispatch
.AcquireForCcFlush
= RxAcquireForCcFlush
;
5121 RxFastIoDispatch
.ReleaseForCcFlush
= RxReleaseForCcFlush
;
5123 RxInitializeTopLevelIrpPackage();
5125 RxData
.CacheManagerCallbacks
.AcquireForLazyWrite
= RxAcquireFcbForLazyWrite
;
5126 RxData
.CacheManagerCallbacks
.ReleaseFromLazyWrite
= RxReleaseFcbFromLazyWrite
;
5127 RxData
.CacheManagerCallbacks
.AcquireForReadAhead
= RxAcquireFcbForReadAhead
;
5128 RxData
.CacheManagerCallbacks
.ReleaseFromReadAhead
= RxReleaseFcbFromReadAhead
;
5130 RxData
.CacheManagerNoOpCallbacks
.AcquireForLazyWrite
= RxNoOpAcquire
;
5131 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromLazyWrite
= RxNoOpRelease
;
5132 RxData
.CacheManagerNoOpCallbacks
.AcquireForReadAhead
= RxNoOpAcquire
;
5133 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromReadAhead
= RxNoOpRelease
;
5142 return STATUS_NOT_IMPLEMENTED
;
5149 RxInitializeMinirdrDispatchTable(
5150 IN PDRIVER_OBJECT DriverObject
)
5160 RxInitializeRegistrationStructures(
5165 ExInitializeFastMutex(&RxData
.MinirdrRegistrationMutex
);
5166 RxData
.NumberOfMinirdrsRegistered
= 0;
5167 RxData
.NumberOfMinirdrsStarted
= 0;
5168 InitializeListHead(&RxData
.RegisteredMiniRdrs
);
5170 return STATUS_SUCCESS
;
5178 RxInitializeTopLevelIrpPackage(
5181 KeInitializeSpinLock(&TopLevelIrpSpinLock
);
5182 InitializeListHead(&TopLevelIrpAllocatedContextsList
);
5188 PDRIVER_OBJECT DriverObject
,
5198 RxIsMemberOfTopLevelIrpAllocatedContextsList(
5199 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
5202 PLIST_ENTRY NextEntry
;
5203 BOOLEAN Found
= FALSE
;
5204 PRX_TOPLEVELIRP_CONTEXT ListContext
;
5206 /* Browse all the allocated TLC to find ours */
5207 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
5208 for (NextEntry
= TopLevelIrpAllocatedContextsList
.Flink
;
5209 NextEntry
!= &TopLevelIrpAllocatedContextsList
;
5210 NextEntry
= NextEntry
->Flink
)
5212 ListContext
= CONTAINING_RECORD(NextEntry
, RX_TOPLEVELIRP_CONTEXT
, ListEntry
);
5213 ASSERT(ListContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
5214 ASSERT(BooleanFlagOn(ListContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
5217 if (ListContext
== TopLevelContext
)
5223 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
5237 /* No associated SRV_OPEN, it's OK to purge */
5238 if (IsListEmpty(&Fcb
->SrvOpenList
))
5243 /* Only allow to purge if all the associated SRV_OPEN
5244 * - have no outstanding opens ongoing
5245 * - have only read attribute set
5247 for (Entry
= Fcb
->SrvOpenList
.Flink
;
5248 Entry
!= &Fcb
->SrvOpenList
;
5249 Entry
= Entry
->Flink
)
5253 SrvOpen
= CONTAINING_RECORD(Entry
, SRV_OPEN
, SrvOpenQLinks
);
5255 /* Failing previous needs, don't allow purge */
5256 if (SrvOpen
->UncleanFobxCount
!= 0 ||
5257 (SrvOpen
->DesiredAccess
& 0xFFEFFFFF) != FILE_READ_ATTRIBUTES
)
5263 /* All correct, allow purge */
5271 RxIsThisAnRdbssTopLevelContext(
5272 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
5274 ULONG_PTR StackTop
, StackBottom
;
5276 /* Bail out for flags */
5277 if ((ULONG_PTR
)TopLevelContext
<= FSRTL_FAST_IO_TOP_LEVEL_IRP
)
5282 /* Is our provided TLC allocated on stack? */
5283 IoGetStackLimits(&StackTop
, &StackBottom
);
5284 if ((ULONG_PTR
)TopLevelContext
<= StackBottom
- sizeof(RX_TOPLEVELIRP_CONTEXT
) &&
5285 (ULONG_PTR
)TopLevelContext
>= StackTop
)
5287 /* Yes, so check whether it's really a TLC by checking alignement & signature */
5288 if (!BooleanFlagOn((ULONG_PTR
)TopLevelContext
, 0x3) && TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
)
5296 /* No, use the helper function */
5297 return RxIsMemberOfTopLevelIrpAllocatedContextsList(TopLevelContext
);
5304 RxIsThisTheTopLevelIrp(
5309 /* When we put oursleves as top level, we set TLC as 'IRP', so look for it */
5310 TopLevelIrp
= IoGetTopLevelIrp();
5311 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
5313 TopLevelIrp
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->Irp
;
5316 return (TopLevelIrp
== Irp
);
5321 RxLockOperationCompletion(
5326 return STATUS_NOT_IMPLEMENTED
;
5335 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
5336 IN PUNICODE_STRING OriginatorId
,
5341 PUNICODE_STRING Originator
= OriginatorId
;
5342 LARGE_INTEGER LargeLine
;
5344 /* Set optional parameters */
5345 LargeLine
.QuadPart
= Line
;
5346 if (OriginatorId
== NULL
|| OriginatorId
->Length
== 0)
5348 Originator
= (PUNICODE_STRING
)&unknownId
;
5352 RxLogEventWithAnnotation(DeviceObject
, EventId
, Status
, &LargeLine
, sizeof(LargeLine
), Originator
, 1);
5357 RxLogEventWithAnnotation(
5358 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
5361 IN PVOID DataBuffer
,
5362 IN USHORT DataBufferLength
,
5363 IN PUNICODE_STRING Annotation
,
5364 IN ULONG AnnotationCount
)
5372 PRX_CONTEXT RxContext
)
5375 return STATUS_NOT_IMPLEMENTED
;
5383 RxLowIoIoCtlShellCompletion(
5384 PRX_CONTEXT RxContext
)
5391 DPRINT("RxLowIoIoCtlShellCompletion(%p)\n", RxContext
);
5393 Irp
= RxContext
->CurrentIrp
;
5394 Status
= RxContext
->IoStatusBlock
.Status
;
5396 /* Set information and status */
5397 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
)
5399 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
5402 Irp
->IoStatus
.Status
= Status
;
5408 RxLowIoLockControlShell(
5409 IN PRX_CONTEXT RxContext
)
5412 return STATUS_NOT_IMPLEMENTED
;
5420 RxLowIoNotifyChangeDirectoryCompletion(
5421 PRX_CONTEXT RxContext
)
5425 DPRINT("Completing NCD with: %lx, %lx\n", RxContext
->IoStatusBlock
.Status
, RxContext
->IoStatusBlock
.Information
);
5427 /* Just copy back the IO_STATUS to the IRP */
5428 RxSetIoStatusStatus(RxContext
, RxContext
->IoStatusBlock
.Status
);
5429 RxSetIoStatusInfo(RxContext
, RxContext
->IoStatusBlock
.Information
);
5431 return RxContext
->IoStatusBlock
.Status
;
5439 PRX_CONTEXT RxContext
)
5446 DPRINT("RxLowIoReadShell(%p)\n", RxContext
);
5448 Fcb
= (PFCB
)RxContext
->pFcb
;
5449 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
5451 return STATUS_MORE_PROCESSING_REQUIRED
;
5454 /* Always update stats for disks */
5455 if (Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
5457 ExInterlockedAddLargeStatistic(&RxContext
->RxDeviceObject
->NetworkReadBytesRequested
, RxContext
->LowIoContext
.ParamsFor
.ReadWrite
.ByteCount
);
5460 /* And forward the read to the mini-rdr */
5461 Status
= RxLowIoSubmit(RxContext
, RxLowIoReadShellCompletion
);
5462 DPRINT("RxLowIoReadShell(%p), Status: %lx\n", RxContext
, Status
);
5469 RxLowIoReadShellCompletion(
5470 PRX_CONTEXT RxContext
)
5475 BOOLEAN PagingIo
, IsPipe
;
5476 PIO_STACK_LOCATION Stack
;
5477 PLOWIO_CONTEXT LowIoContext
;
5481 DPRINT("RxLowIoReadShellCompletion(%p)\n", RxContext
);
5483 Status
= RxContext
->IoStatusBlock
.Status
;
5484 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext
, Status
, RxContext
->IoStatusBlock
.Information
);
5486 Irp
= RxContext
->CurrentIrp
;
5487 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
5489 /* Set IRP information from the RX_CONTEXT status block */
5490 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
5492 /* Fixup status for paging file if nothing was read */
5495 if (NT_SUCCESS(Status
) && RxContext
->IoStatusBlock
.Information
== 0)
5497 Status
= STATUS_END_OF_FILE
;
5501 LowIoContext
= &RxContext
->LowIoContext
;
5502 ASSERT(RxLowIoIsBufferLocked(LowIoContext
));
5504 /* Check broken cases that should never happen */
5505 Fcb
= (PFCB
)RxContext
->pFcb
;
5506 if (Status
== STATUS_FILE_LOCK_CONFLICT
)
5508 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_THIS_READ_ENLARGED
))
5511 return STATUS_RETRY
;
5514 else if (Status
== STATUS_SUCCESS
)
5516 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
))
5518 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
) ||
5519 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
))
5525 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
5531 /* Readahead should go through Cc and not finish here */
5532 ASSERT(!BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_READAHEAD
));
5534 /* If it's sync, RxCommonRead will finish the work - nothing to do here */
5535 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_SYNCCALL
))
5540 Stack
= RxContext
->CurrentIrpSp
;
5541 IsPipe
= BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
);
5542 /* Release lock if required */
5545 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
5549 /* Set FastIo if read was a success */
5550 if (NT_SUCCESS(Status
) && !IsPipe
)
5552 SetFlag(Stack
->FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
5555 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
5557 RxResumeBlockedOperations_Serially(RxContext
, &((PFOBX
)RxContext
->pFobx
)->Specific
.NamedPipe
.ReadSerializationQueue
);
5561 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
5570 /* Final sanity checks */
5571 ASSERT(Status
!= STATUS_RETRY
);
5572 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
5573 ASSERT(RxContext
->MajorFunction
== IRP_MJ_READ
);
5582 RxNotifyChangeDirectory(
5583 PRX_CONTEXT RxContext
)
5587 PIO_STACK_LOCATION Stack
;
5591 /* The IRP can abviously wait */
5592 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
5594 /* Initialize its lowio */
5595 RxInitializeLowIoContext(&RxContext
->LowIoContext
, LOWIO_OP_NOTIFY_CHANGE_DIRECTORY
);
5599 /* Lock user buffer */
5600 Stack
= RxContext
->CurrentIrpSp
;
5601 RxLockUserBuffer(RxContext
, IoWriteAccess
, Stack
->Parameters
.NotifyDirectory
.Length
);
5603 /* Copy parameters from IO_STACK */
5604 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.WatchTree
= BooleanFlagOn(Stack
->Flags
, SL_WATCH_TREE
);
5605 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.CompletionFilter
= Stack
->Parameters
.NotifyDirectory
.CompletionFilter
;
5606 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.NotificationBufferLength
= Stack
->Parameters
.NotifyDirectory
.Length
;
5608 /* If we have an associated MDL */
5609 Irp
= RxContext
->CurrentIrp
;
5610 if (Irp
->MdlAddress
!= NULL
)
5612 /* Then, call mini-rdr */
5613 RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.pNotificationBuffer
= MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
5614 if (RxContext
->LowIoContext
.ParamsFor
.NotifyChangeDirectory
.pNotificationBuffer
!= NULL
)
5616 Status
= RxLowIoSubmit(RxContext
, RxLowIoNotifyChangeDirectoryCompletion
);
5620 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5625 Status
= STATUS_INVALID_PARAMETER
;
5638 RxPostStackOverflowRead (
5639 IN PRX_CONTEXT RxContext
)
5644 return STATUS_NOT_IMPLEMENTED
;
5651 RxpPrepareCreateContextForReuse(
5652 PRX_CONTEXT RxContext
)
5654 /* Reuse can only happen for open operations (STATUS_RETRY) */
5655 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
5657 /* Release the FCB if it was acquired */
5658 if (RxContext
->Create
.FcbAcquired
)
5660 RxReleaseFcb(RxContext
, RxContext
->pFcb
);
5661 RxContext
->Create
.FcbAcquired
= FALSE
;
5664 /* Free the canonical name */
5665 RxFreeCanonicalNameBuffer(RxContext
);
5667 /* If we have a VNetRoot associated */
5668 if (RxContext
->Create
.pVNetRoot
!= NULL
|| RxContext
->Create
.NetNamePrefixEntry
!= NULL
)
5670 /* Remove our link and thus, dereference the VNetRoot */
5671 RxpAcquirePrefixTableLockShared(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
, TRUE
);
5672 if (RxContext
->Create
.pVNetRoot
!= NULL
)
5674 RxDereferenceVNetRoot(RxContext
->Create
.pVNetRoot
, TRUE
);
5675 RxContext
->Create
.pVNetRoot
= NULL
;
5677 RxpReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
5680 DPRINT("RxContext: %p prepared for reuse\n", RxContext
);
5687 RxpQueryInfoMiniRdr(
5688 PRX_CONTEXT RxContext
,
5689 FILE_INFORMATION_CLASS FileInfoClass
,
5695 Fcb
= (PFCB
)RxContext
->pFcb
;
5697 /* Set the RX_CONTEXT */
5698 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
5699 RxContext
->Info
.Buffer
= Buffer
;
5702 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryFileInfo
, (RxContext
));
5712 IN PRX_CONTEXT RxContext
)
5716 NET_ROOT_TYPE NetRootType
;
5717 UNICODE_STRING CanonicalName
, FileName
, NetRootName
;
5721 Irp
= RxContext
->CurrentIrp
;
5723 /* This has to come from MUP */
5724 if (Irp
->RequestorMode
== UserMode
)
5726 return STATUS_INVALID_DEVICE_REQUEST
;
5729 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
5731 PQUERY_PATH_REQUEST QueryRequest
;
5733 /* Get parameters */
5734 QueryRequest
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
5736 /* Don't overflow allocation */
5737 if (QueryRequest
->PathNameLength
>= MAXUSHORT
- 1)
5739 return STATUS_INVALID_DEVICE_REQUEST
;
5742 /* Forcefully rewrite IRP MJ */
5743 RxContext
->MajorFunction
= IRP_MJ_CREATE
;
5745 /* Fake canon name */
5746 RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
= RxAllocatePoolWithTag(NonPagedPool
, QueryRequest
->PathNameLength
, RX_MISC_POOLTAG
);
5747 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
== NULL
)
5749 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5753 /* Copy the prefix to look for */
5754 RtlCopyMemory(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, &QueryRequest
->FilePathName
[0], QueryRequest
->PathNameLength
);
5755 RxContext
->PrefixClaim
.SuppliedPathName
.Length
= QueryRequest
->PathNameLength
;
5756 RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
= QueryRequest
->PathNameLength
;
5758 /* Zero the create parameters */
5759 RtlZeroMemory(&RxContext
->Create
.NtCreateParameters
,
5760 FIELD_OFFSET(RX_CONTEXT
, AlsoCanonicalNameBuffer
) - FIELD_OFFSET(RX_CONTEXT
, Create
.NtCreateParameters
));
5761 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
5762 RxContext
->Create
.NtCreateParameters
.SecurityContext
= QueryRequest
->SecurityContext
;
5766 /* If not devcontrol, it comes from open, name was already copied */
5767 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
5768 ASSERT(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
);
5771 /* Canonilize name */
5772 NetRootType
= NET_ROOT_WILD
;
5773 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
5774 FileName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
5775 FileName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
5776 FileName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
5777 NetRootName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
5778 NetRootName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
5779 NetRootName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
5780 Status
= RxFirstCanonicalize(RxContext
, &FileName
, &CanonicalName
, &NetRootType
);
5781 /* It went fine, attempt to establish a connection (that way we know whether the prefix is accepted) */
5782 if (NT_SUCCESS(Status
))
5784 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &NetRootName
);
5786 if (Status
== STATUS_PENDING
)
5791 if (NT_SUCCESS(Status
))
5793 PQUERY_PATH_RESPONSE QueryResponse
;
5795 /* We accept the length that was canon (minus netroot) */
5796 QueryResponse
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
5797 QueryResponse
->LengthAccepted
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
- NetRootName
.Length
;
5801 /* If we reach that point with MJ, reset everything and make IRP being a device control */
5802 if (RxContext
->MajorFunction
== IRP_MJ_CREATE
)
5804 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
)
5806 RxFreePoolWithTag(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, RX_MISC_POOLTAG
);
5809 RxpPrepareCreateContextForReuse(RxContext
);
5811 RxContext
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
5819 RxPrepareToReparseSymbolicLink(
5820 PRX_CONTEXT RxContext
,
5821 BOOLEAN SymbolicLinkEmbeddedInOldPath
,
5822 PUNICODE_STRING NewPath
,
5823 BOOLEAN NewPathIsAbsolute
,
5824 PBOOLEAN ReparseRequired
)
5827 return STATUS_NOT_IMPLEMENTED
;
5838 LOCK_OPERATION Lock
;
5839 PIO_STACK_LOCATION Stack
;
5840 PRX_CONTEXT RxContext
= Context
;
5842 /* NULL IRP is no option */
5848 /* Check whether preparation was really needed */
5849 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
5853 /* Mark the context as prepared */
5854 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
);
5856 /* Just lock the user buffer, with the correct length, depending on the MJ */
5857 Lock
= IoReadAccess
;
5858 Stack
= RxContext
->CurrentIrpSp
;
5859 if (RxContext
->MajorFunction
== IRP_MJ_READ
|| RxContext
->MajorFunction
== IRP_MJ_WRITE
)
5861 if (!BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
5863 if (RxContext
->MajorFunction
== IRP_MJ_READ
)
5865 Lock
= IoWriteAccess
;
5867 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.Read
.Length
);
5872 if ((RxContext
->MajorFunction
== IRP_MJ_DIRECTORY_CONTROL
&& RxContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) ||
5873 RxContext
->MajorFunction
== IRP_MJ_QUERY_EA
)
5875 Lock
= IoWriteAccess
;
5876 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.QueryDirectory
.Length
);
5878 else if (RxContext
->MajorFunction
== IRP_MJ_SET_EA
)
5880 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.SetEa
.Length
);
5884 /* As it will be posted (async), mark the IRP pending */
5885 IoMarkIrpPending(Irp
);
5890 RxpUnregisterMinirdr(
5891 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
)
5902 PRX_CONTEXT LocalContext
)
5909 MmFlushImageSection(&Fcb
->NonPaged
->SectionObjectPointers
, MmFlushForWrite
);
5911 /* And force close */
5912 RxReleaseFcb(NULL
, Fcb
);
5913 MmForceSectionClosed(&Fcb
->NonPaged
->SectionObjectPointers
, TRUE
);
5914 Status
= RxAcquireExclusiveFcb(NULL
, Fcb
);
5915 ASSERT(Status
== STATUS_SUCCESS
);
5919 RxQueryAlternateNameInfo(
5920 PRX_CONTEXT RxContext
,
5921 PFILE_NAME_INFORMATION AltNameInfo
)
5924 return STATUS_NOT_IMPLEMENTED
;
5932 PRX_CONTEXT RxContext
,
5933 PFILE_BASIC_INFORMATION BasicInfo
)
5937 DPRINT("RxQueryBasicInfo(%p, %p)\n", RxContext
, BasicInfo
);
5939 /* Simply zero and forward to mini-rdr */
5940 RtlZeroMemory(BasicInfo
, sizeof(FILE_BASIC_INFORMATION
));
5941 return RxpQueryInfoMiniRdr(RxContext
, FileBasicInformation
, BasicInfo
);
5945 RxQueryCompressedInfo(
5946 PRX_CONTEXT RxContext
,
5947 PFILE_COMPRESSION_INFORMATION CompressionInfo
)
5950 return STATUS_NOT_IMPLEMENTED
;
5958 PRX_CONTEXT RxContext
)
5965 BOOLEAN LockNotGranted
;
5966 ULONG Length
, FileIndex
;
5967 PUNICODE_STRING FileName
;
5968 PIO_STACK_LOCATION Stack
;
5969 FILE_INFORMATION_CLASS FileInfoClass
;
5973 DPRINT("RxQueryDirectory(%p)\n", RxContext
);
5975 /* Get parameters */
5976 Stack
= RxContext
->CurrentIrpSp
;
5977 Length
= Stack
->Parameters
.QueryDirectory
.Length
;
5978 FileName
= Stack
->Parameters
.QueryDirectory
.FileName
;
5979 FileInfoClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
5980 DPRINT("Wait: %d, Length: %ld, FileName: %p, Class: %d\n",
5981 FlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
), Length
,
5982 FileName
, FileInfoClass
);
5984 Irp
= RxContext
->CurrentIrp
;
5985 Flags
= Stack
->Flags
;
5986 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
5987 DPRINT("Index: %d, Buffer: %p, Flags: %x\n", FileIndex
, Irp
->UserBuffer
, Flags
);
5989 if (FileName
!= NULL
)
5991 DPRINT("FileName: %wZ\n", FileName
);
5994 /* No FOBX: not a standard file/directory */
5995 Fobx
= (PFOBX
)RxContext
->pFobx
;
5998 return STATUS_OBJECT_NAME_INVALID
;
6001 /* We can only deal with a disk */
6002 Fcb
= (PFCB
)RxContext
->pFcb
;
6003 if (Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
6005 DPRINT1("Not a disk! %x\n", Fcb
->pNetRoot
->Type
);
6006 return STATUS_INVALID_DEVICE_REQUEST
;
6009 /* Setup RX_CONTEXT related fields */
6010 RxContext
->QueryDirectory
.FileIndex
= FileIndex
;
6011 RxContext
->QueryDirectory
.RestartScan
= BooleanFlagOn(Flags
, SL_RESTART_SCAN
);
6012 RxContext
->QueryDirectory
.ReturnSingleEntry
= BooleanFlagOn(Flags
, SL_RETURN_SINGLE_ENTRY
);
6013 RxContext
->QueryDirectory
.IndexSpecified
= BooleanFlagOn(Flags
, SL_INDEX_SPECIFIED
);
6014 RxContext
->QueryDirectory
.InitialQuery
= (Fobx
->UnicodeQueryTemplate
.Buffer
== NULL
) && !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
6016 /* We don't support (yet?) a specific index being set */
6017 if (RxContext
->QueryDirectory
.IndexSpecified
)
6019 return STATUS_NOT_IMPLEMENTED
;
6022 /* Try to lock FCB */
6023 LockNotGranted
= TRUE
;
6024 if (RxContext
->QueryDirectory
.InitialQuery
)
6026 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
6027 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
6029 if (!NT_SUCCESS(Status
))
6034 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
6036 RxContext
->QueryDirectory
.InitialQuery
= FALSE
;
6037 RxConvertToSharedFcb(RxContext
, Fcb
);
6040 LockNotGranted
= FALSE
;
6045 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
6046 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
6048 if (!NT_SUCCESS(Status
))
6053 LockNotGranted
= FALSE
;
6057 /* If it failed, post request */
6060 return RxFsdPostRequest(RxContext
);
6063 /* This cannot be done on a orphaned directory */
6064 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
6066 RxReleaseFcb(RxContext
, Fcb
);
6067 return STATUS_FILE_CLOSED
;
6073 if (!RxContext
->QueryDirectory
.IndexSpecified
&& RxContext
->QueryDirectory
.RestartScan
)
6075 RxContext
->QueryDirectory
.FileIndex
= 0;
6078 /* Assume success */
6079 Status
= STATUS_SUCCESS
;
6080 /* If initial query, prepare FOBX */
6081 if (RxContext
->QueryDirectory
.InitialQuery
)
6083 /* We cannot have a template already! */
6084 ASSERT(!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
));
6086 /* If we have a file name and a correct one, duplicate it in the FOBX */
6087 if (FileName
!= NULL
&& FileName
->Length
!= 0 && FileName
->Buffer
!= NULL
&&
6088 (FileName
->Length
!= sizeof(WCHAR
) || FileName
->Buffer
[0] != '*') &&
6089 (FileName
->Length
!= 12 * sizeof(WCHAR
) ||
6090 RtlCompareMemory(FileName
->Buffer
, Rx8QMdot3QM
, 12 * sizeof(WCHAR
)) != 12 * sizeof(WCHAR
)))
6092 Fobx
->ContainsWildCards
= FsRtlDoesNameContainWildCards(FileName
);
6094 Fobx
->UnicodeQueryTemplate
.Buffer
= RxAllocatePoolWithTag(PagedPool
, FileName
->Length
, RX_DIRCTL_POOLTAG
);
6095 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
6097 /* UNICODE_STRING; length has to be even */
6098 if ((FileName
->Length
& 1) != 0)
6100 Status
= STATUS_INVALID_PARAMETER
;
6101 RxFreePoolWithTag(Fobx
->UnicodeQueryTemplate
.Buffer
, RX_DIRCTL_POOLTAG
);
6105 Fobx
->UnicodeQueryTemplate
.Length
= FileName
->Length
;
6106 Fobx
->UnicodeQueryTemplate
.MaximumLength
= FileName
->Length
;
6107 RtlMoveMemory(Fobx
->UnicodeQueryTemplate
.Buffer
, FileName
->Buffer
, FileName
->Length
);
6109 SetFlag(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
);
6114 Status
= STATUS_INSUFFICIENT_RESOURCES
;
6117 /* No name specified, or a match all wildcard? Match everything */
6120 Fobx
->ContainsWildCards
= TRUE
;
6122 Fobx
->UnicodeQueryTemplate
.Buffer
= &RxStarForTemplate
;
6123 Fobx
->UnicodeQueryTemplate
.Length
= sizeof(WCHAR
);
6124 Fobx
->UnicodeQueryTemplate
.MaximumLength
= sizeof(WCHAR
);
6126 SetFlag(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
6129 /* No need for exclusive any longer */
6130 if (NT_SUCCESS(Status
))
6132 RxConvertToSharedFcb(RxContext
, Fcb
);
6136 /* Lock user buffer and forward to mini-rdr */
6137 if (NT_SUCCESS(Status
))
6139 RxLockUserBuffer(RxContext
, IoModifyAccess
, Length
);
6140 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
6141 RxContext
->Info
.Buffer
= RxNewMapUserBuffer(RxContext
);
6142 RxContext
->Info
.Length
= Length
;
6144 if (RxContext
->Info
.Buffer
!= NULL
)
6146 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryDirectory
, (RxContext
));
6149 /* Post if mini-rdr asks to */
6150 if (RxContext
->PostRequest
)
6152 RxFsdPostRequest(RxContext
);
6156 Irp
->IoStatus
.Information
= Length
- RxContext
->Info
.LengthRemaining
;
6162 RxReleaseFcb(RxContext
, Fcb
);
6171 PRX_CONTEXT RxContext
,
6172 PFILE_EA_INFORMATION EaInfo
)
6175 return STATUS_NOT_IMPLEMENTED
;
6179 RxQueryInternalInfo(
6180 PRX_CONTEXT RxContext
,
6181 PFILE_INTERNAL_INFORMATION InternalInfo
)
6184 return STATUS_NOT_IMPLEMENTED
;
6189 PRX_CONTEXT RxContext
,
6190 PFILE_NAME_INFORMATION NameInfo
)
6193 return STATUS_NOT_IMPLEMENTED
;
6198 PRX_CONTEXT RxContext
,
6199 PFILE_PIPE_INFORMATION PipeInfo
)
6202 return STATUS_NOT_IMPLEMENTED
;
6206 RxQueryPositionInfo(
6207 PRX_CONTEXT RxContext
,
6208 PFILE_POSITION_INFORMATION PositionInfo
)
6211 return STATUS_NOT_IMPLEMENTED
;
6218 RxQueryStandardInfo(
6219 PRX_CONTEXT RxContext
,
6220 PFILE_STANDARD_INFORMATION StandardInfo
)
6228 DPRINT("RxQueryStandardInfo(%p, %p)\n", RxContext
, StandardInfo
);
6230 /* Zero output buffer */
6231 RtlZeroMemory(StandardInfo
, sizeof(FILE_STANDARD_INFORMATION
));
6233 Fcb
= (PFCB
)RxContext
->pFcb
;
6234 Fobx
= (PFOBX
)RxContext
->pFobx
;
6235 /* If not a standard file type, or opened for backup, immediately forward to mini-rdr */
6236 if ((NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&& NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
) ||
6237 BooleanFlagOn(Fobx
->pSrvOpen
->CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
6239 return RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
6242 /* Otherwise, fill what we can already */
6243 Status
= STATUS_SUCCESS
;
6244 StandardInfo
->NumberOfLinks
= Fcb
->NumberOfLinks
;
6245 StandardInfo
->DeletePending
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
6246 StandardInfo
->Directory
= (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY
);
6247 if (StandardInfo
->NumberOfLinks
== 0)
6249 StandardInfo
->NumberOfLinks
= 1;
6252 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
6254 StandardInfo
->AllocationSize
.QuadPart
= Fcb
->Header
.AllocationSize
.QuadPart
;
6255 RxGetFileSizeWithLock(Fcb
, &StandardInfo
->EndOfFile
.QuadPart
);
6258 /* If we are asked to forcefully forward to mini-rdr or if size isn't cached, do it */
6259 if (RxForceQFIPassThrough
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILESIZECACHEING_ENABLED
))
6261 Status
= RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
6265 RxContext
->IoStatusBlock
.Information
-= sizeof(FILE_STANDARD_INFORMATION
);
6276 RxReadRegistryParameters(
6283 UNICODE_STRING KeyName
, ParamName
;
6284 OBJECT_ATTRIBUTES ObjectAttributes
;
6285 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
6289 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters");
6290 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
6291 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
6292 if (!NT_SUCCESS(Status
))
6297 PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
;
6298 RtlInitUnicodeString(&ParamName
, L
"DisableByteRangeLockingOnReadOnlyFiles");
6299 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6300 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6302 DisableByteRangeLockingOnReadOnlyFiles
= (*(PULONG
)PartialInfo
->Data
!= 0);
6305 RtlInitUnicodeString(&ParamName
, L
"ReadAheadGranularity");
6306 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6307 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6309 ULONG Granularity
= *(PULONG
)PartialInfo
->Data
;
6311 if (Granularity
> 16)
6316 ReadAheadGranularity
= Granularity
<< PAGE_SHIFT
;
6319 RtlInitUnicodeString(&ParamName
, L
"DisableFlushOnCleanup");
6320 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6321 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6323 DisableFlushOnCleanup
= (*(PULONG
)PartialInfo
->Data
!= 0);
6335 OUT PRDBSS_DEVICE_OBJECT
*DeviceObject
,
6336 IN OUT PDRIVER_OBJECT DriverObject
,
6337 IN PMINIRDR_DISPATCH MrdrDispatch
,
6339 IN PUNICODE_STRING DeviceName
,
6340 IN ULONG DeviceExtensionSize
,
6341 IN DEVICE_TYPE DeviceType
,
6342 IN ULONG DeviceCharacteristics
)
6345 PRDBSS_DEVICE_OBJECT RDBSSDevice
;
6351 return STATUS_INVALID_PARAMETER
;
6354 /* Create device object with provided parameters */
6355 Status
= IoCreateDevice(DriverObject
,
6356 DeviceExtensionSize
+ sizeof(RDBSS_DEVICE_OBJECT
),
6359 DeviceCharacteristics
,
6361 (PDEVICE_OBJECT
*)&RDBSSDevice
);
6362 if (!NT_SUCCESS(Status
))
6367 if (!RxData
.DriverObject
)
6369 return STATUS_UNSUCCESSFUL
;
6372 /* Initialize our DO extension */
6373 RDBSSDevice
->RDBSSDeviceObject
= NULL
;
6374 ++RxFileSystemDeviceObject
->ReferenceCount
;
6375 *DeviceObject
= RDBSSDevice
;
6376 RDBSSDevice
->RdbssExports
= &RxExports
;
6377 RDBSSDevice
->Dispatch
= MrdrDispatch
;
6378 RDBSSDevice
->RegistrationControls
= Controls
;
6379 RDBSSDevice
->DeviceName
= *DeviceName
;
6380 RDBSSDevice
->RegisterUncProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS
);
6381 RDBSSDevice
->RegisterMailSlotProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS
);
6382 InitializeListHead(&RDBSSDevice
->OverflowQueue
[0]);
6383 InitializeListHead(&RDBSSDevice
->OverflowQueue
[1]);
6384 InitializeListHead(&RDBSSDevice
->OverflowQueue
[2]);
6385 KeInitializeSpinLock(&RDBSSDevice
->OverflowQueueSpinLock
);
6386 RDBSSDevice
->NetworkProviderPriority
= RxGetNetworkProviderPriority(DeviceName
);
6388 DPRINT("Registered MiniRdr %wZ (prio: %x)\n", DeviceName
, RDBSSDevice
->NetworkProviderPriority
);
6390 ExAcquireFastMutex(&RxData
.MinirdrRegistrationMutex
);
6391 InsertTailList(&RxData
.RegisteredMiniRdrs
, &RDBSSDevice
->MiniRdrListLinks
);
6392 ExReleaseFastMutex(&RxData
.MinirdrRegistrationMutex
);
6394 /* Unless mini-rdr explicitly asked not to, initialize dispatch table */
6395 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH
))
6397 RxInitializeMinirdrDispatchTable(DriverObject
);
6400 /* Unless mini-rdr explicitly asked not to, initialize prefix scavenger */
6401 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER
))
6403 LARGE_INTEGER ScavengerTimeLimit
;
6405 RDBSSDevice
->pRxNetNameTable
= &RDBSSDevice
->RxNetNameTableInDeviceObject
;
6406 RxInitializePrefixTable(RDBSSDevice
->pRxNetNameTable
, 0, FALSE
);
6407 RDBSSDevice
->RxNetNameTableInDeviceObject
.IsNetNameTable
= TRUE
;
6408 ScavengerTimeLimit
.QuadPart
= MrdrDispatch
->ScavengerTimeout
* 10000000LL;
6409 RDBSSDevice
->pRdbssScavenger
= &RDBSSDevice
->RdbssScavengerInDeviceObject
;
6410 RxInitializeRdbssScavenger(RDBSSDevice
->pRdbssScavenger
, ScavengerTimeLimit
);
6413 RDBSSDevice
->pAsynchronousRequestsCompletionEvent
= NULL
;
6415 return STATUS_SUCCESS
;
6420 RxReleaseFcbFromLazyWrite(
6428 RxReleaseFcbFromReadAhead(
6436 RxReleaseFileForNtCreateSection(
6437 PFILE_OBJECT FileObject
)
6444 RxReleaseForCcFlush(
6445 PFILE_OBJECT FileObject
,
6446 PDEVICE_OBJECT DeviceObject
)
6449 return STATUS_NOT_IMPLEMENTED
;
6456 RxRemoveFromTopLevelIrpAllocatedContextsList(
6457 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6461 /* Make sure this is a TLC and that it was allocated (otherwise, it is not in the list */
6462 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6463 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6465 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
6466 RemoveEntryList(&TopLevelContext
->ListEntry
);
6467 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
6474 RxRemoveOverflowEntry(
6475 PRDBSS_DEVICE_OBJECT DeviceObject
,
6476 WORK_QUEUE_TYPE Queue
)
6479 PRX_CONTEXT Context
;
6481 KeAcquireSpinLock(&DeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
6482 if (DeviceObject
->OverflowQueueCount
[Queue
] <= 0)
6484 /* No entries left, nothing to return */
6485 InterlockedDecrement(&DeviceObject
->PostedRequestCount
[Queue
]);
6492 /* Decrement count */
6493 --DeviceObject
->OverflowQueueCount
[Queue
];
6496 Entry
= RemoveHeadList(&DeviceObject
->OverflowQueue
[Queue
]);
6497 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, OverflowListEntry
);
6498 ClearFlag(Context
->Flags
, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
| RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
6499 Context
->OverflowListEntry
.Flink
= NULL
;
6501 KeReleaseSpinLock(&DeviceObject
->OverflowQueueSpinLock
, OldIrql
);
6510 RxRemoveShareAccess(
6511 _Inout_ PFILE_OBJECT FileObject
,
6512 _Inout_ PSHARE_ACCESS ShareAccess
,
6514 _In_ PSZ wherelogtag
)
6518 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6519 IoRemoveShareAccess(FileObject
, ShareAccess
);
6520 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6527 RxRemoveShareAccessPerSrvOpens(
6528 IN OUT PSRV_OPEN SrvOpen
)
6530 ACCESS_MASK DesiredAccess
;
6532 BOOLEAN WriteAccess
;
6533 BOOLEAN DeleteAccess
;
6537 /* Get access that were granted to SRV_OPEN */
6538 DesiredAccess
= SrvOpen
->DesiredAccess
;
6539 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
6540 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
6541 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
6543 /* If any, drop them */
6544 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
6547 BOOLEAN SharedWrite
;
6548 BOOLEAN SharedDelete
;
6549 ULONG DesiredShareAccess
;
6550 PSHARE_ACCESS ShareAccess
;
6552 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
6553 DesiredShareAccess
= SrvOpen
->ShareAccess
;
6555 ShareAccess
->Readers
-= ReadAccess
;
6556 ShareAccess
->Writers
-= WriteAccess
;
6557 ShareAccess
->Deleters
-= DeleteAccess
;
6559 ShareAccess
->OpenCount
--;
6561 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
6562 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
6563 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
6564 ShareAccess
->SharedRead
-= SharedRead
;
6565 ShareAccess
->SharedWrite
-= SharedWrite
;
6566 ShareAccess
->SharedDelete
-= SharedDelete
;
6571 RxSearchForCollapsibleOpen(
6572 PRX_CONTEXT RxContext
,
6573 ACCESS_MASK DesiredAccess
,
6578 PLIST_ENTRY ListEntry
;
6579 BOOLEAN ShouldTry
, Purged
, Scavenged
;
6583 DPRINT("RxSearchForCollapsibleOpen(%p, %x, %x)\n", RxContext
, DesiredAccess
, ShareAccess
);
6585 Fcb
= (PFCB
)RxContext
->pFcb
;
6587 /* If we're asked to open for backup, don't allow SRV_OPEN reuse */
6588 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
6590 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6592 RxScavengeRelatedFobxs(Fcb
);
6593 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6595 return STATUS_NOT_FOUND
;
6598 /* If basic open, ask the mini-rdr if we should try to collapse */
6599 if (RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN
||
6600 RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN_IF
)
6604 if (Fcb
->MRxDispatch
!= NULL
)
6606 ASSERT(RxContext
->pRelevantSrvOpen
== NULL
);
6607 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
6609 ShouldTry
= NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
));
6617 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
))
6622 /* If we shouldn't try, ask the caller to allocate a new SRV_OPEN */
6625 if (NT_SUCCESS(RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
)))
6627 return STATUS_NOT_FOUND
;
6630 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6632 RxScavengeRelatedFobxs(Fcb
);
6633 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6635 return STATUS_NOT_FOUND
;
6638 /* Only collapse for matching NET_ROOT & disks */
6639 if (Fcb
->pNetRoot
!= RxContext
->Create
.pNetRoot
||
6640 Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
6642 return STATUS_NOT_FOUND
;
6647 Status
= STATUS_NOT_FOUND
;
6649 /* Browse all our SRV_OPEN to find the matching one */
6650 for (ListEntry
= Fcb
->SrvOpenList
.Flink
;
6651 ListEntry
!= &Fcb
->SrvOpenList
;
6652 ListEntry
= ListEntry
->Flink
)
6656 SrvOpen
= CONTAINING_RECORD(ListEntry
, SRV_OPEN
, SrvOpenQLinks
);
6657 /* Not the same VNET_ROOT, move to the next one */
6658 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
6660 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6664 /* Is there a sharing violation? */
6665 if (SrvOpen
->DesiredAccess
!= DesiredAccess
|| SrvOpen
->ShareAccess
!= ShareAccess
||
6666 BooleanFlagOn(SrvOpen
->Flags
, (SRVOPEN_FLAG_CLOSED
| SRVOPEN_FLAG_COLLAPSING_DISABLED
| SRVOPEN_FLAG_FILE_DELETED
| SRVOPEN_FLAG_FILE_RENAMED
)))
6668 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
6670 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6674 /* Check against the SRV_OPEN */
6675 Status
= RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
);
6676 if (!NT_SUCCESS(Status
))
6683 /* Don't allow collaspse for reparse point opening */
6684 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
^ SrvOpen
->CreateOptions
, FILE_OPEN_REPARSE_POINT
))
6688 Status
= STATUS_NOT_FOUND
;
6692 /* Not readonly? Or bytereange lock disabled? Try to collapse! */
6693 if (DisableByteRangeLockingOnReadOnlyFiles
|| !BooleanFlagOn(SrvOpen
->pFcb
->Attributes
, FILE_ATTRIBUTE_READONLY
))
6695 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
6697 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
6698 if (NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
)))
6700 /* Is close delayed - great reuse*/
6701 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
6703 DPRINT("Delayed close successfull, reusing %p\n", SrvOpen
);
6704 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
6705 ClearFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
6708 return STATUS_SUCCESS
;
6711 Status
= STATUS_NOT_FOUND
;
6716 /* We browse the whole list and didn't find any matching? NOT_FOUND */
6717 if (ListEntry
== &Fcb
->SrvOpenList
)
6719 Status
= STATUS_NOT_FOUND
;
6722 /* Only required access: read attributes? Don't reuse */
6723 if ((DesiredAccess
& 0xFFEFFFFF) == FILE_READ_ATTRIBUTES
)
6725 return STATUS_NOT_FOUND
;
6728 /* Not found? Scavenge and retry to look for collaspile SRV_OPEN */
6731 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6733 RxScavengeRelatedFobxs(Fcb
);
6737 /* Not found? Purgeable? Purge and retry to look for collaspile SRV_OPEN */
6738 if (!Purged
&& RxIsOkToPurgeFcb(Fcb
))
6740 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6745 /* If sharing violation, keep track of it */
6746 if (Status
== STATUS_SHARING_VIOLATION
)
6748 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6751 DPRINT("Status: %x\n", Status
);
6760 _In_ ACCESS_MASK DesiredAccess
,
6761 _In_ ULONG DesiredShareAccess
,
6762 _Inout_ PFILE_OBJECT FileObject
,
6763 _Out_ PSHARE_ACCESS ShareAccess
,
6765 _In_ PSZ wherelogtag
)
6769 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6770 IoSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
);
6771 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6778 RxSetupNetFileObject(
6779 PRX_CONTEXT RxContext
)
6783 PFILE_OBJECT FileObject
;
6784 PIO_STACK_LOCATION Stack
;
6788 /* Assert FOBX is FOBX or NULL */
6789 Fobx
= (PFOBX
)RxContext
->pFobx
;
6790 ASSERT((Fobx
== NULL
) || (NodeType(Fobx
) == RDBSS_NTC_FOBX
));
6792 Fcb
= (PFCB
)RxContext
->pFcb
;
6793 Stack
= RxContext
->CurrentIrpSp
;
6794 FileObject
= Stack
->FileObject
;
6795 /* If it's temporary mark FO as such */
6796 if (Fcb
!= NULL
&& NodeType(Fcb
) != RDBSS_NTC_VCB
&&
6797 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TEMPORARY
))
6799 if (FileObject
== NULL
)
6804 FileObject
->Flags
|= FO_TEMPORARY_FILE
;
6807 /* No FO, nothing to setup */
6808 if (FileObject
== NULL
)
6813 /* Assign FCB & CCB (FOBX) to FO */
6814 FileObject
->FsContext
= Fcb
;
6815 FileObject
->FsContext2
= Fobx
;
6818 ULONG_PTR StackTop
, StackBottom
;
6820 /* If FO is allocated on pool, keep track of it */
6821 IoGetStackLimits(&StackTop
, &StackBottom
);
6822 if ((ULONG_PTR
)FileObject
<= StackBottom
|| (ULONG_PTR
)FileObject
>= StackTop
)
6824 Fobx
->AssociatedFileObject
= FileObject
;
6828 Fobx
->AssociatedFileObject
= NULL
;
6831 /* Make sure to mark FOBX if it's a DFS open */
6832 if (RxContext
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
))
6834 SetFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
6838 ClearFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
6842 /* Set Cc pointers */
6843 FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
6845 /* Update access state */
6846 if (Stack
->Parameters
.Create
.SecurityContext
!= NULL
)
6848 PACCESS_STATE AccessState
;
6850 AccessState
= Stack
->Parameters
.Create
.SecurityContext
->AccessState
;
6851 AccessState
->PreviouslyGrantedAccess
|= AccessState
->RemainingDesiredAccess
;
6852 AccessState
->RemainingDesiredAccess
= 0;
6862 IN PRX_CONTEXT RxContext
,
6863 OUT PBOOLEAN PostToFsp
)
6866 BOOLEAN Wait
, AlreadyStarted
;
6867 PRDBSS_DEVICE_OBJECT DeviceObject
;
6869 /* If we've not been post, then, do it */
6870 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
))
6872 SECURITY_SUBJECT_CONTEXT SubjectContext
;
6874 SeCaptureSubjectContext(&SubjectContext
);
6875 RxContext
->FsdUid
= RxGetUid(&SubjectContext
);
6876 SeReleaseSubjectContext(&SubjectContext
);
6879 return STATUS_PENDING
;
6882 /* Acquire all the required locks */
6883 Wait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
6884 if (!ExAcquireResourceExclusiveLite(&RxData
.Resource
, Wait
))
6887 return STATUS_PENDING
;
6890 if (!RxAcquirePrefixTableLockExclusive(RxContext
->RxDeviceObject
->pRxNetNameTable
, Wait
))
6892 ExReleaseResourceLite(&RxData
.Resource
);
6894 return STATUS_PENDING
;
6897 AlreadyStarted
= FALSE
;
6898 DeviceObject
= RxContext
->RxDeviceObject
;
6901 /* MUP handle set, means already registered */
6902 if (DeviceObject
->MupHandle
!= NULL
)
6904 AlreadyStarted
= TRUE
;
6905 Status
= STATUS_REDIRECTOR_STARTED
;
6909 /* If we're asked to register to MUP, then do it */
6910 Status
= STATUS_SUCCESS
;
6911 if (DeviceObject
->RegisterUncProvider
)
6913 Status
= FsRtlRegisterUncProvider(&DeviceObject
->MupHandle
,
6914 &DeviceObject
->DeviceName
,
6915 DeviceObject
->RegisterMailSlotProvider
);
6917 if (!NT_SUCCESS(Status
))
6919 DeviceObject
->MupHandle
= NULL
;
6923 /* Register as file system */
6924 IoRegisterFileSystem(&DeviceObject
->DeviceObject
);
6925 DeviceObject
->RegisteredAsFileSystem
= TRUE
;
6927 /* Inform mini-rdr it has to start */
6928 MINIRDR_CALL(Status
, RxContext
, DeviceObject
->Dispatch
, MRxStart
, (RxContext
, DeviceObject
));
6929 if (NT_SUCCESS(Status
))
6931 ++DeviceObject
->StartStopContext
.Version
;
6932 RxSetRdbssState(DeviceObject
, RDBSS_STARTED
);
6933 InterlockedExchangeAdd(&RxData
.NumberOfMinirdrsStarted
, 1);
6935 Status
= RxInitializeMRxDispatcher(DeviceObject
);
6940 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status
))
6942 if (!AlreadyStarted
)
6944 RxUnstart(RxContext
, DeviceObject
);
6948 RxReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
);
6949 ExReleaseResourceLite(&RxData
.Resource
);
6959 IN PRX_CONTEXT RxContext
,
6960 OUT PBOOLEAN PostToFsp
)
6963 return STATUS_NOT_IMPLEMENTED
;
6968 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6972 return STATUS_NOT_IMPLEMENTED
;
6979 RxTryToBecomeTheTopLevelIrp(
6980 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
6982 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6983 IN BOOLEAN ForceTopLevel
6986 BOOLEAN FromPool
= FALSE
;
6990 /* If not top level, and not have to be, quit */
6991 if (IoGetTopLevelIrp() && !ForceTopLevel
)
6996 /* If not TLC provider, allocate one */
6997 if (TopLevelContext
== NULL
)
6999 TopLevelContext
= RxAllocatePoolWithTag(NonPagedPool
, sizeof(RX_TOPLEVELIRP_CONTEXT
), RX_TLC_POOLTAG
);
7000 if (TopLevelContext
== NULL
)
7009 __RxInitializeTopLevelIrpContext(TopLevelContext
, Irp
, RxDeviceObject
, FromPool
);
7011 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
7014 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
7017 /* Make it top level IRP */
7018 IoSetTopLevelIrp((PIRP
)TopLevelContext
);
7026 RxUpdateShareAccess(
7027 _Inout_ PFILE_OBJECT FileObject
,
7028 _Inout_ PSHARE_ACCESS ShareAccess
,
7030 _In_ PSZ wherelogtag
)
7034 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
7035 IoUpdateShareAccess(FileObject
, ShareAccess
);
7036 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
7043 RxUninitializeCacheMap(
7044 PRX_CONTEXT RxContext
,
7045 PFILE_OBJECT FileObject
,
7046 PLARGE_INTEGER TruncateSize
)
7050 CACHE_UNINITIALIZE_EVENT UninitEvent
;
7054 Fcb
= FileObject
->FsContext
;
7055 ASSERT(NodeTypeIsFcb(Fcb
));
7056 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
7058 KeInitializeEvent(&UninitEvent
.Event
, SynchronizationEvent
, FALSE
);
7059 CcUninitializeCacheMap(FileObject
, TruncateSize
, &UninitEvent
);
7061 /* Always release the FCB before waiting for the uninit event */
7062 RxReleaseFcb(RxContext
, Fcb
);
7064 KeWaitForSingleObject(&UninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
7066 /* Re-acquire it afterwards */
7067 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
7068 ASSERT(NT_SUCCESS(Status
));
7074 IN PDRIVER_OBJECT DriverObject
)
7083 IN PFILE_LOCK_INFO LockInfo
)
7090 PRX_CONTEXT Context
,
7091 PRDBSS_DEVICE_OBJECT DeviceObject
)
7100 RxUnwindTopLevelIrp(
7101 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
7103 DPRINT("RxUnwindTopLevelIrp(%p)\n", TopLevelContext
);
7105 /* No TLC provided? Ask the system for ours! */
7106 if (TopLevelContext
== NULL
)
7108 TopLevelContext
= (PRX_TOPLEVELIRP_CONTEXT
)IoGetTopLevelIrp();
7109 if (TopLevelContext
== NULL
)
7114 /* In that case, just assert it's really ours */
7115 ASSERT(RxIsThisAnRdbssTopLevelContext(TopLevelContext
));
7116 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
7119 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
7120 ASSERT(TopLevelContext
->Thread
== PsGetCurrentThread());
7121 /* Restore the previous top level IRP */
7122 IoSetTopLevelIrp(TopLevelContext
->Previous
);
7123 /* If TLC was allocated from pool, remove it from list and release it */
7124 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
7126 RxRemoveFromTopLevelIrpAllocatedContextsList(TopLevelContext
);
7127 RxFreePoolWithTag(TopLevelContext
, RX_TLC_POOLTAG
);
7135 RxUpdateShareAccessPerSrvOpens(
7136 IN PSRV_OPEN SrvOpen
)
7138 ACCESS_MASK DesiredAccess
;
7140 BOOLEAN WriteAccess
;
7141 BOOLEAN DeleteAccess
;
7145 /* If already updated, no need to continue */
7146 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
))
7151 /* Check if any access wanted */
7152 DesiredAccess
= SrvOpen
->DesiredAccess
;
7153 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
7154 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
7155 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
7157 /* In that case, update it */
7158 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
7161 BOOLEAN SharedWrite
;
7162 BOOLEAN SharedDelete
;
7163 ULONG DesiredShareAccess
;
7164 PSHARE_ACCESS ShareAccess
;
7166 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
7167 DesiredShareAccess
= SrvOpen
->ShareAccess
;
7169 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
7170 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
7171 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
7173 ShareAccess
->OpenCount
++;
7175 ShareAccess
->Readers
+= ReadAccess
;
7176 ShareAccess
->Writers
+= WriteAccess
;
7177 ShareAccess
->Deleters
+= DeleteAccess
;
7178 ShareAccess
->SharedRead
+= SharedRead
;
7179 ShareAccess
->SharedWrite
+= SharedWrite
;
7180 ShareAccess
->SharedDelete
+= SharedDelete
;
7183 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
);
7190 RxXXXControlFileCallthru(
7191 PRX_CONTEXT Context
)
7197 DPRINT("RxXXXControlFileCallthru(%p)\n", Context
);
7199 /* No dispatch table? Nothing to dispatch */
7200 if (Context
->RxDeviceObject
->Dispatch
== NULL
)
7202 Context
->pFobx
= NULL
;
7203 return STATUS_INVALID_DEVICE_REQUEST
;
7206 /* Init the lowio context */
7207 Status
= RxLowIoPopulateFsctlInfo(Context
);
7208 if (!NT_SUCCESS(Status
))
7213 /* Check whether we're consistent: a length means a buffer */
7214 if ((Context
->LowIoContext
.ParamsFor
.FsCtl
.InputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pInputBuffer
== NULL
) ||
7215 (Context
->LowIoContext
.ParamsFor
.FsCtl
.OutputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pOutputBuffer
== NULL
))
7217 return STATUS_INVALID_PARAMETER
;
7220 /* Forward the call to the mini-rdr */
7221 DPRINT("Calling: %p\n", Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile
);
7222 Status
= Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile(Context
);
7223 if (Status
!= STATUS_PENDING
)
7225 Context
->CurrentIrp
->IoStatus
.Information
= Context
->InformationToReturn
;
7228 DPRINT("RxXXXControlFileCallthru: %x, %ld\n", Context
->CurrentIrp
->IoStatus
.Status
, Context
->CurrentIrp
->IoStatus
.Information
);