Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

fs_rec.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 fs_rec.c 00008 00009 Abstract: 00010 00011 This module contains the main functions for the mini-file system recognizer 00012 driver. 00013 00014 Author: 00015 00016 Darryl E. Havens (darrylh) 22-nov-1993 00017 00018 Environment: 00019 00020 Kernel mode, local to I/O system 00021 00022 Revision History: 00023 00024 00025 --*/ 00026 00027 #include "fs_rec.h" 00028 00029 // 00030 // The local debug trace level 00031 // 00032 00033 #define Dbg (FSREC_DEBUG_LEVEL_FSREC) 00034 00035 #if DBG 00036 00037 #include <stdarg.h> 00038 #include <stdio.h> 00039 00040 LONG FsRecDebugTraceLevel = 0; 00041 LONG FsRecDebugTraceIndent = 0; 00042 00043 #endif 00044 00045 #ifdef ALLOC_PRAGMA 00046 #pragma alloc_text(INIT,DriverEntry) 00047 #pragma alloc_text(INIT,FsRecCreateAndRegisterDO) 00048 00049 #pragma alloc_text(PAGE,FsRecCleanupClose) 00050 #pragma alloc_text(PAGE,FsRecCreate) 00051 #pragma alloc_text(PAGE,FsRecFsControl) 00052 #pragma alloc_text(PAGE,FsRecGetDeviceSectorSize) 00053 #pragma alloc_text(PAGE,FsRecGetDeviceSectors) 00054 #pragma alloc_text(PAGE,FsRecLoadFileSystem) 00055 #pragma alloc_text(PAGE,FsRecReadBlock) 00056 #pragma alloc_text(PAGE,FsRecUnload) 00057 #endif // ALLOC_PRAGMA 00058 00059 // 00060 // Mutex for serializing driver loads. 00061 // 00062 00063 PKEVENT FsRecLoadSync; 00064 00065 00066 NTSTATUS 00067 DriverEntry ( 00068 IN PDRIVER_OBJECT DriverObject, 00069 IN PUNICODE_STRING RegistryPath 00070 ) 00071 00072 /*++ 00073 00074 Routine Description: 00075 00076 This routine is invoked once when the driver is loaded to allow the driver 00077 to initialize itself. The initialization for the driver consists of simply 00078 creating a device object for each type of file system recognized by this 00079 driver, and then registering each as active file systems. 00080 00081 Arguments: 00082 00083 DriverObject - Pointer to the driver object for this driver. 00084 00085 RegistryPath - Pointer to the registry service node for this driver. 00086 00087 Return Value: 00088 00089 The function value is the final status of the initialization for the driver. 00090 00091 --*/ 00092 00093 { 00094 PDEVICE_OBJECT UdfsMainRecognizerDeviceObject; 00095 NTSTATUS status; 00096 ULONG count = 0; 00097 00098 PAGED_CODE(); 00099 00100 // 00101 // Mark the entire driver as pagable. 00102 // 00103 00104 MmPageEntireDriver ((PVOID)DriverEntry); 00105 00106 // 00107 // Begin by initializing the driver object so that it the driver is 00108 // prepared to provide services. 00109 // 00110 00111 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl; 00112 DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate; 00113 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecCleanupClose; 00114 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecCleanupClose; 00115 DriverObject->DriverUnload = FsRecUnload; 00116 00117 FsRecLoadSync = ExAllocatePoolWithTag( NonPagedPool, sizeof(KEVENT), FSREC_POOL_TAG ); 00118 00119 if (FsRecLoadSync == NULL) { 00120 00121 return STATUS_INSUFFICIENT_RESOURCES; 00122 } 00123 00124 KeInitializeEvent( FsRecLoadSync, SynchronizationEvent, TRUE ); 00125 00126 // 00127 // Create and initialize each of the file system driver type device 00128 // objects. 00129 // 00130 00131 status = FsRecCreateAndRegisterDO( DriverObject, 00132 NULL, 00133 NULL, 00134 L"\\Cdfs", 00135 L"\\FileSystem\\CdfsRecognizer", 00136 CdfsFileSystem, 00137 FILE_DEVICE_CD_ROM_FILE_SYSTEM ); 00138 if (NT_SUCCESS( status )) { 00139 count++; 00140 } 00141 00142 status = FsRecCreateAndRegisterDO( DriverObject, 00143 NULL, 00144 &UdfsMainRecognizerDeviceObject, 00145 L"\\UdfsCdRom", 00146 L"\\FileSystem\\UdfsCdRomRecognizer", 00147 UdfsFileSystem, 00148 FILE_DEVICE_CD_ROM_FILE_SYSTEM ); 00149 if (NT_SUCCESS( status )) { 00150 count++; 00151 } 00152 00153 status = FsRecCreateAndRegisterDO( DriverObject, 00154 UdfsMainRecognizerDeviceObject, 00155 NULL, 00156 L"\\UdfsDisk", 00157 L"\\FileSystem\\UdfsDiskRecognizer", 00158 UdfsFileSystem, 00159 FILE_DEVICE_DISK_FILE_SYSTEM ); 00160 if (NT_SUCCESS( status )) { 00161 count++; 00162 } 00163 00164 status = FsRecCreateAndRegisterDO( DriverObject, 00165 NULL, 00166 NULL, 00167 L"\\Fat", 00168 L"\\FileSystem\\FatRecognizer", 00169 FatFileSystem, 00170 FILE_DEVICE_DISK_FILE_SYSTEM ); 00171 if (NT_SUCCESS( status )) { 00172 count++; 00173 } 00174 00175 status = FsRecCreateAndRegisterDO( DriverObject, 00176 NULL, 00177 NULL, 00178 L"\\Ntfs", 00179 L"\\FileSystem\\NtfsRecognizer", 00180 NtfsFileSystem, 00181 FILE_DEVICE_DISK_FILE_SYSTEM ); 00182 if (NT_SUCCESS( status )) { 00183 count++; 00184 } 00185 00186 if (count) { 00187 return STATUS_SUCCESS; 00188 } else { 00189 return STATUS_IMAGE_ALREADY_LOADED; 00190 } 00191 } 00192 00193 00194 NTSTATUS 00195 FsRecCleanupClose ( 00196 IN PDEVICE_OBJECT DeviceObject, 00197 IN PIRP Irp 00198 ) 00199 00200 /*++ 00201 00202 Routine Description: 00203 00204 This routine is invoked when someone attempts to cleanup or close one of 00205 the system recognizer's registered device objects. 00206 00207 Arguments: 00208 00209 DeviceObject - Pointer to the device object being closed. 00210 00211 Irp - Pointer to the cleanup/close IRP. 00212 00213 Return Value: 00214 00215 The final function value is STATUS_SUCCESS. 00216 00217 --*/ 00218 00219 { 00220 PAGED_CODE(); 00221 00222 // 00223 // Simply complete the request successfully (note that IoStatus.Status in 00224 // Irp is already initialized to STATUS_SUCCESS). 00225 // 00226 00227 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00228 return STATUS_SUCCESS; 00229 } 00230 00231 00232 NTSTATUS 00233 FsRecCreate ( 00234 IN PDEVICE_OBJECT DeviceObject, 00235 IN PIRP Irp 00236 ) 00237 00238 /*++ 00239 00240 Routine Description: 00241 00242 This routine is invoked when someone attempts to open one of the file 00243 system recognizer's registered device objects. 00244 00245 Arguments: 00246 00247 DeviceObject - Pointer to the device object being opened. 00248 00249 Irp - Pointer to the create IRP. 00250 00251 Return Value: 00252 00253 The final function value indicates whether or not the open was successful. 00254 00255 --*/ 00256 00257 { 00258 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); 00259 NTSTATUS status; 00260 00261 PAGED_CODE(); 00262 00263 // 00264 // Simply ensure that the name of the "file" being opened is NULL, and 00265 // complete the request accordingly. 00266 // 00267 00268 if (irpSp->FileObject->FileName.Length) { 00269 status = STATUS_OBJECT_PATH_NOT_FOUND; 00270 } else { 00271 status = STATUS_SUCCESS; 00272 } 00273 00274 Irp->IoStatus.Status = status; 00275 Irp->IoStatus.Information = FILE_OPENED; 00276 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00277 return status; 00278 } 00279 00280 00281 NTSTATUS 00282 FsRecCreateAndRegisterDO ( 00283 IN PDRIVER_OBJECT DriverObject, 00284 IN PDEVICE_OBJECT HeadRecognizer OPTIONAL, 00285 OUT PDEVICE_OBJECT *NewRecognizer OPTIONAL, 00286 IN PWCHAR RecFileSystem, 00287 IN PWCHAR FileSystemName, 00288 IN FILE_SYSTEM_TYPE FileSystemType, 00289 IN DEVICE_TYPE DeviceType 00290 ) 00291 00292 /*++ 00293 00294 Routine Description: 00295 00296 This routine creates a device object for the specified file system type and 00297 registers it as an active file system. 00298 00299 Arguments: 00300 00301 DriverObject - Pointer to the driver object for this driver. 00302 00303 HeadRecognizer - Optionally supplies a pre-existing recognizer that the 00304 newly created DO should be jointly serialized and unregistered with. 00305 This is useful if a given filesystem exists on multiple device types 00306 and thus requires multiple recognizers. 00307 00308 NewDeviceObject - Receives the created DO on success.. 00309 00310 RecFileSystem - Name of the file system to be recognized. 00311 00312 FileSystemName - Name of file system device object to be registered. 00313 00314 FileSystemType - Type of this file system recognizer device object. 00315 00316 DeviceType - Type of media this file system recognizer device object will inspect. 00317 00318 Return Value: 00319 00320 The final function value indicates whether or not the device object was 00321 successfully created and registered. 00322 00323 --*/ 00324 00325 { 00326 PDEVICE_OBJECT deviceObject; 00327 NTSTATUS status; 00328 UNICODE_STRING nameString; 00329 OBJECT_ATTRIBUTES objectAttributes; 00330 HANDLE fsHandle; 00331 IO_STATUS_BLOCK ioStatus; 00332 PDEVICE_EXTENSION deviceExtension; 00333 00334 PAGED_CODE(); 00335 00336 if (NewRecognizer) { 00337 00338 *NewRecognizer = NULL; 00339 } 00340 00341 // 00342 // Begin by attempting to open the file system driver's device object. If 00343 // it works, then the file system is already loaded, so don't load this 00344 // driver. Otherwise, this mini-driver is the one that should be loaded. 00345 // 00346 00347 RtlInitUnicodeString( &nameString, RecFileSystem ); 00348 InitializeObjectAttributes( &objectAttributes, 00349 &nameString, 00350 OBJ_CASE_INSENSITIVE, 00351 (HANDLE) NULL, 00352 (PSECURITY_DESCRIPTOR) NULL ); 00353 00354 status = ZwCreateFile( &fsHandle, 00355 SYNCHRONIZE, 00356 &objectAttributes, 00357 &ioStatus, 00358 (PLARGE_INTEGER) NULL, 00359 0, 00360 FILE_SHARE_READ | FILE_SHARE_WRITE, 00361 FILE_OPEN, 00362 0, 00363 (PVOID) NULL, 00364 0 ); 00365 00366 if (NT_SUCCESS( status )) { 00367 ZwClose( fsHandle ); 00368 } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { 00369 status = STATUS_SUCCESS; 00370 } 00371 00372 if (NT_SUCCESS( status )) { 00373 return STATUS_IMAGE_ALREADY_LOADED; 00374 } 00375 00376 // 00377 // Attempt to create a device object for this driver. This device object 00378 // will be used to represent the driver as an active file system in the 00379 // system. 00380 // 00381 00382 RtlInitUnicodeString( &nameString, FileSystemName ); 00383 00384 status = IoCreateDevice( DriverObject, 00385 sizeof( DEVICE_EXTENSION ), 00386 &nameString, 00387 DeviceType, 00388 0, 00389 FALSE, 00390 &deviceObject ); 00391 if (!NT_SUCCESS( status )) { 00392 return status; 00393 } 00394 00395 // 00396 // Initialize the device extension for this device object. 00397 // 00398 00399 deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; 00400 deviceExtension->FileSystemType = FileSystemType; 00401 deviceExtension->State = Active; 00402 00403 // 00404 // Is this a filesystem being jointly recognized by recognizers for 00405 // different device types? 00406 // 00407 00408 if (HeadRecognizer) { 00409 00410 // 00411 // Link into the list. 00412 // 00413 00414 deviceExtension->CoRecognizer = ((PDEVICE_EXTENSION)HeadRecognizer->DeviceExtension)->CoRecognizer; 00415 ((PDEVICE_EXTENSION)HeadRecognizer->DeviceExtension)->CoRecognizer = deviceObject; 00416 00417 } else { 00418 00419 // 00420 // Initialize the list of codependant recognizer objects. 00421 // 00422 00423 deviceExtension->CoRecognizer = deviceObject; 00424 } 00425 00426 #if _PNP_POWER_ 00427 deviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE; 00428 #endif 00429 00430 // 00431 // Finally, register this driver as an active, loaded file system and 00432 // return to the caller. 00433 // 00434 00435 if (NewRecognizer) { 00436 00437 *NewRecognizer = deviceObject; 00438 } 00439 00440 IoRegisterFileSystem( deviceObject ); 00441 return STATUS_SUCCESS; 00442 } 00443 00444 00445 NTSTATUS 00446 FsRecFsControl ( 00447 IN PDEVICE_OBJECT DeviceObject, 00448 IN PIRP Irp 00449 ) 00450 00451 /*++ 00452 00453 Routine Description: 00454 00455 This function performs the mount and driver reload functions for this mini- 00456 file system recognizer driver. 00457 00458 Arguments: 00459 00460 DeviceObject - Pointer to this driver's device object. 00461 00462 Irp - Pointer to the I/O Request Packet (IRP) representing the function to 00463 be performed. 00464 00465 Return Value: 00466 00467 The function value is the final status of the operation. 00468 00469 00470 --*/ 00471 00472 { 00473 PDEVICE_EXTENSION deviceExtension; 00474 PIO_STACK_LOCATION irpSp; 00475 NTSTATUS status; 00476 00477 PAGED_CODE(); 00478 00479 // 00480 // Simply vector to the appropriate FS control function given the type 00481 // of file system being interrogated. 00482 // 00483 00484 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 00485 irpSp = IoGetCurrentIrpStackLocation( Irp ); 00486 00487 // 00488 // Handle the inactive recognizer states directly. 00489 // 00490 00491 if (deviceExtension->State != Active && irpSp->MinorFunction == IRP_MN_MOUNT_VOLUME) { 00492 00493 if (deviceExtension->State == Transparent) { 00494 00495 status = STATUS_UNRECOGNIZED_VOLUME; 00496 00497 } else { 00498 00499 status = STATUS_FS_DRIVER_REQUIRED; 00500 } 00501 00502 Irp->IoStatus.Status = status; 00503 IoCompleteRequest( Irp, IO_NO_INCREMENT ); 00504 return status; 00505 } 00506 00507 switch ( deviceExtension->FileSystemType ) { 00508 00509 case FatFileSystem: 00510 00511 status = FatRecFsControl( DeviceObject, Irp ); 00512 break; 00513 00514 case NtfsFileSystem: 00515 00516 status = NtfsRecFsControl( DeviceObject, Irp ); 00517 break; 00518 00519 case CdfsFileSystem: 00520 00521 status = CdfsRecFsControl( DeviceObject, Irp ); 00522 break; 00523 00524 case UdfsFileSystem: 00525 00526 status = UdfsRecFsControl( DeviceObject, Irp ); 00527 break; 00528 00529 default: 00530 00531 status = STATUS_INVALID_DEVICE_REQUEST; 00532 } 00533 00534 return status; 00535 } 00536 00537 00538 VOID 00539 FsRecUnload ( 00540 IN PDRIVER_OBJECT DriverObject 00541 ) 00542 00543 /*++ 00544 00545 Routine Description: 00546 00547 This routine cleans up the driver's data structures so that it can be 00548 unloaded. 00549 00550 Arguments: 00551 00552 DriverObject - Pointer to the driver object for this driver. 00553 00554 Return Value: 00555 00556 None. 00557 00558 --*/ 00559 00560 { 00561 PAGED_CODE(); 00562 00563 // 00564 // Simply delete all of the device objects that this driver has created, the 00565 // load event, and return. 00566 // 00567 00568 while (DriverObject->DeviceObject) { 00569 IoDeleteDevice( DriverObject->DeviceObject ); 00570 } 00571 00572 ExFreePool( FsRecLoadSync ); 00573 00574 return; 00575 } 00576 00577 00578 NTSTATUS 00579 FsRecLoadFileSystem ( 00580 IN PDEVICE_OBJECT DeviceObject, 00581 IN PWCHAR DriverServiceName 00582 ) 00583 00584 /*++ 00585 00586 00587 Routine Description: 00588 00589 This routine performs the common work of loading a filesystem on behalf 00590 of one of our recognizers. 00591 00592 Arguments: 00593 00594 DeviceObject - Pointer to the device object for the recognizer. 00595 00596 DriverServiceName - Specifies the name of the node in the registry 00597 associated with the driver to be loaded. 00598 00599 Return Value: 00600 00601 NTSTATUS. The recognizer will be set into a transparent mode on return. 00602 00603 --*/ 00604 00605 { 00606 UNICODE_STRING driverName; 00607 PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 00608 NTSTATUS status = STATUS_IMAGE_ALREADY_LOADED; 00609 00610 PAGED_CODE(); 00611 00612 // 00613 // Quickly check if the recognizer has already fired. 00614 // 00615 00616 if (deviceExtension->State != Transparent) { 00617 00618 // 00619 // Serialize all threads trying to load this filesystem. 00620 // 00621 // We need to do this for several reasons. With the new behavior in 00622 // IoRegisterFileSystem, we do not know ahead of time whether the 00623 // filesystem has been loaded ahead or behind this recognizer in the 00624 // scan queue. This means that we cannot make this recognizer transparent 00625 // before the real filesystem has become registered, or else if the 00626 // filesystem loads behind us we may let threads go through that will 00627 // not find it in that window of time. 00628 // 00629 // The reason this is possible is that NtLoadDriver does not guarantee 00630 // that if it returns STATUS_IMAGE_ALREADY_LOADED, that the driver in 00631 // question has actually initialized itself, which *is* guaranteed if 00632 // it returns STATUS_SUCCESS. We have to keep these threads bottled 00633 // up until they can rescan with the promise that what they need is there. 00634 // 00635 // As a bonus, we can now guarantee that the recognizer goes away in 00636 // all cases, not just when the driver successfully loads itself. 00637 // 00638 00639 KeWaitForSingleObject( FsRecLoadSync, 00640 Executive, 00641 KernelMode, 00642 FALSE, 00643 NULL ); 00644 KeEnterCriticalRegion(); 00645 00646 // 00647 // Attempt the filesystem load precisely once for all recognizers 00648 // of a given filesystem. 00649 // 00650 00651 if (deviceExtension->State == Active) { 00652 00653 // 00654 // For bonus points, in the future we may want to log an event 00655 // on failure. 00656 // 00657 00658 RtlInitUnicodeString( &driverName, DriverServiceName ); 00659 status = ZwLoadDriver( &driverName ); 00660 00661 // 00662 // Now walk all codependant recognizers and instruct them to go 00663 // into the fast unload state. Since IO only expects the fsDO 00664 // it is asking to load a filesystem to to unregister itself, if 00665 // we unregistered all of the co-recognizers they would dangle. 00666 // Unfortunately, this means that fsrec may wind up hanging around 00667 // quite a bit longer than strictly neccesary. 00668 // 00669 // Note: we come right back to the original DeviceObject at the 00670 // end of this loop (important). It is also very important that 00671 // we only did this once since after we release the mutex the co- 00672 // recognizers may begin going away in any order. 00673 // 00674 00675 while (deviceExtension->State != FastUnload) { 00676 00677 deviceExtension->State = FastUnload; 00678 00679 DeviceObject = deviceExtension->CoRecognizer; 00680 deviceExtension = DeviceObject->DeviceExtension; 00681 } 00682 } 00683 00684 // 00685 // Unregister this recognizer precisely once. 00686 // 00687 00688 if (deviceExtension->State != Transparent) { 00689 00690 IoUnregisterFileSystem( DeviceObject ); 00691 deviceExtension->State = Transparent; 00692 } 00693 00694 KeSetEvent( FsRecLoadSync, 0, FALSE ); 00695 KeLeaveCriticalRegion(); 00696 } 00697 00698 return status; 00699 } 00700 00701 00702 BOOLEAN 00703 FsRecGetDeviceSectors ( 00704 IN PDEVICE_OBJECT DeviceObject, 00705 IN ULONG BytesPerSector, 00706 OUT PLARGE_INTEGER NumberOfSectors 00707 ) 00708 00709 /*++ 00710 00711 Routine Description: 00712 00713 This routine returns information about the partition represented by the 00714 device object. 00715 00716 Arguments: 00717 00718 DeviceObject - Pointer to the device object from which to read. 00719 00720 BytesPerSector - The number of bytes per sector for the device being read. 00721 00722 NumberOfSectors - Variable to receive the number of sectors for this 00723 partition. 00724 00725 Return Value: 00726 00727 The function value is TRUE if the information was found, otherwise FALSE. 00728 00729 --*/ 00730 00731 { 00732 PARTITION_INFORMATION partitionInfo; 00733 IO_STATUS_BLOCK ioStatus; 00734 KEVENT event; 00735 PIRP irp; 00736 NTSTATUS status; 00737 ULONG remainder; 00738 00739 PAGED_CODE(); 00740 00741 // 00742 // We only do this for disks right now. This is likely to change when we 00743 // have to recognize CDUDF media. 00744 // 00745 00746 if (DeviceObject->DeviceType != FILE_DEVICE_DISK) { 00747 00748 return FALSE; 00749 } 00750 00751 // 00752 // Get the number of sectors on this partition. 00753 // 00754 00755 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 00756 00757 irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_PARTITION_INFO, 00758 DeviceObject, 00759 (PVOID) NULL, 00760 0, 00761 &partitionInfo, 00762 sizeof( partitionInfo ), 00763 FALSE, 00764 &event, 00765 &ioStatus ); 00766 if (!irp) { 00767 return FALSE; 00768 } 00769 00770 // 00771 // Override verify logic - we don't care. The fact we're in the picture means 00772 // someone is trying to mount new/changed media in the first place. 00773 // 00774 00775 SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME ); 00776 00777 status = IoCallDriver( DeviceObject, irp ); 00778 if (status == STATUS_PENDING) { 00779 (VOID) KeWaitForSingleObject( &event, 00780 Executive, 00781 KernelMode, 00782 FALSE, 00783 (PLARGE_INTEGER) NULL ); 00784 status = ioStatus.Status; 00785 } 00786 00787 if (!NT_SUCCESS( status )) { 00788 return FALSE; 00789 } 00790 00791 *NumberOfSectors = RtlExtendedLargeIntegerDivide( partitionInfo.PartitionLength, 00792 BytesPerSector, 00793 &remainder ); 00794 00795 return TRUE; 00796 } 00797 00798 00799 BOOLEAN 00800 FsRecGetDeviceSectorSize ( 00801 IN PDEVICE_OBJECT DeviceObject, 00802 OUT PULONG BytesPerSector 00803 ) 00804 00805 /*++ 00806 00807 Routine Description: 00808 00809 This routine returns the sector size of the underlying device. 00810 00811 Arguments: 00812 00813 DeviceObject - Pointer to the device object from which to read. 00814 00815 BytesPerSector - Variable to receive the number of bytes per sector for the 00816 device being read. 00817 00818 Return Value: 00819 00820 The function value is TRUE if the information was found, otherwise FALSE. 00821 00822 --*/ 00823 00824 { 00825 DISK_GEOMETRY diskGeometry; 00826 IO_STATUS_BLOCK ioStatus; 00827 KEVENT event; 00828 PIRP irp; 00829 NTSTATUS status; 00830 ULONG ControlCode; 00831 00832 PAGED_CODE(); 00833 00834 // 00835 // Figure out what kind of device we have so we can use the right IOCTL. 00836 // 00837 00838 switch (DeviceObject->DeviceType) { 00839 case FILE_DEVICE_CD_ROM: 00840 ControlCode = IOCTL_CDROM_GET_DRIVE_GEOMETRY; 00841 break; 00842 00843 case FILE_DEVICE_DISK: 00844 ControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY; 00845 break; 00846 00847 default: 00848 return FALSE; 00849 } 00850 00851 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 00852 irp = IoBuildDeviceIoControlRequest( ControlCode, 00853 DeviceObject, 00854 (PVOID) NULL, 00855 0, 00856 &diskGeometry, 00857 sizeof( diskGeometry ), 00858 FALSE, 00859 &event, 00860 &ioStatus ); 00861 00862 if (!irp) { 00863 return FALSE; 00864 } 00865 00866 // 00867 // Override verify logic - we don't care. The fact we're in the picture means 00868 // someone is trying to mount new/changed media in the first place. 00869 // 00870 00871 SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME ); 00872 00873 status = IoCallDriver( DeviceObject, irp ); 00874 if (status == STATUS_PENDING) { 00875 (VOID) KeWaitForSingleObject( &event, 00876 Executive, 00877 KernelMode, 00878 FALSE, 00879 (PLARGE_INTEGER) NULL ); 00880 status = ioStatus.Status; 00881 } 00882 00883 if (!NT_SUCCESS( status )) { 00884 return FALSE; 00885 } 00886 00887 // 00888 // Ensure that the drive actually knows how many bytes there are per 00889 // sector. Floppy drives do not know if the media is unformatted. 00890 // 00891 00892 if (!diskGeometry.BytesPerSector) { 00893 return FALSE; 00894 } 00895 00896 // 00897 // Store the return values for the caller. 00898 // 00899 00900 *BytesPerSector = diskGeometry.BytesPerSector; 00901 00902 return TRUE; 00903 } 00904 00905 00906 BOOLEAN 00907 FsRecReadBlock( 00908 IN PDEVICE_OBJECT DeviceObject, 00909 IN PLARGE_INTEGER ByteOffset, 00910 IN ULONG MinimumBytes, 00911 IN ULONG BytesPerSector, 00912 OUT PVOID *Buffer, 00913 OUT PBOOLEAN IsDeviceFailure OPTIONAL 00914 ) 00915 00916 /*++ 00917 00918 Routine Description: 00919 00920 This routine reads a minimum numbers of bytes into a buffer starting at 00921 the byte offset from the base of the device represented by the device 00922 object. 00923 00924 Arguments: 00925 00926 DeviceObject - Pointer to the device object from which to read. 00927 00928 ByteOffset - Pointer to a 64-bit byte offset from the base of the device 00929 from which to start the read. 00930 00931 MinimumBytes - Supplies the minimum number of bytes to be read. 00932 00933 BytesPerSector - The number of bytes per sector for the device being read. 00934 00935 Buffer - Variable to receive a pointer to the allocated buffer containing 00936 the bytes read. 00937 00938 IsDeviceFailure - Variable to receive an indication whether a failure 00939 was a result of talking to the device. 00940 00941 Return Value: 00942 00943 The function value is TRUE if the bytes were read, otherwise FALSE. 00944 00945 --*/ 00946 00947 { 00948 #define RoundUp( x, y ) ( ((x + (y-1)) / y) * y ) 00949 00950 IO_STATUS_BLOCK ioStatus; 00951 KEVENT event; 00952 PIRP irp; 00953 NTSTATUS status; 00954 00955 PAGED_CODE(); 00956 00957 if (IsDeviceFailure) { 00958 *IsDeviceFailure = FALSE; 00959 } 00960 00961 KeInitializeEvent( &event, SynchronizationEvent, FALSE ); 00962 00963 // 00964 // Set the minimum number of bytes to read to the maximum of the bytes that 00965 // the caller wants to read, and the number of bytes in a sector. 00966 // 00967 00968 if (MinimumBytes < BytesPerSector) { 00969 MinimumBytes = BytesPerSector; 00970 } else { 00971 MinimumBytes = RoundUp( MinimumBytes, BytesPerSector ); 00972 } 00973 00974 // 00975 // Allocate a buffer large enough to contain the bytes required, round the 00976 // request to a page boundary to solve any alignment requirements. 00977 // 00978 00979 if (!*Buffer) { 00980 00981 *Buffer = ExAllocatePoolWithTag( NonPagedPool, 00982 (MinimumBytes + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1), 00983 FSREC_POOL_TAG ); 00984 if (!*Buffer) { 00985 return FALSE; 00986 } 00987 } 00988 00989 // 00990 // Read the actual bytes off of the media. 00991 // 00992 00993 irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ, 00994 DeviceObject, 00995 *Buffer, 00996 MinimumBytes, 00997 ByteOffset, 00998 &event, 00999 &ioStatus ); 01000 if (!irp) { 01001 return FALSE; 01002 } 01003 01004 // 01005 // Override verify logic - we don't care. The fact we're in the picture means 01006 // someone is trying to mount new/changed media in the first place. 01007 // 01008 01009 SetFlag( IoGetNextIrpStackLocation( irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME ); 01010 01011 status = IoCallDriver( DeviceObject, irp ); 01012 if (status == STATUS_PENDING) { 01013 (VOID) KeWaitForSingleObject( &event, 01014 Executive, 01015 KernelMode, 01016 FALSE, 01017 (PLARGE_INTEGER) NULL ); 01018 status = ioStatus.Status; 01019 } 01020 01021 if (!NT_SUCCESS( status )) { 01022 01023 if (IsDeviceFailure) { 01024 *IsDeviceFailure = TRUE; 01025 } 01026 return FALSE; 01027 } 01028 01029 return TRUE; 01030 } 01031 01032 01033 #if DBG 01034 BOOLEAN 01035 FsRecDebugTrace ( 01036 LONG IndentIncrement, 01037 ULONG TraceMask, 01038 PCHAR Format, 01039 ... 01040 ) 01041 01042 /*++ 01043 01044 Routine Description: 01045 01046 This routine is a simple debug info printer that returns a constant boolean value. This 01047 makes it possible to splice it into the middle of boolean expressions to discover which 01048 elements are firing. 01049 01050 We will use this as our general debug printer. See udfdata.h for how we use the DebugTrace 01051 macro to accomplish the effect. 01052 01053 Arguments: 01054 01055 IndentIncrement - amount to change the indentation by. 01056 01057 TraceMask - specification of what debug trace level this call should be noisy at. 01058 01059 Return Value: 01060 01061 USHORT - The 16bit CRC 01062 01063 --*/ 01064 01065 { 01066 va_list Arglist; 01067 LONG i; 01068 UCHAR Buffer[128]; 01069 int Bytes; 01070 01071 #define Min(a, b) ((a) < (b) ? (a) : (b)) 01072 01073 if (TraceMask == 0 || (FsRecDebugTraceLevel & TraceMask) != 0) { 01074 01075 // 01076 // Emit a preamble of our thread ID. 01077 // 01078 01079 DbgPrint( "%p:", PsGetCurrentThread()); 01080 01081 if (IndentIncrement < 0) { 01082 01083 FsRecDebugTraceIndent += IndentIncrement; 01084 } 01085 01086 if (FsRecDebugTraceIndent < 0) { 01087 01088 FsRecDebugTraceIndent = 0; 01089 } 01090 01091 // 01092 // Build the indent in big chunks since calling DbgPrint repeatedly is expensive. 01093 // 01094 01095 for (i = FsRecDebugTraceIndent; i > 0; i -= (sizeof(Buffer) - 1)) { 01096 01097 RtlFillMemory( Buffer, Min( i, (sizeof(Buffer) - 1 )), ' '); 01098 *(Buffer + Min( i, (sizeof(Buffer) - 1 ))) = '\0'; 01099 01100 DbgPrint( Buffer ); 01101 } 01102 01103 // 01104 // Format the output into a buffer and then print it. 01105 // 01106 01107 va_start( Arglist, Format ); 01108 Bytes = _vsnprintf( Buffer, sizeof(Buffer), Format, Arglist ); 01109 va_end( Arglist ); 01110 01111 // 01112 // detect buffer overflow 01113 // 01114 01115 if (Bytes == -1) { 01116 01117 Buffer[sizeof(Buffer) - 1] = '\n'; 01118 } 01119 01120 DbgPrint( Buffer ); 01121 01122 if (IndentIncrement > 0) { 01123 01124 FsRecDebugTraceIndent += IndentIncrement; 01125 } 01126 } 01127 01128 return TRUE; 01129 } 01130 #endif 01131

Generated on Sat May 15 19:40:04 2004 for test by doxygen 1.3.7