1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
7 *
8 * File: UDFinit.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
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.
16 *
17 *************************************************************************/
18 
19 #include            "udffs.h"
20 
21 // define the file specific bug-check id
22 #define         UDF_BUG_CHECK_ID                UDF_FILE_INIT
23 
24 // global variables are declared here
25 UDFData                 UDFGlobalData;
26 
27 #define KD_PREFIX
28 
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}
39 };
40 /*
41 ULONG  MajorVersion = 0;
42 ULONG  MinorVersion = 0;
43 ULONG  BuildNumber  = 0;
44 */
45 ULONG  FsRegistered = FALSE;
46 
47 WORK_QUEUE_ITEM    RemountWorkQueueItem;
48 
49 //ptrFsRtlNotifyVolumeEvent FsRtlNotifyVolumeEvent = NULL;
50 
51 HANDLE  FsNotification_ThreadId = (HANDLE)(-1);
52 
53 NTSTATUS
54 UDFCreateFsDeviceObject(
55     PCWSTR          FsDeviceName,
56     PDRIVER_OBJECT  DriverObject,
57     DEVICE_TYPE     DeviceType,
58     PDEVICE_OBJECT  *DeviceObject);
59 
60 NTSTATUS
61 UDFDismountDevice(
62     PUNICODE_STRING unicodeCdRomDeviceName);
63 
64 VOID
65 UDFRemountAll(
66     IN PVOID Context);
67 
68 /*************************************************************************
69 *
70 * Function: DriverEntry()
71 *
72 * Description:
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.
77 *
78 * Expected Interrupt Level (for execution) :
79 *
80 *  IRQL_PASSIVE_LEVEL
81 *
82 * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded).
83 *
84 *************************************************************************/
85 NTSTATUS
86 NTAPI
87 DriverEntry(
88     PDRIVER_OBJECT  DriverObject,       // created by the I/O sub-system
89     PUNICODE_STRING RegistryPath        // path to the registry key
90     )
91 {
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;
98 //    ULONG           CdRomNumber;
99 //    CCHAR           deviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
100 //    ANSI_STRING     deviceName;
101 //    UNICODE_STRING  unicodeCdRomDeviceName;
102     PUDFFS_DEV_EXTENSION FSDevExt;
103     HKEY            hUdfRootKey;
104     LARGE_INTEGER   delay;
105 
106 //    UDFPrint(("UDF: Entered " VER_STR_PRODUCT_NAME " UDF DriverEntry \n"));
107 //    UDFPrint((KD_PREFIX "Build " VER_STR_PRODUCT "\n"));
108 
109     _SEH2_TRY {
110         _SEH2_TRY {
111 
112 /*
113             CrNtInit(DriverObject, RegistryPath);
114 
115             //PsGetVersion(&MajorVersion, &MinorVersion, &BuildNumber, NULL);
116             UDFPrint(("UDF: OS Version Major: %x, Minor: %x, Build number: %d\n",
117                                 MajorVersion, MinorVersion, BuildNumber));
118 */
119 #ifdef __REACTOS__
120             UDFPrint(("UDF Init: OS should be ReactOS\n"));
121 #endif
122 
123             // initialize the global data structure
124             RtlZeroMemory(&UDFGlobalData, sizeof(UDFGlobalData));
125 
126             // initialize some required fields
127             UDFGlobalData.NodeIdentifier.NodeType = UDF_NODE_TYPE_GLOBAL_DATA;
128             UDFGlobalData.NodeIdentifier.NodeSize = sizeof(UDFGlobalData);
129 
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);
135 
136             RC = UDFInitializeResourceLite(&(UDFGlobalData.DelayedCloseResource));
137             ASSERT(NT_SUCCESS(RC));
138 //            UDFSetFlag(UDFGlobalData.UDFFlags, UDF_DATA_FLAGS_RESOURCE_INITIALIZED);
139 
140             // keep a ptr to the driver object sent to us by the I/O Mgr
141             UDFGlobalData.DriverObject = DriverObject;
142 
143             //SeEnableAccessToExports();
144 
145             // initialize the mounted logical volume list head
146             InitializeListHead(&(UDFGlobalData.VCBQueue));
147 
148             UDFPrint(("UDF: Init memory manager\n"));
149             // Initialize internal memory management
150             if(!MyAllocInit()) {
151                 try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
152             }
153             InternalMMInitialized = TRUE;
154 
155 #ifdef USE_DLD
156             // Initialize Deadlock Detector
157             DLDInit(1280);
158             DLDetectInitialized = TRUE;
159 #endif
160             // before we proceed with any more initialization, read in
161             //  user supplied configurable values ...
162 
163             // Save RegistryPath
164             RtlCopyMemory(&(UDFGlobalData.SavedRegPath), RegistryPath, sizeof(UNICODE_STRING));
165 
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);
169 
170             RegTGetKeyHandle(NULL, UDFGlobalData.SavedRegPath.Buffer, &hUdfRootKey);
171 
172             RtlInitUnicodeString(&UDFGlobalData.UnicodeStrRoot, L"\\");
173             RtlInitUnicodeString(&UDFGlobalData.UnicodeStrSDir, L":");
174             RtlInitUnicodeString(&UDFGlobalData.AclName, UDF_SN_NT_ACL);
175 
176             UDFPrint(("UDF: Init delayed close queues\n"));
177 #ifdef UDF_DELAYED_CLOSE
178             InitializeListHead( &UDFGlobalData.DelayedCloseQueue );
179             InitializeListHead( &UDFGlobalData.DirDelayedCloseQueue );
180 
181             ExInitializeWorkItem( &UDFGlobalData.CloseItem,
182                                   UDFDelayedClose,
183                                   NULL );
184 
185             UDFGlobalData.DelayedCloseCount = 0;
186             UDFGlobalData.DirDelayedCloseCount = 0;
187 #endif //UDF_DELAYED_CLOSE
188 
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 ...
193 
194             UDFGlobalData.DefaultZoneSizeInNumStructs=10;
195 
196             UDFPrint(("UDF: Init zones\n"));
197             if (!NT_SUCCESS(RC = UDFInitializeZones()))
198                 try_return(RC);
199 
200             UDFPrint(("UDF: Init pointers\n"));
201             // initialize the IRP major function table, and the fast I/O table
202             UDFInitializeFunctionPointers(DriverObject);
203 
204             UDFGlobalData.CPU_Count = KeNumberProcessors;
205 
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 ...
212 
213             RtlInitUnicodeString(&DriverDeviceName, UDF_FS_NAME);
214 
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
224                     FALSE,
225                     &(UDFGlobalData.UDFDeviceObject)))) {
226                         // failed to create a device object, leave ...
227                 try_return(RC);
228             }
229 
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));
234 
235             // Initialize the signature fields
236             FSDevExt->NodeIdentifier.NodeType = UDF_NODE_TYPE_UDFFS_DRVOBJ;
237             FSDevExt->NodeIdentifier.NodeSize = sizeof(UDFFS_DEV_EXTENSION);
238 
239             RtlInitUnicodeString(&unicodeDeviceName, UDF_DOS_FS_NAME);
240             IoCreateSymbolicLink(&unicodeDeviceName, &DriverDeviceName);
241 
242             UDFPrint(("UDF: Create CD dev obj\n"));
243             if (!NT_SUCCESS(RC = UDFCreateFsDeviceObject(UDF_FS_NAME_CD,
244                                     DriverObject,
245                                     FILE_DEVICE_CD_ROM_FILE_SYSTEM,
246                                     &(UDFGlobalData.UDFDeviceObject_CD)))) {
247                 // failed to create a device object, leave ...
248                 try_return(RC);
249             }
250 #ifdef UDF_HDD_SUPPORT
251             UDFPrint(("UDF: Create HDD dev obj\n"));
252             if (!NT_SUCCESS(RC = UDFCreateFsDeviceObject(UDF_FS_NAME_HDD,
253                                     DriverObject,
254                                     FILE_DEVICE_DISK_FILE_SYSTEM,
255                                     &(UDFGlobalData.UDFDeviceObject_HDD)))) {
256                 // failed to create a device object, leave ...
257                 try_return(RC);
258             }
259 #endif //UDF_HDD_SUPPORT
260 
261 /*            RtlInitUnicodeString(&DriverDeviceName, UDF_FS_NAME_OTHER);
262 
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
271                     FALSE,
272                     &(UDFGlobalData.UDFDeviceObject_OTHER)))) {
273                         // failed to create a device object, leave ...
274                 try_return(RC);
275             }
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);
280 
281             RtlInitUnicodeString(&DriverDeviceName, UDF_FS_NAME_TAPE);
282 
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
291                     FALSE,
292                     &(UDFGlobalData.UDFDeviceObject_TAPE)))) {
293                         // failed to create a device object, leave ...
294                 try_return(RC);
295             }
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);
300 */
301 
302             if (UDFGlobalData.UDFDeviceObject_CD) {
303                 UDFPrint(("UDFCreateFsDeviceObject: IoRegisterFileSystem() for CD\n"));
304                 IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_CD);
305             }
306 #ifdef UDF_HDD_SUPPORT
307             if (UDFGlobalData.UDFDeviceObject_HDD) {
308                 UDFPrint(("UDFCreateFsDeviceObject: IoRegisterFileSystem() for HDD\n"));
309                 IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_HDD);
310             }
311 #endif // UDF_HDD_SUPPORT
312             FsRegistered = TRUE;
313 
314             UDFPrint(("UDF: IoRegisterFsRegistrationChange()\n"));
315             IoRegisterFsRegistrationChange( DriverObject, UDFFsNotification );
316 
317 //            delay.QuadPart = -10000000;
318 //            KeDelayExecutionThread(KernelMode, FALSE, &delay);        //10 microseconds
319 
320            delay.QuadPart = -10000000; // 1 sec
321            KeDelayExecutionThread(KernelMode, FALSE, &delay);
322 
323 #if 0
324             if(!WinVer_IsNT) {
325                 /*ExInitializeWorkItem(&RemountWorkQueueItem, UDFRemountAll, NULL);
326                 UDFPrint(("UDFDriverEntry: create remount thread\n"));
327                 ExQueueWorkItem(&RemountWorkQueueItem, DelayedWorkQueue);*/
328 
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);
334 
335                     if (!NT_SUCCESS(RC)) {
336                         RtlFreeUnicodeString(&unicodeCdRomDeviceName);
337                         break;
338                     }
339 
340                     RC = UDFDismountDevice(&unicodeCdRomDeviceName);
341                     RtlFreeUnicodeString(&unicodeCdRomDeviceName);
342 
343                     if (!NT_SUCCESS(RC)) break;
344 
345                 }
346 
347                 PVOID ModuleBase = NULL;
348 
349                 // get NTOSKRNL.EXE exports
350                 ModuleBase = CrNtGetModuleBase("NTOSKRNL.EXE");
351                 if(ModuleBase) {
352                     FsRtlNotifyVolumeEvent = (ptrFsRtlNotifyVolumeEvent)CrNtGetProcAddress(ModuleBase, "FsRtlNotifyVolumeEvent");
353                 }
354 
355             }
356 #endif
357             RC = STATUS_SUCCESS;
358 
359         } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
360             // we encountered an exception somewhere, eat it up
361             UDFPrint(("UDF: exception\n"));
362             RC = _SEH2_GetExceptionCode();
363         } _SEH2_END;
364 
365         InternalMMInitialized = FALSE;
366 
367         try_exit:   NOTHING;
368     } _SEH2_FINALLY {
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;
376             }*/
377 #ifdef USE_DLD
378             if (DLDetectInitialized) DLDFree();
379 #endif
380             if (InternalMMInitialized) {
381                 MyAllocRelease();
382             }
383             if (UDFGlobalData.UDFDeviceObject_CD) {
384                 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_CD);
385                 UDFGlobalData.UDFDeviceObject_CD = NULL;
386             }
387 #ifdef UDF_HDD_SUPPORT
388 
389             if (UDFGlobalData.UDFDeviceObject_HDD) {
390                 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_HDD);
391                 UDFGlobalData.UDFDeviceObject_HDD = NULL;
392             }
393 #endif // UDF_HDD_SUPPORT
394 
395 /*
396             if (UDFGlobalData.UDFDeviceObject_OTHER) {
397                 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_CD);
398                 UDFGlobalData.UDFDeviceObject_CD = NULL;
399             }
400 
401             if (UDFGlobalData.UDFDeviceObject_TAPE) {
402                 IoDeleteDevice(UDFGlobalData.UDFDeviceObject_CD);
403                 UDFGlobalData.UDFDeviceObject_CD = NULL;
404             }
405 */
406             // free up any memory we might have reserved for zones/lookaside
407             //  lists
408             if (UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_ZONES_INITIALIZED) {
409                 UDFDestroyZones();
410             }
411 
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);
417             }
418 //        } else {
419         }
420     } _SEH2_END;
421 
422     return(RC);
423 } // end DriverEntry()
424 
425 
426 
427 /*************************************************************************
428 *
429 * Function: UDFInitializeFunctionPointers()
430 *
431 * Description:
432 *   Initialize the IRP... function pointer array in the driver object
433 *   structure. Also initialize the fast-io function ptr array ...
434 *
435 * Expected Interrupt Level (for execution) :
436 *
437 *  IRQL_PASSIVE_LEVEL
438 *
439 * Return Value: None
440 *
441 *************************************************************************/
442 VOID
443 NTAPI
444 UDFInitializeFunctionPointers(
445     PDRIVER_OBJECT      DriverObject       // created by the I/O sub-system
446     )
447 {
448     PFAST_IO_DISPATCH    PtrFastIoDispatch = NULL;
449 
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.
456 
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.
460 
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
465     //  the near future.
466 
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
473 
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
478 
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
485     // functions.
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.
508 
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
515 
516 //    if(MajorVersion >= 0x05) {
517         // w2k and higher
518 //        DriverObject->MajorFunction[IRP_MJ_PNP]           = UDFPnp;
519 //    }
520 
521     // Now, it is time to initialize the fast-io stuff ...
522     PtrFastIoDispatch = DriverObject->FastIoDispatch = &(UDFGlobalData.UDFFastIoDispatch);
523 
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.
529 
530     RtlZeroMemory(PtrFastIoDispatch, sizeof(FAST_IO_DISPATCH));
531 
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
545 
546     PtrFastIoDispatch->AcquireFileForNtCreateSection = UDFFastIoAcqCreateSec;
547     PtrFastIoDispatch->ReleaseFileForNtCreateSection = UDFFastIoRelCreateSec;
548 
549 //    PtrFastIoDispatch->FastIoDeviceControl = UDFFastIoDeviceControl;
550 
551     // the remaining are only valid under NT Version 4.0 and later
552 #if(_WIN32_WINNT >= 0x0400)
553 
554     PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = UDFFastIoQueryNetInfo;
555 
556     PtrFastIoDispatch->AcquireForModWrite       = UDFFastIoAcqModWrite;
557     PtrFastIoDispatch->ReleaseForModWrite       = UDFFastIoRelModWrite;
558     PtrFastIoDispatch->AcquireForCcFlush        = UDFFastIoAcqCcFlush;
559     PtrFastIoDispatch->ReleaseForCcFlush        = UDFFastIoRelCcFlush;
560 
561 /*    // MDL functionality
562 
563     PtrFastIoDispatch->MdlRead                  = UDFFastIoMdlRead;
564     PtrFastIoDispatch->MdlReadComplete          = UDFFastIoMdlReadComplete;
565     PtrFastIoDispatch->PrepareMdlWrite          = UDFFastIoPrepareMdlWrite;
566     PtrFastIoDispatch->MdlWriteComplete         = UDFFastIoMdlWriteComplete;*/
567 
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)
573 
574     // last but not least, initialize the Cache Manager callback functions
575     //  which are used in CcInitializeCacheMap()
576 
577     UDFGlobalData.CacheMgrCallBacks.AcquireForLazyWrite  = UDFAcqLazyWrite;
578     UDFGlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = UDFRelLazyWrite;
579     UDFGlobalData.CacheMgrCallBacks.AcquireForReadAhead  = UDFAcqReadAhead;
580     UDFGlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = UDFRelReadAhead;
581 
582     DriverObject->DriverUnload = UDFDriverUnload;
583 
584     return;
585 } // end UDFInitializeFunctionPointers()
586 
587 NTSTATUS
588 UDFCreateFsDeviceObject(
589     PCWSTR          FsDeviceName,
590     PDRIVER_OBJECT  DriverObject,
591     DEVICE_TYPE     DeviceType,
592     PDEVICE_OBJECT  *DeviceObject
593     )
594 {
595     NTSTATUS RC = STATUS_SUCCESS;
596     UNICODE_STRING  DriverDeviceName;
597     PUDFFS_DEV_EXTENSION FSDevExt;
598     RtlInitUnicodeString(&DriverDeviceName, FsDeviceName);
599     *DeviceObject = NULL;
600 
601     UDFPrint(("UDFCreateFsDeviceObject: create dev\n"));
602 
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
608             DeviceType,
609             0,                  // no special characteristics
610                                 // do not want this as an exclusive device, though you might
611             FALSE,
612             DeviceObject))) {
613                 // failed to create a device object, leave ...
614         return(RC);
615     }
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));
620 
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);*/
629     return(RC);
630 } // end UDFCreateFsDeviceObject()
631 
632 
633 NTSTATUS
634 UDFDismountDevice(
635     PUNICODE_STRING unicodeCdRomDeviceName
636     )
637 {
638     NTSTATUS RC;
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;
644 
645     _SEH2_TRY {
646 
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);
649 
650         InitializeObjectAttributes ( &ObjectAttributes,
651                                      unicodeCdRomDeviceName,
652                                      OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
653                                      NULL,
654                                      NULL );
655 
656         UDFPrint(("\n*** UDFDismountDevice: Create\n"));
657         RC = ZwCreateFile( &NtFileHandle,
658                            GENERIC_READ,
659                            &ObjectAttributes,
660                            &IoStatus,
661                            NULL,
662                            FILE_ATTRIBUTE_NORMAL,
663                            FILE_SHARE_READ,
664                            FILE_OPEN,
665                            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
666                            NULL,
667                            0 );
668 
669 
670         if (!NT_SUCCESS(RC)) try_return(RC);
671 
672         UDFPrint(("\n*** UDFDismountDevice: QueryVolInfo\n"));
673         RC = ZwQueryVolumeInformationFile( NtFileHandle,
674                                            &IoStatus,
675                                            Buffer,
676                                            sizeof(FILE_FS_ATTRIBUTE_INFORMATION)+2*sizeof(UDF_FS_TITLE_DVDRAM),
677                                            FileFsAttributeInformation);
678 
679 #define UDF_CHECK_FS_NAME(name) \
680     (Buffer->FileSystemNameLength+sizeof(WCHAR) == sizeof(name) && \
681             DbgCompareMemory(&Buffer->FileSystemName[0],name  , sizeof(name)) == sizeof(name))
682 
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);
691 
692         UDFPrint(("\n*** UDFDismountDevice: LockVolume\n"));
693         RC = ZwFsControlFile(NtFileHandle,
694                              NULL,
695                              NULL,
696                              NULL,
697                              &IoStatus,
698                              FSCTL_LOCK_VOLUME,
699                              NULL,
700                              NULL,
701                              NULL,
702                              NULL);
703 
704         if (!NT_SUCCESS(RC)) try_return(RC);
705 
706         UDFPrint(("\n*** UDFDismountDevice: DismountVolume\n"));
707         RC = ZwFsControlFile(NtFileHandle,
708                              NULL,
709                              NULL,
710                              NULL,
711                              &IoStatus,
712                              FSCTL_DISMOUNT_VOLUME,
713                              NULL,
714                              NULL,
715                              NULL,
716                              NULL);
717 
718         if (!NT_SUCCESS(RC)) try_return(RC);
719 
720         UDFPrint(("\n*** UDFDismountDevice: NotifyMediaChange\n"));
721         RC = ZwDeviceIoControlFile(NtFileHandle,
722                                    NULL,
723                                    NULL,
724                                    NULL,
725                                    &IoStatus,
726                                    IOCTL_CDRW_NOTIFY_MEDIA_CHANGE,
727                                    &buffer,
728                                    sizeof(buffer),
729                                    &buffer,
730                                    sizeof(buffer));
731 
732         if (!NT_SUCCESS(RC)) try_return(RC);
733 
734 
735         UDFPrint(("\n*** UDFDismountDevice: UnlockVolume\n"));
736         RC = ZwFsControlFile(NtFileHandle,
737                              NULL,
738                              NULL,
739                              NULL,
740                              &IoStatus,
741                              FSCTL_UNLOCK_VOLUME,
742                              NULL,
743                              NULL,
744                              NULL,
745                              NULL);
746 
747         UDFPrint(("\n*** UDFDismountDevice: Close\n"));
748         ZwClose( NtFileHandle );
749 
750         NtFileHandle = (HANDLE)-1;
751 
752         UDFPrint(("\n*** UDFDismountDevice: Create 2\n"));
753         RC = ZwCreateFile( &NtFileHandle,
754                            GENERIC_READ,
755                            &ObjectAttributes,
756                            &IoStatus,
757                            NULL,
758                            FILE_ATTRIBUTE_NORMAL,
759                            FILE_SHARE_READ,
760                            FILE_OPEN,
761                            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
762                            NULL,
763                            0 );
764 
765 try_exit: NOTHING;
766 
767     } _SEH2_FINALLY {
768         if (Buffer) MyFreePool__(Buffer);
769         if (NtFileHandle != (HANDLE)-1) ZwClose( NtFileHandle );
770     } _SEH2_END;
771 
772     UDFPrint(("\n*** UDFDismountDevice: RC=%x\n",RC));
773     return RC;
774 }
775 
776 
777 VOID
778 NTAPI
779 UDFFsNotification(
780     IN PDEVICE_OBJECT DeviceObject,
781     IN BOOLEAN FsActive
782     )
783 
784 /*
785 
786 Routine Description:
787 
788     This routine is invoked whenever a file system has either registered or
789     unregistered itself as an active file system.
790 
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.
794 
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.
798 
799 Arguments:
800 
801     DeviceObject - Pointer to the file system's device object.
802 
803     FsActive - bolean indicating whether the file system has registered
804         (TRUE) or unregistered (FALSE) itself as an active file system.
805 
806 Return Value:
807 
808     None.
809 
810 */
811 
812 {
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.
815     if (!FsRegistered ||
816         DeviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
817         return;
818     }
819 
820     // Begin by determining whether this file system is registering or
821     // unregistering as an active file system.
822     if (FsActive
823         && UDFGlobalData.UDFDeviceObject_CD  != DeviceObject
824 #ifdef UDF_HDD_SUPPORT
825         && UDFGlobalData.UDFDeviceObject_HDD != DeviceObject
826 #endif // UDF_HDD_SUPPORT
827     ) {
828         UDFPrint(("\n*** UDFFSNotification \n\n"));
829 
830         // Acquire GlobalDataResource
831         UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
832 
833         if(FsNotification_ThreadId != PsGetCurrentThreadId()) {
834 
835             FsNotification_ThreadId = PsGetCurrentThreadId();
836 
837             IoUnregisterFileSystem(UDFGlobalData.UDFDeviceObject_CD);
838             IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_CD);
839 
840 #ifdef UDF_HDD_SUPPORT
841             IoUnregisterFileSystem(UDFGlobalData.UDFDeviceObject_HDD);
842             IoRegisterFileSystem(UDFGlobalData.UDFDeviceObject_HDD);
843 #endif // UDF_HDD_SUPPORT
844 
845             FsNotification_ThreadId = (HANDLE)(-1);
846 
847         } else {
848             UDFPrint(("\n*** recursive UDFFSNotification call,\n can't become top-level UDF FSD \n\n"));
849         }
850 
851         // Release the global resource.
852         UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
853 
854 
855     }
856 }
857 /*VOID
858 UDFRemountAll(
859     IN PVOID Context
860     )
861 {
862     NTSTATUS RC = STATUS_SUCCESS;
863     ULONG           CdRomNumber;
864     CCHAR           deviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
865     ANSI_STRING     deviceName;
866     UNICODE_STRING  unicodeCdRomDeviceName;
867     LARGE_INTEGER   delay;
868 
869 */
870 /*    delay.QuadPart = -80*10000000;
871     KeDelayExecutionThread(KernelMode, FALSE, &delay);        //10 seconds*/
872 
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);
878 
879         if (!NT_SUCCESS(RC)) {
880             RtlFreeUnicodeString(&unicodeCdRomDeviceName);
881             break;
882         }
883 
884         RC = UDFDismountDevice(&unicodeCdRomDeviceName);
885         RtlFreeUnicodeString(&unicodeCdRomDeviceName);
886 
887         if (!NT_SUCCESS(RC)) break;
888     }
889 }*/
890