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