1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
10 * Module: UDF File System Driver (Kernel mode execution only)
13 * This file contains the initialization code for the kernel mode
14 * UDF FSD module. The DriverEntry() routine is called by the I/O
15 * sub-system to initialize the FSD.
17 *************************************************************************/
21 // define the file specific bug-check id
22 #define UDF_BUG_CHECK_ID UDF_FILE_INIT
24 // global variables are declared here
25 UDFData UDFGlobalData
;
29 struct UDF_MEDIA_CLASS_NAMES UDFMediaClassName
[] = {
30 {MediaUnknown
, REG_DEFAULT_UNKNOWN
},
31 {MediaHdd
, REG_DEFAULT_HDD
},
32 {MediaCdr
, REG_DEFAULT_CDR
},
33 {MediaCdrw
, REG_DEFAULT_CDRW
},
34 {MediaCdrom
, REG_DEFAULT_CDROM
},
35 {MediaZip
, REG_DEFAULT_ZIP
},
36 {MediaFloppy
, REG_DEFAULT_FLOPPY
},
37 {MediaDvdr
, REG_DEFAULT_DVDR
},
38 {MediaDvdrw
, REG_DEFAULT_DVDRW
}
41 ULONG MajorVersion = 0;
42 ULONG MinorVersion = 0;
43 ULONG BuildNumber = 0;
45 ULONG FsRegistered
= FALSE
;
47 WORK_QUEUE_ITEM RemountWorkQueueItem
;
49 //ptrFsRtlNotifyVolumeEvent FsRtlNotifyVolumeEvent = NULL;
51 HANDLE FsNotification_ThreadId
= (HANDLE
)(-1);
54 UDFCreateFsDeviceObject(
56 PDRIVER_OBJECT DriverObject
,
57 DEVICE_TYPE DeviceType
,
58 PDEVICE_OBJECT
*DeviceObject
);
62 PUNICODE_STRING unicodeCdRomDeviceName
);
68 /*************************************************************************
70 * Function: DriverEntry()
73 * This routine is the standard entry point for all kernel mode drivers.
74 * The routine is invoked at IRQL PASSIVE_LEVEL in the context of a
75 * system worker thread.
76 * All FSD specific data structures etc. are initialized here.
78 * Expected Interrupt Level (for execution) :
82 * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
84 *************************************************************************/
88 PDRIVER_OBJECT DriverObject
, // created by the I/O sub-system
89 PUNICODE_STRING RegistryPath
// path to the registry key
92 NTSTATUS RC
= STATUS_SUCCESS
;
93 UNICODE_STRING DriverDeviceName
;
94 UNICODE_STRING unicodeDeviceName
;
95 // BOOLEAN RegisteredShutdown = FALSE;
96 BOOLEAN InternalMMInitialized
= FALSE
;
97 // BOOLEAN DLDetectInitialized = FALSE;
99 // CCHAR deviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
100 // ANSI_STRING deviceName;
101 // UNICODE_STRING unicodeCdRomDeviceName;
102 PUDFFS_DEV_EXTENSION FSDevExt
;
106 // UDFPrint(("UDF: Entered " VER_STR_PRODUCT_NAME " UDF DriverEntry \n"));
107 // UDFPrint((KD_PREFIX "Build " VER_STR_PRODUCT "\n"));
113 CrNtInit(DriverObject, RegistryPath);
115 //PsGetVersion(&MajorVersion, &MinorVersion, &BuildNumber, NULL);
116 UDFPrint(("UDF: OS Version Major: %x, Minor: %x, Build number: %d\n",
117 MajorVersion, MinorVersion, BuildNumber));
120 UDFPrint(("UDF Init: OS should be ReactOS\n"));
123 // initialize the global data structure
124 RtlZeroMemory(&UDFGlobalData
, sizeof(UDFGlobalData
));
126 // initialize some required fields
127 UDFGlobalData
.NodeIdentifier
.NodeType
= UDF_NODE_TYPE_GLOBAL_DATA
;
128 UDFGlobalData
.NodeIdentifier
.NodeSize
= sizeof(UDFGlobalData
);
130 // initialize the global data resource and remember the fact that
131 // the resource has been initialized
132 RC
= UDFInitializeResourceLite(&(UDFGlobalData
.GlobalDataResource
));
133 ASSERT(NT_SUCCESS(RC
));
134 UDFSetFlag(UDFGlobalData
.UDFFlags
, UDF_DATA_FLAGS_RESOURCE_INITIALIZED
);
136 RC
= UDFInitializeResourceLite(&(UDFGlobalData
.DelayedCloseResource
));
137 ASSERT(NT_SUCCESS(RC
));
138 // UDFSetFlag(UDFGlobalData.UDFFlags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED);
140 // keep a ptr to the driver object sent to us by the I/O Mgr
141 UDFGlobalData
.DriverObject
= DriverObject
;
143 //SeEnableAccessToExports();
145 // initialize the mounted logical volume list head
146 InitializeListHead(&(UDFGlobalData
.VCBQueue
));
148 UDFPrint(("UDF: Init memory manager\n"));
149 // Initialize internal memory management
151 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
153 InternalMMInitialized
= TRUE
;
156 // Initialize Deadlock Detector
158 DLDetectInitialized
= TRUE
;
160 // before we proceed with any more initialization, read in
161 // user supplied configurable values ...
164 RtlCopyMemory(&(UDFGlobalData
.SavedRegPath
), RegistryPath
, sizeof(UNICODE_STRING
));
166 UDFGlobalData
.SavedRegPath
.Buffer
= (PWSTR
)MyAllocatePool__(NonPagedPool
, RegistryPath
->Length
+ 2);
167 if(!UDFGlobalData
.SavedRegPath
.Buffer
) try_return (RC
= STATUS_INSUFFICIENT_RESOURCES
);
168 RtlCopyMemory(UDFGlobalData
.SavedRegPath
.Buffer
, RegistryPath
->Buffer
, RegistryPath
->Length
+ 2);
170 RegTGetKeyHandle(NULL
, UDFGlobalData
.SavedRegPath
.Buffer
, &hUdfRootKey
);
172 RtlInitUnicodeString(&UDFGlobalData
.UnicodeStrRoot
, L
"\\");
173 RtlInitUnicodeString(&UDFGlobalData
.UnicodeStrSDir
, L
":");
174 RtlInitUnicodeString(&UDFGlobalData
.AclName
, UDF_SN_NT_ACL
);
176 UDFPrint(("UDF: Init delayed close queues\n"));
177 #ifdef UDF_DELAYED_CLOSE
178 InitializeListHead( &UDFGlobalData
.DelayedCloseQueue
);
179 InitializeListHead( &UDFGlobalData
.DirDelayedCloseQueue
);
181 ExInitializeWorkItem( &UDFGlobalData
.CloseItem
,
185 UDFGlobalData
.DelayedCloseCount
= 0;
186 UDFGlobalData
.DirDelayedCloseCount
= 0;
187 #endif //UDF_DELAYED_CLOSE
189 // we should have the registry data (if any), allocate zone memory ...
190 // This is an example of when FSD implementations __try to pre-allocate
191 // some fixed amount of memory to avoid internal fragmentation and/or waiting
192 // later during run-time ...
194 UDFGlobalData
.DefaultZoneSizeInNumStructs
=10;
196 UDFPrint(("UDF: Init zones\n"));
197 if (!NT_SUCCESS(RC
= UDFInitializeZones()))
200 UDFPrint(("UDF: Init pointers\n"));
201 // initialize the IRP major function table, and the fast I/O table
202 UDFInitializeFunctionPointers(DriverObject
);
204 UDFGlobalData
.CPU_Count
= KeNumberProcessors
;
206 // create a device object representing the driver itself
207 // so that requests can be targeted to the driver ...
208 // e.g. for a disk-based FSD, "mount" requests will be sent to
209 // this device object by the I/O Manager.
210 // For a redirector/server, you may have applications
211 // send "special" IOCTL's using this device object ...
213 RtlInitUnicodeString(&DriverDeviceName
, UDF_FS_NAME
);
215 UDFPrint(("UDF: Create Driver dev obj\n"));
216 if (!NT_SUCCESS(RC
= IoCreateDevice(
217 DriverObject
, // our driver object
218 sizeof(UDFFS_DEV_EXTENSION
), // don't need an extension for this object
219 &DriverDeviceName
, // name - can be used to "open" the driver
220 // see the book for alternate choices
221 FILE_DEVICE_CD_ROM_FILE_SYSTEM
,
222 0, // no special characteristics
223 // do not want this as an exclusive device, though you might
225 &(UDFGlobalData
.UDFDeviceObject
)))) {
226 // failed to create a device object, leave ...
230 FSDevExt
= (PUDFFS_DEV_EXTENSION
)((UDFGlobalData
.UDFDeviceObject
)->DeviceExtension
);
231 // Zero it out (typically this has already been done by the I/O
232 // Manager but it does not hurt to do it again)!
233 RtlZeroMemory(FSDevExt
, sizeof(UDFFS_DEV_EXTENSION
));
235 // Initialize the signature fields
236 FSDevExt
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_UDFFS_DRVOBJ
;
237 FSDevExt
->NodeIdentifier
.NodeSize
= sizeof(UDFFS_DEV_EXTENSION
);
239 RtlInitUnicodeString(&unicodeDeviceName
, UDF_DOS_FS_NAME
);
240 IoCreateSymbolicLink(&unicodeDeviceName
, &DriverDeviceName
);
242 UDFPrint(("UDF: Create CD dev obj\n"));
243 if (!NT_SUCCESS(RC
= UDFCreateFsDeviceObject(UDF_FS_NAME_CD
,
245 FILE_DEVICE_CD_ROM_FILE_SYSTEM
,
246 &(UDFGlobalData
.UDFDeviceObject_CD
)))) {
247 // failed to create a device object, leave ...
250 #ifdef UDF_HDD_SUPPORT
251 UDFPrint(("UDF: Create HDD dev obj\n"));
252 if (!NT_SUCCESS(RC
= UDFCreateFsDeviceObject(UDF_FS_NAME_HDD
,
254 FILE_DEVICE_DISK_FILE_SYSTEM
,
255 &(UDFGlobalData
.UDFDeviceObject_HDD
)))) {
256 // failed to create a device object, leave ...
259 #endif //UDF_HDD_SUPPORT
261 /* RtlInitUnicodeString(&DriverDeviceName, UDF_FS_NAME_OTHER);
263 if (!NT_SUCCESS(RC = IoCreateDevice(
264 DriverObject, // our driver object
265 0, // don't need an extension for this object
266 &DriverDeviceName, // name - can be used to "open" the driver
267 // see the book for alternate choices
268 FILE_DEVICE_FILE_SYSTEM,
269 0, // no special characteristics
270 // do not want this as an exclusive device, though you might
272 &(UDFGlobalData.UDFDeviceObject_OTHER)))) {
273 // failed to create a device object, leave ...
276 // register the driver with the I/O Manager, pretend as if this is
277 // a physical disk based FSD (or in order words, this FSD manages
278 // logical volumes residing on physical disk drives)
279 IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_OTHER);
281 RtlInitUnicodeString(&DriverDeviceName, UDF_FS_NAME_TAPE);
283 if (!NT_SUCCESS(RC = IoCreateDevice(
284 DriverObject, // our driver object
285 0, // don't need an extension for this object
286 &DriverDeviceName, // name - can be used to "open" the driver
287 // see the book for alternate choices
288 FILE_DEVICE_TAPE_FILE_SYSTEM,
289 0, // no special characteristics
290 // do not want this as an exclusive device, though you might
292 &(UDFGlobalData.UDFDeviceObject_TAPE)))) {
293 // failed to create a device object, leave ...
296 // register the driver with the I/O Manager, pretend as if this is
297 // a physical disk based FSD (or in order words, this FSD manages
298 // logical volumes residing on physical disk drives)
299 IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_TAPE);
302 if (UDFGlobalData
.UDFDeviceObject_CD
) {
303 UDFPrint(("UDFCreateFsDeviceObject: IoRegisterFileSystem() for CD\n"));
304 IoRegisterFileSystem(UDFGlobalData
.UDFDeviceObject_CD
);
306 #ifdef UDF_HDD_SUPPORT
307 if (UDFGlobalData
.UDFDeviceObject_HDD
) {
308 UDFPrint(("UDFCreateFsDeviceObject: IoRegisterFileSystem() for HDD\n"));
309 IoRegisterFileSystem(UDFGlobalData
.UDFDeviceObject_HDD
);
311 #endif // UDF_HDD_SUPPORT
314 UDFPrint(("UDF: IoRegisterFsRegistrationChange()\n"));
315 IoRegisterFsRegistrationChange( DriverObject
, UDFFsNotification
);
317 // delay.QuadPart = -10000000;
318 // KeDelayExecutionThread(KernelMode, FALSE, &delay); //10 microseconds
320 delay
.QuadPart
= -10000000; // 1 sec
321 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
325 /*ExInitializeWorkItem(&RemountWorkQueueItem, UDFRemountAll, NULL);
326 UDFPrint(("UDFDriverEntry: create remount thread\n"));
327 ExQueueWorkItem(&RemountWorkQueueItem, DelayedWorkQueue);*/
329 for(CdRomNumber
= 0;true;CdRomNumber
++) {
330 sprintf(deviceNameBuffer
, "\\Device\\CdRom%d", CdRomNumber
);
331 UDFPrint(( "UDF: DriverEntry : dismount %s\n", deviceNameBuffer
));
332 RtlInitString(&deviceName
, deviceNameBuffer
);
333 RC
= RtlAnsiStringToUnicodeString(&unicodeCdRomDeviceName
, &deviceName
, TRUE
);
335 if (!NT_SUCCESS(RC
)) {
336 RtlFreeUnicodeString(&unicodeCdRomDeviceName
);
340 RC
= UDFDismountDevice(&unicodeCdRomDeviceName
);
341 RtlFreeUnicodeString(&unicodeCdRomDeviceName
);
343 if (!NT_SUCCESS(RC
)) break;
347 PVOID ModuleBase
= NULL
;
349 // get NTOSKRNL.EXE exports
350 ModuleBase
= CrNtGetModuleBase("NTOSKRNL.EXE");
352 FsRtlNotifyVolumeEvent
= (ptrFsRtlNotifyVolumeEvent
)CrNtGetProcAddress(ModuleBase
, "FsRtlNotifyVolumeEvent");
359 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
360 // we encountered an exception somewhere, eat it up
361 UDFPrint(("UDF: exception\n"));
362 RC
= _SEH2_GetExceptionCode();
365 InternalMMInitialized
= FALSE
;
369 // start unwinding if we were unsuccessful
370 if (!NT_SUCCESS(RC
)) {
371 UDFPrint(("UDF: failed with status %x\n", RC
));
372 // Now, delete any device objects, etc. we may have created
373 /* if (UDFGlobalData.UDFDeviceObject) {
374 IoDeleteDevice(UDFGlobalData.UDFDeviceObject);
375 UDFGlobalData.UDFDeviceObject = NULL;
378 if (DLDetectInitialized
) DLDFree();
380 if (InternalMMInitialized
) {
383 if (UDFGlobalData
.UDFDeviceObject_CD
) {
384 IoDeleteDevice(UDFGlobalData
.UDFDeviceObject_CD
);
385 UDFGlobalData
.UDFDeviceObject_CD
= NULL
;
387 #ifdef UDF_HDD_SUPPORT
389 if (UDFGlobalData
.UDFDeviceObject_HDD
) {
390 IoDeleteDevice(UDFGlobalData
.UDFDeviceObject_HDD
);
391 UDFGlobalData
.UDFDeviceObject_HDD
= NULL
;
393 #endif // UDF_HDD_SUPPORT
396 if (UDFGlobalData.UDFDeviceObject_OTHER) {
397 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_CD);
398 UDFGlobalData.UDFDeviceObject_CD = NULL;
401 if (UDFGlobalData.UDFDeviceObject_TAPE) {
402 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_CD);
403 UDFGlobalData.UDFDeviceObject_CD = NULL;
406 // free up any memory we might have reserved for zones/lookaside
408 if (UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_ZONES_INITIALIZED
) {
412 // delete the resource we may have initialized
413 if (UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_RESOURCE_INITIALIZED
) {
414 // un-initialize this resource
415 UDFDeleteResource(&(UDFGlobalData
.GlobalDataResource
));
416 UDFClearFlag(UDFGlobalData
.UDFFlags
, UDF_DATA_FLAGS_RESOURCE_INITIALIZED
);
423 } // end DriverEntry()
427 /*************************************************************************
429 * Function: UDFInitializeFunctionPointers()
432 * Initialize the IRP... function pointer array in the driver object
433 * structure. Also initialize the fast-io function ptr array ...
435 * Expected Interrupt Level (for execution) :
441 *************************************************************************/
444 UDFInitializeFunctionPointers(
445 PDRIVER_OBJECT DriverObject
// created by the I/O sub-system
448 PFAST_IO_DISPATCH PtrFastIoDispatch
= NULL
;
450 // initialize the function pointers for the IRP major
451 // functions that this FSD is prepared to handle ...
452 // NT Version 4.0 has 28 possible functions that a
453 // kernel mode driver can handle.
454 // NT Version 3.51 and before has only 22 such functions,
455 // of which 18 are typically interesting to most FSD's.
457 // The only interesting new functions that a FSD might
458 // want to respond to beginning with Version 4.0 are the
459 // IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests.
461 // The code below does not handle quota manipulation, neither
462 // does the NT Version 4.0 operating system (or I/O Manager).
463 // However, you should be on the lookout for any such new
464 // functionality that the FSD might have to implement in
467 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = UDFCreate
;
468 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = UDFClose
;
469 DriverObject
->MajorFunction
[IRP_MJ_READ
] = UDFRead
;
470 #ifndef UDF_READ_ONLY_BUILD
471 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = UDFWrite
;
472 #endif //UDF_READ_ONLY_BUILD
474 DriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] = UDFFileInfo
;
475 #ifndef UDF_READ_ONLY_BUILD
476 DriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] = UDFFileInfo
;
477 #endif //UDF_READ_ONLY_BUILD
479 #ifndef UDF_READ_ONLY_BUILD
480 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = UDFFlush
;
481 #endif //UDF_READ_ONLY_BUILD
482 // To implement support for querying and modifying volume attributes
483 // (volume information query/set operations), enable initialization
484 // of the following two function pointers and then implement the supporting
486 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] = UDFQueryVolInfo
;
487 #ifndef UDF_READ_ONLY_BUILD
488 DriverObject
->MajorFunction
[IRP_MJ_SET_VOLUME_INFORMATION
] = UDFSetVolInfo
;
489 #endif //UDF_READ_ONLY_BUILD
490 DriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] = UDFDirControl
;
491 // To implement support for file system IOCTL calls, enable initialization
492 // of the following function pointer and implement appropriate support.
493 DriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] = UDFFSControl
;
494 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = UDFDeviceControl
;
495 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = UDFShutdown
;
496 // For byte-range lock support, enable initialization of the following
497 // function pointer and implement appropriate support.
498 DriverObject
->MajorFunction
[IRP_MJ_LOCK_CONTROL
] = UDFLockControl
;
499 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = UDFCleanup
;
500 #ifdef UDF_HANDLE_EAS
501 DriverObject
->MajorFunction
[IRP_MJ_QUERY_EA
] = UDFQuerySetEA
;
502 #ifndef UDF_READ_ONLY_BUILD
503 DriverObject
->MajorFunction
[IRP_MJ_SET_EA
] = UDFQuerySetEA
;
504 #endif //UDF_READ_ONLY_BUILD
505 #endif //UDF_HANDLE_EAS
506 // If the FSD supports security attributes, we should provide appropriate
507 // dispatch entry points and initialize the function pointers as given below.
509 #ifdef UDF_ENABLE_SECURITY
510 DriverObject
->MajorFunction
[IRP_MJ_QUERY_SECURITY
] = UDFGetSecurity
;
511 #ifndef UDF_READ_ONLY_BUILD
512 DriverObject
->MajorFunction
[IRP_MJ_SET_SECURITY
] = UDFSetSecurity
;
513 #endif //UDF_READ_ONLY_BUILD
514 #endif //UDF_ENABLE_SECURITY
516 // if(MajorVersion >= 0x05) {
518 // DriverObject->MajorFunction[IRP_MJ_PNP] = UDFPnp;
521 // Now, it is time to initialize the fast-io stuff ...
522 PtrFastIoDispatch
= DriverObject
->FastIoDispatch
= &(UDFGlobalData
.UDFFastIoDispatch
);
524 // initialize the global fast-io structure
525 // NOTE: The fast-io structure has undergone a substantial revision
526 // in Windows NT Version 4.0. The structure has been extensively expanded.
527 // Therefore, if the driver needs to work on both V3.51 and V4.0+,
528 // we will have to be able to distinguish between the two versions at compile time.
530 RtlZeroMemory(PtrFastIoDispatch
, sizeof(FAST_IO_DISPATCH
));
532 PtrFastIoDispatch
->SizeOfFastIoDispatch
= sizeof(FAST_IO_DISPATCH
);
533 PtrFastIoDispatch
->FastIoCheckIfPossible
= UDFFastIoCheckIfPossible
;
534 PtrFastIoDispatch
->FastIoRead
= FsRtlCopyRead
;
535 #ifndef UDF_READ_ONLY_BUILD
536 PtrFastIoDispatch
->FastIoWrite
= UDFFastIoCopyWrite
/*FsRtlCopyWrite*/;
537 #endif //UDF_READ_ONLY_BUILD
538 PtrFastIoDispatch
->FastIoQueryBasicInfo
= UDFFastIoQueryBasicInfo
;
539 PtrFastIoDispatch
->FastIoQueryStandardInfo
= UDFFastIoQueryStdInfo
;
540 PtrFastIoDispatch
->FastIoLock
= UDFFastLock
; // Lock
541 PtrFastIoDispatch
->FastIoUnlockSingle
= UDFFastUnlockSingle
; // UnlockSingle
542 PtrFastIoDispatch
->FastIoUnlockAll
= UDFFastUnlockAll
; // UnlockAll
543 PtrFastIoDispatch
->FastIoUnlockAllByKey
= (unsigned char (__stdcall
*)(struct _FILE_OBJECT
*,
544 PVOID
,unsigned long,struct _IO_STATUS_BLOCK
*,struct _DEVICE_OBJECT
*))UDFFastUnlockAllByKey
; // UnlockAllByKey
546 PtrFastIoDispatch
->AcquireFileForNtCreateSection
= UDFFastIoAcqCreateSec
;
547 PtrFastIoDispatch
->ReleaseFileForNtCreateSection
= UDFFastIoRelCreateSec
;
549 // PtrFastIoDispatch->FastIoDeviceControl = UDFFastIoDeviceControl;
551 // the remaining are only valid under NT Version 4.0 and later
552 #if(_WIN32_WINNT >= 0x0400)
554 PtrFastIoDispatch
->FastIoQueryNetworkOpenInfo
= UDFFastIoQueryNetInfo
;
556 PtrFastIoDispatch
->AcquireForModWrite
= UDFFastIoAcqModWrite
;
557 PtrFastIoDispatch
->ReleaseForModWrite
= UDFFastIoRelModWrite
;
558 PtrFastIoDispatch
->AcquireForCcFlush
= UDFFastIoAcqCcFlush
;
559 PtrFastIoDispatch
->ReleaseForCcFlush
= UDFFastIoRelCcFlush
;
561 /* // MDL functionality
563 PtrFastIoDispatch->MdlRead = UDFFastIoMdlRead;
564 PtrFastIoDispatch->MdlReadComplete = UDFFastIoMdlReadComplete;
565 PtrFastIoDispatch->PrepareMdlWrite = UDFFastIoPrepareMdlWrite;
566 PtrFastIoDispatch->MdlWriteComplete = UDFFastIoMdlWriteComplete;*/
568 // this FSD does not support compressed read/write functionality,
569 // NTFS does, and if we design a FSD that can provide such functionality,
570 // we should consider initializing the fast io entry points for reading
571 // and/or writing compressed data ...
572 #endif // (_WIN32_WINNT >= 0x0400)
574 // last but not least, initialize the Cache Manager callback functions
575 // which are used in CcInitializeCacheMap()
577 UDFGlobalData
.CacheMgrCallBacks
.AcquireForLazyWrite
= UDFAcqLazyWrite
;
578 UDFGlobalData
.CacheMgrCallBacks
.ReleaseFromLazyWrite
= UDFRelLazyWrite
;
579 UDFGlobalData
.CacheMgrCallBacks
.AcquireForReadAhead
= UDFAcqReadAhead
;
580 UDFGlobalData
.CacheMgrCallBacks
.ReleaseFromReadAhead
= UDFRelReadAhead
;
582 DriverObject
->DriverUnload
= UDFDriverUnload
;
585 } // end UDFInitializeFunctionPointers()
588 UDFCreateFsDeviceObject(
590 PDRIVER_OBJECT DriverObject
,
591 DEVICE_TYPE DeviceType
,
592 PDEVICE_OBJECT
*DeviceObject
595 NTSTATUS RC
= STATUS_SUCCESS
;
596 UNICODE_STRING DriverDeviceName
;
597 PUDFFS_DEV_EXTENSION FSDevExt
;
598 RtlInitUnicodeString(&DriverDeviceName
, FsDeviceName
);
599 *DeviceObject
= NULL
;
601 UDFPrint(("UDFCreateFsDeviceObject: create dev\n"));
603 if (!NT_SUCCESS(RC
= IoCreateDevice(
604 DriverObject
, // our driver object
605 sizeof(UDFFS_DEV_EXTENSION
), // don't need an extension for this object
606 &DriverDeviceName
, // name - can be used to "open" the driver
607 // see the book for alternate choices
609 0, // no special characteristics
610 // do not want this as an exclusive device, though you might
613 // failed to create a device object, leave ...
616 FSDevExt
= (PUDFFS_DEV_EXTENSION
)((*DeviceObject
)->DeviceExtension
);
617 // Zero it out (typically this has already been done by the I/O
618 // Manager but it does not hurt to do it again)!
619 RtlZeroMemory(FSDevExt
, sizeof(UDFFS_DEV_EXTENSION
));
621 // Initialize the signature fields
622 FSDevExt
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_UDFFS_DEVOBJ
;
623 FSDevExt
->NodeIdentifier
.NodeSize
= sizeof(UDFFS_DEV_EXTENSION
);
624 // register the driver with the I/O Manager, pretend as if this is
625 // a physical disk based FSD (or in order words, this FSD manages
626 // logical volumes residing on physical disk drives)
627 /* UDFPrint(("UDFCreateFsDeviceObject: IoRegisterFileSystem()\n"));
628 IoRegisterFileSystem(*DeviceObject);*/
630 } // end UDFCreateFsDeviceObject()
635 PUNICODE_STRING unicodeCdRomDeviceName
639 IO_STATUS_BLOCK IoStatus
;
640 HANDLE NtFileHandle
= (HANDLE
)-1;
641 OBJECT_ATTRIBUTES ObjectAttributes
;
642 NOTIFY_MEDIA_CHANGE_USER_IN buffer
= { 0 };
643 PFILE_FS_ATTRIBUTE_INFORMATION Buffer
;
647 Buffer
= (PFILE_FS_ATTRIBUTE_INFORMATION
)MyAllocatePool__(NonPagedPool
,sizeof(FILE_FS_ATTRIBUTE_INFORMATION
)+2*sizeof(UDF_FS_TITLE_DVDRAM
));
648 if (!Buffer
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
650 InitializeObjectAttributes ( &ObjectAttributes
,
651 unicodeCdRomDeviceName
,
652 OBJ_CASE_INSENSITIVE
,
656 UDFPrint(("\n*** UDFDismountDevice: Create\n"));
657 RC
= ZwCreateFile( &NtFileHandle
,
662 FILE_ATTRIBUTE_NORMAL
,
665 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
670 if (!NT_SUCCESS(RC
)) try_return(RC
);
672 UDFPrint(("\n*** UDFDismountDevice: QueryVolInfo\n"));
673 RC
= ZwQueryVolumeInformationFile( NtFileHandle
,
676 sizeof(FILE_FS_ATTRIBUTE_INFORMATION
)+2*sizeof(UDF_FS_TITLE_DVDRAM
),
677 FileFsAttributeInformation
);
679 #define UDF_CHECK_FS_NAME(name) \
680 (Buffer->FileSystemNameLength+sizeof(WCHAR) == sizeof(name) && \
681 DbgCompareMemory(&Buffer->FileSystemName[0],name , sizeof(name)) == sizeof(name))
683 if (NT_SUCCESS(RC
) &&
684 (UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_CDR
) ||
685 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_CDRW
) ||
686 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_DVDR
) ||
687 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_DVDRW
) ||
688 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_DVDpR
) ||
689 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_DVDpRW
) ||
690 UDF_CHECK_FS_NAME((PVOID
)UDF_FS_TITLE_DVDRAM
) )) try_return(STATUS_SUCCESS
);
692 UDFPrint(("\n*** UDFDismountDevice: LockVolume\n"));
693 RC
= ZwFsControlFile(NtFileHandle
,
704 if (!NT_SUCCESS(RC
)) try_return(RC
);
706 UDFPrint(("\n*** UDFDismountDevice: DismountVolume\n"));
707 RC
= ZwFsControlFile(NtFileHandle
,
712 FSCTL_DISMOUNT_VOLUME
,
718 if (!NT_SUCCESS(RC
)) try_return(RC
);
720 UDFPrint(("\n*** UDFDismountDevice: NotifyMediaChange\n"));
721 RC
= ZwDeviceIoControlFile(NtFileHandle
,
726 IOCTL_CDRW_NOTIFY_MEDIA_CHANGE
,
732 if (!NT_SUCCESS(RC
)) try_return(RC
);
735 UDFPrint(("\n*** UDFDismountDevice: UnlockVolume\n"));
736 RC
= ZwFsControlFile(NtFileHandle
,
747 UDFPrint(("\n*** UDFDismountDevice: Close\n"));
748 ZwClose( NtFileHandle
);
750 NtFileHandle
= (HANDLE
)-1;
752 UDFPrint(("\n*** UDFDismountDevice: Create 2\n"));
753 RC
= ZwCreateFile( &NtFileHandle
,
758 FILE_ATTRIBUTE_NORMAL
,
761 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
768 if (Buffer
) MyFreePool__(Buffer
);
769 if (NtFileHandle
!= (HANDLE
)-1) ZwClose( NtFileHandle
);
772 UDFPrint(("\n*** UDFDismountDevice: RC=%x\n",RC
));
780 IN PDEVICE_OBJECT DeviceObject
,
788 This routine is invoked whenever a file system has either registered or
789 unregistered itself as an active file system.
791 For the former case, this routine creates a device object and attaches it
792 to the specified file system's device object. This allows this driver
793 to filter all requests to that file system.
795 For the latter case, this file system's device object is located,
796 detached, and deleted. This removes this file system as a filter for
797 the specified file system.
801 DeviceObject - Pointer to the file system's device object.
803 FsActive - bolean indicating whether the file system has registered
804 (TRUE) or unregistered (FALSE) itself as an active file system.
813 // Begin by determine whether or not the file system is a cdrom-based file
814 // system. If not, then this driver is not concerned with it.
816 DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
) {
820 // Begin by determining whether this file system is registering or
821 // unregistering as an active file system.
823 && UDFGlobalData
.UDFDeviceObject_CD
!= DeviceObject
824 #ifdef UDF_HDD_SUPPORT
825 && UDFGlobalData
.UDFDeviceObject_HDD
!= DeviceObject
826 #endif // UDF_HDD_SUPPORT
828 UDFPrint(("\n*** UDFFSNotification \n\n"));
830 // Acquire GlobalDataResource
831 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
833 if(FsNotification_ThreadId
!= PsGetCurrentThreadId()) {
835 FsNotification_ThreadId
= PsGetCurrentThreadId();
837 IoUnregisterFileSystem(UDFGlobalData
.UDFDeviceObject_CD
);
838 IoRegisterFileSystem(UDFGlobalData
.UDFDeviceObject_CD
);
840 #ifdef UDF_HDD_SUPPORT
841 IoUnregisterFileSystem(UDFGlobalData
.UDFDeviceObject_HDD
);
842 IoRegisterFileSystem(UDFGlobalData
.UDFDeviceObject_HDD
);
843 #endif // UDF_HDD_SUPPORT
845 FsNotification_ThreadId
= (HANDLE
)(-1);
848 UDFPrint(("\n*** recursive UDFFSNotification call,\n can't become top-level UDF FSD \n\n"));
851 // Release the global resource.
852 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
862 NTSTATUS RC = STATUS_SUCCESS;
864 CCHAR deviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
865 ANSI_STRING deviceName;
866 UNICODE_STRING unicodeCdRomDeviceName;
870 /* delay.QuadPart = -80*10000000;
871 KeDelayExecutionThread(KernelMode, FALSE, &delay); //10 seconds*/
873 /* for(CdRomNumber = 0;true;CdRomNumber++) {
874 sprintf(deviceNameBuffer, "\\Device\\CdRom%d", CdRomNumber);
875 UDFPrint(( "UDF: UDFRemountAll : dismount %s\n", deviceNameBuffer));
876 RtlInitString(&deviceName, deviceNameBuffer);
877 RC = RtlAnsiStringToUnicodeString(&unicodeCdRomDeviceName, &deviceName, TRUE);
879 if (!NT_SUCCESS(RC)) {
880 RtlFreeUnicodeString(&unicodeCdRomDeviceName);
884 RC = UDFDismountDevice(&unicodeCdRomDeviceName);
885 RtlFreeUnicodeString(&unicodeCdRomDeviceName);
887 if (!NT_SUCCESS(RC)) break;