-/* $Id: vpb.c,v 1.21 2003/07/10 15:47:00 royce Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/vpb.c
* PURPOSE: Volume Parameter Block managment
- * PROGRAMMER: David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <internal/io.h>
-#include <internal/mm.h>
-#include <internal/pool.h>
-
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
static KSPIN_LOCK IoVpbLock;
-#define TAG_VPB TAG('V', 'P', 'B', ' ')
-#define TAG_SYSB TAG('S', 'Y', 'S', 'B')
-
/* FUNCTIONS *****************************************************************/
-VOID
+VOID INIT_FUNCTION
IoInitVpbImplementation(VOID)
{
KeInitializeSpinLock(&IoVpbLock);
}
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);
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-NtQueryVolumeInformationFile(IN HANDLE FileHandle,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- OUT PVOID FsInformation,
- IN ULONG Length,
- IN FS_INFORMATION_CLASS FsInformationClass)
+ /* 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
* FileFsSizeInformation FILE_FS_SIZE_INFORMATION
* FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
* FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
- * FileFsControlInformation
+ * FileFsControlInformation
* FileFsQuotaQueryInformation --
* FileFsQuotaSetInformation --
- * FileFsMaximumInformation
+ * 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)
{
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION StackPtr;
PVOID SystemBuffer;
- IO_STATUS_BLOCK IoSB;
-
- assert(IoStatusBlock != NULL);
- assert(FsInformation != NULL);
-
+ KPROCESSOR_MODE PreviousMode;
+
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,
- UserMode,
+ PreviousMode,
(PVOID*)&FileObject,
NULL);
if (!NT_SUCCESS(Status))
{
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);
ObDereferenceObject(FileObject);
return(STATUS_INSUFFICIENT_RESOURCES);
}
-
- //trigger FileObject/Event dereferencing
+
+ /* 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 = &IoSB;
+ Irp->UserIosb = IoStatusBlock;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
+
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Parameters.QueryVolume.Length = Length;
StackPtr->Parameters.QueryVolume.FsInformationClass =
FsInformationClass;
-
+
Status = IoCallDriver(DeviceObject,
Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&FileObject->Event,
UserRequest,
- KernelMode,
+ PreviousMode,
FALSE,
NULL);
- Status = IoSB.Status;
+ Status = IoStatusBlock->Status;
}
DPRINT("Status %x\n", Status);
-
+
if (NT_SUCCESS(Status))
{
- DPRINT("Information %lu\n", IoStatusBlock->Information);
- MmSafeCopyToUser(FsInformation,
- SystemBuffer,
- IoSB.Information);
- }
- if (IoStatusBlock)
- {
- *IoStatusBlock = IoSB;
+ _SEH_TRY
+ {
+ DPRINT("Information %lu\n", IoStatusBlock->Information);
+ RtlCopyMemory(FsInformation,
+ SystemBuffer,
+ IoStatusBlock->Information);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
+
ExFreePool(SystemBuffer);
-
+
return(Status);
}
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
NTSTATUS Status;
-
- assert(FsInformation != NULL);
-
+
+ ASSERT(FsInformation != NULL);
+
DPRINT("FsInformation %p\n", FsInformation);
-
+
Status = ObReferenceObjectByPointer(FileObject,
FILE_READ_ATTRIBUTES,
IoFileObjectType,
{
return(Status);
}
-
+
DeviceObject = FileObject->DeviceObject;
-
+
Irp = IoAllocateIrp(DeviceObject->StackSize,
TRUE);
if (Irp == NULL)
return(STATUS_INSUFFICIENT_RESOURCES);
}
- //trigger FileObject/Event dereferencing
+ /* 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->Parameters.QueryVolume.Length = Length;
StackPtr->Parameters.QueryVolume.FsInformationClass =
FsInformationClass;
-
+
Status = IoCallDriver(DeviceObject,
Irp);
if (Status == STATUS_PENDING)
Status = IoStatusBlock.Status;
}
DPRINT("Status %x\n", Status);
-
+
if (ReturnedLength != NULL)
{
*ReturnedLength = IoStatusBlock.Information;
}
-
+
return(Status);
}
NTSTATUS Status;
PIO_STACK_LOCATION StackPtr;
PVOID SystemBuffer;
- IO_STATUS_BLOCK IoSB;
+ KPROCESSOR_MODE PreviousMode;
+
+ 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,
NULL,
- UserMode,
+ 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)
{
- IoFreeIrp(Irp);
- ObDereferenceObject(FileObject);
- return(STATUS_INSUFFICIENT_RESOURCES);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto failfreeirp;
}
-
- MmSafeCopyFromUser(SystemBuffer,
- FsInformation,
- Length);
-
- //trigger FileObject/Event dereferencing
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ 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 = &IoSB;
+ Irp->UserIosb = IoStatusBlock;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
-
+
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Parameters.SetVolume.Length = Length;
StackPtr->Parameters.SetVolume.FsInformationClass =
FsInformationClass;
-
+
Status = IoCallDriver(DeviceObject,Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&FileObject->Event,
UserRequest,
- KernelMode,
+ PreviousMode,
FALSE,
NULL);
- Status = IoSB.Status;
+ _SEH_TRY
+ {
+ Status = IoStatusBlock->Status;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- if (IoStatusBlock)
- {
- *IoStatusBlock = IoSB;
- }
+
ExFreePool(SystemBuffer);
-
+
return(Status);
}
Irql);
}
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCheckQuerySetVolumeInformation(IN FS_INFORMATION_CLASS FsInformationClass,
+ IN ULONG Length,
+ IN BOOLEAN SetOperation)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
/* EOF */