Fixed an uninitialized variable error.
[reactos.git] / reactos / ntoskrnl / io / vpb.c
index 14577ba..f7d0722 100644 (file)
-/*
+/* $Id$
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/vpb.c
- * PURPOSE:         Volume Parameters Block managment
- * PROGRAMMER:      David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- *                  Created 22/05/98
+ * PURPOSE:         Volume Parameter Block managment
+ *
+ * PROGRAMMERS:     David Welch (welch@mcmail.com)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <internal/string.h>
-
+#include <ntoskrnl.h>
+#define NDEBUG
 #include <internal/debug.h>
 
+/* GLOBALS *******************************************************************/
+
+static KSPIN_LOCK IoVpbLock;
+
 /* FUNCTIONS *****************************************************************/
 
-NTSTATUS IoAttachVpb(PDEVICE_OBJECT DeviceObject)
+VOID INIT_FUNCTION
+IoInitVpbImplementation(VOID)
+{
+   KeInitializeSpinLock(&IoVpbLock);
+}
+
+NTSTATUS
+STDCALL
+IopAttachVpb(PDEVICE_OBJECT DeviceObject)
+{
+    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:
+ *       FileHandle  = Handle to a file object on the target volume
+ *       ReturnLength = DataWritten
+ *       FsInformation = Caller should supply storage for the information
+ *                       structure.
+ *       Length = Size of the information structure
+ *       FsInformationClass = Index to a information structure
+ *
+ *             FileFsVolumeInformation         FILE_FS_VOLUME_INFORMATION
+ *             FileFsLabelInformation          FILE_FS_LABEL_INFORMATION
+ *             FileFsSizeInformation           FILE_FS_SIZE_INFORMATION
+ *             FileFsDeviceInformation         FILE_FS_DEVICE_INFORMATION
+ *             FileFsAttributeInformation      FILE_FS_ATTRIBUTE_INFORMATION
+ *             FileFsControlInformation
+ *             FileFsQuotaQueryInformation     --
+ *             FileFsQuotaSetInformation       --
+ *             FileFsMaximumInformation
+ *
+ * RETURNS: Status
+ *
+ * @implemented
+ */
+
+NTSTATUS STDCALL
+NtQueryVolumeInformationFile(IN HANDLE FileHandle,
+                            OUT PIO_STATUS_BLOCK IoStatusBlock,
+                            OUT PVOID FsInformation,
+                            IN ULONG Length,
+                            IN FS_INFORMATION_CLASS FsInformationClass)
 {
-   PVPB Vpb;
+   PFILE_OBJECT FileObject;
+   PDEVICE_OBJECT DeviceObject;
+   PIRP Irp;
+   NTSTATUS Status = STATUS_SUCCESS;
+   PIO_STACK_LOCATION StackPtr;
+   PVOID SystemBuffer;
+   KPROCESSOR_MODE PreviousMode;
+
+   DPRINT("FsInformation %p\n", FsInformation);
+
+   PreviousMode = ExGetPreviousMode();
    
-   Vpb = ExAllocatePool(NonPagedPool,sizeof(VPB));
-   if (Vpb==NULL)
+   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,
+                                     0, /* FIXME - depends on the information class! */
+                                     IoFileObjectType,
+                                     PreviousMode,
+                                     (PVOID*)&FileObject,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
      {
-       return(STATUS_UNSUCCESSFUL);
+       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);
+     }
+
+   /* Trigger FileObject/Event dereferencing */
+   Irp->Tail.Overlay.OriginalFileObject = FileObject;
+
+   Irp->RequestorMode = PreviousMode;
+   Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+   KeResetEvent( &FileObject->Event );
+   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;
+   StackPtr->Flags = 0;
+   StackPtr->Control = 0;
+   StackPtr->DeviceObject = DeviceObject;
+   StackPtr->FileObject = FileObject;
+   StackPtr->Parameters.QueryVolume.Length = Length;
+   StackPtr->Parameters.QueryVolume.FsInformationClass =
+       FsInformationClass;
+
+   Status = IoCallDriver(DeviceObject,
+                        Irp);
+   if (Status == STATUS_PENDING)
+     {
+       KeWaitForSingleObject(&FileObject->Event,
+                             UserRequest,
+                             PreviousMode,
+                             FALSE,
+                             NULL);
+       Status = IoStatusBlock->Status;
+     }
+   DPRINT("Status %x\n", Status);
+
+   if (NT_SUCCESS(Status))
+     {
+        _SEH_TRY
+        {
+            DPRINT("Information %lu\n", IoStatusBlock->Information);
+            RtlCopyMemory(FsInformation,
+                          SystemBuffer,
+                          IoStatusBlock->Information);
+       }
+       _SEH_HANDLE
+       {
+            Status = _SEH_GetExceptionCode();
+       }
+        _SEH_END;
+     }
+
+   ExFreePool(SystemBuffer);
+
+   return(Status);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
+                        IN FS_INFORMATION_CLASS FsInformationClass,
+                        IN ULONG Length,
+                        OUT PVOID FsInformation,
+                        OUT PULONG ReturnedLength)
+{
+   IO_STATUS_BLOCK IoStatusBlock;
+   PIO_STACK_LOCATION StackPtr;
+   PDEVICE_OBJECT DeviceObject;
+   PIRP Irp;
+   NTSTATUS Status;
+
+   ASSERT(FsInformation != NULL);
+
+   DPRINT("FsInformation %p\n", FsInformation);
+
+   Status = ObReferenceObjectByPointer(FileObject,
+                                      FILE_READ_ATTRIBUTES,
+                                      IoFileObjectType,
+                                      KernelMode);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+
+   DeviceObject = FileObject->DeviceObject;
+
+   Irp = IoAllocateIrp(DeviceObject->StackSize,
+                      TRUE);
+   if (Irp == NULL)
+     {
+       ObDereferenceObject(FileObject);
+       return(STATUS_INSUFFICIENT_RESOURCES);
+     }
+
+   /* Trigger FileObject/Event dereferencing */
+   Irp->Tail.Overlay.OriginalFileObject = FileObject;
+   Irp->RequestorMode = KernelMode;
+   Irp->AssociatedIrp.SystemBuffer = FsInformation;
+   KeResetEvent( &FileObject->Event );
+   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;
+   StackPtr->Flags = 0;
+   StackPtr->Control = 0;
+   StackPtr->DeviceObject = DeviceObject;
+   StackPtr->FileObject = FileObject;
+   StackPtr->Parameters.QueryVolume.Length = Length;
+   StackPtr->Parameters.QueryVolume.FsInformationClass =
+       FsInformationClass;
+
+   Status = IoCallDriver(DeviceObject,
+                        Irp);
+   if (Status == STATUS_PENDING)
+     {
+       KeWaitForSingleObject(&FileObject->Event,
+                             UserRequest,
+                             KernelMode,
+                             FALSE,
+                             NULL);
+       Status = IoStatusBlock.Status;
+     }
+   DPRINT("Status %x\n", Status);
+
+   if (ReturnedLength != NULL)
+     {
+       *ReturnedLength = IoStatusBlock.Information;
+     }
+
+   return(Status);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtSetVolumeInformationFile(IN HANDLE FileHandle,
+                          OUT PIO_STATUS_BLOCK IoStatusBlock,
+                          IN PVOID FsInformation,
+                          IN ULONG Length,
+                          IN FS_INFORMATION_CLASS FsInformationClass)
+{
+   PFILE_OBJECT FileObject;
+   PDEVICE_OBJECT DeviceObject;
+   PIRP Irp;
+   NTSTATUS Status;
+   PIO_STACK_LOCATION StackPtr;
+   PVOID SystemBuffer;
+   KPROCESSOR_MODE PreviousMode;
+
+   PreviousMode = ExGetPreviousMode();
    
-   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;
-   memset(Vpb->VolumeLabel,0,sizeof(WCHAR)*MAXIMUM_VOLUME_LABEL_LENGTH);
-   
-   DeviceObject->Vpb = Vpb;
+   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,
+                                     NULL,
+                                     PreviousMode,
+                                     (PVOID*)&FileObject,
+                                     NULL);
+   if (Status != STATUS_SUCCESS)
+     {
+       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)
+     {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto failfreeirp;
+     }
+
+   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;
+   Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
+   KeResetEvent( &FileObject->Event );
+   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;
+   StackPtr->Flags = 0;
+   StackPtr->Control = 0;
+   StackPtr->DeviceObject = DeviceObject;
+   StackPtr->FileObject = FileObject;
+   StackPtr->Parameters.SetVolume.Length = Length;
+   StackPtr->Parameters.SetVolume.FsInformationClass =
+       FsInformationClass;
+
+   Status = IoCallDriver(DeviceObject,Irp);
+   if (Status == STATUS_PENDING)
+     {
+       KeWaitForSingleObject(&FileObject->Event,
+                             UserRequest,
+                             PreviousMode,
+                             FALSE,
+                             NULL);
+        _SEH_TRY
+        {
+           Status = IoStatusBlock->Status;
+        }
+        _SEH_HANDLE
+        {
+            Status = _SEH_GetExceptionCode();
+        }
+        _SEH_END;
+     }
+
+   ExFreePool(SystemBuffer);
+
+   return(Status);
 }
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+IoAcquireVpbSpinLock(OUT PKIRQL Irql)
+{
+   KeAcquireSpinLock(&IoVpbLock,
+                    Irql);
+}
+
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+IoReleaseVpbSpinLock(IN KIRQL Irql)
+{
+   KeReleaseSpinLock(&IoVpbLock,
+                    Irql);
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
+                                 IN ULONG Length,
+                                 IN BOOLEAN SetOperation)
+{
+     UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+/* EOF */