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(
917 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
918 PV_NET_ROOT VNetRoot
,
919 BOOLEAN ForceFilesClosed
)
922 return STATUS_NOT_IMPLEMENTED
;
928 PDEVICE_OBJECT DeviceObject
,
938 RxCanonicalizeFileNameByServerSpecs(
939 PRX_CONTEXT RxContext
,
940 PUNICODE_STRING NetRootName
)
942 USHORT NextChar
, CurChar
;
947 /* Validate file name is not empty */
948 MaxChars
= NetRootName
->Length
/ sizeof(WCHAR
);
951 return STATUS_MORE_PROCESSING_REQUIRED
;
954 /* Validate name is correct */
955 for (NextChar
= 0, CurChar
= 0; CurChar
+ 1 < MaxChars
; NextChar
= CurChar
+ 1)
959 for (i
= NextChar
+ 1; i
< MaxChars
; ++i
)
961 if (NetRootName
->Buffer
[i
] == '\\' || NetRootName
->Buffer
[i
] == ':')
968 if (CurChar
== NextChar
)
970 if (((NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':') || NextChar
== (MaxChars
- 1)) && NetRootName
->Buffer
[NextChar
] != '.')
977 if (CurChar
>= MaxChars
- 1)
982 if (NetRootName
->Buffer
[CurChar
+ 1] != ':')
984 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
989 if (NetRootName
->Buffer
[1] != ':')
991 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
997 if ((CurChar
- NextChar
) == 1)
999 if (NetRootName
->Buffer
[NextChar
+ 2] != '.')
1004 if (NetRootName
->Buffer
[NextChar
] == '\\' || NetRootName
->Buffer
[NextChar
] == ':' || NetRootName
->Buffer
[NextChar
] == '.')
1006 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1011 if ((CurChar
- NextChar
) != 2 || (NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':')
1012 || NetRootName
->Buffer
[NextChar
+ 1] != '.')
1017 if (NetRootName
->Buffer
[NextChar
+ 2] == '.')
1019 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1025 return STATUS_MORE_PROCESSING_REQUIRED
;
1029 RxCanonicalizeNameAndObtainNetRoot(
1030 PRX_CONTEXT RxContext
,
1031 PUNICODE_STRING FileName
,
1032 PUNICODE_STRING NetRootName
)
1035 NET_ROOT_TYPE NetRootType
;
1036 UNICODE_STRING CanonicalName
;
1040 NetRootType
= NET_ROOT_WILD
;
1042 RtlInitEmptyUnicodeString(NetRootName
, NULL
, 0);
1043 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
1045 /* if not relative opening, just handle the passed name */
1046 if (RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
== NULL
)
1048 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1049 if (!NT_SUCCESS(Status
))
1058 /* Make sure we have a valid FCB and a FOBX */
1059 Fcb
= RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext
;
1061 RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext2
== NULL
)
1063 return STATUS_INVALID_PARAMETER
;
1066 if (!NodeTypeIsFcb(Fcb
))
1068 return STATUS_INVALID_PARAMETER
;
1074 /* Get/Create the associated VNetRoot for opening */
1075 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1076 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
&&
1077 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_MAILSLOT_REPARSE
))
1079 ASSERT(CanonicalName
.Buffer
== RxContext
->Create
.CanonicalNameBuffer
);
1081 RxFreeCanonicalNameBuffer(RxContext
);
1082 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
1083 if (NT_SUCCESS(Status
))
1085 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
1089 /* Filename cannot contain wildcards */
1090 if (FsRtlDoesNameContainWildCards(NetRootName
))
1092 Status
= STATUS_OBJECT_NAME_INVALID
;
1095 /* Make sure file name is correct */
1096 if (NT_SUCCESS(Status
))
1098 Status
= RxCanonicalizeFileNameByServerSpecs(RxContext
, NetRootName
);
1101 /* Give the mini-redirector a chance to prepare the name */
1102 if (NT_SUCCESS(Status
) || Status
== STATUS_MORE_PROCESSING_REQUIRED
)
1104 if (RxContext
->Create
.pNetRoot
!= NULL
)
1106 NTSTATUS IgnoredStatus
;
1108 MINIRDR_CALL(IgnoredStatus
, RxContext
, RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
1109 MRxPreparseName
, (RxContext
, NetRootName
));
1110 (void)IgnoredStatus
;
1119 RxCheckFcbStructuresForAlignment(
1127 _In_ ACCESS_MASK DesiredAccess
,
1128 _In_ ULONG DesiredShareAccess
,
1129 _Inout_ PFILE_OBJECT FileObject
,
1130 _Inout_ PSHARE_ACCESS ShareAccess
,
1131 _In_ BOOLEAN Update
,
1133 _In_ PSZ wherelogtag
)
1137 RxDumpWantedAccess(where
, "", wherelogtag
, DesiredAccess
, DesiredShareAccess
);
1138 RxDumpCurrentAccess(where
, "", wherelogtag
, ShareAccess
);
1140 return IoCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
, Update
);
1147 RxCheckShareAccessPerSrvOpens(
1149 IN ACCESS_MASK DesiredAccess
,
1150 IN ULONG DesiredShareAccess
)
1153 BOOLEAN WriteAccess
;
1154 BOOLEAN DeleteAccess
;
1155 PSHARE_ACCESS ShareAccess
;
1159 ShareAccess
= &Fcb
->ShareAccessPerSrvOpens
;
1161 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess
, DesiredShareAccess
);
1162 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess
);
1164 /* Check if any access wanted */
1165 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
1166 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
1167 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
1169 if (ReadAccess
|| WriteAccess
|| DeleteAccess
)
1171 BOOLEAN SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
1172 BOOLEAN SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
1173 BOOLEAN SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
1175 /* Check whether there's a violation */
1177 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
1179 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
1181 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
1182 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
1183 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
1184 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
1186 return STATUS_SHARING_VIOLATION
;
1190 return STATUS_SUCCESS
;
1194 RxCleanupPipeQueues(
1195 PRX_CONTEXT Context
)
1204 RxCloseAssociatedSrvOpen(
1206 IN PRX_CONTEXT RxContext OPTIONAL
)
1211 BOOLEAN CloseSrvOpen
;
1212 PRX_CONTEXT LocalContext
;
1216 /* Assume SRV_OPEN is already closed */
1217 CloseSrvOpen
= FALSE
;
1218 /* If we have a FOBX, we'll have to close it */
1221 /* If the FOBX isn't closed yet */
1222 if (!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
))
1224 SrvOpen
= Fobx
->SrvOpen
;
1225 Fcb
= (PFCB
)SrvOpen
->pFcb
;
1226 /* Check whether we've to close SRV_OPEN first */
1227 if (!BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1229 CloseSrvOpen
= TRUE
;
1233 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1235 /* Not much to do */
1236 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1238 if (SrvOpen
->OpenCount
> 0)
1240 --SrvOpen
->OpenCount
;
1245 /* No need to close SRV_OPEN, so close FOBX */
1248 RxMarkFobxOnClose(Fobx
);
1250 return STATUS_SUCCESS
;
1255 /* No FOBX? No RX_CONTEXT, ok, job done! */
1256 if (RxContext
== NULL
)
1258 return STATUS_SUCCESS
;
1261 /* Get the FCB from RX_CONTEXT */
1262 Fcb
= (PFCB
)RxContext
->pFcb
;
1266 /* If we don't have RX_CONTEXT, allocte one, we'll need it */
1267 if (RxContext
== NULL
)
1269 ASSERT(Fobx
!= NULL
);
1271 LocalContext
= RxCreateRxContext(NULL
, Fcb
->RxDeviceObject
, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING
| RX_CONTEXT_FLAG_WAIT
);
1272 if (LocalContext
== NULL
)
1274 return STATUS_INSUFFICIENT_RESOURCES
;
1277 LocalContext
->MajorFunction
= 2;
1278 LocalContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
1279 LocalContext
->pFobx
= (PMRX_FOBX
)Fobx
;
1280 LocalContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)Fobx
->SrvOpen
;
1284 LocalContext
= RxContext
;
1287 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1289 /* Now, close the FOBX */
1292 RxMarkFobxOnClose(Fobx
);
1296 InterlockedDecrement((volatile long *)&Fcb
->OpenCount
);
1299 /* If not a "standard" file, SRV_OPEN can be null */
1300 if (SrvOpen
== NULL
)
1302 ASSERT((NodeType(Fcb
) == RDBSS_NTC_OPENTARGETDIR_FCB
) || (NodeType(Fcb
) == RDBSS_NTC_IPC_SHARE
) || (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
));
1303 RxDereferenceNetFcb(Fcb
);
1305 if (LocalContext
!= RxContext
)
1307 RxDereferenceAndDeleteRxContext(LocalContext
);
1310 return STATUS_SUCCESS
;
1313 /* If SRV_OPEN isn't in a good condition, nothing to close */
1314 if (SrvOpen
->Condition
!= Condition_Good
)
1316 if (LocalContext
!= RxContext
)
1318 RxDereferenceAndDeleteRxContext(LocalContext
);
1321 return STATUS_SUCCESS
;
1324 /* Decrease open count */
1325 if (SrvOpen
->OpenCount
> 0)
1327 --SrvOpen
->OpenCount
;
1330 /* If we're the only one left, is there a FOBX handled by Scavenger? */
1331 if (SrvOpen
->OpenCount
== 1)
1333 if (!IsListEmpty(&SrvOpen
->FobxList
))
1335 if (!IsListEmpty(&CONTAINING_RECORD(SrvOpen
->FobxList
.Flink
, FOBX
, FobxQLinks
)->ScavengerFinalizationList
))
1337 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
1342 /* Nothing left, purge FCB */
1343 if (SrvOpen
->OpenCount
== 0 && RxContext
== NULL
)
1345 RxPurgeNetFcb(Fcb
, LocalContext
);
1348 /* Already closed? Job done! */
1349 SrvOpen
= Fobx
->SrvOpen
;
1350 if (SrvOpen
== NULL
||
1351 (SrvOpen
->OpenCount
!= 0 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
)) ||
1352 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
))
1354 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1355 if (LocalContext
!= RxContext
)
1357 RxDereferenceAndDeleteRxContext(LocalContext
);
1360 return STATUS_SUCCESS
;
1363 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1365 /* Inform mini-rdr about closing */
1366 MINIRDR_CALL(Status
, LocalContext
, Fcb
->MRxDispatch
, MRxCloseSrvOpen
, (LocalContext
));
1367 DPRINT("MRxCloseSrvOpen returned: %lx, called with RX_CONTEXT %p for FOBX %p (FCB %p, SRV_OPEN %p)\n ",
1368 Status
, RxContext
, Fobx
, Fcb
, SrvOpen
);
1370 /* And mark as such */
1371 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSED
);
1372 SrvOpen
->Key
= (PVOID
)-1;
1374 /* If we were delayed, we're not! */
1375 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
1377 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
1381 RxRemoveShareAccessPerSrvOpens(SrvOpen
);
1382 RxPurgeChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
1385 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1387 /* Mark the FOBX closed as well */
1388 SetFlag(Fobx
->Flags
, FOBX_FLAG_SRVOPEN_CLOSED
);
1390 if (LocalContext
!= RxContext
)
1392 RxDereferenceAndDeleteRxContext(LocalContext
);
1402 RxCollapseOrCreateSrvOpen(
1403 PRX_CONTEXT RxContext
)
1410 PIO_STACK_LOCATION Stack
;
1411 ACCESS_MASK DesiredAccess
;
1412 RX_BLOCK_CONDITION FcbCondition
;
1416 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext
);
1418 Fcb
= (PFCB
)RxContext
->pFcb
;
1419 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1420 ++Fcb
->UncleanCount
;
1422 Stack
= RxContext
->CurrentIrpSp
;
1423 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
1424 ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
1426 Disposition
= RxContext
->Create
.NtCreateParameters
.Disposition
;
1428 /* Try to find a reusable SRV_OPEN */
1429 Status
= RxSearchForCollapsibleOpen(RxContext
, DesiredAccess
, ShareAccess
);
1430 if (Status
== STATUS_NOT_FOUND
)
1432 /* If none found, create one */
1433 SrvOpen
= RxCreateSrvOpen((PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
, Fcb
);
1434 if (SrvOpen
== NULL
)
1436 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1440 SrvOpen
->DesiredAccess
= DesiredAccess
;
1441 SrvOpen
->ShareAccess
= ShareAccess
;
1442 Status
= STATUS_SUCCESS
;
1445 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
1447 if (Status
!= STATUS_SUCCESS
)
1449 FcbCondition
= Condition_Bad
;
1453 RxInitiateSrvOpenKeyAssociation(SrvOpen
);
1455 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1456 RxContext
->CurrentIrp
->IoStatus
.Information
= 0xABCDEF;
1457 /* Inform the mini-rdr we're handling a create */
1458 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCreate
, (RxContext
));
1459 ASSERT(RxContext
->CurrentIrp
->IoStatus
.Information
== 0xABCDEF);
1461 DPRINT("MRxCreate returned: %x\n", Status
);
1462 if (Status
== STATUS_SUCCESS
)
1464 /* In case of overwrite, reset file size */
1465 if (Disposition
== FILE_OVERWRITE
|| Disposition
== FILE_OVERWRITE_IF
)
1467 RxAcquirePagingIoResource(RxContext
, Fcb
);
1468 Fcb
->Header
.AllocationSize
.QuadPart
= 0LL;
1469 Fcb
->Header
.FileSize
.QuadPart
= 0LL;
1470 Fcb
->Header
.ValidDataLength
.QuadPart
= 0LL;
1471 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1472 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1473 RxReleasePagingIoResource(RxContext
, Fcb
);
1477 /* Otherwise, adjust sizes */
1478 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1479 if (CcIsFileCached(RxContext
->CurrentIrpSp
->FileObject
))
1481 RxAdjustAllocationSizeforCC(Fcb
);
1483 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1487 /* Set the IoStatus with information returned by mini-rdr */
1488 RxContext
->CurrentIrp
->IoStatus
.Information
= RxContext
->Create
.ReturnedCreateInformation
;
1490 SrvOpen
->OpenStatus
= Status
;
1491 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1492 RxTransitionSrvOpen(SrvOpen
, (Status
== STATUS_SUCCESS
? Condition_Good
: Condition_Bad
));
1494 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1496 RxCompleteSrvOpenKeyAssociation(SrvOpen
);
1498 if (Status
== STATUS_SUCCESS
)
1500 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
1502 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
1504 SrvOpen
->CreateOptions
= RxContext
->Create
.NtCreateParameters
.CreateOptions
;
1505 FcbCondition
= Condition_Good
;
1509 FcbCondition
= Condition_Bad
;
1510 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1511 RxContext
->pRelevantSrvOpen
= NULL
;
1513 if (RxContext
->pFobx
!= NULL
)
1515 RxDereferenceNetFobx(RxContext
->pFobx
, LHS_ExclusiveLockHeld
);
1516 RxContext
->pFobx
= NULL
;
1521 /* Set FCB state - good or bad - depending on whether create succeed */
1522 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb
, Fcb
->Condition
);
1523 RxTransitionNetFcb(Fcb
, FcbCondition
);
1525 else if (Status
== STATUS_SUCCESS
)
1527 BOOLEAN IsGood
, ExtraOpen
;
1529 /* A reusable SRV_OPEN was found */
1530 RxContext
->CurrentIrp
->IoStatus
.Information
= FILE_OPENED
;
1533 SrvOpen
= (PSRV_OPEN
)RxContext
->pRelevantSrvOpen
;
1535 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1536 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1537 if (!StableCondition(SrvOpen
->Condition
))
1539 RxReferenceSrvOpen(SrvOpen
);
1540 ++SrvOpen
->OpenCount
;
1543 RxReleaseFcb(RxContext
, Fcb
);
1544 RxContext
->Create
.FcbAcquired
= FALSE
;
1546 RxWaitForStableSrvOpen(SrvOpen
, RxContext
);
1548 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext
, Fcb
)))
1550 RxContext
->Create
.FcbAcquired
= TRUE
;
1553 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1556 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1559 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCollapseOpen
, (RxContext
));
1561 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1565 Status
= SrvOpen
->OpenStatus
;
1570 --SrvOpen
->OpenCount
;
1571 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1575 --Fcb
->UncleanCount
;
1577 DPRINT("Status: %x\n", Status
);
1584 PRX_CONTEXT Context
)
1586 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1592 PFILE_OBJECT FileObject
;
1593 LARGE_INTEGER TruncateSize
;
1594 PLARGE_INTEGER TruncateSizePtr
;
1595 BOOLEAN NeedPurge
, FcbTableAcquired
, OneLeft
, IsFile
, FcbAcquired
, LeftForDelete
;
1599 Fcb
= (PFCB
)Context
->pFcb
;
1600 Fobx
= (PFOBX
)Context
->pFobx
;
1601 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context
, Fobx
, Fcb
);
1603 /* File system closing, it's OK */
1606 if (Fcb
->UncleanCount
> 0)
1608 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1611 return STATUS_SUCCESS
;
1614 /* Check we have a correct FCB type */
1615 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&&
1616 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&&
1617 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1618 NodeType(Fcb
) != RDBSS_NTC_SPOOLFILE
)
1620 DPRINT1("Invalid Fcb type for %p\n", Fcb
);
1621 RxBugCheck(Fcb
->Header
.NodeTypeCode
, 0, 0);
1624 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1625 ASSERT(!BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
));
1627 RxMarkFobxOnCleanup(Fobx
, &NeedPurge
);
1629 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1630 if (!NT_SUCCESS(Status
))
1637 Fobx
->AssociatedFileObject
= NULL
;
1639 /* In case SRV_OPEN used is part of FCB */
1640 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_SRVOPEN_USED
))
1642 ASSERT(Fcb
->UncleanCount
!= 0);
1643 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1645 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1647 --Fcb
->UncachedUncleanCount
;
1650 /* Inform mini-rdr */
1651 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1653 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1654 --Fobx
->SrvOpen
->UncleanFobxCount
;
1656 RxUninitializeCacheMap(Context
, FileObject
, NULL
);
1658 RxReleaseFcb(Context
, Fcb
);
1660 return STATUS_SUCCESS
;
1663 /* Report the fact that file could be set as delete on close */
1664 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
1666 SetFlag(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
1669 /* Cancel any pending notification */
1670 RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx
);
1672 /* Backup open count before we start playing with it */
1673 OpenCount
= Fcb
->ShareAccess
.OpenCount
;
1675 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
1676 FcbTableAcquired
= FALSE
;
1677 LeftForDelete
= FALSE
;
1678 OneLeft
= (Fcb
->UncleanCount
== 1);
1682 /* Unclean count and delete on close? Verify whether we're the one */
1683 if (OneLeft
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
))
1685 if (RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, FALSE
))
1687 FcbTableAcquired
= TRUE
;
1691 RxReleaseFcb(Context
, Fcb
);
1693 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
1695 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1696 if (Status
!= STATUS_SUCCESS
)
1698 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1702 FcbTableAcquired
= TRUE
;
1705 /* That means we'll perform the delete on close! */
1706 if (Fcb
->UncleanCount
== 1)
1708 LeftForDelete
= TRUE
;
1712 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1713 FcbTableAcquired
= FALSE
;
1718 TruncateSizePtr
= NULL
;
1719 /* Handle cleanup for pipes and printers */
1720 if (NetRoot
->Type
== NET_ROOT_PIPE
|| NetRoot
->Type
== NET_ROOT_PRINT
)
1722 RxCleanupPipeQueues(Context
);
1724 /* Handle cleanup for files */
1725 else if (NetRoot
->Type
== NET_ROOT_DISK
|| NetRoot
->Type
== NET_ROOT_WILD
)
1727 Context
->LowIoContext
.Flags
|= LOWIO_CONTEXT_FLAG_SAVEUNLOCKS
;
1728 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
1731 FsRtlFastUnlockAll(&Fcb
->Specific
.Fcb
.FileLock
, FileObject
, RxGetRequestorProcess(Context
), Context
);
1733 /* If there are still locks to release, proceed */
1734 if (Context
->LowIoContext
.ParamsFor
.Locks
.LockList
!= NULL
)
1736 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_UNLOCK_MULTIPLE
);
1737 Context
->LowIoContext
.ParamsFor
.Locks
.Flags
= 0;
1738 Status
= RxLowIoLockControlShell(Context
);
1741 /* Fix times and size */
1742 RxAdjustFileTimesAndSize(Context
);
1744 /* If we're the only one left... */
1747 /* And if we're supposed to delete on close */
1750 /* Update the sizes */
1751 RxAcquirePagingIoResource(Context
, Fcb
);
1752 Fcb
->Header
.FileSize
.QuadPart
= 0;
1753 Fcb
->Header
.ValidDataLength
.QuadPart
= 0;
1754 RxReleasePagingIoResource(Context
, Fcb
);
1756 /* Otherwise, call the mini-rdr to adjust sizes */
1759 /* File got grown up, fill with zeroes */
1760 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
1761 (Fcb
->Header
.ValidDataLength
.QuadPart
< Fcb
->Header
.FileSize
.QuadPart
))
1763 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxZeroExtend
, (Context
));
1764 Fcb
->Header
.ValidDataLength
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1767 /* File was truncated, let mini-rdr proceed */
1768 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
))
1770 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxTruncate
, (Context
));
1771 ClearFlag(Fcb
->FcbState
, FCB_STATE_TRUNCATE_ON_CLOSE
);
1773 /* Keep track of file change for Cc uninit */
1774 TruncateSize
.QuadPart
= Fcb
->Header
.FileSize
.QuadPart
;
1775 TruncateSizePtr
= &TruncateSize
;
1780 /* If RxMarkFobxOnCleanup() asked for purge, make sure we're the only one left first */
1788 /* Otherwise, try to see whether we can purge */
1791 NeedPurge
= (OneLeft
&& (LeftForDelete
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
)));
1798 /* We have to still be there! */
1799 ASSERT(Fcb
->UncleanCount
!= 0);
1800 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1802 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1804 --Fcb
->UncachedUncleanCount
;
1807 /* Inform mini-rdr about ongoing cleanup */
1808 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1810 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1811 --Fobx
->SrvOpen
->UncleanFobxCount
;
1814 if (DisableFlushOnCleanup
)
1816 /* Only if we're the last standing */
1817 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
&&
1818 Fcb
->UncleanCount
== Fcb
->UncachedUncleanCount
)
1820 DPRINT("Flushing %p due to last cached handle cleanup\n", Context
);
1821 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1827 if (Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
1829 DPRINT("Flushing %p on cleanup\n", Context
);
1830 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1834 /* If only remaining uncached & unclean, then flush and purge */
1835 if (!BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1837 if (Fcb
->UncachedUncleanCount
!= 0)
1839 if (Fcb
->UncachedUncleanCount
== Fcb
->UncleanCount
&&
1840 Fcb
->NonPaged
->SectionObjectPointers
.DataSectionObject
!= NULL
)
1842 DPRINT("Flushing FCB in system cache for %p\n", Context
);
1843 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
1848 /* If purge required, and not about to delete, flush */
1849 if (!LeftForDelete
&& NeedPurge
)
1851 DPRINT("Flushing FCB in system cache for %p\n", Context
);
1852 RxFlushFcbInSystemCache(Fcb
, TRUE
);
1855 /* If it was a file, drop cache */
1858 DPRINT("Uninit cache map for file\n");
1859 RxUninitializeCacheMap(Context
, FileObject
, TruncateSizePtr
);
1862 /* If that's the one left for deletion, or if it needs purge, flush */
1863 if (LeftForDelete
|| NeedPurge
)
1865 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, !LeftForDelete
);
1866 /* If that's for deletion, also remove from FCB table */
1869 RxRemoveNameNetFcb(Fcb
);
1870 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1871 FcbTableAcquired
= FALSE
;
1875 /* Remove any share access */
1876 if (OpenCount
!= 0 && NetRoot
->Type
== NET_ROOT_DISK
)
1878 RxRemoveShareAccess(FileObject
, &Fcb
->ShareAccess
, "Cleanup the share access", "ClnUpShr");
1881 /* In case there's caching, on a file, update file metadata */
1882 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
&& BooleanFlagOn(Fobx
->Flags
, 0x20000000) &&
1883 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
) && !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
))
1889 SetFlag(FileObject
->Flags
, FO_CLEANUP_COMPLETE
);
1891 FcbAcquired
= FALSE
;
1892 RxReleaseFcb(Context
, Fcb
);
1898 RxReleaseFcb(Context
, Fcb
);
1901 if (FcbTableAcquired
)
1903 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1909 #undef BugCheckFileId
1915 PRX_CONTEXT Context
)
1917 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
1921 PFILE_OBJECT FileObject
;
1922 BOOLEAN DereferenceFobx
, AcquiredFcb
;
1926 Fcb
= (PFCB
)Context
->pFcb
;
1927 Fobx
= (PFOBX
)Context
->pFobx
;
1928 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1929 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context
, Fobx
, Fcb
, FileObject
);
1931 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1932 if (!NT_SUCCESS(Status
))
1942 /* Check our FCB type is expected */
1943 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1944 (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
|| (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
&&
1945 (NodeType(Fcb
) < RDBSS_NTC_SPOOLFILE
|| NodeType(Fcb
) > RDBSS_NTC_OPENTARGETDIR_FCB
))))
1947 RxBugCheck(NodeType(Fcb
), 0, 0);
1950 RxReferenceNetFcb(Fcb
);
1952 DereferenceFobx
= FALSE
;
1953 /* If we're not closing FS */
1959 SrvOpen
= (PSRV_OPEN
)Fobx
->pSrvOpen
;
1960 SrvCall
= (PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
;
1961 /* Handle delayed close */
1962 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
1964 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
| FCB_STATE_ORPHANED
))
1966 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
))
1968 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx
, SrvOpen
);
1970 if (SrvOpen
->OpenCount
== 1 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_COLLAPSING_DISABLED
))
1972 if (InterlockedIncrement(&SrvCall
->NumberOfCloseDelayedFiles
) >= SrvCall
->MaximumNumberOfCloseDelayedFiles
)
1974 InterlockedDecrement(&SrvCall
->NumberOfCloseDelayedFiles
);
1978 DereferenceFobx
= TRUE
;
1979 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
1986 /* If we reach maximum of delayed close/or if there are no delayed close */
1987 if (!DereferenceFobx
)
1991 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
1992 if (NetRoot
->Type
!= NET_ROOT_PRINT
)
1994 /* Delete if asked */
1995 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
1997 RxScavengeRelatedFobxs(Fcb
);
1998 RxSynchronizeWithScavenger(Context
);
2000 RxReleaseFcb(Context
, Fcb
);
2002 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
2003 RxOrphanThisFcb(Fcb
);
2004 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
2006 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2007 ASSERT(NT_SUCCESS(Status
));
2012 RxMarkFobxOnClose(Fobx
);
2015 if (DereferenceFobx
)
2017 ASSERT(Fobx
!= NULL
);
2018 RxDereferenceNetFobx(Fobx
, LHS_SharedLockHeld
);
2022 RxCloseAssociatedSrvOpen(Fobx
, Context
);
2025 RxDereferenceNetFobx(Fobx
, LHS_ExclusiveLockHeld
);
2029 Freed
= RxDereferenceAndFinalizeNetFcb(Fcb
, Context
, FALSE
, FALSE
);
2030 AcquiredFcb
= !Freed
;
2032 FileObject
->FsContext
= (PVOID
)-1;
2036 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
2040 RxReleaseFcb(Context
, Fcb
);
2041 AcquiredFcb
= FALSE
;
2046 if (_SEH2_AbnormalTermination())
2050 RxReleaseFcb(Context
, Fcb
);
2055 ASSERT(!AcquiredFcb
);
2060 DPRINT("Status: %x\n", Status
);
2062 #undef BugCheckFileId
2068 PRX_CONTEXT Context
)
2072 PFILE_OBJECT FileObject
;
2073 PIO_STACK_LOCATION Stack
;
2077 DPRINT("RxCommonCreate(%p)\n", Context
);
2079 Irp
= Context
->CurrentIrp
;
2080 Stack
= Context
->CurrentIrpSp
;
2081 FileObject
= Stack
->FileObject
;
2083 /* Check whether that's a device opening */
2084 if (FileObject
->FileName
.Length
== 0 && FileObject
->RelatedFileObject
== NULL
)
2086 FileObject
->FsContext
= &RxDeviceFCB
;
2087 FileObject
->FsContext2
= NULL
;
2089 ++RxDeviceFCB
.NodeReferenceCount
;
2090 ++RxDeviceFCB
.OpenCount
;
2092 Irp
->IoStatus
.Information
= FILE_OPENED
;
2093 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject
, Context
->RxDeviceObject
, &Context
->RxDeviceObject
->DeviceName
);
2095 Status
= STATUS_SUCCESS
;
2099 PFCB RelatedFcb
= NULL
;
2101 /* Make sure caller is consistent */
2102 if (FlagOn(Stack
->Parameters
.Create
.Options
, FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
) ==
2103 (FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
))
2105 DPRINT1("Create.Options: %x\n", Stack
->Parameters
.Create
.Options
);
2106 return STATUS_INVALID_PARAMETER
;
2109 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
2110 Context
, FileObject
, Stack
->Parameters
.Create
.Options
, Stack
->Flags
, Stack
->Parameters
.Create
.FileAttributes
,
2111 Stack
->Parameters
.Create
.ShareAccess
, Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
2112 DPRINT("FileName: %wZ\n", &FileObject
->FileName
);
2114 if (FileObject
->RelatedFileObject
!= NULL
)
2116 RelatedFcb
= FileObject
->RelatedFileObject
->FsContext
;
2117 DPRINT("Rel FO: %p, path: %wZ\n", FileObject
->RelatedFileObject
, RelatedFcb
->FcbTableEntry
.Path
);
2120 /* Going to rename? */
2121 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
2123 DPRINT("TargetDir!\n");
2126 /* Copy create parameters to the context */
2127 RxCopyCreateParameters(Context
);
2129 /* If the caller wants to establish a connection, go ahead */
2130 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_CREATE_TREE_CONNECTION
))
2132 Status
= RxCreateTreeConnect(Context
);
2136 /* Validate file name */
2137 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2138 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2139 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2141 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2142 RtlMoveMemory(&FileObject
->FileName
.Buffer
[0], &FileObject
->FileName
.Buffer
[1],
2143 FileObject
->FileName
.Length
);
2145 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
2146 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
2147 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
2149 return STATUS_OBJECT_NAME_INVALID
;
2153 /* Attempt to open the file */
2156 UNICODE_STRING NetRootName
;
2158 /* Strip last \ if required */
2159 if (FileObject
->FileName
.Length
!= 0 &&
2160 FileObject
->FileName
.Buffer
[FileObject
->FileName
.Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
2162 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NON_DIRECTORY_FILE
))
2164 return STATUS_OBJECT_NAME_INVALID
;
2167 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
2168 Context
->Create
.Flags
|= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
;
2171 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
))
2173 FileObject
->Flags
|= FO_WRITE_THROUGH
;
2176 /* Get the associated net root to opening */
2177 Status
= RxCanonicalizeNameAndObtainNetRoot(Context
, &FileObject
->FileName
, &NetRootName
);
2178 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
2183 /* And attempt to open */
2184 Status
= RxCreateFromNetRoot(Context
, &NetRootName
);
2185 if (Status
== STATUS_SHARING_VIOLATION
)
2189 else if (Status
== STATUS_REPARSE
)
2191 Context
->CurrentIrp
->IoStatus
.Information
= 0;
2195 ASSERT(!BooleanFlagOn(Context
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_REPARSE
));
2198 while (Status
== STATUS_MORE_PROCESSING_REQUIRED
);
2201 if (Status
== STATUS_RETRY
)
2203 RxpPrepareCreateContextForReuse(Context
);
2205 ASSERT(Status
!= STATUS_PENDING
);
2208 DPRINT("Status: %lx\n", Status
);
2217 RxCommonDevFCBCleanup(
2218 PRX_CONTEXT Context
)
2225 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context
);
2227 Fcb
= Context
->pFcb
;
2228 Status
= STATUS_SUCCESS
;
2229 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2231 /* Our FOBX if set, has to be a VNetRoot */
2232 if (Context
->pFobx
!= NULL
)
2234 RxAcquirePrefixTableLockShared(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2235 if (Context
->pFobx
->NodeTypeCode
!= RDBSS_NTC_V_NETROOT
)
2237 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2239 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2243 --Fcb
->UncleanCount
;
2254 RxCommonDevFCBClose(
2255 PRX_CONTEXT Context
)
2259 PMRX_V_NET_ROOT NetRoot
;
2263 DPRINT("RxCommonDevFCBClose(%p)\n", Context
);
2265 Fcb
= Context
->pFcb
;
2266 NetRoot
= (PMRX_V_NET_ROOT
)Context
->pFobx
;
2267 Status
= STATUS_SUCCESS
;
2268 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
2270 /* Our FOBX if set, has to be a VNetRoot */
2271 if (NetRoot
!= NULL
)
2273 RxAcquirePrefixTableLockExclusive(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
2274 if (NetRoot
->NodeTypeCode
== RDBSS_NTC_V_NETROOT
)
2276 --NetRoot
->NumberOfOpens
;
2277 RxDereferenceVNetRoot(NetRoot
, LHS_ExclusiveLockHeld
);
2281 Status
= STATUS_NOT_IMPLEMENTED
;
2283 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
2295 RxCommonDevFCBFsCtl(
2296 PRX_CONTEXT Context
)
2299 return STATUS_NOT_IMPLEMENTED
;
2307 RxCommonDevFCBIoCtl(
2308 PRX_CONTEXT Context
)
2314 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context
);
2316 if (Context
->pFobx
!= NULL
)
2318 return STATUS_INVALID_HANDLE
;
2321 /* Is that a prefix claim from MUP? */
2322 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2324 return RxPrefixClaim(Context
);
2327 /* Otherwise, pass through the mini-rdr */
2328 Status
= RxXXXControlFileCallthru(Context
);
2329 if (Status
!= STATUS_PENDING
)
2331 if (Context
->PostRequest
)
2333 Context
->ResumeRoutine
= RxCommonDevFCBIoCtl
;
2334 Status
= RxFsdPostRequest(Context
);
2338 DPRINT("Status: %lx\n", Status
);
2344 RxCommonDevFCBQueryVolInfo(
2345 PRX_CONTEXT Context
)
2348 return STATUS_NOT_IMPLEMENTED
;
2356 RxCommonDeviceControl(
2357 PRX_CONTEXT Context
)
2363 /* Prefix claim is only allowed for device, not files */
2364 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
2366 return STATUS_INVALID_DEVICE_REQUEST
;
2369 /* Submit to mini-rdr */
2370 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_IOCTL
);
2371 Status
= RxLowIoSubmit(Context
, RxLowIoIoCtlShellCompletion
);
2372 if (Status
== STATUS_PENDING
)
2374 RxDereferenceAndDeleteRxContext_Real(Context
);
2385 RxCommonDirectoryControl(
2386 PRX_CONTEXT Context
)
2391 PIO_STACK_LOCATION Stack
;
2395 Fcb
= (PFCB
)Context
->pFcb
;
2396 Fobx
= (PFOBX
)Context
->pFobx
;
2397 Stack
= Context
->CurrentIrpSp
;
2398 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context
, Fobx
, Fcb
, Stack
->MinorFunction
);
2400 /* Call the appropriate helper */
2401 if (Stack
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
)
2403 Status
= RxQueryDirectory(Context
);
2405 else if (Stack
->MinorFunction
== IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
2407 Status
= RxNotifyChangeDirectory(Context
);
2408 if (Status
== STATUS_PENDING
)
2410 RxDereferenceAndDeleteRxContext_Real(Context
);
2415 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2423 RxCommonDispatchProblem(
2424 PRX_CONTEXT Context
)
2427 return STATUS_NOT_IMPLEMENTED
;
2432 RxCommonFileSystemControl(
2433 PRX_CONTEXT Context
)
2436 return STATUS_NOT_IMPLEMENTED
;
2441 RxCommonFlushBuffers(
2442 PRX_CONTEXT Context
)
2445 return STATUS_NOT_IMPLEMENTED
;
2450 RxCommonLockControl(
2451 PRX_CONTEXT Context
)
2454 return STATUS_NOT_IMPLEMENTED
;
2460 PRX_CONTEXT Context
)
2463 return STATUS_NOT_IMPLEMENTED
;
2471 RxCommonQueryInformation(
2472 PRX_CONTEXT Context
)
2474 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
2475 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
2476 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
2483 PIO_STACK_LOCATION Stack
;
2484 FILE_INFORMATION_CLASS FileInfoClass
;
2488 Fcb
= (PFCB
)Context
->pFcb
;
2489 Fobx
= (PFOBX
)Context
->pFobx
;
2490 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2492 Irp
= Context
->CurrentIrp
;
2493 Stack
= Context
->CurrentIrpSp
;
2494 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp
->AssociatedIrp
.SystemBuffer
,
2495 Stack
->Parameters
.QueryFile
.Length
, Stack
->Parameters
.QueryFile
.FileInformationClass
);
2497 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2498 FileInfoClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
2505 /* Get a writable buffer */
2506 Buffer
= RxMapSystemBuffer(Context
);
2509 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2513 RtlZeroMemory(Buffer
, Context
->Info
.Length
);
2515 /* Validate file type */
2516 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
)
2518 if (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
2520 Status
= STATUS_INVALID_PARAMETER
;
2523 else if (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
)
2525 if (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
)
2527 Status
= STATUS_NOT_IMPLEMENTED
;
2531 Status
= STATUS_INVALID_PARAMETER
;
2538 /* Acquire the right lock */
2539 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
2540 FileInfoClass
!= FileNameInformation
)
2542 if (FileInfoClass
== FileCompressionInformation
)
2544 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
2548 Status
= RxAcquireSharedFcb(Context
, Fcb
);
2551 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2553 Status
= STATUS_PENDING
;
2556 else if (!NT_SUCCESS(Status
))
2564 /* Dispatch to the right helper */
2565 switch (FileInfoClass
)
2567 case FileBasicInformation
:
2568 Status
= RxQueryBasicInfo(Context
, Buffer
);
2571 case FileStandardInformation
:
2572 Status
= RxQueryStandardInfo(Context
, Buffer
);
2575 case FileInternalInformation
:
2576 Status
= RxQueryInternalInfo(Context
, Buffer
);
2579 case FileEaInformation
:
2580 Status
= RxQueryEaInfo(Context
, Buffer
);
2583 case FileNameInformation
:
2584 Status
= RxQueryNameInfo(Context
, Buffer
);
2587 case FileAllInformation
:
2588 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo
);
2589 if (!NT_SUCCESS(Status
))
2594 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
), RxQueryStandardInfo
);
2595 if (!NT_SUCCESS(Status
))
2600 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2601 sizeof(FILE_STANDARD_INFORMATION
), RxQueryInternalInfo
);
2602 if (!NT_SUCCESS(Status
))
2607 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2608 sizeof(FILE_STANDARD_INFORMATION
) +
2609 sizeof(FILE_INTERNAL_INFORMATION
), RxQueryEaInfo
);
2610 if (!NT_SUCCESS(Status
))
2615 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2616 sizeof(FILE_STANDARD_INFORMATION
) +
2617 sizeof(FILE_INTERNAL_INFORMATION
) +
2618 sizeof(FILE_EA_INFORMATION
), RxQueryPositionInfo
);
2619 if (!NT_SUCCESS(Status
))
2624 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2625 sizeof(FILE_STANDARD_INFORMATION
) +
2626 sizeof(FILE_INTERNAL_INFORMATION
) +
2627 sizeof(FILE_EA_INFORMATION
) +
2628 sizeof(FILE_POSITION_INFORMATION
), RxQueryNameInfo
);
2631 case FileAlternateNameInformation
:
2632 Status
= RxQueryAlternateNameInfo(Context
, Buffer
);
2635 case FilePipeInformation
:
2636 case FilePipeLocalInformation
:
2637 case FilePipeRemoteInformation
:
2638 Status
= RxQueryPipeInfo(Context
, Buffer
);
2641 case FileCompressionInformation
:
2642 Status
= RxQueryCompressedInfo(Context
, Buffer
);
2646 Context
->IoStatusBlock
.Status
= RxpQueryInfoMiniRdr(Context
, FileInfoClass
, Buffer
);
2647 Status
= Context
->IoStatusBlock
.Status
;
2651 if (Context
->Info
.Length
< 0)
2653 Status
= STATUS_BUFFER_OVERFLOW
;
2654 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2657 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryFile
.Length
- Context
->Info
.Length
;
2663 RxReleaseFcb(Context
, Fcb
);
2668 DPRINT("Status: %x\n", Status
);
2671 #undef SET_SIZE_AND_QUERY
2676 RxCommonQueryQuotaInformation(
2677 PRX_CONTEXT Context
)
2680 return STATUS_NOT_IMPLEMENTED
;
2685 RxCommonQuerySecurity(
2686 PRX_CONTEXT Context
)
2689 return STATUS_NOT_IMPLEMENTED
;
2697 RxCommonQueryVolumeInformation(
2698 PRX_CONTEXT Context
)
2704 PIO_STACK_LOCATION Stack
;
2708 Fcb
= (PFCB
)Context
->pFcb
;
2709 Fobx
= (PFOBX
)Context
->pFobx
;
2711 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2713 Irp
= Context
->CurrentIrp
;
2714 Stack
= Context
->CurrentIrpSp
;
2715 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack
->Parameters
.QueryVolume
.Length
,
2716 Stack
->Parameters
.QueryVolume
.FsInformationClass
, Irp
->AssociatedIrp
.SystemBuffer
);
2718 Context
->Info
.FsInformationClass
= Stack
->Parameters
.QueryVolume
.FsInformationClass
;
2719 Context
->Info
.Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2720 Context
->Info
.Length
= Stack
->Parameters
.QueryVolume
.Length
;
2722 /* Forward to mini-rdr */
2723 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxQueryVolumeInfo
, (Context
));
2725 /* Post request if mini-rdr asked to */
2726 if (Context
->PostRequest
)
2728 Status
= RxFsdPostRequest(Context
);
2732 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryVolume
.Length
- Context
->Info
.Length
;
2735 DPRINT("Status: %x\n", Status
);
2742 PRX_CONTEXT RxContext
)
2750 PFILE_OBJECT FileObject
;
2751 LARGE_INTEGER ByteOffset
;
2752 PIO_STACK_LOCATION Stack
;
2753 PLOWIO_CONTEXT LowIoContext
;
2754 PRDBSS_DEVICE_OBJECT RxDeviceObject
;
2755 ULONG ReadLength
, CapturedRxContextSerialNumber
= RxContext
->SerialNumber
;
2756 BOOLEAN CanWait
, PagingIo
, NoCache
, Sync
, PostRequest
, IsPipe
, ReadCachingEnabled
, ReadCachingDisabled
, InFsp
, OwnerSet
;
2760 Fcb
= (PFCB
)RxContext
->pFcb
;
2761 Fobx
= (PFOBX
)RxContext
->pFobx
;
2762 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext
, Fobx
, Fcb
);
2764 /* Get some parameters */
2765 Irp
= RxContext
->CurrentIrp
;
2766 Stack
= RxContext
->CurrentIrpSp
;
2767 CanWait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
2768 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
2769 NoCache
= BooleanFlagOn(Irp
->Flags
, IRP_NOCACHE
);
2770 Sync
= !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
2771 InFsp
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
);
2772 ReadLength
= Stack
->Parameters
.Read
.Length
;
2773 ByteOffset
.QuadPart
= Stack
->Parameters
.Read
.ByteOffset
.QuadPart
;
2774 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength
, ByteOffset
.QuadPart
,
2775 (CanWait
? "CW" : "!CW"), (PagingIo
? "PI" : "!PI"), (NoCache
? "NC" : "!NC"), (Sync
? "S" : "!S"));
2777 RxItsTheSameContext();
2779 Irp
->IoStatus
.Information
= 0;
2781 /* Should the read be loud - so far, it's just ignored on ReactOS:
2782 * s/DPRINT/DPRINT1/g will make it loud
2784 LowIoContext
= &RxContext
->LowIoContext
;
2785 CheckForLoudOperations(RxContext
);
2786 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
))
2788 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2789 ByteOffset
, ReadLength
,
2790 Fcb
, Fcb
->Header
.ValidDataLength
, Fcb
->Header
.FileSize
, Fcb
->Header
.AllocationSize
);
2793 RxDeviceObject
= RxContext
->RxDeviceObject
;
2795 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
) && Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
2797 InterlockedIncrement((volatile long *)&RxDeviceObject
->ReadOperations
);
2799 if (ByteOffset
.QuadPart
!= Fobx
->Specific
.DiskFile
.PredictedReadOffset
)
2801 InterlockedIncrement((volatile long *)&RxDeviceObject
->RandomReadOperations
);
2803 Fobx
->Specific
.DiskFile
.PredictedReadOffset
= ByteOffset
.QuadPart
+ ReadLength
;
2807 ExInterlockedAddLargeStatistic(&RxDeviceObject
->PagingReadBytesRequested
, ReadLength
);
2811 ExInterlockedAddLargeStatistic(&RxDeviceObject
->NonPagingReadBytesRequested
, ReadLength
);
2815 ExInterlockedAddLargeStatistic(&RxDeviceObject
->CacheReadBytesRequested
, ReadLength
);
2819 /* A pagefile cannot be a pipe */
2820 IsPipe
= Fcb
->NetRoot
->Type
== NET_ROOT_PIPE
;
2821 if (IsPipe
&& PagingIo
)
2823 return STATUS_INVALID_DEVICE_REQUEST
;
2826 /* Null-length read is no-op */
2827 if (ReadLength
== 0)
2829 return STATUS_SUCCESS
;
2832 /* Validate FCB type */
2833 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&& NodeType(Fcb
) != RDBSS_NTC_VOLUME_FCB
)
2835 return STATUS_INVALID_DEVICE_REQUEST
;
2838 /* Init the lowio context for possible forward */
2839 RxInitializeLowIoContext(LowIoContext
, LOWIO_OP_READ
);
2841 PostRequest
= FALSE
;
2842 ReadCachingDisabled
= FALSE
;
2844 ReadCachingEnabled
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2845 FileObject
= Stack
->FileObject
;
2846 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
2851 /* If no caching, make sure current Cc data have been flushed */
2852 if (!PagingIo
&& NoCache
&& !ReadCachingEnabled
&& FileObject
->SectionObjectPointer
!= NULL
)
2854 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
2855 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2860 else if (Status
!= STATUS_SUCCESS
)
2865 ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, TRUE
);
2866 CcFlushCache(FileObject
->SectionObjectPointer
, &ByteOffset
, ReadLength
, &Irp
->IoStatus
);
2867 RxReleasePagingIoResource(RxContext
, Fcb
);
2869 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
2874 RxAcquirePagingIoResource(RxContext
, Fcb
);
2875 RxReleasePagingIoResource(RxContext
, Fcb
);
2878 /* Acquire the appropriate lock */
2879 if (PagingIo
&& !ReadCachingEnabled
)
2883 if (!ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, CanWait
))
2891 LowIoContext
->Resource
= Fcb
->Header
.PagingIoResource
;
2896 if (!ReadCachingEnabled
)
2898 if (!CanWait
&& NoCache
)
2900 Status
= RxAcquireSharedFcbWaitForEx(RxContext
, Fcb
);
2901 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2903 DPRINT1("RdAsyLNG %x\n", RxContext
);
2907 if (Status
!= STATUS_SUCCESS
)
2909 DPRINT1("RdAsyOthr %x\n", RxContext
);
2913 if (RxIsFcbAcquiredShared(Fcb
) <= 0xF000)
2915 LowIoContext
->Resource
= Fcb
->Header
.Resource
;
2925 Status
= RxAcquireSharedFcb(RxContext
, Fcb
);
2926 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2931 else if (Status
!= STATUS_SUCCESS
)
2939 RxItsTheSameContext();
2941 ReadCachingDisabled
= (ReadCachingEnabled
== FALSE
);
2947 RxGetFileSizeWithLock(Fcb
, &FileSize
);
2949 /* Make sure FLOCK doesn't conflict */
2952 if (!FsRtlCheckLockForReadAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
2954 Status
= STATUS_FILE_LOCK_CONFLICT
;
2959 /* Validate byteoffset vs length */
2960 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
2962 if (ByteOffset
.QuadPart
>= FileSize
)
2964 Status
= STATUS_END_OF_FILE
;
2968 if (ReadLength
> FileSize
- ByteOffset
.QuadPart
)
2970 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
2975 if (!PagingIo
&& !NoCache
&& ReadCachingEnabled
&&
2976 !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
))
2978 /* File was not cached yet, do it */
2979 if (FileObject
->PrivateCacheMap
== NULL
)
2981 if (BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
))
2983 Status
= STATUS_FILE_CLOSED
;
2987 RxAdjustAllocationSizeforCC(Fcb
);
2989 CcInitializeCacheMap(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
2990 FALSE
, &RxData
.CacheManagerCallbacks
, Fcb
);
2992 if (BooleanFlagOn(Fcb
->MRxDispatch
->MRxFlags
, RDBSS_NO_DEFERRED_CACHE_READAHEAD
))
2994 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
2998 CcSetAdditionalCacheAttributes(FileObject
, TRUE
, FALSE
);
2999 SetFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3002 CcSetReadAheadGranularity(FileObject
, NetRoot
->DiskParameters
.ReadAheadGranularity
);
3005 /* This should never happen - fix your RDR */
3006 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
3011 CcMdlRead(FileObject
, &ByteOffset
, ReadLength
, &Irp
->MdlAddress
, &Irp
->IoStatus
);
3012 Status
= Irp
->IoStatus
.Status
;
3013 ASSERT(NT_SUCCESS(Status
));
3018 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3019 if (SystemBuffer
== NULL
)
3021 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3025 SetFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3027 RxItsTheSameContext();
3029 /* Perform the read */
3030 if (!CcCopyRead(FileObject
, &ByteOffset
, ReadLength
, CanWait
, SystemBuffer
, &Irp
->IoStatus
))
3032 if (!ReadCachingEnabled
)
3034 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3037 RxItsTheSameContext();
3043 if (!ReadCachingEnabled
)
3045 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3048 Status
= Irp
->IoStatus
.Status
;
3049 ASSERT(NT_SUCCESS(Status
));
3054 /* Validate the reading */
3055 if (FileObject
->PrivateCacheMap
!= NULL
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) &&
3056 ByteOffset
.QuadPart
>= 4096)
3058 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
3059 ClearFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
3062 /* If it's consistent, forward to mini-rdr */
3063 if (Fcb
->CachedNetRootType
!= NET_ROOT_DISK
|| BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) ||
3064 ByteOffset
.QuadPart
< Fcb
->Header
.ValidDataLength
.QuadPart
)
3066 LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
= ReadLength
;
3067 LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
= ByteOffset
.QuadPart
;
3069 RxItsTheSameContext();
3071 if (InFsp
&& ReadCachingDisabled
)
3073 ExSetResourceOwnerPointer((PagingIo
? Fcb
->Header
.PagingIoResource
: Fcb
->Header
.Resource
),
3074 (PVOID
)((ULONG_PTR
)RxContext
| 3));
3078 Status
= RxLowIoReadShell(RxContext
);
3080 RxItsTheSameContext();
3084 if (ByteOffset
.QuadPart
> FileSize
)
3087 Irp
->IoStatus
.Information
= ReadLength
;
3091 if (ByteOffset
.QuadPart
+ ReadLength
> FileSize
)
3093 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
3096 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
3097 RtlZeroMemory(SystemBuffer
, ReadLength
);
3098 Irp
->IoStatus
.Information
= ReadLength
;
3104 RxItsTheSameContext();
3106 /* Post if required */
3109 InterlockedIncrement((volatile long *)&RxContext
->ReferenceCount
);
3110 Status
= RxFsdPostRequest(RxContext
);
3114 /* Update FO in case of sync IO */
3115 if (!IsPipe
&& !PagingIo
)
3117 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
3119 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
3124 /* Set FastIo if read was a success */
3125 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
3127 if (!IsPipe
&& !PagingIo
)
3129 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
3133 /* In case we're done (not expected any further processing */
3134 if (_SEH2_AbnormalTermination() || Status
!= STATUS_PENDING
|| PostRequest
)
3136 /* Release everything that can be */
3137 if (ReadCachingDisabled
)
3143 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3147 RxReleasePagingIoResource(RxContext
, Fcb
);
3154 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
3158 RxReleaseFcb(RxContext
, Fcb
);
3163 /* Dereference/Delete context */
3166 RxDereferenceAndDeleteRxContext(RxContext
);
3170 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
3172 RxResumeBlockedOperations_Serially(RxContext
, &Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
3176 /* We cannot return more than asked */
3177 if (Status
== STATUS_SUCCESS
)
3179 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
3186 RxDereferenceAndDeleteRxContext(RxContext
);
3197 PRX_CONTEXT Context
)
3200 return STATUS_NOT_IMPLEMENTED
;
3205 RxCommonSetInformation(
3206 PRX_CONTEXT Context
)
3209 return STATUS_NOT_IMPLEMENTED
;
3214 RxCommonSetQuotaInformation(
3215 PRX_CONTEXT Context
)
3218 return STATUS_NOT_IMPLEMENTED
;
3223 RxCommonSetSecurity(
3224 PRX_CONTEXT Context
)
3227 return STATUS_NOT_IMPLEMENTED
;
3232 RxCommonSetVolumeInformation(
3233 PRX_CONTEXT Context
)
3236 return STATUS_NOT_IMPLEMENTED
;
3241 RxCommonUnimplemented(
3242 PRX_CONTEXT Context
)
3245 return STATUS_NOT_IMPLEMENTED
;
3251 PRX_CONTEXT Context
)
3254 return STATUS_NOT_IMPLEMENTED
;
3260 IN PRX_CONTEXT RxContext
)
3265 return STATUS_NOT_IMPLEMENTED
;
3272 RxCopyCreateParameters(
3273 IN PRX_CONTEXT RxContext
)
3277 PFILE_OBJECT FileObject
;
3278 PIO_STACK_LOCATION Stack
;
3279 PDFS_NAME_CONTEXT DfsNameContext
;
3280 PIO_SECURITY_CONTEXT SecurityContext
;
3282 Irp
= RxContext
->CurrentIrp
;
3283 Stack
= RxContext
->CurrentIrpSp
;
3284 FileObject
= Stack
->FileObject
;
3285 SecurityContext
= Stack
->Parameters
.Create
.SecurityContext
;
3287 RxContext
->Create
.NtCreateParameters
.SecurityContext
= SecurityContext
;
3288 if (SecurityContext
->AccessState
!= NULL
&& SecurityContext
->AccessState
->SecurityDescriptor
!= NULL
)
3290 RxContext
->Create
.SdLength
= RtlLengthSecurityDescriptor(SecurityContext
->AccessState
->SecurityDescriptor
);
3291 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext
->Create
.NtCreateParameters
.SecurityContext
,
3292 RxContext
->Create
.SdLength
);
3294 if (SecurityContext
->SecurityQos
!= NULL
)
3296 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityContext
->SecurityQos
->ImpersonationLevel
;
3300 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityImpersonation
;
3302 RxContext
->Create
.NtCreateParameters
.DesiredAccess
= SecurityContext
->DesiredAccess
;
3304 RxContext
->Create
.NtCreateParameters
.AllocationSize
.QuadPart
= Irp
->Overlay
.AllocationSize
.QuadPart
;
3305 RxContext
->Create
.NtCreateParameters
.FileAttributes
= Stack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
;
3306 RxContext
->Create
.NtCreateParameters
.ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
3307 RxContext
->Create
.NtCreateParameters
.Disposition
= (Stack
->Parameters
.Create
.Options
>> 24) & 0x000000FF;
3308 RxContext
->Create
.NtCreateParameters
.CreateOptions
= Stack
->Parameters
.Create
.Options
& 0xFFFFFF;
3310 DfsContext
= FileObject
->FsContext2
;
3311 DfsNameContext
= FileObject
->FsContext
;
3312 RxContext
->Create
.NtCreateParameters
.DfsContext
= DfsContext
;
3313 RxContext
->Create
.NtCreateParameters
.DfsNameContext
= DfsNameContext
;
3314 ASSERT(DfsContext
== NULL
|| DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) ||
3315 DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) ||
3316 DfsContext
== UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT
) ||
3317 DfsContext
== UIntToPtr(DFS_USER_NAME_CONTEXT
));
3318 ASSERT(DfsNameContext
== NULL
|| DfsNameContext
->NameContextType
== DFS_OPEN_CONTEXT
||
3319 DfsNameContext
->NameContextType
== DFS_DOWNLEVEL_OPEN_CONTEXT
||
3320 DfsNameContext
->NameContextType
== DFS_CSCAGENT_NAME_CONTEXT
||
3321 DfsNameContext
->NameContextType
== DFS_USER_NAME_CONTEXT
);
3322 FileObject
->FsContext2
= NULL
;
3323 FileObject
->FsContext
= NULL
;
3325 RxContext
->pFcb
= NULL
;
3326 RxContext
->Create
.ReturnedCreateInformation
= 0;
3328 /* if we stripped last \, it has to be a directory! */
3329 if (BooleanFlagOn(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
))
3331 SetFlag(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DIRECTORY_FILE
);
3334 RxContext
->Create
.EaLength
= Stack
->Parameters
.Create
.EaLength
;
3335 if (RxContext
->Create
.EaLength
== 0)
3337 RxContext
->Create
.EaBuffer
= NULL
;
3341 RxContext
->Create
.EaBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
3342 DPRINT("EA Buffer: %p, Length: %lx\n", Irp
->AssociatedIrp
.SystemBuffer
, RxContext
->Create
.EaLength
);
3347 RxCreateFromNetRoot(
3348 PRX_CONTEXT Context
,
3349 PUNICODE_STRING NetRootName
)
3354 PFILE_OBJECT FileObject
;
3355 PIO_STACK_LOCATION Stack
;
3356 ACCESS_MASK DesiredAccess
;
3357 USHORT DesiredShareAccess
;
3361 /* Validate that the context is consistent */
3362 if (Context
->Create
.pNetRoot
== NULL
)
3364 return STATUS_BAD_NETWORK_PATH
;
3367 NetRoot
= (PNET_ROOT
)Context
->Create
.pNetRoot
;
3368 if (Context
->RxDeviceObject
!= NetRoot
->pSrvCall
->RxDeviceObject
)
3370 return STATUS_BAD_NETWORK_PATH
;
3373 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) &&
3374 !BooleanFlagOn(NetRoot
->pSrvCall
->Flags
, SRVCALL_FLAG_DFS_AWARE_SERVER
))
3376 return STATUS_DFS_UNAVAILABLE
;
3379 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
3380 BooleanFlagOn(NetRoot
->Flags
, NETROOT_FLAG_DFS_AWARE_NETROOT
))
3382 return STATUS_OBJECT_TYPE_MISMATCH
;
3385 Stack
= Context
->CurrentIrpSp
;
3386 DesiredShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
3387 if (NetRoot
->Type
== NET_ROOT_PRINT
)
3389 DesiredShareAccess
= FILE_SHARE_VALID_FLAGS
;
3392 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
3394 /* We don't support renaming yet */
3395 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
3398 return STATUS_NOT_IMPLEMENTED
;
3401 /* Try to find (or create) the FCB for the file */
3402 Status
= RxFindOrCreateFcb(Context
, NetRootName
);
3403 Fcb
= (PFCB
)Context
->pFcb
;
3406 ASSERT(!NT_SUCCESS(Status
));
3408 if (!NT_SUCCESS(Status
) || Fcb
== NULL
)
3413 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_CREATE_MAILSLOT
))
3415 Fcb
->Header
.NodeTypeCode
= RDBSS_NTC_MAILSLOT
;
3419 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
3422 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
3423 if (NT_SUCCESS(Status
))
3425 RxTransitionNetFcb(Fcb
, Condition_Good
);
3426 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb
, Fcb
->Condition
);
3428 RxSetupNetFileObject(Context
);
3429 return STATUS_SUCCESS
;
3433 FileObject
= Stack
->FileObject
;
3434 /* Check SA for conflict */
3435 if (Fcb
->OpenCount
> 0)
3437 Status
= RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
3438 &Fcb
->ShareAccess
, FALSE
, "early check per useropens", "EarlyPerUO");
3439 if (!NT_SUCCESS(Status
))
3441 RxDereferenceNetFcb(Fcb
);
3446 if (BooleanFlagOn(Context
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
) &&
3447 !BooleanFlagOn(Context
->Create
.NtCreateParameters
.DesiredAccess
, ~SYNCHRONIZE
))
3454 /* Find a SRV_OPEN that suits the opening */
3455 Status
= RxCollapseOrCreateSrvOpen(Context
);
3456 if (Status
== STATUS_SUCCESS
)
3461 SrvOpen
= (PSRV_OPEN
)Context
->pRelevantSrvOpen
;
3462 Fobx
= (PFOBX
)Context
->pFobx
;
3463 /* There are already opens, check for conflict */
3464 if (Fcb
->OpenCount
!= 0)
3466 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
,
3467 FileObject
, &Fcb
->ShareAccess
,
3468 FALSE
, "second check per useropens",
3471 ++SrvOpen
->UncleanFobxCount
;
3472 RxDereferenceNetFobx(Fobx
, LHS_LockNotHeld
);
3479 if (NetRoot
->Type
!= NET_ROOT_PIPE
)
3481 RxSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
3482 &Fcb
->ShareAccess
, "initial shareaccess setup", "InitShrAcc");
3486 RxSetupNetFileObject(Context
);
3488 /* No conflict? Set up SA */
3489 if (Fcb
->OpenCount
!= 0 && NetRoot
->Type
!= NET_ROOT_PIPE
)
3491 RxUpdateShareAccess(FileObject
, &Fcb
->ShareAccess
, "update share access", "UpdShrAcc");
3494 ++Fcb
->UncleanCount
;
3495 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
3497 ++Fcb
->UncachedUncleanCount
;
3500 if (SrvOpen
->UncleanFobxCount
== 0 && Fcb
->UncleanCount
== 1 &&
3501 !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE
))
3503 RxChangeBufferingState(SrvOpen
, NULL
, FALSE
);
3506 /* No pending close, we're active */
3507 ClearFlag(Fcb
->FcbState
, FCB_STATE_DELAY_CLOSE
);
3510 ++SrvOpen
->UncleanFobxCount
;
3511 ++SrvOpen
->OpenCount
;
3512 SrvOpen
->ulFileSizeVersion
= Fcb
->ulFileSizeVersion
;
3514 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NO_INTERMEDIATE_BUFFERING
))
3516 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
);
3517 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
);
3519 ClearFlag(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
);
3520 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
3522 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, TRUE
, TRUE
);
3525 /* Now, update SA for the SRV_OPEN */
3526 RxUpdateShareAccessPerSrvOpens(SrvOpen
);
3528 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
3530 SetFlag(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
);
3533 /* Update the FOBX info */
3536 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
3538 SetFlag(FileObject
->Flags
, FO_NAMED_PIPE
);
3541 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PRINT
||
3542 Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
3544 Fobx
->PipeHandleInformation
= &Fobx
->Specific
.NamedPipe
.PipeHandleInformation
;
3546 Fobx
->Specific
.NamedPipe
.CollectDataTime
.QuadPart
= 0;
3547 Fobx
->Specific
.NamedPipe
.CollectDataSize
= Context
->Create
.pNetRoot
->NamedPipeParameters
.DataCollectionSize
;
3549 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.TypeOfPipe
= Context
->Create
.PipeType
;
3550 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.ReadMode
= Context
->Create
.PipeReadMode
;
3551 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.CompletionMode
= Context
->Create
.PipeCompletionMode
;
3553 InitializeListHead(&Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
3554 InitializeListHead(&Fobx
->Specific
.NamedPipe
.WriteSerializationQueue
);
3558 Status
= STATUS_SUCCESS
;
3563 if (Fcb
->OpenCount
== 0)
3565 if (Context
->Create
.FcbAcquired
)
3567 Context
->Create
.FcbAcquired
= (RxDereferenceAndFinalizeNetFcb(Fcb
,
3571 if (!Context
->Create
.FcbAcquired
)
3573 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
3579 RxDereferenceNetFcb(Fcb
);
3591 RxCreateTreeConnect(
3592 IN PRX_CONTEXT RxContext
)
3595 PV_NET_ROOT VNetRoot
;
3596 PFILE_OBJECT FileObject
;
3597 PIO_STACK_LOCATION Stack
;
3598 NET_ROOT_TYPE NetRootType
;
3599 UNICODE_STRING CanonicalName
, RemainingName
;
3603 Stack
= RxContext
->CurrentIrpSp
;
3604 FileObject
= Stack
->FileObject
;
3606 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
3607 /* As long as we don't know connection type, mark it wild */
3608 NetRootType
= NET_ROOT_WILD
;
3609 /* Get the type by parsing the name */
3610 Status
= RxFirstCanonicalize(RxContext
, &FileObject
->FileName
, &CanonicalName
, &NetRootType
);
3611 if (!NT_SUCCESS(Status
))
3616 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
3617 RxContext
->Create
.TreeConnectOpenDeferred
= FALSE
;
3618 RtlInitEmptyUnicodeString(&RxContext
->Create
.TransportName
, NULL
, 0);
3619 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserName
, NULL
, 0);
3620 RtlInitEmptyUnicodeString(&RxContext
->Create
.Password
, NULL
, 0);
3621 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserDomainName
, NULL
, 0);
3623 /* We don't handle EA - they come from DFS, don't care */
3624 if (Stack
->Parameters
.Create
.EaLength
> 0)
3629 /* Mount if required */
3630 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3631 if (Status
== STATUS_NETWORK_CREDENTIAL_CONFLICT
)
3633 RxScavengeVNetRoots(RxContext
->RxDeviceObject
);
3634 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3637 if (!NT_SUCCESS(Status
))
3642 /* Validate the rest of the name with mini-rdr */
3643 if (RemainingName
.Length
> 0)
3645 MINIRDR_CALL(Status
, RxContext
,
3646 RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
3647 MRxIsValidDirectory
, (RxContext
, &RemainingName
));
3650 if (!NT_SUCCESS(Status
))
3655 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
3656 RxReferenceVNetRoot(VNetRoot
);
3657 if (InterlockedCompareExchange(&VNetRoot
->AdditionalReferenceForDeleteFsctlTaken
, 1, 0) != 0)
3659 RxDereferenceVNetRoot(VNetRoot
, LHS_LockNotHeld
);
3662 FileObject
->FsContext
= &RxDeviceFCB
;
3663 FileObject
->FsContext2
= VNetRoot
;
3665 VNetRoot
->ConstructionStatus
= STATUS_SUCCESS
;
3666 ++VNetRoot
->NumberOfOpens
;
3668 /* Create is over - clear context */
3669 RxContext
->Create
.pSrvCall
= NULL
;
3670 RxContext
->Create
.pNetRoot
= NULL
;
3671 RxContext
->Create
.pVNetRoot
= NULL
;
3678 RxDebugControlCommand(
3679 _In_ PSTR ControlString
)
3687 IN PDRIVER_OBJECT DriverObject
,
3688 IN PUNICODE_STRING RegistryPath
)
3691 USHORT i
, State
= 0;
3693 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject
, RegistryPath
);
3697 RxCheckFcbStructuresForAlignment();
3699 RtlZeroMemory(&RxData
, sizeof(RxData
));
3700 RxData
.NodeTypeCode
= RDBSS_NTC_DATA_HEADER
;
3701 RxData
.NodeByteSize
= sizeof(RxData
);
3702 RxData
.DriverObject
= DriverObject
;
3704 RtlZeroMemory(&RxDeviceFCB
, sizeof(RxDeviceFCB
));
3705 RxDeviceFCB
.spacer
.NodeTypeCode
= RDBSS_NTC_DEVICE_FCB
;
3706 RxDeviceFCB
.spacer
.NodeByteSize
= sizeof(RxDeviceFCB
);
3708 KeInitializeSpinLock(&RxStrucSupSpinLock
);
3709 RxExports
.pRxStrucSupSpinLock
= &RxStrucSupSpinLock
;
3711 RxInitializeDebugSupport();
3713 RxFileSystemDeviceObject
= (PRDBSS_DEVICE_OBJECT
)&RxSpaceForTheWrappersDeviceObject
;
3714 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject
, sizeof(RxSpaceForTheWrappersDeviceObject
));
3719 RxGetRegistryParameters(RegistryPath
);
3720 RxReadRegistryParameters();
3722 Status
= RxInitializeRegistrationStructures();
3723 if (!NT_SUCCESS(Status
))
3729 RxInitializeDispatcher();
3731 ExInitializeNPagedLookasideList(&RxContextLookasideList
, RxAllocatePoolWithTag
, RxFreePool
, 0, sizeof(RX_CONTEXT
), RX_IRPC_POOLTAG
, 4);
3733 InitializeListHead(&RxIrpsList
);
3734 KeInitializeSpinLock(&RxIrpsListSpinLock
);
3736 InitializeListHead(&RxActiveContexts
);
3737 InitializeListHead(&RxSrvCalldownList
);
3739 ExInitializeFastMutex(&RxContextPerFileSerializationMutex
);
3740 ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex
);
3741 KeInitializeMutex(&RxScavengerMutex
, 1);
3742 KeInitializeMutex(&RxSerializationMutex
, 1);
3744 for (i
= 0; i
< RxMaximumWorkQueue
; ++i
)
3746 RxFileSystemDeviceObject
->PostedRequestCount
[i
] = 0;
3747 RxFileSystemDeviceObject
->OverflowQueueCount
[i
] = 0;
3748 InitializeListHead(&RxFileSystemDeviceObject
->OverflowQueue
[i
]);
3751 KeInitializeSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
);
3753 RxInitializeDispatchVectors(DriverObject
);
3755 ExInitializeResourceLite(&RxData
.Resource
);
3756 RxData
.OurProcess
= IoGetCurrentProcess();
3758 RxInitializeRxTimer();
3762 if (!NT_SUCCESS(Status
))
3764 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BC4, Status
);
3765 RxInitUnwind(DriverObject
, State
);
3769 /* There are still bits to init - be consider it's fine for now */
3772 return STATUS_NOT_IMPLEMENTED
;
3774 return STATUS_SUCCESS
;
3782 RxDumpCurrentAccess(
3785 _In_ PSZ wherelogtag
,
3786 _In_ PSHARE_ACCESS ShareAccess
)
3798 _In_ PSZ wherelogtag
,
3799 _In_ ACCESS_MASK DesiredAccess
,
3800 _In_ ULONG DesiredShareAccess
)
3807 RxFastIoCheckIfPossible(
3808 PFILE_OBJECT FileObject
,
3809 PLARGE_INTEGER FileOffset
,
3810 ULONG Length
, BOOLEAN Wait
,
3811 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
3812 PIO_STATUS_BLOCK IoStatus
,
3813 PDEVICE_OBJECT DeviceObject
)
3820 /* Get the FCB to validate it */
3821 Fcb
= FileObject
->FsContext
;
3822 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
)
3824 DPRINT1("Not a file, FastIO not possible!\n");
3828 if (FileObject
->DeletePending
)
3830 DPRINT1("File delete pending\n");
3834 /* If there's a pending write operation, deny fast operation */
3835 if (Fcb
->NonPaged
->OutstandingAsyncWrites
!= 0)
3837 DPRINT1("Write operations to be completed\n");
3841 /* Deny read on orphaned node */
3842 SrvOpen
= (PSRV_OPEN
)((PFOBX
)FileObject
->FsContext2
)->pSrvOpen
;
3843 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
3845 DPRINT1("SRV_OPEN orphaned\n");
3849 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
3851 DPRINT1("FCB orphaned\n");
3855 /* If there's a buffering state change pending, deny fast operation (it might change
3858 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING
))
3860 DPRINT1("Buffering change pending\n");
3864 /* File got renamed/deleted, deny operation */
3865 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_DELETED
) ||
3866 BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_FILE_RENAMED
))
3868 DPRINT1("File renamed/deleted\n");
3872 /* Process pending change buffering state operations */
3873 FsRtlEnterFileSystem();
3874 RxProcessChangeBufferingStateRequestsForSrvOpen(SrvOpen
);
3875 FsRtlExitFileSystem();
3877 /* If operation to come is a read operation */
3878 if (CheckForReadOperation
)
3880 LARGE_INTEGER LargeLength
;
3882 /* Check that read cache is enabled */
3883 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
3885 DPRINT1("Read caching disabled\n");
3889 /* Check whether there's a lock conflict */
3890 LargeLength
.QuadPart
= Length
;
3891 if (!FsRtlFastCheckLockForRead(&Fcb
->Specific
.Fcb
.FileLock
,
3896 PsGetCurrentProcess()))
3898 DPRINT1("FsRtlFastCheckLockForRead failed\n");
3911 RxFastIoDeviceControl(
3912 PFILE_OBJECT FileObject
,
3914 PVOID InputBuffer OPTIONAL
,
3915 ULONG InputBufferLength
,
3916 PVOID OutputBuffer OPTIONAL
,
3917 ULONG OutputBufferLength
,
3918 ULONG IoControlCode
,
3919 PIO_STATUS_BLOCK IoStatus
,
3920 PDEVICE_OBJECT DeviceObject
)
3922 /* Only supported IOCTL */
3923 if (IoControlCode
== IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
)
3940 PFILE_OBJECT FileObject
,
3941 PLARGE_INTEGER FileOffset
,
3946 PIO_STATUS_BLOCK IoStatus
,
3947 PDEVICE_OBJECT DeviceObject
)
3950 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
3954 DPRINT("RxFastIoRead: %p (%p, %p)\n", FileObject
, FileObject
->FsContext
,
3955 FileObject
->FsContext2
);
3956 DPRINT("Reading %ld at %I64x\n", Length
, FileOffset
->QuadPart
);
3958 /* Prepare a TLI context */
3959 ASSERT(RxIsThisTheTopLevelIrp(NULL
));
3960 RxInitializeTopLevelIrpContext(&TopLevelContext
, (PIRP
)FSRTL_FAST_IO_TOP_LEVEL_IRP
,
3961 (PRDBSS_DEVICE_OBJECT
)DeviceObject
);
3963 Ret
= FsRtlCopyRead2(FileObject
, FileOffset
, Length
, Wait
, LockKey
, Buffer
,
3964 IoStatus
, DeviceObject
, &TopLevelContext
);
3967 DPRINT("Read OK\n");
3971 DPRINT1("Read failed!\n");
3980 PFILE_OBJECT FileObject
,
3981 PLARGE_INTEGER FileOffset
,
3986 PIO_STATUS_BLOCK IoStatus
,
3987 PDEVICE_OBJECT DeviceObject
)
3995 PRX_CONTEXT RxContext
,
3996 PUNICODE_STRING NetRootName
)
4002 PV_NET_ROOT VNetRoot
;
4003 BOOLEAN TableAcquired
, AcquiredExclusive
;
4007 NetRoot
= (PNET_ROOT
)RxContext
->Create
.pNetRoot
;
4008 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
4009 ASSERT(NetRoot
== VNetRoot
->NetRoot
);
4011 Status
= STATUS_SUCCESS
;
4012 AcquiredExclusive
= FALSE
;
4014 RxAcquireFcbTableLockShared(&NetRoot
->FcbTable
, TRUE
);
4015 TableAcquired
= TRUE
;
4016 Version
= NetRoot
->FcbTable
.Version
;
4018 /* Look for a cached FCB */
4019 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4022 DPRINT("RxFcbTableLookupFcb returned NULL fcb for %wZ\n", NetRootName
);
4026 DPRINT("FCB found for %wZ\n", &Fcb
->FcbTableEntry
.Path
);
4027 /* If FCB was to be orphaned, consider it as not suitable */
4028 if (Fcb
->fShouldBeOrphaned
)
4030 RxDereferenceNetFcb(Fcb
);
4031 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4033 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
4034 TableAcquired
= TRUE
;
4035 AcquiredExclusive
= TRUE
;
4037 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4038 if (Fcb
!= NULL
&& Fcb
->fShouldBeOrphaned
)
4040 RxOrphanThisFcb(Fcb
);
4041 RxDereferenceNetFcb(Fcb
);
4047 /* If FCB was not found or is not covering full path, prepare for more work */
4048 if (Fcb
== NULL
|| Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
4050 if (!AcquiredExclusive
)
4052 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4053 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
4054 TableAcquired
= TRUE
;
4057 /* If FCB table was updated in between, re-attempt a lookup */
4058 if (NetRoot
->FcbTable
.Version
!= Version
)
4060 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
4061 if (Fcb
!= NULL
&& Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
4068 /* Allocate the FCB */
4073 Fcb
= RxCreateNetFcb(RxContext
, VNetRoot
, NetRootName
);
4076 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4080 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4081 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
4087 if (_SEH2_AbnormalTermination())
4089 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4090 TableAcquired
= FALSE
;
4094 RxTransitionNetFcb(Fcb
, Condition_Bad
);
4096 ExAcquireResourceExclusiveLite(Fcb
->Header
.Resource
, TRUE
);
4097 if (RxDereferenceAndFinalizeNetFcb(Fcb
, NULL
, FALSE
, FALSE
) != 0)
4099 ExReleaseResourceLite(Fcb
->Header
.Resource
);
4108 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
4111 if (!NT_SUCCESS(Status
))
4116 RxContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
4117 DPRINT("FCB %p is in condition %lx\n", Fcb
, Fcb
->Condition
);
4119 if (!RxContext
->Create
.FcbAcquired
)
4121 RxWaitForStableNetFcb(Fcb
, RxContext
);
4122 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
4123 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
4130 RxFirstCanonicalize(
4131 PRX_CONTEXT RxContext
,
4132 PUNICODE_STRING FileName
,
4133 PUNICODE_STRING CanonicalName
,
4134 PNET_ROOT_TYPE NetRootType
)
4138 BOOLEAN UncName
, PrependString
, IsSpecial
;
4139 USHORT CanonicalLength
;
4140 UNICODE_STRING SessionIdString
;
4141 WCHAR SessionIdBuffer
[16];
4145 Type
= NET_ROOT_WILD
;
4146 PrependString
= FALSE
;
4149 Status
= STATUS_SUCCESS
;
4151 /* Name has to contain at least \\ */
4152 if (FileName
->Length
< 2 * sizeof(WCHAR
))
4154 return STATUS_OBJECT_NAME_INVALID
;
4157 /* First easy check, is that a path with a name? */
4158 CanonicalLength
= FileName
->Length
;
4159 if (FileName
->Length
> 5 * sizeof(WCHAR
))
4161 if (FileName
->Buffer
[0] == '\\' && FileName
->Buffer
[1] == ';')
4163 if (FileName
->Buffer
[3] == ':')
4165 Type
= NET_ROOT_DISK
;
4169 Type
= NET_ROOT_PRINT
;
4174 /* Nope, attempt deeper parsing */
4175 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
&& FileName
->Buffer
[1] != ';')
4178 PWSTR FirstSlash
, EndOfString
;
4180 SetFlag(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_UNC_NAME
);
4183 /* The lack of drive letter will be replaced by session ID */
4184 SessionId
= RxGetSessionId(RxContext
->CurrentIrpSp
);
4185 RtlInitEmptyUnicodeString(&SessionIdString
, SessionIdBuffer
, sizeof(SessionIdBuffer
));
4186 RtlIntegerToUnicodeString(SessionId
, 10, &SessionIdString
);
4188 EndOfString
= Add2Ptr(FileName
->Buffer
, FileName
->Length
);
4189 for (FirstSlash
= &FileName
->Buffer
[1]; FirstSlash
!= EndOfString
; ++FirstSlash
)
4191 if (*FirstSlash
== OBJ_NAME_PATH_SEPARATOR
)
4197 if (EndOfString
- FirstSlash
<= sizeof(WCHAR
))
4199 Status
= STATUS_OBJECT_NAME_INVALID
;
4204 DPRINT1("WARNING: Assuming not special + disk!\n");
4205 Type
= NET_ROOT_DISK
;
4206 Status
= STATUS_SUCCESS
;
4207 //Status = STATUS_NOT_IMPLEMENTED;
4208 /* Should be check against IPC, mailslot, and so on */
4212 /* Update net root type with our deduced one */
4213 *NetRootType
= Type
;
4214 DPRINT("Returning type: %x\n", Type
);
4216 if (!NT_SUCCESS(Status
))
4221 /* Do we have to prepend session ID? */
4226 PrependString
= TRUE
;
4227 CanonicalLength
+= SessionIdString
.Length
+ 3 * sizeof(WCHAR
);
4231 /* If not UNC path, we should preprend stuff */
4232 if (!PrependString
&& !IsSpecial
&& FileName
->Buffer
[0] != '\\')
4234 return STATUS_OBJECT_PATH_INVALID
;
4237 /* Allocate the buffer */
4238 Status
= RxAllocateCanonicalNameBuffer(RxContext
, CanonicalName
, CanonicalLength
);
4239 if (!NT_SUCCESS(Status
))
4244 /* We don't support that case, we always return disk */
4247 ASSERT(CanonicalName
->Length
== CanonicalLength
);
4249 Status
= STATUS_NOT_IMPLEMENTED
;
4253 /* If we have to prepend, go ahead */
4256 CanonicalName
->Buffer
[0] = '\\';
4257 CanonicalName
->Buffer
[1] = ';';
4258 CanonicalName
->Buffer
[2] = ':';
4259 CanonicalName
->Length
= 3 * sizeof(WCHAR
);
4260 RtlAppendUnicodeStringToString(CanonicalName
, &SessionIdString
);
4261 RtlAppendUnicodeStringToString(CanonicalName
, FileName
);
4263 DPRINT1("CanonicalName: %wZ\n", CanonicalName
);
4265 /* Otherwise, that's a simple copy */
4268 RtlCopyUnicodeString(CanonicalName
, FileName
);
4279 RxFreeCanonicalNameBuffer(
4280 PRX_CONTEXT Context
)
4282 /* These two buffers are always the same */
4283 ASSERT(Context
->Create
.CanonicalNameBuffer
== Context
->AlsoCanonicalNameBuffer
);
4285 if (Context
->Create
.CanonicalNameBuffer
!= NULL
)
4287 RxFreePoolWithTag(Context
->Create
.CanonicalNameBuffer
, RX_MISC_POOLTAG
);
4288 Context
->Create
.CanonicalNameBuffer
= NULL
;
4289 Context
->AlsoCanonicalNameBuffer
= NULL
;
4292 ASSERT(Context
->AlsoCanonicalNameBuffer
== NULL
);
4296 RxFsdCommonDispatch(
4297 PRX_FSD_DISPATCH_VECTOR DispatchVector
,
4298 UCHAR MajorFunction
,
4299 PIO_STACK_LOCATION Stack
,
4300 PFILE_OBJECT FileObject
,
4302 PRDBSS_DEVICE_OBJECT RxDeviceObject
)
4306 PRX_CONTEXT Context
;
4307 UCHAR MinorFunction
;
4308 PFILE_OBJECT StackFileObject
;
4309 PRX_FSD_DISPATCH DispatchFunc
;
4310 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4311 BOOLEAN TopLevel
, Closing
, PassToDriver
, SetCancelRoutine
, PostRequest
, CanWait
;
4313 Status
= STATUS_SUCCESS
;
4315 DPRINT("RxFsdCommonDispatch(%p, %d, %p, %p, %p, %p)\n", DispatchVector
, MajorFunction
, Stack
, FileObject
, Irp
, RxDeviceObject
);
4317 FsRtlEnterFileSystem();
4319 TopLevel
= RxTryToBecomeTheTopLevelIrp(&TopLevelContext
, Irp
, RxDeviceObject
, FALSE
);
4325 PostRequest
= FALSE
;
4326 SetCancelRoutine
= TRUE
;
4327 MinorFunction
= Stack
->MinorFunction
;
4329 switch (MajorFunction
)
4331 case IRP_MJ_FILE_SYSTEM_CONTROL
:
4332 if (FileObject
!= NULL
)
4334 CanWait
= IoIsOperationSynchronous(Irp
);
4344 case IRP_MJ_QUERY_INFORMATION
:
4345 case IRP_MJ_SET_INFORMATION
:
4346 case IRP_MJ_QUERY_EA
:
4348 case IRP_MJ_FLUSH_BUFFERS
:
4349 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
4350 case IRP_MJ_SET_VOLUME_INFORMATION
:
4351 case IRP_MJ_DIRECTORY_CONTROL
:
4352 case IRP_MJ_DEVICE_CONTROL
:
4353 case IRP_MJ_LOCK_CONTROL
:
4354 case IRP_MJ_QUERY_SECURITY
:
4355 case IRP_MJ_SET_SECURITY
:
4356 CanWait
= IoIsOperationSynchronous(Irp
);
4360 case IRP_MJ_CLEANUP
:
4362 SetCancelRoutine
= FALSE
;
4369 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
4370 /* Should we stop it right now, or mini-rdr deserves to know? */
4371 PassToDriver
= TRUE
;
4372 if (RxGetRdbssState(RxDeviceObject
) != RDBSS_STARTABLE
)
4374 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& !Closing
)
4376 PassToDriver
= FALSE
;
4377 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
4378 DPRINT1("Not started!\n");
4383 if (DispatchVector
!= RxDeviceFCBVector
&& (FileObject
->FileName
.Length
!= 0 || FileObject
->RelatedFileObject
!= NULL
))
4385 PassToDriver
= FALSE
;
4386 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
4387 DPRINT1("Not started!\n");
4390 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
4392 StackFileObject
= Stack
->FileObject
;
4393 /* Make sure we don't deal with orphaned stuff */
4394 if (StackFileObject
!= NULL
&& StackFileObject
->FsContext
!= NULL
)
4396 if (StackFileObject
->FsContext2
!= UIntToPtr(DFS_OPEN_CONTEXT
) &&
4397 StackFileObject
->FsContext2
!= UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
4398 StackFileObject
->FsContext
!= &RxDeviceFCB
)
4403 Fcb
= StackFileObject
->FsContext
;
4404 Fobx
= StackFileObject
->FsContext2
;
4406 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
) ||
4407 BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
4411 PassToDriver
= TRUE
;
4415 PassToDriver
= FALSE
;
4416 Status
= STATUS_UNEXPECTED_NETWORK_ERROR
;
4417 DPRINT1("Operation on orphaned FCB: %p\n", Fcb
);
4423 /* Did we receive a close request whereas we're stopping? */
4424 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& Closing
)
4428 Fcb
= StackFileObject
->FsContext
;
4430 DPRINT1("Close received after stop\n");
4431 DPRINT1("Irp: %p %d:%d FO: %p FCB: %p\n",
4432 Irp
, Stack
->MajorFunction
, Stack
->MinorFunction
, StackFileObject
, Fcb
);
4434 if (Fcb
!= NULL
&& Fcb
!= &RxDeviceFCB
&&
4437 DPRINT1("OpenCount: %ld, UncleanCount: %ld, Name: %wZ\n",
4438 Fcb
->OpenCount
, Fcb
->UncleanCount
, &Fcb
->FcbTableEntry
.Path
);
4442 /* Should we stop the whole thing now? */
4445 if (MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
|| MinorFunction
!= IRP_MN_REMOVE_DEVICE
)
4447 IoMarkIrpPending(Irp
);
4448 Irp
->IoStatus
.Status
= Status
;
4449 Irp
->IoStatus
.Information
= 0;
4450 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4451 Status
= STATUS_PENDING
;
4455 Irp
->IoStatus
.Status
= Status
;
4456 Irp
->IoStatus
.Information
= 0;
4457 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4463 /* No? Allocate a context to deal with the mini-rdr */
4464 Context
= RxCreateRxContext(Irp
, RxDeviceObject
, (CanWait
? RX_CONTEXT_FLAG_WAIT
: 0));
4465 if (Context
== NULL
)
4467 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4468 RxCompleteRequest_Real(RxNull
, Irp
, STATUS_INSUFFICIENT_RESOURCES
);
4472 /* Set cancel routine if required */
4473 if (SetCancelRoutine
)
4475 IoAcquireCancelSpinLock(&OldIrql
);
4476 IoSetCancelRoutine(Irp
, RxCancelRoutine
);
4480 IoAcquireCancelSpinLock(&OldIrql
);
4481 IoSetCancelRoutine(Irp
, NULL
);
4483 IoReleaseCancelSpinLock(OldIrql
);
4485 ASSERT(MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
4487 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
4488 Irp
->IoStatus
.Information
= 0;
4489 /* Get the dispatch routine */
4490 DispatchFunc
= DispatchVector
[MajorFunction
].CommonRoutine
;
4492 if (MajorFunction
== IRP_MJ_READ
|| MajorFunction
== IRP_MJ_WRITE
)
4494 /* Handle the complete MDL case */
4495 if (BooleanFlagOn(MinorFunction
, IRP_MN_COMPLETE
))
4497 DispatchFunc
= RxCompleteMdl
;
4501 /* Do we have to post request? */
4502 if (BooleanFlagOn(MinorFunction
, IRP_MN_DPC
))
4508 /* Our read function needs stack, make sure we won't overflow,
4509 * otherwise, post the request
4511 if (MajorFunction
== IRP_MJ_READ
)
4513 if (IoGetRemainingStackSize() < 0xE00)
4515 Context
->PendingReturned
= TRUE
;
4516 Status
= RxPostStackOverflowRead(Context
);
4517 if (Status
!= STATUS_PENDING
)
4519 Context
->PendingReturned
= FALSE
;
4520 RxCompleteAsynchronousRequest(Context
, Status
);
4530 Context
->ResumeRoutine
= DispatchFunc
;
4531 /* There's a dispatch routine? Time to dispatch! */
4532 if (DispatchFunc
!= NULL
)
4534 Context
->PendingReturned
= TRUE
;
4537 Status
= RxFsdPostRequest(Context
);
4541 /* Retry as long as we have */
4544 Status
= DispatchFunc(Context
);
4546 while (Status
== STATUS_RETRY
);
4548 if (Status
== STATUS_PENDING
)
4553 /* Sanity check: did someone mess with our context? */
4554 if (Context
->CurrentIrp
!= Irp
|| Context
->CurrentIrpSp
!= Stack
||
4555 Context
->MajorFunction
!= MajorFunction
|| Stack
->MinorFunction
!= MinorFunction
)
4557 DPRINT1("RX_CONTEXT %p has been contaminated!\n", Context
);
4558 DPRINT1("->CurrentIrp %p %p\n", Context
->CurrentIrp
, Irp
);
4559 DPRINT1("->CurrentIrpSp %p %p\n", Context
->CurrentIrpSp
, Stack
);
4560 DPRINT1("->MajorFunction %d %d\n", Context
->MajorFunction
, MajorFunction
);
4561 DPRINT1("->MinorFunction %d %d\n", Context
->MinorFunction
, MinorFunction
);
4563 Context
->PendingReturned
= FALSE
;
4564 Status
= RxCompleteAsynchronousRequest(Context
, Status
);
4569 Status
= STATUS_NOT_IMPLEMENTED
;
4576 RxUnwindTopLevelIrp(&TopLevelContext
);
4579 FsRtlExitFileSystem();
4583 DPRINT("RxFsdDispatch, Status: %lx\n", Status
);
4593 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
4597 PIO_STACK_LOCATION Stack
;
4598 PRX_FSD_DISPATCH_VECTOR DispatchVector
;
4602 DPRINT("RxFsdDispatch(%p, %p)\n", RxDeviceObject
, Irp
);
4604 Stack
= IoGetCurrentIrpStackLocation(Irp
);
4606 /* Dispatch easy case */
4607 if (Stack
->MajorFunction
== IRP_MJ_SYSTEM_CONTROL
)
4609 return RxSystemControl(RxDeviceObject
, Irp
);
4612 /* Bail out broken cases */
4613 if (Stack
->MajorFunction
== IRP_MJ_CREATE_MAILSLOT
||
4614 Stack
->MajorFunction
== IRP_MJ_CREATE_NAMED_PIPE
)
4616 IoMarkIrpPending(Irp
);
4617 Irp
->IoStatus
.Information
= 0;
4618 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_INVALID
;
4619 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4620 return STATUS_PENDING
;
4623 /* Immediately handle create */
4624 if (Stack
->MajorFunction
== IRP_MJ_CREATE
)
4626 return RxFsdCommonDispatch(&RxFsdDispatchVector
[0], Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
4629 /* If not a creation, we must have at least a FO with a FCB */
4630 if (Stack
->FileObject
== NULL
|| Stack
->FileObject
->FsContext
== NULL
)
4632 IoMarkIrpPending(Irp
);
4633 Irp
->IoStatus
.Information
= 0;
4634 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
4635 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4636 return STATUS_PENDING
;
4639 /* Set the dispatch vector if required */
4640 Fcb
= Stack
->FileObject
->FsContext
;
4641 if (!NodeTypeIsFcb(Fcb
) || Fcb
->PrivateDispatchVector
== NULL
)
4643 DispatchVector
= &RxFsdDispatchVector
[0];
4647 DispatchVector
= Fcb
->PrivateDispatchVector
;
4650 /* Device cannot accept such requests */
4651 if (RxDeviceObject
== RxFileSystemDeviceObject
)
4653 IoMarkIrpPending(Irp
);
4654 Irp
->IoStatus
.Information
= 0;
4655 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
4656 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
4657 return STATUS_PENDING
;
4660 /* Dispatch for real! */
4661 return RxFsdCommonDispatch(DispatchVector
, Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
4669 IN PRX_CONTEXT RxContext
)
4671 /* Initialize posting if required */
4672 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
4674 RxPrePostIrp(RxContext
, RxContext
->CurrentIrp
);
4677 DPRINT("Posting MN: %d, Ctxt: %p, IRP: %p, Thrd: %lx #%lx\n",
4678 RxContext
->MinorFunction
, RxContext
,
4679 RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
4680 RxContext
->SerialNumber
);
4682 RxAddToWorkque(RxContext
, RxContext
->CurrentIrp
);
4683 return STATUS_PENDING
;
4695 WORK_QUEUE_TYPE Queue
;
4696 PRDBSS_DEVICE_OBJECT VolumeDO
;
4697 PRX_CONTEXT RxContext
, EntryContext
;
4701 RxContext
= Context
;
4702 EntryContext
= Context
;
4703 /* Save IRQL at entry for later checking */
4704 EntryIrql
= KeGetCurrentIrql();
4706 /* No FO, deal with device */
4707 if (RxContext
->CurrentIrpSp
->FileObject
!= NULL
)
4709 VolumeDO
= RxFileSystemDeviceObject
;
4716 /* Which queue to used for delayed? */
4717 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
))
4719 Queue
= DelayedWorkQueue
;
4723 ASSERT(BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
4724 Queue
= CriticalWorkQueue
;
4731 BOOLEAN RecursiveCall
;
4732 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4734 ASSERT(RxContext
->MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
4735 ASSERT(!RxContext
->PostRequest
);
4737 RxContext
->LastExecutionThread
= PsGetCurrentThread();
4738 SetFlag(RxContext
->Flags
, (RX_CONTEXT_FLAG_IN_FSP
| RX_CONTEXT_FLAG_WAIT
));
4740 DPRINT("Dispatch: MN: %d, Ctxt: %p, IRP: %p, THRD: %lx #%lx", RxContext
->MinorFunction
,
4741 RxContext
, RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
4742 RxContext
->SerialNumber
);
4744 Irp
= RxContext
->CurrentIrp
;
4746 FsRtlEnterFileSystem();
4748 RecursiveCall
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
);
4749 RxTryToBecomeTheTopLevelIrp(&TopLevelContext
,
4750 (RecursiveCall
? (PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
: RxContext
->CurrentIrp
),
4751 RxContext
->RxDeviceObject
, TRUE
);
4753 ASSERT(RxContext
->ResumeRoutine
!= NULL
);
4755 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_DPC
) && Irp
->Tail
.Overlay
.Thread
== NULL
)
4757 ASSERT((RxContext
->MajorFunction
== IRP_MJ_WRITE
) || (RxContext
->MajorFunction
== IRP_MJ_READ
));
4758 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4761 /* Call the resume routine */
4766 NoComplete
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_COMPLETE_FROM_FSP
);
4768 Status
= RxContext
->ResumeRoutine(RxContext
);
4769 if (!NoComplete
&& Status
!= STATUS_PENDING
)
4771 if (Status
!= STATUS_RETRY
)
4773 Status
= RxCompleteRequest(RxContext
, Status
);
4777 while (Status
== STATUS_RETRY
);
4779 RxUnwindTopLevelIrp(&TopLevelContext
);
4780 FsRtlExitFileSystem();
4782 if (VolumeDO
!= NULL
)
4784 RxContext
= RxRemoveOverflowEntry(VolumeDO
, Queue
);
4790 } while (RxContext
!= NULL
);
4792 /* Did we mess with IRQL? */
4793 if (KeGetCurrentIrql() >= APC_LEVEL
)
4795 DPRINT1("High IRQL for Ctxt %p, on entry: %x\n", EntryContext
, EntryIrql
);
4803 RxGetNetworkProviderPriority(
4804 PUNICODE_STRING DeviceName
)
4815 RxGetRegistryParameters(
4816 IN PUNICODE_STRING RegistryPath
)
4820 UCHAR Buffer
[0x400];
4821 HANDLE DriverHandle
, KeyHandle
;
4822 UNICODE_STRING KeyName
, OutString
;
4823 OBJECT_ATTRIBUTES ObjectAttributes
;
4827 InitializeObjectAttributes(&ObjectAttributes
, RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
4828 Status
= ZwOpenKey(&DriverHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4829 if (!NT_SUCCESS(Status
))
4834 RtlInitUnicodeString(&KeyName
, L
"Parameters");
4835 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, DriverHandle
, FALSE
);
4836 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4837 if (NT_SUCCESS(Status
))
4839 /* The only parameter we deal with is InitialDebugString */
4840 RxGetStringRegistryParameter(KeyHandle
, L
"InitialDebugString", &OutString
, Buffer
, sizeof(Buffer
), 0);
4841 if (OutString
.Length
!= 0 && OutString
.Length
< 0x140)
4846 Read
= OutString
.Buffer
;
4847 Write
= (PSTR
)OutString
.Buffer
;
4848 for (i
= 0; i
< OutString
.Length
; ++i
)
4856 /* Which is a string we'll just write out */
4857 DPRINT("InitialDebugString read from registry: '%s'\n", OutString
.Buffer
);
4858 RxDebugControlCommand((PSTR
)OutString
.Buffer
);
4864 ZwClose(DriverHandle
);
4872 IN PIO_STACK_LOCATION IrpSp
)
4875 PACCESS_TOKEN Token
;
4876 PIO_SECURITY_CONTEXT SecurityContext
;
4880 /* If that's not a prefix claim, not an open request, session id will be 0 */
4881 if (IrpSp
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
|| IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_REDIR_QUERY_PATH
)
4883 if (IrpSp
->MajorFunction
!= IRP_MJ_CREATE
|| IrpSp
->Parameters
.Create
.SecurityContext
== NULL
)
4888 SecurityContext
= IrpSp
->Parameters
.Create
.SecurityContext
;
4892 SecurityContext
= ((PQUERY_PATH_REQUEST
)IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
)->SecurityContext
;
4895 /* Query the session id */
4896 Token
= SeQuerySubjectContextToken(&SecurityContext
->AccessState
->SubjectSecurityContext
);
4897 SeQuerySessionIdToken(Token
, &SessionId
);
4907 RxGetStringRegistryParameter(
4908 IN HANDLE KeyHandle
,
4910 OUT PUNICODE_STRING OutString
,
4912 IN ULONG BufferLength
,
4913 IN BOOLEAN LogFailure
)
4917 UNICODE_STRING KeyString
;
4921 RtlInitUnicodeString(&KeyString
, KeyName
);
4922 Status
= ZwQueryValueKey(KeyHandle
, &KeyString
, KeyValuePartialInformation
, Buffer
, BufferLength
, &ResultLength
);
4923 OutString
->Length
= 0;
4924 OutString
->Buffer
= 0;
4925 if (!NT_SUCCESS(Status
))
4929 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BD3, Status
);
4935 OutString
->Buffer
= (PWSTR
)(((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->Data
);
4936 OutString
->Length
= ((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->DataLength
- sizeof(UNICODE_NULL
);
4937 OutString
->MaximumLength
= OutString
->Length
;
4939 return STATUS_SUCCESS
;
4945 PRDBSS_DEVICE_OBJECT
4946 RxGetTopDeviceObjectIfRdbssIrp(
4950 PRDBSS_DEVICE_OBJECT TopDevice
= NULL
;
4952 TopLevelIrp
= IoGetTopLevelIrp();
4953 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
4955 TopDevice
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->RxDeviceObject
;
4966 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
4969 PACCESS_TOKEN Token
;
4973 Token
= SeQuerySubjectContextToken(SubjectSecurityContext
);
4974 SeQueryAuthenticationIdToken(Token
, &Luid
);
4981 RxIndicateChangeOfBufferingStateForSrvOpen(
4982 PMRX_SRV_CALL SrvCall
,
4983 PMRX_SRV_OPEN SrvOpen
,
4992 RxInitializeDebugSupport(
5003 RxInitializeDispatchVectors(
5004 PDRIVER_OBJECT DriverObject
)
5010 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; ++i
)
5012 DriverObject
->MajorFunction
[i
] = (PDRIVER_DISPATCH
)RxFsdDispatch
;
5015 RxDeviceFCB
.PrivateDispatchVector
= RxDeviceFCBVector
;
5016 ASSERT(RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
5017 ASSERT(RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
5019 DriverObject
->FastIoDispatch
= &RxFastIoDispatch
;
5020 RxFastIoDispatch
.SizeOfFastIoDispatch
= sizeof(RxFastIoDispatch
);
5021 RxFastIoDispatch
.FastIoCheckIfPossible
= RxFastIoCheckIfPossible
;
5022 RxFastIoDispatch
.FastIoRead
= RxFastIoRead
;
5023 RxFastIoDispatch
.FastIoWrite
= RxFastIoWrite
;
5024 RxFastIoDispatch
.FastIoQueryBasicInfo
= NULL
;
5025 RxFastIoDispatch
.FastIoQueryStandardInfo
= NULL
;
5026 RxFastIoDispatch
.FastIoLock
= NULL
;
5027 RxFastIoDispatch
.FastIoUnlockSingle
= NULL
;
5028 RxFastIoDispatch
.FastIoUnlockAll
= NULL
;
5029 RxFastIoDispatch
.FastIoUnlockAllByKey
= NULL
;
5030 RxFastIoDispatch
.FastIoDeviceControl
= RxFastIoDeviceControl
;
5031 RxFastIoDispatch
.AcquireFileForNtCreateSection
= RxAcquireFileForNtCreateSection
;
5032 RxFastIoDispatch
.ReleaseFileForNtCreateSection
= RxReleaseFileForNtCreateSection
;
5033 RxFastIoDispatch
.AcquireForCcFlush
= RxAcquireForCcFlush
;
5034 RxFastIoDispatch
.ReleaseForCcFlush
= RxReleaseForCcFlush
;
5036 RxInitializeTopLevelIrpPackage();
5038 RxData
.CacheManagerCallbacks
.AcquireForLazyWrite
= RxAcquireFcbForLazyWrite
;
5039 RxData
.CacheManagerCallbacks
.ReleaseFromLazyWrite
= RxReleaseFcbFromLazyWrite
;
5040 RxData
.CacheManagerCallbacks
.AcquireForReadAhead
= RxAcquireFcbForReadAhead
;
5041 RxData
.CacheManagerCallbacks
.ReleaseFromReadAhead
= RxReleaseFcbFromReadAhead
;
5043 RxData
.CacheManagerNoOpCallbacks
.AcquireForLazyWrite
= RxNoOpAcquire
;
5044 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromLazyWrite
= RxNoOpRelease
;
5045 RxData
.CacheManagerNoOpCallbacks
.AcquireForReadAhead
= RxNoOpAcquire
;
5046 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromReadAhead
= RxNoOpRelease
;
5055 return STATUS_NOT_IMPLEMENTED
;
5062 RxInitializeMinirdrDispatchTable(
5063 IN PDRIVER_OBJECT DriverObject
)
5073 RxInitializeRegistrationStructures(
5078 ExInitializeFastMutex(&RxData
.MinirdrRegistrationMutex
);
5079 RxData
.NumberOfMinirdrsRegistered
= 0;
5080 RxData
.NumberOfMinirdrsStarted
= 0;
5081 InitializeListHead(&RxData
.RegisteredMiniRdrs
);
5083 return STATUS_SUCCESS
;
5091 RxInitializeTopLevelIrpPackage(
5094 KeInitializeSpinLock(&TopLevelIrpSpinLock
);
5095 InitializeListHead(&TopLevelIrpAllocatedContextsList
);
5101 PDRIVER_OBJECT DriverObject
,
5111 RxIsMemberOfTopLevelIrpAllocatedContextsList(
5112 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
5115 PLIST_ENTRY NextEntry
;
5116 BOOLEAN Found
= FALSE
;
5117 PRX_TOPLEVELIRP_CONTEXT ListContext
;
5119 /* Browse all the allocated TLC to find ours */
5120 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
5121 for (NextEntry
= TopLevelIrpAllocatedContextsList
.Flink
;
5122 NextEntry
!= &TopLevelIrpAllocatedContextsList
;
5123 NextEntry
= NextEntry
->Flink
)
5125 ListContext
= CONTAINING_RECORD(NextEntry
, RX_TOPLEVELIRP_CONTEXT
, ListEntry
);
5126 ASSERT(ListContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
5127 ASSERT(BooleanFlagOn(ListContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
5130 if (ListContext
== TopLevelContext
)
5136 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
5150 /* No associated SRV_OPEN, it's OK to purge */
5151 if (IsListEmpty(&Fcb
->SrvOpenList
))
5156 /* Only allow to purge if all the associated SRV_OPEN
5157 * - have no outstanding opens ongoing
5158 * - have only read attribute set
5160 for (Entry
= Fcb
->SrvOpenList
.Flink
;
5161 Entry
!= &Fcb
->SrvOpenList
;
5162 Entry
= Entry
->Flink
)
5166 SrvOpen
= CONTAINING_RECORD(Entry
, SRV_OPEN
, SrvOpenQLinks
);
5168 /* Failing previous needs, don't allow purge */
5169 if (SrvOpen
->UncleanFobxCount
!= 0 ||
5170 (SrvOpen
->DesiredAccess
& 0xFFEFFFFF) != FILE_READ_ATTRIBUTES
)
5176 /* All correct, allow purge */
5184 RxIsThisAnRdbssTopLevelContext(
5185 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
5187 ULONG_PTR StackTop
, StackBottom
;
5189 /* Bail out for flags */
5190 if ((ULONG_PTR
)TopLevelContext
<= FSRTL_FAST_IO_TOP_LEVEL_IRP
)
5195 /* Is our provided TLC allocated on stack? */
5196 IoGetStackLimits(&StackTop
, &StackBottom
);
5197 if ((ULONG_PTR
)TopLevelContext
<= StackBottom
- sizeof(RX_TOPLEVELIRP_CONTEXT
) &&
5198 (ULONG_PTR
)TopLevelContext
>= StackTop
)
5200 /* Yes, so check whether it's really a TLC by checking alignement & signature */
5201 if (!BooleanFlagOn((ULONG_PTR
)TopLevelContext
, 0x3) && TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
)
5209 /* No, use the helper function */
5210 return RxIsMemberOfTopLevelIrpAllocatedContextsList(TopLevelContext
);
5217 RxIsThisTheTopLevelIrp(
5222 /* When we put oursleves as top level, we set TLC as 'IRP', so look for it */
5223 TopLevelIrp
= IoGetTopLevelIrp();
5224 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
5226 TopLevelIrp
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->Irp
;
5229 return (TopLevelIrp
== Irp
);
5234 RxLockOperationCompletion(
5239 return STATUS_NOT_IMPLEMENTED
;
5248 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
5249 IN PUNICODE_STRING OriginatorId
,
5254 PUNICODE_STRING Originator
= OriginatorId
;
5255 LARGE_INTEGER LargeLine
;
5257 /* Set optional parameters */
5258 LargeLine
.QuadPart
= Line
;
5259 if (OriginatorId
== NULL
|| OriginatorId
->Length
== 0)
5261 Originator
= (PUNICODE_STRING
)&unknownId
;
5265 RxLogEventWithAnnotation(DeviceObject
, EventId
, Status
, &LargeLine
, sizeof(LargeLine
), Originator
, 1);
5270 RxLogEventWithAnnotation(
5271 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
5274 IN PVOID DataBuffer
,
5275 IN USHORT DataBufferLength
,
5276 IN PUNICODE_STRING Annotation
,
5277 IN ULONG AnnotationCount
)
5285 PRX_CONTEXT RxContext
)
5288 return STATUS_NOT_IMPLEMENTED
;
5296 RxLowIoIoCtlShellCompletion(
5297 PRX_CONTEXT RxContext
)
5304 DPRINT("RxLowIoIoCtlShellCompletion(%p)\n", RxContext
);
5306 Irp
= RxContext
->CurrentIrp
;
5307 Status
= RxContext
->IoStatusBlock
.Status
;
5309 /* Set information and status */
5310 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
)
5312 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
5315 Irp
->IoStatus
.Status
= Status
;
5321 RxLowIoLockControlShell(
5322 IN PRX_CONTEXT RxContext
)
5325 return STATUS_NOT_IMPLEMENTED
;
5333 PRX_CONTEXT RxContext
)
5340 DPRINT("RxLowIoReadShell(%p)\n", RxContext
);
5342 Fcb
= (PFCB
)RxContext
->pFcb
;
5343 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
5345 return STATUS_MORE_PROCESSING_REQUIRED
;
5348 /* Always update stats for disks */
5349 if (Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
5351 ExInterlockedAddLargeStatistic(&RxContext
->RxDeviceObject
->NetworkReadBytesRequested
, RxContext
->LowIoContext
.ParamsFor
.ReadWrite
.ByteCount
);
5354 /* And forward the read to the mini-rdr */
5355 Status
= RxLowIoSubmit(RxContext
, RxLowIoReadShellCompletion
);
5356 DPRINT("RxLowIoReadShell(%p), Status: %lx\n", RxContext
, Status
);
5363 RxLowIoReadShellCompletion(
5364 PRX_CONTEXT RxContext
)
5369 BOOLEAN PagingIo
, IsPipe
;
5370 PIO_STACK_LOCATION Stack
;
5371 PLOWIO_CONTEXT LowIoContext
;
5375 DPRINT("RxLowIoReadShellCompletion(%p)\n", RxContext
);
5377 Status
= RxContext
->IoStatusBlock
.Status
;
5378 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext
, Status
, RxContext
->IoStatusBlock
.Information
);
5380 Irp
= RxContext
->CurrentIrp
;
5381 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
5383 /* Set IRP information from the RX_CONTEXT status block */
5384 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
5386 /* Fixup status for paging file if nothing was read */
5389 if (NT_SUCCESS(Status
) && RxContext
->IoStatusBlock
.Information
== 0)
5391 Status
= STATUS_END_OF_FILE
;
5395 LowIoContext
= &RxContext
->LowIoContext
;
5396 ASSERT(RxLowIoIsBufferLocked(LowIoContext
));
5398 /* Check broken cases that should never happen */
5399 Fcb
= (PFCB
)RxContext
->pFcb
;
5400 if (Status
== STATUS_FILE_LOCK_CONFLICT
)
5402 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_THIS_READ_ENLARGED
))
5405 return STATUS_RETRY
;
5408 else if (Status
== STATUS_SUCCESS
)
5410 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
))
5412 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
) ||
5413 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
))
5419 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
5425 /* Readahead should go through Cc and not finish here */
5426 ASSERT(!BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_READAHEAD
));
5428 /* If it's sync, RxCommonRead will finish the work - nothing to do here */
5429 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_SYNCCALL
))
5434 Stack
= RxContext
->CurrentIrpSp
;
5435 IsPipe
= BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
);
5436 /* Release lock if required */
5439 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
5443 /* Set FastIo if read was a success */
5444 if (NT_SUCCESS(Status
) && !IsPipe
)
5446 SetFlag(Stack
->FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
5449 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
5451 RxResumeBlockedOperations_Serially(RxContext
, &((PFOBX
)RxContext
->pFobx
)->Specific
.NamedPipe
.ReadSerializationQueue
);
5455 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
5464 /* Final sanity checks */
5465 ASSERT(Status
!= STATUS_RETRY
);
5466 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
5467 ASSERT(RxContext
->MajorFunction
== IRP_MJ_READ
);
5473 RxNotifyChangeDirectory(
5474 PRX_CONTEXT RxContext
)
5477 return STATUS_NOT_IMPLEMENTED
;
5481 RxPostStackOverflowRead (
5482 IN PRX_CONTEXT RxContext
)
5487 return STATUS_NOT_IMPLEMENTED
;
5494 RxpPrepareCreateContextForReuse(
5495 PRX_CONTEXT RxContext
)
5497 /* Reuse can only happen for open operations (STATUS_RETRY) */
5498 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
5500 /* Release the FCB if it was acquired */
5501 if (RxContext
->Create
.FcbAcquired
)
5503 RxReleaseFcb(RxContext
, RxContext
->pFcb
);
5504 RxContext
->Create
.FcbAcquired
= FALSE
;
5507 /* Free the canonical name */
5508 RxFreeCanonicalNameBuffer(RxContext
);
5510 /* If we have a VNetRoot associated */
5511 if (RxContext
->Create
.pVNetRoot
!= NULL
|| RxContext
->Create
.NetNamePrefixEntry
!= NULL
)
5513 /* Remove our link and thus, dereference the VNetRoot */
5514 RxpAcquirePrefixTableLockShared(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
, TRUE
);
5515 if (RxContext
->Create
.pVNetRoot
!= NULL
)
5517 RxDereferenceVNetRoot(RxContext
->Create
.pVNetRoot
, TRUE
);
5518 RxContext
->Create
.pVNetRoot
= NULL
;
5520 RxpReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
5523 DPRINT("RxContext: %p prepared for reuse\n", RxContext
);
5530 RxpQueryInfoMiniRdr(
5531 PRX_CONTEXT RxContext
,
5532 FILE_INFORMATION_CLASS FileInfoClass
,
5538 Fcb
= (PFCB
)RxContext
->pFcb
;
5540 /* Set the RX_CONTEXT */
5541 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
5542 RxContext
->Info
.Buffer
= Buffer
;
5545 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryFileInfo
, (RxContext
));
5555 IN PRX_CONTEXT RxContext
)
5559 NET_ROOT_TYPE NetRootType
;
5560 UNICODE_STRING CanonicalName
, FileName
, NetRootName
;
5564 Irp
= RxContext
->CurrentIrp
;
5566 /* This has to come from MUP */
5567 if (Irp
->RequestorMode
== UserMode
)
5569 return STATUS_INVALID_DEVICE_REQUEST
;
5572 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
5574 PQUERY_PATH_REQUEST QueryRequest
;
5576 /* Get parameters */
5577 QueryRequest
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
5579 /* Don't overflow allocation */
5580 if (QueryRequest
->PathNameLength
>= MAXUSHORT
- 1)
5582 return STATUS_INVALID_DEVICE_REQUEST
;
5585 /* Forcefully rewrite IRP MJ */
5586 RxContext
->MajorFunction
= IRP_MJ_CREATE
;
5588 /* Fake canon name */
5589 RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
= RxAllocatePoolWithTag(NonPagedPool
, QueryRequest
->PathNameLength
, RX_MISC_POOLTAG
);
5590 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
== NULL
)
5592 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5596 /* Copy the prefix to look for */
5597 RtlCopyMemory(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, &QueryRequest
->FilePathName
[0], QueryRequest
->PathNameLength
);
5598 RxContext
->PrefixClaim
.SuppliedPathName
.Length
= QueryRequest
->PathNameLength
;
5599 RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
= QueryRequest
->PathNameLength
;
5601 /* Zero the create parameters */
5602 RtlZeroMemory(&RxContext
->Create
.NtCreateParameters
,
5603 FIELD_OFFSET(RX_CONTEXT
, AlsoCanonicalNameBuffer
) - FIELD_OFFSET(RX_CONTEXT
, Create
.NtCreateParameters
));
5604 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
5605 RxContext
->Create
.NtCreateParameters
.SecurityContext
= QueryRequest
->SecurityContext
;
5609 /* If not devcontrol, it comes from open, name was already copied */
5610 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
5611 ASSERT(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
);
5614 /* Canonilize name */
5615 NetRootType
= NET_ROOT_WILD
;
5616 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
5617 FileName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
5618 FileName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
5619 FileName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
5620 NetRootName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
5621 NetRootName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
5622 NetRootName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
5623 Status
= RxFirstCanonicalize(RxContext
, &FileName
, &CanonicalName
, &NetRootType
);
5624 /* It went fine, attempt to establish a connection (that way we know whether the prefix is accepted) */
5625 if (NT_SUCCESS(Status
))
5627 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &NetRootName
);
5629 if (Status
== STATUS_PENDING
)
5634 if (NT_SUCCESS(Status
))
5636 PQUERY_PATH_RESPONSE QueryResponse
;
5638 /* We accept the length that was canon (minus netroot) */
5639 QueryResponse
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
5640 QueryResponse
->LengthAccepted
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
- NetRootName
.Length
;
5644 /* If we reach that point with MJ, reset everything and make IRP being a device control */
5645 if (RxContext
->MajorFunction
== IRP_MJ_CREATE
)
5647 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
)
5649 RxFreePoolWithTag(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, RX_MISC_POOLTAG
);
5652 RxpPrepareCreateContextForReuse(RxContext
);
5654 RxContext
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
5662 RxPrepareToReparseSymbolicLink(
5663 PRX_CONTEXT RxContext
,
5664 BOOLEAN SymbolicLinkEmbeddedInOldPath
,
5665 PUNICODE_STRING NewPath
,
5666 BOOLEAN NewPathIsAbsolute
,
5667 PBOOLEAN ReparseRequired
)
5670 return STATUS_NOT_IMPLEMENTED
;
5681 LOCK_OPERATION Lock
;
5682 PIO_STACK_LOCATION Stack
;
5683 PRX_CONTEXT RxContext
= Context
;
5685 /* NULL IRP is no option */
5691 /* Check whether preparation was really needed */
5692 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
5696 /* Mark the context as prepared */
5697 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
);
5699 /* Just lock the user buffer, with the correct length, depending on the MJ */
5700 Lock
= IoReadAccess
;
5701 Stack
= RxContext
->CurrentIrpSp
;
5702 if (RxContext
->MajorFunction
== IRP_MJ_READ
|| RxContext
->MajorFunction
== IRP_MJ_WRITE
)
5704 if (!BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
5706 if (RxContext
->MajorFunction
== IRP_MJ_READ
)
5708 Lock
= IoWriteAccess
;
5710 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.Read
.Length
);
5715 if ((RxContext
->MajorFunction
== IRP_MJ_DIRECTORY_CONTROL
&& RxContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) ||
5716 RxContext
->MajorFunction
== IRP_MJ_QUERY_EA
)
5718 Lock
= IoWriteAccess
;
5719 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.QueryDirectory
.Length
);
5721 else if (RxContext
->MajorFunction
== IRP_MJ_SET_EA
)
5723 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.SetEa
.Length
);
5727 /* As it will be posted (async), mark the IRP pending */
5728 IoMarkIrpPending(Irp
);
5733 RxpUnregisterMinirdr(
5734 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
)
5745 PRX_CONTEXT LocalContext
)
5752 MmFlushImageSection(&Fcb
->NonPaged
->SectionObjectPointers
, MmFlushForWrite
);
5754 /* And force close */
5755 RxReleaseFcb(NULL
, Fcb
);
5756 MmForceSectionClosed(&Fcb
->NonPaged
->SectionObjectPointers
, TRUE
);
5757 Status
= RxAcquireExclusiveFcb(NULL
, Fcb
);
5758 ASSERT(Status
== STATUS_SUCCESS
);
5762 RxQueryAlternateNameInfo(
5763 PRX_CONTEXT RxContext
,
5764 PFILE_NAME_INFORMATION AltNameInfo
)
5767 return STATUS_NOT_IMPLEMENTED
;
5775 PRX_CONTEXT RxContext
,
5776 PFILE_BASIC_INFORMATION BasicInfo
)
5780 DPRINT("RxQueryBasicInfo(%p, %p)\n", RxContext
, BasicInfo
);
5782 /* Simply zero and forward to mini-rdr */
5783 RtlZeroMemory(BasicInfo
, sizeof(FILE_BASIC_INFORMATION
));
5784 return RxpQueryInfoMiniRdr(RxContext
, FileBasicInformation
, BasicInfo
);
5788 RxQueryCompressedInfo(
5789 PRX_CONTEXT RxContext
,
5790 PFILE_COMPRESSION_INFORMATION CompressionInfo
)
5793 return STATUS_NOT_IMPLEMENTED
;
5801 PRX_CONTEXT RxContext
)
5808 BOOLEAN LockNotGranted
;
5809 ULONG Length
, FileIndex
;
5810 PUNICODE_STRING FileName
;
5811 PIO_STACK_LOCATION Stack
;
5812 FILE_INFORMATION_CLASS FileInfoClass
;
5816 DPRINT("RxQueryDirectory(%p)\n", RxContext
);
5818 /* Get parameters */
5819 Stack
= RxContext
->CurrentIrpSp
;
5820 Length
= Stack
->Parameters
.QueryDirectory
.Length
;
5821 FileName
= Stack
->Parameters
.QueryDirectory
.FileName
;
5822 FileInfoClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
5823 DPRINT("Wait: %d, Length: %ld, FileName: %p, Class: %d\n",
5824 FlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
), Length
,
5825 FileName
, FileInfoClass
);
5827 Irp
= RxContext
->CurrentIrp
;
5828 Flags
= Stack
->Flags
;
5829 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
5830 DPRINT("Index: %d, Buffer: %p, Flags: %x\n", FileIndex
, Irp
->UserBuffer
, Flags
);
5832 if (FileName
!= NULL
)
5834 DPRINT("FileName: %wZ\n", FileName
);
5837 /* No FOBX: not a standard file/directory */
5838 Fobx
= (PFOBX
)RxContext
->pFobx
;
5841 return STATUS_OBJECT_NAME_INVALID
;
5844 /* We can only deal with a disk */
5845 Fcb
= (PFCB
)RxContext
->pFcb
;
5846 if (Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
5848 DPRINT1("Not a disk! %x\n", Fcb
->pNetRoot
->Type
);
5849 return STATUS_INVALID_DEVICE_REQUEST
;
5852 /* Setup RX_CONTEXT related fields */
5853 RxContext
->QueryDirectory
.FileIndex
= FileIndex
;
5854 RxContext
->QueryDirectory
.RestartScan
= BooleanFlagOn(Flags
, SL_RESTART_SCAN
);
5855 RxContext
->QueryDirectory
.ReturnSingleEntry
= BooleanFlagOn(Flags
, SL_RETURN_SINGLE_ENTRY
);
5856 RxContext
->QueryDirectory
.IndexSpecified
= BooleanFlagOn(Flags
, SL_INDEX_SPECIFIED
);
5857 RxContext
->QueryDirectory
.InitialQuery
= (Fobx
->UnicodeQueryTemplate
.Buffer
== NULL
) && !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
5859 /* We don't support (yet?) a specific index being set */
5860 if (RxContext
->QueryDirectory
.IndexSpecified
)
5862 return STATUS_NOT_IMPLEMENTED
;
5865 /* Try to lock FCB */
5866 LockNotGranted
= TRUE
;
5867 if (RxContext
->QueryDirectory
.InitialQuery
)
5869 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5870 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
5872 if (!NT_SUCCESS(Status
))
5877 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
5879 RxContext
->QueryDirectory
.InitialQuery
= FALSE
;
5880 RxConvertToSharedFcb(RxContext
, Fcb
);
5883 LockNotGranted
= FALSE
;
5888 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5889 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
5891 if (!NT_SUCCESS(Status
))
5896 LockNotGranted
= FALSE
;
5900 /* If it failed, post request */
5903 return RxFsdPostRequest(RxContext
);
5906 /* This cannot be done on a orphaned directory */
5907 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
5909 RxReleaseFcb(RxContext
, Fcb
);
5910 return STATUS_FILE_CLOSED
;
5916 if (!RxContext
->QueryDirectory
.IndexSpecified
&& RxContext
->QueryDirectory
.RestartScan
)
5918 RxContext
->QueryDirectory
.FileIndex
= 0;
5921 /* Assume success */
5922 Status
= STATUS_SUCCESS
;
5923 /* If initial query, prepare FOBX */
5924 if (RxContext
->QueryDirectory
.InitialQuery
)
5926 /* We cannot have a template already! */
5927 ASSERT(!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
));
5929 /* If we have a file name and a correct one, duplicate it in the FOBX */
5930 if (FileName
!= NULL
&& FileName
->Length
!= 0 && FileName
->Buffer
!= NULL
&&
5931 (FileName
->Length
!= sizeof(WCHAR
) || FileName
->Buffer
[0] != '*') &&
5932 (FileName
->Length
!= 12 * sizeof(WCHAR
) ||
5933 RtlCompareMemory(FileName
->Buffer
, Rx8QMdot3QM
, 12 * sizeof(WCHAR
)) != 12 * sizeof(WCHAR
)))
5935 Fobx
->ContainsWildCards
= FsRtlDoesNameContainWildCards(FileName
);
5937 Fobx
->UnicodeQueryTemplate
.Buffer
= RxAllocatePoolWithTag(PagedPool
, FileName
->Length
, RX_DIRCTL_POOLTAG
);
5938 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
5940 /* UNICODE_STRING; length has to be even */
5941 if ((FileName
->Length
& 1) != 0)
5943 Status
= STATUS_INVALID_PARAMETER
;
5944 RxFreePoolWithTag(Fobx
->UnicodeQueryTemplate
.Buffer
, RX_DIRCTL_POOLTAG
);
5948 Fobx
->UnicodeQueryTemplate
.Length
= FileName
->Length
;
5949 Fobx
->UnicodeQueryTemplate
.MaximumLength
= FileName
->Length
;
5950 RtlMoveMemory(Fobx
->UnicodeQueryTemplate
.Buffer
, FileName
->Buffer
, FileName
->Length
);
5952 SetFlag(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
);
5957 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5960 /* No name specified, or a match all wildcard? Match everything */
5963 Fobx
->ContainsWildCards
= TRUE
;
5965 Fobx
->UnicodeQueryTemplate
.Buffer
= &RxStarForTemplate
;
5966 Fobx
->UnicodeQueryTemplate
.Length
= sizeof(WCHAR
);
5967 Fobx
->UnicodeQueryTemplate
.MaximumLength
= sizeof(WCHAR
);
5969 SetFlag(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
5972 /* No need for exclusive any longer */
5973 if (NT_SUCCESS(Status
))
5975 RxConvertToSharedFcb(RxContext
, Fcb
);
5979 /* Lock user buffer and forward to mini-rdr */
5980 if (NT_SUCCESS(Status
))
5982 RxLockUserBuffer(RxContext
, IoModifyAccess
, Length
);
5983 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
5984 RxContext
->Info
.Buffer
= RxNewMapUserBuffer(RxContext
);
5985 RxContext
->Info
.Length
= Length
;
5987 if (RxContext
->Info
.Buffer
!= NULL
)
5989 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryDirectory
, (RxContext
));
5992 /* Post if mini-rdr asks to */
5993 if (RxContext
->PostRequest
)
5995 RxFsdPostRequest(RxContext
);
5999 Irp
->IoStatus
.Information
= Length
- RxContext
->Info
.LengthRemaining
;
6005 RxReleaseFcb(RxContext
, Fcb
);
6014 PRX_CONTEXT RxContext
,
6015 PFILE_EA_INFORMATION EaInfo
)
6018 return STATUS_NOT_IMPLEMENTED
;
6022 RxQueryInternalInfo(
6023 PRX_CONTEXT RxContext
,
6024 PFILE_INTERNAL_INFORMATION InternalInfo
)
6027 return STATUS_NOT_IMPLEMENTED
;
6032 PRX_CONTEXT RxContext
,
6033 PFILE_NAME_INFORMATION NameInfo
)
6036 return STATUS_NOT_IMPLEMENTED
;
6041 PRX_CONTEXT RxContext
,
6042 PFILE_PIPE_INFORMATION PipeInfo
)
6045 return STATUS_NOT_IMPLEMENTED
;
6049 RxQueryPositionInfo(
6050 PRX_CONTEXT RxContext
,
6051 PFILE_POSITION_INFORMATION PositionInfo
)
6054 return STATUS_NOT_IMPLEMENTED
;
6061 RxQueryStandardInfo(
6062 PRX_CONTEXT RxContext
,
6063 PFILE_STANDARD_INFORMATION StandardInfo
)
6071 DPRINT("RxQueryStandardInfo(%p, %p)\n", RxContext
, StandardInfo
);
6073 /* Zero output buffer */
6074 RtlZeroMemory(StandardInfo
, sizeof(FILE_STANDARD_INFORMATION
));
6076 Fcb
= (PFCB
)RxContext
->pFcb
;
6077 Fobx
= (PFOBX
)RxContext
->pFobx
;
6078 /* If not a standard file type, or opened for backup, immediately forward to mini-rdr */
6079 if ((NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&& NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
) ||
6080 BooleanFlagOn(Fobx
->pSrvOpen
->CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
6082 return RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
6085 /* Otherwise, fill what we can already */
6086 Status
= STATUS_SUCCESS
;
6087 StandardInfo
->NumberOfLinks
= Fcb
->NumberOfLinks
;
6088 StandardInfo
->DeletePending
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
6089 StandardInfo
->Directory
= (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY
);
6090 if (StandardInfo
->NumberOfLinks
== 0)
6092 StandardInfo
->NumberOfLinks
= 1;
6095 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
6097 StandardInfo
->AllocationSize
.QuadPart
= Fcb
->Header
.AllocationSize
.QuadPart
;
6098 RxGetFileSizeWithLock(Fcb
, &StandardInfo
->EndOfFile
.QuadPart
);
6101 /* If we are asked to forcefully forward to mini-rdr or if size isn't cached, do it */
6102 if (RxForceQFIPassThrough
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILESIZECACHEING_ENABLED
))
6104 Status
= RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
6108 RxContext
->IoStatusBlock
.Information
-= sizeof(FILE_STANDARD_INFORMATION
);
6119 RxReadRegistryParameters(
6126 UNICODE_STRING KeyName
, ParamName
;
6127 OBJECT_ATTRIBUTES ObjectAttributes
;
6128 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
6132 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters");
6133 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
6134 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
6135 if (!NT_SUCCESS(Status
))
6140 PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
;
6141 RtlInitUnicodeString(&ParamName
, L
"DisableByteRangeLockingOnReadOnlyFiles");
6142 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6143 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6145 DisableByteRangeLockingOnReadOnlyFiles
= (*(PULONG
)PartialInfo
->Data
!= 0);
6148 RtlInitUnicodeString(&ParamName
, L
"ReadAheadGranularity");
6149 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6150 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6152 ULONG Granularity
= *(PULONG
)PartialInfo
->Data
;
6154 if (Granularity
> 16)
6159 ReadAheadGranularity
= Granularity
<< PAGE_SHIFT
;
6162 RtlInitUnicodeString(&ParamName
, L
"DisableFlushOnCleanup");
6163 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
6164 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
6166 DisableFlushOnCleanup
= (*(PULONG
)PartialInfo
->Data
!= 0);
6178 OUT PRDBSS_DEVICE_OBJECT
*DeviceObject
,
6179 IN OUT PDRIVER_OBJECT DriverObject
,
6180 IN PMINIRDR_DISPATCH MrdrDispatch
,
6182 IN PUNICODE_STRING DeviceName
,
6183 IN ULONG DeviceExtensionSize
,
6184 IN DEVICE_TYPE DeviceType
,
6185 IN ULONG DeviceCharacteristics
)
6188 PRDBSS_DEVICE_OBJECT RDBSSDevice
;
6194 return STATUS_INVALID_PARAMETER
;
6197 /* Create device object with provided parameters */
6198 Status
= IoCreateDevice(DriverObject
,
6199 DeviceExtensionSize
+ sizeof(RDBSS_DEVICE_OBJECT
),
6202 DeviceCharacteristics
,
6204 (PDEVICE_OBJECT
*)&RDBSSDevice
);
6205 if (!NT_SUCCESS(Status
))
6210 if (!RxData
.DriverObject
)
6212 return STATUS_UNSUCCESSFUL
;
6215 /* Initialize our DO extension */
6216 RDBSSDevice
->RDBSSDeviceObject
= NULL
;
6217 ++RxFileSystemDeviceObject
->ReferenceCount
;
6218 *DeviceObject
= RDBSSDevice
;
6219 RDBSSDevice
->RdbssExports
= &RxExports
;
6220 RDBSSDevice
->Dispatch
= MrdrDispatch
;
6221 RDBSSDevice
->RegistrationControls
= Controls
;
6222 RDBSSDevice
->DeviceName
= *DeviceName
;
6223 RDBSSDevice
->RegisterUncProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS
);
6224 RDBSSDevice
->RegisterMailSlotProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS
);
6225 InitializeListHead(&RDBSSDevice
->OverflowQueue
[0]);
6226 InitializeListHead(&RDBSSDevice
->OverflowQueue
[1]);
6227 InitializeListHead(&RDBSSDevice
->OverflowQueue
[2]);
6228 KeInitializeSpinLock(&RDBSSDevice
->OverflowQueueSpinLock
);
6229 RDBSSDevice
->NetworkProviderPriority
= RxGetNetworkProviderPriority(DeviceName
);
6231 DPRINT("Registered MiniRdr %wZ (prio: %x)\n", DeviceName
, RDBSSDevice
->NetworkProviderPriority
);
6233 ExAcquireFastMutex(&RxData
.MinirdrRegistrationMutex
);
6234 InsertTailList(&RxData
.RegisteredMiniRdrs
, &RDBSSDevice
->MiniRdrListLinks
);
6235 ExReleaseFastMutex(&RxData
.MinirdrRegistrationMutex
);
6237 /* Unless mini-rdr explicitly asked not to, initialize dispatch table */
6238 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH
))
6240 RxInitializeMinirdrDispatchTable(DriverObject
);
6243 /* Unless mini-rdr explicitly asked not to, initialize prefix scavenger */
6244 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER
))
6246 LARGE_INTEGER ScavengerTimeLimit
;
6248 RDBSSDevice
->pRxNetNameTable
= &RDBSSDevice
->RxNetNameTableInDeviceObject
;
6249 RxInitializePrefixTable(RDBSSDevice
->pRxNetNameTable
, 0, FALSE
);
6250 RDBSSDevice
->RxNetNameTableInDeviceObject
.IsNetNameTable
= TRUE
;
6251 ScavengerTimeLimit
.QuadPart
= MrdrDispatch
->ScavengerTimeout
* 10000000LL;
6252 RDBSSDevice
->pRdbssScavenger
= &RDBSSDevice
->RdbssScavengerInDeviceObject
;
6253 RxInitializeRdbssScavenger(RDBSSDevice
->pRdbssScavenger
, ScavengerTimeLimit
);
6256 RDBSSDevice
->pAsynchronousRequestsCompletionEvent
= NULL
;
6258 return STATUS_SUCCESS
;
6263 RxReleaseFcbFromLazyWrite(
6271 RxReleaseFcbFromReadAhead(
6279 RxReleaseFileForNtCreateSection(
6280 PFILE_OBJECT FileObject
)
6287 RxReleaseForCcFlush(
6288 PFILE_OBJECT FileObject
,
6289 PDEVICE_OBJECT DeviceObject
)
6292 return STATUS_NOT_IMPLEMENTED
;
6299 RxRemoveFromTopLevelIrpAllocatedContextsList(
6300 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6304 /* Make sure this is a TLC and that it was allocated (otherwise, it is not in the list */
6305 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6306 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6308 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
6309 RemoveEntryList(&TopLevelContext
->ListEntry
);
6310 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
6317 RxRemoveOverflowEntry(
6318 PRDBSS_DEVICE_OBJECT DeviceObject
,
6319 WORK_QUEUE_TYPE Queue
)
6322 PRX_CONTEXT Context
;
6324 KeAcquireSpinLock(&DeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
6325 if (DeviceObject
->OverflowQueueCount
[Queue
] <= 0)
6327 /* No entries left, nothing to return */
6328 InterlockedDecrement(&DeviceObject
->PostedRequestCount
[Queue
]);
6335 /* Decrement count */
6336 --DeviceObject
->OverflowQueueCount
[Queue
];
6339 Entry
= RemoveHeadList(&DeviceObject
->OverflowQueue
[Queue
]);
6340 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, OverflowListEntry
);
6341 ClearFlag(Context
->Flags
, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
| RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
6342 Context
->OverflowListEntry
.Flink
= NULL
;
6344 KeReleaseSpinLock(&DeviceObject
->OverflowQueueSpinLock
, OldIrql
);
6353 RxRemoveShareAccess(
6354 _Inout_ PFILE_OBJECT FileObject
,
6355 _Inout_ PSHARE_ACCESS ShareAccess
,
6357 _In_ PSZ wherelogtag
)
6361 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6362 IoRemoveShareAccess(FileObject
, ShareAccess
);
6363 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6370 RxRemoveShareAccessPerSrvOpens(
6371 IN OUT PSRV_OPEN SrvOpen
)
6373 ACCESS_MASK DesiredAccess
;
6375 BOOLEAN WriteAccess
;
6376 BOOLEAN DeleteAccess
;
6380 /* Get access that were granted to SRV_OPEN */
6381 DesiredAccess
= SrvOpen
->DesiredAccess
;
6382 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
6383 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
6384 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
6386 /* If any, drop them */
6387 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
6390 BOOLEAN SharedWrite
;
6391 BOOLEAN SharedDelete
;
6392 ULONG DesiredShareAccess
;
6393 PSHARE_ACCESS ShareAccess
;
6395 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
6396 DesiredShareAccess
= SrvOpen
->ShareAccess
;
6398 ShareAccess
->Readers
-= ReadAccess
;
6399 ShareAccess
->Writers
-= WriteAccess
;
6400 ShareAccess
->Deleters
-= DeleteAccess
;
6402 ShareAccess
->OpenCount
--;
6404 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
6405 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
6406 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
6407 ShareAccess
->SharedRead
-= SharedRead
;
6408 ShareAccess
->SharedWrite
-= SharedWrite
;
6409 ShareAccess
->SharedDelete
-= SharedDelete
;
6414 RxSearchForCollapsibleOpen(
6415 PRX_CONTEXT RxContext
,
6416 ACCESS_MASK DesiredAccess
,
6421 PLIST_ENTRY ListEntry
;
6422 BOOLEAN ShouldTry
, Purged
, Scavenged
;
6426 DPRINT("RxSearchForCollapsibleOpen(%p, %x, %x)\n", RxContext
, DesiredAccess
, ShareAccess
);
6428 Fcb
= (PFCB
)RxContext
->pFcb
;
6430 /* If we're asked to open for backup, don't allow SRV_OPEN reuse */
6431 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
6433 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6435 RxScavengeRelatedFobxs(Fcb
);
6436 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6438 return STATUS_NOT_FOUND
;
6441 /* If basic open, ask the mini-rdr if we should try to collapse */
6442 if (RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN
||
6443 RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN_IF
)
6447 if (Fcb
->MRxDispatch
!= NULL
)
6449 ASSERT(RxContext
->pRelevantSrvOpen
== NULL
);
6450 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
6452 ShouldTry
= NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
));
6460 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
))
6465 /* If we shouldn't try, ask the caller to allocate a new SRV_OPEN */
6468 if (NT_SUCCESS(RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
)))
6470 return STATUS_NOT_FOUND
;
6473 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6475 RxScavengeRelatedFobxs(Fcb
);
6476 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6478 return STATUS_NOT_FOUND
;
6481 /* Only collapse for matching NET_ROOT & disks */
6482 if (Fcb
->pNetRoot
!= RxContext
->Create
.pNetRoot
||
6483 Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
6485 return STATUS_NOT_FOUND
;
6490 Status
= STATUS_NOT_FOUND
;
6492 /* Browse all our SRV_OPEN to find the matching one */
6493 for (ListEntry
= Fcb
->SrvOpenList
.Flink
;
6494 ListEntry
!= &Fcb
->SrvOpenList
;
6495 ListEntry
= ListEntry
->Flink
)
6499 SrvOpen
= CONTAINING_RECORD(ListEntry
, SRV_OPEN
, SrvOpenQLinks
);
6500 /* Not the same VNET_ROOT, move to the next one */
6501 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
6503 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6507 /* Is there a sharing violation? */
6508 if (SrvOpen
->DesiredAccess
!= DesiredAccess
|| SrvOpen
->ShareAccess
!= ShareAccess
||
6509 BooleanFlagOn(SrvOpen
->Flags
, (SRVOPEN_FLAG_CLOSED
| SRVOPEN_FLAG_COLLAPSING_DISABLED
| SRVOPEN_FLAG_FILE_DELETED
| SRVOPEN_FLAG_FILE_RENAMED
)))
6511 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
6513 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6517 /* Check against the SRV_OPEN */
6518 Status
= RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
);
6519 if (!NT_SUCCESS(Status
))
6526 /* Don't allow collaspse for reparse point opening */
6527 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
^ SrvOpen
->CreateOptions
, FILE_OPEN_REPARSE_POINT
))
6531 Status
= STATUS_NOT_FOUND
;
6535 /* Not readonly? Or bytereange lock disabled? Try to collapse! */
6536 if (DisableByteRangeLockingOnReadOnlyFiles
|| !BooleanFlagOn(SrvOpen
->pFcb
->Attributes
, FILE_ATTRIBUTE_READONLY
))
6538 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
6540 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
6541 if (NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
)))
6543 /* Is close delayed - great reuse*/
6544 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
6546 DPRINT("Delayed close successfull, reusing %p\n", SrvOpen
);
6547 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
6548 ClearFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
6551 return STATUS_SUCCESS
;
6554 Status
= STATUS_NOT_FOUND
;
6559 /* We browse the whole list and didn't find any matching? NOT_FOUND */
6560 if (ListEntry
== &Fcb
->SrvOpenList
)
6562 Status
= STATUS_NOT_FOUND
;
6565 /* Only required access: read attributes? Don't reuse */
6566 if ((DesiredAccess
& 0xFFEFFFFF) == FILE_READ_ATTRIBUTES
)
6568 return STATUS_NOT_FOUND
;
6571 /* Not found? Scavenge and retry to look for collaspile SRV_OPEN */
6574 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
6576 RxScavengeRelatedFobxs(Fcb
);
6580 /* Not found? Purgeable? Purge and retry to look for collaspile SRV_OPEN */
6581 if (!Purged
&& RxIsOkToPurgeFcb(Fcb
))
6583 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
6588 /* If sharing violation, keep track of it */
6589 if (Status
== STATUS_SHARING_VIOLATION
)
6591 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
6594 DPRINT("Status: %x\n", Status
);
6603 _In_ ACCESS_MASK DesiredAccess
,
6604 _In_ ULONG DesiredShareAccess
,
6605 _Inout_ PFILE_OBJECT FileObject
,
6606 _Out_ PSHARE_ACCESS ShareAccess
,
6608 _In_ PSZ wherelogtag
)
6612 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6613 IoSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
);
6614 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6621 RxSetupNetFileObject(
6622 PRX_CONTEXT RxContext
)
6626 PFILE_OBJECT FileObject
;
6627 PIO_STACK_LOCATION Stack
;
6631 /* Assert FOBX is FOBX or NULL */
6632 Fobx
= (PFOBX
)RxContext
->pFobx
;
6633 ASSERT((Fobx
== NULL
) || (NodeType(Fobx
) == RDBSS_NTC_FOBX
));
6635 Fcb
= (PFCB
)RxContext
->pFcb
;
6636 Stack
= RxContext
->CurrentIrpSp
;
6637 FileObject
= Stack
->FileObject
;
6638 /* If it's temporary mark FO as such */
6639 if (Fcb
!= NULL
&& NodeType(Fcb
) != RDBSS_NTC_VCB
&&
6640 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TEMPORARY
))
6642 if (FileObject
== NULL
)
6647 FileObject
->Flags
|= FO_TEMPORARY_FILE
;
6650 /* No FO, nothing to setup */
6651 if (FileObject
== NULL
)
6656 /* Assign FCB & CCB (FOBX) to FO */
6657 FileObject
->FsContext
= Fcb
;
6658 FileObject
->FsContext2
= Fobx
;
6661 ULONG_PTR StackTop
, StackBottom
;
6663 /* If FO is allocated on pool, keep track of it */
6664 IoGetStackLimits(&StackTop
, &StackBottom
);
6665 if ((ULONG_PTR
)FileObject
<= StackBottom
|| (ULONG_PTR
)FileObject
>= StackTop
)
6667 Fobx
->AssociatedFileObject
= FileObject
;
6671 Fobx
->AssociatedFileObject
= NULL
;
6674 /* Make sure to mark FOBX if it's a DFS open */
6675 if (RxContext
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
))
6677 SetFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
6681 ClearFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
6685 /* Set Cc pointers */
6686 FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
6688 /* Update access state */
6689 if (Stack
->Parameters
.Create
.SecurityContext
!= NULL
)
6691 PACCESS_STATE AccessState
;
6693 AccessState
= Stack
->Parameters
.Create
.SecurityContext
->AccessState
;
6694 AccessState
->PreviouslyGrantedAccess
|= AccessState
->RemainingDesiredAccess
;
6695 AccessState
->RemainingDesiredAccess
= 0;
6705 IN PRX_CONTEXT RxContext
,
6706 OUT PBOOLEAN PostToFsp
)
6709 BOOLEAN Wait
, AlreadyStarted
;
6710 PRDBSS_DEVICE_OBJECT DeviceObject
;
6712 /* If we've not been post, then, do it */
6713 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
))
6715 SECURITY_SUBJECT_CONTEXT SubjectContext
;
6717 SeCaptureSubjectContext(&SubjectContext
);
6718 RxContext
->FsdUid
= RxGetUid(&SubjectContext
);
6719 SeReleaseSubjectContext(&SubjectContext
);
6722 return STATUS_PENDING
;
6725 /* Acquire all the required locks */
6726 Wait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
6727 if (!ExAcquireResourceExclusiveLite(&RxData
.Resource
, Wait
))
6730 return STATUS_PENDING
;
6733 if (!RxAcquirePrefixTableLockExclusive(RxContext
->RxDeviceObject
->pRxNetNameTable
, Wait
))
6735 ExReleaseResourceLite(&RxData
.Resource
);
6737 return STATUS_PENDING
;
6740 AlreadyStarted
= FALSE
;
6741 DeviceObject
= RxContext
->RxDeviceObject
;
6744 /* MUP handle set, means already registered */
6745 if (DeviceObject
->MupHandle
!= NULL
)
6747 AlreadyStarted
= TRUE
;
6748 Status
= STATUS_REDIRECTOR_STARTED
;
6752 /* If we're asked to register to MUP, then do it */
6753 Status
= STATUS_SUCCESS
;
6754 if (DeviceObject
->RegisterUncProvider
)
6756 Status
= FsRtlRegisterUncProvider(&DeviceObject
->MupHandle
,
6757 &DeviceObject
->DeviceName
,
6758 DeviceObject
->RegisterMailSlotProvider
);
6760 if (!NT_SUCCESS(Status
))
6762 DeviceObject
->MupHandle
= NULL
;
6766 /* Register as file system */
6767 IoRegisterFileSystem(&DeviceObject
->DeviceObject
);
6768 DeviceObject
->RegisteredAsFileSystem
= TRUE
;
6770 /* Inform mini-rdr it has to start */
6771 MINIRDR_CALL(Status
, RxContext
, DeviceObject
->Dispatch
, MRxStart
, (RxContext
, DeviceObject
));
6772 if (NT_SUCCESS(Status
))
6774 ++DeviceObject
->StartStopContext
.Version
;
6775 RxSetRdbssState(DeviceObject
, RDBSS_STARTED
);
6776 InterlockedExchangeAdd(&RxData
.NumberOfMinirdrsStarted
, 1);
6778 Status
= RxInitializeMRxDispatcher(DeviceObject
);
6783 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status
))
6785 if (!AlreadyStarted
)
6787 RxUnstart(RxContext
, DeviceObject
);
6791 RxReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
);
6792 ExReleaseResourceLite(&RxData
.Resource
);
6802 IN PRX_CONTEXT RxContext
,
6803 OUT PBOOLEAN PostToFsp
)
6806 return STATUS_NOT_IMPLEMENTED
;
6811 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6815 return STATUS_NOT_IMPLEMENTED
;
6822 RxTryToBecomeTheTopLevelIrp(
6823 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
6825 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6826 IN BOOLEAN ForceTopLevel
6829 BOOLEAN FromPool
= FALSE
;
6833 /* If not top level, and not have to be, quit */
6834 if (IoGetTopLevelIrp() && !ForceTopLevel
)
6839 /* If not TLC provider, allocate one */
6840 if (TopLevelContext
== NULL
)
6842 TopLevelContext
= RxAllocatePoolWithTag(NonPagedPool
, sizeof(RX_TOPLEVELIRP_CONTEXT
), RX_TLC_POOLTAG
);
6843 if (TopLevelContext
== NULL
)
6852 __RxInitializeTopLevelIrpContext(TopLevelContext
, Irp
, RxDeviceObject
, FromPool
);
6854 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6857 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6860 /* Make it top level IRP */
6861 IoSetTopLevelIrp((PIRP
)TopLevelContext
);
6869 RxUpdateShareAccess(
6870 _Inout_ PFILE_OBJECT FileObject
,
6871 _Inout_ PSHARE_ACCESS ShareAccess
,
6873 _In_ PSZ wherelogtag
)
6877 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6878 IoUpdateShareAccess(FileObject
, ShareAccess
);
6879 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6886 RxUninitializeCacheMap(
6887 PRX_CONTEXT RxContext
,
6888 PFILE_OBJECT FileObject
,
6889 PLARGE_INTEGER TruncateSize
)
6893 CACHE_UNINITIALIZE_EVENT UninitEvent
;
6897 Fcb
= FileObject
->FsContext
;
6898 ASSERT(NodeTypeIsFcb(Fcb
));
6899 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
6901 KeInitializeEvent(&UninitEvent
.Event
, SynchronizationEvent
, FALSE
);
6902 CcUninitializeCacheMap(FileObject
, TruncateSize
, &UninitEvent
);
6904 /* Always release the FCB before waiting for the uninit event */
6905 RxReleaseFcb(RxContext
, Fcb
);
6907 KeWaitForSingleObject(&UninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
6909 /* Re-acquire it afterwards */
6910 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
6911 ASSERT(NT_SUCCESS(Status
));
6917 IN PDRIVER_OBJECT DriverObject
)
6926 IN PFILE_LOCK_INFO LockInfo
)
6933 PRX_CONTEXT Context
,
6934 PRDBSS_DEVICE_OBJECT DeviceObject
)
6943 RxUnwindTopLevelIrp(
6944 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6946 DPRINT("RxUnwindTopLevelIrp(%p)\n", TopLevelContext
);
6948 /* No TLC provided? Ask the system for ours! */
6949 if (TopLevelContext
== NULL
)
6951 TopLevelContext
= (PRX_TOPLEVELIRP_CONTEXT
)IoGetTopLevelIrp();
6952 if (TopLevelContext
== NULL
)
6957 /* In that case, just assert it's really ours */
6958 ASSERT(RxIsThisAnRdbssTopLevelContext(TopLevelContext
));
6959 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6962 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6963 ASSERT(TopLevelContext
->Thread
== PsGetCurrentThread());
6964 /* Restore the previous top level IRP */
6965 IoSetTopLevelIrp(TopLevelContext
->Previous
);
6966 /* If TLC was allocated from pool, remove it from list and release it */
6967 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
6969 RxRemoveFromTopLevelIrpAllocatedContextsList(TopLevelContext
);
6970 RxFreePoolWithTag(TopLevelContext
, RX_TLC_POOLTAG
);
6978 RxUpdateShareAccessPerSrvOpens(
6979 IN PSRV_OPEN SrvOpen
)
6981 ACCESS_MASK DesiredAccess
;
6983 BOOLEAN WriteAccess
;
6984 BOOLEAN DeleteAccess
;
6988 /* If already updated, no need to continue */
6989 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
))
6994 /* Check if any access wanted */
6995 DesiredAccess
= SrvOpen
->DesiredAccess
;
6996 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
6997 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
6998 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
7000 /* In that case, update it */
7001 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
7004 BOOLEAN SharedWrite
;
7005 BOOLEAN SharedDelete
;
7006 ULONG DesiredShareAccess
;
7007 PSHARE_ACCESS ShareAccess
;
7009 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
7010 DesiredShareAccess
= SrvOpen
->ShareAccess
;
7012 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
7013 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
7014 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
7016 ShareAccess
->OpenCount
++;
7018 ShareAccess
->Readers
+= ReadAccess
;
7019 ShareAccess
->Writers
+= WriteAccess
;
7020 ShareAccess
->Deleters
+= DeleteAccess
;
7021 ShareAccess
->SharedRead
+= SharedRead
;
7022 ShareAccess
->SharedWrite
+= SharedWrite
;
7023 ShareAccess
->SharedDelete
+= SharedDelete
;
7026 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
);
7033 RxXXXControlFileCallthru(
7034 PRX_CONTEXT Context
)
7040 DPRINT("RxXXXControlFileCallthru(%p)\n", Context
);
7042 /* No dispatch table? Nothing to dispatch */
7043 if (Context
->RxDeviceObject
->Dispatch
== NULL
)
7045 Context
->pFobx
= NULL
;
7046 return STATUS_INVALID_DEVICE_REQUEST
;
7049 /* Init the lowio context */
7050 Status
= RxLowIoPopulateFsctlInfo(Context
);
7051 if (!NT_SUCCESS(Status
))
7056 /* Check whether we're consistent: a length means a buffer */
7057 if ((Context
->LowIoContext
.ParamsFor
.FsCtl
.InputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pInputBuffer
== NULL
) ||
7058 (Context
->LowIoContext
.ParamsFor
.FsCtl
.OutputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pOutputBuffer
== NULL
))
7060 return STATUS_INVALID_PARAMETER
;
7063 /* Forward the call to the mini-rdr */
7064 DPRINT("Calling: %p\n", Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile
);
7065 Status
= Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile(Context
);
7066 if (Status
!= STATUS_PENDING
)
7068 Context
->CurrentIrp
->IoStatus
.Information
= Context
->InformationToReturn
;
7071 DPRINT("RxXXXControlFileCallthru: %x, %ld\n", Context
->CurrentIrp
->IoStatus
.Status
, Context
->CurrentIrp
->IoStatus
.Information
);