3 Copyright (c) 1989-2000 Microsoft Corporation
11 This module implements the DRIVER_INITIALIZATION routine for Fat
18 DRIVER_INITIALIZE DriverEntry
;
23 _In_ PDRIVER_OBJECT DriverObject
,
24 _In_ PUNICODE_STRING RegistryPath
27 _Function_class_(DRIVER_UNLOAD
)
32 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
34 _In_ PDRIVER_OBJECT DriverObject
39 FatGetCompatibilityModeValue(
40 IN PUNICODE_STRING ValueName
,
49 #pragma alloc_text(INIT, DriverEntry)
50 #pragma alloc_text(INIT, FatGetCompatibilityModeValue)
51 #pragma alloc_text(INIT, FatIsFujitsuFMR)
52 //#pragma alloc_text(PAGE, FatUnload)
55 #define COMPATIBILITY_MODE_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem"
56 #define COMPATIBILITY_MODE_VALUE_NAME L"Win31FileSystem"
57 #define CODE_PAGE_INVARIANCE_VALUE_NAME L"FatDisableCodePageInvariance"
60 #define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + \
63 #define REGISTRY_HARDWARE_DESCRIPTION_W \
64 L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System"
66 #define REGISTRY_MACHINE_IDENTIFIER_W L"Identifier"
68 #define FUJITSU_FMR_NAME_W L"FUJITSU FMR-"
75 _In_ PDRIVER_OBJECT DriverObject
,
76 _In_ PUNICODE_STRING RegistryPath
83 This is the initialization routine for the Fat file system
84 device driver. This routine creates the device object for the FileSystem
85 device and performs all other driver initialization.
89 DriverObject - Pointer to driver object created by the system.
93 NTSTATUS - The function value is the final status from the initialization
101 UNICODE_STRING UnicodeString
;
102 FS_FILTER_CALLBACKS FilterCallbacks
;
103 UNICODE_STRING ValueName
;
106 UNREFERENCED_PARAMETER( RegistryPath
);
109 // Create the device object for disks. To avoid problems with filters who
110 // know this name, we must keep it.
113 RtlInitUnicodeString( &UnicodeString
, L
"\\Fat" );
114 Status
= IoCreateDevice( DriverObject
,
117 FILE_DEVICE_DISK_FILE_SYSTEM
,
120 &FatDiskFileSystemDeviceObject
);
122 if (!NT_SUCCESS( Status
)) {
127 // Create the device object for "cdroms".
130 RtlInitUnicodeString( &UnicodeString
, L
"\\FatCdrom" );
131 Status
= IoCreateDevice( DriverObject
,
134 FILE_DEVICE_CD_ROM_FILE_SYSTEM
,
137 &FatCdromFileSystemDeviceObject
);
139 if (!NT_SUCCESS( Status
)) {
140 IoDeleteDevice( FatDiskFileSystemDeviceObject
);
145 #pragma prefast( push )
146 #pragma prefast( disable:28155, "these are all correct" )
147 #pragma prefast( disable:28169, "these are all correct" )
148 #pragma prefast( disable:28175, "this is a filesystem, touching FastIoDispatch is allowed" )
151 DriverObject
->DriverUnload
= FatUnload
;
154 // Note that because of the way data caching is done, we set neither
155 // the Direct I/O or Buffered I/O bit in DeviceObject->Flags. If
156 // data is not in the cache, or the request is not buffered, we may,
157 // set up for Direct I/O by hand.
161 // Initialize the driver object with this driver's entry points.
164 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = (PDRIVER_DISPATCH
)FatFsdCreate
;
165 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = (PDRIVER_DISPATCH
)FatFsdClose
;
166 DriverObject
->MajorFunction
[IRP_MJ_READ
] = (PDRIVER_DISPATCH
)FatFsdRead
;
167 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = (PDRIVER_DISPATCH
)FatFsdWrite
;
168 DriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] = (PDRIVER_DISPATCH
)FatFsdQueryInformation
;
169 DriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] = (PDRIVER_DISPATCH
)FatFsdSetInformation
;
170 DriverObject
->MajorFunction
[IRP_MJ_QUERY_EA
] = (PDRIVER_DISPATCH
)FatFsdQueryEa
;
171 DriverObject
->MajorFunction
[IRP_MJ_SET_EA
] = (PDRIVER_DISPATCH
)FatFsdSetEa
;
172 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = (PDRIVER_DISPATCH
)FatFsdFlushBuffers
;
173 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = (PDRIVER_DISPATCH
)FatFsdQueryVolumeInformation
;
174 DriverObject
->MajorFunction
[IRP_MJ_SET_VOLUME_INFORMATION
] = (PDRIVER_DISPATCH
)FatFsdSetVolumeInformation
;
175 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = (PDRIVER_DISPATCH
)FatFsdCleanup
;
176 DriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] = (PDRIVER_DISPATCH
)FatFsdDirectoryControl
;
177 DriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] = (PDRIVER_DISPATCH
)FatFsdFileSystemControl
;
178 DriverObject
->MajorFunction
[IRP_MJ_LOCK_CONTROL
] = (PDRIVER_DISPATCH
)FatFsdLockControl
;
179 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = (PDRIVER_DISPATCH
)FatFsdDeviceControl
;
180 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = (PDRIVER_DISPATCH
)FatFsdShutdown
;
181 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = (PDRIVER_DISPATCH
)FatFsdPnp
;
183 DriverObject
->FastIoDispatch
= &FatFastIoDispatch
;
185 RtlZeroMemory(&FatFastIoDispatch
, sizeof(FatFastIoDispatch
));
187 FatFastIoDispatch
.SizeOfFastIoDispatch
= sizeof(FAST_IO_DISPATCH
);
188 FatFastIoDispatch
.FastIoCheckIfPossible
= FatFastIoCheckIfPossible
; // CheckForFastIo
189 FatFastIoDispatch
.FastIoRead
= FsRtlCopyRead
; // Read
190 FatFastIoDispatch
.FastIoWrite
= FsRtlCopyWrite
; // Write
191 FatFastIoDispatch
.FastIoQueryBasicInfo
= FatFastQueryBasicInfo
; // QueryBasicInfo
192 FatFastIoDispatch
.FastIoQueryStandardInfo
= FatFastQueryStdInfo
; // QueryStandardInfo
193 FatFastIoDispatch
.FastIoLock
= FatFastLock
; // Lock
194 FatFastIoDispatch
.FastIoUnlockSingle
= FatFastUnlockSingle
; // UnlockSingle
195 FatFastIoDispatch
.FastIoUnlockAll
= FatFastUnlockAll
; // UnlockAll
196 FatFastIoDispatch
.FastIoUnlockAllByKey
= FatFastUnlockAllByKey
; // UnlockAllByKey
197 FatFastIoDispatch
.FastIoQueryNetworkOpenInfo
= FatFastQueryNetworkOpenInfo
;
198 FatFastIoDispatch
.AcquireForCcFlush
= FatAcquireForCcFlush
;
199 FatFastIoDispatch
.ReleaseForCcFlush
= FatReleaseForCcFlush
;
200 FatFastIoDispatch
.MdlRead
= FsRtlMdlReadDev
;
201 FatFastIoDispatch
.MdlReadComplete
= FsRtlMdlReadCompleteDev
;
202 FatFastIoDispatch
.PrepareMdlWrite
= FsRtlPrepareMdlWriteDev
;
203 FatFastIoDispatch
.MdlWriteComplete
= FsRtlMdlWriteCompleteDev
;
206 #pragma prefast( pop )
210 // Initialize the filter callbacks we use.
213 RtlZeroMemory( &FilterCallbacks
,
214 sizeof(FS_FILTER_CALLBACKS
) );
216 FilterCallbacks
.SizeOfFsFilterCallbacks
= sizeof(FS_FILTER_CALLBACKS
);
217 FilterCallbacks
.PreAcquireForSectionSynchronization
= FatFilterCallbackAcquireForCreateSection
;
219 Status
= FsRtlRegisterFileSystemFilterCallbacks( DriverObject
,
222 if (!NT_SUCCESS( Status
)) {
224 IoDeleteDevice( FatDiskFileSystemDeviceObject
);
225 IoDeleteDevice( FatCdromFileSystemDeviceObject
);
230 // Initialize the global data structures
234 // The FatData record
237 RtlZeroMemory( &FatData
, sizeof(FAT_DATA
));
239 FatData
.NodeTypeCode
= FAT_NTC_DATA_HEADER
;
240 FatData
.NodeByteSize
= sizeof(FAT_DATA
);
242 InitializeListHead(&FatData
.VcbQueue
);
244 FatData
.DriverObject
= DriverObject
;
245 FatData
.DiskFileSystemDeviceObject
= FatDiskFileSystemDeviceObject
;
246 FatData
.CdromFileSystemDeviceObject
= FatCdromFileSystemDeviceObject
;
249 // This list head keeps track of closes yet to be done.
252 InitializeListHead( &FatData
.AsyncCloseList
);
253 InitializeListHead( &FatData
.DelayedCloseList
);
255 FatData
.FatCloseItem
= IoAllocateWorkItem( FatDiskFileSystemDeviceObject
);
257 if (FatData
.FatCloseItem
== NULL
) {
258 IoDeleteDevice (FatDiskFileSystemDeviceObject
);
259 IoDeleteDevice (FatCdromFileSystemDeviceObject
);
260 return STATUS_INSUFFICIENT_RESOURCES
;
264 // Allocate the zero page
268 FatData
.ZeroPage
= ExAllocatePoolWithTag( NonPagedPoolNx
, PAGE_SIZE
, 'ZtaF' );
270 FatData
.ZeroPage
= ExAllocatePoolWithTag( NonPagedPool
, PAGE_SIZE
, 'ZtaF' );
272 if (FatData
.ZeroPage
== NULL
) {
273 IoDeleteDevice (FatDiskFileSystemDeviceObject
);
274 IoDeleteDevice (FatCdromFileSystemDeviceObject
);
275 return STATUS_INSUFFICIENT_RESOURCES
;
277 RtlZeroMemory( FatData
.ZeroPage
, PAGE_SIZE
);
281 // Now initialize our general purpose spinlock (gag) and figure out how
282 // deep and wide we want our delayed lists (along with fooling ourselves
283 // about the lookaside depths).
286 KeInitializeSpinLock( &FatData
.GeneralSpinLock
);
288 switch ( MmQuerySystemSize() ) {
293 FatMaxDelayedCloseCount
= FAT_MAX_DELAYED_CLOSES
;
299 FatMaxDelayedCloseCount
= 4 * FAT_MAX_DELAYED_CLOSES
;
306 FatMaxDelayedCloseCount
= 16 * FAT_MAX_DELAYED_CLOSES
;
312 // Initialize the cache manager callback routines
315 FatData
.CacheManagerCallbacks
.AcquireForLazyWrite
= &FatAcquireFcbForLazyWrite
;
316 FatData
.CacheManagerCallbacks
.ReleaseFromLazyWrite
= &FatReleaseFcbFromLazyWrite
;
317 FatData
.CacheManagerCallbacks
.AcquireForReadAhead
= &FatAcquireFcbForReadAhead
;
318 FatData
.CacheManagerCallbacks
.ReleaseFromReadAhead
= &FatReleaseFcbFromReadAhead
;
320 FatData
.CacheManagerNoOpCallbacks
.AcquireForLazyWrite
= &FatNoOpAcquire
;
321 FatData
.CacheManagerNoOpCallbacks
.ReleaseFromLazyWrite
= &FatNoOpRelease
;
322 FatData
.CacheManagerNoOpCallbacks
.AcquireForReadAhead
= &FatNoOpAcquire
;
323 FatData
.CacheManagerNoOpCallbacks
.ReleaseFromReadAhead
= &FatNoOpRelease
;
326 // Set up global pointer to our process.
329 FatData
.OurProcess
= PsGetCurrentProcess();
332 // Setup the number of processors we support for statistics as the current number
336 #if (NTDDI_VERSION >= NTDDI_VISTA)
337 FatData
.NumberProcessors
= KeQueryActiveProcessorCount( NULL
);
339 FatData
.NumberProcessors
= KeNumberProcessors
;
344 // Read the registry to determine if we are in ChicagoMode.
347 ValueName
.Buffer
= COMPATIBILITY_MODE_VALUE_NAME
;
348 ValueName
.Length
= sizeof(COMPATIBILITY_MODE_VALUE_NAME
) - sizeof(WCHAR
);
349 ValueName
.MaximumLength
= sizeof(COMPATIBILITY_MODE_VALUE_NAME
);
351 Status
= FatGetCompatibilityModeValue( &ValueName
, &Value
);
353 if (NT_SUCCESS(Status
) && FlagOn(Value
, 1)) {
355 FatData
.ChicagoMode
= FALSE
;
359 FatData
.ChicagoMode
= TRUE
;
363 // Read the registry to determine if we are going to generate LFNs
364 // for valid 8.3 names with extended characters.
367 ValueName
.Buffer
= CODE_PAGE_INVARIANCE_VALUE_NAME
;
368 ValueName
.Length
= sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME
) - sizeof(WCHAR
);
369 ValueName
.MaximumLength
= sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME
);
371 Status
= FatGetCompatibilityModeValue( &ValueName
, &Value
);
373 if (NT_SUCCESS(Status
) && FlagOn(Value
, 1)) {
375 FatData
.CodePageInvariant
= FALSE
;
379 FatData
.CodePageInvariant
= TRUE
;
383 // Initialize our global resource and fire up the lookaside lists.
386 ExInitializeResourceLite( &FatData
.Resource
);
388 ExInitializeNPagedLookasideList( &FatIrpContextLookasideList
,
392 POOL_NX_ALLOCATION
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
394 POOL_RAISE_IF_ALLOCATION_FAILURE
,
400 ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList
,
404 POOL_NX_ALLOCATION
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
406 POOL_RAISE_IF_ALLOCATION_FAILURE
,
408 sizeof(NON_PAGED_FCB
),
412 ExInitializeNPagedLookasideList( &FatEResourceLookasideList
,
416 POOL_NX_ALLOCATION
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
418 POOL_RAISE_IF_ALLOCATION_FAILURE
,
424 ExInitializeSListHead( &FatCloseContextSList
);
425 ExInitializeFastMutex( &FatCloseQueueMutex
);
426 KeInitializeEvent( &FatReserveEvent
, SynchronizationEvent
, TRUE
);
429 // Register the file system with the I/O system
432 IoRegisterFileSystem(FatDiskFileSystemDeviceObject
);
433 ObReferenceObject (FatDiskFileSystemDeviceObject
);
434 IoRegisterFileSystem(FatCdromFileSystemDeviceObject
);
435 ObReferenceObject (FatCdromFileSystemDeviceObject
);
438 // Find out if we are running an a FujitsuFMR machine.
441 FatData
.FujitsuFMR
= FatIsFujitsuFMR();
443 #if (NTDDI_VERSION >= NTDDI_WIN8)
446 // Find out global disk accounting state, cache the result
449 FatDiskAccountingEnabled
= PsIsDiskCountersEnabled();
454 // And return to our caller
457 return( STATUS_SUCCESS
);
461 _Function_class_(DRIVER_UNLOAD
)\f
466 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
468 _In_ PDRIVER_OBJECT DriverObject
476 This is the unload routine for the filesystem
480 DriverObject - Pointer to driver object created by the system.
489 UNREFERENCED_PARAMETER( DriverObject
);
492 ExDeleteNPagedLookasideList (&FatEResourceLookasideList
);
493 ExDeleteNPagedLookasideList (&FatNonPagedFcbLookasideList
);
494 ExDeleteNPagedLookasideList (&FatIrpContextLookasideList
);
495 ExDeleteResourceLite( &FatData
.Resource
);
496 IoFreeWorkItem (FatData
.FatCloseItem
);
497 ObDereferenceObject( FatDiskFileSystemDeviceObject
);
498 ObDereferenceObject( FatCdromFileSystemDeviceObject
);
503 // Local Support routine
507 FatGetCompatibilityModeValue (
508 IN PUNICODE_STRING ValueName
,
516 Given a unicode value name this routine will go into the registry
517 location for the Chicago compatibilitymode information and get the
522 ValueName - the unicode name for the registry value located in the registry.
523 Value - a pointer to the ULONG for the result.
529 If STATUS_SUCCESSFUL is returned, the location *Value will be
530 updated with the DWORD value from the registry. If any failing
531 status is returned, this value is untouched.
540 UCHAR Buffer
[KEY_WORK_AREA
];
541 UNICODE_STRING KeyName
;
542 OBJECT_ATTRIBUTES ObjectAttributes
;
543 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
545 KeyName
.Buffer
= COMPATIBILITY_MODE_KEY_NAME
;
546 KeyName
.Length
= sizeof(COMPATIBILITY_MODE_KEY_NAME
) - sizeof(WCHAR
);
547 KeyName
.MaximumLength
= sizeof(COMPATIBILITY_MODE_KEY_NAME
);
549 InitializeObjectAttributes(&ObjectAttributes
,
551 OBJ_CASE_INSENSITIVE
,
555 Status
= ZwOpenKey(&Handle
,
559 if (!NT_SUCCESS(Status
)) {
564 RequestLength
= KEY_WORK_AREA
;
566 KeyValueInformation
= (PKEY_VALUE_FULL_INFORMATION
)Buffer
;
570 Status
= ZwQueryValueKey(Handle
,
572 KeyValueFullInformation
,
577 NT_ASSERT( Status
!= STATUS_BUFFER_OVERFLOW
);
579 if (Status
== STATUS_BUFFER_OVERFLOW
) {
582 // Try to get a buffer big enough.
585 if (KeyValueInformation
!= (PKEY_VALUE_FULL_INFORMATION
)Buffer
) {
587 ExFreePool(KeyValueInformation
);
590 RequestLength
+= 256;
592 KeyValueInformation
= (PKEY_VALUE_FULL_INFORMATION
)
593 ExAllocatePoolWithTag(PagedPool
,
597 if (!KeyValueInformation
) {
600 return STATUS_NO_MEMORY
;
611 if (NT_SUCCESS(Status
)) {
613 if (KeyValueInformation
->DataLength
!= 0) {
618 // Return contents to the caller.
622 ((PUCHAR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
628 // Treat as if no value was found
631 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
635 if (KeyValueInformation
!= (PKEY_VALUE_FULL_INFORMATION
)Buffer
) {
637 ExFreePool(KeyValueInformation
);
644 // Local Support routine
655 This routine tells if is we running on a FujitsuFMR machine.
662 BOOLEAN - TRUE is we are and FALSE otherwise
672 UCHAR Buffer
[KEY_WORK_AREA
];
673 UNICODE_STRING KeyName
;
674 UNICODE_STRING ValueName
;
675 OBJECT_ATTRIBUTES ObjectAttributes
;
676 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
679 // Set default as PC/AT
682 KeyName
.Buffer
= REGISTRY_HARDWARE_DESCRIPTION_W
;
683 KeyName
.Length
= sizeof(REGISTRY_HARDWARE_DESCRIPTION_W
) - sizeof(WCHAR
);
684 KeyName
.MaximumLength
= sizeof(REGISTRY_HARDWARE_DESCRIPTION_W
);
686 InitializeObjectAttributes(&ObjectAttributes
,
688 OBJ_CASE_INSENSITIVE
,
692 Status
= ZwOpenKey(&Handle
,
696 if (!NT_SUCCESS(Status
)) {
701 ValueName
.Buffer
= REGISTRY_MACHINE_IDENTIFIER_W
;
702 ValueName
.Length
= sizeof(REGISTRY_MACHINE_IDENTIFIER_W
) - sizeof(WCHAR
);
703 ValueName
.MaximumLength
= sizeof(REGISTRY_MACHINE_IDENTIFIER_W
);
705 RequestLength
= KEY_WORK_AREA
;
707 KeyValueInformation
= (PKEY_VALUE_FULL_INFORMATION
)Buffer
;
711 Status
= ZwQueryValueKey(Handle
,
713 KeyValueFullInformation
,
718 // NT_ASSERT( Status != STATUS_BUFFER_OVERFLOW );
720 if (Status
== STATUS_BUFFER_OVERFLOW
) {
723 // Try to get a buffer big enough.
726 if (KeyValueInformation
!= (PKEY_VALUE_FULL_INFORMATION
)Buffer
) {
728 ExFreePool(KeyValueInformation
);
731 RequestLength
+= 256;
733 KeyValueInformation
= (PKEY_VALUE_FULL_INFORMATION
)
734 ExAllocatePoolWithTag(PagedPool
, RequestLength
, ' taF');
736 if (!KeyValueInformation
) {
750 if (NT_SUCCESS(Status
) &&
751 (KeyValueInformation
->DataLength
>= sizeof(FUJITSU_FMR_NAME_W
)) &&
752 (RtlCompareMemory((PUCHAR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
,
754 sizeof(FUJITSU_FMR_NAME_W
) - sizeof(WCHAR
)) ==
755 sizeof(FUJITSU_FMR_NAME_W
) - sizeof(WCHAR
))) {
764 if (KeyValueInformation
!= (PKEY_VALUE_FULL_INFORMATION
)Buffer
) {
766 ExFreePool(KeyValueInformation
);