test: fs_rec.c Source File

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