mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
- Remove "zero-stream" from null, NT doesn't support this.
- Implement Fast I/O Dispatch entrypoints for null. - Support query file information and lock IRPs, just like NT. - Remove query volume information IRP, not supported by NT. - Page the entire driver. svn path=/trunk/; revision=26256
This commit is contained in:
parent
ca95775748
commit
0c5f9a2ec6
2 changed files with 178 additions and 198 deletions
|
@ -1,205 +1,207 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
* PROJECT: ReactOS Kernel
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* FILE: drivers/base/null/null.c
|
||||||
* FILE: services/null/null.c
|
* PURPOSE: Beep Device Driver
|
||||||
* PURPOSE: NULL device driver
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
* David Welch (welch@mcmail.com)
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 13/08/1998: Created
|
|
||||||
* 29/04/2002: Fixed bugs, added zero-stream device
|
|
||||||
* 28/06/2004: Compile against the DDK, use PSEH where necessary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES */
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
|
|
||||||
#include <pseh/pseh.h>
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
#include "null.h"
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
/* OBJECTS */
|
NullQueryFileInformation(OUT PVOID Buffer,
|
||||||
static const NULL_EXTENSION nxNull = NullBitBucket;
|
IN PULONG Length,
|
||||||
static const NULL_EXTENSION nxZero = NullZeroStream;
|
IN FILE_INFORMATION_CLASS InformationClass)
|
||||||
|
|
||||||
/* FUNCTIONS */
|
|
||||||
static NTSTATUS STDCALL
|
|
||||||
NullDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
|
PFILE_STANDARD_INFORMATION StandardInfo = Buffer;
|
||||||
NTSTATUS nErrCode;
|
PAGED_CODE();
|
||||||
|
|
||||||
nErrCode = STATUS_SUCCESS;
|
/* We only support one class */
|
||||||
Irp->IoStatus.Information = 0;
|
if (InformationClass != FileStandardInformation)
|
||||||
|
|
||||||
switch(piosStack->MajorFunction)
|
|
||||||
{
|
{
|
||||||
/* opening and closing handles to the device */
|
/* Fail */
|
||||||
case IRP_MJ_CREATE:
|
return STATUS_INVALID_INFO_CLASS;
|
||||||
case IRP_MJ_CLOSE:
|
|
||||||
switch(NULL_DEVICE_TYPE(DeviceObject))
|
|
||||||
{
|
|
||||||
case NullBitBucket:
|
|
||||||
case NullZeroStream:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* write data */
|
|
||||||
case IRP_MJ_WRITE:
|
|
||||||
{
|
|
||||||
switch(NULL_DEVICE_TYPE(DeviceObject))
|
|
||||||
{
|
|
||||||
case NullBitBucket:
|
|
||||||
Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NullZeroStream:
|
|
||||||
nErrCode = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read data */
|
|
||||||
case IRP_MJ_READ:
|
|
||||||
{
|
|
||||||
switch(NULL_DEVICE_TYPE(DeviceObject))
|
|
||||||
{
|
|
||||||
case NullBitBucket:
|
|
||||||
nErrCode = STATUS_END_OF_FILE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NullZeroStream:
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, piosStack->Parameters.Read.Length);
|
|
||||||
Irp->IoStatus.Information = piosStack->Parameters.Read.Length;
|
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
nErrCode = _SEH_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ASSERT(FALSE);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
|
||||||
switch(piosStack->Parameters.QueryVolume.FsInformationClass)
|
|
||||||
{
|
|
||||||
case FileFsDeviceInformation:
|
|
||||||
{
|
|
||||||
ULONG BufferLength = piosStack->Parameters.QueryVolume.Length;
|
|
||||||
PFILE_FS_DEVICE_INFORMATION FsDeviceInfo = (PFILE_FS_DEVICE_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
||||||
|
|
||||||
if (BufferLength >= sizeof(FILE_FS_DEVICE_INFORMATION))
|
|
||||||
{
|
|
||||||
FsDeviceInfo->DeviceType = FILE_DEVICE_NULL;
|
|
||||||
FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
|
|
||||||
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
|
|
||||||
nErrCode = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
nErrCode = STATUS_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
nErrCode = STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
nErrCode = STATUS_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = nErrCode;
|
/* Fill out the information */
|
||||||
|
RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
|
||||||
|
StandardInfo->NumberOfLinks = 1;
|
||||||
|
|
||||||
|
/* Return the length and success */
|
||||||
|
*Length = sizeof(FILE_STANDARD_INFORMATION);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
NullRead(IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
OUT PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Complete successfully */
|
||||||
|
IoStatus->Status = STATUS_END_OF_FILE;
|
||||||
|
IoStatus->Information = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
NullWrite(IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Complete successfully */
|
||||||
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
|
IoStatus->Information = Length;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
NullDispatch(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
NTSTATUS Status;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
ULONG Length;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Get the file object and check what kind of request this is */
|
||||||
|
FileObject = IoStack->FileObject;
|
||||||
|
switch (IoStack->MajorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MJ_CREATE:
|
||||||
|
case IRP_MJ_CLOSE:
|
||||||
|
|
||||||
|
/* Check if this is synch I/O */
|
||||||
|
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||||
|
{
|
||||||
|
/* Set distinguished value for Cc */
|
||||||
|
FileObject->PrivateCacheMap = (PVOID)1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete successfully */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_READ:
|
||||||
|
|
||||||
|
/* Return as if we read the entire file */
|
||||||
|
Irp->IoStatus.Status = STATUS_END_OF_FILE;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_WRITE:
|
||||||
|
|
||||||
|
/* Return as if we wrote the entire request */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = IoStack->Parameters.Write.Length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_LOCK_CONTROL:
|
||||||
|
|
||||||
|
/* Dummy */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MJ_QUERY_INFORMATION:
|
||||||
|
|
||||||
|
/* Get the length inputted and do the request */
|
||||||
|
Length = IoStack->Parameters.QueryFile.Length;
|
||||||
|
Irp->IoStatus.Status = NullQueryFileInformation(Irp->AssociatedIrp.
|
||||||
|
SystemBuffer,
|
||||||
|
&Length,
|
||||||
|
IoStack->
|
||||||
|
Parameters.
|
||||||
|
QueryFile.
|
||||||
|
FileInformationClass);
|
||||||
|
|
||||||
|
/* Return the actual length */
|
||||||
|
Irp->IoStatus.Information = Length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete the request */
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
return (nErrCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID STDCALL
|
NTSTATUS
|
||||||
NullUnload(PDRIVER_OBJECT DriverObject)
|
STDCALL
|
||||||
|
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath)
|
||||||
{
|
{
|
||||||
}
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Null");
|
||||||
|
NTSTATUS Status;
|
||||||
|
PFAST_IO_DISPATCH FastIoDispatch;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* TODO: \Device\Zero should be memory-mappable */
|
/* Page the driver */
|
||||||
NTSTATUS STDCALL
|
MmPageEntireDriver(DriverEntry);
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
||||||
{
|
|
||||||
PDEVICE_OBJECT pdoNullDevice;
|
|
||||||
PDEVICE_OBJECT pdoZeroDevice;
|
|
||||||
UNICODE_STRING wstrNullDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Null");
|
|
||||||
UNICODE_STRING wstrZeroDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Zero");
|
|
||||||
NTSTATUS nErrCode;
|
|
||||||
|
|
||||||
/* register driver routines */
|
/* Create null device */
|
||||||
|
Status = IoCreateDevice(DriverObject,
|
||||||
|
0,
|
||||||
|
&DeviceName,
|
||||||
|
FILE_DEVICE_NULL,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
&DeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
|
||||||
|
/* Register driver routines */
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch;
|
||||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch;
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch;
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch;
|
DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch;
|
||||||
DriverObject->DriverUnload = NullUnload;
|
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = NullDispatch;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = NullDispatch;
|
||||||
|
|
||||||
/* create null device */
|
/* Allocate the fast I/O dispatch table */
|
||||||
nErrCode = IoCreateDevice(DriverObject,
|
FastIoDispatch = ExAllocatePool(NonPagedPool, sizeof(FAST_IO_DISPATCH));
|
||||||
sizeof(NULL_EXTENSION),
|
if (!FastIoDispatch)
|
||||||
&wstrNullDeviceName,
|
|
||||||
FILE_DEVICE_NULL,
|
|
||||||
0,
|
|
||||||
FALSE,
|
|
||||||
&pdoNullDevice);
|
|
||||||
|
|
||||||
/* failure */
|
|
||||||
if(!NT_SUCCESS(nErrCode))
|
|
||||||
{
|
{
|
||||||
return (nErrCode);
|
/* Failed, cleanup */
|
||||||
|
IoDeleteDevice(DeviceObject);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdoNullDevice->DeviceExtension = (PVOID)&nxNull;
|
/* Initialize it */
|
||||||
|
RtlZeroMemory(FastIoDispatch, sizeof(FAST_IO_DISPATCH));
|
||||||
|
FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
|
||||||
|
|
||||||
/* create zero device */
|
/* Setup our pointers */
|
||||||
nErrCode = IoCreateDevice(DriverObject,
|
FastIoDispatch->FastIoRead = NullRead;
|
||||||
sizeof(NULL_EXTENSION),
|
FastIoDispatch->FastIoWrite = NullWrite;
|
||||||
&wstrZeroDeviceName,
|
DriverObject->FastIoDispatch = FastIoDispatch;
|
||||||
FILE_DEVICE_NULL,
|
|
||||||
FILE_READ_ONLY_DEVICE, /* zero device is read-only */
|
|
||||||
FALSE,
|
|
||||||
&pdoZeroDevice);
|
|
||||||
|
|
||||||
/* failure */
|
/* Return success */
|
||||||
if(!NT_SUCCESS(nErrCode))
|
return STATUS_SUCCESS;
|
||||||
{
|
|
||||||
IoDeleteDevice(pdoNullDevice);
|
|
||||||
return (nErrCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdoZeroDevice->DeviceExtension = (PVOID)&nxZero;
|
|
||||||
pdoZeroDevice->Flags |= DO_BUFFERED_IO;
|
|
||||||
|
|
||||||
return (nErrCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS kernel
|
|
||||||
* FILE: services/dd/null/null.h
|
|
||||||
* PURPOSE: NULL device driver internal definitions
|
|
||||||
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 29/04/2002: Created
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum __tagNULL_EXTENSION{
|
|
||||||
NullBitBucket,
|
|
||||||
NullZeroStream,
|
|
||||||
} NULL_EXTENSION, *PNULL_EXTENSION;
|
|
||||||
|
|
||||||
#define NULL_DEVICE_TYPE(__DEVICE__) (*((PNULL_EXTENSION)((__DEVICE__)->DeviceExtension)))
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
|
||||||
|
|
||||||
/* EOF */
|
|
Loading…
Reference in a new issue