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>
37 #define RX_TOPLEVELCTX_FLAG_FROM_POOL 1
41 (NTAPI
*PRX_FSD_DISPATCH
) (
44 typedef struct _RX_FSD_DISPATCH_VECTOR
46 PRX_FSD_DISPATCH CommonRoutine
;
47 } RX_FSD_DISPATCH_VECTOR
, *PRX_FSD_DISPATCH_VECTOR
;
51 RxAcquireFileForNtCreateSection(
52 PFILE_OBJECT FileObject
);
57 PFILE_OBJECT FileObject
,
58 PDEVICE_OBJECT DeviceObject
);
61 RxAddToTopLevelIrpAllocatedContextsList(
62 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
);
88 RxCommonDevFCBCleanup(
104 PRX_CONTEXT Context
);
108 RxCommonDevFCBQueryVolInfo(
109 PRX_CONTEXT Context
);
113 RxCommonDeviceControl(
114 PRX_CONTEXT Context
);
118 RxCommonDirectoryControl(
119 PRX_CONTEXT Context
);
123 RxCommonDispatchProblem(
124 PRX_CONTEXT Context
);
128 RxCommonFileSystemControl(
129 PRX_CONTEXT Context
);
133 RxCommonFlushBuffers(
134 PRX_CONTEXT Context
);
139 PRX_CONTEXT Context
);
144 PRX_CONTEXT Context
);
148 RxCommonQueryInformation(
149 PRX_CONTEXT Context
);
153 RxCommonQueryQuotaInformation(
154 PRX_CONTEXT Context
);
158 RxCommonQuerySecurity(
159 PRX_CONTEXT Context
);
163 RxCommonQueryVolumeInformation(
164 PRX_CONTEXT Context
);
169 PRX_CONTEXT Context
);
174 PRX_CONTEXT Context
);
178 RxCommonSetInformation(
179 PRX_CONTEXT Context
);
183 RxCommonSetQuotaInformation(
184 PRX_CONTEXT Context
);
189 PRX_CONTEXT Context
);
193 RxCommonSetVolumeInformation(
194 PRX_CONTEXT Context
);
198 RxCommonUnimplemented(
199 PRX_CONTEXT Context
);
204 PRX_CONTEXT Context
);
207 RxCopyCreateParameters(
208 IN PRX_CONTEXT RxContext
);
213 PUNICODE_STRING NetRootName
);
217 IN PRX_CONTEXT RxContext
);
221 RxFastIoCheckIfPossible(
222 PFILE_OBJECT FileObject
,
223 PLARGE_INTEGER FileOffset
,
224 ULONG Length
, BOOLEAN Wait
,
225 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
226 PIO_STATUS_BLOCK IoStatus
,
227 PDEVICE_OBJECT DeviceObject
);
231 RxFastIoDeviceControl(
232 PFILE_OBJECT FileObject
,
234 PVOID InputBuffer OPTIONAL
,
235 ULONG InputBufferLength
,
236 PVOID OutputBuffer OPTIONAL
,
237 ULONG OutputBufferLength
,
239 PIO_STATUS_BLOCK IoStatus
,
240 PDEVICE_OBJECT DeviceObject
);
245 PFILE_OBJECT FileObject
,
246 PLARGE_INTEGER FileOffset
,
251 PIO_STATUS_BLOCK IoStatus
,
252 PDEVICE_OBJECT DeviceObject
);
257 PFILE_OBJECT FileObject
,
258 PLARGE_INTEGER FileOffset
,
263 PIO_STATUS_BLOCK IoStatus
,
264 PDEVICE_OBJECT DeviceObject
);
268 PRX_CONTEXT RxContext
,
269 PUNICODE_STRING NetRootName
);
273 PRX_CONTEXT RxContext
,
274 PUNICODE_STRING FileName
,
275 PUNICODE_STRING CanonicalName
,
276 PNET_ROOT_TYPE NetRootType
);
279 RxFreeCanonicalNameBuffer(
280 PRX_CONTEXT Context
);
289 RxGetRegistryParameters(
290 IN PUNICODE_STRING RegistryPath
);
294 RxGetStringRegistryParameter(
297 OUT PUNICODE_STRING OutString
,
299 IN ULONG BufferLength
,
300 IN BOOLEAN LogFailure
);
304 RxInitializeDebugSupport(
309 RxInitializeDispatchVectors(
310 PDRIVER_OBJECT DriverObject
);
314 RxInitializeRegistrationStructures(
319 RxInitializeTopLevelIrpPackage(
325 PDRIVER_OBJECT DriverObject
,
329 RxIsThisAnRdbssTopLevelContext(
330 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
);
334 RxLowIoIoCtlShellCompletion(
335 PRX_CONTEXT RxContext
);
339 PRX_CONTEXT RxContext
);
343 RxLowIoReadShellCompletion(
344 PRX_CONTEXT RxContext
);
348 PRX_CONTEXT RxContext
);
351 RxNotifyChangeDirectory(
352 PRX_CONTEXT RxContext
);
356 PRX_CONTEXT RxContext
,
357 FILE_INFORMATION_CLASS FileInfoClass
,
361 RxQueryAlternateNameInfo(
362 PRX_CONTEXT RxContext
,
363 PFILE_NAME_INFORMATION AltNameInfo
);
367 PRX_CONTEXT RxContext
,
368 PFILE_BASIC_INFORMATION BasicInfo
);
371 RxQueryCompressedInfo(
372 PRX_CONTEXT RxContext
,
373 PFILE_COMPRESSION_INFORMATION CompressionInfo
);
377 PRX_CONTEXT RxContext
);
381 PRX_CONTEXT RxContext
,
382 PFILE_EA_INFORMATION EaInfo
);
386 PRX_CONTEXT RxContext
,
387 PFILE_INTERNAL_INFORMATION InternalInfo
);
391 PRX_CONTEXT RxContext
,
392 PFILE_NAME_INFORMATION NameInfo
);
396 PRX_CONTEXT RxContext
,
397 PFILE_PIPE_INFORMATION PipeInfo
);
401 PRX_CONTEXT RxContext
,
402 PFILE_POSITION_INFORMATION PositionInfo
);
406 PRX_CONTEXT RxContext
,
407 PFILE_STANDARD_INFORMATION StandardInfo
);
411 RxReadRegistryParameters(
416 RxReleaseFileForNtCreateSection(
417 PFILE_OBJECT FileObject
);
422 PFILE_OBJECT FileObject
,
423 PDEVICE_OBJECT DeviceObject
);
426 RxRemoveOverflowEntry(
427 PRDBSS_DEVICE_OBJECT DeviceObject
,
428 WORK_QUEUE_TYPE Queue
);
431 RxSearchForCollapsibleOpen(
432 PRX_CONTEXT RxContext
,
433 ACCESS_MASK DesiredAccess
,
437 RxSetupNetFileObject(
438 PRX_CONTEXT RxContext
);
442 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
446 RxUninitializeCacheMap(
447 PRX_CONTEXT RxContext
,
448 PFILE_OBJECT FileObject
,
449 PLARGE_INTEGER TruncateSize
);
454 PRDBSS_DEVICE_OBJECT DeviceObject
);
457 RxXXXControlFileCallthru(
458 PRX_CONTEXT Context
);
462 _RxAllocatePoolWithTag(
463 _In_ POOL_TYPE PoolType
,
464 _In_ SIZE_T NumberOfBytes
,
478 WCHAR RxStarForTemplate
= '*';
479 WCHAR Rx8QMdot3QM
[] = L
">>>>>>>>.>>>*";
480 BOOLEAN DisableByteRangeLockingOnReadOnlyFiles
= FALSE
;
481 BOOLEAN DisableFlushOnCleanup
= FALSE
;
482 ULONG ReadAheadGranularity
= 1 << PAGE_SHIFT
;
483 LIST_ENTRY RxActiveContexts
;
484 NPAGED_LOOKASIDE_LIST RxContextLookasideList
;
485 FAST_MUTEX RxContextPerFileSerializationMutex
;
488 RX_FSD_DISPATCH_VECTOR RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
490 { RxCommonDispatchProblem
},
491 { RxCommonDispatchProblem
},
492 { RxCommonDevFCBClose
},
493 { RxCommonDispatchProblem
},
494 { RxCommonDispatchProblem
},
495 { RxCommonDispatchProblem
},
496 { RxCommonDispatchProblem
},
497 { RxCommonDispatchProblem
},
498 { RxCommonDispatchProblem
},
499 { RxCommonDispatchProblem
},
500 { RxCommonDevFCBQueryVolInfo
},
501 { RxCommonDispatchProblem
},
502 { RxCommonDispatchProblem
},
503 { RxCommonDevFCBFsCtl
},
504 { RxCommonDevFCBIoCtl
},
505 { RxCommonDevFCBIoCtl
},
506 { RxCommonDispatchProblem
},
507 { RxCommonDispatchProblem
},
508 { RxCommonDevFCBCleanup
},
509 { RxCommonDispatchProblem
},
510 { RxCommonDispatchProblem
},
511 { RxCommonDispatchProblem
},
512 { RxCommonUnimplemented
},
513 { RxCommonUnimplemented
},
514 { RxCommonUnimplemented
},
515 { RxCommonUnimplemented
},
516 { RxCommonUnimplemented
},
517 { RxCommonUnimplemented
},
519 RDBSS_EXPORTS RxExports
;
520 FAST_IO_DISPATCH RxFastIoDispatch
;
521 PRDBSS_DEVICE_OBJECT RxFileSystemDeviceObject
;
522 RX_FSD_DISPATCH_VECTOR RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
+ 1] =
525 { RxCommonUnimplemented
},
529 { RxCommonQueryInformation
},
530 { RxCommonSetInformation
},
533 { RxCommonFlushBuffers
},
534 { RxCommonQueryVolumeInformation
},
535 { RxCommonSetVolumeInformation
},
536 { RxCommonDirectoryControl
},
537 { RxCommonFileSystemControl
},
538 { RxCommonDeviceControl
},
539 { RxCommonDeviceControl
},
540 { RxCommonUnimplemented
},
541 { RxCommonLockControl
},
543 { RxCommonUnimplemented
},
544 { RxCommonQuerySecurity
},
545 { RxCommonSetSecurity
},
546 { RxCommonUnimplemented
},
547 { RxCommonUnimplemented
},
548 { RxCommonUnimplemented
},
549 { RxCommonQueryQuotaInformation
},
550 { RxCommonSetQuotaInformation
},
551 { RxCommonUnimplemented
},
553 ULONG RxFsdEntryCount
;
554 LIST_ENTRY RxIrpsList
;
555 KSPIN_LOCK RxIrpsListSpinLock
;
556 KMUTEX RxScavengerMutex
;
557 KMUTEX RxSerializationMutex
;
558 UCHAR RxSpaceForTheWrappersDeviceObject
[sizeof(*RxFileSystemDeviceObject
)];
559 KSPIN_LOCK TopLevelIrpSpinLock
;
560 LIST_ENTRY TopLevelIrpAllocatedContextsList
;
561 BOOLEAN RxForceQFIPassThrough
= FALSE
;
563 DECLARE_CONST_UNICODE_STRING(unknownId
, L
"???");
570 #define ASSERT(exp) \
573 RxAssert(#exp, __FILE__, __LINE__, NULL); \
578 #undef RxAllocatePool
579 #undef RxAllocatePoolWithTag
582 #define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
583 #define RxAllocatePoolWithTag _RxAllocatePoolWithTag
584 #define RxFreePool _RxFreePool
585 #define RxFreePoolWithTag _RxFreePoolWithTag
588 /* FUNCTIONS ****************************************************************/
591 CheckForLoudOperations(
592 PRX_CONTEXT RxContext
)
601 __RxInitializeTopLevelIrpContext(
602 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
604 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
607 DPRINT("__RxInitializeTopLevelIrpContext(%p, %p, %p, %u)\n", TopLevelContext
, Irp
, RxDeviceObject
, Flags
);
609 RtlZeroMemory(TopLevelContext
, sizeof(RX_TOPLEVELIRP_CONTEXT
));
610 TopLevelContext
->Irp
= Irp
;
611 TopLevelContext
->Flags
= (Flags
? RX_TOPLEVELCTX_FLAG_FROM_POOL
: 0);
612 TopLevelContext
->Signature
= RX_TOPLEVELIRP_CONTEXT_SIGNATURE
;
613 TopLevelContext
->RxDeviceObject
= RxDeviceObject
;
614 TopLevelContext
->Previous
= IoGetTopLevelIrp();
615 TopLevelContext
->Thread
= PsGetCurrentThread();
617 /* We cannot add to list something that'd come from stack */
618 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
620 RxAddToTopLevelIrpAllocatedContextsList(TopLevelContext
);
626 RxAcquireExclusiveFcbResourceInMRx(
627 _Inout_ PMRX_FCB Fcb
)
630 return STATUS_NOT_IMPLEMENTED
;
635 RxAcquireFcbForLazyWrite(
645 RxAcquireFcbForReadAhead(
655 RxAcquireFileForNtCreateSection(
656 PFILE_OBJECT FileObject
)
664 PFILE_OBJECT FileObject
,
665 PDEVICE_OBJECT DeviceObject
)
668 return STATUS_NOT_IMPLEMENTED
;
675 RxAddToTopLevelIrpAllocatedContextsList(
676 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
680 DPRINT("RxAddToTopLevelIrpAllocatedContextsList(%p)\n", TopLevelContext
);
682 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
683 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
685 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
686 InsertTailList(&TopLevelIrpAllocatedContextsList
, &TopLevelContext
->ListEntry
);
687 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
695 IN PRX_CONTEXT RxContext
,
700 WORK_QUEUE_TYPE Queue
;
701 PIO_STACK_LOCATION Stack
;
703 Stack
= RxContext
->CurrentIrpSp
;
704 RxContext
->PostRequest
= FALSE
;
706 /* First of all, select the appropriate queue - delayed for prefix claim, critical for the rest */
707 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
&&
708 Stack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
710 Queue
= DelayedWorkQueue
;
711 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
);
715 Queue
= CriticalWorkQueue
;
716 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
);
719 /* Check for overflow */
720 if (Stack
->FileObject
!= NULL
)
722 KeAcquireSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
724 Queued
= InterlockedIncrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
725 /* In case of an overflow, add the new queued call to the overflow list */
728 InterlockedDecrement(&RxFileSystemDeviceObject
->PostedRequestCount
[Queue
]);
729 InsertTailList(&RxFileSystemDeviceObject
->OverflowQueue
[Queue
], &RxContext
->OverflowListEntry
);
730 ++RxFileSystemDeviceObject
->OverflowQueueCount
[Queue
];
732 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
736 KeReleaseSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
, OldIrql
);
739 ExInitializeWorkItem(&RxContext
->WorkQueueItem
, RxFspDispatch
, RxContext
);
740 ExQueueWorkItem((PWORK_QUEUE_ITEM
)&RxContext
->WorkQueueItem
, Queue
);
747 RxAllocateCanonicalNameBuffer(
748 PRX_CONTEXT RxContext
,
749 PUNICODE_STRING CanonicalName
,
750 USHORT CanonicalLength
)
754 DPRINT("RxContext: %p - CanonicalNameBuffer: %p\n", RxContext
, RxContext
->Create
.CanonicalNameBuffer
);
756 /* Context must be free of any already allocated name */
757 ASSERT(RxContext
->Create
.CanonicalNameBuffer
== NULL
);
759 /* Validate string length */
760 if (CanonicalLength
> USHRT_MAX
- 1)
762 CanonicalName
->Buffer
= NULL
;
763 return STATUS_OBJECT_PATH_INVALID
;
766 CanonicalName
->Buffer
= RxAllocatePoolWithTag(PagedPool
| POOL_COLD_ALLOCATION
, CanonicalLength
, RX_MISC_POOLTAG
);
767 if (CanonicalName
->Buffer
== NULL
)
769 return STATUS_INSUFFICIENT_RESOURCES
;
772 CanonicalName
->Length
= 0;
773 CanonicalName
->MaximumLength
= CanonicalLength
;
775 /* Set the two places - they must always be identical */
776 RxContext
->Create
.CanonicalNameBuffer
= CanonicalName
->Buffer
;
777 RxContext
->AlsoCanonicalNameBuffer
= CanonicalName
->Buffer
;
779 return STATUS_SUCCESS
;
785 PDEVICE_OBJECT DeviceObject
,
795 RxCanonicalizeFileNameByServerSpecs(
796 PRX_CONTEXT RxContext
,
797 PUNICODE_STRING NetRootName
)
799 USHORT NextChar
, CurChar
;
804 /* Validate file name is not empty */
805 MaxChars
= NetRootName
->Length
/ sizeof(WCHAR
);
808 return STATUS_MORE_PROCESSING_REQUIRED
;
811 /* Validate name is correct */
812 for (NextChar
= 0; CurChar
+ 1 < MaxChars
; NextChar
= CurChar
+ 1)
816 for (i
= NextChar
+ 1; i
< MaxChars
; ++i
)
818 if (NetRootName
->Buffer
[i
] == '\\' || NetRootName
->Buffer
[i
] == ':')
825 if (CurChar
== NextChar
)
827 if (((NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':') || NextChar
== (MaxChars
- 1)) && NetRootName
->Buffer
[NextChar
] != '.')
834 if (CurChar
>= MaxChars
- 1)
839 if (NetRootName
->Buffer
[CurChar
+ 1] != ':')
841 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
846 if (NetRootName
->Buffer
[1] != ':')
848 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
854 if ((CurChar
- NextChar
) == 1)
856 if (NetRootName
->Buffer
[NextChar
+ 2] != '.')
861 if (NetRootName
->Buffer
[NextChar
] == '\\' || NetRootName
->Buffer
[NextChar
] == ':' || NetRootName
->Buffer
[NextChar
] == '.')
863 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
868 if ((CurChar
- NextChar
) != 2 || (NetRootName
->Buffer
[NextChar
] != '\\' && NetRootName
->Buffer
[NextChar
] != ':')
869 || NetRootName
->Buffer
[NextChar
+ 1] != '.')
874 if (NetRootName
->Buffer
[NextChar
+ 2] == '.')
876 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
882 return STATUS_MORE_PROCESSING_REQUIRED
;
886 RxCanonicalizeNameAndObtainNetRoot(
887 PRX_CONTEXT RxContext
,
888 PUNICODE_STRING FileName
,
889 PUNICODE_STRING NetRootName
)
892 NET_ROOT_TYPE NetRootType
;
893 UNICODE_STRING CanonicalName
;
897 NetRootType
= NET_ROOT_WILD
;
899 RtlInitEmptyUnicodeString(NetRootName
, NULL
, 0);
900 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
902 /* if not relative opening, just handle the passed name */
903 if (RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
== NULL
)
905 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
906 if (!NT_SUCCESS(Status
))
915 /* Make sure we have a valid FCB and a FOBX */
916 Fcb
= RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext
;
918 RxContext
->CurrentIrpSp
->FileObject
->RelatedFileObject
->FsContext2
== NULL
)
920 return STATUS_INVALID_PARAMETER
;
923 if (!NodeTypeIsFcb(Fcb
))
925 return STATUS_INVALID_PARAMETER
;
931 /* Get/Create the associated VNetRoot for opening */
932 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
933 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
&&
934 BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_MAILSLOT_REPARSE
))
936 ASSERT(CanonicalName
.Buffer
== RxContext
->Create
.CanonicalNameBuffer
);
938 RxFreeCanonicalNameBuffer(RxContext
);
939 Status
= RxFirstCanonicalize(RxContext
, FileName
, &CanonicalName
, &NetRootType
);
940 if (NT_SUCCESS(Status
))
942 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, NetRootName
);
946 /* Filename cannot contain wildcards */
947 if (FsRtlDoesNameContainWildCards(NetRootName
))
949 Status
= STATUS_OBJECT_NAME_INVALID
;
952 /* Make sure file name is correct */
953 if (NT_SUCCESS(Status
))
955 Status
= RxCanonicalizeFileNameByServerSpecs(RxContext
, NetRootName
);
958 /* Give the mini-redirector a chance to prepare the name */
959 if (NT_SUCCESS(Status
) || Status
== STATUS_MORE_PROCESSING_REQUIRED
)
961 if (RxContext
->Create
.pNetRoot
!= NULL
)
963 NTSTATUS IgnoredStatus
;
965 MINIRDR_CALL(IgnoredStatus
, RxContext
, RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
966 MRxPreparseName
, (RxContext
, NetRootName
));
976 RxChangeBufferingState(
979 BOOLEAN ComputeNewState
)
982 return STATUS_NOT_IMPLEMENTED
;
987 RxCheckFcbStructuresForAlignment(
995 _In_ ACCESS_MASK DesiredAccess
,
996 _In_ ULONG DesiredShareAccess
,
997 _Inout_ PFILE_OBJECT FileObject
,
998 _Inout_ PSHARE_ACCESS ShareAccess
,
1001 _In_ PSZ wherelogtag
)
1005 RxDumpWantedAccess(where
, "", wherelogtag
, DesiredAccess
, DesiredShareAccess
);
1006 RxDumpCurrentAccess(where
, "", wherelogtag
, ShareAccess
);
1008 return IoCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
, Update
);
1015 RxCheckShareAccessPerSrvOpens(
1017 IN ACCESS_MASK DesiredAccess
,
1018 IN ULONG DesiredShareAccess
)
1021 BOOLEAN WriteAccess
;
1022 BOOLEAN DeleteAccess
;
1023 PSHARE_ACCESS ShareAccess
;
1027 ShareAccess
= &Fcb
->ShareAccessPerSrvOpens
;
1029 RxDumpWantedAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", DesiredAccess
, DesiredShareAccess
);
1030 RxDumpCurrentAccess("RxCheckShareAccessPerSrvOpens", "", "RxCheckShareAccessPerSrvOpens", ShareAccess
);
1032 /* Check if any access wanted */
1033 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
1034 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
1035 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
1037 if (ReadAccess
|| WriteAccess
|| DeleteAccess
)
1039 BOOLEAN SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
1040 BOOLEAN SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
1041 BOOLEAN SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
1043 /* Check whether there's a violation */
1045 (ShareAccess
->SharedRead
< ShareAccess
->OpenCount
)) ||
1047 (ShareAccess
->SharedWrite
< ShareAccess
->OpenCount
)) ||
1049 (ShareAccess
->SharedDelete
< ShareAccess
->OpenCount
)) ||
1050 ((ShareAccess
->Readers
!= 0) && !SharedRead
) ||
1051 ((ShareAccess
->Writers
!= 0) && !SharedWrite
) ||
1052 ((ShareAccess
->Deleters
!= 0) && !SharedDelete
))
1054 return STATUS_SHARING_VIOLATION
;
1058 return STATUS_SUCCESS
;
1062 RxCloseAssociatedSrvOpen(
1064 IN PRX_CONTEXT RxContext OPTIONAL
)
1067 return STATUS_NOT_IMPLEMENTED
;
1074 RxCollapseOrCreateSrvOpen(
1075 PRX_CONTEXT RxContext
)
1082 PIO_STACK_LOCATION Stack
;
1083 ACCESS_MASK DesiredAccess
;
1084 RX_BLOCK_CONDITION FcbCondition
;
1088 DPRINT("RxCollapseOrCreateSrvOpen(%p)\n", RxContext
);
1090 Fcb
= (PFCB
)RxContext
->pFcb
;
1091 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1092 ++Fcb
->UncleanCount
;
1094 Stack
= RxContext
->CurrentIrpSp
;
1095 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
1096 ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
1098 Disposition
= RxContext
->Create
.NtCreateParameters
.Disposition
;
1100 /* Try to find a reusable SRV_OPEN */
1101 Status
= RxSearchForCollapsibleOpen(RxContext
, DesiredAccess
, ShareAccess
);
1102 if (Status
== STATUS_NOT_FOUND
)
1104 /* If none found, create one */
1105 SrvOpen
= RxCreateSrvOpen((PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
, Fcb
);
1106 if (SrvOpen
== NULL
)
1108 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1112 SrvOpen
->DesiredAccess
= DesiredAccess
;
1113 SrvOpen
->ShareAccess
= ShareAccess
;
1114 Status
= STATUS_SUCCESS
;
1117 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
1119 if (Status
!= STATUS_SUCCESS
)
1121 FcbCondition
= Condition_Bad
;
1125 RxInitiateSrvOpenKeyAssociation(SrvOpen
);
1127 /* Cookie to check the mini-rdr doesn't mess with RX_CONTEXT */
1128 RxContext
->CurrentIrp
->IoStatus
.Information
= 0xABCDEF;
1129 /* Inform the mini-rdr we're handling a create */
1130 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCreate
, (RxContext
));
1131 ASSERT(RxContext
->CurrentIrp
->IoStatus
.Information
== 0xABCDEF);
1133 DPRINT("MRxCreate returned: %x\n", Status
);
1134 if (Status
== STATUS_SUCCESS
)
1136 /* In case of overwrite, reset file size */
1137 if (Disposition
== FILE_OVERWRITE
|| Disposition
== FILE_OVERWRITE_IF
)
1139 RxAcquirePagingIoResource(RxContext
, Fcb
);
1140 Fcb
->Header
.AllocationSize
.QuadPart
= 0LL;
1141 Fcb
->Header
.FileSize
.QuadPart
= 0LL;
1142 Fcb
->Header
.ValidDataLength
.QuadPart
= 0LL;
1143 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1144 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1145 RxReleasePagingIoResource(RxContext
, Fcb
);
1149 /* Otherwise, adjust sizes */
1150 RxContext
->CurrentIrpSp
->FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
1151 if (CcIsFileCached(RxContext
->CurrentIrpSp
->FileObject
))
1153 RxAdjustAllocationSizeforCC(Fcb
);
1155 CcSetFileSizes(RxContext
->CurrentIrpSp
->FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
);
1159 /* Set the IoStatus with information returned by mini-rdr */
1160 RxContext
->CurrentIrp
->IoStatus
.Information
= RxContext
->Create
.ReturnedCreateInformation
;
1162 SrvOpen
->OpenStatus
= Status
;
1163 /* Set SRV_OPEN state - good or bad - depending on whether create succeed */
1164 RxTransitionSrvOpen(SrvOpen
, (Status
== STATUS_SUCCESS
? Condition_Good
: Condition_Bad
));
1166 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1168 RxCompleteSrvOpenKeyAssociation(SrvOpen
);
1170 if (Status
== STATUS_SUCCESS
)
1172 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
1174 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
1176 SrvOpen
->CreateOptions
= RxContext
->Create
.NtCreateParameters
.CreateOptions
;
1177 FcbCondition
= Condition_Good
;
1181 FcbCondition
= Condition_Bad
;
1182 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1183 RxContext
->pRelevantSrvOpen
= NULL
;
1185 if (RxContext
->pFobx
!= NULL
)
1187 RxDereferenceNetFobx(RxContext
->pFobx
, LHS_ExclusiveLockHeld
);
1188 RxContext
->pFobx
= NULL
;
1193 /* Set FCB state - good or bad - depending on whether create succeed */
1194 DPRINT("Transitioning FCB %p to condition %lx\n", Fcb
, Fcb
->Condition
);
1195 RxTransitionNetFcb(Fcb
, FcbCondition
);
1197 else if (Status
== STATUS_SUCCESS
)
1199 BOOLEAN IsGood
, ExtraOpen
;
1201 /* A reusable SRV_OPEN was found */
1202 RxContext
->CurrentIrp
->IoStatus
.Information
= FILE_OPENED
;
1205 SrvOpen
= (PSRV_OPEN
)RxContext
->pRelevantSrvOpen
;
1207 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1208 /* If the SRV_OPEN isn't in a stable situation, wait for it to become stable */
1209 if (!StableCondition(SrvOpen
->Condition
))
1211 RxReferenceSrvOpen(SrvOpen
);
1212 ++SrvOpen
->OpenCount
;
1215 RxReleaseFcb(RxContext
, Fcb
);
1216 RxContext
->Create
.FcbAcquired
= FALSE
;
1218 RxWaitForStableSrvOpen(SrvOpen
, RxContext
);
1220 if (NT_SUCCESS(RxAcquireExclusiveFcb(RxContext
, Fcb
)))
1222 RxContext
->Create
.FcbAcquired
= TRUE
;
1225 IsGood
= (SrvOpen
->Condition
== Condition_Good
);
1228 /* Inform the mini-rdr we do an opening with a reused SRV_OPEN */
1231 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxCollapseOpen
, (RxContext
));
1233 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
1237 Status
= SrvOpen
->OpenStatus
;
1242 --SrvOpen
->OpenCount
;
1243 RxDereferenceSrvOpen(SrvOpen
, LHS_ExclusiveLockHeld
);
1247 --Fcb
->UncleanCount
;
1249 DPRINT("Status: %x\n", Status
);
1256 PRX_CONTEXT Context
)
1258 #define BugCheckFileId RDBSS_BUG_CHECK_CLEANUP
1263 PFILE_OBJECT FileObject
;
1267 Fcb
= (PFCB
)Context
->pFcb
;
1268 Fobx
= (PFOBX
)Context
->pFobx
;
1269 DPRINT("RxCommonCleanup(%p); FOBX: %p, FCB: %p\n", Context
, Fobx
, Fcb
);
1271 /* File system closing, it's OK */
1274 if (Fcb
->UncleanCount
> 0)
1276 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1279 return STATUS_SUCCESS
;
1282 /* Check we have a correct FCB type */
1283 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&&
1284 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&&
1285 NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1286 NodeType(Fcb
) != RDBSS_NTC_SPOOLFILE
)
1288 DPRINT1("Invalid Fcb type for %p\n", Fcb
);
1289 RxBugCheck(Fcb
->Header
.NodeTypeCode
, 0, 0);
1292 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1293 ASSERT(!BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
));
1295 RxMarkFobxOnCleanup(Fobx
, &NeedPurge
);
1297 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1298 if (!NT_SUCCESS(Status
))
1303 Fobx
->AssociatedFileObject
= NULL
;
1305 /* In case SRV_OPEN used is part of FCB */
1306 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_SRVOPEN_USED
))
1308 ASSERT(Fcb
->UncleanCount
!= 0);
1309 InterlockedDecrement((volatile long *)&Fcb
->UncleanCount
);
1311 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
1313 --Fcb
->UncachedUncleanCount
;
1316 /* Inform mini-rdr */
1317 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxCleanupFobx
, (Context
));
1319 ASSERT(Fobx
->SrvOpen
->UncleanFobxCount
!= 0);
1320 --Fobx
->SrvOpen
->UncleanFobxCount
;
1322 RxUninitializeCacheMap(Context
, FileObject
, NULL
);
1324 RxReleaseFcb(Context
, Fcb
);
1326 return STATUS_SUCCESS
;
1330 return STATUS_NOT_IMPLEMENTED
;
1331 #undef BugCheckFileId
1337 PRX_CONTEXT Context
)
1339 #define BugCheckFileId RDBSS_BUG_CHECK_CLOSE
1343 PFILE_OBJECT FileObject
;
1344 BOOLEAN DereferenceFobx
, AcquiredFcb
;
1348 Fcb
= (PFCB
)Context
->pFcb
;
1349 Fobx
= (PFOBX
)Context
->pFobx
;
1350 FileObject
= Context
->CurrentIrpSp
->FileObject
;
1351 DPRINT("RxCommonClose(%p); FOBX: %p, FCB: %p, FO: %p\n", Context
, Fobx
, Fcb
, FileObject
);
1353 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1354 if (!NT_SUCCESS(Status
))
1364 /* Check our FCB type is expected */
1365 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
&&
1366 (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
|| (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
&&
1367 (NodeType(Fcb
) < RDBSS_NTC_SPOOLFILE
|| NodeType(Fcb
) > RDBSS_NTC_OPENTARGETDIR_FCB
))))
1369 RxBugCheck(NodeType(Fcb
), 0, 0);
1372 RxReferenceNetFcb(Fcb
);
1374 DereferenceFobx
= FALSE
;
1375 /* If we're not closing FS */
1381 SrvOpen
= (PSRV_OPEN
)Fobx
->pSrvOpen
;
1382 SrvCall
= (PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
;
1383 /* Handle delayed close */
1384 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
1386 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
| FCB_STATE_ORPHANED
))
1388 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
))
1390 DPRINT("Delay close for FOBX: %p, SrvOpen %p\n", Fobx
, SrvOpen
);
1392 if (SrvOpen
->OpenCount
== 1 && !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_COLLAPSING_DISABLED
))
1394 if (InterlockedIncrement(&SrvCall
->NumberOfCloseDelayedFiles
) >= SrvCall
->MaximumNumberOfCloseDelayedFiles
)
1396 InterlockedDecrement(&SrvCall
->NumberOfCloseDelayedFiles
);
1400 DereferenceFobx
= TRUE
;
1401 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
1408 /* If we reach maximum of delayed close/or if there are no delayed close */
1409 if (!DereferenceFobx
)
1413 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
1414 if (NetRoot
->Type
!= NET_ROOT_PRINT
)
1416 /* Delete if asked */
1417 if (BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
))
1419 RxScavengeRelatedFobxs(Fcb
);
1420 RxSynchronizeWithScavenger(Context
);
1422 RxReleaseFcb(Context
, Fcb
);
1424 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
1425 RxOrphanThisFcb(Fcb
);
1426 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
1428 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1429 ASSERT(NT_SUCCESS(Status
));
1434 RxMarkFobxOnClose(Fobx
);
1437 if (DereferenceFobx
)
1439 ASSERT(Fobx
!= NULL
);
1440 RxDereferenceNetFobx(Fobx
, LHS_SharedLockHeld
);
1444 RxCloseAssociatedSrvOpen(Fobx
, Context
);
1447 RxDereferenceNetFobx(Fobx
, LHS_ExclusiveLockHeld
);
1451 Freed
= RxDereferenceAndFinalizeNetFcb(Fcb
, Context
, FALSE
, FALSE
);
1452 AcquiredFcb
= !Freed
;
1454 FileObject
->FsContext
= (PVOID
)-1;
1458 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
1462 RxReleaseFcb(Context
, Fcb
);
1463 AcquiredFcb
= FALSE
;
1468 if (_SEH2_AbnormalTermination())
1472 RxReleaseFcb(Context
, Fcb
);
1477 ASSERT(!AcquiredFcb
);
1482 DPRINT("Status: %x\n", Status
);
1484 #undef BugCheckFileId
1490 PRX_CONTEXT Context
)
1494 PFILE_OBJECT FileObject
;
1495 PIO_STACK_LOCATION Stack
;
1499 DPRINT("RxCommonCreate(%p)\n", Context
);
1501 Irp
= Context
->CurrentIrp
;
1502 Stack
= Context
->CurrentIrpSp
;
1503 FileObject
= Stack
->FileObject
;
1505 /* Check whether that's a device opening */
1506 if (FileObject
->FileName
.Length
== 0 && FileObject
->RelatedFileObject
== NULL
)
1508 FileObject
->FsContext
= &RxDeviceFCB
;
1509 FileObject
->FsContext2
= NULL
;
1511 ++RxDeviceFCB
.NodeReferenceCount
;
1512 ++RxDeviceFCB
.OpenCount
;
1514 Irp
->IoStatus
.Information
= FILE_OPENED
;
1515 DPRINT("Device opening FO: %p, DO: %p, Name: %wZ\n", FileObject
, Context
->RxDeviceObject
, &Context
->RxDeviceObject
->DeviceName
);
1517 Status
= STATUS_SUCCESS
;
1521 PFCB RelatedFcb
= NULL
;
1523 /* Make sure caller is consistent */
1524 if (FlagOn(Stack
->Parameters
.Create
.Options
, FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
) ==
1525 (FILE_DIRECTORY_FILE
| FILE_NON_DIRECTORY_FILE
| FILE_OPEN_REMOTE_INSTANCE
))
1527 DPRINT1("Create.Options: %x\n", Stack
->Parameters
.Create
.Options
);
1528 return STATUS_INVALID_PARAMETER
;
1531 DPRINT("Ctxt: %p, FO: %p, Options: %lx, Flags: %lx, Attr: %lx, ShareAccess: %lx, DesiredAccess: %lx\n",
1532 Context
, FileObject
, Stack
->Parameters
.Create
.Options
, Stack
->Flags
, Stack
->Parameters
.Create
.FileAttributes
,
1533 Stack
->Parameters
.Create
.ShareAccess
, Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
);
1534 DPRINT("FileName: %wZ\n", &FileObject
->FileName
);
1536 if (FileObject
->RelatedFileObject
!= NULL
)
1538 RelatedFcb
= FileObject
->RelatedFileObject
->FsContext
;
1539 DPRINT("Rel FO: %p, path: %wZ\n", FileObject
->RelatedFileObject
, RelatedFcb
->FcbTableEntry
.Path
);
1542 /* Going to rename? */
1543 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
1545 DPRINT("TargetDir!\n");
1548 /* Copy create parameters to the context */
1549 RxCopyCreateParameters(Context
);
1551 /* If the caller wants to establish a connection, go ahead */
1552 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_CREATE_TREE_CONNECTION
))
1554 Status
= RxCreateTreeConnect(Context
);
1558 /* Validate file name */
1559 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
1560 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
1561 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
1563 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
1564 RtlMoveMemory(&FileObject
->FileName
.Buffer
[0], &FileObject
->FileName
.Buffer
[1],
1565 FileObject
->FileName
.Length
);
1567 if (FileObject
->FileName
.Length
> sizeof(WCHAR
) &&
1568 FileObject
->FileName
.Buffer
[1] == OBJ_NAME_PATH_SEPARATOR
&&
1569 FileObject
->FileName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
1571 return STATUS_OBJECT_NAME_INVALID
;
1575 /* Attempt to open the file */
1578 UNICODE_STRING NetRootName
;
1580 /* Strip last \ if required */
1581 if (FileObject
->FileName
.Length
!= 0 &&
1582 FileObject
->FileName
.Buffer
[FileObject
->FileName
.Length
/ sizeof(WCHAR
) - 1] == OBJ_NAME_PATH_SEPARATOR
)
1584 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NON_DIRECTORY_FILE
))
1586 return STATUS_OBJECT_NAME_INVALID
;
1589 FileObject
->FileName
.Length
-= sizeof(WCHAR
);
1590 Context
->Create
.Flags
|= RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
;
1593 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_WRITE_THROUGH
))
1595 FileObject
->Flags
|= FO_WRITE_THROUGH
;
1598 /* Get the associated net root to opening */
1599 Status
= RxCanonicalizeNameAndObtainNetRoot(Context
, &FileObject
->FileName
, &NetRootName
);
1600 if (Status
!= STATUS_MORE_PROCESSING_REQUIRED
)
1605 /* And attempt to open */
1606 Status
= RxCreateFromNetRoot(Context
, &NetRootName
);
1607 if (Status
== STATUS_SHARING_VIOLATION
)
1611 else if (Status
== STATUS_REPARSE
)
1613 Context
->CurrentIrp
->IoStatus
.Information
= 0;
1617 ASSERT(!BooleanFlagOn(Context
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_REPARSE
));
1620 while (Status
== STATUS_MORE_PROCESSING_REQUIRED
);
1623 if (Status
== STATUS_RETRY
)
1625 RxpPrepareCreateContextForReuse(Context
);
1627 ASSERT(Status
!= STATUS_PENDING
);
1630 DPRINT("Status: %lx\n", Status
);
1639 RxCommonDevFCBCleanup(
1640 PRX_CONTEXT Context
)
1647 DPRINT("RxCommonDevFCBCleanup(%p)\n", Context
);
1649 Fcb
= Context
->pFcb
;
1650 Status
= STATUS_SUCCESS
;
1651 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
1653 /* Our FOBX if set, has to be a VNetRoot */
1654 if (Context
->pFobx
!= NULL
)
1656 RxAcquirePrefixTableLockShared(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
1657 if (Context
->pFobx
->NodeTypeCode
!= RDBSS_NTC_V_NETROOT
)
1659 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1661 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
1665 --Fcb
->UncleanCount
;
1676 RxCommonDevFCBClose(
1677 PRX_CONTEXT Context
)
1681 PMRX_V_NET_ROOT NetRoot
;
1685 DPRINT("RxCommonDevFCBClose(%p)\n", Context
);
1687 Fcb
= Context
->pFcb
;
1688 NetRoot
= (PMRX_V_NET_ROOT
)Context
->pFobx
;
1689 Status
= STATUS_SUCCESS
;
1690 ASSERT(NodeType(Fcb
) == RDBSS_NTC_DEVICE_FCB
);
1692 /* Our FOBX if set, has to be a VNetRoot */
1693 if (NetRoot
!= NULL
)
1695 RxAcquirePrefixTableLockShared(Context
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
1696 if (NetRoot
->NodeTypeCode
== RDBSS_NTC_V_NETROOT
)
1698 --NetRoot
->NumberOfOpens
;
1699 RxDereferenceVNetRoot(NetRoot
, LHS_ExclusiveLockHeld
);
1703 Status
= STATUS_NOT_IMPLEMENTED
;
1705 RxReleasePrefixTableLock(Context
->RxDeviceObject
->pRxNetNameTable
);
1717 RxCommonDevFCBFsCtl(
1718 PRX_CONTEXT Context
)
1721 return STATUS_NOT_IMPLEMENTED
;
1729 RxCommonDevFCBIoCtl(
1730 PRX_CONTEXT Context
)
1736 DPRINT("RxCommonDevFCBIoCtl(%p)\n", Context
);
1738 if (Context
->pFobx
!= NULL
)
1740 return STATUS_INVALID_HANDLE
;
1743 /* Is that a prefix claim from MUP? */
1744 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
1746 return RxPrefixClaim(Context
);
1749 /* Otherwise, pass through the mini-rdr */
1750 Status
= RxXXXControlFileCallthru(Context
);
1751 if (Status
!= STATUS_PENDING
)
1753 if (Context
->PostRequest
)
1755 Context
->ResumeRoutine
= RxCommonDevFCBIoCtl
;
1756 Status
= RxFsdPostRequest(Context
);
1760 DPRINT("Status: %lx\n", Status
);
1766 RxCommonDevFCBQueryVolInfo(
1767 PRX_CONTEXT Context
)
1770 return STATUS_NOT_IMPLEMENTED
;
1778 RxCommonDeviceControl(
1779 PRX_CONTEXT Context
)
1785 /* Prefix claim is only allowed for device, not files */
1786 if (Context
->CurrentIrpSp
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_REDIR_QUERY_PATH
)
1788 return STATUS_INVALID_DEVICE_REQUEST
;
1791 /* Submit to mini-rdr */
1792 RxInitializeLowIoContext(&Context
->LowIoContext
, LOWIO_OP_IOCTL
);
1793 Status
= RxLowIoSubmit(Context
, RxLowIoIoCtlShellCompletion
);
1794 if (Status
== STATUS_PENDING
)
1796 RxDereferenceAndDeleteRxContext_Real(Context
);
1807 RxCommonDirectoryControl(
1808 PRX_CONTEXT Context
)
1813 PIO_STACK_LOCATION Stack
;
1817 Fcb
= (PFCB
)Context
->pFcb
;
1818 Fobx
= (PFOBX
)Context
->pFobx
;
1819 Stack
= Context
->CurrentIrpSp
;
1820 DPRINT("RxCommonDirectoryControl(%p) FOBX: %p, FCB: %p, Minor: %d\n", Context
, Fobx
, Fcb
, Stack
->MinorFunction
);
1822 /* Call the appropriate helper */
1823 if (Stack
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
)
1825 Status
= RxQueryDirectory(Context
);
1827 else if (Stack
->MinorFunction
== IRP_MN_NOTIFY_CHANGE_DIRECTORY
)
1829 Status
= RxNotifyChangeDirectory(Context
);
1830 if (Status
== STATUS_PENDING
)
1832 RxDereferenceAndDeleteRxContext_Real(Context
);
1837 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1845 RxCommonDispatchProblem(
1846 PRX_CONTEXT Context
)
1849 return STATUS_NOT_IMPLEMENTED
;
1854 RxCommonFileSystemControl(
1855 PRX_CONTEXT Context
)
1858 return STATUS_NOT_IMPLEMENTED
;
1863 RxCommonFlushBuffers(
1864 PRX_CONTEXT Context
)
1867 return STATUS_NOT_IMPLEMENTED
;
1872 RxCommonLockControl(
1873 PRX_CONTEXT Context
)
1876 return STATUS_NOT_IMPLEMENTED
;
1882 PRX_CONTEXT Context
)
1885 return STATUS_NOT_IMPLEMENTED
;
1893 RxCommonQueryInformation(
1894 PRX_CONTEXT Context
)
1896 #define SET_SIZE_AND_QUERY(AlreadyConsummed, Function) \
1897 Context->Info.Length = Stack->Parameters.QueryFile.Length - (AlreadyConsummed); \
1898 Status = Function(Context, Add2Ptr(Buffer, AlreadyConsummed))
1905 PIO_STACK_LOCATION Stack
;
1906 FILE_INFORMATION_CLASS FileInfoClass
;
1910 Fcb
= (PFCB
)Context
->pFcb
;
1911 Fobx
= (PFOBX
)Context
->pFobx
;
1912 DPRINT("RxCommonQueryInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
1914 Irp
= Context
->CurrentIrp
;
1915 Stack
= Context
->CurrentIrpSp
;
1916 DPRINT("Buffer: %p, Length: %lx, Class: %ld\n", Irp
->AssociatedIrp
.SystemBuffer
,
1917 Stack
->Parameters
.QueryFile
.Length
, Stack
->Parameters
.QueryFile
.FileInformationClass
);
1919 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
1920 FileInfoClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
1927 /* Get a writable buffer */
1928 Buffer
= RxMapSystemBuffer(Context
);
1931 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1935 RtlZeroMemory(Buffer
, Context
->Info
.Length
);
1937 /* Validate file type */
1938 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_UNKNOWN
)
1940 if (NodeType(Fcb
) < RDBSS_NTC_STORAGE_TYPE_DIRECTORY
)
1942 Status
= STATUS_INVALID_PARAMETER
;
1945 else if (NodeType(Fcb
) > RDBSS_NTC_STORAGE_TYPE_FILE
)
1947 if (NodeType(Fcb
) == RDBSS_NTC_MAILSLOT
)
1949 Status
= STATUS_NOT_IMPLEMENTED
;
1953 Status
= STATUS_INVALID_PARAMETER
;
1960 /* Acquire the right lock */
1961 if (!BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_PAGING_FILE
) &&
1962 FileInfoClass
!= FileNameInformation
)
1964 if (FileInfoClass
== FileCompressionInformation
)
1966 Status
= RxAcquireExclusiveFcb(Context
, Fcb
);
1970 Status
= RxAcquireSharedFcb(Context
, Fcb
);
1973 if (Status
== STATUS_LOCK_NOT_GRANTED
)
1975 Status
= STATUS_PENDING
;
1978 else if (!NT_SUCCESS(Status
))
1986 /* Dispatch to the right helper */
1987 switch (FileInfoClass
)
1989 case FileBasicInformation
:
1990 Status
= RxQueryBasicInfo(Context
, Buffer
);
1993 case FileStandardInformation
:
1994 Status
= RxQueryStandardInfo(Context
, Buffer
);
1997 case FileInternalInformation
:
1998 Status
= RxQueryInternalInfo(Context
, Buffer
);
2001 case FileEaInformation
:
2002 Status
= RxQueryEaInfo(Context
, Buffer
);
2005 case FileNameInformation
:
2006 Status
= RxQueryNameInfo(Context
, Buffer
);
2009 case FileAllInformation
:
2010 SET_SIZE_AND_QUERY(0, RxQueryBasicInfo
);
2011 if (!NT_SUCCESS(Status
))
2016 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
), RxQueryStandardInfo
);
2017 if (!NT_SUCCESS(Status
))
2022 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2023 sizeof(FILE_STANDARD_INFORMATION
), RxQueryInternalInfo
);
2024 if (!NT_SUCCESS(Status
))
2029 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2030 sizeof(FILE_STANDARD_INFORMATION
) +
2031 sizeof(FILE_INTERNAL_INFORMATION
), RxQueryEaInfo
);
2032 if (!NT_SUCCESS(Status
))
2037 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2038 sizeof(FILE_STANDARD_INFORMATION
) +
2039 sizeof(FILE_INTERNAL_INFORMATION
) +
2040 sizeof(FILE_EA_INFORMATION
), RxQueryPositionInfo
);
2041 if (!NT_SUCCESS(Status
))
2046 SET_SIZE_AND_QUERY(sizeof(FILE_BASIC_INFORMATION
) +
2047 sizeof(FILE_STANDARD_INFORMATION
) +
2048 sizeof(FILE_INTERNAL_INFORMATION
) +
2049 sizeof(FILE_EA_INFORMATION
) +
2050 sizeof(FILE_POSITION_INFORMATION
), RxQueryNameInfo
);
2053 case FileAlternateNameInformation
:
2054 Status
= RxQueryAlternateNameInfo(Context
, Buffer
);
2057 case FilePipeInformation
:
2058 case FilePipeLocalInformation
:
2059 case FilePipeRemoteInformation
:
2060 Status
= RxQueryPipeInfo(Context
, Buffer
);
2063 case FileCompressionInformation
:
2064 Status
= RxQueryCompressedInfo(Context
, Buffer
);
2068 Context
->IoStatusBlock
.Status
= RxpQueryInfoMiniRdr(Context
, FileInfoClass
, Buffer
);
2069 Status
= Context
->IoStatusBlock
.Status
;
2073 if (Context
->Info
.Length
< 0)
2075 Status
= STATUS_BUFFER_OVERFLOW
;
2076 Context
->Info
.Length
= Stack
->Parameters
.QueryFile
.Length
;
2079 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryFile
.Length
- Context
->Info
.Length
;
2085 RxReleaseFcb(Context
, Fcb
);
2090 DPRINT("Status: %x\n", Status
);
2093 #undef SET_SIZE_AND_QUERY
2098 RxCommonQueryQuotaInformation(
2099 PRX_CONTEXT Context
)
2102 return STATUS_NOT_IMPLEMENTED
;
2107 RxCommonQuerySecurity(
2108 PRX_CONTEXT Context
)
2111 return STATUS_NOT_IMPLEMENTED
;
2119 RxCommonQueryVolumeInformation(
2120 PRX_CONTEXT Context
)
2126 PIO_STACK_LOCATION Stack
;
2130 Fcb
= (PFCB
)Context
->pFcb
;
2131 Fobx
= (PFOBX
)Context
->pFobx
;
2133 DPRINT("RxCommonQueryVolumeInformation(%p) FCB: %p, FOBX: %p\n", Context
, Fcb
, Fobx
);
2135 Irp
= Context
->CurrentIrp
;
2136 Stack
= Context
->CurrentIrpSp
;
2137 DPRINT("Length: %lx, Class: %lx, Buffer %p\n", Stack
->Parameters
.QueryVolume
.Length
,
2138 Stack
->Parameters
.QueryVolume
.FsInformationClass
, Irp
->AssociatedIrp
.SystemBuffer
);
2140 Context
->Info
.FsInformationClass
= Stack
->Parameters
.QueryVolume
.FsInformationClass
;
2141 Context
->Info
.Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2142 Context
->Info
.Length
= Stack
->Parameters
.QueryVolume
.Length
;
2144 /* Forward to mini-rdr */
2145 MINIRDR_CALL(Status
, Context
, Fcb
->MRxDispatch
, MRxQueryVolumeInfo
, (Context
));
2147 /* Post request if mini-rdr asked to */
2148 if (Context
->PostRequest
)
2150 Status
= RxFsdPostRequest(Context
);
2154 Irp
->IoStatus
.Information
= Stack
->Parameters
.QueryVolume
.Length
- Context
->Info
.Length
;
2157 DPRINT("Status: %x\n", Status
);
2164 PRX_CONTEXT RxContext
)
2172 PFILE_OBJECT FileObject
;
2173 LARGE_INTEGER ByteOffset
;
2174 PIO_STACK_LOCATION Stack
;
2175 PLOWIO_CONTEXT LowIoContext
;
2176 PRDBSS_DEVICE_OBJECT RxDeviceObject
;
2177 ULONG ReadLength
, CapturedRxContextSerialNumber
= RxContext
->SerialNumber
;
2178 BOOLEAN CanWait
, PagingIo
, NoCache
, Sync
, PostRequest
, IsPipe
, ReadCachingEnabled
, ReadCachingDisabled
, InFsp
, OwnerSet
;
2182 Fcb
= (PFCB
)RxContext
->pFcb
;
2183 Fobx
= (PFOBX
)RxContext
->pFobx
;
2184 DPRINT("RxCommonRead(%p) FOBX: %p, FCB: %p\n", RxContext
, Fobx
, Fcb
);
2186 /* Get some parameters */
2187 Irp
= RxContext
->CurrentIrp
;
2188 Stack
= RxContext
->CurrentIrpSp
;
2189 CanWait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
2190 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
2191 NoCache
= BooleanFlagOn(Irp
->Flags
, IRP_NOCACHE
);
2192 Sync
= !BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_ASYNC_OPERATION
);
2193 InFsp
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
);
2194 ReadLength
= Stack
->Parameters
.Read
.Length
;
2195 ByteOffset
.QuadPart
= Stack
->Parameters
.Read
.ByteOffset
.QuadPart
;
2196 DPRINT("Reading: %lx@%I64x %s %s %s %s\n", ReadLength
, ByteOffset
.QuadPart
,
2197 (CanWait
? "CW" : "!CW"), (PagingIo
? "PI" : "!PI"), (NoCache
? "NC" : "!NC"), (Sync
? "S" : "!S"));
2199 RxItsTheSameContext();
2201 Irp
->IoStatus
.Information
= 0;
2203 /* Should the read be loud - so far, it's just ignored on ReactOS:
2204 * s/DPRINT/DPRINT1/g will make it loud
2206 LowIoContext
= &RxContext
->LowIoContext
;
2207 CheckForLoudOperations(RxContext
);
2208 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_LOUDOPS
))
2210 DPRINT("LoudRead %I64x/%lx on %lx vdl/size/alloc %I64x/%I64x/%I64x\n",
2211 ByteOffset
, ReadLength
,
2212 Fcb
, Fcb
->Header
.ValidDataLength
, Fcb
->Header
.FileSize
, Fcb
->Header
.AllocationSize
);
2215 RxDeviceObject
= RxContext
->RxDeviceObject
;
2217 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
) && Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
2219 InterlockedIncrement((volatile long *)&RxDeviceObject
->ReadOperations
);
2221 if (ByteOffset
.QuadPart
!= Fobx
->Specific
.DiskFile
.PredictedReadOffset
)
2223 InterlockedIncrement((volatile long *)&RxDeviceObject
->RandomReadOperations
);
2225 Fobx
->Specific
.DiskFile
.PredictedReadOffset
= ByteOffset
.QuadPart
+ ReadLength
;
2229 ExInterlockedAddLargeStatistic(&RxDeviceObject
->PagingReadBytesRequested
, ReadLength
);
2233 ExInterlockedAddLargeStatistic(&RxDeviceObject
->NonPagingReadBytesRequested
, ReadLength
);
2237 ExInterlockedAddLargeStatistic(&RxDeviceObject
->CacheReadBytesRequested
, ReadLength
);
2241 /* A pagefile cannot be a pipe */
2242 IsPipe
= Fcb
->NetRoot
->Type
== NET_ROOT_PIPE
;
2243 if (IsPipe
&& PagingIo
)
2245 return STATUS_INVALID_DEVICE_REQUEST
;
2248 /* Null-length read is no-op */
2249 if (ReadLength
== 0)
2251 return STATUS_SUCCESS
;
2254 /* Validate FCB type */
2255 if (NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
&& NodeType(Fcb
) != RDBSS_NTC_VOLUME_FCB
)
2257 return STATUS_INVALID_DEVICE_REQUEST
;
2260 /* Init the lowio context for possible forward */
2261 RxInitializeLowIoContext(LowIoContext
, LOWIO_OP_READ
);
2263 PostRequest
= FALSE
;
2264 ReadCachingDisabled
= FALSE
;
2266 ReadCachingEnabled
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2267 FileObject
= Stack
->FileObject
;
2268 NetRoot
= (PNET_ROOT
)Fcb
->pNetRoot
;
2273 /* If no caching, make sure current Cc data have been flushed */
2274 if (!PagingIo
&& NoCache
&& !ReadCachingEnabled
&& FileObject
->SectionObjectPointer
!= NULL
)
2276 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
2277 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2282 else if (Status
!= STATUS_SUCCESS
)
2287 ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, TRUE
);
2288 CcFlushCache(FileObject
->SectionObjectPointer
, &ByteOffset
, ReadLength
, &Irp
->IoStatus
);
2289 RxReleasePagingIoResource(RxContext
, Fcb
);
2291 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
2296 RxAcquirePagingIoResource(RxContext
, Fcb
);
2297 RxReleasePagingIoResource(RxContext
, Fcb
);
2300 /* Acquire the appropriate lock */
2301 if (PagingIo
&& !ReadCachingEnabled
)
2305 if (!ExAcquireResourceSharedLite(Fcb
->Header
.PagingIoResource
, CanWait
))
2313 LowIoContext
->Resource
= Fcb
->Header
.PagingIoResource
;
2318 if (!ReadCachingEnabled
)
2320 if (!CanWait
&& NoCache
)
2322 Status
= RxAcquireSharedFcbWaitForEx(RxContext
, Fcb
);
2323 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2325 DPRINT1("RdAsyLNG %x\n", RxContext
);
2329 if (Status
!= STATUS_SUCCESS
)
2331 DPRINT1("RdAsyOthr %x\n", RxContext
);
2335 if (RxIsFcbAcquiredShared(Fcb
) <= 0xF000)
2337 LowIoContext
->Resource
= Fcb
->Header
.Resource
;
2347 Status
= RxAcquireSharedFcb(RxContext
, Fcb
);
2348 if (Status
== STATUS_LOCK_NOT_GRANTED
)
2353 else if (Status
!= STATUS_SUCCESS
)
2361 RxItsTheSameContext();
2363 ReadCachingDisabled
= (ReadCachingEnabled
== FALSE
);
2369 RxGetFileSizeWithLock(Fcb
, &FileSize
);
2371 /* Make sure FLOCK doesn't conflict */
2374 if (!FsRtlCheckLockForReadAccess(&Fcb
->Specific
.Fcb
.FileLock
, Irp
))
2376 Status
= STATUS_FILE_LOCK_CONFLICT
;
2381 /* Validate byteoffset vs length */
2382 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
))
2384 if (ByteOffset
.QuadPart
>= FileSize
)
2386 Status
= STATUS_END_OF_FILE
;
2390 if (ReadLength
> FileSize
- ByteOffset
.QuadPart
)
2392 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
2397 if (!PagingIo
&& !NoCache
&& ReadCachingEnabled
&&
2398 !BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
))
2400 /* File was not cached yet, do it */
2401 if (FileObject
->PrivateCacheMap
== NULL
)
2403 if (BooleanFlagOn(FileObject
->Flags
, FO_CLEANUP_COMPLETE
))
2405 Status
= STATUS_FILE_CLOSED
;
2409 RxAdjustAllocationSizeforCC(Fcb
);
2411 CcInitializeCacheMap(FileObject
, (PCC_FILE_SIZES
)&Fcb
->Header
.AllocationSize
,
2412 FALSE
, &RxData
.CacheManagerCallbacks
, Fcb
);
2414 if (BooleanFlagOn(Fcb
->MRxDispatch
->MRxFlags
, RDBSS_NO_DEFERRED_CACHE_READAHEAD
))
2416 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
2420 CcSetAdditionalCacheAttributes(FileObject
, TRUE
, FALSE
);
2421 SetFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
2424 CcSetReadAheadGranularity(FileObject
, NetRoot
->DiskParameters
.ReadAheadGranularity
);
2427 /* This should never happen - fix your RDR */
2428 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
2433 CcMdlRead(FileObject
, &ByteOffset
, ReadLength
, &Irp
->MdlAddress
, &Irp
->IoStatus
);
2434 Status
= Irp
->IoStatus
.Status
;
2435 ASSERT(NT_SUCCESS(Status
));
2440 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
2441 if (SystemBuffer
== NULL
)
2443 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2447 SetFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2449 RxItsTheSameContext();
2451 /* Perform the read */
2452 if (!CcCopyRead(FileObject
, &ByteOffset
, ReadLength
, CanWait
, SystemBuffer
, &Irp
->IoStatus
))
2454 if (!ReadCachingEnabled
)
2456 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2459 RxItsTheSameContext();
2465 if (!ReadCachingEnabled
)
2467 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2470 Status
= Irp
->IoStatus
.Status
;
2471 ASSERT(NT_SUCCESS(Status
));
2476 /* Validate the reading */
2477 if (FileObject
->PrivateCacheMap
!= NULL
&& BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) &&
2478 ByteOffset
.QuadPart
>= 4096)
2480 CcSetAdditionalCacheAttributes(FileObject
, FALSE
, FALSE
);
2481 ClearFlag(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
);
2484 /* If it's consistent, forward to mini-rdr */
2485 if (Fcb
->CachedNetRootType
!= NET_ROOT_DISK
|| BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_READAHEAD_DEFERRED
) ||
2486 ByteOffset
.QuadPart
< Fcb
->Header
.ValidDataLength
.QuadPart
)
2488 LowIoContext
->ParamsFor
.ReadWrite
.ByteCount
= ReadLength
;
2489 LowIoContext
->ParamsFor
.ReadWrite
.ByteOffset
= ByteOffset
.QuadPart
;
2491 RxItsTheSameContext();
2493 if (InFsp
&& ReadCachingDisabled
)
2495 ExSetResourceOwnerPointer((PagingIo
? Fcb
->Header
.PagingIoResource
: Fcb
->Header
.Resource
),
2496 (PVOID
)((ULONG_PTR
)RxContext
| 3));
2500 Status
= RxLowIoReadShell(RxContext
);
2502 RxItsTheSameContext();
2506 if (ByteOffset
.QuadPart
> FileSize
)
2509 Irp
->IoStatus
.Information
= ReadLength
;
2513 if (ByteOffset
.QuadPart
+ ReadLength
> FileSize
)
2515 ReadLength
= FileSize
- ByteOffset
.QuadPart
;
2518 SystemBuffer
= RxNewMapUserBuffer(RxContext
);
2519 RtlZeroMemory(SystemBuffer
, ReadLength
);
2520 Irp
->IoStatus
.Information
= ReadLength
;
2526 RxItsTheSameContext();
2528 /* Post if required */
2531 InterlockedIncrement((volatile long *)&RxContext
->ReferenceCount
);
2532 Status
= RxFsdPostRequest(RxContext
);
2536 /* Update FO in case of sync IO */
2537 if (!IsPipe
&& !PagingIo
)
2539 if (BooleanFlagOn(FileObject
->Flags
, FO_SYNCHRONOUS_IO
))
2541 FileObject
->CurrentByteOffset
.QuadPart
= ByteOffset
.QuadPart
+ Irp
->IoStatus
.Information
;
2546 /* Set FastIo if read was a success */
2547 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
2549 if (!IsPipe
&& !PagingIo
)
2551 SetFlag(FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
2555 /* In case we're done (not expected any further processing */
2556 if (_SEH2_AbnormalTermination() || Status
!= STATUS_PENDING
|| PostRequest
)
2558 /* Release everything that can be */
2559 if (ReadCachingDisabled
)
2565 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
2569 RxReleasePagingIoResource(RxContext
, Fcb
);
2576 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
2580 RxReleaseFcb(RxContext
, Fcb
);
2585 /* Dereference/Delete context */
2588 RxDereferenceAndDeleteRxContext(RxContext
);
2592 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
2594 RxResumeBlockedOperations_Serially(RxContext
, &Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
2598 /* We cannot return more than asked */
2599 if (Status
== STATUS_SUCCESS
)
2601 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
2608 RxDereferenceAndDeleteRxContext(RxContext
);
2619 PRX_CONTEXT Context
)
2622 return STATUS_NOT_IMPLEMENTED
;
2627 RxCommonSetInformation(
2628 PRX_CONTEXT Context
)
2631 return STATUS_NOT_IMPLEMENTED
;
2636 RxCommonSetQuotaInformation(
2637 PRX_CONTEXT Context
)
2640 return STATUS_NOT_IMPLEMENTED
;
2645 RxCommonSetSecurity(
2646 PRX_CONTEXT Context
)
2649 return STATUS_NOT_IMPLEMENTED
;
2654 RxCommonSetVolumeInformation(
2655 PRX_CONTEXT Context
)
2658 return STATUS_NOT_IMPLEMENTED
;
2663 RxCommonUnimplemented(
2664 PRX_CONTEXT Context
)
2667 return STATUS_NOT_IMPLEMENTED
;
2673 PRX_CONTEXT Context
)
2676 return STATUS_NOT_IMPLEMENTED
;
2682 IN PRX_CONTEXT RxContext
)
2687 return STATUS_NOT_IMPLEMENTED
;
2694 RxCopyCreateParameters(
2695 IN PRX_CONTEXT RxContext
)
2699 PFILE_OBJECT FileObject
;
2700 PIO_STACK_LOCATION Stack
;
2701 PDFS_NAME_CONTEXT DfsNameContext
;
2702 PIO_SECURITY_CONTEXT SecurityContext
;
2704 Irp
= RxContext
->CurrentIrp
;
2705 Stack
= RxContext
->CurrentIrpSp
;
2706 FileObject
= Stack
->FileObject
;
2707 SecurityContext
= Stack
->Parameters
.Create
.SecurityContext
;
2709 RxContext
->Create
.NtCreateParameters
.SecurityContext
= SecurityContext
;
2710 if (SecurityContext
->AccessState
!= NULL
&& SecurityContext
->AccessState
->SecurityDescriptor
!= NULL
)
2712 RxContext
->Create
.SdLength
= RtlLengthSecurityDescriptor(SecurityContext
->AccessState
->SecurityDescriptor
);
2713 DPRINT("SD Ctxt: %p, Length: %lx\n", RxContext
->Create
.NtCreateParameters
.SecurityContext
,
2714 RxContext
->Create
.SdLength
);
2716 if (SecurityContext
->SecurityQos
!= NULL
)
2718 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityContext
->SecurityQos
->ImpersonationLevel
;
2722 RxContext
->Create
.NtCreateParameters
.ImpersonationLevel
= SecurityImpersonation
;
2724 RxContext
->Create
.NtCreateParameters
.DesiredAccess
= SecurityContext
->DesiredAccess
;
2726 RxContext
->Create
.NtCreateParameters
.AllocationSize
.QuadPart
= Irp
->Overlay
.AllocationSize
.QuadPart
;
2727 RxContext
->Create
.NtCreateParameters
.FileAttributes
= Stack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
;
2728 RxContext
->Create
.NtCreateParameters
.ShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
2729 RxContext
->Create
.NtCreateParameters
.Disposition
= (Stack
->Parameters
.Create
.Options
>> 24) & 0x000000FF;
2730 RxContext
->Create
.NtCreateParameters
.CreateOptions
= Stack
->Parameters
.Create
.Options
& 0xFFFFFF;
2732 DfsContext
= FileObject
->FsContext2
;
2733 DfsNameContext
= FileObject
->FsContext
;
2734 RxContext
->Create
.NtCreateParameters
.DfsContext
= DfsContext
;
2735 RxContext
->Create
.NtCreateParameters
.DfsNameContext
= DfsNameContext
;
2736 ASSERT(DfsContext
== NULL
|| DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) ||
2737 DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) ||
2738 DfsContext
== UIntToPtr(DFS_CSCAGENT_NAME_CONTEXT
) ||
2739 DfsContext
== UIntToPtr(DFS_USER_NAME_CONTEXT
));
2740 ASSERT(DfsNameContext
== NULL
|| DfsNameContext
->NameContextType
== DFS_OPEN_CONTEXT
||
2741 DfsNameContext
->NameContextType
== DFS_DOWNLEVEL_OPEN_CONTEXT
||
2742 DfsNameContext
->NameContextType
== DFS_CSCAGENT_NAME_CONTEXT
||
2743 DfsNameContext
->NameContextType
== DFS_USER_NAME_CONTEXT
);
2744 FileObject
->FsContext2
= NULL
;
2745 FileObject
->FsContext
= NULL
;
2747 RxContext
->pFcb
= NULL
;
2748 RxContext
->Create
.ReturnedCreateInformation
= 0;
2750 /* if we stripped last \, it has to be a directory! */
2751 if (BooleanFlagOn(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH
))
2753 SetFlag(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DIRECTORY_FILE
);
2756 RxContext
->Create
.EaLength
= Stack
->Parameters
.Create
.EaLength
;
2757 if (RxContext
->Create
.EaLength
== 0)
2759 RxContext
->Create
.EaBuffer
= NULL
;
2763 RxContext
->Create
.EaBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
2764 DPRINT("EA Buffer: %p, Length: %lx\n", Irp
->AssociatedIrp
.SystemBuffer
, RxContext
->Create
.EaLength
);
2769 RxCreateFromNetRoot(
2770 PRX_CONTEXT Context
,
2771 PUNICODE_STRING NetRootName
)
2776 PFILE_OBJECT FileObject
;
2777 PIO_STACK_LOCATION Stack
;
2778 ACCESS_MASK DesiredAccess
;
2779 USHORT DesiredShareAccess
;
2783 /* Validate that the context is consistent */
2784 if (Context
->Create
.pNetRoot
== NULL
)
2786 return STATUS_BAD_NETWORK_PATH
;
2789 NetRoot
= (PNET_ROOT
)Context
->Create
.pNetRoot
;
2790 if (Context
->RxDeviceObject
!= NetRoot
->pSrvCall
->RxDeviceObject
)
2792 return STATUS_BAD_NETWORK_PATH
;
2795 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
) &&
2796 !BooleanFlagOn(NetRoot
->pSrvCall
->Flags
, SRVCALL_FLAG_DFS_AWARE_SERVER
))
2798 return STATUS_DFS_UNAVAILABLE
;
2801 if (Context
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
2802 BooleanFlagOn(NetRoot
->Flags
, NETROOT_FLAG_DFS_AWARE_NETROOT
))
2804 return STATUS_OBJECT_TYPE_MISMATCH
;
2807 Stack
= Context
->CurrentIrpSp
;
2808 DesiredShareAccess
= Stack
->Parameters
.Create
.ShareAccess
& FILE_SHARE_VALID_FLAGS
;
2809 if (NetRoot
->Type
== NET_ROOT_PRINT
)
2811 DesiredShareAccess
= FILE_SHARE_VALID_FLAGS
;
2814 DesiredAccess
= Stack
->Parameters
.Create
.SecurityContext
->DesiredAccess
& FILE_ALL_ACCESS
;
2816 /* We don't support renaming yet */
2817 if (BooleanFlagOn(Stack
->Flags
, SL_OPEN_TARGET_DIRECTORY
))
2820 return STATUS_NOT_IMPLEMENTED
;
2823 /* Try to find (or create) the FCB for the file */
2824 Status
= RxFindOrCreateFcb(Context
, NetRootName
);
2825 Fcb
= (PFCB
)Context
->pFcb
;
2828 ASSERT(!NT_SUCCESS(Status
));
2830 if (!NT_SUCCESS(Status
) || Fcb
== NULL
)
2835 if (BooleanFlagOn(Context
->Flags
, RX_CONTEXT_FLAG_CREATE_MAILSLOT
))
2837 Fcb
->Header
.NodeTypeCode
= RDBSS_NTC_MAILSLOT
;
2841 Status
= STATUS_MORE_PROCESSING_REQUIRED
;
2844 /* If finding FCB worked (mailslot case), mark the FCB as good and quit */
2845 if (NT_SUCCESS(Status
))
2847 RxTransitionNetFcb(Fcb
, Condition_Good
);
2848 DPRINT("Transitioning FCB %lx Condition %lx\n", Fcb
, Fcb
->Condition
);
2850 RxSetupNetFileObject(Context
);
2851 return STATUS_SUCCESS
;
2855 FileObject
= Stack
->FileObject
;
2856 /* Check SA for conflict */
2857 if (Fcb
->OpenCount
> 0)
2859 Status
= RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
2860 &Fcb
->ShareAccess
, FALSE
, "early check per useropens", "EarlyPerUO");
2861 if (!NT_SUCCESS(Status
))
2863 RxDereferenceNetFcb(Fcb
);
2868 if (BooleanFlagOn(Context
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
) &&
2869 !BooleanFlagOn(Context
->Create
.NtCreateParameters
.DesiredAccess
, ~SYNCHRONIZE
))
2876 /* Find a SRV_OPEN that suits the opening */
2877 Status
= RxCollapseOrCreateSrvOpen(Context
);
2878 if (Status
== STATUS_SUCCESS
)
2883 SrvOpen
= (PSRV_OPEN
)Context
->pRelevantSrvOpen
;
2884 Fobx
= (PFOBX
)Context
->pFobx
;
2885 /* There are already opens, check for conflict */
2886 if (Fcb
->OpenCount
!= 0)
2888 if (!NT_SUCCESS(RxCheckShareAccess(DesiredAccess
, DesiredShareAccess
,
2889 FileObject
, &Fcb
->ShareAccess
,
2890 FALSE
, "second check per useropens",
2893 ++SrvOpen
->UncleanFobxCount
;
2894 RxDereferenceNetFobx(Fobx
, LHS_LockNotHeld
);
2901 if (NetRoot
->Type
!= NET_ROOT_PIPE
)
2903 RxSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
,
2904 &Fcb
->ShareAccess
, "initial shareaccess setup", "InitShrAcc");
2908 RxSetupNetFileObject(Context
);
2910 /* No conflict? Set up SA */
2911 if (Fcb
->OpenCount
!= 0 && NetRoot
->Type
!= NET_ROOT_PIPE
)
2913 RxUpdateShareAccess(FileObject
, &Fcb
->ShareAccess
, "update share access", "UpdShrAcc");
2916 ++Fcb
->UncleanCount
;
2917 if (BooleanFlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
))
2919 ++Fcb
->UncachedUncleanCount
;
2922 if (SrvOpen
->UncleanFobxCount
== 0 && Fcb
->UncleanCount
== 1 &&
2923 !BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE
))
2925 RxChangeBufferingState(SrvOpen
, NULL
, FALSE
);
2928 /* No pending close, we're active */
2929 ClearFlag(Fcb
->FcbState
, FCB_STATE_DELAY_CLOSE
);
2932 ++SrvOpen
->UncleanFobxCount
;
2933 ++SrvOpen
->OpenCount
;
2934 SrvOpen
->ulFileSizeVersion
= Fcb
->ulFileSizeVersion
;
2936 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_NO_INTERMEDIATE_BUFFERING
))
2938 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_READ_CACHING
);
2939 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING
);
2941 ClearFlag(Fcb
->FcbState
, FCB_STATE_WRITECACHING_ENABLED
);
2942 ClearFlag(Fcb
->FcbState
, FCB_STATE_READCACHING_ENABLED
);
2944 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, TRUE
, TRUE
);
2947 /* Now, update SA for the SRV_OPEN */
2948 RxUpdateShareAccessPerSrvOpens(SrvOpen
);
2950 if (BooleanFlagOn(Stack
->Parameters
.Create
.Options
, FILE_DELETE_ON_CLOSE
))
2952 SetFlag(Fobx
->Flags
, FOBX_FLAG_DELETE_ON_CLOSE
);
2955 /* Update the FOBX info */
2958 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
2960 SetFlag(FileObject
->Flags
, FO_NAMED_PIPE
);
2963 if (Context
->Create
.pNetRoot
->Type
== NET_ROOT_PRINT
||
2964 Context
->Create
.pNetRoot
->Type
== NET_ROOT_PIPE
)
2966 Fobx
->PipeHandleInformation
= &Fobx
->Specific
.NamedPipe
.PipeHandleInformation
;
2968 Fobx
->Specific
.NamedPipe
.CollectDataTime
.QuadPart
= 0;
2969 Fobx
->Specific
.NamedPipe
.CollectDataSize
= Context
->Create
.pNetRoot
->NamedPipeParameters
.DataCollectionSize
;
2971 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.TypeOfPipe
= Context
->Create
.PipeType
;
2972 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.ReadMode
= Context
->Create
.PipeReadMode
;
2973 Fobx
->Specific
.NamedPipe
.PipeHandleInformation
.CompletionMode
= Context
->Create
.PipeCompletionMode
;
2975 InitializeListHead(&Fobx
->Specific
.NamedPipe
.ReadSerializationQueue
);
2976 InitializeListHead(&Fobx
->Specific
.NamedPipe
.WriteSerializationQueue
);
2980 Status
= STATUS_SUCCESS
;
2985 if (Fcb
->OpenCount
== 0)
2987 if (Context
->Create
.FcbAcquired
)
2989 Context
->Create
.FcbAcquired
= (RxDereferenceAndFinalizeNetFcb(Fcb
,
2993 if (!Context
->Create
.FcbAcquired
)
2995 RxTrackerUpdateHistory(Context
, NULL
, TRACKER_FCB_FREE
, __LINE__
, __FILE__
, 0);
3001 RxDereferenceNetFcb(Fcb
);
3013 RxCreateTreeConnect(
3014 IN PRX_CONTEXT RxContext
)
3017 PV_NET_ROOT VNetRoot
;
3018 PFILE_OBJECT FileObject
;
3019 PIO_STACK_LOCATION Stack
;
3020 NET_ROOT_TYPE NetRootType
;
3021 UNICODE_STRING CanonicalName
, RemainingName
;
3025 Stack
= RxContext
->CurrentIrpSp
;
3026 FileObject
= Stack
->FileObject
;
3028 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
3029 /* As long as we don't know connection type, mark it wild */
3030 NetRootType
= NET_ROOT_WILD
;
3031 /* Get the type by parsing the name */
3032 Status
= RxFirstCanonicalize(RxContext
, &FileObject
->FileName
, &CanonicalName
, &NetRootType
);
3033 if (!NT_SUCCESS(Status
))
3038 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
3039 RxContext
->Create
.TreeConnectOpenDeferred
= FALSE
;
3040 RtlInitEmptyUnicodeString(&RxContext
->Create
.TransportName
, NULL
, 0);
3041 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserName
, NULL
, 0);
3042 RtlInitEmptyUnicodeString(&RxContext
->Create
.Password
, NULL
, 0);
3043 RtlInitEmptyUnicodeString(&RxContext
->Create
.UserDomainName
, NULL
, 0);
3045 /* We don't handle EA - they come from DFS, don't care */
3046 if (Stack
->Parameters
.Create
.EaLength
> 0)
3051 /* Mount if required */
3052 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3053 if (Status
== STATUS_NETWORK_CREDENTIAL_CONFLICT
)
3055 RxScavengeVNetRoots(RxContext
->RxDeviceObject
);
3056 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &RemainingName
);
3059 if (!NT_SUCCESS(Status
))
3064 /* Validate the rest of the name with mini-rdr */
3065 if (RemainingName
.Length
> 0)
3067 MINIRDR_CALL(Status
, RxContext
,
3068 RxContext
->Create
.pNetRoot
->pSrvCall
->RxDeviceObject
->Dispatch
,
3069 MRxIsValidDirectory
, (RxContext
, &RemainingName
));
3072 if (!NT_SUCCESS(Status
))
3077 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
3078 RxReferenceVNetRoot(VNetRoot
);
3079 if (InterlockedCompareExchange(&VNetRoot
->AdditionalReferenceForDeleteFsctlTaken
, 1, 0) != 0)
3081 RxDereferenceVNetRoot(VNetRoot
, LHS_LockNotHeld
);
3084 FileObject
->FsContext
= &RxDeviceFCB
;
3085 FileObject
->FsContext2
= VNetRoot
;
3087 VNetRoot
->ConstructionStatus
= STATUS_SUCCESS
;
3088 ++VNetRoot
->NumberOfOpens
;
3090 /* Create is over - clear context */
3091 RxContext
->Create
.pSrvCall
= NULL
;
3092 RxContext
->Create
.pNetRoot
= NULL
;
3093 RxContext
->Create
.pVNetRoot
= NULL
;
3100 RxDebugControlCommand(
3101 _In_ PSTR ControlString
)
3109 IN PDRIVER_OBJECT DriverObject
,
3110 IN PUNICODE_STRING RegistryPath
)
3113 USHORT i
, State
= 0;
3115 DPRINT("RxDriverEntry(%p, %p)\n", DriverObject
, RegistryPath
);
3119 RxCheckFcbStructuresForAlignment();
3121 RtlZeroMemory(&RxData
, sizeof(RxData
));
3122 RxData
.NodeTypeCode
= RDBSS_NTC_DATA_HEADER
;
3123 RxData
.NodeByteSize
= sizeof(RxData
);
3124 RxData
.DriverObject
= DriverObject
;
3126 RtlZeroMemory(&RxDeviceFCB
, sizeof(RxDeviceFCB
));
3127 RxDeviceFCB
.spacer
.NodeTypeCode
= RDBSS_NTC_DEVICE_FCB
;
3128 RxDeviceFCB
.spacer
.NodeByteSize
= sizeof(RxDeviceFCB
);
3130 KeInitializeSpinLock(&RxStrucSupSpinLock
);
3131 RxExports
.pRxStrucSupSpinLock
= &RxStrucSupSpinLock
;
3133 RxInitializeDebugSupport();
3135 RxFileSystemDeviceObject
= (PRDBSS_DEVICE_OBJECT
)&RxSpaceForTheWrappersDeviceObject
;
3136 RtlZeroMemory(&RxSpaceForTheWrappersDeviceObject
, sizeof(RxSpaceForTheWrappersDeviceObject
));
3141 RxGetRegistryParameters(RegistryPath
);
3142 RxReadRegistryParameters();
3144 Status
= RxInitializeRegistrationStructures();
3145 if (!NT_SUCCESS(Status
))
3151 RxInitializeDispatcher();
3153 ExInitializeNPagedLookasideList(&RxContextLookasideList
, RxAllocatePoolWithTag
, RxFreePool
, 0, sizeof(RX_CONTEXT
), RX_IRPC_POOLTAG
, 4);
3155 InitializeListHead(&RxIrpsList
);
3156 KeInitializeSpinLock(&RxIrpsListSpinLock
);
3158 InitializeListHead(&RxActiveContexts
);
3159 InitializeListHead(&RxSrvCalldownList
);
3161 ExInitializeFastMutex(&RxContextPerFileSerializationMutex
);
3162 ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex
);
3163 KeInitializeMutex(&RxScavengerMutex
, 1);
3164 KeInitializeMutex(&RxSerializationMutex
, 1);
3166 for (i
= 0; i
< RxMaximumWorkQueue
; ++i
)
3168 RxFileSystemDeviceObject
->PostedRequestCount
[i
] = 0;
3169 RxFileSystemDeviceObject
->OverflowQueueCount
[i
] = 0;
3170 InitializeListHead(&RxFileSystemDeviceObject
->OverflowQueue
[i
]);
3173 KeInitializeSpinLock(&RxFileSystemDeviceObject
->OverflowQueueSpinLock
);
3175 RxInitializeDispatchVectors(DriverObject
);
3177 ExInitializeResourceLite(&RxData
.Resource
);
3178 RxData
.OurProcess
= IoGetCurrentProcess();
3180 RxInitializeRxTimer();
3184 if (!NT_SUCCESS(Status
))
3186 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BC4, Status
);
3187 RxInitUnwind(DriverObject
, State
);
3191 /* There are still bits to init - be consider it's fine for now */
3194 return STATUS_NOT_IMPLEMENTED
;
3196 return STATUS_SUCCESS
;
3204 RxDumpCurrentAccess(
3207 _In_ PSZ wherelogtag
,
3208 _In_ PSHARE_ACCESS ShareAccess
)
3220 _In_ PSZ wherelogtag
,
3221 _In_ ACCESS_MASK DesiredAccess
,
3222 _In_ ULONG DesiredShareAccess
)
3229 RxFastIoCheckIfPossible(
3230 PFILE_OBJECT FileObject
,
3231 PLARGE_INTEGER FileOffset
,
3232 ULONG Length
, BOOLEAN Wait
,
3233 ULONG LockKey
, BOOLEAN CheckForReadOperation
,
3234 PIO_STATUS_BLOCK IoStatus
,
3235 PDEVICE_OBJECT DeviceObject
)
3243 RxFastIoDeviceControl(
3244 PFILE_OBJECT FileObject
,
3246 PVOID InputBuffer OPTIONAL
,
3247 ULONG InputBufferLength
,
3248 PVOID OutputBuffer OPTIONAL
,
3249 ULONG OutputBufferLength
,
3250 ULONG IoControlCode
,
3251 PIO_STATUS_BLOCK IoStatus
,
3252 PDEVICE_OBJECT DeviceObject
)
3254 /* Only supported IOCTL */
3255 if (IoControlCode
== IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
)
3269 PFILE_OBJECT FileObject
,
3270 PLARGE_INTEGER FileOffset
,
3275 PIO_STATUS_BLOCK IoStatus
,
3276 PDEVICE_OBJECT DeviceObject
)
3285 PFILE_OBJECT FileObject
,
3286 PLARGE_INTEGER FileOffset
,
3291 PIO_STATUS_BLOCK IoStatus
,
3292 PDEVICE_OBJECT DeviceObject
)
3300 RxFinalizeConnection(
3301 IN OUT PNET_ROOT NetRoot
,
3302 IN OUT PV_NET_ROOT VNetRoot OPTIONAL
,
3303 IN LOGICAL ForceFilesClosed
)
3306 return STATUS_NOT_IMPLEMENTED
;
3311 PRX_CONTEXT RxContext
,
3312 PUNICODE_STRING NetRootName
)
3318 PV_NET_ROOT VNetRoot
;
3319 BOOLEAN TableAcquired
, AcquiredExclusive
;
3323 NetRoot
= (PNET_ROOT
)RxContext
->Create
.pNetRoot
;
3324 VNetRoot
= (PV_NET_ROOT
)RxContext
->Create
.pVNetRoot
;
3325 ASSERT(NetRoot
== VNetRoot
->NetRoot
);
3327 Status
= STATUS_SUCCESS
;
3328 AcquiredExclusive
= FALSE
;
3330 RxAcquireFcbTableLockShared(&NetRoot
->FcbTable
, TRUE
);
3331 TableAcquired
= TRUE
;
3332 Version
= NetRoot
->FcbTable
.Version
;
3334 /* Look for a cached FCB */
3335 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
3338 DPRINT("RxFcbTableLookupFcb returned NULL fcb for %wZ\n", NetRootName
);
3342 DPRINT("FCB found for %wZ\n", &Fcb
->FcbTableEntry
.Path
);
3343 /* If FCB was to be orphaned, consider it as not suitable */
3344 if (Fcb
->fShouldBeOrphaned
)
3346 RxDereferenceNetFcb(Fcb
);
3347 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3349 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
3350 TableAcquired
= TRUE
;
3351 AcquiredExclusive
= TRUE
;
3353 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
3354 if (Fcb
!= NULL
&& Fcb
->fShouldBeOrphaned
)
3356 RxOrphanThisFcb(Fcb
);
3357 RxDereferenceNetFcb(Fcb
);
3363 /* If FCB was not found or is not covering full path, prepare for more work */
3364 if (Fcb
== NULL
|| Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
3366 if (!AcquiredExclusive
)
3368 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3369 RxAcquireFcbTableLockExclusive(&NetRoot
->FcbTable
, TRUE
);
3370 TableAcquired
= TRUE
;
3373 /* If FCB table was updated in between, re-attempt a lookup */
3374 if (NetRoot
->FcbTable
.Version
!= Version
)
3376 Fcb
= RxFcbTableLookupFcb(&NetRoot
->FcbTable
, NetRootName
);
3377 if (Fcb
!= NULL
&& Fcb
->FcbTableEntry
.Path
.Length
!= NetRootName
->Length
)
3384 /* Allocate the FCB */
3389 Fcb
= RxCreateNetFcb(RxContext
, VNetRoot
, NetRootName
);
3392 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3396 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
3397 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
3403 if (_SEH2_AbnormalTermination())
3405 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3406 TableAcquired
= FALSE
;
3410 RxTransitionNetFcb(Fcb
, Condition_Bad
);
3412 ExAcquireResourceExclusiveLite(Fcb
->Header
.Resource
, TRUE
);
3413 if (RxDereferenceAndFinalizeNetFcb(Fcb
, NULL
, FALSE
, FALSE
) != 0)
3415 ExReleaseResourceLite(Fcb
->Header
.Resource
);
3424 RxReleaseFcbTableLock(&NetRoot
->FcbTable
);
3427 if (!NT_SUCCESS(Status
))
3432 RxContext
->pFcb
= RX_GET_MRX_FCB(Fcb
);
3433 DPRINT("FCB %p is in condition %lx\n", Fcb
, Fcb
->Condition
);
3435 if (!RxContext
->Create
.FcbAcquired
)
3437 RxWaitForStableNetFcb(Fcb
, RxContext
);
3438 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
3439 RxContext
->Create
.FcbAcquired
= NT_SUCCESS(Status
);
3446 RxFirstCanonicalize(
3447 PRX_CONTEXT RxContext
,
3448 PUNICODE_STRING FileName
,
3449 PUNICODE_STRING CanonicalName
,
3450 PNET_ROOT_TYPE NetRootType
)
3454 BOOLEAN UncName
, PrependString
, IsSpecial
;
3455 USHORT CanonicalLength
;
3456 UNICODE_STRING SessionIdString
;
3457 WCHAR SessionIdBuffer
[16];
3461 Type
= NET_ROOT_WILD
;
3462 PrependString
= FALSE
;
3465 Status
= STATUS_SUCCESS
;
3467 /* Name has to contain at least \\ */
3468 if (FileName
->Length
< 2 * sizeof(WCHAR
))
3470 return STATUS_OBJECT_NAME_INVALID
;
3473 /* First easy check, is that a path with a name? */
3474 CanonicalLength
= FileName
->Length
;
3475 if (FileName
->Length
> 5 * sizeof(WCHAR
))
3477 if (FileName
->Buffer
[0] == '\\' && FileName
->Buffer
[1] == ';')
3479 if (FileName
->Buffer
[3] == ':')
3481 Type
= NET_ROOT_DISK
;
3485 Type
= NET_ROOT_PRINT
;
3490 /* Nope, attempt deeper parsing */
3491 if (FileName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
&& FileName
->Buffer
[1] != ';')
3494 PWSTR FirstSlash
, EndOfString
;
3496 SetFlag(RxContext
->Create
.Flags
, RX_CONTEXT_CREATE_FLAG_UNC_NAME
);
3499 /* The lack of drive letter will be replaced by session ID */
3500 SessionId
= RxGetSessionId(RxContext
->CurrentIrpSp
);
3501 RtlInitEmptyUnicodeString(&SessionIdString
, SessionIdBuffer
, sizeof(SessionIdBuffer
));
3502 RtlIntegerToUnicodeString(SessionId
, 10, &SessionIdString
);
3504 EndOfString
= Add2Ptr(FileName
->Buffer
, FileName
->Length
);
3505 for (FirstSlash
= &FileName
->Buffer
[1]; FirstSlash
!= EndOfString
; ++FirstSlash
)
3507 if (*FirstSlash
== OBJ_NAME_PATH_SEPARATOR
)
3513 if (EndOfString
- FirstSlash
<= sizeof(WCHAR
))
3515 Status
= STATUS_OBJECT_NAME_INVALID
;
3520 DPRINT1("WARNING: Assuming not special + disk!\n");
3521 Type
= NET_ROOT_DISK
;
3522 Status
= STATUS_SUCCESS
;
3523 //Status = STATUS_NOT_IMPLEMENTED;
3524 /* Should be check against IPC, mailslot, and so on */
3528 /* Update net root type with our deduced one */
3529 *NetRootType
= Type
;
3530 DPRINT("Returning type: %x\n", Type
);
3532 if (!NT_SUCCESS(Status
))
3537 /* Do we have to prepend session ID? */
3542 PrependString
= TRUE
;
3543 CanonicalLength
+= SessionIdString
.Length
+ 3 * sizeof(WCHAR
);
3547 /* If not UNC path, we should preprend stuff */
3548 if (!PrependString
&& !IsSpecial
&& FileName
->Buffer
[0] != '\\')
3550 return STATUS_OBJECT_PATH_INVALID
;
3553 /* Allocate the buffer */
3554 Status
= RxAllocateCanonicalNameBuffer(RxContext
, CanonicalName
, CanonicalLength
);
3555 if (!NT_SUCCESS(Status
))
3560 /* We don't support that case, we always return disk */
3563 ASSERT(CanonicalName
->Length
== CanonicalLength
);
3565 Status
= STATUS_NOT_IMPLEMENTED
;
3569 /* If we have to prepend, go ahead */
3572 CanonicalName
->Buffer
[0] = '\\';
3573 CanonicalName
->Buffer
[1] = ';';
3574 CanonicalName
->Buffer
[2] = ':';
3575 CanonicalName
->Length
= 3 * sizeof(WCHAR
);
3576 RtlAppendUnicodeStringToString(CanonicalName
, &SessionIdString
);
3577 RtlAppendUnicodeStringToString(CanonicalName
, FileName
);
3579 DPRINT1("CanonicalName: %wZ\n", CanonicalName
);
3581 /* Otherwise, that's a simple copy */
3584 RtlCopyUnicodeString(CanonicalName
, FileName
);
3595 RxFreeCanonicalNameBuffer(
3596 PRX_CONTEXT Context
)
3598 /* These two buffers are always the same */
3599 ASSERT(Context
->Create
.CanonicalNameBuffer
== Context
->AlsoCanonicalNameBuffer
);
3601 if (Context
->Create
.CanonicalNameBuffer
!= NULL
)
3603 RxFreePoolWithTag(Context
->Create
.CanonicalNameBuffer
, RX_MISC_POOLTAG
);
3604 Context
->Create
.CanonicalNameBuffer
= NULL
;
3605 Context
->AlsoCanonicalNameBuffer
= NULL
;
3608 ASSERT(Context
->AlsoCanonicalNameBuffer
== NULL
);
3612 RxFsdCommonDispatch(
3613 PRX_FSD_DISPATCH_VECTOR DispatchVector
,
3614 UCHAR MajorFunction
,
3615 PIO_STACK_LOCATION Stack
,
3616 PFILE_OBJECT FileObject
,
3618 PRDBSS_DEVICE_OBJECT RxDeviceObject
)
3622 PRX_CONTEXT Context
;
3623 UCHAR MinorFunction
;
3624 PFILE_OBJECT StackFileObject
;
3625 PRX_FSD_DISPATCH DispatchFunc
;
3626 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
3627 BOOLEAN TopLevel
, Closing
, PassToDriver
, SetCancelRoutine
, PostRequest
, CanWait
;
3629 Status
= STATUS_SUCCESS
;
3631 DPRINT("RxFsdCommonDispatch(%p, %d, %p, %p, %p, %p)\n", DispatchVector
, MajorFunction
, Stack
, FileObject
, Irp
, RxDeviceObject
);
3633 FsRtlEnterFileSystem();
3635 TopLevel
= RxTryToBecomeTheTopLevelIrp(&TopLevelContext
, Irp
, RxDeviceObject
, FALSE
);
3641 PostRequest
= FALSE
;
3642 SetCancelRoutine
= TRUE
;
3643 MinorFunction
= Stack
->MinorFunction
;
3645 switch (MajorFunction
)
3647 case IRP_MJ_FILE_SYSTEM_CONTROL
:
3648 if (FileObject
!= NULL
)
3650 CanWait
= IoIsOperationSynchronous(Irp
);
3660 case IRP_MJ_QUERY_INFORMATION
:
3661 case IRP_MJ_SET_INFORMATION
:
3662 case IRP_MJ_QUERY_EA
:
3664 case IRP_MJ_FLUSH_BUFFERS
:
3665 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
3666 case IRP_MJ_SET_VOLUME_INFORMATION
:
3667 case IRP_MJ_DIRECTORY_CONTROL
:
3668 case IRP_MJ_DEVICE_CONTROL
:
3669 case IRP_MJ_LOCK_CONTROL
:
3670 case IRP_MJ_QUERY_SECURITY
:
3671 case IRP_MJ_SET_SECURITY
:
3672 CanWait
= IoIsOperationSynchronous(Irp
);
3676 case IRP_MJ_CLEANUP
:
3678 SetCancelRoutine
= FALSE
;
3685 KeAcquireSpinLock(&RxStrucSupSpinLock
, &OldIrql
);
3686 /* Should we stop it right now, or mini-rdr deserves to know? */
3687 PassToDriver
= TRUE
;
3688 if (RxGetRdbssState(RxDeviceObject
) != RDBSS_STARTABLE
)
3690 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& !Closing
)
3692 PassToDriver
= FALSE
;
3693 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
3694 DPRINT1("Not started!\n");
3699 if (DispatchVector
!= RxDeviceFCBVector
&& (FileObject
->FileName
.Length
!= 0 || FileObject
->RelatedFileObject
!= NULL
))
3701 PassToDriver
= FALSE
;
3702 Status
= STATUS_REDIRECTOR_NOT_STARTED
;
3703 DPRINT1("Not started!\n");
3706 KeReleaseSpinLock(&RxStrucSupSpinLock
, OldIrql
);
3708 StackFileObject
= Stack
->FileObject
;
3709 /* Make sure we don't deal with orphaned stuff */
3710 if (StackFileObject
!= NULL
&& StackFileObject
->FsContext
!= NULL
)
3712 if (StackFileObject
->FsContext2
!= UIntToPtr(DFS_OPEN_CONTEXT
) &&
3713 StackFileObject
->FsContext2
!= UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT
) &&
3714 StackFileObject
->FsContext
!= &RxDeviceFCB
)
3719 Fcb
= StackFileObject
->FsContext
;
3720 Fobx
= StackFileObject
->FsContext2
;
3722 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
) ||
3723 BooleanFlagOn(Fobx
->pSrvOpen
->Flags
, SRVOPEN_FLAG_ORPHANED
))
3727 PassToDriver
= TRUE
;
3731 PassToDriver
= FALSE
;
3732 Status
= STATUS_UNEXPECTED_NETWORK_ERROR
;
3733 DPRINT1("Operation on orphaned FCB: %p\n", Fcb
);
3739 /* Did we receive a close request whereas we're stopping? */
3740 if (RxGetRdbssState(RxDeviceObject
) == RDBSS_STOP_IN_PROGRESS
&& Closing
)
3744 Fcb
= StackFileObject
->FsContext
;
3746 DPRINT1("Close received after stop\n");
3747 DPRINT1("Irp: %p %d:%d FO: %p FCB: %p\n",
3748 Irp
, Stack
->MajorFunction
, Stack
->MinorFunction
, StackFileObject
, Fcb
);
3750 if (Fcb
!= NULL
&& Fcb
!= &RxDeviceFCB
&&
3753 DPRINT1("OpenCount: %ld, UncleanCount: %ld, Name: %wZ\n",
3754 Fcb
->OpenCount
, Fcb
->UncleanCount
, &Fcb
->FcbTableEntry
.Path
);
3758 /* Should we stop the whole thing now? */
3761 if (MajorFunction
!= IRP_MJ_DIRECTORY_CONTROL
|| MinorFunction
!= IRP_MN_REMOVE_DEVICE
)
3763 IoMarkIrpPending(Irp
);
3764 Irp
->IoStatus
.Status
= Status
;
3765 Irp
->IoStatus
.Information
= 0;
3766 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3767 Status
= STATUS_PENDING
;
3771 Irp
->IoStatus
.Status
= Status
;
3772 Irp
->IoStatus
.Information
= 0;
3773 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3779 /* No? Allocate a context to deal with the mini-rdr */
3780 Context
= RxCreateRxContext(Irp
, RxDeviceObject
, (CanWait
? RX_CONTEXT_FLAG_WAIT
: 0));
3781 if (Context
== NULL
)
3783 Status
= STATUS_INSUFFICIENT_RESOURCES
;
3784 RxCompleteRequest_Real(RxNull
, Irp
, STATUS_INSUFFICIENT_RESOURCES
);
3788 /* Set cancel routine if required */
3789 if (SetCancelRoutine
)
3791 IoAcquireCancelSpinLock(&OldIrql
);
3792 IoSetCancelRoutine(Irp
, RxCancelRoutine
);
3796 IoAcquireCancelSpinLock(&OldIrql
);
3797 IoSetCancelRoutine(Irp
, NULL
);
3799 IoReleaseCancelSpinLock(OldIrql
);
3801 ASSERT(MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
3803 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
3804 Irp
->IoStatus
.Information
= 0;
3805 /* Get the dispatch routine */
3806 DispatchFunc
= DispatchVector
[MajorFunction
].CommonRoutine
;
3808 if (MajorFunction
== IRP_MJ_READ
|| MajorFunction
== IRP_MJ_WRITE
)
3810 /* Handle the complete MDL case */
3811 if (BooleanFlagOn(MinorFunction
, IRP_MN_COMPLETE
))
3813 DispatchFunc
= RxCompleteMdl
;
3817 /* Do we have to post request? */
3818 if (BooleanFlagOn(MinorFunction
, IRP_MN_DPC
))
3824 /* Our read function needs stack, make sure we won't overflow,
3825 * otherwise, post the request
3827 if (MajorFunction
== IRP_MJ_READ
)
3829 if (IoGetRemainingStackSize() < 0xE00)
3831 Context
->PendingReturned
= TRUE
;
3832 Status
= RxPostStackOverflowRead(Context
);
3833 if (Status
!= STATUS_PENDING
)
3835 Context
->PendingReturned
= FALSE
;
3836 RxCompleteAsynchronousRequest(Context
, Status
);
3846 Context
->ResumeRoutine
= DispatchFunc
;
3847 /* There's a dispatch routine? Time to dispatch! */
3848 if (DispatchFunc
!= NULL
)
3850 Context
->PendingReturned
= TRUE
;
3853 Status
= RxFsdPostRequest(Context
);
3857 /* Retry as long as we have */
3860 Status
= DispatchFunc(Context
);
3862 while (Status
== STATUS_RETRY
);
3864 if (Status
== STATUS_PENDING
)
3869 /* Sanity check: did someone mess with our context? */
3870 if (Context
->CurrentIrp
!= Irp
|| Context
->CurrentIrpSp
!= Stack
||
3871 Context
->MajorFunction
!= MajorFunction
|| Stack
->MinorFunction
!= MinorFunction
)
3873 DPRINT1("RX_CONTEXT %p has been contaminated!\n", Context
);
3874 DPRINT1("->CurrentIrp %p %p\n", Context
->CurrentIrp
, Irp
);
3875 DPRINT1("->CurrentIrpSp %p %p\n", Context
->CurrentIrpSp
, Stack
);
3876 DPRINT1("->MajorFunction %d %d\n", Context
->MajorFunction
, MajorFunction
);
3877 DPRINT1("->MinorFunction %d %d\n", Context
->MinorFunction
, MinorFunction
);
3879 Context
->PendingReturned
= FALSE
;
3880 Status
= RxCompleteAsynchronousRequest(Context
, Status
);
3885 Status
= STATUS_NOT_IMPLEMENTED
;
3892 RxUnwindTopLevelIrp(&TopLevelContext
);
3895 FsRtlExitFileSystem();
3899 DPRINT("RxFsdDispatch, Status: %lx\n", Status
);
3909 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
3913 PIO_STACK_LOCATION Stack
;
3914 PRX_FSD_DISPATCH_VECTOR DispatchVector
;
3918 DPRINT("RxFsdDispatch(%p, %p)\n", RxDeviceObject
, Irp
);
3920 Stack
= IoGetCurrentIrpStackLocation(Irp
);
3922 /* Dispatch easy case */
3923 if (Stack
->MajorFunction
== IRP_MJ_SYSTEM_CONTROL
)
3925 return RxSystemControl(RxDeviceObject
, Irp
);
3928 /* Bail out broken cases */
3929 if (Stack
->MajorFunction
== IRP_MJ_CREATE_MAILSLOT
||
3930 Stack
->MajorFunction
== IRP_MJ_CREATE_NAMED_PIPE
)
3932 IoMarkIrpPending(Irp
);
3933 Irp
->IoStatus
.Information
= 0;
3934 Irp
->IoStatus
.Status
= STATUS_OBJECT_NAME_INVALID
;
3935 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3936 return STATUS_PENDING
;
3939 /* Immediately handle create */
3940 if (Stack
->MajorFunction
== IRP_MJ_CREATE
)
3942 return RxFsdCommonDispatch(&RxFsdDispatchVector
[0], Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
3945 /* If not a creation, we must have at least a FO with a FCB */
3946 if (Stack
->FileObject
== NULL
|| Stack
->FileObject
->FsContext
== NULL
)
3948 IoMarkIrpPending(Irp
);
3949 Irp
->IoStatus
.Information
= 0;
3950 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
3951 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3952 return STATUS_PENDING
;
3955 /* Set the dispatch vector if required */
3956 Fcb
= Stack
->FileObject
->FsContext
;
3957 if (!NodeTypeIsFcb(Fcb
) || Fcb
->PrivateDispatchVector
== NULL
)
3959 DispatchVector
= &RxFsdDispatchVector
[0];
3963 DispatchVector
= Fcb
->PrivateDispatchVector
;
3966 /* Device cannot accept such requests */
3967 if (RxDeviceObject
== RxFileSystemDeviceObject
)
3969 IoMarkIrpPending(Irp
);
3970 Irp
->IoStatus
.Information
= 0;
3971 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
3972 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
3973 return STATUS_PENDING
;
3976 /* Dispatch for real! */
3977 return RxFsdCommonDispatch(DispatchVector
, Stack
->MajorFunction
, Stack
, Stack
->FileObject
, Irp
, RxDeviceObject
);
3985 IN PRX_CONTEXT RxContext
)
3987 /* Initialize posting if required */
3988 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
3990 RxPrePostIrp(RxContext
, RxContext
->CurrentIrp
);
3993 DPRINT("Posting MN: %d, Ctxt: %p, IRP: %p, Thrd: %lx #%lx\n",
3994 RxContext
->MinorFunction
, RxContext
,
3995 RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
3996 RxContext
->SerialNumber
);
3998 RxAddToWorkque(RxContext
, RxContext
->CurrentIrp
);
3999 return STATUS_PENDING
;
4011 WORK_QUEUE_TYPE Queue
;
4012 PRDBSS_DEVICE_OBJECT VolumeDO
;
4013 PRX_CONTEXT RxContext
, EntryContext
;
4017 RxContext
= Context
;
4018 EntryContext
= Context
;
4019 /* Save IRQL at entry for later checking */
4020 EntryIrql
= KeGetCurrentIrql();
4022 /* No FO, deal with device */
4023 if (RxContext
->CurrentIrpSp
->FileObject
!= NULL
)
4025 VolumeDO
= RxFileSystemDeviceObject
;
4032 /* Which queue to used for delayed? */
4033 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
))
4035 Queue
= DelayedWorkQueue
;
4039 ASSERT(BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
4040 Queue
= CriticalWorkQueue
;
4047 BOOLEAN RecursiveCall
;
4048 RX_TOPLEVELIRP_CONTEXT TopLevelContext
;
4050 ASSERT(RxContext
->MajorFunction
<= IRP_MJ_MAXIMUM_FUNCTION
);
4051 ASSERT(!RxContext
->PostRequest
);
4053 RxContext
->LastExecutionThread
= PsGetCurrentThread();
4054 SetFlag(RxContext
->Flags
, (RX_CONTEXT_FLAG_IN_FSP
| RX_CONTEXT_FLAG_WAIT
));
4056 DPRINT("Dispatch: MN: %d, Ctxt: %p, IRP: %p, THRD: %lx #%lx", RxContext
->MinorFunction
,
4057 RxContext
, RxContext
->CurrentIrp
, RxContext
->LastExecutionThread
,
4058 RxContext
->SerialNumber
);
4060 Irp
= RxContext
->CurrentIrp
;
4062 FsRtlEnterFileSystem();
4064 RecursiveCall
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
);
4065 RxTryToBecomeTheTopLevelIrp(&TopLevelContext
,
4066 (RecursiveCall
? (PIRP
)FSRTL_FSP_TOP_LEVEL_IRP
: RxContext
->CurrentIrp
),
4067 RxContext
->RxDeviceObject
, TRUE
);
4069 ASSERT(RxContext
->ResumeRoutine
!= NULL
);
4071 if (BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_DPC
) && Irp
->Tail
.Overlay
.Thread
== NULL
)
4073 ASSERT((RxContext
->MajorFunction
== IRP_MJ_WRITE
) || (RxContext
->MajorFunction
== IRP_MJ_READ
));
4074 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
4077 /* Call the resume routine */
4082 NoComplete
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_COMPLETE_FROM_FSP
);
4084 Status
= RxContext
->ResumeRoutine(RxContext
);
4085 if (!NoComplete
&& Status
!= STATUS_PENDING
)
4087 if (Status
!= STATUS_RETRY
)
4089 Status
= RxCompleteRequest(RxContext
, Status
);
4093 while (Status
== STATUS_RETRY
);
4095 RxUnwindTopLevelIrp(&TopLevelContext
);
4096 FsRtlExitFileSystem();
4098 if (VolumeDO
!= NULL
)
4100 RxContext
= RxRemoveOverflowEntry(VolumeDO
, Queue
);
4106 } while (RxContext
!= NULL
);
4108 /* Did we mess with IRQL? */
4109 if (KeGetCurrentIrql() >= APC_LEVEL
)
4111 DPRINT1("High IRQL for Ctxt %p, on entry: %x\n", EntryContext
, EntryIrql
);
4119 RxGetNetworkProviderPriority(
4120 PUNICODE_STRING DeviceName
)
4131 RxGetRegistryParameters(
4132 IN PUNICODE_STRING RegistryPath
)
4136 UCHAR Buffer
[0x400];
4137 HANDLE DriverHandle
, KeyHandle
;
4138 UNICODE_STRING KeyName
, OutString
;
4139 OBJECT_ATTRIBUTES ObjectAttributes
;
4143 InitializeObjectAttributes(&ObjectAttributes
, RegistryPath
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
4144 Status
= ZwOpenKey(&DriverHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4145 if (!NT_SUCCESS(Status
))
4150 RtlInitUnicodeString(&KeyName
, L
"Parameters");
4151 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, DriverHandle
, FALSE
);
4152 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
4153 if (NT_SUCCESS(Status
))
4155 /* The only parameter we deal with is InitialDebugString */
4156 RxGetStringRegistryParameter(KeyHandle
, L
"InitialDebugString", &OutString
, Buffer
, sizeof(Buffer
), 0);
4157 if (OutString
.Length
!= 0 && OutString
.Length
< 0x140)
4162 Read
= OutString
.Buffer
;
4163 Write
= (PSTR
)OutString
.Buffer
;
4164 for (i
= 0; i
< OutString
.Length
; ++i
)
4172 /* Which is a string we'll just write out */
4173 DPRINT("InitialDebugString read from registry: '%s'\n", OutString
.Buffer
);
4174 RxDebugControlCommand((PSTR
)OutString
.Buffer
);
4180 ZwClose(DriverHandle
);
4188 IN PIO_STACK_LOCATION IrpSp
)
4191 PACCESS_TOKEN Token
;
4192 PIO_SECURITY_CONTEXT SecurityContext
;
4196 /* If that's not a prefix claim, not an open request, session id will be 0 */
4197 if (IrpSp
->MajorFunction
!= IRP_MJ_DEVICE_CONTROL
|| IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_REDIR_QUERY_PATH
)
4199 if (IrpSp
->MajorFunction
!= IRP_MJ_CREATE
|| IrpSp
->Parameters
.Create
.SecurityContext
== NULL
)
4204 SecurityContext
= IrpSp
->Parameters
.Create
.SecurityContext
;
4208 SecurityContext
= ((PQUERY_PATH_REQUEST
)IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
)->SecurityContext
;
4211 /* Query the session id */
4212 Token
= SeQuerySubjectContextToken(&SecurityContext
->AccessState
->SubjectSecurityContext
);
4213 SeQuerySessionIdToken(Token
, &SessionId
);
4223 RxGetStringRegistryParameter(
4224 IN HANDLE KeyHandle
,
4226 OUT PUNICODE_STRING OutString
,
4228 IN ULONG BufferLength
,
4229 IN BOOLEAN LogFailure
)
4233 UNICODE_STRING KeyString
;
4237 RtlInitUnicodeString(&KeyString
, KeyName
);
4238 Status
= ZwQueryValueKey(KeyHandle
, &KeyString
, KeyValuePartialInformation
, Buffer
, BufferLength
, &ResultLength
);
4239 OutString
->Length
= 0;
4240 OutString
->Buffer
= 0;
4241 if (!NT_SUCCESS(Status
))
4245 RxLogFailure(RxFileSystemDeviceObject
, NULL
, 0x80000BD3, Status
);
4251 OutString
->Buffer
= (PWSTR
)(((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->Data
);
4252 OutString
->Length
= ((PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
)->DataLength
- sizeof(UNICODE_NULL
);
4253 OutString
->MaximumLength
= OutString
->Length
;
4255 return STATUS_SUCCESS
;
4261 PRDBSS_DEVICE_OBJECT
4262 RxGetTopDeviceObjectIfRdbssIrp(
4266 PRDBSS_DEVICE_OBJECT TopDevice
= NULL
;
4268 TopLevelIrp
= IoGetTopLevelIrp();
4269 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
4271 TopDevice
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->RxDeviceObject
;
4282 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
)
4285 PACCESS_TOKEN Token
;
4289 Token
= SeQuerySubjectContextToken(SubjectSecurityContext
);
4290 SeQueryAuthenticationIdToken(Token
, &Luid
);
4297 RxIndicateChangeOfBufferingStateForSrvOpen(
4298 PMRX_SRV_CALL SrvCall
,
4299 PMRX_SRV_OPEN SrvOpen
,
4308 RxInitializeDebugSupport(
4319 RxInitializeDispatchVectors(
4320 PDRIVER_OBJECT DriverObject
)
4326 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; ++i
)
4328 DriverObject
->MajorFunction
[i
] = (PDRIVER_DISPATCH
)RxFsdDispatch
;
4331 RxDeviceFCB
.PrivateDispatchVector
= RxDeviceFCBVector
;
4332 ASSERT(RxFsdDispatchVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
4333 ASSERT(RxDeviceFCBVector
[IRP_MJ_MAXIMUM_FUNCTION
].CommonRoutine
!= NULL
);
4335 DriverObject
->FastIoDispatch
= &RxFastIoDispatch
;
4336 RxFastIoDispatch
.SizeOfFastIoDispatch
= sizeof(RxFastIoDispatch
);
4337 RxFastIoDispatch
.FastIoCheckIfPossible
= RxFastIoCheckIfPossible
;
4338 RxFastIoDispatch
.FastIoRead
= RxFastIoRead
;
4339 RxFastIoDispatch
.FastIoWrite
= RxFastIoWrite
;
4340 RxFastIoDispatch
.FastIoQueryBasicInfo
= NULL
;
4341 RxFastIoDispatch
.FastIoQueryStandardInfo
= NULL
;
4342 RxFastIoDispatch
.FastIoLock
= NULL
;
4343 RxFastIoDispatch
.FastIoUnlockSingle
= NULL
;
4344 RxFastIoDispatch
.FastIoUnlockAll
= NULL
;
4345 RxFastIoDispatch
.FastIoUnlockAllByKey
= NULL
;
4346 RxFastIoDispatch
.FastIoDeviceControl
= RxFastIoDeviceControl
;
4347 RxFastIoDispatch
.AcquireFileForNtCreateSection
= RxAcquireFileForNtCreateSection
;
4348 RxFastIoDispatch
.ReleaseFileForNtCreateSection
= RxReleaseFileForNtCreateSection
;
4349 RxFastIoDispatch
.AcquireForCcFlush
= RxAcquireForCcFlush
;
4350 RxFastIoDispatch
.ReleaseForCcFlush
= RxReleaseForCcFlush
;
4352 RxInitializeTopLevelIrpPackage();
4354 RxData
.CacheManagerCallbacks
.AcquireForLazyWrite
= RxAcquireFcbForLazyWrite
;
4355 RxData
.CacheManagerCallbacks
.ReleaseFromLazyWrite
= RxReleaseFcbFromLazyWrite
;
4356 RxData
.CacheManagerCallbacks
.AcquireForReadAhead
= RxAcquireFcbForReadAhead
;
4357 RxData
.CacheManagerCallbacks
.ReleaseFromReadAhead
= RxReleaseFcbFromReadAhead
;
4359 RxData
.CacheManagerNoOpCallbacks
.AcquireForLazyWrite
= RxNoOpAcquire
;
4360 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromLazyWrite
= RxNoOpRelease
;
4361 RxData
.CacheManagerNoOpCallbacks
.AcquireForReadAhead
= RxNoOpAcquire
;
4362 RxData
.CacheManagerNoOpCallbacks
.ReleaseFromReadAhead
= RxNoOpRelease
;
4371 return STATUS_NOT_IMPLEMENTED
;
4378 RxInitializeMinirdrDispatchTable(
4379 IN PDRIVER_OBJECT DriverObject
)
4389 RxInitializeRegistrationStructures(
4394 ExInitializeFastMutex(&RxData
.MinirdrRegistrationMutex
);
4395 RxData
.NumberOfMinirdrsRegistered
= 0;
4396 RxData
.NumberOfMinirdrsStarted
= 0;
4397 InitializeListHead(&RxData
.RegisteredMiniRdrs
);
4399 return STATUS_SUCCESS
;
4404 RxInitializeRxTimer(
4408 return STATUS_NOT_IMPLEMENTED
;
4416 RxInitializeTopLevelIrpPackage(
4419 KeInitializeSpinLock(&TopLevelIrpSpinLock
);
4420 InitializeListHead(&TopLevelIrpAllocatedContextsList
);
4426 PDRIVER_OBJECT DriverObject
,
4436 RxIsMemberOfTopLevelIrpAllocatedContextsList(
4437 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
4440 PLIST_ENTRY NextEntry
;
4441 BOOLEAN Found
= FALSE
;
4442 PRX_TOPLEVELIRP_CONTEXT ListContext
;
4444 /* Browse all the allocated TLC to find ours */
4445 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
4446 for (NextEntry
= TopLevelIrpAllocatedContextsList
.Flink
;
4447 NextEntry
!= &TopLevelIrpAllocatedContextsList
;
4448 NextEntry
= NextEntry
->Flink
)
4450 ListContext
= CONTAINING_RECORD(NextEntry
, RX_TOPLEVELIRP_CONTEXT
, ListEntry
);
4451 ASSERT(ListContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
4452 ASSERT(BooleanFlagOn(ListContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
4455 if (ListContext
== TopLevelContext
)
4461 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
4478 RxIsThisAnRdbssTopLevelContext(
4479 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
4481 ULONG_PTR StackTop
, StackBottom
;
4483 /* Bail out for flags */
4484 if ((ULONG_PTR
)TopLevelContext
<= FSRTL_FAST_IO_TOP_LEVEL_IRP
)
4489 /* Is our provided TLC allocated on stack? */
4490 IoGetStackLimits(&StackTop
, &StackBottom
);
4491 if ((ULONG_PTR
)TopLevelContext
<= StackBottom
- sizeof(RX_TOPLEVELIRP_CONTEXT
) &&
4492 (ULONG_PTR
)TopLevelContext
>= StackTop
)
4494 /* Yes, so check whether it's really a TLC by checking alignement & signature */
4495 if (!BooleanFlagOn((ULONG_PTR
)TopLevelContext
, 0x3) && TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
)
4503 /* No, use the helper function */
4504 return RxIsMemberOfTopLevelIrpAllocatedContextsList(TopLevelContext
);
4511 RxIsThisTheTopLevelIrp(
4516 /* When we put oursleves as top level, we set TLC as 'IRP', so look for it */
4517 TopLevelIrp
= IoGetTopLevelIrp();
4518 if (RxIsThisAnRdbssTopLevelContext((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
))
4520 TopLevelIrp
= ((PRX_TOPLEVELIRP_CONTEXT
)TopLevelIrp
)->Irp
;
4523 return (TopLevelIrp
== Irp
);
4528 RxLockOperationCompletion(
4533 return STATUS_NOT_IMPLEMENTED
;
4542 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
4543 IN PUNICODE_STRING OriginatorId
,
4548 PUNICODE_STRING Originator
= OriginatorId
;
4549 LARGE_INTEGER LargeLine
;
4551 /* Set optional parameters */
4552 LargeLine
.QuadPart
= Line
;
4553 if (OriginatorId
== NULL
|| OriginatorId
->Length
== 0)
4555 Originator
= (PUNICODE_STRING
)&unknownId
;
4559 RxLogEventWithAnnotation(DeviceObject
, EventId
, Status
, &LargeLine
, sizeof(LargeLine
), Originator
, 1);
4564 RxLogEventWithAnnotation(
4565 IN PRDBSS_DEVICE_OBJECT DeviceObject
,
4568 IN PVOID DataBuffer
,
4569 IN USHORT DataBufferLength
,
4570 IN PUNICODE_STRING Annotation
,
4571 IN ULONG AnnotationCount
)
4579 PRX_CONTEXT RxContext
)
4582 return STATUS_NOT_IMPLEMENTED
;
4590 RxLowIoIoCtlShellCompletion(
4591 PRX_CONTEXT RxContext
)
4598 DPRINT("RxLowIoIoCtlShellCompletion(%p)\n", RxContext
);
4600 Irp
= RxContext
->CurrentIrp
;
4601 Status
= RxContext
->IoStatusBlock
.Status
;
4603 /* Set information and status */
4604 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_OVERFLOW
)
4606 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
4609 Irp
->IoStatus
.Status
= Status
;
4619 PRX_CONTEXT RxContext
)
4626 DPRINT("RxLowIoReadShell(%p)\n", RxContext
);
4628 Fcb
= (PFCB
)RxContext
->pFcb
;
4629 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
4631 return STATUS_MORE_PROCESSING_REQUIRED
;
4634 /* Always update stats for disks */
4635 if (Fcb
->CachedNetRootType
== NET_ROOT_DISK
)
4637 ExInterlockedAddLargeStatistic(&RxContext
->RxDeviceObject
->NetworkReadBytesRequested
, RxContext
->LowIoContext
.ParamsFor
.ReadWrite
.ByteCount
);
4640 /* And forward the read to the mini-rdr */
4641 Status
= RxLowIoSubmit(RxContext
, RxLowIoReadShellCompletion
);
4642 DPRINT("RxLowIoReadShell(%p), Status: %lx\n", RxContext
, Status
);
4649 RxLowIoReadShellCompletion(
4650 PRX_CONTEXT RxContext
)
4655 BOOLEAN PagingIo
, IsPipe
;
4656 PIO_STACK_LOCATION Stack
;
4657 PLOWIO_CONTEXT LowIoContext
;
4661 DPRINT("RxLowIoReadShellCompletion(%p)\n", RxContext
);
4663 Status
= RxContext
->IoStatusBlock
.Status
;
4664 DPRINT("In %p, Status: %lx, Information: %lx\n", RxContext
, Status
, RxContext
->IoStatusBlock
.Information
);
4666 Irp
= RxContext
->CurrentIrp
;
4667 PagingIo
= BooleanFlagOn(Irp
->Flags
, IRP_PAGING_IO
);
4669 /* Set IRP information from the RX_CONTEXT status block */
4670 Irp
->IoStatus
.Information
= RxContext
->IoStatusBlock
.Information
;
4672 /* Fixup status for paging file if nothing was read */
4675 if (NT_SUCCESS(Status
) && RxContext
->IoStatusBlock
.Information
== 0)
4677 Status
= STATUS_END_OF_FILE
;
4681 LowIoContext
= &RxContext
->LowIoContext
;
4682 ASSERT(RxLowIoIsBufferLocked(LowIoContext
));
4684 /* Check broken cases that should never happen */
4685 Fcb
= (PFCB
)RxContext
->pFcb
;
4686 if (Status
== STATUS_FILE_LOCK_CONFLICT
)
4688 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_THIS_READ_ENLARGED
))
4691 return STATUS_RETRY
;
4694 else if (Status
== STATUS_SUCCESS
)
4696 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_RECURSIVE_CALL
))
4698 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_DISK_COMPRESSED
) ||
4699 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_BUF_COMPRESSED
))
4705 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILE_IS_SHADOWED
))
4711 /* Readahead should go through Cc and not finish here */
4712 ASSERT(!BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_READAHEAD
));
4714 /* If it's sync, RxCommonRead will finish the work - nothing to do here */
4715 if (BooleanFlagOn(LowIoContext
->Flags
, LOWIO_CONTEXT_FLAG_SYNCCALL
))
4720 Stack
= RxContext
->CurrentIrpSp
;
4721 IsPipe
= BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_OPERATION
);
4722 /* Release lock if required */
4725 RxReleasePagingIoResourceForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
4729 /* Set FastIo if read was a success */
4730 if (NT_SUCCESS(Status
) && !IsPipe
)
4732 SetFlag(Stack
->FileObject
->Flags
, FO_FILE_FAST_IO_READ
);
4735 if (BooleanFlagOn(RxContext
->FlagsForLowIo
, RXCONTEXT_FLAG4LOWIO_PIPE_SYNC_OPERATION
))
4737 RxResumeBlockedOperations_Serially(RxContext
, &((PFOBX
)RxContext
->pFobx
)->Specific
.NamedPipe
.ReadSerializationQueue
);
4741 RxReleaseFcbForThread(RxContext
, Fcb
, LowIoContext
->ResourceThreadId
);
4750 /* Final sanity checks */
4751 ASSERT(Status
!= STATUS_RETRY
);
4752 ASSERT(Irp
->IoStatus
.Information
<= Stack
->Parameters
.Read
.Length
);
4753 ASSERT(RxContext
->MajorFunction
== IRP_MJ_READ
);
4759 RxNotifyChangeDirectory(
4760 PRX_CONTEXT RxContext
)
4763 return STATUS_NOT_IMPLEMENTED
;
4767 RxPostStackOverflowRead (
4768 IN PRX_CONTEXT RxContext
)
4773 return STATUS_NOT_IMPLEMENTED
;
4780 RxpPrepareCreateContextForReuse(
4781 PRX_CONTEXT RxContext
)
4783 /* Reuse can only happen for open operations (STATUS_RETRY) */
4784 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
4786 /* Release the FCB if it was acquired */
4787 if (RxContext
->Create
.FcbAcquired
)
4789 RxReleaseFcb(RxContext
, RxContext
->pFcb
);
4790 RxContext
->Create
.FcbAcquired
= FALSE
;
4793 /* Free the canonical name */
4794 RxFreeCanonicalNameBuffer(RxContext
);
4796 /* If we have a VNetRoot associated */
4797 if (RxContext
->Create
.pVNetRoot
!= NULL
|| RxContext
->Create
.NetNamePrefixEntry
!= NULL
)
4799 /* Remove our link and thus, dereference the VNetRoot */
4800 RxpAcquirePrefixTableLockShared(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
, TRUE
);
4801 if (RxContext
->Create
.pVNetRoot
!= NULL
)
4803 RxDereferenceVNetRoot(RxContext
->Create
.pVNetRoot
, TRUE
);
4804 RxContext
->Create
.pVNetRoot
= NULL
;
4806 RxpReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
, TRUE
);
4809 DPRINT("RxContext: %p prepared for reuse\n", RxContext
);
4816 RxpQueryInfoMiniRdr(
4817 PRX_CONTEXT RxContext
,
4818 FILE_INFORMATION_CLASS FileInfoClass
,
4824 Fcb
= (PFCB
)RxContext
->pFcb
;
4826 /* Set the RX_CONTEXT */
4827 RxContext
->Info
.FsInformationClass
= FileInfoClass
;
4828 RxContext
->Info
.Buffer
= Buffer
;
4831 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryFileInfo
, (RxContext
));
4841 IN PRX_CONTEXT RxContext
)
4845 NET_ROOT_TYPE NetRootType
;
4846 UNICODE_STRING CanonicalName
, FileName
, NetRootName
;
4850 Irp
= RxContext
->CurrentIrp
;
4852 /* This has to come from MUP */
4853 if (Irp
->RequestorMode
== UserMode
)
4855 return STATUS_INVALID_DEVICE_REQUEST
;
4858 if (RxContext
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
)
4860 PQUERY_PATH_REQUEST QueryRequest
;
4862 /* Get parameters */
4863 QueryRequest
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
4865 /* Don't overflow allocation */
4866 if (QueryRequest
->PathNameLength
>= MAXUSHORT
- 1)
4868 return STATUS_INVALID_DEVICE_REQUEST
;
4871 /* Forcefully rewrite IRP MJ */
4872 RxContext
->MajorFunction
= IRP_MJ_CREATE
;
4874 /* Fake canon name */
4875 RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
= RxAllocatePoolWithTag(NonPagedPool
, QueryRequest
->PathNameLength
, RX_MISC_POOLTAG
);
4876 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
== NULL
)
4878 Status
= STATUS_INSUFFICIENT_RESOURCES
;
4882 /* Copy the prefix to look for */
4883 RtlCopyMemory(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, &QueryRequest
->FilePathName
[0], QueryRequest
->PathNameLength
);
4884 RxContext
->PrefixClaim
.SuppliedPathName
.Length
= QueryRequest
->PathNameLength
;
4885 RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
= QueryRequest
->PathNameLength
;
4887 /* Zero the create parameters */
4888 RtlZeroMemory(&RxContext
->Create
.NtCreateParameters
,
4889 FIELD_OFFSET(RX_CONTEXT
, AlsoCanonicalNameBuffer
) - FIELD_OFFSET(RX_CONTEXT
, Create
.NtCreateParameters
));
4890 RxContext
->Create
.ThisIsATreeConnectOpen
= TRUE
;
4891 RxContext
->Create
.NtCreateParameters
.SecurityContext
= QueryRequest
->SecurityContext
;
4895 /* If not devcontrol, it comes from open, name was already copied */
4896 ASSERT(RxContext
->MajorFunction
== IRP_MJ_CREATE
);
4897 ASSERT(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
);
4900 /* Canonilize name */
4901 NetRootType
= NET_ROOT_WILD
;
4902 RtlInitEmptyUnicodeString(&CanonicalName
, NULL
, 0);
4903 FileName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
4904 FileName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
4905 FileName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
4906 NetRootName
.Length
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
;
4907 NetRootName
.MaximumLength
= RxContext
->PrefixClaim
.SuppliedPathName
.MaximumLength
;
4908 NetRootName
.Buffer
= RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
;
4909 Status
= RxFirstCanonicalize(RxContext
, &FileName
, &CanonicalName
, &NetRootType
);
4910 /* It went fine, attempt to establish a connection (that way we know whether the prefix is accepted) */
4911 if (NT_SUCCESS(Status
))
4913 Status
= RxFindOrConstructVirtualNetRoot(RxContext
, &CanonicalName
, NetRootType
, &NetRootName
);
4915 if (Status
== STATUS_PENDING
)
4920 if (NT_SUCCESS(Status
))
4922 PQUERY_PATH_RESPONSE QueryResponse
;
4924 /* We accept the length that was canon (minus netroot) */
4925 QueryResponse
= RxContext
->CurrentIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
4926 QueryResponse
->LengthAccepted
= RxContext
->PrefixClaim
.SuppliedPathName
.Length
- NetRootName
.Length
;
4930 /* If we reach that point with MJ, reset everything and make IRP being a device control */
4931 if (RxContext
->MajorFunction
== IRP_MJ_CREATE
)
4933 if (RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
!= NULL
)
4935 RxFreePoolWithTag(RxContext
->PrefixClaim
.SuppliedPathName
.Buffer
, RX_MISC_POOLTAG
);
4938 RxpPrepareCreateContextForReuse(RxContext
);
4940 RxContext
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
4948 RxPrepareToReparseSymbolicLink(
4949 PRX_CONTEXT RxContext
,
4950 BOOLEAN SymbolicLinkEmbeddedInOldPath
,
4951 PUNICODE_STRING NewPath
,
4952 BOOLEAN NewPathIsAbsolute
,
4953 PBOOLEAN ReparseRequired
)
4956 return STATUS_NOT_IMPLEMENTED
;
4967 LOCK_OPERATION Lock
;
4968 PIO_STACK_LOCATION Stack
;
4969 PRX_CONTEXT RxContext
= Context
;
4971 /* NULL IRP is no option */
4977 /* Check whether preparation was really needed */
4978 if (BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
))
4982 /* Mark the context as prepared */
4983 SetFlag(RxContext
->Flags
, RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED
);
4985 /* Just lock the user buffer, with the correct length, depending on the MJ */
4986 Lock
= IoReadAccess
;
4987 Stack
= RxContext
->CurrentIrpSp
;
4988 if (RxContext
->MajorFunction
== IRP_MJ_READ
|| RxContext
->MajorFunction
== IRP_MJ_WRITE
)
4990 if (!BooleanFlagOn(RxContext
->MinorFunction
, IRP_MN_MDL
))
4992 if (RxContext
->MajorFunction
== IRP_MJ_READ
)
4994 Lock
= IoWriteAccess
;
4996 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.Read
.Length
);
5001 if ((RxContext
->MajorFunction
== IRP_MJ_DIRECTORY_CONTROL
&& RxContext
->MinorFunction
== IRP_MN_QUERY_DIRECTORY
) ||
5002 RxContext
->MajorFunction
== IRP_MJ_QUERY_EA
)
5004 Lock
= IoWriteAccess
;
5005 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.QueryDirectory
.Length
);
5007 else if (RxContext
->MajorFunction
== IRP_MJ_SET_EA
)
5009 RxLockUserBuffer(RxContext
, Lock
, Stack
->Parameters
.SetEa
.Length
);
5013 /* As it will be posted (async), mark the IRP pending */
5014 IoMarkIrpPending(Irp
);
5019 RxpUnregisterMinirdr(
5020 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
)
5026 RxQueryAlternateNameInfo(
5027 PRX_CONTEXT RxContext
,
5028 PFILE_NAME_INFORMATION AltNameInfo
)
5031 return STATUS_NOT_IMPLEMENTED
;
5039 PRX_CONTEXT RxContext
,
5040 PFILE_BASIC_INFORMATION BasicInfo
)
5044 DPRINT("RxQueryBasicInfo(%p, %p)\n", RxContext
, BasicInfo
);
5046 /* Simply zero and forward to mini-rdr */
5047 RtlZeroMemory(BasicInfo
, sizeof(FILE_BASIC_INFORMATION
));
5048 return RxpQueryInfoMiniRdr(RxContext
, FileBasicInformation
, BasicInfo
);
5052 RxQueryCompressedInfo(
5053 PRX_CONTEXT RxContext
,
5054 PFILE_COMPRESSION_INFORMATION CompressionInfo
)
5057 return STATUS_NOT_IMPLEMENTED
;
5065 PRX_CONTEXT RxContext
)
5072 BOOLEAN LockNotGranted
;
5073 ULONG Length
, FileIndex
;
5074 PUNICODE_STRING FileName
;
5075 PIO_STACK_LOCATION Stack
;
5076 FILE_INFORMATION_CLASS FileInfoClass
;
5080 DPRINT("RxQueryDirectory(%p)\n", RxContext
);
5082 /* Get parameters */
5083 Stack
= RxContext
->CurrentIrpSp
;
5084 Length
= Stack
->Parameters
.QueryDirectory
.Length
;
5085 FileName
= Stack
->Parameters
.QueryDirectory
.FileName
;
5086 FileInfoClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
5087 DPRINT("Wait: %d, Length: %ld, FileName: %p, Class: %d\n",
5088 FlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
), Length
,
5089 FileName
, FileInfoClass
);
5091 Irp
= RxContext
->CurrentIrp
;
5092 Flags
= Stack
->Flags
;
5093 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
5094 DPRINT("Index: %d, Buffer: %p, Flags: %x\n", FileIndex
, Irp
->UserBuffer
, Flags
);
5096 if (FileName
!= NULL
)
5098 DPRINT("FileName: %wZ\n", FileName
);
5101 /* No FOBX: not a standard file/directory */
5102 Fobx
= (PFOBX
)RxContext
->pFobx
;
5105 return STATUS_OBJECT_NAME_INVALID
;
5108 /* We can only deal with a disk */
5109 Fcb
= (PFCB
)RxContext
->pFcb
;
5110 if (Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
5112 DPRINT1("Not a disk! %x\n", Fcb
->pNetRoot
->Type
);
5113 return STATUS_INVALID_DEVICE_REQUEST
;
5116 /* Setup RX_CONTEXT related fields */
5117 RxContext
->QueryDirectory
.FileIndex
= FileIndex
;
5118 RxContext
->QueryDirectory
.RestartScan
= BooleanFlagOn(Flags
, SL_RESTART_SCAN
);
5119 RxContext
->QueryDirectory
.ReturnSingleEntry
= BooleanFlagOn(Flags
, SL_RETURN_SINGLE_ENTRY
);
5120 RxContext
->QueryDirectory
.IndexSpecified
= BooleanFlagOn(Flags
, SL_INDEX_SPECIFIED
);
5121 RxContext
->QueryDirectory
.InitialQuery
= (Fobx
->UnicodeQueryTemplate
.Buffer
== NULL
) && !BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
5123 /* We don't support (yet?) a specific index being set */
5124 if (RxContext
->QueryDirectory
.IndexSpecified
)
5126 return STATUS_NOT_IMPLEMENTED
;
5129 /* Try to lock FCB */
5130 LockNotGranted
= TRUE
;
5131 if (RxContext
->QueryDirectory
.InitialQuery
)
5133 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5134 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
5136 if (!NT_SUCCESS(Status
))
5141 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
5143 RxContext
->QueryDirectory
.InitialQuery
= FALSE
;
5144 RxConvertToSharedFcb(RxContext
, Fcb
);
5147 LockNotGranted
= FALSE
;
5152 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
5153 if (Status
!= STATUS_LOCK_NOT_GRANTED
)
5155 if (!NT_SUCCESS(Status
))
5160 LockNotGranted
= FALSE
;
5164 /* If it failed, post request */
5167 return RxFsdPostRequest(RxContext
);
5170 /* This cannot be done on a orphaned directory */
5171 if (BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_ORPHANED
))
5173 RxReleaseFcb(RxContext
, Fcb
);
5174 return STATUS_FILE_CLOSED
;
5180 if (!RxContext
->QueryDirectory
.IndexSpecified
&& RxContext
->QueryDirectory
.RestartScan
)
5182 RxContext
->QueryDirectory
.FileIndex
= 0;
5185 /* Assume success */
5186 Status
= STATUS_SUCCESS
;
5187 /* If initial query, prepare FOBX */
5188 if (RxContext
->QueryDirectory
.InitialQuery
)
5190 /* We cannot have a template already! */
5191 ASSERT(!BooleanFlagOn(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
));
5193 /* If we have a file name and a correct one, duplicate it in the FOBX */
5194 if (FileName
!= NULL
&& FileName
->Length
!= 0 && FileName
->Buffer
!= NULL
&&
5195 (FileName
->Length
!= sizeof(WCHAR
) || FileName
->Buffer
[0] != '*') &&
5196 (FileName
->Length
!= 12 * sizeof(WCHAR
) ||
5197 RtlCompareMemory(FileName
->Buffer
, Rx8QMdot3QM
, 12 * sizeof(WCHAR
)) != 12 * sizeof(WCHAR
)))
5199 Fobx
->ContainsWildCards
= FsRtlDoesNameContainWildCards(FileName
);
5201 Fobx
->UnicodeQueryTemplate
.Buffer
= RxAllocatePoolWithTag(PagedPool
, FileName
->Length
, RX_DIRCTL_POOLTAG
);
5202 if (Fobx
->UnicodeQueryTemplate
.Buffer
!= NULL
)
5204 /* UNICODE_STRING; length has to be even */
5205 if ((FileName
->Length
& 1) != 0)
5207 Status
= STATUS_INVALID_PARAMETER
;
5208 RxFreePoolWithTag(Fobx
->UnicodeQueryTemplate
.Buffer
, RX_DIRCTL_POOLTAG
);
5212 Fobx
->UnicodeQueryTemplate
.Length
= FileName
->Length
;
5213 Fobx
->UnicodeQueryTemplate
.MaximumLength
= FileName
->Length
;
5214 RtlMoveMemory(Fobx
->UnicodeQueryTemplate
.Buffer
, FileName
->Buffer
, FileName
->Length
);
5216 SetFlag(Fobx
->Flags
, FOBX_FLAG_FREE_UNICODE
);
5221 Status
= STATUS_INSUFFICIENT_RESOURCES
;
5224 /* No name specified, or a match all wildcard? Match everything */
5227 Fobx
->ContainsWildCards
= TRUE
;
5229 Fobx
->UnicodeQueryTemplate
.Buffer
= &RxStarForTemplate
;
5230 Fobx
->UnicodeQueryTemplate
.Length
= sizeof(WCHAR
);
5231 Fobx
->UnicodeQueryTemplate
.MaximumLength
= sizeof(WCHAR
);
5233 SetFlag(Fobx
->Flags
, FOBX_FLAG_MATCH_ALL
);
5236 /* No need for exclusive any longer */
5237 if (NT_SUCCESS(Status
))
5239 RxConvertToSharedFcb(RxContext
, Fcb
);
5243 /* Lock user buffer and forward to mini-rdr */
5244 if (NT_SUCCESS(Status
))
5246 RxLockUserBuffer(RxContext
, IoModifyAccess
, Length
);
5247 RxContext
->Info
.FileInformationClass
= FileInfoClass
;
5248 RxContext
->Info
.Buffer
= RxNewMapUserBuffer(RxContext
);
5249 RxContext
->Info
.Length
= Length
;
5251 if (RxContext
->Info
.Buffer
!= NULL
)
5253 MINIRDR_CALL(Status
, RxContext
, Fcb
->MRxDispatch
, MRxQueryDirectory
, (RxContext
));
5256 /* Post if mini-rdr asks to */
5257 if (RxContext
->PostRequest
)
5259 RxFsdPostRequest(RxContext
);
5263 Irp
->IoStatus
.Information
= Length
- RxContext
->Info
.LengthRemaining
;
5269 RxReleaseFcb(RxContext
, Fcb
);
5278 PRX_CONTEXT RxContext
,
5279 PFILE_EA_INFORMATION EaInfo
)
5282 return STATUS_NOT_IMPLEMENTED
;
5286 RxQueryInternalInfo(
5287 PRX_CONTEXT RxContext
,
5288 PFILE_INTERNAL_INFORMATION InternalInfo
)
5291 return STATUS_NOT_IMPLEMENTED
;
5296 PRX_CONTEXT RxContext
,
5297 PFILE_NAME_INFORMATION NameInfo
)
5300 return STATUS_NOT_IMPLEMENTED
;
5305 PRX_CONTEXT RxContext
,
5306 PFILE_PIPE_INFORMATION PipeInfo
)
5309 return STATUS_NOT_IMPLEMENTED
;
5313 RxQueryPositionInfo(
5314 PRX_CONTEXT RxContext
,
5315 PFILE_POSITION_INFORMATION PositionInfo
)
5318 return STATUS_NOT_IMPLEMENTED
;
5325 RxQueryStandardInfo(
5326 PRX_CONTEXT RxContext
,
5327 PFILE_STANDARD_INFORMATION StandardInfo
)
5335 DPRINT("RxQueryStandardInfo(%p, %p)\n", RxContext
, StandardInfo
);
5337 /* Zero output buffer */
5338 RtlZeroMemory(StandardInfo
, sizeof(FILE_STANDARD_INFORMATION
));
5340 Fcb
= (PFCB
)RxContext
->pFcb
;
5341 Fobx
= (PFOBX
)RxContext
->pFobx
;
5342 /* If not a standard file type, or opened for backup, immediately forward to mini-rdr */
5343 if ((NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_DIRECTORY
&& NodeType(Fcb
) != RDBSS_NTC_STORAGE_TYPE_FILE
) ||
5344 BooleanFlagOn(Fobx
->pSrvOpen
->CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
5346 return RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
5349 /* Otherwise, fill what we can already */
5350 Status
= STATUS_SUCCESS
;
5351 StandardInfo
->NumberOfLinks
= Fcb
->NumberOfLinks
;
5352 StandardInfo
->DeletePending
= BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_DELETE_ON_CLOSE
);
5353 StandardInfo
->Directory
= (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_DIRECTORY
);
5354 if (StandardInfo
->NumberOfLinks
== 0)
5356 StandardInfo
->NumberOfLinks
= 1;
5359 if (NodeType(Fcb
) == RDBSS_NTC_STORAGE_TYPE_FILE
)
5361 StandardInfo
->AllocationSize
.QuadPart
= Fcb
->Header
.AllocationSize
.QuadPart
;
5362 RxGetFileSizeWithLock(Fcb
, &StandardInfo
->EndOfFile
.QuadPart
);
5365 /* If we are asked to forcefully forward to mini-rdr or if size isn't cached, do it */
5366 if (RxForceQFIPassThrough
|| !BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_FILESIZECACHEING_ENABLED
))
5368 Status
= RxpQueryInfoMiniRdr(RxContext
, FileStandardInformation
, StandardInfo
);
5372 RxContext
->IoStatusBlock
.Information
-= sizeof(FILE_STANDARD_INFORMATION
);
5383 RxReadRegistryParameters(
5390 UNICODE_STRING KeyName
, ParamName
;
5391 OBJECT_ATTRIBUTES ObjectAttributes
;
5392 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
5396 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters");
5397 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
5398 Status
= ZwOpenKey(&KeyHandle
, READ_CONTROL
| KEY_NOTIFY
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
5399 if (!NT_SUCCESS(Status
))
5404 PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)Buffer
;
5405 RtlInitUnicodeString(&ParamName
, L
"DisableByteRangeLockingOnReadOnlyFiles");
5406 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
5407 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
5409 DisableByteRangeLockingOnReadOnlyFiles
= ((ULONG
)PartialInfo
->Data
!= 0);
5412 RtlInitUnicodeString(&ParamName
, L
"ReadAheadGranularity");
5413 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
5414 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
5416 ULONG Granularity
= (ULONG
)PartialInfo
->Data
;
5418 if (Granularity
> 16)
5423 ReadAheadGranularity
= Granularity
<< PAGE_SHIFT
;
5426 RtlInitUnicodeString(&ParamName
, L
"DisableFlushOnCleanup");
5427 Status
= ZwQueryValueKey(KeyHandle
, &ParamName
, KeyValuePartialInformation
, PartialInfo
, sizeof(Buffer
), &ResultLength
);
5428 if (NT_SUCCESS(Status
) && PartialInfo
->Type
== REG_DWORD
)
5430 DisableFlushOnCleanup
= ((ULONG
)PartialInfo
->Data
!= 0);
5442 OUT PRDBSS_DEVICE_OBJECT
*DeviceObject
,
5443 IN OUT PDRIVER_OBJECT DriverObject
,
5444 IN PMINIRDR_DISPATCH MrdrDispatch
,
5446 IN PUNICODE_STRING DeviceName
,
5447 IN ULONG DeviceExtensionSize
,
5448 IN DEVICE_TYPE DeviceType
,
5449 IN ULONG DeviceCharacteristics
)
5452 PRDBSS_DEVICE_OBJECT RDBSSDevice
;
5458 return STATUS_INVALID_PARAMETER
;
5461 /* Create device object with provided parameters */
5462 Status
= IoCreateDevice(DriverObject
,
5463 DeviceExtensionSize
+ sizeof(RDBSS_DEVICE_OBJECT
),
5466 DeviceCharacteristics
,
5468 (PDEVICE_OBJECT
*)&RDBSSDevice
);
5469 if (!NT_SUCCESS(Status
))
5474 if (!RxData
.DriverObject
)
5476 return STATUS_UNSUCCESSFUL
;
5479 /* Initialize our DO extension */
5480 RDBSSDevice
->RDBSSDeviceObject
= NULL
;
5481 ++RxFileSystemDeviceObject
->ReferenceCount
;
5482 *DeviceObject
= RDBSSDevice
;
5483 RDBSSDevice
->RdbssExports
= &RxExports
;
5484 RDBSSDevice
->Dispatch
= MrdrDispatch
;
5485 RDBSSDevice
->RegistrationControls
= Controls
;
5486 RDBSSDevice
->DeviceName
= *DeviceName
;
5487 RDBSSDevice
->RegisterUncProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS
);
5488 RDBSSDevice
->RegisterMailSlotProvider
= !BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS
);
5489 InitializeListHead(&RDBSSDevice
->OverflowQueue
[0]);
5490 InitializeListHead(&RDBSSDevice
->OverflowQueue
[1]);
5491 InitializeListHead(&RDBSSDevice
->OverflowQueue
[2]);
5492 KeInitializeSpinLock(&RDBSSDevice
->OverflowQueueSpinLock
);
5493 RDBSSDevice
->NetworkProviderPriority
= RxGetNetworkProviderPriority(DeviceName
);
5495 DPRINT("Registered MiniRdr %wZ (prio: %x)\n", DeviceName
, RDBSSDevice
->NetworkProviderPriority
);
5497 ExAcquireFastMutex(&RxData
.MinirdrRegistrationMutex
);
5498 InsertTailList(&RxData
.RegisteredMiniRdrs
, &RDBSSDevice
->MiniRdrListLinks
);
5499 ExReleaseFastMutex(&RxData
.MinirdrRegistrationMutex
);
5501 /* Unless mini-rdr explicitly asked not to, initialize dispatch table */
5502 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_DRIVER_DISPATCH
))
5504 RxInitializeMinirdrDispatchTable(DriverObject
);
5507 /* Unless mini-rdr explicitly asked not to, initialize prefix scavenger */
5508 if (!BooleanFlagOn(Controls
, RX_REGISTERMINI_FLAG_DONT_INIT_PREFIX_N_SCAVENGER
))
5510 LARGE_INTEGER ScavengerTimeLimit
;
5512 RDBSSDevice
->pRxNetNameTable
= &RDBSSDevice
->RxNetNameTableInDeviceObject
;
5513 RxInitializePrefixTable(RDBSSDevice
->pRxNetNameTable
, 0, FALSE
);
5514 RDBSSDevice
->RxNetNameTableInDeviceObject
.IsNetNameTable
= TRUE
;
5515 ScavengerTimeLimit
.QuadPart
= MrdrDispatch
->ScavengerTimeout
* 10000000LL;
5516 RDBSSDevice
->pRdbssScavenger
= &RDBSSDevice
->RdbssScavengerInDeviceObject
;
5517 RxInitializeRdbssScavenger(RDBSSDevice
->pRdbssScavenger
, ScavengerTimeLimit
);
5520 RDBSSDevice
->pAsynchronousRequestsCompletionEvent
= NULL
;
5522 return STATUS_SUCCESS
;
5527 RxReleaseFcbFromLazyWrite(
5535 RxReleaseFcbFromReadAhead(
5543 RxReleaseFileForNtCreateSection(
5544 PFILE_OBJECT FileObject
)
5551 RxReleaseForCcFlush(
5552 PFILE_OBJECT FileObject
,
5553 PDEVICE_OBJECT DeviceObject
)
5556 return STATUS_NOT_IMPLEMENTED
;
5563 RxRemoveFromTopLevelIrpAllocatedContextsList(
5564 PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
5568 /* Make sure this is a TLC and that it was allocated (otherwise, it is not in the list */
5569 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
5570 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
5572 KeAcquireSpinLock(&TopLevelIrpSpinLock
, &OldIrql
);
5573 RemoveEntryList(&TopLevelContext
->ListEntry
);
5574 KeReleaseSpinLock(&TopLevelIrpSpinLock
, OldIrql
);
5581 RxRemoveOverflowEntry(
5582 PRDBSS_DEVICE_OBJECT DeviceObject
,
5583 WORK_QUEUE_TYPE Queue
)
5586 PRX_CONTEXT Context
;
5588 KeAcquireSpinLock(&DeviceObject
->OverflowQueueSpinLock
, &OldIrql
);
5589 if (DeviceObject
->OverflowQueueCount
[Queue
] <= 0)
5591 /* No entries left, nothing to return */
5592 InterlockedDecrement(&DeviceObject
->PostedRequestCount
[Queue
]);
5599 /* Decrement count */
5600 --DeviceObject
->OverflowQueueCount
[Queue
];
5603 Entry
= RemoveHeadList(&DeviceObject
->OverflowQueue
[Queue
]);
5604 Context
= CONTAINING_RECORD(Entry
, RX_CONTEXT
, OverflowListEntry
);
5605 ClearFlag(Context
->Flags
, ~(RX_CONTEXT_FLAG_FSP_DELAYED_OVERFLOW_QUEUE
| RX_CONTEXT_FLAG_FSP_CRITICAL_OVERFLOW_QUEUE
));
5606 Context
->OverflowListEntry
.Flink
= NULL
;
5608 KeReleaseSpinLock(&DeviceObject
->OverflowQueueSpinLock
, OldIrql
);
5614 RxRemoveShareAccess(
5615 _Inout_ PFILE_OBJECT FileObject
,
5616 _Inout_ PSHARE_ACCESS ShareAccess
,
5618 _In_ PSZ wherelogtag
)
5624 RxSearchForCollapsibleOpen(
5625 PRX_CONTEXT RxContext
,
5626 ACCESS_MASK DesiredAccess
,
5631 PLIST_ENTRY ListEntry
;
5632 BOOLEAN ShouldTry
, Purged
, Scavenged
;
5636 DPRINT("RxSearchForCollapsibleOpen(%p, %x, %x)\n", RxContext
, DesiredAccess
, ShareAccess
);
5638 Fcb
= (PFCB
)RxContext
->pFcb
;
5640 /* If we're asked to open for backup, don't allow SRV_OPEN reuse */
5641 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_OPEN_FOR_BACKUP_INTENT
))
5643 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
5645 RxScavengeRelatedFobxs(Fcb
);
5646 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
5648 return STATUS_NOT_FOUND
;
5651 /* If basic open, ask the mini-rdr if we should try to collapse */
5652 if (RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN
||
5653 RxContext
->Create
.NtCreateParameters
.Disposition
== FILE_OPEN_IF
)
5657 if (Fcb
->MRxDispatch
!= NULL
)
5659 ASSERT(RxContext
->pRelevantSrvOpen
== NULL
);
5660 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
5662 ShouldTry
= NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
));
5670 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
, FILE_DELETE_ON_CLOSE
))
5675 /* If we shouldn't try, ask the caller to allocate a new SRV_OPEN */
5678 if (NT_SUCCESS(RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
)))
5680 return STATUS_NOT_FOUND
;
5683 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
5685 RxScavengeRelatedFobxs(Fcb
);
5686 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
5688 return STATUS_NOT_FOUND
;
5691 /* Only collapse for matching NET_ROOT & disks */
5692 if (Fcb
->pNetRoot
!= RxContext
->Create
.pNetRoot
||
5693 Fcb
->pNetRoot
->Type
!= NET_ROOT_DISK
)
5695 return STATUS_NOT_FOUND
;
5700 Status
= STATUS_NOT_FOUND
;
5702 /* Browse all our SRV_OPEN to find the matching one */
5703 for (ListEntry
= Fcb
->SrvOpenList
.Flink
;
5704 ListEntry
!= &Fcb
->SrvOpenList
;
5705 ListEntry
= ListEntry
->Flink
)
5709 SrvOpen
= CONTAINING_RECORD(ListEntry
, SRV_OPEN
, SrvOpenQLinks
);
5710 /* Not the same VNET_ROOT, move to the next one */
5711 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
5713 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
5717 /* Is there a sharing violation? */
5718 if (SrvOpen
->DesiredAccess
!= DesiredAccess
|| SrvOpen
->ShareAccess
!= ShareAccess
||
5719 BooleanFlagOn(SrvOpen
->Flags
, (SRVOPEN_FLAG_CLOSED
| SRVOPEN_FLAG_COLLAPSING_DISABLED
| SRVOPEN_FLAG_FILE_DELETED
| SRVOPEN_FLAG_FILE_RENAMED
)))
5721 if (SrvOpen
->pVNetRoot
!= RxContext
->Create
.pVNetRoot
)
5723 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
5727 /* Check against the SRV_OPEN */
5728 Status
= RxCheckShareAccessPerSrvOpens(Fcb
, DesiredAccess
, ShareAccess
);
5729 if (!NT_SUCCESS(Status
))
5736 /* Don't allow collaspse for reparse point opening */
5737 if (BooleanFlagOn(RxContext
->Create
.NtCreateParameters
.CreateOptions
^ SrvOpen
->CreateOptions
, FILE_OPEN_REPARSE_POINT
))
5741 Status
= STATUS_NOT_FOUND
;
5745 /* Not readonly? Or bytereange lock disabled? Try to collapse! */
5746 if (DisableByteRangeLockingOnReadOnlyFiles
|| !BooleanFlagOn(SrvOpen
->pFcb
->Attributes
, FILE_ATTRIBUTE_READONLY
))
5748 RxContext
->pRelevantSrvOpen
= (PMRX_SRV_OPEN
)SrvOpen
;
5750 ASSERT(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen
!= NULL
);
5751 if (NT_SUCCESS(Fcb
->MRxDispatch
->MRxShouldTryToCollapseThisOpen(RxContext
)))
5753 /* Is close delayed - great reuse*/
5754 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
))
5756 DPRINT("Delayed close successfull, reusing %p\n", SrvOpen
);
5757 InterlockedDecrement(&((PSRV_CALL
)Fcb
->pNetRoot
->pSrvCall
)->NumberOfCloseDelayedFiles
);
5758 ClearFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_CLOSE_DELAYED
);
5761 return STATUS_SUCCESS
;
5764 Status
= STATUS_NOT_FOUND
;
5769 /* We browse the whole list and didn't find any matching? NOT_FOUND */
5770 if (ListEntry
== &Fcb
->SrvOpenList
)
5772 Status
= STATUS_NOT_FOUND
;
5775 /* Only required access: read attributes? Don't reuse */
5776 if ((DesiredAccess
& 0xFFEFFFFF) == FILE_READ_ATTRIBUTES
)
5778 return STATUS_NOT_FOUND
;
5781 /* Not found? Scavenge and retry to look for collaspile SRV_OPEN */
5784 ClearFlag(Fcb
->FcbState
, FCB_STATE_COLLAPSING_ENABLED
);
5786 RxScavengeRelatedFobxs(Fcb
);
5790 /* Not found? Purgeable? Purge and retry to look for collaspile SRV_OPEN */
5791 if (!Purged
&& RxIsOkToPurgeFcb(Fcb
))
5793 RxPurgeFcbInSystemCache(Fcb
, NULL
, 0, FALSE
, TRUE
);
5798 /* If sharing violation, keep track of it */
5799 if (Status
== STATUS_SHARING_VIOLATION
)
5801 RxContext
->Create
.TryForScavengingOnSharingViolation
= TRUE
;
5804 DPRINT("Status: %x\n", Status
);
5813 _In_ ACCESS_MASK DesiredAccess
,
5814 _In_ ULONG DesiredShareAccess
,
5815 _Inout_ PFILE_OBJECT FileObject
,
5816 _Out_ PSHARE_ACCESS ShareAccess
,
5818 _In_ PSZ wherelogtag
)
5822 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
5823 IoSetShareAccess(DesiredAccess
, DesiredShareAccess
, FileObject
, ShareAccess
);
5824 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
5831 RxSetupNetFileObject(
5832 PRX_CONTEXT RxContext
)
5836 PFILE_OBJECT FileObject
;
5837 PIO_STACK_LOCATION Stack
;
5841 /* Assert FOBX is FOBX or NULL */
5842 Fobx
= (PFOBX
)RxContext
->pFobx
;
5843 ASSERT((Fobx
== NULL
) || (NodeType(Fobx
) == RDBSS_NTC_FOBX
));
5845 Fcb
= (PFCB
)RxContext
->pFcb
;
5846 Stack
= RxContext
->CurrentIrpSp
;
5847 FileObject
= Stack
->FileObject
;
5848 /* If it's temporary mark FO as such */
5849 if (Fcb
!= NULL
&& NodeType(Fcb
) != RDBSS_NTC_VCB
&&
5850 BooleanFlagOn(Fcb
->FcbState
, FCB_STATE_TEMPORARY
))
5852 if (FileObject
== NULL
)
5857 FileObject
->Flags
|= FO_TEMPORARY_FILE
;
5860 /* No FO, nothing to setup */
5861 if (FileObject
== NULL
)
5866 /* Assign FCB & CCB (FOBX) to FO */
5867 FileObject
->FsContext
= Fcb
;
5868 FileObject
->FsContext2
= Fobx
;
5871 ULONG_PTR StackTop
, StackBottom
;
5873 /* If FO is allocated on pool, keep track of it */
5874 IoGetStackLimits(&StackTop
, &StackBottom
);
5875 if ((ULONG_PTR
)FileObject
<= StackBottom
|| (ULONG_PTR
)FileObject
>= StackTop
)
5877 Fobx
->AssociatedFileObject
= FileObject
;
5881 Fobx
->AssociatedFileObject
= NULL
;
5884 /* Make sure to mark FOBX if it's a DFS open */
5885 if (RxContext
->Create
.NtCreateParameters
.DfsContext
== UIntToPtr(DFS_OPEN_CONTEXT
))
5887 SetFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
5891 ClearFlag(Fobx
->Flags
, FOBX_FLAG_DFS_OPEN
);
5895 /* Set Cc pointers */
5896 FileObject
->SectionObjectPointer
= &Fcb
->NonPaged
->SectionObjectPointers
;
5898 /* Update access state */
5899 if (Stack
->Parameters
.Create
.SecurityContext
!= NULL
)
5901 PACCESS_STATE AccessState
;
5903 AccessState
= Stack
->Parameters
.Create
.SecurityContext
->AccessState
;
5904 AccessState
->PreviouslyGrantedAccess
|= AccessState
->RemainingDesiredAccess
;
5905 AccessState
->RemainingDesiredAccess
= 0;
5915 IN PRX_CONTEXT RxContext
,
5916 OUT PBOOLEAN PostToFsp
)
5919 BOOLEAN Wait
, AlreadyStarted
;
5920 PRDBSS_DEVICE_OBJECT DeviceObject
;
5922 /* If we've not been post, then, do it */
5923 if (!BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_IN_FSP
))
5925 SECURITY_SUBJECT_CONTEXT SubjectContext
;
5927 SeCaptureSubjectContext(&SubjectContext
);
5928 RxContext
->FsdUid
= RxGetUid(&SubjectContext
);
5929 SeReleaseSubjectContext(&SubjectContext
);
5932 return STATUS_PENDING
;
5935 /* Acquire all the required locks */
5936 Wait
= BooleanFlagOn(RxContext
->Flags
, RX_CONTEXT_FLAG_WAIT
);
5937 if (!ExAcquireResourceExclusiveLite(&RxData
.Resource
, Wait
))
5940 return STATUS_PENDING
;
5943 if (!RxAcquirePrefixTableLockExclusive(RxContext
->RxDeviceObject
->pRxNetNameTable
, Wait
))
5945 ExReleaseResourceLite(&RxData
.Resource
);
5947 return STATUS_PENDING
;
5950 AlreadyStarted
= FALSE
;
5951 DeviceObject
= RxContext
->RxDeviceObject
;
5954 /* MUP handle set, means already registered */
5955 if (DeviceObject
->MupHandle
!= NULL
)
5957 AlreadyStarted
= TRUE
;
5958 Status
= STATUS_REDIRECTOR_STARTED
;
5962 /* If we're asked to register to MUP, then do it */
5963 Status
= STATUS_SUCCESS
;
5964 if (DeviceObject
->RegisterUncProvider
)
5966 Status
= FsRtlRegisterUncProvider(&DeviceObject
->MupHandle
,
5967 &DeviceObject
->DeviceName
,
5968 DeviceObject
->RegisterMailSlotProvider
);
5970 if (!NT_SUCCESS(Status
))
5972 DeviceObject
->MupHandle
= NULL
;
5976 /* Register as file system */
5977 IoRegisterFileSystem(&DeviceObject
->DeviceObject
);
5978 DeviceObject
->RegisteredAsFileSystem
= TRUE
;
5980 /* Inform mini-rdr it has to start */
5981 MINIRDR_CALL(Status
, RxContext
, DeviceObject
->Dispatch
, MRxStart
, (RxContext
, DeviceObject
));
5982 if (NT_SUCCESS(Status
))
5984 ++DeviceObject
->StartStopContext
.Version
;
5985 RxSetRdbssState(DeviceObject
, RDBSS_STARTED
);
5986 InterlockedExchangeAdd(&RxData
.NumberOfMinirdrsStarted
, 1);
5988 Status
= RxInitializeMRxDispatcher(DeviceObject
);
5993 if (_SEH2_AbnormalTermination() || !NT_SUCCESS(Status
))
5995 if (!AlreadyStarted
)
5997 RxUnstart(RxContext
, DeviceObject
);
6001 RxReleasePrefixTableLock(RxContext
->RxDeviceObject
->pRxNetNameTable
);
6002 ExReleaseResourceLite(&RxData
.Resource
);
6012 IN PRX_CONTEXT RxContext
,
6013 OUT PBOOLEAN PostToFsp
)
6016 return STATUS_NOT_IMPLEMENTED
;
6021 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6025 return STATUS_NOT_IMPLEMENTED
;
6032 RxTryToBecomeTheTopLevelIrp(
6033 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
,
6035 IN PRDBSS_DEVICE_OBJECT RxDeviceObject
,
6036 IN BOOLEAN ForceTopLevel
6039 BOOLEAN FromPool
= FALSE
;
6043 /* If not top level, and not have to be, quit */
6044 if (IoGetTopLevelIrp() && !ForceTopLevel
)
6049 /* If not TLC provider, allocate one */
6050 if (TopLevelContext
== NULL
)
6052 TopLevelContext
= RxAllocatePoolWithTag(NonPagedPool
, sizeof(RX_TOPLEVELIRP_CONTEXT
), RX_TLC_POOLTAG
);
6053 if (TopLevelContext
== NULL
)
6062 __RxInitializeTopLevelIrpContext(TopLevelContext
, Irp
, RxDeviceObject
, FromPool
);
6064 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6067 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6070 /* Make it top level IRP */
6071 IoSetTopLevelIrp((PIRP
)TopLevelContext
);
6079 RxUpdateShareAccess(
6080 _Inout_ PFILE_OBJECT FileObject
,
6081 _Inout_ PSHARE_ACCESS ShareAccess
,
6083 _In_ PSZ wherelogtag
)
6087 RxDumpCurrentAccess(where
, "before", wherelogtag
, ShareAccess
);
6088 IoUpdateShareAccess(FileObject
, ShareAccess
);
6089 RxDumpCurrentAccess(where
, "after", wherelogtag
, ShareAccess
);
6096 RxUninitializeCacheMap(
6097 PRX_CONTEXT RxContext
,
6098 PFILE_OBJECT FileObject
,
6099 PLARGE_INTEGER TruncateSize
)
6103 CACHE_UNINITIALIZE_EVENT UninitEvent
;
6107 Fcb
= FileObject
->FsContext
;
6108 ASSERT(NodeTypeIsFcb(Fcb
));
6109 ASSERT(RxIsFcbAcquiredExclusive(Fcb
));
6111 KeInitializeEvent(&UninitEvent
.Event
, SynchronizationEvent
, FALSE
);
6112 CcUninitializeCacheMap(FileObject
, TruncateSize
, &UninitEvent
);
6114 /* Always release the FCB before waiting for the uninit event */
6115 RxReleaseFcb(RxContext
, Fcb
);
6117 KeWaitForSingleObject(&UninitEvent
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
6119 /* Re-acquire it afterwards */
6120 Status
= RxAcquireExclusiveFcb(RxContext
, Fcb
);
6121 ASSERT(NT_SUCCESS(Status
));
6127 IN PDRIVER_OBJECT DriverObject
)
6136 IN PFILE_LOCK_INFO LockInfo
)
6143 PRX_CONTEXT Context
,
6144 PRDBSS_DEVICE_OBJECT DeviceObject
)
6153 RxUnwindTopLevelIrp(
6154 IN OUT PRX_TOPLEVELIRP_CONTEXT TopLevelContext
)
6156 DPRINT("RxUnwindTopLevelIrp(%p)\n", TopLevelContext
);
6158 /* No TLC provided? Ask the system for ours! */
6159 if (TopLevelContext
== NULL
)
6161 TopLevelContext
= (PRX_TOPLEVELIRP_CONTEXT
)IoGetTopLevelIrp();
6162 if (TopLevelContext
== NULL
)
6167 /* In that case, just assert it's really ours */
6168 ASSERT(RxIsThisAnRdbssTopLevelContext(TopLevelContext
));
6169 ASSERT(BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
));
6172 ASSERT(TopLevelContext
->Signature
== RX_TOPLEVELIRP_CONTEXT_SIGNATURE
);
6173 ASSERT(TopLevelContext
->Thread
== PsGetCurrentThread());
6174 /* Restore the previous top level IRP */
6175 IoSetTopLevelIrp(TopLevelContext
->Previous
);
6176 /* If TLC was allocated from pool, remove it from list and release it */
6177 if (BooleanFlagOn(TopLevelContext
->Flags
, RX_TOPLEVELCTX_FLAG_FROM_POOL
))
6179 RxRemoveFromTopLevelIrpAllocatedContextsList(TopLevelContext
);
6180 RxFreePoolWithTag(TopLevelContext
, RX_TLC_POOLTAG
);
6188 RxUpdateShareAccessPerSrvOpens(
6189 IN PSRV_OPEN SrvOpen
)
6191 ACCESS_MASK DesiredAccess
;
6193 BOOLEAN WriteAccess
;
6194 BOOLEAN DeleteAccess
;
6198 /* If already updated, no need to continue */
6199 if (BooleanFlagOn(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
))
6204 /* Check if any access wanted */
6205 DesiredAccess
= SrvOpen
->DesiredAccess
;
6206 ReadAccess
= (DesiredAccess
& (FILE_READ_DATA
| FILE_EXECUTE
)) != 0;
6207 WriteAccess
= (DesiredAccess
& (FILE_WRITE_DATA
| FILE_APPEND_DATA
)) != 0;
6208 DeleteAccess
= (DesiredAccess
& DELETE
) != 0;
6210 /* In that case, update it */
6211 if ((ReadAccess
) || (WriteAccess
) || (DeleteAccess
))
6214 BOOLEAN SharedWrite
;
6215 BOOLEAN SharedDelete
;
6216 ULONG DesiredShareAccess
;
6217 PSHARE_ACCESS ShareAccess
;
6219 ShareAccess
= &((PFCB
)SrvOpen
->pFcb
)->ShareAccessPerSrvOpens
;
6220 DesiredShareAccess
= SrvOpen
->ShareAccess
;
6222 SharedRead
= (DesiredShareAccess
& FILE_SHARE_READ
) != 0;
6223 SharedWrite
= (DesiredShareAccess
& FILE_SHARE_WRITE
) != 0;
6224 SharedDelete
= (DesiredShareAccess
& FILE_SHARE_DELETE
) != 0;
6226 ShareAccess
->OpenCount
++;
6228 ShareAccess
->Readers
+= ReadAccess
;
6229 ShareAccess
->Writers
+= WriteAccess
;
6230 ShareAccess
->Deleters
+= DeleteAccess
;
6231 ShareAccess
->SharedRead
+= SharedRead
;
6232 ShareAccess
->SharedWrite
+= SharedWrite
;
6233 ShareAccess
->SharedDelete
+= SharedDelete
;
6236 SetFlag(SrvOpen
->Flags
, SRVOPEN_FLAG_SHAREACCESS_UPDATED
);
6243 RxXXXControlFileCallthru(
6244 PRX_CONTEXT Context
)
6250 DPRINT("RxXXXControlFileCallthru(%p)\n", Context
);
6252 /* No dispatch table? Nothing to dispatch */
6253 if (Context
->RxDeviceObject
->Dispatch
== NULL
)
6255 Context
->pFobx
= NULL
;
6256 return STATUS_INVALID_DEVICE_REQUEST
;
6259 /* Init the lowio context */
6260 Status
= RxLowIoPopulateFsctlInfo(Context
);
6261 if (!NT_SUCCESS(Status
))
6266 /* Check whether we're consistent: a length means a buffer */
6267 if ((Context
->LowIoContext
.ParamsFor
.FsCtl
.InputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pInputBuffer
== NULL
) ||
6268 (Context
->LowIoContext
.ParamsFor
.FsCtl
.OutputBufferLength
> 0 && Context
->LowIoContext
.ParamsFor
.FsCtl
.pOutputBuffer
== NULL
))
6270 return STATUS_INVALID_PARAMETER
;
6273 /* Forward the call to the mini-rdr */
6274 DPRINT("Calling: %p\n", Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile
);
6275 Status
= Context
->RxDeviceObject
->Dispatch
->MRxDevFcbXXXControlFile(Context
);
6276 if (Status
!= STATUS_PENDING
)
6278 Context
->CurrentIrp
->IoStatus
.Information
= Context
->InformationToReturn
;
6281 DPRINT("RxXXXControlFileCallthru: %x, %ld\n", Context
->CurrentIrp
->IoStatus
.Status
, Context
->CurrentIrp
->IoStatus
.Information
);