Complete IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_CLEANUP

Use correct buffer when filling read request. Use SEH when needed
Correctly propagate DO_BUFFERED_IO, DO_DIRECT_IO and FILE_DEVICE_SECURE_OPEN flags

svn path=/trunk/; revision=21741
This commit is contained in:
Hervé Poussineau 2006-04-25 22:22:22 +00:00
parent b110d67ed6
commit fbd4530bfa
6 changed files with 217 additions and 84 deletions

View file

@ -35,6 +35,9 @@ ClassCreate(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: open all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -49,6 +52,9 @@ ClassClose(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: close all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -63,6 +69,9 @@ ClassCleanup(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: cleanup all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -361,7 +370,8 @@ cleanup:
DeviceExtension->ReadIsPending = FALSE;
DeviceExtension->InputCount = 0;
DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA));
Fdo->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO;
Fdo->Flags |= DO_POWER_PAGABLE;
Fdo->Flags |= DO_BUFFERED_IO; /* FIXME: Why is it needed for 1st stage setup? */
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
@ -381,6 +391,53 @@ cleanup:
return STATUS_SUCCESS;
}
static NTSTATUS
FillOneEntry(
IN PDEVICE_OBJECT ClassDeviceObject,
IN PIRP Irp,
IN PKEYBOARD_INPUT_DATA DataStart)
{
NTSTATUS Status = STATUS_SUCCESS;
if (ClassDeviceObject->Flags & DO_BUFFERED_IO)
{
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
DataStart,
sizeof(KEYBOARD_INPUT_DATA));
}
else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
{
PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
if (DestAddress)
{
RtlCopyMemory(
DestAddress,
DataStart,
sizeof(KEYBOARD_INPUT_DATA));
}
else
Status = STATUS_UNSUCCESSFUL;
}
else
{
_SEH_TRY
{
RtlCopyMemory(
Irp->UserBuffer,
DataStart,
sizeof(KEYBOARD_INPUT_DATA));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
static BOOLEAN
ClassCallback(
IN PDEVICE_OBJECT ClassDeviceObject,
@ -406,28 +463,32 @@ ClassCallback(
*/
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
{
NTSTATUS Status;
Irp = ClassDeviceObject->CurrentIrp;
ClassDeviceObject->CurrentIrp = NULL;
Stack = IoGetCurrentIrpStackLocation(Irp);
/* A read request is waiting for input, so go straight to it */
/* FIXME: use SEH */
RtlCopyMemory(
Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->AssociatedIrp.SystemBuffer,
DataStart,
sizeof(KEYBOARD_INPUT_DATA));
Status = FillOneEntry(
ClassDeviceObject,
Irp,
DataStart);
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
if (NT_SUCCESS(Status))
{
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
ClassDeviceExtension->ReadIsPending = FALSE;
ClassDeviceExtension->ReadIsPending = FALSE;
/* Skip the packet we just sent away */
DataStart++;
(*ConsumedCount)++;
InputCount--;
/* Skip the packet we just sent away */
DataStart++;
(*ConsumedCount)++;
InputCount--;
}
}
/* If we have data from the port driver and a higher service to send the data to */
@ -439,9 +500,11 @@ ClassCallback(
ReadSize = InputCount;
/*
* FIXME: If we exceed the buffer, data gets thrown away.. better
* solution?
*/
* If we exceed the buffer, data gets thrown away...
* Try at least to display a dialog
*/
if (Irp != NULL)
IoRaiseHardError(Irp, NULL, ClassDeviceObject);
/*
* Move the input data from the port data queue to our class data
@ -549,7 +612,7 @@ ClassAddDevice(
sizeof(PORT_DEVICE_EXTENSION),
NULL,
Pdo->DeviceType,
FILE_DEVICE_SECURE_OPEN,
Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0,
TRUE,
&Fdo);
if (!NT_SUCCESS(Status))
@ -573,6 +636,8 @@ ClassAddDevice(
Fdo->Flags |= DO_POWER_PAGABLE;
if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
Fdo->Flags |= DO_BUFFERED_IO;
if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
Fdo->Flags |= DO_DIRECT_IO;
if (DriverExtension->ConnectMultiplePorts)
DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject;
@ -646,35 +711,35 @@ ClassStartIo(
if (DeviceExtension->InputCount > 0)
{
KIRQL oldIrql;
NTSTATUS Status;
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
DPRINT("Mdl: %p, UserBuffer: %p, InputCount: %lu\n",
Irp->MdlAddress,
Irp->UserBuffer,
DeviceExtension->InputCount);
Status = FillOneEntry(
DeviceObject,
Irp,
DeviceExtension->PortData - DeviceExtension->InputCount);
/* FIXME: use SEH */
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
DeviceExtension->PortData - DeviceExtension->InputCount,
sizeof(KEYBOARD_INPUT_DATA));
if (DeviceExtension->InputCount > 1)
if (NT_SUCCESS(Status))
{
RtlMoveMemory(
DeviceExtension->PortData - DeviceExtension->InputCount,
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
(DeviceExtension->InputCount - 1) * sizeof(KEYBOARD_INPUT_DATA));
}
DeviceExtension->PortData--;
DeviceExtension->InputCount--;
DeviceExtension->ReadIsPending = FALSE;
if (DeviceExtension->InputCount > 1)
{
RtlMoveMemory(
DeviceExtension->PortData - DeviceExtension->InputCount,
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
(DeviceExtension->InputCount - 1) * sizeof(KEYBOARD_INPUT_DATA));
}
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
DeviceExtension->PortData--;
DeviceExtension->InputCount--;
DeviceExtension->ReadIsPending = FALSE;
Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(KEYBOARD_INPUT_DATA);
}
/* Go to next packet and complete this request */
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
IoStartNextPacket(DeviceObject, FALSE);

View file

@ -1,6 +1,7 @@
#include <ntifs.h>
#include <kbdmou.h>
#include <ntddkbd.h>
#include <pseh/pseh.h>
#include <stdio.h>
#define MAX_PATH 260

View file

@ -1,6 +1,7 @@
<module name="kbdclass" type="kernelmodedriver" installbase="system32/drivers" installname="kbdclass.sys">
<bootstrap base="reactos" />
<define name="__USE_W32API" />
<library>pseh</library>
<library>ntoskrnl</library>
<library>hal</library>
<file>kbdclass.c</file>

View file

@ -35,6 +35,9 @@ ClassCreate(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: open all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -49,6 +52,9 @@ ClassClose(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: close all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -63,6 +69,9 @@ ClassCleanup(
return ForwardIrpAndForget(DeviceObject, Irp);
/* FIXME: cleanup all associated Port devices */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
@ -114,7 +123,7 @@ ClassDeviceControl(
PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
if (Head->Flink != Head)
{
/* We have at least one keyboard */
/* We have at least one mouse */
PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoSkipCurrentIrpStackLocation(Irp);
@ -358,6 +367,53 @@ cleanup:
return STATUS_SUCCESS;
}
static NTSTATUS
FillOneEntry(
IN PDEVICE_OBJECT ClassDeviceObject,
IN PIRP Irp,
IN PMOUSE_INPUT_DATA DataStart)
{
NTSTATUS Status = STATUS_SUCCESS;
if (ClassDeviceObject->Flags & DO_BUFFERED_IO)
{
RtlCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
DataStart,
sizeof(MOUSE_INPUT_DATA));
}
else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
{
PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
if (DestAddress)
{
RtlCopyMemory(
DestAddress,
DataStart,
sizeof(MOUSE_INPUT_DATA));
}
else
Status = STATUS_UNSUCCESSFUL;
}
else
{
_SEH_TRY
{
RtlCopyMemory(
Irp->UserBuffer,
DataStart,
sizeof(MOUSE_INPUT_DATA));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status;
}
static BOOLEAN
ClassCallback(
IN PDEVICE_OBJECT ClassDeviceObject,
@ -383,28 +439,32 @@ ClassCallback(
*/
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
{
NTSTATUS Status;
Irp = ClassDeviceObject->CurrentIrp;
ClassDeviceObject->CurrentIrp = NULL;
Stack = IoGetCurrentIrpStackLocation(Irp);
/* A read request is waiting for input, so go straight to it */
/* FIXME: use SEH */
RtlCopyMemory(
Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer,
DataStart,
sizeof(MOUSE_INPUT_DATA));
Status = FillOneEntry(
ClassDeviceObject,
Irp,
DataStart);
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
if (NT_SUCCESS(Status))
{
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
ClassDeviceExtension->ReadIsPending = FALSE;
ClassDeviceExtension->ReadIsPending = FALSE;
/* Skip the packet we just sent away */
DataStart++;
(*ConsumedCount)++;
InputCount--;
/* Skip the packet we just sent away */
DataStart++;
(*ConsumedCount)++;
InputCount--;
}
}
/* If we have data from the port driver and a higher service to send the data to */
@ -416,9 +476,11 @@ ClassCallback(
ReadSize = InputCount;
/*
* FIXME: If we exceed the buffer, data gets thrown away.. better
* solution?
*/
* If we exceed the buffer, data gets thrown away...
* Try at least to display a dialog
*/
if (Irp != NULL)
IoRaiseHardError(Irp, NULL, ClassDeviceObject);
/*
* Move the input data from the port data queue to our class data
@ -526,7 +588,7 @@ ClassAddDevice(
sizeof(PORT_DEVICE_EXTENSION),
NULL,
Pdo->DeviceType,
FILE_DEVICE_SECURE_OPEN,
Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0,
TRUE,
&Fdo);
if (!NT_SUCCESS(Status))
@ -550,6 +612,8 @@ ClassAddDevice(
Fdo->Flags |= DO_POWER_PAGABLE;
if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
Fdo->Flags |= DO_BUFFERED_IO;
if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
Fdo->Flags |= DO_DIRECT_IO;
if (DriverExtension->ConnectMultiplePorts)
DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject;
@ -623,35 +687,35 @@ ClassStartIo(
if (DeviceExtension->InputCount > 0)
{
KIRQL oldIrql;
NTSTATUS Status;
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
DPRINT("Mdl: %p, UserBuffer: %p, InputCount: %lu\n",
Irp->MdlAddress,
Irp->UserBuffer,
DeviceExtension->InputCount);
Status = FillOneEntry(
DeviceObject,
Irp,
DeviceExtension->PortData - DeviceExtension->InputCount);
/* FIXME: use SEH */
RtlCopyMemory(
Irp->MdlAddress ? MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) : Irp->UserBuffer,
DeviceExtension->PortData - DeviceExtension->InputCount,
sizeof(MOUSE_INPUT_DATA));
if (DeviceExtension->InputCount > 1)
if (NT_SUCCESS(Status))
{
RtlMoveMemory(
DeviceExtension->PortData - DeviceExtension->InputCount,
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
}
DeviceExtension->PortData--;
DeviceExtension->InputCount--;
DeviceExtension->ReadIsPending = FALSE;
if (DeviceExtension->InputCount > 1)
{
RtlMoveMemory(
DeviceExtension->PortData - DeviceExtension->InputCount,
DeviceExtension->PortData - DeviceExtension->InputCount + 1,
(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
}
/* Go to next packet and complete this request with STATUS_SUCCESS */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
DeviceExtension->PortData--;
DeviceExtension->InputCount--;
DeviceExtension->ReadIsPending = FALSE;
Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA);
Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA);
}
/* Go to next packet and complete this request */
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
IoStartNextPacket(DeviceObject, FALSE);

View file

@ -1,6 +1,7 @@
#include <ntifs.h>
#include <kbdmou.h>
#include <ntddmou.h>
#include <pseh/pseh.h>
#include <stdio.h>
#define MAX_PATH 260

View file

@ -1,6 +1,7 @@
<module name="mouclass" type="kernelmodedriver" installbase="system32/drivers" installname="mouclass.sys">
<include base="mouclass">.</include>
<define name="__USE_W32API" />
<library>pseh</library>
<library>ntoskrnl</library>
<library>hal</library>
<file>misc.c</file>