Rewrite mouclass, so it can now handle more than one mouse.
win32k: try to open the keyboard/mouse in a loop, as they can not be present at startup
Modified: trunk/reactos/bootdata/hivesys.inf
Added: trunk/reactos/drivers/input/mouclass/misc.c
Modified: trunk/reactos/drivers/input/mouclass/mouclass.c
Modified: trunk/reactos/drivers/input/mouclass/mouclass.h
Modified: trunk/reactos/drivers/input/mouclass/mouclass.xml
Modified: trunk/reactos/subsys/win32k/ntuser/input.c

Modified: trunk/reactos/bootdata/hivesys.inf
--- trunk/reactos/bootdata/hivesys.inf	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/bootdata/hivesys.inf	2005-10-31 00:14:45 UTC (rev 18906)
@@ -532,7 +532,7 @@
 HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","ConnectMultiplePorts",0x00010001,0x00000000
 HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","MouseDataQueueSize",0x00010001,0x00000064
-HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDeviceBaseName",0x00000000,"PointerClass"
+HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDeviceBaseName",0x00000000,"PointerClassPnp"
 HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318}","UpperFilters",0x00010000,"mouclass"
 
 ; Mailslot filesystem driver

Added: trunk/reactos/drivers/input/mouclass/misc.c
--- trunk/reactos/drivers/input/mouclass/misc.c	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/drivers/input/mouclass/misc.c	2005-10-31 00:14:45 UTC (rev 18906)
@@ -0,0 +1,61 @@
+/* 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Mouse class driver
+ * FILE:            drivers/input/mouclass/misc.c
+ * PURPOSE:         Misceallenous operations
+ * 
+ * PROGRAMMERS:     HervÚ Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "mouclass.h"
+
+static NTSTATUS NTAPI
+ForwardIrpAndWaitCompletion(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp,
+	IN PVOID Context)
+{
+	if (Irp->PendingReturned)
+		KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+	return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+ForwardIrpAndWait(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	PDEVICE_OBJECT LowerDevice = ((PMOUCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+	KEVENT Event;
+	NTSTATUS Status;
+	
+	KeInitializeEvent(&Event, NotificationEvent, FALSE);
+	IoCopyCurrentIrpStackLocationToNext(Irp);
+	
+	DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
+	IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
+	
+	Status = IoCallDriver(LowerDevice, Irp);
+	if (Status == STATUS_PENDING)
+	{
+		Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+		if (NT_SUCCESS(Status))
+			Status = Irp->IoStatus.Status;
+	}
+	
+	return Status;
+}
+
+NTSTATUS NTAPI
+ForwardIrpAndForget(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	PDEVICE_OBJECT LowerDevice = ((PMOUCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+	
+	IoSkipCurrentIrpStackLocation(Irp);
+	return IoCallDriver(LowerDevice, Irp);
+}
Property changes on: trunk/reactos/drivers/input/mouclass/misc.c
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/reactos/drivers/input/mouclass/mouclass.c
--- trunk/reactos/drivers/input/mouclass/mouclass.c	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/drivers/input/mouclass/mouclass.c	2005-10-31 00:14:45 UTC (rev 18906)
@@ -1,277 +1,599 @@
-/*
+/* 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Mouse class driver
+ * FILE:            drivers/mouclass/mouclass.c
+ * PURPOSE:         Mouse class driver
+ * 
+ * PROGRAMMERS:     HervÚ Poussineau (hpoussin@reactos.org)
+ */
 
- ** Mouse class driver 0.0.1
- ** Written by Jason Filby (jasonfilby@yahoo.com)
- ** For ReactOS (www.reactos.com)
+#define NDEBUG
+#include <debug.h>
 
- ** The class driver between win32k and the various mouse port drivers
+#define INITGUID
+#include "mouclass.h"
 
- ** FIXME: Support IRP cancellation properly.
-*/
+static VOID NTAPI
+DriverUnload(IN PDRIVER_OBJECT DriverObject)
+{
+	// nothing to do here yet
+}
 
-#include <ddk/ntddk.h>
-#include <ddk/ntddmou.h>
-#include <ddk/kbdmou.h>
-#include "mouclass.h"
+static NTSTATUS NTAPI
+MouclassCreate(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	DPRINT("IRP_MJ_CREATE\n");
 
-#define NDEBUG
-#include <debug.h>
+	if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+		return ForwardIrpAndForget(DeviceObject, Irp);
 
-NTSTATUS STDCALL
-DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
+	/* FIXME: open all associated Port devices */
+	return STATUS_SUCCESS;
+}
 
-PDEVICE_OBJECT MouclassDeviceObject;
+static NTSTATUS NTAPI
+MouclassClose(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	DPRINT("IRP_MJ_CLOSE\n");
 
-static BOOLEAN MouseClassCallBack(
-   PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart,
-   PMOUSE_INPUT_DATA MouseDataEnd, PULONG ConsumedCount)
+	if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+		return ForwardIrpAndForget(DeviceObject, Irp);
+
+	/* FIXME: close all associated Port devices */
+	return STATUS_SUCCESS;
+}
+
+static NTSTATUS NTAPI
+MouclassRead(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
 {
-   PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
-   PIRP Irp = NULL;
-   KIRQL OldIrql;
-   PIO_STACK_LOCATION Stack;
-   ULONG InputCount = MouseDataEnd - MouseDataStart;
-   ULONG ReadSize;
+	DPRINT("IRP_MJ_READ\n");
 
-   DPRINT("Entering MouseClassCallBack\n");
-   /* A filter driver might have consumed all the data already; I'm
-    * not sure if they are supposed to move the packets when they
-    * consume them though.
-    */
-   if (ClassDeviceExtension->ReadIsPending == TRUE &&
-       InputCount)
-   {
-      Irp = ClassDeviceObject->CurrentIrp;
-      ClassDeviceObject->CurrentIrp = NULL;
-      Stack = IoGetCurrentIrpStackLocation(Irp);
+	if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+		return ForwardIrpAndForget(DeviceObject, Irp);
 
-      /* A read request is waiting for input, so go straight to it */
-      RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, MouseDataStart,
-                    sizeof(MOUSE_INPUT_DATA));
+	if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA))
+	{
+		Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+		Irp->IoStatus.Information = 0;
+		IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-      /* 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);
+		return STATUS_BUFFER_TOO_SMALL;
+	}
 
-      ClassDeviceExtension->ReadIsPending = FALSE;
+	IoMarkIrpPending(Irp);
+	IoStartPacket(DeviceObject, Irp, NULL, NULL);
+	return STATUS_PENDING;
+}
 
-      /* Skip the packet we just sent away */
-      MouseDataStart++;
-      (*ConsumedCount)++;
-      InputCount--;
-   }
+static NTSTATUS NTAPI
+IrpStub(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
-   /* If we have data from the port driver and a higher service to send the data to */
-   if (InputCount != 0)
-   {
-      KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
+	if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+	{
+		/* Forward some IRPs to lower device */
+		switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
+		{
+			case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+				return ForwardIrpAndForget(DeviceObject, Irp);
+			default:
+			{
+				DPRINT1("Port DO stub for major function 0x%lx\n",
+					IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+				ASSERT(FALSE);
+				Status = Irp->IoStatus.Status;
+			}
+		}
+	}
+	else if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) /* HACK FOR I8042PRT */
+	{
+		Status = STATUS_SUCCESS;
+	}
+	else
+	{
+		DPRINT1("Class DO stub for major function 0x%lx\n",
+			IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+		ASSERT(FALSE);
+		Status = Irp->IoStatus.Status;
+	}
 
-      if (ClassDeviceExtension->InputCount + InputCount > MOUSE_BUFFER_SIZE)
-      {
-         ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount;
-      } else {
-         ReadSize = InputCount;
-      }
+	Irp->IoStatus.Status = Status;
+	IoCompleteRequest(Irp, IO_NO_INCREMENT);
+	return Status;
+}
 
-      /*
-       * FIXME: If we exceed the buffer, mouse data gets thrown away.. better
-       * solution?
-       */
+static NTSTATUS
+ReadRegistryEntries(
+	IN PUNICODE_STRING RegistryPath,
+	IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
+{
+	RTL_QUERY_REGISTRY_TABLE Parameters[4];
+	NTSTATUS Status;
 
-      /*
-       * Move the mouse input data from the port data queue to our class data
-       * queue.
-       */
-      RtlMoveMemory(ClassDeviceExtension->PortData, (PCHAR)MouseDataStart,
-                    sizeof(MOUSE_INPUT_DATA) * ReadSize);
+	ULONG DefaultConnectMultiplePorts = 1;
+	ULONG DefaultMouseDataQueueSize = 0x64;
+	UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerClassPnp");
 
-      /* Move the pointer and counter up */
-      ClassDeviceExtension->PortData += ReadSize;
-      ClassDeviceExtension->InputCount += ReadSize;
+	RtlZeroMemory(Parameters, sizeof(Parameters));
 
-      KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
-      (*ConsumedCount) += ReadSize;
-   } else {
-      DPRINT("MouseClassCallBack() entered, InputCount = %d - DOING NOTHING\n", InputCount);
-   }
+	Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
+	Parameters[0].Name = L"ConnectMultiplePorts";
+	Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts;
+	Parameters[0].DefaultType = REG_DWORD;
+	Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
+	Parameters[0].DefaultLength = sizeof(ULONG);
+	
+	Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
+	Parameters[1].Name = L"MouseDataQueueSize";
+	Parameters[1].EntryContext = &DriverExtension->MouseDataQueueSize;
+	Parameters[1].DefaultType = REG_DWORD;
+	Parameters[1].DefaultData = &DefaultMouseDataQueueSize;
+	Parameters[1].DefaultLength = sizeof(ULONG);
+	
+	Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
+	Parameters[2].Name = L"PointerDeviceBaseName";
+	Parameters[2].EntryContext = &DriverExtension->PointerDeviceBaseName;
+	Parameters[2].DefaultType = REG_SZ;
+	Parameters[2].DefaultData = &DefaultPointerDeviceBaseName;
+	Parameters[2].DefaultLength = sizeof(ULONG);
 
-   if (Irp != NULL)
-   {
-      IoStartNextPacket(ClassDeviceObject, FALSE);
-      IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
-   }
+	Status = RtlQueryRegistryValues(
+		RTL_REGISTRY_ABSOLUTE,
+		RegistryPath->Buffer,
+		Parameters,
+		NULL,
+		NULL);
 
-   DPRINT("Leaving MouseClassCallBack\n");
-   return TRUE;
+	if (NT_SUCCESS(Status))
+	{
+		/* Check values */
+		if (DriverExtension->ConnectMultiplePorts != 0
+			&& DriverExtension->ConnectMultiplePorts != 1)
+		{
+			DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
+		}
+		if (DriverExtension->MouseDataQueueSize == 0)
+		{
+			DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize;
+		}
+	}
+
+	return Status;
 }
 
-static NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
+static NTSTATUS
+CreatePointerClassDeviceObject(
+	IN PDRIVER_OBJECT DriverObject,
+	OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
 {
-   PDEVICE_OBJECT PortDeviceObject = NULL;
-   PFILE_OBJECT FileObject = NULL;
-   NTSTATUS status;
-   UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
-   IO_STATUS_BLOCK ioStatus;
-   KEVENT event;
-   PIRP irp;
-   CONNECT_DATA ClassInformation;
-   PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension;
+	PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+	ULONG DeviceId = 0;
+	ULONG PrefixLength;
+	UNICODE_STRING DeviceNameU;
+	PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
+	PDEVICE_OBJECT Fdo;
+	PMOUCLASS_DEVICE_EXTENSION DeviceExtension;
+	NTSTATUS Status;
 
-   // Get the port driver's DeviceObject
-   // FIXME: The name might change.. find a way to be more dynamic?
+	DPRINT("CreatePointerClassDeviceObject(0x%p)\n", DriverObject);
 
-   status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
+	/* Create new device object */
+	DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+	DeviceNameU.Length = 0;
+	DeviceNameU.MaximumLength =
+		wcslen(L"\\Device\\") * sizeof(WCHAR)           /* "\Device\" */
+		+ DriverExtension->PointerDeviceBaseName.Length /* "PointerClass" */
+		+ 4 * sizeof(WCHAR)                             /* Id between 0 and 9999 */
+		+ sizeof(UNICODE_NULL);                         /* Final NULL char */
+	DeviceNameU.Buffer = ExAllocatePool(PagedPool, DeviceNameU.MaximumLength);
+	if (!DeviceNameU.Buffer)
+	{
+		DPRINT("ExAllocatePool() failed\n");
+		return STATUS_INSUFFICIENT_RESOURCES;
+	}
+	Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
+		goto cleanup;
+	}
+	Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->PointerDeviceBaseName);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
+		goto cleanup;
+	}
+	PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
+	DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
+	while (DeviceId < 9999)
+	{
+		DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%ld", DeviceId) * sizeof(WCHAR);
+		Status = IoCreateDevice(
+			DriverObject,
+			sizeof(MOUCLASS_DEVICE_EXTENSION),
+			&DeviceNameU,
+			FILE_DEVICE_MOUSE,
+			FILE_DEVICE_SECURE_OPEN,
+			FALSE,
+			&Fdo);
+		if (NT_SUCCESS(Status))
+			goto cleanup;
+		else if (Status != STATUS_OBJECT_NAME_COLLISION)
+		{
+			DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+			goto cleanup;
+		}
+		DeviceId++;
+	}
+	DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->PointerDeviceBaseName);
+	Status = STATUS_UNSUCCESSFUL;
+cleanup:
+	ExFreePool(DeviceNameU.Buffer);
+	if (!NT_SUCCESS(Status))
+		return Status;
 
-   if(status != STATUS_SUCCESS)
-   {
-      DPRINT("MOUCLASS: Could not connect to mouse port driver\n");
-      DPRINT("Status: %x\n", status);
-      return status;
-   }
+	DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
+	RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
+	DeviceExtension->Common.IsClassDO = TRUE;
+	DeviceExtension->DriverExtension = DriverExtension;
+	DeviceExtension->PnpState = dsStopped;
+	KeInitializeSpinLock(&(DeviceExtension->SpinLock));
+	DeviceExtension->ReadIsPending = FALSE;
+	DeviceExtension->InputCount = 0;
+	DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
+	Fdo->Flags |= DO_POWER_PAGABLE;
+	Fdo->Flags |= DO_BUFFERED_IO;
+	Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
-   DeviceExtension->PortDeviceObject = PortDeviceObject;
-   DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA));
-   DeviceExtension->InputCount = 0;
-   DeviceExtension->ReadIsPending = FALSE;
-   DeviceExtension->WorkItem = NULL;
-   KeInitializeSpinLock(&(DeviceExtension->SpinLock));
-   DeviceExtension->PassiveCallbackQueued = FALSE;
+	/* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
 
-   // Connect our callback to the port driver
+	if (ClassDO)
+		*ClassDO = Fdo;
 
-   KeInitializeEvent(&event, NotificationEvent, FALSE);
+	return STATUS_SUCCESS;
+}
 
-   ClassInformation.ClassDeviceObject = ClassDeviceObject;
-   ClassInformation.ClassService      = MouseClassCallBack;
+static BOOLEAN
+MouclassCallback(
+	IN PDEVICE_OBJECT ClassDeviceObject,
+	IN OUT PMOUSE_INPUT_DATA MouseDataStart,
+	IN PMOUSE_INPUT_DATA MouseDataEnd,
+	IN OUT PULONG ConsumedCount)
+{
+	PMOUCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
+	PIRP Irp = NULL;
+	KIRQL OldIrql;
+	PIO_STACK_LOCATION Stack;
+	ULONG InputCount = MouseDataEnd - MouseDataStart;
+	ULONG ReadSize;
 
-   irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
-      PortDeviceObject, &ClassInformation, sizeof(CONNECT_DATA), NULL, 0, TRUE, &event, &ioStatus);
+	ASSERT(ClassDeviceExtension->Common.IsClassDO);
 
-   status = IoCallDriver(DeviceExtension->PortDeviceObject, irp);
+	DPRINT("MouclassCallback()\n");
+	/* A filter driver might have consumed all the data already; I'm
+	 * not sure if they are supposed to move the packets when they
+	 * consume them though.
+	 */
+	if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
+	{
+		Irp = ClassDeviceObject->CurrentIrp;
+		ClassDeviceObject->CurrentIrp = NULL;
+		Stack = IoGetCurrentIrpStackLocation(Irp);
 
-   if (status == STATUS_PENDING) {
-      KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
-   } else {
-      ioStatus.Status = status;
-   }
+		/* A read request is waiting for input, so go straight to it */
+		RtlMoveMemory(
+			Irp->AssociatedIrp.SystemBuffer,
+			MouseDataStart,
+			sizeof(MOUSE_INPUT_DATA));
 
-   return ioStatus.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;
+
+		/* Skip the packet we just sent away */
+		MouseDataStart++;
+		(*ConsumedCount)++;
+		InputCount--;
+	}
+
+	/* If we have data from the port driver and a higher service to send the data to */
+	if (InputCount != 0)
+	{
+		KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
+
+		if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->MouseDataQueueSize)
+			ReadSize = ClassDeviceExtension->DriverExtension->MouseDataQueueSize - ClassDeviceExtension->InputCount;
+		else
+			ReadSize = InputCount;
+
+		/*
+		 * FIXME: If we exceed the buffer, mouse data gets thrown away.. better
+		 * solution?
+		*/
+
+		/*
+		 * Move the mouse input data from the port data queue to our class data
+		 * queue.
+		 */
+		RtlMoveMemory(
+			ClassDeviceExtension->PortData,
+			(PCHAR)MouseDataStart,
+			sizeof(MOUSE_INPUT_DATA) * ReadSize);
+
+		/* Move the pointer and counter up */
+		ClassDeviceExtension->PortData += ReadSize;
+		ClassDeviceExtension->InputCount += ReadSize;
+
+		KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
+		(*ConsumedCount) += ReadSize;
+	}
+	else
+	{
+		DPRINT("MouclassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount);
+	}
+
+	if (Irp != NULL)
+	{
+		IoStartNextPacket(ClassDeviceObject, FALSE);
+		IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
+	}
+
+	DPRINT("Leaving MouclassCallback()\n");
+	return TRUE;
 }
 
-static NTSTATUS STDCALL MouseClassDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/* Send IOCTL_INTERNAL_MOUSE_CONNECT to pointer port */
+static NTSTATUS
+ConnectMousePortDriver(
+	IN PDEVICE_OBJECT PointerPortDO,
+	IN PDEVICE_OBJECT PointerClassDO)
 {
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   NTSTATUS Status;
+	KEVENT Event;
+	PIRP Irp;
+	IO_STATUS_BLOCK IoStatus;
+	CONNECT_DATA ConnectData;
+	NTSTATUS Status;
 
-   switch (Stack->MajorFunction)
-   {
-      case IRP_MJ_CREATE:
-         Status = ConnectMousePortDriver(MouclassDeviceObject);
-         break;
+	KeInitializeEvent(&Event, NotificationEvent, FALSE);
 
-      case IRP_MJ_CLOSE:
-         Status = STATUS_SUCCESS;
-         break;
+	ConnectData.ClassDeviceObject = PointerClassDO;
+	ConnectData.ClassService      = MouclassCallback;
 
-      case IRP_MJ_READ:
-         if (Stack->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA))
-         {
-            Status = STATUS_BUFFER_TOO_SMALL;
-            break;
-         }
-         IoMarkIrpPending(Irp);
-         IoStartPacket(DeviceObject, Irp, NULL, NULL);
-	 return STATUS_PENDING;
+	Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
+		PointerPortDO,
+		&ConnectData, sizeof(CONNECT_DATA),
+		NULL, 0,
+		TRUE, &Event, &IoStatus);
 
-      default:
-         DPRINT1("NOT IMPLEMENTED\n");
-         Status = STATUS_NOT_IMPLEMENTED;
-         break;
-   }
+	Status = IoCallDriver(PointerPortDO, Irp);
 
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = 0;
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+	if (Status == STATUS_PENDING)
+		KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+	else
+		IoStatus.Status = Status;
 
-   return Status;
+	return IoStatus.Status;
 }
 
-static VOID STDCALL
-MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static NTSTATUS NTAPI
+MouclassAddDevice(
+	IN PDRIVER_OBJECT DriverObject,
+	IN PDEVICE_OBJECT Pdo)
 {
-   PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+	PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+	PDEVICE_OBJECT Fdo;
+	PMOUCLASS_DEVICE_EXTENSION DeviceExtension;
+	NTSTATUS Status;
 
-   if (DeviceExtension->InputCount > 0)
-   {
-      KIRQL oldIrql;
+	DPRINT("MouclassAddDevice called. Pdo = 0x%p\n", Pdo);
 
-      KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
+	DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
 
-      RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
-                    DeviceExtension->PortData - DeviceExtension->InputCount,
-                    sizeof(MOUSE_INPUT_DATA));
+	/* Create new device object */
+	Status = IoCreateDevice(
+		DriverObject,
+		sizeof(MOUCLASS_DEVICE_EXTENSION),
+		NULL,
+		Pdo->DeviceType,
+		FILE_DEVICE_SECURE_OPEN,
+		FALSE,
+		&Fdo);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+		return Status;
+	}
 
-      if (DeviceExtension->InputCount > 1)
-      {
-         RtlMoveMemory(
-            DeviceExtension->PortData - DeviceExtension->InputCount,
-            DeviceExtension->PortData - DeviceExtension->InputCount + 1,
-            (DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
-      }
-      DeviceExtension->PortData--;
-      DeviceExtension->InputCount--;
-      DeviceExtension->ReadIsPending = FALSE;
+	DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
+	RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION));
+	DeviceExtension->Common.IsClassDO = FALSE;
+	DeviceExtension->PnpState = dsStopped;
+	Fdo->Flags |= DO_POWER_PAGABLE;
+	Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
+		IoDeleteDevice(Fdo);
+		return Status;
+	}
+	Fdo->Flags |= DO_BUFFERED_IO;
+	Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
-      /* 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);
-      IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
+	if (DriverExtension->ConnectMultiplePorts)
+		Status = ConnectMousePortDriver(Fdo, DriverExtension->MainMouclassDeviceObject);
+	else
+		Status = ConnectMousePortDriver(Fdo, Fdo);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
+		/* FIXME: why can't I cleanup without error? */
+		//IoDetachDevice(Fdo);
+		//IoDeleteDevice(Fdo);
+		return Status;
+	}
 
-      IoStartNextPacket(DeviceObject, FALSE);
-      KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
-   } else {
-      DeviceExtension->ReadIsPending = TRUE;
-   }
+	/* Register GUID_DEVINTERFACE_MOUSE interface */
+	Status = IoRegisterDeviceInterface(
+		Pdo,
+		&GUID_DEVINTERFACE_MOUSE,
+		NULL,
+		&DeviceExtension->MouseInterfaceName);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
+		return Status;
+	}
+
+	return STATUS_SUCCESS;
 }
 
-NTSTATUS STDCALL
-DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+static VOID NTAPI
+MouclassStartIo(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
 {
-   PDEVICE_OBJECT DeviceObject;
-   UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Mouse");
-   UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\Mouse");
-   NTSTATUS Status;
+	PMOUCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+	PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
 
-   DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch;
-   DriverObject->MajorFunction[IRP_MJ_CLOSE]  = MouseClassDispatch;
-   DriverObject->MajorFunction[IRP_MJ_READ]   = MouseClassDispatch;
-   DriverObject->DriverStartIo                = MouseClassStartIo;
+	ASSERT(DeviceExtension->Common.IsClassDO);
 
-   Status = IoCreateDevice(DriverObject,
-			   sizeof(DEVICE_EXTENSION),
-			   &DeviceName,
-			   FILE_DEVICE_MOUSE,
-			   0,
-			   TRUE,
-			   &DeviceObject);
-   if (!NT_SUCCESS(Status))
-   {
-      return(Status);
-   }
+	if (DeviceExtension->InputCount > 0)
+	{
+		KIRQL oldIrql;
 
-   DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
+		KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
 
-   Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
-   if (!NT_SUCCESS(Status))
-   {
-      IoDeleteDevice(DeviceObject);
-      return Status;
-   }
+		RtlMoveMemory(
+			Irp->AssociatedIrp.SystemBuffer,
+			DeviceExtension->PortData - DeviceExtension->InputCount,
+			sizeof(MOUSE_INPUT_DATA));
 
-   MouclassDeviceObject = DeviceObject;
+		if (DeviceExtension->InputCount > 1)
+		{
+			RtlMoveMemory(
+				DeviceExtension->PortData - DeviceExtension->InputCount,
+				DeviceExtension->PortData - DeviceExtension->InputCount + 1,
+				(DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA));
+		}
+		DeviceExtension->PortData--;
+		DeviceExtension->InputCount--;
+		DeviceExtension->ReadIsPending = FALSE;
 
-   return STATUS_SUCCESS;
+		/* 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);
+		IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
+
+		IoStartNextPacket(DeviceObject, FALSE);
+		KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
+	}
+	else
+	{
+		DeviceExtension->ReadIsPending = TRUE;
+	}
 }
+
+static NTSTATUS
+SearchForLegacyDrivers(
+	IN PMOUCLASS_DRIVER_EXTENSION DriverExtension)
+{
+	PDEVICE_OBJECT PortDeviceObject = NULL;
+	PFILE_OBJECT FileObject = NULL;
+	UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
+	NTSTATUS Status;
+
+	/* FIXME: search for more than once legacy driver */
+
+	Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
+	if(Status != STATUS_SUCCESS)
+	{
+		DPRINT("Could not open old device object (Status 0x%08lx)\n", Status);
+		return Status;
+	}
+
+	if (DriverExtension->ConnectMultiplePorts)
+		Status = ConnectMousePortDriver(PortDeviceObject, DriverExtension->MainMouclassDeviceObject);
+	else
+	{
+		/* What to do */
+		KEBUGCHECK(0);
+	}
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status);
+		return Status;
+	}
+	return STATUS_SUCCESS;
+}
+
+/*
+ * Standard DriverEntry method.
+ */
+NTSTATUS NTAPI
+DriverEntry(
+	IN PDRIVER_OBJECT DriverObject,
+	IN PUNICODE_STRING RegistryPath)
+{
+	PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+	ULONG i;
+	NTSTATUS Status;
+
+	Status = IoAllocateDriverObjectExtension(
+		DriverObject,
+		DriverObject,
+		sizeof(MOUCLASS_DRIVER_EXTENSION),
+		(PVOID*)&DriverExtension);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
+		return Status;
+	}
+	RtlZeroMemory(DriverExtension, sizeof(MOUCLASS_DRIVER_EXTENSION));
+
+	Status = ReadRegistryEntries(RegistryPath, DriverExtension);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status);
+		return Status;
+	}
+
+	if (DriverExtension->ConnectMultiplePorts == 1)
+	{
+		Status = CreatePointerClassDeviceObject(
+			DriverObject,
+			&DriverExtension->MainMouclassDeviceObject);
+		if (!NT_SUCCESS(Status))
+		{
+			DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
+			return Status;
+		}
+	}
+
+	DriverObject->DriverExtension->AddDevice = MouclassAddDevice;
+	DriverObject->DriverUnload = DriverUnload;
+
+	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+		DriverObject->MajorFunction[i] = IrpStub;
+
+	DriverObject->MajorFunction[IRP_MJ_CREATE] = MouclassCreate;
+	DriverObject->MajorFunction[IRP_MJ_CLOSE]  = MouclassClose;
+	DriverObject->MajorFunction[IRP_MJ_READ]   = MouclassRead;
+	DriverObject->DriverStartIo                = MouclassStartIo;
+
+	SearchForLegacyDrivers(DriverExtension);
+
+	return STATUS_SUCCESS;
+}

Modified: trunk/reactos/drivers/input/mouclass/mouclass.h
--- trunk/reactos/drivers/input/mouclass/mouclass.h	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/drivers/input/mouclass/mouclass.h	2005-10-31 00:14:45 UTC (rev 18906)
@@ -1,11 +1,65 @@
-#define MOUSE_BUFFER_SIZE 100
+#include <ntddk.h>
+#include <kbdmou.h>
+#include <ntddmou.h>
+#include <stdio.h>
 
-typedef struct _DEVICE_EXTENSION {
-   PIO_WORKITEM WorkItem;
-   KSPIN_LOCK SpinLock;
-   BOOLEAN PassiveCallbackQueued;
-   BOOLEAN ReadIsPending;
-   ULONG InputCount;
-   PMOUSE_INPUT_DATA PortData;
-   PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject)
-} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+#if defined(__GNUC__)
+  NTSTATUS NTAPI
+  IoAttachDeviceToDeviceStackSafe(
+    IN PDEVICE_OBJECT SourceDevice,
+    IN PDEVICE_OBJECT TargetDevice,
+    OUT PDEVICE_OBJECT *AttachedToDeviceObject);
+#else
+  #error Unknown compiler!
+#endif
+
+typedef enum
+{
+	dsStopped,
+	dsStarted,
+	dsPaused,
+	dsRemoved,
+	dsSurpriseRemoved
+} MOUCLASS_DEVICE_STATE;
+
+typedef struct _MOUCLASS_DRIVER_EXTENSION
+{
+	/* Registry settings */
+	ULONG ConnectMultiplePorts;
+	ULONG MouseDataQueueSize;
+	UNICODE_STRING PointerDeviceBaseName;
+
+	PDEVICE_OBJECT MainMouclassDeviceObject;
+} MOUCLASS_DRIVER_EXTENSION, *PMOUCLASS_DRIVER_EXTENSION;
+
+typedef struct _COMMON_DEVICE_EXTENSION
+{
+	BOOLEAN IsClassDO;
+} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
+
+typedef struct _MOUPORT_DEVICE_EXTENSION
+{
+	COMMON_DEVICE_EXTENSION Common;
+} MOUPORT_DEVICE_EXTENSION, *PMOUPORT_DEVICE_EXTENSION;
+
+typedef struct _MOUCLASS_DEVICE_EXTENSION
+{
+	COMMON_DEVICE_EXTENSION Common;
+
+	MOUCLASS_DEVICE_STATE PnpState;
+	PMOUCLASS_DRIVER_EXTENSION DriverExtension;
+	PDEVICE_OBJECT LowerDevice;
+	UNICODE_STRING MouseInterfaceName;
+
+	KSPIN_LOCK SpinLock;
+	BOOLEAN ReadIsPending;
+	ULONG InputCount;
+	PMOUSE_INPUT_DATA PortData;
+} MOUCLASS_DEVICE_EXTENSION, *PMOUCLASS_DEVICE_EXTENSION;
+
+/* misc.c */
+
+NTSTATUS NTAPI
+ForwardIrpAndForget(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp);

Modified: trunk/reactos/drivers/input/mouclass/mouclass.xml
--- trunk/reactos/drivers/input/mouclass/mouclass.xml	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/drivers/input/mouclass/mouclass.xml	2005-10-31 00:14:45 UTC (rev 18906)
@@ -3,6 +3,7 @@
 	<define name="__USE_W32API" />
 	<library>ntoskrnl</library>
 	<library>hal</library>
+	<file>misc.c</file>
 	<file>mouclass.c</file>
 	<file>mouclass.rc</file>
 </module>

Modified: trunk/reactos/subsys/win32k/ntuser/input.c
--- trunk/reactos/subsys/win32k/ntuser/input.c	2005-10-31 00:10:32 UTC (rev 18905)
+++ trunk/reactos/subsys/win32k/ntuser/input.c	2005-10-31 00:14:45 UTC (rev 18906)
@@ -151,7 +151,7 @@
 VOID STDCALL
 MouseThreadMain(PVOID StartContext)
 {
[truncated at 1000 lines; 59 more skipped]