[ros-diffs] [ion] 24564: - A much simpler and featured RawFs driver that I had been working on while learning how to write simple FS drivers. Still missing some advanced functionality (Lite Stream File Objects and FS Notifications) because the Kernel doesn't fully support them yet. This one actually creates the \\Device names so that user-mode can even talk to it.

ion at svn.reactos.org ion at svn.reactos.org
Wed Oct 18 20:00:44 CEST 2006


Author: ion
Date: Wed Oct 18 22:00:42 2006
New Revision: 24564

URL: http://svn.reactos.org/svn/reactos?rev=24564&view=rev
Log:
- A much simpler and featured RawFs driver that I had been working on while learning how to write simple FS drivers. Still missing some advanced functionality (Lite Stream File Objects and FS Notifications) because the Kernel doesn't fully support them yet. This one actually creates the \\Device names so that user-mode can even talk to it.

Modified:
    trunk/reactos/ntoskrnl/io/iomgr/rawfs.c

Modified: trunk/reactos/ntoskrnl/io/iomgr/rawfs.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/rawfs.c?rev=24564&r1=24563&r2=24564&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/rawfs.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/rawfs.c Wed Oct 18 22:00:42 2006
@@ -1,962 +1,1105 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/io/rawfs.c
- * PURPOSE:         Raw filesystem driver
- *
- * PROGRAMMERS:     Casper S. Hornstrup (chorns at users.sourceforge.net)
- */
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/io/iomgr/rawfs.c
+* PURPOSE:         Raw File System Driver
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
+*/
 
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* TYPES *******************************************************************/
 
-typedef struct _RAWFS_GLOBAL_DATA
-{
-  PDRIVER_OBJECT DriverObject;
-  PDEVICE_OBJECT DeviceObject;
-  ULONG Flags;
-  ERESOURCE VolumeListLock;
-  LIST_ENTRY VolumeListHead;
-  NPAGED_LOOKASIDE_LIST FcbLookasideList;
-  NPAGED_LOOKASIDE_LIST CcbLookasideList;
-} RAWFS_GLOBAL_DATA, *PRAWFS_GLOBAL_DATA, VCB, *PVCB;
-
-typedef struct _RAWFS_DEVICE_EXTENSION
-{
-  KSPIN_LOCK FcbListLock;
-  LIST_ENTRY FcbListHead;
-  PDEVICE_OBJECT StorageDevice;
-  ULONG Flags;
-  struct _RAWFS_FCB *VolumeFcb;
-  LIST_ENTRY VolumeListEntry;
-} RAWFS_DEVICE_EXTENSION, *PRAWFS_DEVICE_EXTENSION;
-
-typedef struct _RAWFS_IRP_CONTEXT
-{
-   PIRP Irp;
-   PDEVICE_OBJECT DeviceObject;
-   PRAWFS_DEVICE_EXTENSION DeviceExt;
-   ULONG Flags;
-   WORK_QUEUE_ITEM WorkQueueItem;
-   PIO_STACK_LOCATION Stack;
-   UCHAR MajorFunction;
-   UCHAR MinorFunction;
-   PFILE_OBJECT FileObject;
-} RAWFS_IRP_CONTEXT, *PRAWFS_IRP_CONTEXT;
-
-#define IRPCONTEXT_CANWAIT  0x0001
-
-#define FCB_CACHE_INITIALIZED   0x0001
-#define FCB_DELETE_PENDING      0x0002
-#define FCB_IS_FAT              0x0004
-#define FCB_IS_PAGE_FILE        0x0008
-#define FCB_IS_VOLUME           0x0010
-
-typedef struct _RAWFS_FCB
-{
-  /* Start FCB header required by ReactOS/Windows NT */
-  FSRTL_COMMON_FCB_HEADER RFCB;
-  SECTION_OBJECT_POINTERS SectionObjectPointers;
-  ERESOURCE MainResource;
-  ERESOURCE PagingIoResource;
-  /* End FCB header required by ReactOS/Windows NT */
-
-  /* Reference count */
-  LONG RefCount;
-
-  /* List of FCB's for this volume */
-  LIST_ENTRY FcbListEntry;
-
-  /* Pointer to the parent fcb */
-  struct _RAWFS_FCB* ParentFcb;
-
-  /* Flags for the FCB */
-  ULONG Flags;
-
-  /* Pointer to the file object which has initialized the fcb */
-  PFILE_OBJECT FileObject;
-} RAWFS_FCB, *PRAWFS_FCB;
-
-typedef struct _RAWFS_CCB
-{
-  LARGE_INTEGER CurrentByteOffset;
-} RAWFS_CCB, *PRAWFS_CCB;
-
-/* GLOBALS ******************************************************************/
-
-static PDRIVER_OBJECT RawFsDriverObject;
-static PDEVICE_OBJECT DiskDeviceObject;
-static PDEVICE_OBJECT CdromDeviceObject;
-static PDEVICE_OBJECT TapeDeviceObject;
-static NPAGED_LOOKASIDE_LIST IrpContextLookasideList;
-static LONG RawFsQueueCount = 0;
+typedef struct _VCB
+{
+    USHORT NodeTypeCode;
+    USHORT NodeByteSize;
+    PDEVICE_OBJECT TargetDeviceObject;
+    PVPB Vpb;
+    ULONG VcbState;
+    KMUTEX Mutex;
+    CLONG OpenCount;
+    SHARE_ACCESS ShareAccess;
+    ULONG BytesPerSector;
+    LARGE_INTEGER SectorsOnDisk;
+} VCB, *PVCB;
+
+typedef struct _VOLUME_DEVICE_OBJECT
+{
+    DEVICE_OBJECT DeviceObject;
+    VCB Vcb;
+} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;
+
+/* GLOBALS *******************************************************************/
+
+PDEVICE_OBJECT RawDiskDeviceObject, RawCdromDeviceObject, RawTapeDeviceObject;
 
 /* FUNCTIONS *****************************************************************/
 
+VOID
+NTAPI
+RawInitializeVcb(IN OUT PVCB Vcb,
+                 IN PDEVICE_OBJECT TargetDeviceObject,
+                 IN PVPB Vpb)
+{
+    PAGED_CODE();
+
+    /* Clear it */
+    RtlZeroMemory(Vcb, sizeof(VCB));
+
+    /* Associate to system objects */
+    Vcb->TargetDeviceObject = TargetDeviceObject;
+    Vcb->Vpb = Vpb;
+
+    /* Initialize the lock */
+    KeInitializeMutex(&Vcb->Mutex, 0);
+}
+
 BOOLEAN
-RawFsIsRawFileSystemDeviceObject(IN PDEVICE_OBJECT DeviceObject)
-{
-  DPRINT("RawFsIsRawFileSystemDeviceObject(DeviceObject 0x%p)\n", DeviceObject);
-
-  if (DeviceObject == DiskDeviceObject)
-    return TRUE;
-  if (DeviceObject == CdromDeviceObject)
-    return TRUE;
-  if (DeviceObject == TapeDeviceObject)
-    return TRUE;
-  return FALSE;
-}
-
-static NTSTATUS
-RawFsDispatchRequest(IN PRAWFS_IRP_CONTEXT IrpContext);
-
-/*static */NTSTATUS
-RawFsReadDisk(IN PDEVICE_OBJECT pDeviceObject,
-  IN PLARGE_INTEGER ReadOffset,
-  IN ULONG ReadLength,
-  IN OUT PUCHAR Buffer)
-{
-  IO_STATUS_BLOCK IoStatus;
-  NTSTATUS Status;
-  KEVENT Event;
-  PIRP Irp;
-
-  KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-  DPRINT("RawFsReadDisk(pDeviceObject 0x%p, Offset %I64x, Length %d, Buffer 0x%p)\n",
-	  pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
-
-  DPRINT ("Building synchronous FSD Request...\n");
-  Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
-    pDeviceObject,
-    Buffer,
-    ReadLength,
-    ReadOffset,
-    &Event,
-    &IoStatus);
-  if (Irp == NULL)
-    {
-      DPRINT("IoBuildSynchronousFsdRequest() failed\n");
-      return STATUS_UNSUCCESSFUL;
-    }
-
-  DPRINT("Calling IO Driver... with irp 0x%p\n", Irp);
-  Status = IoCallDriver(pDeviceObject, Irp);
-
-  DPRINT("Waiting for IO Operation for 0x%p\n", Irp);
-  if (Status == STATUS_PENDING)
-    {
-      DPRINT("Operation pending\n");
-      KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
-      DPRINT("Getting IO Status... for 0x%p\n", Irp);
-      Status = IoStatus.Status;
-    }
-
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("RawFsReadDisk() failed. Status %x\n", Status);
-      DPRINT("(pDeviceObject 0x%p, Offset %I64x, Size %d, Buffer 0x%p\n",
-	      pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer);
-      return Status;
-    }
-  DPRINT("Block request succeeded for 0x%p\n", Irp);
-  return STATUS_SUCCESS;
-}
-
-/*static */NTSTATUS
-RawFsWriteDisk(IN PDEVICE_OBJECT pDeviceObject,
-  IN PLARGE_INTEGER WriteOffset,
-  IN ULONG WriteLength,
-  IN PUCHAR Buffer)
-{
-  IO_STATUS_BLOCK IoStatus;
-  NTSTATUS Status;
-  KEVENT Event;
-  PIRP Irp;
-
-  DPRINT("RawFsWriteDisk(pDeviceObject 0x%p, Offset %I64x, Size %d, Buffer 0x%p)\n",
-	  pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
-
-  KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-  DPRINT("Building synchronous FSD Request...\n");
-  Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
-    pDeviceObject,
-    Buffer,
-    WriteLength,
-    WriteOffset,
-    &Event,
-    &IoStatus);
-  if (!Irp)
-    {
-      DPRINT("IoBuildSynchronousFsdRequest()\n");
-      return(STATUS_UNSUCCESSFUL);
-    }
-
-  DPRINT("Calling IO Driver...\n");
-  Status = IoCallDriver(pDeviceObject, Irp);
-
-  DPRINT("Waiting for IO Operation...\n");
-  if (Status == STATUS_PENDING)
-    {
-      KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
-      DPRINT("Getting IO Status...\n");
-      Status = IoStatus.Status;
-    }
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("RawFsWriteDisk() failed. Status %x\n", Status);
-      DPRINT("(pDeviceObject 0x%p, Offset %I64x, Size %d, Buffer 0x%p\n",
-	      pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
-      return Status;
-    }
-
-  return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-RawFsBlockDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
-  IN ULONG CtlCode,
-  IN PVOID InputBuffer,
-  IN ULONG InputBufferSize,
-  IN OUT PVOID OutputBuffer,
-  IN OUT PULONG pOutputBufferSize)
-{
-	ULONG OutputBufferSize = 0;
-	KEVENT Event;
-	PIRP Irp;
-	IO_STATUS_BLOCK IoStatus;
-	NTSTATUS Status;
-
-	DPRINT("RawFsBlockDeviceIoControl(DeviceObject 0x%p, CtlCode %x, "
-    "InputBuffer 0x%p, InputBufferSize %x, OutputBuffer 0x%p, "
-    "POutputBufferSize 0x%p (%x)\n", DeviceObject, CtlCode,
-    InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize,
-    pOutputBufferSize ? *pOutputBufferSize : 0);
-
-	if (pOutputBufferSize)
-  	{
-  		OutputBufferSize = *pOutputBufferSize;
-  	}
-
-	KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-	DPRINT("Building device I/O control request ...\n");
-	Irp = IoBuildDeviceIoControlRequest(CtlCode,
-    DeviceObject,
-    InputBuffer,
-    InputBufferSize,
-    OutputBuffer,
-    OutputBufferSize,
-    FALSE,
-    &Event,
-    &IoStatus);
-	if (Irp == NULL)
-  	{
-  		DPRINT("IoBuildDeviceIoControlRequest failed\n");
-  		return STATUS_INSUFFICIENT_RESOURCES;
-  	}
-
-	DPRINT("Calling IO Driver... with irp 0x%p\n", Irp);
-	Status = IoCallDriver(DeviceObject, Irp);
-
-	DPRINT("Waiting for IO Operation for 0x%p\n", Irp);
-	if (Status == STATUS_PENDING)
-    {
-    	DPRINT("Operation pending\n");
-    	KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
-    	DPRINT("Getting IO Status... for 0x%p\n", Irp);
-    	Status = IoStatus.Status;
-    }
-	if (OutputBufferSize)
-  	{
-  		*pOutputBufferSize = OutputBufferSize;
-  	}
-	DPRINT("Returning Status %x\n", Status);
-	return Status;
-}
-
-static PRAWFS_FCB
-RawFsNewFCB(IN PRAWFS_GLOBAL_DATA pGlobalData)
-{
-  PRAWFS_FCB Fcb;
-
-  Fcb = ExAllocateFromNPagedLookasideList(&pGlobalData->FcbLookasideList);
-  memset(Fcb, 0, sizeof(RAWFS_FCB));
-  ExInitializeResourceLite(&Fcb->PagingIoResource);
-  ExInitializeResourceLite(&Fcb->MainResource);
-//  FsRtlInitializeFileLock(&Fcb->FileLock, NULL, NULL);
-  return Fcb;
-}
-
-static VOID
-RawFsDestroyFCB(IN PRAWFS_GLOBAL_DATA pGlobalData, IN PRAWFS_FCB pFcb)
-{
-  //FsRtlUninitializeFileLock(&pFcb->FileLock);
-  ExDeleteResourceLite(&pFcb->PagingIoResource);
-  ExDeleteResourceLite(&pFcb->MainResource);
-  ExFreeToNPagedLookasideList(&pGlobalData->FcbLookasideList, pFcb);
-}
-
-static PRAWFS_CCB
-RawFsNewCCB(PRAWFS_GLOBAL_DATA pGlobalData)
-{
-  PRAWFS_CCB Ccb;
-
-  Ccb = ExAllocateFromNPagedLookasideList(&pGlobalData->CcbLookasideList);
-  memset(Ccb, 0, sizeof(RAWFS_CCB));
-  return Ccb;
-}
-
-/*static */VOID
-RawFsDestroyCCB(PRAWFS_GLOBAL_DATA pGlobalData, PRAWFS_CCB pCcb)
-{
-  ExFreeToNPagedLookasideList(&pGlobalData->CcbLookasideList, pCcb);
-}
-
-static PRAWFS_IRP_CONTEXT
-RawFsAllocateIrpContext(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
-{
-  PRAWFS_GLOBAL_DATA GlobalData;
-  PRAWFS_IRP_CONTEXT IrpContext;
-  UCHAR MajorFunction;
-
-  DPRINT("RawFsAllocateIrpContext(DeviceObject 0x%p, Irp 0x%p)\n", DeviceObject, Irp);
-
-  ASSERT(DeviceObject);
-  ASSERT(Irp);
-
-  GlobalData = (PRAWFS_GLOBAL_DATA) DeviceObject->DeviceExtension;
-  IrpContext = ExAllocateFromNPagedLookasideList(&IrpContextLookasideList);
-  if (IrpContext)
-    {
-      RtlZeroMemory(IrpContext, sizeof(IrpContext));
-      IrpContext->Irp = Irp;
-      IrpContext->DeviceObject = DeviceObject;
-      IrpContext->DeviceExt = DeviceObject->DeviceExtension;
-      IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
-      ASSERT(IrpContext->Stack);
-      MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
-      IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
-      IrpContext->FileObject = IrpContext->Stack->FileObject;
-      if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
-        MajorFunction == IRP_MJ_DEVICE_CONTROL ||
-        MajorFunction == IRP_MJ_SHUTDOWN)
+NTAPI
+RawCheckForDismount(IN PVCB Vcb,
+                    IN BOOLEAN CreateOperation)
+{
+    KIRQL OldIrql;
+    PVPB Vpb;
+    BOOLEAN Delete;
+
+    /* Lock VPB */
+    IoAcquireVpbSpinLock(&OldIrql);
+
+    /* Reference it and check if a create is being done */
+    Vpb = Vcb->Vpb;
+    if (Vcb->Vpb->ReferenceCount != CreateOperation)
+    {
+        /* Don't do anything */
+        Delete = FALSE;
+    }
+    else
+    {
+        /* Otherwise, delete the volume */
+        Delete = TRUE;
+
+        /* Check if it has a VPB and unmount it */
+        if (Vpb->RealDevice->Vpb == Vpb)
         {
-          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
+            Vpb->DeviceObject = NULL;
+            Vpb->Flags &= ~VPB_MOUNTED;
         }
-      else if (MajorFunction != IRP_MJ_CLEANUP &&
-        MajorFunction != IRP_MJ_CLOSE &&
-        IoIsOperationSynchronous(Irp))
+    }
+
+    /* Release lock and return status */
+    IoReleaseVpbSpinLock(OldIrql);
+    return Delete;
+}
+
+NTSTATUS
+NTAPI
+RawCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp,
+                     IN PVOID Context)
+{
+    PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Check if this was a valid sync R/W request */
+    if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
+         (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) &&
+        ((IoStackLocation->FileObject)) &&
+         (FlagOn(IoStackLocation->FileObject->Flags, FO_SYNCHRONOUS_IO)) &&
+         (NT_SUCCESS(Irp->IoStatus.Status)))
+    {
+        /* Update byte offset */
+        IoStackLocation->FileObject->CurrentByteOffset.QuadPart +=
+            Irp->IoStatus.Information;
+    }
+
+    /* Mark the IRP Pending if it was */
+    if (Irp->PendingReturned) IoMarkIrpPending(Irp);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawClose(IN PVCB Vcb,
+         IN PIRP Irp,
+         IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    BOOLEAN Deleted = FALSE;
+    PAGED_CODE();
+
+    /* Make sure we can clean up */
+    Status = KeWaitForSingleObject(&Vcb->Mutex,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Decrease the open count and check if this is a dismount */
+    Vcb->OpenCount--;
+    if (!Vcb->OpenCount) Deleted = RawCheckForDismount(Vcb, FALSE);
+
+    /* Check if we should delete the device */
+    KeReleaseMutex(&Vcb->Mutex, FALSE);
+    if (Deleted)
+    {
+        /* Delete it */
+        IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
+                                                         VOLUME_DEVICE_OBJECT,
+                                                         Vcb));
+    }
+
+    /* Complete the request */
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawCreate(IN PVCB Vcb,
+          IN PIRP Irp,
+          IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    BOOLEAN Deleted = FALSE;
+    USHORT ShareAccess;
+    ACCESS_MASK DesiredAccess;
+    PAGED_CODE();
+
+    /* Make sure we can clean up */
+    Status = KeWaitForSingleObject(&Vcb->Mutex,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Check if this is a valid non-directory file open */
+    if ((!(IoStackLocation->FileObject) ||
+         !(IoStackLocation->FileObject->FileName.Length)) &&
+        ((IoStackLocation->Parameters.Create.Options >> 24) == FILE_OPEN) &&
+         (!(IoStackLocation->Parameters.Create.Options & FILE_DIRECTORY_FILE)))
+    {
+        /* Make sure the VCB isn't locked */
+        if (Vcb->VcbState & 1)
         {
-          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
+            /* Refuse the operation */
+            Status = STATUS_ACCESS_DENIED;
+            Irp->IoStatus.Information = 0;
         }
-    }
-  return IrpContext;
-}
-
-static VOID
-RawFsFreeIrpContext(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsFreeIrpContext(IrpContext 0x%p)\n", IrpContext);
-
-  ASSERT(IrpContext);
-
-  ExFreeToNPagedLookasideList(&IrpContextLookasideList, IrpContext);
-}
-
-static VOID
-STDCALL RawFsDoRequest(PVOID IrpContext)
-{
-  ULONG Count;
-
-  Count = InterlockedDecrement(&RawFsQueueCount);
-
-  DPRINT("RawFsDoRequest(IrpContext 0x%p), MajorFunction %x, %d\n",
-    IrpContext, ((PRAWFS_IRP_CONTEXT) IrpContext)->MajorFunction, Count);
-
-  RawFsDispatchRequest((PRAWFS_IRP_CONTEXT) IrpContext);
-}
-
-static NTSTATUS
-RawFsQueueRequest(PRAWFS_IRP_CONTEXT IrpContext)
-{
-  ULONG Count;
-
-  ASSERT(IrpContext != NULL);
-  ASSERT(IrpContext->Irp != NULL);
-
-  Count = InterlockedIncrement(&RawFsQueueCount);
-
-  DPRINT("RawFsQueueRequest (IrpContext 0x%p), %d\n", IrpContext, Count);
-
-  IrpContext->Flags |= IRPCONTEXT_CANWAIT;
-  IoMarkIrpPending (IrpContext->Irp);
-  ExInitializeWorkItem (&IrpContext->WorkQueueItem, RawFsDoRequest, IrpContext);
-  ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
-  return STATUS_PENDING;
-}
-
-static NTSTATUS
-RawFsClose(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsClose(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsCreateFile(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  PRAWFS_DEVICE_EXTENSION DeviceExt;
-  PRAWFS_GLOBAL_DATA GlobalData;
-  PIO_STACK_LOCATION IoSp;
-  PFILE_OBJECT FileObject;
-  ULONG RequestedDisposition;
-  ULONG RequestedOptions;
-  PRAWFS_FCB pFcb;
-  PRAWFS_CCB pCcb;
-
-  GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
-  IoSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
-  RequestedDisposition = ((IoSp->Parameters.Create.Options >> 24) & 0xff);
-  RequestedOptions = IoSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
-  FileObject = IoSp->FileObject;
-  DeviceExt = IrpContext->DeviceObject->DeviceExtension;
-
-  if (FileObject->FileName.Length == 0 &&
-      FileObject->RelatedFileObject == NULL)
-    {
-      /* This a open operation for the volume itself */
-      if (RequestedDisposition == FILE_CREATE
-    	    || RequestedDisposition == FILE_OVERWRITE_IF
-    	    || RequestedDisposition == FILE_SUPERSEDE)
-      	{
-      	  return STATUS_ACCESS_DENIED;
-      	}
-      if (RequestedOptions & FILE_DIRECTORY_FILE)
-      	{
-      	  return STATUS_NOT_A_DIRECTORY;
-      	}
-      pFcb = DeviceExt->VolumeFcb;
-      pCcb = RawFsNewCCB(GlobalData);
-      if (pCcb == NULL)
-      	{
-      	  return (STATUS_INSUFFICIENT_RESOURCES);
-      	}
-
-      FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
-      FileObject->FsContext = pFcb;
-      FileObject->FsContext2 = pCcb;
-      pFcb->RefCount++;
-
-      IrpContext->Irp->IoStatus.Information = FILE_OPENED;
-      return(STATUS_SUCCESS);
-    }
-
-  /* This filesystem driver only supports volume access */
-  return(STATUS_INVALID_PARAMETER);
-}
-
-static NTSTATUS
-RawFsCreate(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  NTSTATUS Status;
-
-  DPRINT("RawFsCreate(IrpContext 0x%p)\n", IrpContext);
-
-  ASSERT(IrpContext);
-
-  if (RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
-    {
-      /* DeviceObject represents FileSystem instead of logical volume */
-      DPRINT("RawFsCreate() called with file system\n");
-      IrpContext->Irp->IoStatus.Information = FILE_OPENED;
-      IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
-      IoCompleteRequest(IrpContext->Irp, IO_DISK_INCREMENT);
-      RawFsFreeIrpContext(IrpContext);
-      return STATUS_SUCCESS;
-    }
-
-  if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
-    {
-      return RawFsQueueRequest(IrpContext);
-    }
-
-  IrpContext->Irp->IoStatus.Information = 0;
-
-  Status = RawFsCreateFile(IrpContext);
-
-  IrpContext->Irp->IoStatus.Status = Status;
-  IoCompleteRequest(IrpContext->Irp,
-    (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
-  RawFsFreeIrpContext(IrpContext);
-
-  return Status;
-}
-
-static NTSTATUS
-RawFsRead(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsRead(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsWrite(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsWrite(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsMount(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  PRAWFS_GLOBAL_DATA GlobalData = NULL;
-  PDEVICE_OBJECT DeviceObject = NULL;
-  PRAWFS_DEVICE_EXTENSION DeviceExt = NULL;
-  PRAWFS_FCB VolumeFcb = NULL;
-  PRAWFS_FCB Fcb = NULL;
-  PARTITION_INFORMATION PartitionInfo;
-  DISK_GEOMETRY DiskGeometry;
-  LARGE_INTEGER VolumeSize;
-  NTSTATUS Status;
-  ULONG Size;
-
-  DPRINT("RawFsMount(IrpContext 0x%p)\n", IrpContext);
-
-  ASSERT(IrpContext);
-
-  if (!RawFsIsRawFileSystemDeviceObject(IrpContext->DeviceObject))
-    {
-      Status = STATUS_INVALID_DEVICE_REQUEST;
-      DPRINT("Not for me\n");
-      goto ByeBye;
-    }
-
-  GlobalData = (PRAWFS_GLOBAL_DATA) IrpContext->DeviceObject->DeviceExtension;
-
-  Status = IoCreateDevice(GlobalData->DriverObject,
-    sizeof(RAWFS_DEVICE_EXTENSION),
-    NULL,
-    FILE_DEVICE_FILE_SYSTEM,
-    0,
-    FALSE,
-    &DeviceObject);
-  if (!NT_SUCCESS(Status))
-    {
-      goto ByeBye;
-    }
-
-  DeviceObject->Flags |= DO_DIRECT_IO;
-  DeviceExt = (PVOID) DeviceObject->DeviceExtension;
-  RtlZeroMemory(DeviceExt, sizeof(RAWFS_DEVICE_EXTENSION));
-
-  /* Use same vpb as device disk */
-  DeviceObject->Vpb = IrpContext->Stack->Parameters.MountVolume.DeviceObject->Vpb;
-  DeviceExt->StorageDevice = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
-  DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
-  DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
-  DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
-  DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
-  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-
-  KeInitializeSpinLock(&DeviceExt->FcbListLock);
-  InitializeListHead(&DeviceExt->FcbListHead);
-
-  /* First try getting harddisk geometry then try getting CD-ROM geometry */
-  Size = sizeof(DISK_GEOMETRY);
-  Status = RawFsBlockDeviceIoControl(
-    IrpContext->Stack->Parameters.MountVolume.DeviceObject,
-    IOCTL_DISK_GET_DRIVE_GEOMETRY,
-    NULL,
-    0,
-    &DiskGeometry,
-    &Size);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("RawFsBlockDeviceIoControl failed with status 0x%.08x\n", Status);
-      goto ByeBye;
-    }
-  if (DiskGeometry.MediaType == FixedMedia)
-    {
-      // We have found a hard disk
-      Size = sizeof(PARTITION_INFORMATION);
-      Status = RawFsBlockDeviceIoControl(
-        IrpContext->Stack->Parameters.MountVolume.DeviceObject,
-        IOCTL_DISK_GET_PARTITION_INFO,
-        NULL,
-        0,
-        &PartitionInfo,
-        &Size);
-      if (!NT_SUCCESS(Status))
+        else
         {
-          DPRINT("RawFsBlockDeviceIoControl() failed (%x)\n", Status);
-          goto ByeBye;
+            /* Setup share access */
+            ShareAccess = IoStackLocation->Parameters.Create.ShareAccess;
+            DesiredAccess = IoStackLocation->Parameters.Create.
+                            SecurityContext->DesiredAccess;
+
+            /* Check if this VCB was already opened */
+            if (Vcb->OpenCount > 0)
+            {
+                /* Try to see if we have access to it */
+                Status = IoCheckShareAccess(DesiredAccess,
+                                            ShareAccess,
+                                            IoStackLocation->FileObject,
+                                            &Vcb->ShareAccess,
+                                            TRUE);
+                if (!NT_SUCCESS(Status)) Irp->IoStatus.Information = 0;
+            }
+
+            /* Make sure we have access */
+            if (NT_SUCCESS(Status))
+            {
+                /* Check if this is the first open */
+                if (!Vcb->OpenCount)
+                {
+                    /* Set the share access */
+                    IoSetShareAccess(DesiredAccess,
+                                     ShareAccess,
+                                     IoStackLocation->FileObject,
+                                     &Vcb->ShareAccess);
+                }
+
+                /* Increase the open count and set the VPB */
+                Vcb->OpenCount += 1;
+                IoStackLocation->FileObject->Vpb = Vcb->Vpb;
+
+                /* Set IRP status and disable intermediate buffering */
+                Status = STATUS_SUCCESS;
+                Irp->IoStatus.Information = FILE_OPENED;
+                IoStackLocation->FileObject->Flags |=
+                    FO_NO_INTERMEDIATE_BUFFERING;
+            }
         }
-#ifndef NDEBUG
-      DbgPrint("Partition Information:\n");
-      DbgPrint("StartingOffset      %u\n", PartitionInfo.StartingOffset.QuadPart);
-      DbgPrint("PartitionLength     %u\n", PartitionInfo.PartitionLength.QuadPart);
-      DbgPrint("HiddenSectors       %u\n", PartitionInfo.HiddenSectors);
-      DbgPrint("PartitionNumber     %u\n", PartitionInfo.PartitionNumber);
-      DbgPrint("PartitionType       %u\n", PartitionInfo.PartitionType);
-      DbgPrint("BootIndicator       %u\n", PartitionInfo.BootIndicator);
-      DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
-      DbgPrint("RewritePartition    %u\n", PartitionInfo.RewritePartition);
+    }
+    else
+    {
+        /* Invalid create request */
+        Status = STATUS_INVALID_PARAMETER;
+        Irp->IoStatus.Information = 0;
+    }
+
+    /* Check if the request failed */
+    if (!(NT_SUCCESS(Status)) && !(Vcb->OpenCount))
+    {
+        /* Check if we can dismount the device */
+        Deleted = RawCheckForDismount(Vcb, FALSE);
+    }
+
+    /* Check if we should delete the device */
+    KeReleaseMutex(&Vcb->Mutex, FALSE);
+    if (Deleted)
+    {
+        /* Delete it */
+        IoDeleteDevice((PDEVICE_OBJECT)CONTAINING_RECORD(Vcb,
+                                                         VOLUME_DEVICE_OBJECT,
+                                                         Vcb));
+    }
+
+    /* Complete the request */
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawReadWriteDeviceControl(IN PVCB Vcb,
+                          IN PIRP Irp,
+                          IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Don't do anything if the request was 0 bytes */
+    if (((IoStackLocation->MajorFunction == IRP_MJ_READ) ||
+         (IoStackLocation->MajorFunction == IRP_MJ_WRITE)) &&
+        !(IoStackLocation->Parameters.Read.Length))
+    {
+        /* Complete it */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+        return STATUS_SUCCESS;
+    }
+
+    /* Copy the IRP stack location */
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+
+    /* Disable verifies */
+    IoGetNextIrpStackLocation(Irp)->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
+
+    /* Setup a completion routine */
+    IoSetCompletionRoutine(Irp,
+                           RawCompletionRoutine,
+                           NULL,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    /* Call the next driver and exit */
+    Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawMountVolume(IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    PDEVICE_OBJECT DeviceObject;
+    PVOLUME_DEVICE_OBJECT Volume;
+    PAGED_CODE();
+
+    /* Remember our owner */
+    DeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject;
+
+    /* Create the volume */
+    Status = IoCreateDevice(RawDiskDeviceObject->DriverObject,
+                            sizeof(VOLUME_DEVICE_OBJECT) -
+                            sizeof(DEVICE_OBJECT),
+                            NULL,
+                            FILE_DEVICE_DISK_FILE_SYSTEM,
+                            0,
+                            FALSE,
+                            (PDEVICE_OBJECT*)&Volume);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Use highest alignment requirement */
+    Volume->DeviceObject.AlignmentRequirement = max(DeviceObject->
+                                                    AlignmentRequirement,
+                                                    Volume->DeviceObject.
+                                                    AlignmentRequirement);
+
+    /* Setup the VCB */
+    RawInitializeVcb(&Volume->Vcb,
+                     IoStackLocation->Parameters.MountVolume.DeviceObject,
+                     IoStackLocation->Parameters.MountVolume.Vpb);
+
+    /* Set dummy label and serial number */
+    Volume->Vcb.Vpb->SerialNumber = 0xFFFFFFFF;
+    Volume->Vcb.Vpb->VolumeLabelLength = 0;
+
+    /* Setup the DO */
+    Volume->Vcb.Vpb->DeviceObject = &Volume->DeviceObject;
+    Volume->DeviceObject.StackSize = DeviceObject->StackSize + 1;
+    Volume->DeviceObject.SectorSize = DeviceObject->SectorSize;
+    Volume->DeviceObject.Flags |= DO_DIRECT_IO;
+    Volume->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawUserFsCtrl(IN PIO_STACK_LOCATION IoStackLocation,
+              IN PVCB Vcb)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Lock the device */
+    Status = KeWaitForSingleObject(&Vcb->Mutex,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Check what kind of request this is */
+    switch (IoStackLocation->Parameters.FileSystemControl.FsControlCode)
+    {
+        /* Oplock requests */
+        case FSCTL_REQUEST_OPLOCK_LEVEL_1:
+        case FSCTL_REQUEST_OPLOCK_LEVEL_2:
+        case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
+        case FSCTL_OPLOCK_BREAK_NOTIFY:
+
+            /* We don't handle them */
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+        /* Lock request */
+        case FSCTL_LOCK_VOLUME:
+
+            /* Make sure we're not locked, and that we're alone */
+            if (!(Vcb->VcbState & 1) && (Vcb->OpenCount == 1))
+            {
+                /* Lock the VCB */
+                Vcb->VcbState |= 1;
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                /* Otherwise, we can't do this */
+                Status = STATUS_ACCESS_DENIED;
+            }
+            break;
+
+        /* Unlock request */
+        case FSCTL_UNLOCK_VOLUME:
+
+            /* Make sure we're locked */
+            if (!(Vcb->VcbState & 1))
+            {
+                /* Let caller know we're not */
+                Status = STATUS_NOT_LOCKED;
+            }
+            else
+            {
+                /* Unlock the VCB */
+                Vcb->VcbState &= ~1;
+                Status = STATUS_SUCCESS;
+            }
+            break;
+
+        /* Dismount request */
+        case FSCTL_DISMOUNT_VOLUME:
+
+            /* Make sure we're locked */
+            if (Vcb->VcbState & 1)
+            {
+                /* Do nothing, just return success */
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                /* We can't dismount, device not locked */
+                Status = STATUS_ACCESS_DENIED;
+            }
+            break;
+
+        /* Unknown request */
+        default:
+
+            /* Fail */
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+
+    /* Unlock device and return */
+    KeReleaseMutex(&Vcb->Mutex, FALSE);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawFileSystemControl(IN PVCB Vcb,
+                     IN PIRP Irp,
+                     IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Check the kinds of FSCTLs that we support */
+    switch (IoStackLocation->MinorFunction)
+    {
+        /* User-mode request */
+        case IRP_MN_USER_FS_REQUEST:
+
+            /* Handle it */
+            Status = RawUserFsCtrl(IoStackLocation, Vcb);
+            break;
+
+        /* Mount request */
+        case IRP_MN_MOUNT_VOLUME:
+
+            /* Mount the volume */
+            Status = RawMountVolume(IoStackLocation);
+            break;
+
+        case IRP_MN_VERIFY_VOLUME:
+
+            /* We don't do verifies */
+            Status = STATUS_WRONG_VOLUME;
+            Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
+
+            /* Check if we should delete the device */
+            if (RawCheckForDismount(Vcb, FALSE))
+            {
+                /* Do it */
+                IoDeleteDevice((PDEVICE_OBJECT)
+                               CONTAINING_RECORD(Vcb,
+                                                 VOLUME_DEVICE_OBJECT,
+                                                 Vcb));
+            }
+
+            /* We're done */
+            break;
+
+        /* Invalid request */
+        default:
+
+            /* Fail it */
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
+    }
+
+    /* Complete the request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawQueryInformation(IN PVCB Vcb,
+                    IN PIRP Irp,
+                    IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+    PULONG Length;
+    PFILE_POSITION_INFORMATION Buffer;
+    PAGED_CODE();
+
+    /* Get information from the IRP */
+    Length = &IoStackLocation->Parameters.QueryFile.Length;
+    Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+    /* We only handle this request */
+    if (IoStackLocation->Parameters.QueryFile.FileInformationClass ==
+        FilePositionInformation)
+    {
+        /* Validate buffer size */
+        if (*Length < sizeof(FILE_POSITION_INFORMATION))
+        {
+            /* Invalid, fail */
+            Irp->IoStatus.Information = 0;
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        else
+        {
+            /* Get offset and update length */
+            Buffer->CurrentByteOffset = IoStackLocation->FileObject->
+                                        CurrentByteOffset;
+            *Length -= sizeof(FILE_POSITION_INFORMATION);
+
+            /* Set IRP Status information */
+            Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
+            Status = STATUS_SUCCESS;
+        }
+    }
+
+    /* Complete it */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawSetInformation(IN PVCB Vcb,
+                  IN PIRP Irp,
+                  IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+    PULONG Length;
+    PFILE_POSITION_INFORMATION Buffer;
+    PDEVICE_OBJECT DeviceObject;
+    PAGED_CODE();
+
+    /* Get information from the IRP */
+    Length = &IoStackLocation->Parameters.QueryFile.Length;
+    Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+    /* We only handle this request */
+    if (IoStackLocation->Parameters.QueryFile.FileInformationClass ==
+        FilePositionInformation)
+    {
+        /* Get the DO */
+        DeviceObject = IoGetRelatedDeviceObject(IoStackLocation->FileObject);
+
+        /* Make sure the offset is aligned */
+        if ((Buffer->CurrentByteOffset.LowPart &
+            DeviceObject->AlignmentRequirement))
+        {
+            /* It's not, fail */
+            Status = STATUS_INVALID_PARAMETER;
+        }
+        else
+        {
+            /* Otherwise, set offset */
+            IoStackLocation->FileObject->CurrentByteOffset = Buffer->
+                                                             CurrentByteOffset;
+
+            /* Set IRP Status information */
+            Status = STATUS_SUCCESS;
+        }
+    }
+
+    /* Complete it */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawQueryFsVolumeInfo(IN PVCB Vcb,
+                     IN PFILE_FS_VOLUME_INFORMATION Buffer,
+                     IN OUT PULONG Length)
+{
+    PAGED_CODE();
+
+    /* Clear the buffer and stub it out */
+    RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
+    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
+    Buffer->SupportsObjects = FALSE;
+    Buffer->VolumeLabelLength = 0;
+
+    /* Return length and success */
+    *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawQueryFsSizeInfo(IN PVCB Vcb,
+                   IN PFILE_FS_SIZE_INFORMATION Buffer,
+                   IN OUT PULONG Length)
+{
+    PIRP Irp;
+    KEVENT Event;
+    NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    PDEVICE_OBJECT RealDevice;
+    DISK_GEOMETRY DiskGeometry;
+    PARTITION_INFORMATION PartitionInformation;
+    BOOLEAN DiskHasPartitions;
+    PAGED_CODE();
+
+    /* Validate the buffer */
+    if (*Length < sizeof(FILE_FS_SIZE_INFORMATION))
+    {
+        /* Fail */
+        return STATUS_BUFFER_OVERFLOW;
+    }
+
+    /* Clear the buffer, initialize the event and set the DO */
+    RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    RealDevice = Vcb->Vpb->RealDevice;
+
+    /* Build query IRP */
+    Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
+                                        RealDevice,
+                                        NULL,
+                                        0,
+                                        &DiskGeometry,
+                                        sizeof(DISK_GEOMETRY),
+                                        FALSE,
+                                        &Event,
+                                        &IoStatusBlock);
+
+    /* Call driver and check if we're pending */
+    Status = IoCallDriver(RealDevice, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        /* Wait on driver to finish */
+        KeWaitForSingleObject(&Event,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+        Status = IoStatusBlock.Status;
+    }
+
+    /* Fail if we couldn't get CHS data */
+    if (!NT_SUCCESS(Status))
+    {
+        *Length = 0;
+        return Status;
+    }
+
+    /* Check if this is a floppy */
+    if (FlagOn(RealDevice->Characteristics, FILE_FLOPPY_DISKETTE))
+    {
+        /* Floppies don't have partitions */
+        DiskHasPartitions = FALSE;
+    }
+    else
+    {
+        /* Setup query IRP */
+        KeResetEvent(&Event);
+        Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
+                                            RealDevice,
+                                            NULL,
+                                            0,
+                                            &PartitionInformation,
+                                            sizeof(PARTITION_INFORMATION),
+                                            FALSE,
+                                            &Event,
+                                            &IoStatusBlock);
+
+        /* Call driver and check if we're pending */
+        Status = IoCallDriver(RealDevice, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            /* Wait on driver to finish */
+            KeWaitForSingleObject(&Event,
+                                  Executive,
+                                  KernelMode,
+                                  FALSE,
+                                  NULL);
+            Status = IoStatusBlock.Status;
+        }
+
+        /* If this was an invalid request, then the disk is not partitioned */
+        if (Status == STATUS_INVALID_DEVICE_REQUEST)
+        {
+            DiskHasPartitions = FALSE;
+        }
+        else
+        {
+            /* Otherwise, it must be */
+            ASSERT(NT_SUCCESS(Status));
+            DiskHasPartitions = TRUE;
+        }
+    }
+
+    /* Set sector data */
+    Buffer->BytesPerSector = DiskGeometry.BytesPerSector;
+    Buffer->SectorsPerAllocationUnit = 1;
+
+    /* Calculate allocation units */
+    if (DiskHasPartitions)
+    {
+        /* Use partition data */
+        Buffer->TotalAllocationUnits =
+            RtlExtendedLargeIntegerDivide(PartitionInformation.PartitionLength,
+                                          DiskGeometry.BytesPerSector,
+                                          NULL);
+    }
+    else
+    {
+        /* Use CHS */
+        Buffer->TotalAllocationUnits =
+            RtlExtendedIntegerMultiply(DiskGeometry.Cylinders,
+                                       DiskGeometry.TracksPerCylinder *
+                                       DiskGeometry.SectorsPerTrack);
+    }
+
+    /* Set available units */
+    Buffer->AvailableAllocationUnits = Buffer->TotalAllocationUnits;
+
+    /* Return length and success */
+    *Length -= sizeof(FILE_FS_SIZE_INFORMATION);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawQueryFsDeviceInfo(IN PVCB Vcb,
+                     IN PFILE_FS_DEVICE_INFORMATION Buffer,
+                     IN OUT PULONG Length)
+{
+    PAGED_CODE();
+
+    /* Validate buffer */
+    if (*Length < sizeof(FILE_FS_DEVICE_INFORMATION))
+    {
+        /* Fail */
+        return STATUS_BUFFER_OVERFLOW;
+    }
+
+    /* Clear buffer and write information */
+    RtlZeroMemory(Buffer, sizeof(FILE_FS_DEVICE_INFORMATION));
+    Buffer->DeviceType = FILE_DEVICE_DISK;
+    Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
+
+    /* Return length and success */
+    *Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawQueryFsAttributeInfo(IN PVCB Vcb,
+                        IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
+                        IN OUT PULONG Length)
+{
+    ULONG ReturnLength;
+    PAGED_CODE();
+
+    /* Check if the buffer is large enough for our name ("RAW") */
+    ReturnLength = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION,
+                                FileSystemName[0]);
+    ReturnLength += sizeof(L"RAW");
+    if (*Length < ReturnLength) return STATUS_BUFFER_OVERFLOW;
+
+    /* Output the data */
+    Buffer->FileSystemAttributes = 0;
+    Buffer->MaximumComponentNameLength = 0;
+    Buffer->FileSystemNameLength = 6;
+    RtlMoveMemory(&Buffer->FileSystemName[0], L"RAW", 6);
+
+    /* Return length and success */
+    *Length -= ReturnLength;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawQueryVolumeInformation(IN PVCB Vcb,
+                          IN PIRP Irp,
+                          IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    ULONG Length;
+    PVOID Buffer;
+    PAGED_CODE();
+
+    /* Get IRP Data */
+    Length = IoStackLocation->Parameters.QueryVolume.Length;
+    Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+    /* Check the kind of request */
+    switch (IoStackLocation->Parameters.QueryVolume.FsInformationClass)
+    {
+        /* Volume information request */
+        case FileFsVolumeInformation:
+
+            Status = RawQueryFsVolumeInfo(Vcb, Buffer, &Length);
+            break;
+
+        /* File system size invormation */
+        case FileFsSizeInformation:
+
+            Status = RawQueryFsSizeInfo(Vcb, Buffer, &Length);
+            break;
+
+        /* Device information */
+        case FileFsDeviceInformation:
+
+            Status = RawQueryFsDeviceInfo(Vcb, Buffer, &Length);
+            break;
+
+        /* Attribute information */
+        case FileFsAttributeInformation:
+
+            Status = RawQueryFsAttributeInfo(Vcb, Buffer, &Length);
+            break;
+
+        /* Invalid request */
+        default:
+
+            /* Fail it */
+            Status = STATUS_INVALID_PARAMETER;
+            break;
+    }
+
+    /* Set status and complete the request */
+    Irp->IoStatus.Information = IoStackLocation->
+                                Parameters.QueryVolume.Length - Length;
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawCleanup(IN PVCB Vcb,
+           IN PIRP Irp,
+           IN PIO_STACK_LOCATION IoStackLocation)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Make sure we can clean up */
+    Status = KeWaitForSingleObject(&Vcb->Mutex,
+                                   Executive,
+                                   KernelMode,
+                                   FALSE,
+                                   NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Remove shared access and complete the request */
+    IoRemoveShareAccess(IoStackLocation->FileObject, &Vcb->ShareAccess);
+    KeReleaseMutex(&Vcb->Mutex, FALSE);
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RawDispatch(IN PVOLUME_DEVICE_OBJECT DeviceObject,
+            IN PIRP Irp)
+{
+    NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+    PIO_STACK_LOCATION IoStackLocation;
+    PVCB Vcb;
+    PAGED_CODE();
+
+    /* Get the stack location */
+    IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    /* Differentiate between Volume DO and FS DO */
+    if ((((PDEVICE_OBJECT)DeviceObject)->Size == sizeof(DEVICE_OBJECT)) &&
+        !((IoStackLocation->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
+          (IoStackLocation->MinorFunction == IRP_MN_MOUNT_VOLUME)))
+    {
+        /* This is an FS DO. Stub out the common calls */
+        if ((IoStackLocation->MajorFunction == IRP_MJ_CREATE) ||
+            (IoStackLocation->MajorFunction == IRP_MJ_CLEANUP) ||
+            (IoStackLocation->MajorFunction == IRP_MJ_CLOSE))
+        {
+            /* Return success for them */
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            /* Anything else, we don't support */
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+        }
+
+        /* Complete the request */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+        return Status;
+    }
+
+    /* Otherwise, get our VCB and start handling the IRP */
+    FsRtlEnterFileSystem();
+    Vcb = &DeviceObject->Vcb;
+
+    /* Check what kind of IRP this is */
+    switch (IoStackLocation->MajorFunction)
+    {
+        /* Cleanup request */
+        case IRP_MJ_CLEANUP:
+
+            Status = RawCleanup(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Close request */
+        case IRP_MJ_CLOSE:
+
+            Status = RawClose(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Create request */
+        case IRP_MJ_CREATE:
+
+            Status = RawCreate(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* FSCTL request */
+        case IRP_MJ_FILE_SYSTEM_CONTROL:
+
+            Status = RawFileSystemControl(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* R/W or IOCTL request */
+        case IRP_MJ_READ:
+        case IRP_MJ_WRITE:
+        case IRP_MJ_DEVICE_CONTROL:
+
+            Status = RawReadWriteDeviceControl(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Information query request */
+        case IRP_MJ_QUERY_INFORMATION:
+
+            Status = RawQueryInformation(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Information set request */
+        case IRP_MJ_SET_INFORMATION:
+
+            Status = RawSetInformation(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Volume information request */
+        case IRP_MJ_QUERY_VOLUME_INFORMATION:
+
+            Status = RawQueryVolumeInformation(Vcb, Irp, IoStackLocation);
+            break;
+
+        /* Unexpected request */
+        default:
+
+            /* Anything else is pretty bad */
+            KeBugCheck(FILE_SYSTEM);
+    }
+
+    /* Return the status */
+    FsRtlExitFileSystem();
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+RawShutdown(IN PDEVICE_OBJECT DeviceObject,
+            IN PIRP Irp)
+{
+    /* Unregister file systems */
+#if 0 // FIXME: This freezes ROS at shutdown. PnP Problem?
+    IoUnregisterFileSystem(RawDiskDeviceObject);
+    IoUnregisterFileSystem(RawCdromDeviceObject);
+    IoUnregisterFileSystem(RawTapeDeviceObject);
+
+    /* Delete the devices */
+    IoDeleteDevice(RawDiskDeviceObject);
+    IoDeleteDevice(RawCdromDeviceObject);
+    IoDeleteDevice(RawTapeDeviceObject);
 #endif
-      VolumeSize.QuadPart = PartitionInfo.PartitionLength.QuadPart;
-    }
-  else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType <= RemovableMedia)
-    {
-      Status = STATUS_UNRECOGNIZED_VOLUME;
-      goto ByeBye;
-    }
-
-  VolumeFcb = RawFsNewFCB(GlobalData);
-  if (VolumeFcb == NULL)
-    {
-      Status = STATUS_INSUFFICIENT_RESOURCES;
-      goto ByeBye;
-    }
-
-  VolumeFcb->Flags = FCB_IS_VOLUME;
-  VolumeFcb->RFCB.FileSize.QuadPart = VolumeSize.QuadPart;
-  VolumeFcb->RFCB.ValidDataLength.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
-  VolumeFcb->RFCB.AllocationSize.QuadPart = VolumeFcb->RFCB.FileSize.QuadPart;
-  DeviceExt->VolumeFcb = VolumeFcb;
-
-  KeEnterCriticalRegion();
-  ExAcquireResourceExclusiveLite(&GlobalData->VolumeListLock, TRUE);
-  InsertHeadList(&GlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
-  ExReleaseResourceLite(&GlobalData->VolumeListLock);
-  KeLeaveCriticalRegion();
-
-  /* No serial number */
-  DeviceObject->Vpb->SerialNumber = 0;
-
-  /* Set volume label (no label) */
-  *(DeviceObject->Vpb->VolumeLabel) = 0;
-  DeviceObject->Vpb->VolumeLabelLength = 0;
-
-  Status = STATUS_SUCCESS;
-
-ByeBye:
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("RAWFS: RawFsMount() Status 0x%.08x\n", Status);
-
-      if (Fcb)
-        RawFsDestroyFCB(GlobalData, Fcb);
-      if (DeviceObject)
-        IoDeleteDevice(DeviceObject);
-      if (VolumeFcb)
-        RawFsDestroyFCB(GlobalData, VolumeFcb);
-    }
-  return Status;
-}
-
-static NTSTATUS
-RawFsFileSystemControl(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  NTSTATUS Status;
-
-  DPRINT("RawFsFileSystemControl(IrpContext 0x%p)\n", IrpContext);
-
-  ASSERT(IrpContext);
-
-  switch (IrpContext->MinorFunction)
-    {
-      case IRP_MN_USER_FS_REQUEST:
-        DPRINT("RawFs FSC: IRP_MN_USER_FS_REQUEST\n");
-        Status = STATUS_INVALID_DEVICE_REQUEST;
-        break;
-
-      case IRP_MN_MOUNT_VOLUME:
-        DPRINT("RawFs FSC: IRP_MN_MOUNT_VOLUME\n");
-        Status = RawFsMount(IrpContext);
-        break;
-
-      case IRP_MN_VERIFY_VOLUME:
-        DPRINT("RawFs FSC: IRP_MN_VERIFY_VOLUME\n");
-        Status = STATUS_INVALID_DEVICE_REQUEST;
-        break;
-
-      default:
-        DPRINT("RawFs FSC: MinorFunction %d\n", IrpContext->MinorFunction);
-        Status = STATUS_INVALID_DEVICE_REQUEST;
-        break;
-    }
-
-  IrpContext->Irp->IoStatus.Status = Status;
-  IrpContext->Irp->IoStatus.Information = 0;
-
-  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
-  RawFsFreeIrpContext(IrpContext);
-  return Status;
-}
-
-static NTSTATUS
-RawFsQueryInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsQueryInformation(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsSetInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsSetInformation(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsDirectoryControl(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsDirectoryControl(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsQueryVolumeInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsQueryVolumeInformation(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsSetVolumeInformation(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsSetVolumeInformation(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsLockControl(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsLockControl(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsCleanup(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsCleanup(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsFlush(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsFlush(IrpContext 0x%p)\n", IrpContext);
-  UNIMPLEMENTED;
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS STDCALL
-RawFsShutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
-{
-  DPRINT("RawFsShutdown(DeviceObject 0x%p, Irp 0x%p)\n", DeviceObject, Irp);
-
-  /*
-   * Note: Do NOT call UNIMPLEMENTED here!
-   * This function must finish in order to shutdown ReactOS properly!
-   */
-
-  return STATUS_NOT_IMPLEMENTED;
-}
-
-static NTSTATUS
-RawFsDispatchRequest(IN PRAWFS_IRP_CONTEXT IrpContext)
-{
-  DPRINT("RawFsDispatchRequest(IrpContext 0x%p), MajorFunction %x\n",
-    IrpContext, IrpContext->MajorFunction);
-
-  ASSERT(IrpContext);
-
-  switch (IrpContext->MajorFunction)
-    {
-      case IRP_MJ_CLOSE:
-        return RawFsClose(IrpContext);
-      case IRP_MJ_CREATE:
-        return RawFsCreate (IrpContext);
-      case IRP_MJ_READ:
-        return RawFsRead (IrpContext);
-      case IRP_MJ_WRITE:
-        return RawFsWrite (IrpContext);
-      case IRP_MJ_FILE_SYSTEM_CONTROL:
-        return RawFsFileSystemControl(IrpContext);
-      case IRP_MJ_QUERY_INFORMATION:
-        return RawFsQueryInformation (IrpContext);
-      case IRP_MJ_SET_INFORMATION:
-        return RawFsSetInformation (IrpContext);
-      case IRP_MJ_DIRECTORY_CONTROL:
-        return RawFsDirectoryControl(IrpContext);
-      case IRP_MJ_QUERY_VOLUME_INFORMATION:
-        return RawFsQueryVolumeInformation(IrpContext);
-      case IRP_MJ_SET_VOLUME_INFORMATION:
-        return RawFsSetVolumeInformation(IrpContext);
-      case IRP_MJ_LOCK_CONTROL:
-        return RawFsLockControl(IrpContext);
-      case IRP_MJ_CLEANUP:
-        return RawFsCleanup(IrpContext);
-      case IRP_MJ_FLUSH_BUFFERS:
-        return RawFsFlush(IrpContext);
-      default:
-        DPRINT1("Unexpected major function %x\n", IrpContext->MajorFunction);
-        IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
-        IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
-        RawFsFreeIrpContext(IrpContext);
-        return STATUS_DRIVER_INTERNAL_ERROR;
-    }
-}
-
-static NTSTATUS STDCALL
-RawFsBuildRequest(IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp)
-{
-  PRAWFS_IRP_CONTEXT IrpContext;
-  NTSTATUS Status;
-
-  DPRINT("RawFsBuildRequest(DeviceObject 0x%p, Irp 0x%p)\n", DeviceObject, Irp);
-
-  ASSERT(DeviceObject);
-  ASSERT(Irp);
-
-  IrpContext = RawFsAllocateIrpContext(DeviceObject, Irp);
-  if (IrpContext == NULL)
-    {
-      Status = STATUS_INSUFFICIENT_RESOURCES;
-      Irp->IoStatus.Status = Status;
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    }
-  else
-    {
-      if (KeGetCurrentIrql() <= PASSIVE_LEVEL)
-        {
-          FsRtlEnterFileSystem();
-        }
-      else
-        {
-          DPRINT1("RawFs is entered at irql = %d\n", KeGetCurrentIrql());
-        }
-      Status = RawFsDispatchRequest(IrpContext);
-      if (KeGetCurrentIrql() <= PASSIVE_LEVEL)
-        {
-          FsRtlExitFileSystem();
-        }
-    }
-  return Status;
-}
-
-NTSTATUS STDCALL
+
+    /* Complete the request */
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+RawUnload(IN PDRIVER_OBJECT DriverObject)
+{
+#if 0 // FIXME: DriverUnload is never called
+    /* Dereference device objects */
+    ObDereferenceObject(RawDiskDeviceObject);
+    ObDereferenceObject(RawCdromDeviceObject);
+    ObDereferenceObject(RawTapeDeviceObject);
+#endif
+}
+
+NTSTATUS
+NTAPI
 RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject,
-  IN PUNICODE_STRING RegistryPath)
-{
-  PRAWFS_GLOBAL_DATA DeviceData;
-  NTSTATUS Status;
-
-  RawFsDriverObject = DriverObject;
-
-  Status = IoCreateDevice(DriverObject,
-    sizeof(RAWFS_GLOBAL_DATA),
-    NULL,
-    FILE_DEVICE_DISK_FILE_SYSTEM,
-    0,
-    FALSE,
-    &DiskDeviceObject);
-  if (!NT_SUCCESS(Status))
-    {
-      CPRINT("IoCreateDevice() failed with status 0x%.08x\n", Status);
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-      return(Status);
-    }
-  DeviceData = DiskDeviceObject->DeviceExtension;
-  RtlZeroMemory(DeviceData, sizeof(RAWFS_GLOBAL_DATA));
-  DeviceData->DriverObject = DriverObject;
-  DeviceData->DeviceObject = DiskDeviceObject;
-  DiskDeviceObject->Flags |= DO_DIRECT_IO;
-
-
-  Status = IoCreateDevice(DriverObject,
-    sizeof(RAWFS_GLOBAL_DATA),
-    NULL,
-    FILE_DEVICE_CD_ROM_FILE_SYSTEM,
-    0,
-    FALSE,
-    &CdromDeviceObject);
-  if (!NT_SUCCESS(Status))
-    {
-      CPRINT("IoCreateDevice() failed with status 0x%.08x\n", Status);
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-      return(Status);
-    }
-  DeviceData = CdromDeviceObject->DeviceExtension;
-  RtlZeroMemory (DeviceData, sizeof(RAWFS_GLOBAL_DATA));
-  DeviceData->DriverObject = DriverObject;
-  DeviceData->DeviceObject = CdromDeviceObject;
-  CdromDeviceObject->Flags |= DO_DIRECT_IO;
-
-
-  Status = IoCreateDevice(DriverObject,
-    sizeof(RAWFS_GLOBAL_DATA),
-    NULL,
-    FILE_DEVICE_TAPE_FILE_SYSTEM,
-    0,
-    FALSE,
-    &TapeDeviceObject);
-  if (!NT_SUCCESS(Status))
-    {
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-      return(Status);
-    }
-  DeviceData = TapeDeviceObject->DeviceExtension;
-  RtlZeroMemory (DeviceData, sizeof(RAWFS_GLOBAL_DATA));
-  DeviceData->DriverObject = DriverObject;
-  DeviceData->DeviceObject = TapeDeviceObject;
-  TapeDeviceObject->Flags |= DO_DIRECT_IO;
-
-
-  DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH) RawFsShutdown;
-  DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH) RawFsBuildRequest;
-  DriverObject->DriverUnload = NULL;
-
-  ExInitializeNPagedLookasideList(&IrpContextLookasideList,
-    NULL, NULL, 0, sizeof(RAWFS_IRP_CONTEXT), TAG_IRP, 0);
-
-
-  IoRegisterFileSystem(DiskDeviceObject);
-  IoRegisterFileSystem(CdromDeviceObject);
-  IoRegisterFileSystem(TapeDeviceObject);
-
-  return STATUS_SUCCESS;
+                 IN PUNICODE_STRING RegistryPath)
+{
+    UNICODE_STRING DeviceName;
+    NTSTATUS Status;
+
+    /* Create the raw disk device */
+    RtlInitUnicodeString(&DeviceName, L"\\Device\\RawDisk");
+    Status = IoCreateDevice(DriverObject,
+                            0,
+                            NULL,
+                            FILE_DEVICE_DISK_FILE_SYSTEM,
+                            0,
+                            FALSE,
+                            &RawDiskDeviceObject);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Create the raw CDROM device */
+    RtlInitUnicodeString(&DeviceName, L"\\Device\\RawCdRom");
+    Status = IoCreateDevice(DriverObject,
+                            0,
+                            NULL,
+                            FILE_DEVICE_CD_ROM_FILE_SYSTEM,
+                            0,
+                            FALSE,
+                            &RawCdromDeviceObject);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Create the raw tape device */
+    RtlInitUnicodeString(&DeviceName, L"\\Device\\RawTape");
+    Status = IoCreateDevice(DriverObject,
+                            0,
+                            NULL,
+                            FILE_DEVICE_TAPE_FILE_SYSTEM,
+                            0,
+                            FALSE,
+                            &RawTapeDeviceObject);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Set Direct I/O for all devices */
+    RawDiskDeviceObject->Flags |= DO_DIRECT_IO;
+    RawCdromDeviceObject->Flags |= DO_DIRECT_IO;
+    RawTapeDeviceObject->Flags |= DO_DIRECT_IO;
+
+    /* Set generic stubs */
+    DriverObject->MajorFunction[IRP_MJ_CREATE] =
+    DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] =
+    DriverObject->MajorFunction[IRP_MJ_READ] =
+    DriverObject->MajorFunction[IRP_MJ_WRITE] =
+    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
+    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
+    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
+    DriverObject->MajorFunction[IRP_MJ_CLEANUP] =
+    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)RawDispatch;
+
+    /* Shutdown and unload */
+    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = RawShutdown;
+    DriverObject->DriverUnload = RawUnload;
+
+    /* Register the file systems */
+    IoRegisterFileSystem(RawDiskDeviceObject);
+    IoRegisterFileSystem(RawCdromDeviceObject);
+    IoRegisterFileSystem(RawTapeDeviceObject);
+
+#if 0 // FIXME: DriverUnload is never called
+    /* Reference device objects */
+    ObReferenceObject(RawDiskDeviceObject);
+    ObReferenceObject(RawCdromDeviceObject);
+    ObReferenceObject(RawTapeDeviceObject);
+#endif
+    return STATUS_SUCCESS;
 }
 
 /* EOF */




More information about the Ros-diffs mailing list