Fixed an uninitialized variable error.
[reactos.git] / reactos / ntoskrnl / io / vpb.c
index df168e9..f7d0722 100644 (file)
@@ -4,7 +4,7 @@
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/vpb.c
  * PURPOSE:         Volume Parameter Block managment
- * 
+ *
  * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
@@ -18,9 +18,6 @@
 
 static KSPIN_LOCK IoVpbLock;
 
-#define TAG_VPB    TAG('V', 'P', 'B', ' ')
-#define TAG_SYSB   TAG('S', 'Y', 'S', 'B')
-
 /* FUNCTIONS *****************************************************************/
 
 VOID INIT_FUNCTION
@@ -30,41 +27,36 @@ IoInitVpbImplementation(VOID)
 }
 
 NTSTATUS
-IoAttachVpb(PDEVICE_OBJECT DeviceObject)
+STDCALL
+IopAttachVpb(PDEVICE_OBJECT DeviceObject)
 {
-   PVPB Vpb;
-   
-   Vpb = ExAllocatePoolWithTag(NonPagedPool,
-                              sizeof(VPB),
-                              TAG_VPB);
-   if (Vpb == NULL)
-     {
-       return(STATUS_UNSUCCESSFUL);
-     }
-   
-   Vpb->Type = 0;
-   Vpb->Size = sizeof(VPB) / sizeof(DWORD);
-   Vpb->Flags = 0;
-   Vpb->VolumeLabelLength = 0;
-   Vpb->DeviceObject = NULL;
-   Vpb->RealDevice = DeviceObject;
-   Vpb->SerialNumber = 0;
-   Vpb->ReferenceCount = 0;
-   RtlZeroMemory(Vpb->VolumeLabel,
-                sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH);
-   
-   DeviceObject->Vpb = Vpb;
-   
-   return(STATUS_SUCCESS);
-}
+    PVPB Vpb;
+
+    /* Allocate the Vpb */
+    Vpb = ExAllocatePoolWithTag(NonPagedPool,
+                                sizeof(VPB),
+                                TAG_VPB);
+    if (Vpb == NULL) return(STATUS_UNSUCCESSFUL);
+
+    /* Clear it so we don't waste time manually */
+    RtlZeroMemory(Vpb, sizeof(VPB));
 
+    /* Set the Header and Device Field */
+    Vpb->Type = IO_TYPE_VPB;
+    Vpb->Size = sizeof(VPB);
+    Vpb->RealDevice = DeviceObject;
+
+    /* link it to the Device Object */
+    DeviceObject->Vpb = Vpb;
+    return(STATUS_SUCCESS);
+}
 
 /*
  * FUNCTION: Queries the volume information
- * ARGUMENTS: 
+ * ARGUMENTS:
  *       FileHandle  = Handle to a file object on the target volume
  *       ReturnLength = DataWritten
- *       FsInformation = Caller should supply storage for the information 
+ *       FsInformation = Caller should supply storage for the information
  *                       structure.
  *       Length = Size of the information structure
  *       FsInformationClass = Index to a information structure
@@ -74,10 +66,10 @@ IoAttachVpb(PDEVICE_OBJECT DeviceObject)
  *             FileFsSizeInformation           FILE_FS_SIZE_INFORMATION
  *             FileFsDeviceInformation         FILE_FS_DEVICE_INFORMATION
  *             FileFsAttributeInformation      FILE_FS_ATTRIBUTE_INFORMATION
- *             FileFsControlInformation        
+ *             FileFsControlInformation
  *             FileFsQuotaQueryInformation     --
  *             FileFsQuotaSetInformation       --
- *             FileFsMaximumInformation        
+ *             FileFsMaximumInformation
  *
  * RETURNS: Status
  *
@@ -94,20 +86,52 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
    PFILE_OBJECT FileObject;
    PDEVICE_OBJECT DeviceObject;
    PIRP Irp;
-   NTSTATUS Status;
+   NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION StackPtr;
    PVOID SystemBuffer;
    KPROCESSOR_MODE PreviousMode;
-   
-   ASSERT(IoStatusBlock != NULL);
-   ASSERT(FsInformation != NULL);
-   
+
    DPRINT("FsInformation %p\n", FsInformation);
 
    PreviousMode = ExGetPreviousMode();
+   
+   if (PreviousMode != KernelMode)
+   {
+        _SEH_TRY
+        {
+            if (IoStatusBlock != NULL)
+            {
+                ProbeForWrite(IoStatusBlock,
+                              sizeof(IO_STATUS_BLOCK),
+                              sizeof(ULONG));
+            }
+
+            if (Length != 0)
+            {
+                ProbeForWrite(FsInformation,
+                              Length,
+                              1);
+            }
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+   }
+   else
+   {
+       ASSERT(IoStatusBlock != NULL);
+       ASSERT(FsInformation != NULL);
+   }
 
    Status = ObReferenceObjectByHandle(FileHandle,
-                                     FILE_READ_ATTRIBUTES,
+                                     0, /* FIXME - depends on the information class! */
                                      IoFileObjectType,
                                      PreviousMode,
                                      (PVOID*)&FileObject,
@@ -116,9 +140,9 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
      {
        return(Status);
      }
-   
+
    DeviceObject = FileObject->DeviceObject;
-   
+
    Irp = IoAllocateIrp(DeviceObject->StackSize,
                       TRUE);
    if (Irp == NULL)
@@ -126,7 +150,7 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
        ObDereferenceObject(FileObject);
        return(STATUS_INSUFFICIENT_RESOURCES);
      }
-   
+
    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                        Length,
                                        TAG_SYSB);
@@ -136,7 +160,7 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
        ObDereferenceObject(FileObject);
        return(STATUS_INSUFFICIENT_RESOURCES);
      }
-   
+
    /* Trigger FileObject/Event dereferencing */
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
 
@@ -146,7 +170,7 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
    Irp->UserEvent = &FileObject->Event;
    Irp->UserIosb = IoStatusBlock;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   
+
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
    StackPtr->MinorFunction = 0;
@@ -157,7 +181,7 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
    StackPtr->Parameters.QueryVolume.Length = Length;
    StackPtr->Parameters.QueryVolume.FsInformationClass =
        FsInformationClass;
-   
+
    Status = IoCallDriver(DeviceObject,
                         Irp);
    if (Status == STATUS_PENDING)
@@ -170,17 +194,25 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
        Status = IoStatusBlock->Status;
      }
    DPRINT("Status %x\n", Status);
-   
+
    if (NT_SUCCESS(Status))
      {
-       DPRINT("Information %lu\n", IoStatusBlock->Information);
-       MmSafeCopyToUser(FsInformation,
-                        SystemBuffer,
-                        IoStatusBlock->Information);
+        _SEH_TRY
+        {
+            DPRINT("Information %lu\n", IoStatusBlock->Information);
+            RtlCopyMemory(FsInformation,
+                          SystemBuffer,
+                          IoStatusBlock->Information);
+       }
+       _SEH_HANDLE
+       {
+            Status = _SEH_GetExceptionCode();
+       }
+        _SEH_END;
      }
 
    ExFreePool(SystemBuffer);
-   
+
    return(Status);
 }
 
@@ -200,11 +232,11 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
    PDEVICE_OBJECT DeviceObject;
    PIRP Irp;
    NTSTATUS Status;
-   
+
    ASSERT(FsInformation != NULL);
-   
+
    DPRINT("FsInformation %p\n", FsInformation);
-   
+
    Status = ObReferenceObjectByPointer(FileObject,
                                       FILE_READ_ATTRIBUTES,
                                       IoFileObjectType,
@@ -213,9 +245,9 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
      {
        return(Status);
      }
-   
+
    DeviceObject = FileObject->DeviceObject;
-   
+
    Irp = IoAllocateIrp(DeviceObject->StackSize,
                       TRUE);
    if (Irp == NULL)
@@ -232,7 +264,7 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
    Irp->UserEvent = &FileObject->Event;
    Irp->UserIosb = &IoStatusBlock;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   
+
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
    StackPtr->MinorFunction = 0;
@@ -243,7 +275,7 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
    StackPtr->Parameters.QueryVolume.Length = Length;
    StackPtr->Parameters.QueryVolume.FsInformationClass =
        FsInformationClass;
-   
+
    Status = IoCallDriver(DeviceObject,
                         Irp);
    if (Status == STATUS_PENDING)
@@ -256,12 +288,12 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
        Status = IoStatusBlock.Status;
      }
    DPRINT("Status %x\n", Status);
-   
+
    if (ReturnedLength != NULL)
      {
        *ReturnedLength = IoStatusBlock.Information;
      }
-   
+
    return(Status);
 }
 
@@ -284,10 +316,43 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
    PVOID SystemBuffer;
    KPROCESSOR_MODE PreviousMode;
 
-   ASSERT(IoStatusBlock != NULL);
-   ASSERT(FsInformation != NULL);
-
    PreviousMode = ExGetPreviousMode();
+   
+   if (PreviousMode != KernelMode)
+   {
+      Status = STATUS_SUCCESS;
+      _SEH_TRY
+      {
+         if (IoStatusBlock != NULL)
+         {
+            ProbeForWrite(IoStatusBlock,
+                          sizeof(IO_STATUS_BLOCK),
+                          sizeof(ULONG));
+         }
+
+         if (Length != 0)
+         {
+            ProbeForRead(FsInformation,
+                         Length,
+                         1);
+         }
+      }
+      _SEH_HANDLE
+      {
+         Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+
+      if (!NT_SUCCESS(Status))
+      {
+         return Status;
+      }
+   }
+   else
+   {
+      ASSERT(IoStatusBlock != NULL);
+      ASSERT(FsInformation != NULL);
+   }
 
    Status = ObReferenceObjectByHandle(FileHandle,
                                      FILE_WRITE_ATTRIBUTES,
@@ -299,30 +364,57 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
      {
        return(Status);
      }
-   
+
    DeviceObject = FileObject->DeviceObject;
-   
+
    Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE);
    if (Irp == NULL)
      {
        ObDereferenceObject(FileObject);
        return(STATUS_INSUFFICIENT_RESOURCES);
      }
-   
+
    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                        Length,
                                        TAG_SYSB);
    if (SystemBuffer == NULL)
      {
-       IoFreeIrp(Irp);
-       ObDereferenceObject(FileObject);
-       return(STATUS_INSUFFICIENT_RESOURCES);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failfreeirp;
      }
-   
-   MmSafeCopyFromUser(SystemBuffer,
-                     FsInformation,
-                     Length);
-   
+
+   if (PreviousMode != KernelMode)
+   {
+      _SEH_TRY
+      {
+         /* no need to probe again */
+         RtlCopyMemory(SystemBuffer,
+                       FsInformation,
+                       Length);
+      }
+      _SEH_HANDLE
+      {
+         Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+
+      if (!NT_SUCCESS(Status))
+      {
+         ExFreePoolWithTag(SystemBuffer,
+                           TAG_SYSB);
+failfreeirp:
+         IoFreeIrp(Irp);
+         ObDereferenceObject(FileObject);
+         return Status;
+      }
+   }
+   else
+   {
+      RtlCopyMemory(SystemBuffer,
+                    FsInformation,
+                    Length);
+   }
+
    /* Trigger FileObject/Event dereferencing */
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->RequestorMode = PreviousMode;
@@ -331,7 +423,7 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
    Irp->UserEvent = &FileObject->Event;
    Irp->UserIosb = IoStatusBlock;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-   
+
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
    StackPtr->MinorFunction = 0;
@@ -342,7 +434,7 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
    StackPtr->Parameters.SetVolume.Length = Length;
    StackPtr->Parameters.SetVolume.FsInformationClass =
        FsInformationClass;
-   
+
    Status = IoCallDriver(DeviceObject,Irp);
    if (Status == STATUS_PENDING)
      {
@@ -351,11 +443,19 @@ NtSetVolumeInformationFile(IN HANDLE FileHandle,
                              PreviousMode,
                              FALSE,
                              NULL);
-       Status = IoStatusBlock->Status;
+        _SEH_TRY
+        {
+           Status = IoStatusBlock->Status;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
      }
 
    ExFreePool(SystemBuffer);
-   
+
    return(Status);
 }
 
@@ -381,4 +481,17 @@ IoReleaseVpbSpinLock(IN KIRQL Irql)
                     Irql);
 }
 
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
+                                 IN ULONG Length,
+                                 IN BOOLEAN SetOperation)
+{
+     UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 /* EOF */