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

View file

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

View file

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

View file

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

View file

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

View file

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