mirror of
https://github.com/reactos/reactos.git
synced 2024-06-27 16:31:30 +00:00
![Eric Kohl](/assets/img/avatar_default.png)
Fixed buffer size issues in volume functions. Fixed several minor bugs. svn path=/trunk/; revision=1959
377 lines
8.7 KiB
C
377 lines
8.7 KiB
C
/* $Id: vpb.c,v 1.13 2001/06/12 12:30:36 ekohl Exp $
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ddk/ntddk.h>
|
|
#include <internal/io.h>
|
|
#include <internal/mm.h>
|
|
#include <internal/pool.h>
|
|
|
|
|
|
#define NDEBUG
|
|
#include <internal/debug.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
static KSPIN_LOCK IoVpbLock;
|
|
|
|
#define TAG_VPB TAG('V', 'P', 'B', ' ')
|
|
#define TAG_SYSB TAG('S', 'Y', 'S', 'B')
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
VOID
|
|
IoInitVpbImplementation(VOID)
|
|
{
|
|
KeInitializeSpinLock(&IoVpbLock);
|
|
}
|
|
|
|
NTSTATUS
|
|
IoAttachVpb(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);
|
|
}
|
|
|
|
|
|
NTSTATUS STDCALL
|
|
NtQueryVolumeInformationFile(IN HANDLE FileHandle,
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
OUT PVOID FsInformation,
|
|
IN ULONG Length,
|
|
IN FS_INFORMATION_CLASS FsInformationClass)
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
{
|
|
PFILE_OBJECT FileObject;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
PIRP Irp;
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
PIO_STACK_LOCATION StackPtr;
|
|
PVOID SystemBuffer;
|
|
|
|
assert(IoStatusBlock != NULL);
|
|
assert(FsInformation != NULL);
|
|
|
|
DPRINT("FsInformation %p\n", FsInformation);
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
FILE_READ_ATTRIBUTES,
|
|
NULL,
|
|
UserMode,
|
|
(PVOID*)&FileObject,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
DeviceObject = FileObject->DeviceObject;
|
|
|
|
KeInitializeEvent(&Event,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
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);
|
|
}
|
|
|
|
Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
|
|
Irp->UserEvent = &Event;
|
|
Irp->UserIosb = IoStatusBlock;
|
|
|
|
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(&Event,
|
|
UserRequest,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatusBlock->Status;
|
|
}
|
|
DPRINT("Status %x\n", Status);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Information %lu\n", IoStatusBlock->Information);
|
|
MmSafeCopyToUser(FsInformation,
|
|
SystemBuffer,
|
|
IoStatusBlock->Information);
|
|
}
|
|
ExFreePool(SystemBuffer);
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
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;
|
|
KEVENT Event;
|
|
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;
|
|
|
|
KeInitializeEvent(&Event,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
|
TRUE);
|
|
if (Irp == NULL)
|
|
{
|
|
ObDereferenceObject(FileObject);
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
Irp->AssociatedIrp.SystemBuffer = FsInformation;
|
|
Irp->UserEvent = &Event;
|
|
Irp->UserIosb = &IoStatusBlock;
|
|
|
|
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(&Event,
|
|
UserRequest,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatusBlock.Status;
|
|
}
|
|
DPRINT("Status %x\n", Status);
|
|
|
|
if (ReturnedLength != NULL)
|
|
{
|
|
*ReturnedLength = IoStatusBlock.Information;
|
|
}
|
|
ObDereferenceObject(FileObject);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
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;
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
PIO_STACK_LOCATION StackPtr;
|
|
PVOID SystemBuffer;
|
|
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
FILE_WRITE_ATTRIBUTES,
|
|
NULL,
|
|
UserMode,
|
|
(PVOID*)&FileObject,
|
|
NULL);
|
|
if (Status != STATUS_SUCCESS)
|
|
{
|
|
return(Status);
|
|
}
|
|
|
|
DeviceObject = FileObject->DeviceObject;
|
|
|
|
KeInitializeEvent(&Event,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
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);
|
|
}
|
|
|
|
MmSafeCopyFromUser(SystemBuffer,
|
|
FsInformation,
|
|
Length);
|
|
|
|
Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
|
|
Irp->UserEvent = &Event;
|
|
Irp->UserIosb = IoStatusBlock;
|
|
|
|
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(&Event,
|
|
UserRequest,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
}
|
|
|
|
ExFreePool(SystemBuffer);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
VOID STDCALL
|
|
IoAcquireVpbSpinLock(OUT PKIRQL Irql)
|
|
{
|
|
KeAcquireSpinLock(&IoVpbLock,
|
|
Irql);
|
|
}
|
|
|
|
|
|
VOID STDCALL
|
|
IoReleaseVpbSpinLock(IN KIRQL Irql)
|
|
{
|
|
KeReleaseSpinLock(&IoVpbLock,
|
|
Irql);
|
|
}
|
|
|
|
|
|
NTSTATUS STDCALL
|
|
IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject,
|
|
IN BOOLEAN AllowRawMount)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return(STATUS_NOT_IMPLEMENTED);
|
|
}
|
|
|
|
|
|
/* EOF */
|