reactos/reactos/ntoskrnl/io/file.c
2003-03-23 14:46:09 +00:00

439 lines
11 KiB
C

/* $Id: file.c,v 1.23 2003/03/23 14:46:09 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/io/file.c
* PURPOSE: Graceful system shutdown if a bug is detected
* 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>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *******************************************************************/
#define TAG_SYSB TAG('S', 'Y', 'S', 'B')
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
NtQueryInformationFile(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
PFILE_OBJECT FileObject;
NTSTATUS Status;
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION StackPtr;
PVOID SystemBuffer;
IO_STATUS_BLOCK IoSB;
assert(IoStatusBlock != NULL);
assert(FileInformation != NULL);
DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
"Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
Status = ObReferenceObjectByHandle(FileHandle,
FILE_READ_ATTRIBUTES,
IoFileObjectType,
UserMode,
(PVOID *)&FileObject,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
DPRINT("FileObject %x\n", FileObject);
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);
}
Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
Irp->UserIosb = &IoSB;
Irp->UserEvent = &FileObject->Event;
KeResetEvent( &FileObject->Event );
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Flags = 0;
StackPtr->Control = 0;
StackPtr->DeviceObject = DeviceObject;
StackPtr->FileObject = FileObject;
StackPtr->Parameters.QueryFile.FileInformationClass =
FileInformationClass;
StackPtr->Parameters.QueryFile.Length = Length;
Status = IoCallDriver(FileObject->DeviceObject,
Irp);
if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
{
KeWaitForSingleObject(&FileObject->Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoSB.Status;
}
if (IoStatusBlock)
{
*IoStatusBlock = IoSB;
}
if (NT_SUCCESS(Status))
{
DPRINT("Information %lu\n", IoStatusBlock->Information);
MmSafeCopyToUser(FileInformation,
SystemBuffer,
IoStatusBlock->Information);
}
ExFreePool(SystemBuffer);
return(Status);
}
NTSTATUS STDCALL
IoQueryFileInformation(IN PFILE_OBJECT FileObject,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN ULONG Length,
OUT PVOID FileInformation,
OUT PULONG ReturnedLength)
{
IO_STATUS_BLOCK IoStatusBlock;
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION StackPtr;
NTSTATUS Status;
assert(FileInformation != NULL)
Status = ObReferenceObjectByPointer(FileObject,
FILE_READ_ATTRIBUTES,
IoFileObjectType,
KernelMode);
if (!NT_SUCCESS(Status))
{
return(Status);
}
DPRINT("FileObject %x\n", FileObject);
DeviceObject = FileObject->DeviceObject;
Irp = IoAllocateIrp(DeviceObject->StackSize,
TRUE);
if (Irp == NULL)
{
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
Irp->AssociatedIrp.SystemBuffer = FileInformation;
Irp->UserIosb = &IoStatusBlock;
Irp->UserEvent = &FileObject->Event;
KeResetEvent( &FileObject->Event );
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Flags = 0;
StackPtr->Control = 0;
StackPtr->DeviceObject = DeviceObject;
StackPtr->FileObject = FileObject;
StackPtr->Parameters.QueryFile.FileInformationClass =
FileInformationClass;
StackPtr->Parameters.QueryFile.Length = Length;
Status = IoCallDriver(FileObject->DeviceObject,
Irp);
if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
{
KeWaitForSingleObject(&FileObject->Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoStatusBlock.Status;
}
if (ReturnedLength != NULL)
{
*ReturnedLength = IoStatusBlock.Information;
}
return Status;
}
NTSTATUS STDCALL
NtSetInformationFile(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID FileInformation,
ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
PIO_STACK_LOCATION StackPtr;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
NTSTATUS Status;
PVOID SystemBuffer;
IO_STATUS_BLOCK IoSB;
assert(IoStatusBlock != NULL)
assert(FileInformation != NULL)
DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
"Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
Length, FileInformationClass);
/* Get the file object from the file handle */
Status = ObReferenceObjectByHandle(FileHandle,
FILE_WRITE_ATTRIBUTES,
IoFileObjectType,
UserMode,
(PVOID *)&FileObject,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
DPRINT("FileObject %x\n", FileObject);
//io completion port?
if (FileInformationClass == FileCompletionInformation)
{
PKQUEUE Queue;
if (Length < sizeof(FILE_COMPLETION_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
IO_COMPLETION_MODIFY_STATE,//???
ExIoCompletionType,
UserMode,
(PVOID*)&Queue,
NULL);
if (NT_SUCCESS(Status))
{
//FIXME: maybe use lookaside list
FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
FileObject->CompletionContext->Port = Queue;
ObDereferenceObject(Queue);
}
}
ObDereferenceObject(FileObject);
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);
}
MmSafeCopyFromUser(SystemBuffer,
FileInformation,
Length);
Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
Irp->UserIosb = &IoSB;
Irp->UserEvent = &FileObject->Event;
KeResetEvent( &FileObject->Event );
StackPtr = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Flags = 0;
StackPtr->Control = 0;
StackPtr->DeviceObject = DeviceObject;
StackPtr->FileObject = FileObject;
StackPtr->Parameters.SetFile.FileInformationClass =
FileInformationClass;
StackPtr->Parameters.SetFile.Length = Length;
/*
* Pass the IRP to the FSD (and wait for
* it if required)
*/
DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
Status = IoCallDriver(FileObject->DeviceObject,
Irp);
if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
{
KeWaitForSingleObject(&FileObject->Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = IoSB.Status;
}
if (IoStatusBlock)
{
*IoStatusBlock = IoSB;
}
ExFreePool(SystemBuffer);
return Status;
}
NTSTATUS STDCALL
NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PFILE_BASIC_INFORMATION FileInformation)
{
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
/* Open the file */
Status = NtOpenFile (&FileHandle,
SYNCHRONIZE | FILE_READ_ATTRIBUTES,
ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS (Status))
{
DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
return Status;
}
/* Get file attributes */
Status = NtQueryInformationFile (FileHandle,
&IoStatusBlock,
FileInformation,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
NtClose (FileHandle);
if (!NT_SUCCESS (Status))
{
DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
}
return Status;
}
NTSTATUS STDCALL
NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
{
IO_STATUS_BLOCK IoStatusBlock;
HANDLE FileHandle;
NTSTATUS Status;
/* Open the file */
Status = NtOpenFile (&FileHandle,
SYNCHRONIZE | FILE_READ_ATTRIBUTES,
ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS (Status))
{
DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
return Status;
}
/* Get file attributes */
Status = NtQueryInformationFile (FileHandle,
&IoStatusBlock,
FileInformation,
sizeof(FILE_NETWORK_OPEN_INFORMATION),
FileNetworkOpenInformation);
NtClose (FileHandle);
if (!NT_SUCCESS (Status))
{
DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
}
return Status;
}
NTSTATUS STDCALL
NtQueryEaFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN BOOLEAN ReturnSingleEntry,
IN PVOID EaList OPTIONAL,
IN ULONG EaListLength,
IN PULONG EaIndex OPTIONAL,
IN BOOLEAN RestartScan)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS STDCALL
NtSetEaFile(IN HANDLE FileHandle,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID EaBuffer,
IN ULONG EaBufferSize)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */