Major update of Green driver:
authorHervé Poussineau <hpoussin@reactos.org>
Sun, 19 Feb 2006 18:05:01 +0000 (18:05 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Sun, 19 Feb 2006 18:05:01 +0000 (18:05 +0000)
- Add PnP support (stack over the serial port, and enumerate 2 attached devices: a screen and a keyboard)
- Read some parameters from registry (buffer size is still not configurable)

svn path=/trunk/; revision=21165

reactos/drivers/base/green/createclose.c
reactos/drivers/base/green/dispatch.c
reactos/drivers/base/green/green.c
reactos/drivers/base/green/green.h
reactos/drivers/base/green/green.inf [new file with mode: 0644]
reactos/drivers/base/green/green.rbuild
reactos/drivers/base/green/keyboard.c
reactos/drivers/base/green/misc.c
reactos/drivers/base/green/pnp.c
reactos/drivers/base/green/power.c [new file with mode: 0644]
reactos/drivers/base/green/screen.c

index 0d63f2b..c1dc2ec 100644 (file)
@@ -1,23 +1,22 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/createclose.c
- * PURPOSE:         IRP_MJ_CREATE, IRP_MJ_CLOSE and IRP_MJ_CLEANUP operations
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/createclose.c
+ * PURPOSE:     IRP_MJ_CREATE, IRP_MJ_CLOSE and IRP_MJ_CLEANUP operations
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
-//#define NDEBUG
-#include <debug.h>
-
 #include "green.h"
 
+#define NDEBUG
+#include <debug.h>
+
 NTSTATUS NTAPI
 GreenCreate(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP Irp)
 {
-       DPRINT("Green: IRP_MJ_CREATE\n");
+       DPRINT("IRP_MJ_CREATE\n");
 
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
@@ -30,7 +29,7 @@ GreenClose(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP Irp)
 {
-       DPRINT("Green: IRP_MJ_CLOSE\n");
+       DPRINT("IRP_MJ_CLOSE\n");
 
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
index 0d10708..57f2b90 100644 (file)
@@ -1,17 +1,16 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/dispatch.c
- * PURPOSE:         Dispatch routines
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/dispatch.c
+ * PURPOSE:     Dispatch routines
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
+#include "green.h"
+
 #define NDEBUG
 #include <debug.h>
 
-#include "green.h"
-
 NTSTATUS NTAPI
 GreenDispatch(
        IN PDEVICE_OBJECT DeviceObject,
@@ -28,35 +27,56 @@ GreenDispatch(
        Information = Irp->IoStatus.Information;
        Status = Irp->IoStatus.Status;
 
-       DPRINT("Green: Dispatching major function 0x%lx, DeviceType %d\n",
+       DPRINT("Dispatching major function 0x%lx, DeviceType %u\n",
                MajorFunction, DeviceType);
 
-       if (MajorFunction == IRP_MJ_CREATE && DeviceType == Green)
+       if (DeviceType == PassThroughFDO)
+       {
+               IoSkipCurrentIrpStackLocation(Irp);
+               return IoCallDriver(((PCOMMON_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice, Irp);
+       }
+       else if (MajorFunction == IRP_MJ_CREATE && (DeviceType == GreenFDO || DeviceType == KeyboardPDO || DeviceType == ScreenPDO))
                return GreenCreate(DeviceObject, Irp);
-       else if (MajorFunction == IRP_MJ_CLOSE && DeviceType == Green)
+       else if (MajorFunction == IRP_MJ_CLOSE && (DeviceType == GreenFDO || DeviceType == KeyboardPDO || DeviceType == ScreenPDO))
                return GreenClose(DeviceObject, Irp);
-       else if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && DeviceType == Green)
+       else if ((MajorFunction == IRP_MJ_CREATE || MajorFunction == IRP_MJ_CLOSE || MajorFunction == IRP_MJ_CLEANUP)
+               && (DeviceType == KeyboardFDO || DeviceType == ScreenFDO))
+       {
+               IoSkipCurrentIrpStackLocation(Irp);
+               return IoCallDriver(((PCOMMON_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice, Irp);
+       }
+       else if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && DeviceType == GreenFDO)
        {
                return KeyboardInternalDeviceControl(
-                       ((PGREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Keyboard,
+                       ((PGREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->KeyboardFdo,
                        Irp);
        }
-       else if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && DeviceType == Keyboard)
+       else if (MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && DeviceType == KeyboardFDO)
                return KeyboardInternalDeviceControl(DeviceObject, Irp);
-       else if (MajorFunction == IRP_MJ_DEVICE_CONTROL && DeviceType == Green)
+       else if (MajorFunction == IRP_MJ_DEVICE_CONTROL && DeviceType == GreenFDO)
        {
                return ScreenDeviceControl(
-                       ((PGREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Screen,
+                       ((PGREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ScreenFdo,
                        Irp);
        }
-       else if (MajorFunction == IRP_MJ_DEVICE_CONTROL && DeviceType == Screen)
+       else if (MajorFunction == IRP_MJ_DEVICE_CONTROL && DeviceType == ScreenFDO)
                return ScreenDeviceControl(DeviceObject, Irp);
-       else if (MajorFunction == IRP_MJ_WRITE && DeviceType == Screen)
+       else if (MajorFunction == IRP_MJ_WRITE && DeviceType == ScreenFDO)
                return ScreenWrite(DeviceObject, Irp);
+       else if (MajorFunction == IRP_MJ_PNP && (DeviceType == KeyboardFDO || DeviceType == ScreenFDO))
+       {
+               IoSkipCurrentIrpStackLocation(Irp);
+               return IoCallDriver(((PCOMMON_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice, Irp);
+       }
+       else if (MajorFunction == IRP_MJ_PNP && (DeviceType == GreenFDO || DeviceType == KeyboardPDO || DeviceType == ScreenPDO))
+               return GreenPnp(DeviceObject, Irp);
+       else if (MajorFunction == IRP_MJ_POWER && DeviceType == GreenFDO)
+               return GreenPower(DeviceObject, Irp);
        else
        {
-               DPRINT1("Green: unknown combination: MajorFunction 0x%lx, DeviceType %d\n",
+               DPRINT1("Unknown combination: MajorFunction 0x%lx, DeviceType %d\n",
                        MajorFunction, DeviceType);
+               ASSERT(FALSE);
        }
 
        Irp->IoStatus.Information = Information;
index a30ab3e..5834f3b 100644 (file)
@@ -1,17 +1,16 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/green.c
- * PURPOSE:         Driver entry point
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/green.c
+ * PURPOSE:     Driver entry point
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
-//#define NDEBUG
-#include <debug.h>
-
 #include "green.h"
 
+#define NDEBUG
+#include <debug.h>
+
 VOID NTAPI
 DriverUnload(IN PDRIVER_OBJECT DriverObject)
 {
@@ -24,22 +23,46 @@ DriverUnload(IN PDRIVER_OBJECT DriverObject)
 NTSTATUS NTAPI
 DriverEntry(
        IN PDRIVER_OBJECT DriverObject,
-       IN PUNICODE_STRING RegPath)
+       IN PUNICODE_STRING RegistryPath)
 {
+       PGREEN_DRIVER_EXTENSION DriverExtension;
        ULONG i;
+       NTSTATUS Status;
+
+       Status = IoAllocateDriverObjectExtension(
+               DriverObject,
+               DriverObject,
+               sizeof(GREEN_DRIVER_EXTENSION),
+               (PVOID*)&DriverExtension);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+       RtlZeroMemory(DriverExtension, sizeof(GREEN_DRIVER_EXTENSION));
+
+       Status = RtlDuplicateUnicodeString(
+               0,
+               RegistryPath,
+               &DriverExtension->RegistryPath);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("RtlDuplicateUnicodeString() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       Status = ReadRegistryEntries(RegistryPath, DriverExtension);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
 
        DriverObject->DriverUnload = DriverUnload;
        DriverObject->DriverExtension->AddDevice = GreenAddDevice;
 
-       for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+       for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
                DriverObject->MajorFunction[i] = GreenDispatch;
 
-       /* keyboard only */
-       //DriverObject->DriverStartIo = GreenStartIo;
-
-       /* keyboard and screen */
-       DriverObject->MajorFunction[IRP_MJ_CREATE] = GreenCreate;
-       DriverObject->MajorFunction[IRP_MJ_CLOSE] = GreenClose;
-
        return STATUS_SUCCESS;
 }
index 0915ee7..1b8a27c 100644 (file)
@@ -9,14 +9,28 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;
 #include <wincon.h>
 #include <drivers/blue/ntddblue.h>
 
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlDuplicateUnicodeString(
+    IN ULONG Flags,
+    IN PCUNICODE_STRING SourceString,
+    OUT PUNICODE_STRING DestinationString
+);
+#define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE         1
+
 #define INFINITE -1
 #define KEYBOARD_BUFFER_SIZE 100
 
 typedef enum
 {
-       Green,
-       Screen,
-       Keyboard
+       GreenPDO,
+       ScreenPDO,
+       KeyboardPDO,
+       GreenFDO,
+       ScreenFDO,
+       KeyboardFDO,
+       PassThroughFDO,
 } GREEN_DEVICE_TYPE;
 
 typedef struct _COMMON_DEVICE_EXTENSION
@@ -24,9 +38,17 @@ typedef struct _COMMON_DEVICE_EXTENSION
        GREEN_DEVICE_TYPE Type;
 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
+/* For PassThroughFDO devices */
+typedef struct _COMMON_FDO_DEVICE_EXTENSION
+{
+       GREEN_DEVICE_TYPE Type;
+       PDEVICE_OBJECT LowerDevice;
+} COMMON_FDO_DEVICE_EXTENSION, *PCOMMON_FDO_DEVICE_EXTENSION;
+
+/* For KeyboardFDO devices */
 typedef struct _KEYBOARD_DEVICE_EXTENSION
 {
-       COMMON_DEVICE_EXTENSION Common;
+       COMMON_FDO_DEVICE_EXTENSION Common;
        PDEVICE_OBJECT Green;
 
        CONNECT_DATA ClassInformation;
@@ -38,9 +60,10 @@ typedef struct _KEYBOARD_DEVICE_EXTENSION
        KEYBOARD_INPUT_DATA KeyboardInputData[2][KEYBOARD_BUFFER_SIZE];
 } KEYBOARD_DEVICE_EXTENSION, *PKEYBOARD_DEVICE_EXTENSION;
 
+/* For ScreenFDO devices */
 typedef struct _SCREEN_DEVICE_EXTENSION
 {
-       COMMON_DEVICE_EXTENSION Common;
+       COMMON_FDO_DEVICE_EXTENSION Common;
        PDEVICE_OBJECT Green;
 
        PUCHAR VideoMemory;   /* Pointer to video memory */
@@ -58,20 +81,32 @@ typedef struct _SCREEN_DEVICE_EXTENSION
        PDEVICE_OBJECT PreviousBlue;
 } SCREEN_DEVICE_EXTENSION, *PSCREEN_DEVICE_EXTENSION;
 
+/* For GreenFDO devices */
 typedef struct _GREEN_DEVICE_EXTENSION
 {
-       COMMON_DEVICE_EXTENSION Common;
+       COMMON_FDO_DEVICE_EXTENSION Common;
        PDEVICE_OBJECT Serial;
 
-       PDEVICE_OBJECT LowerDevice;
-       ULONG BaudRate;
        SERIAL_LINE_CONTROL LineControl;
        SERIAL_TIMEOUTS Timeouts;
 
-       PDEVICE_OBJECT Keyboard;
-       PDEVICE_OBJECT Screen;
+       PDEVICE_OBJECT KeyboardPdo;
+       PDEVICE_OBJECT ScreenPdo;
+       PDEVICE_OBJECT KeyboardFdo;
+       PDEVICE_OBJECT ScreenFdo;
 } GREEN_DEVICE_EXTENSION, *PGREEN_DEVICE_EXTENSION;
 
+typedef struct _GREEN_DRIVER_EXTENSION
+{
+       UNICODE_STRING RegistryPath;
+
+       UNICODE_STRING AttachedDeviceName;
+       ULONG DeviceReported;
+       ULONG SampleRate;
+
+       PDEVICE_OBJECT GreenMainDO;
+} GREEN_DRIVER_EXTENSION, *PGREEN_DRIVER_EXTENSION;
+
 /************************************ createclose.c */
 
 NTSTATUS NTAPI
@@ -94,9 +129,9 @@ GreenDispatch(
 /************************************ keyboard.c */
 
 NTSTATUS
-KeyboardInitialize(
+KeyboardAddDevice(
        IN PDRIVER_OBJECT DriverObject,
-       OUT PDEVICE_OBJECT* KeyboardFdo);
+       IN PDEVICE_OBJECT Pdo);
 
 NTSTATUS
 KeyboardInternalDeviceControl(
@@ -114,6 +149,11 @@ GreenDeviceIoControl(
        IN OUT PVOID OutputBuffer OPTIONAL,
        IN OUT PULONG OutputBufferSize);
 
+NTSTATUS
+ReadRegistryEntries(
+       IN PUNICODE_STRING RegistryPath,
+       IN PGREEN_DRIVER_EXTENSION DriverExtension);
+
 /************************************ pnp.c */
 
 NTSTATUS NTAPI
@@ -121,12 +161,24 @@ GreenAddDevice(
        IN PDRIVER_OBJECT DriverObject,
        IN PDEVICE_OBJECT Pdo);
 
+NTSTATUS
+GreenPnp(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
+/************************************ power.c */
+
+NTSTATUS
+GreenPower(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
 /************************************ screen.c */
 
 NTSTATUS
-ScreenInitialize(
+ScreenAddDevice(
        IN PDRIVER_OBJECT DriverObject,
-       OUT PDEVICE_OBJECT* ScreenFdo);
+       IN PDEVICE_OBJECT Pdo);
 
 NTSTATUS
 ScreenWrite(
diff --git a/reactos/drivers/base/green/green.inf b/reactos/drivers/base/green/green.inf
new file mode 100644 (file)
index 0000000..b7a3754
--- /dev/null
@@ -0,0 +1,96 @@
+; GREEN.INF
+
+; Installation file for Green (VT100 server emulator) driver
+
+[Version]
+Signature  = "$Windows NT$"
+;Signature  = "$ReactOS$"
+LayoutFile = layout.inf
+Class      = System
+ClassGUID  = {4D36E97D-E325-11CE-BFC1-08002BE10318}
+Provider   = %ReactOS%
+DriverVer  = 12/7/2005,1.00
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+[Manufacturer]
+%ReactOSMfg% = ReactOSMfg
+
+[ReactOSMfg]
+%KEYBOARD.DeviceDesc% = Keyboard_Inst,GREEN\KEYBOARD
+%SCREEN.DeviceDesc% = Screen_Inst,GREEN\SCREEN
+
+;----------------------------- GREEN DRIVER -----------------------------
+
+[DefaultInstall.NT]
+CopyFiles = Green_CopyFiles.NT
+AddReg = Green_AddReg.NT
+
+[Green_CopyFiles.NT]
+green.sys
+
+[DefaultInstall.NT.Services]
+AddService = green, 0x00000002, green_Service_Inst
+
+[green_Service_Inst]
+ServiceType    = 1
+StartType      = 1
+ErrorControl   = 0
+ServiceBinary  = %12%\green.sys
+LoadOrderGroup = Video Init
+Description    = %GREEN.DriverDesc%
+Dependencies   = blue
+
+[Green_AddReg.NT]
+HKLM,"SYSTEM\CurrentControlSet\Services\green\Parameters","AttachedDevice",0x00000000,"\Device\Serial1"
+
+[DefaultUninstall.NT]
+DelFiles = Green_DelFiles.NT
+DelReg = Green_DelReg.NT
+
+[DefaultUninstall.NT.Services]
+DelService = green, 0x00000200
+
+[Green_DelFiles.NT]
+green.sys,,,0x00000001
+
+[Green_DelReg.NT]
+HKLM,"SYSTEM\CurrentControlSet\Services\green\Parameters"
+
+;---------------------------- KEYBOARD DEVICE ---------------------------
+
+[Keyboard_Inst.NT]
+CopyFiles = Green_CopyFiles.NT
+Include = keyboard.inf
+Needs = STANDARD_Inst
+
+[Keyboard_Inst.NT.HW]
+AddReg = Keyboard_AddReg.NT
+
+[Keyboard_AddReg.NT]
+HKR, , "UpperFilters", 0x00010000, "kbdclass"
+
+[Keyboard_Inst.NT.Services]
+AddService = green, 0x00000002, green_Service_Inst
+Include = msmouse.inf
+Needs = PS2_Inst.Services
+
+;----------------------------- SCREEN DEVICE ----------------------------
+
+[Screen_Inst.NT]
+CopyFiles = Green_CopyFiles.NT
+
+[Screen_Inst.NT.Services]
+AddService = green, 0x00000002, green_Service_Inst
+
+;-------------------------------- STRINGS -------------------------------
+
+[Strings]
+ReactOS = "ReactOS Team"
+
+GREEN.DriverDesc = "VT100 server emulator"
+
+ReactOSMfg = "(ReactOS Team)"
+KEYBOARD.DeviceDesc = "Keyboard for remote console"
+SCREEN.DeviceDesc = "Screen for remote console"
index 39f0e66..1c0b6a8 100644 (file)
@@ -1,6 +1,6 @@
 <module name="green" type="kernelmodedriver" installbase="system32/drivers" installname="green.sys">
        <bootstrap base="reactos" />
-        <define name="__USE_W32API" />
+       <define name="__USE_W32API" />
        <library>ntoskrnl</library>
        <library>hal</library>
        <file>createclose.c</file>
@@ -9,6 +9,7 @@
        <file>keyboard.c</file>
        <file>misc.c</file>
        <file>pnp.c</file>
+       <file>power.c</file>
        <file>screen.c</file>
        <file>green.rc</file>
        <pch>green.h</pch>
index 16c86cd..0a4b195 100644 (file)
@@ -1,17 +1,16 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/keyboard.c
- * PURPOSE:         Keyboard part of green management
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/dd/green/keyboard.c
+ * PURPOSE:     Keyboard part of green management
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
+#include "green.h"
+
 #define NDEBUG
 #include <debug.h>
 
-#include "green.h"
-
 static BOOLEAN
 TranslateCharToScanCodes(
        IN PUCHAR InputBuffer,
@@ -100,27 +99,26 @@ TranslateCharToScanCodes(
        }
 
        /* Consume strange character by ignoring it */
-       DPRINT1("Green: strange byte received 0x%02x ('%c')\n",
+       DPRINT1("Strange byte received 0x%02x ('%c')\n",
                *InputBuffer, *InputBuffer >= 32 ? *InputBuffer : '.');
        *BytesConsumed = 1;
        return TRUE;
 }
 
 NTSTATUS
-KeyboardInitialize(
+KeyboardAddDevice(
        IN PDRIVER_OBJECT DriverObject,
-       OUT PDEVICE_OBJECT* KeyboardFdo)
+       IN PDEVICE_OBJECT Pdo)
 {
        PDEVICE_OBJECT Fdo;
        PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
-       UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass1");
        NTSTATUS Status;
 
-       DPRINT("Green: KeyboardInitialize() called\n");
+       DPRINT("KeyboardInitialize() called\n");
 
        Status = IoCreateDevice(DriverObject,
                sizeof(KEYBOARD_DEVICE_EXTENSION),
-               &DeviceName, /* FIXME: don't hardcode string */
+               NULL,
                FILE_DEVICE_KEYBOARD,
                FILE_DEVICE_SECURE_OPEN,
                TRUE,
@@ -130,12 +128,13 @@ KeyboardInitialize(
 
        DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)Fdo->DeviceExtension;
        RtlZeroMemory(DeviceExtension, sizeof(KEYBOARD_DEVICE_EXTENSION));
-       DeviceExtension->Common.Type = Keyboard;
+       DeviceExtension->Common.Type = KeyboardFDO;
+       DeviceExtension->Common.LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo);
+       DeviceExtension->Green = ((PGREEN_DRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject, DriverObject))->GreenMainDO;
+       ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->KeyboardFdo = Fdo;
        Fdo->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO;
        Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
-       *KeyboardFdo = Fdo;
-
        return STATUS_SUCCESS;
 }
 
@@ -157,11 +156,12 @@ KeyboardDpcSendData(
        (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.ClassService)(
                        DeviceExtension->ClassInformation.ClassDeviceObject,
                        DeviceExtension->KeyboardInputData[Queue],
-                       &DeviceExtension->KeyboardInputData[Queue][DeviceExtension->InputDataCount[Queue]],
+                       DeviceExtension->KeyboardInputData[Queue] + DeviceExtension->InputDataCount[Queue],
                        &InputDataConsumed);
 
        DeviceExtension->InputDataCount[Queue] = 0;
 }
+
 static VOID NTAPI
 KeyboardDeviceWorker(
        PVOID Context)
@@ -172,6 +172,7 @@ KeyboardDeviceWorker(
        PDEVICE_OBJECT LowerDevice;
        UCHAR Buffer[16]; /* Arbitrary size */
        ULONG BufferSize;
+       LARGE_INTEGER Zero;
        PIRP Irp;
        IO_STATUS_BLOCK ioStatus;
        KEVENT event;
@@ -182,13 +183,14 @@ KeyboardDeviceWorker(
        PKEYBOARD_INPUT_DATA Input;
        NTSTATUS Status;
 
-       DPRINT("Green: KeyboardDeviceWorker() called\n");
+       DPRINT("KeyboardDeviceWorker() called\n");
 
        DeviceObject = (PDEVICE_OBJECT)Context;
        DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
        GreenDeviceExtension = (PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension;
        LowerDevice = GreenDeviceExtension->Serial;
        BufferSize = sizeof(Buffer);
+       Zero.QuadPart = 0;
 
        /* Initialize device extension */
        DeviceExtension->ActiveQueue = 0;
@@ -205,7 +207,7 @@ KeyboardDeviceWorker(
                        IRP_MJ_READ,
                        LowerDevice,
                        Buffer, BufferSize,
-                       0,
+                       &Zero,
                        &event,
                        &ioStatus);
                if (!Irp)
@@ -242,7 +244,7 @@ KeyboardDeviceWorker(
                                &SpaceInQueue,            /* output buffer size */
                                &BytesConsumed))          /* bytes consumed in input buffer */
                        {
-                               DPRINT1("Green: got char 0x%02x (%c)\n", Buffer[i], Buffer[i] >= 32 ? Buffer[i] : ' ');
+                               DPRINT("Got char 0x%02x (%c)\n", Buffer[i], Buffer[i] >= 32 ? Buffer[i] : ' ');
                                DeviceExtension->InputDataCount[Queue] += BytesConsumed;
 
                                /* Send the data to the keyboard class driver */
@@ -274,25 +276,17 @@ KeyboardInternalDeviceControl(
 {
        PIO_STACK_LOCATION Stack;
        PKEYBOARD_DEVICE_EXTENSION DeviceExtension;
-       PGREEN_DEVICE_EXTENSION GreenDeviceExtension;
-       OBJECT_ATTRIBUTES objectAttributes;
-       PDEVICE_OBJECT LowerDevice;
        NTSTATUS Status;
 
        Stack = IoGetCurrentIrpStackLocation(Irp);
        Irp->IoStatus.Information = 0;
        DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       GreenDeviceExtension = (PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension;
-       LowerDevice = GreenDeviceExtension->Serial;
-       DPRINT1("Green: LowerDevice %p\n", LowerDevice);
 
        switch (Stack->Parameters.DeviceIoControl.IoControlCode)
        {
                case IOCTL_INTERNAL_KEYBOARD_CONNECT:
                {
-                       ULONG Fcr;
-
-                       DPRINT("Green: IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
+                       DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
                        if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
                        {
                                Status = STATUS_INVALID_PARAMETER;
@@ -302,31 +296,11 @@ KeyboardInternalDeviceControl(
                        DeviceExtension->ClassInformation =
                                *((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
 
-                       /* Initialize serial port */
-                       Fcr = 0;
-                       Status = GreenDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
-                               &Fcr, sizeof(Fcr), NULL, NULL);
-                       if (!NT_SUCCESS(Status)) break;
-                       /* Set serial port speed */
-                       Status = GreenDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
-                               &GreenDeviceExtension->BaudRate, sizeof(GreenDeviceExtension->BaudRate), NULL, NULL);
-                       if (!NT_SUCCESS(Status)) break;
-                       /* Set LCR */
-                       Status = GreenDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
-                               &GreenDeviceExtension->LineControl, sizeof(GreenDeviceExtension->LineControl), NULL, NULL);
-                       if (!NT_SUCCESS(Status)) break;
-
-                       /* Set timeouts */
-                       Status = GreenDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
-                               &GreenDeviceExtension->Timeouts, sizeof(GreenDeviceExtension->Timeouts), NULL, NULL);
-                       if (!NT_SUCCESS(Status)) break;
-
                        /* Start read loop */
-                       InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
                        Status = PsCreateSystemThread(
                                &DeviceExtension->WorkerThreadHandle,
                                (ACCESS_MASK)0L,
-                               &objectAttributes,
+                               NULL,
                                NULL,
                                NULL,
                                KeyboardDeviceWorker,
@@ -335,7 +309,7 @@ KeyboardInternalDeviceControl(
                }
                default:
                {
-                       DPRINT("Green: IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
+                       DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
                                Stack->Parameters.DeviceIoControl.IoControlCode);
                        Status = STATUS_INVALID_DEVICE_REQUEST;
                }
index de9bdd0..b467146 100644 (file)
@@ -1,17 +1,16 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/misc.c
- * PURPOSE:         Misceallenous operations
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/misc.c
+ * PURPOSE:     Misceallenous operations
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
-//#define NDEBUG
-#include <debug.h>
-
 #include "green.h"
 
+#define NDEBUG
+#include <debug.h>
+
 NTSTATUS
 GreenDeviceIoControl(
        IN PDEVICE_OBJECT DeviceObject,
@@ -39,7 +38,7 @@ GreenDeviceIoControl(
                &IoStatus);
        if (Irp == NULL)
        {
-               DPRINT("Green: IoBuildDeviceIoControlRequest() failed\n");
+               DPRINT("IoBuildDeviceIoControlRequest() failed\n");
                return STATUS_INSUFFICIENT_RESOURCES;
        }
 
@@ -47,7 +46,7 @@ GreenDeviceIoControl(
 
        if (Status == STATUS_PENDING)
        {
-               DPRINT("Green: Operation pending\n");
+               DPRINT("Operation pending\n");
                KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
                Status = IoStatus.Status;
        }
@@ -59,3 +58,57 @@ GreenDeviceIoControl(
 
        return Status;
 }
+
+NTSTATUS
+ReadRegistryEntries(
+       IN PUNICODE_STRING RegistryPath,
+       IN PGREEN_DRIVER_EXTENSION DriverExtension)
+{
+       UNICODE_STRING ParametersRegistryKey;
+       RTL_QUERY_REGISTRY_TABLE Parameters[4];
+       NTSTATUS Status;
+
+       ULONG DefaultDeviceReported = 0;
+       ULONG DefaultSampleRate = 1200;
+
+       ParametersRegistryKey.Length = 0;
+       ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
+       ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength);
+       if (!ParametersRegistryKey.Buffer)
+       {
+               DPRINT("ExAllocatePool() failed\n");
+               return STATUS_INSUFFICIENT_RESOURCES;
+       }
+       RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
+       RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
+       ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
+
+       RtlZeroMemory(Parameters, sizeof(Parameters));
+
+       Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+       Parameters[0].Name = L"AttachedDevice";
+       Parameters[0].EntryContext = &DriverExtension->AttachedDeviceName;
+
+       Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
+       Parameters[1].Name = L"DeviceReported";
+       Parameters[1].EntryContext = &DriverExtension->DeviceReported;
+       Parameters[1].DefaultType = REG_DWORD;
+       Parameters[1].DefaultData = &DefaultDeviceReported;
+       Parameters[1].DefaultLength = sizeof(ULONG);
+
+       Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
+       Parameters[2].Name = L"SampleRate";
+       Parameters[2].EntryContext = &DriverExtension->SampleRate;
+       Parameters[2].DefaultType = REG_DWORD;
+       Parameters[2].DefaultData = &DefaultSampleRate;
+       Parameters[2].DefaultLength = sizeof(ULONG);
+
+       Status = RtlQueryRegistryValues(
+               RTL_REGISTRY_ABSOLUTE,
+               ParametersRegistryKey.Buffer,
+               Parameters,
+               NULL,
+               NULL);
+
+       return Status;
+}
index 2cd884e..c4e462f 100644 (file)
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/pnp.c
- * PURPOSE:         IRP_MJ_PNP operations
- *
- * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/pnp.c
+ * PURPOSE:     IRP_MJ_PNP operations
+ * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
+#include "green.h"
+
 #define NDEBUG
 #include <debug.h>
 
-#include "green.h"
-
-NTSTATUS NTAPI
-GreenAddDevice(
+static NTSTATUS
+CreateGreenFdo(
        IN PDRIVER_OBJECT DriverObject,
-       IN PDEVICE_OBJECT Pdo)
+       IN PDEVICE_OBJECT GreenPdo)
 {
-       PDEVICE_OBJECT Fdo = NULL;
-       PGREEN_DEVICE_EXTENSION DeviceExtension;
-       UNICODE_STRING serialPortName;
+       PGREEN_DRIVER_EXTENSION DriverExtension = NULL;
+       PGREEN_DEVICE_EXTENSION DeviceExtension = NULL;
+       OBJECT_ATTRIBUTES ObjectAttributes;
+       ULONG Fcr;
+       HANDLE LocalHandle = 0;
+       ACCESS_MASK DesiredAccess = 0; /* FIXME */
        NTSTATUS Status;
 
-       DPRINT("Green: AddDevice(DriverObject %p, Pdo %p)\n", DriverObject, Pdo);
+       DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
 
-       /* Create green FDO */
        Status = IoCreateDevice(DriverObject,
                sizeof(GREEN_DEVICE_EXTENSION),
                NULL,
-               FILE_DEVICE_UNKNOWN,
+               FILE_DEVICE_TERMSRV,
                FILE_DEVICE_SECURE_OPEN,
-               TRUE,
-               &Fdo);
-
+               FALSE,
+               &DriverExtension->GreenMainDO);
        if (!NT_SUCCESS(Status))
        {
-               DPRINT1("Status = %08lx\n", Status);
-               return Status;
+               DPRINT("IoCreateDevice() failed with status %08lx\n", Status);
+               goto cleanup;
        }
 
-       DeviceExtension = (PGREEN_DEVICE_EXTENSION)Fdo->DeviceExtension;
+       DeviceExtension = (PGREEN_DEVICE_EXTENSION)DriverExtension->GreenMainDO->DeviceExtension;
        RtlZeroMemory(DeviceExtension, sizeof(GREEN_DEVICE_EXTENSION));
-       DeviceExtension->Common.Type = Green;
+       DeviceExtension->Common.Type = GreenFDO;
+       DriverExtension->GreenMainDO->Flags |= DO_POWER_PAGABLE;
+       IoAttachDeviceToDeviceStack(DriverExtension->GreenMainDO, GreenPdo);
 
-       Status = KeyboardInitialize(DriverObject, &DeviceExtension->Keyboard);
+       /* Initialize serial port */
+       InitializeObjectAttributes(&ObjectAttributes, &DriverExtension->AttachedDeviceName, OBJ_KERNEL_HANDLE, NULL, NULL);
+       Status = ObOpenObjectByName(
+               &ObjectAttributes,
+               IoDeviceObjectType,
+               NULL,
+               KernelMode,
+               DesiredAccess,
+               NULL,
+               &LocalHandle);
        if (!NT_SUCCESS(Status))
        {
-               IoDeleteDevice(Fdo);
-               DPRINT1("Status = %08lx\n", Status);
-               return Status;
+               DPRINT("ObOpenObjectByName() failed with status %08lx\n", Status);
+               goto cleanup;
        }
-       ((PKEYBOARD_DEVICE_EXTENSION)DeviceExtension->Keyboard->DeviceExtension)->Green = Fdo;
-
-       Status = ScreenInitialize(DriverObject, &DeviceExtension->Screen);
+       Status = ObReferenceObjectByHandle(
+               LocalHandle,
+               DesiredAccess,
+               NULL,
+               KernelMode,
+               (PVOID*)&DeviceExtension->Serial,
+               NULL);
        if (!NT_SUCCESS(Status))
        {
-               IoDeleteDevice(DeviceExtension->Keyboard);
-               IoDeleteDevice(Fdo);
-               DPRINT1("Status = %08lx\n", Status);
-               return Status;
+               DPRINT("ObReferenceObjectByHandle() failed with status %08lx\n", Status);
+               goto cleanup;
+       }
+       Fcr = 0;
+       Status = GreenDeviceIoControl(DeviceExtension->Serial, IOCTL_SERIAL_SET_FIFO_CONTROL,
+               &Fcr, sizeof(Fcr), NULL, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("GreenDeviceIoControl() failed with status %08lx\n", Status);
+               goto cleanup;
+       }
+       Status = GreenDeviceIoControl(DeviceExtension->Serial, IOCTL_SERIAL_SET_BAUD_RATE,
+               &DriverExtension->SampleRate, sizeof(DriverExtension->SampleRate), NULL, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("GreenDeviceIoControl() failed with status %08lx\n", Status);
+               goto cleanup;
        }
-       ((PSCREEN_DEVICE_EXTENSION)DeviceExtension->Screen->DeviceExtension)->Green = Fdo;
-
-       /* initialize green Fdo */
-       DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo);
        DeviceExtension->LineControl.WordLength = 8;
        DeviceExtension->LineControl.Parity = NO_PARITY;
        DeviceExtension->LineControl.StopBits = STOP_BIT_1;
-       DeviceExtension->BaudRate = SERIAL_BAUD_38400;
-       DeviceExtension->Timeouts.ReadTotalTimeoutConstant = 1; /* not null */
-       DeviceExtension->Timeouts.ReadIntervalTimeout = INFINITE;
-       DeviceExtension->Timeouts.ReadTotalTimeoutMultiplier = INFINITE;
-       DeviceExtension->Timeouts.WriteTotalTimeoutMultiplier = 0; /* FIXME */
-       DeviceExtension->Timeouts.WriteTotalTimeoutConstant = 0; /* FIXME */
-
-       /* open associated serial port */
-       RtlInitUnicodeString(&serialPortName, L"\\Device\\Serial1"); /* FIXME: don't hardcode string */
-       Status = ObReferenceObjectByName(
-               &serialPortName,
-               OBJ_EXCLUSIVE | OBJ_KERNEL_HANDLE,
+       Status = GreenDeviceIoControl(DeviceExtension->Serial, IOCTL_SERIAL_SET_LINE_CONTROL,
+               &DeviceExtension->LineControl, sizeof(SERIAL_LINE_CONTROL), NULL, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("GreenDeviceIoControl() failed with status %08lx\n", Status);
+               goto cleanup;
+       }
+       RtlZeroMemory(&DeviceExtension->Timeouts, sizeof(SERIAL_TIMEOUTS));
+       DeviceExtension->Timeouts.ReadIntervalTimeout = 100;
+       Status = GreenDeviceIoControl(DeviceExtension->Serial, IOCTL_SERIAL_SET_TIMEOUTS,
+               &DeviceExtension->Timeouts, sizeof(SERIAL_TIMEOUTS), NULL, NULL);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("GreenDeviceIoControl() failed with status %08lx\n", Status);
+               goto cleanup;
+       }
+
+       DriverExtension->GreenMainDO->Flags |= DO_BUFFERED_IO;
+       DriverExtension->GreenMainDO->Flags &= ~DO_DEVICE_INITIALIZING;
+
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       if (LocalHandle != 0)
+               ZwClose(LocalHandle);
+       if (!NT_SUCCESS(Status))
+       {
+               if (DeviceExtension && DeviceExtension->Serial)
+                       ObDereferenceObject(DeviceExtension->Serial);
+               if (DriverExtension && DriverExtension->GreenMainDO)
+               {
+                       IoDeleteDevice(DriverExtension->GreenMainDO);
+                       DriverExtension->GreenMainDO = NULL;
+               }
+       }
+       return Status;
+}
+
+static NTSTATUS
+ReportGreenPdo(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PGREEN_DRIVER_EXTENSION DriverExtension)
+{
+       PDEVICE_OBJECT GreenPdo = NULL;
+       NTSTATUS Status;
+
+       /* Create green PDO */
+       Status = IoReportDetectedDevice(
+               DriverObject,
+               InterfaceTypeUndefined, -1, -1,
+               NULL, NULL, TRUE,
+               &GreenPdo);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoReportDetectedDevice() failed with status 0x%lx\n", Status);
+               goto cleanup;
+       }
+
+       /* Create green FDO */
+       Status = CreateGreenFdo(DriverObject, GreenPdo);
+
+       IoInvalidateDeviceRelations(GreenPdo, BusRelations);
+
+       /* FIXME: Update registry, set "DeviceReported" to 1 */
+
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       if (!NT_SUCCESS(Status))
+       {
+               if (DriverExtension->GreenMainDO)
+                       IoDeleteDevice(DriverExtension->GreenMainDO);
+       }
+       return Status;
+}
+
+NTSTATUS NTAPI
+GreenAddDevice(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PDEVICE_OBJECT Pdo)
+{
+       PGREEN_DRIVER_EXTENSION DriverExtension;
+
+       DPRINT("AddDevice(DriverObject %p, Pdo %p)\n", DriverObject, Pdo);
+
+       DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+
+       if (Pdo == NULL)
+       {
+               if (DriverExtension->DeviceReported)
+                       /* Green Pdo has already been reported during a previous boot.
+                        * We will get another AddDevice call soon.
+                        */
+                       return STATUS_SUCCESS;
+               else
+                       return ReportGreenPdo(DriverObject, DriverExtension);
+       }
+       else if (DriverExtension->GreenMainDO == NULL)
+       {
+               return CreateGreenFdo(DriverObject, Pdo);
+       }
+       else
+       {
+               PGREEN_DEVICE_EXTENSION GreenDeviceExtension;
+
+               GreenDeviceExtension = (PGREEN_DEVICE_EXTENSION)DriverExtension->GreenMainDO->DeviceExtension;
+               if (Pdo == GreenDeviceExtension->KeyboardPdo)
+                       return KeyboardAddDevice(DriverObject, Pdo);
+               else if (Pdo == GreenDeviceExtension->ScreenPdo)
+                       return ScreenAddDevice(DriverObject, Pdo);
+               else
+                       /* Strange PDO. We don't know it */
+                       ASSERT(FALSE);
+                       return STATUS_UNSUCCESSFUL;
+       }
+}
+
+static NTSTATUS
+GreenQueryBusRelations(
+       IN PDEVICE_OBJECT DeviceObject,
+       OUT PDEVICE_RELATIONS* pDeviceRelations)
+{
+       PGREEN_DEVICE_EXTENSION DeviceExtension;
+       PDEVICE_RELATIONS DeviceRelations = NULL;
+       NTSTATUS Status;
+
+       DeviceExtension = (PGREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+       /* Create PDOs for keyboard and screen */
+       Status = IoCreateDevice(
+               DeviceObject->DriverObject,
+               sizeof(COMMON_DEVICE_EXTENSION),
                NULL,
-               (ACCESS_MASK)0,
-               IoDeviceObjectType,
-               KernelMode,
+               FILE_DEVICE_KEYBOARD,
+               FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
+               FALSE,
+               &DeviceExtension->KeyboardPdo);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoCreateDevice() failed with status 0x%lx\n", Status);
+               goto cleanup;
+       }
+       ((PCOMMON_DEVICE_EXTENSION)DeviceExtension->KeyboardPdo->DeviceExtension)->Type = KeyboardPDO;
+       DeviceExtension->KeyboardPdo->Flags |= DO_POWER_PAGABLE | DO_BUS_ENUMERATED_DEVICE;
+       DeviceExtension->KeyboardPdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+       Status = IoCreateDevice(
+               DeviceObject->DriverObject,
+               sizeof(COMMON_DEVICE_EXTENSION),
                NULL,
-               (PVOID*)&DeviceExtension->Serial);
-       /* FIXME: we never ObDereferenceObject */
+               FILE_DEVICE_SCREEN,
+               FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
+               FALSE,
+               &DeviceExtension->ScreenPdo);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoCreateDevice() failed with status 0x%lx\n", Status);
+               goto cleanup;
+       }
+       ((PCOMMON_DEVICE_EXTENSION)DeviceExtension->ScreenPdo->DeviceExtension)->Type = ScreenPDO;
+       DeviceExtension->ScreenPdo->Flags |= DO_POWER_PAGABLE | DO_BUS_ENUMERATED_DEVICE;
+       DeviceExtension->ScreenPdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+       /* Allocate return structure */
+       DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
+               PagedPool,
+               FIELD_OFFSET(DEVICE_RELATIONS, Objects) + 2 * sizeof(PDEVICE_OBJECT));
+       if (!DeviceRelations)
+               return STATUS_INSUFFICIENT_RESOURCES;
 
-       Fdo->Flags |= DO_POWER_PAGABLE | DO_BUFFERED_IO;
-       Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+       /* Fill return structure */
+       DeviceRelations->Count = 2;
+       ObReferenceObject(DeviceExtension->KeyboardPdo);
+       ObReferenceObject(DeviceExtension->ScreenPdo);
+       DeviceRelations->Objects[0] = DeviceExtension->KeyboardPdo;
+       DeviceRelations->Objects[1] = DeviceExtension->ScreenPdo;
 
-       DPRINT("Status = %08lx\n", Status);
+       *pDeviceRelations = DeviceRelations;
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       if (!NT_SUCCESS(Status))
+       {
+               if (DeviceRelations)
+               {
+                       ULONG i;
+                       for (i = 0; i < DeviceRelations->Count; i++)
+                               ObDereferenceObject(DeviceRelations->Objects[i]);
+                       ExFreePool(DeviceRelations);
+               }
+               if (DeviceExtension->KeyboardPdo)
+               {
+                       IoDeleteDevice(DeviceExtension->KeyboardPdo);
+                       DeviceExtension->KeyboardPdo = NULL;
+               }
+               if (DeviceExtension->ScreenPdo)
+               {
+                       IoDeleteDevice(DeviceExtension->ScreenPdo);
+                       DeviceExtension->ScreenPdo = NULL;
+               }
+       }
        return Status;
 }
+
+static NTSTATUS
+GreenQueryId(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       OUT ULONG_PTR* Information)
+{
+       GREEN_DEVICE_TYPE Type;
+       ULONG IdType;
+       NTSTATUS Status = Irp->IoStatus.Status;
+
+       Type = ((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Type;
+       IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
+
+       switch (IdType)
+       {
+               case BusQueryDeviceID:
+               {
+                       LPCWSTR Source = NULL;
+
+                       if (Type == ScreenPDO)
+                               Source = L"GREEN\\SCREEN";
+                       else if (Type == KeyboardPDO)
+                               Source = L"GREEN\\KEYBOARD";
+                       else
+                       {
+                               DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceId / Unknown type 0x%lx\n",
+                                       Type);
+                               ASSERT(FALSE);
+                       }
+
+                       if (Source)
+                       {
+                               UNICODE_STRING SourceU, String;
+                               RtlInitUnicodeString(&SourceU, Source);
+                               Status = RtlDuplicateUnicodeString(
+                                       RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                       &SourceU,
+                                       &String);
+                               *Information = (ULONG_PTR)String.Buffer;
+                       }
+                       break;
+               }
+               case BusQueryHardwareIDs:
+               {
+                       UNICODE_STRING SourceU = { 0, };
+
+                       if (Type == ScreenPDO)
+                       {
+                               RtlInitUnicodeString(&SourceU, L"GREEN\\SCREEN\0");
+                               /* We can add the two \0 that are at the end of the string */
+                               SourceU.Length = SourceU.MaximumLength = SourceU.Length + 2 * sizeof(WCHAR);
+                       }
+                       else if (Type == KeyboardPDO)
+                       {
+                               RtlInitUnicodeString(&SourceU, L"GREEN\\KEYBOARD\0");
+                               /* We can add the two \0 that are at the end of the string */
+                               SourceU.Length = SourceU.MaximumLength = SourceU.Length + 2 * sizeof(WCHAR);
+                       }
+                       else
+                       {
+                               DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs / Unknown type 0x%lx\n",
+                                       Type);
+                               ASSERT(FALSE);
+                       }
+
+                       if (SourceU.Length)
+                       {
+                               UNICODE_STRING String;
+                               Status = RtlDuplicateUnicodeString(
+                                       RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                       &SourceU,
+                                       &String);
+                               *Information = (ULONG_PTR)String.Buffer;
+                       }
+                       break;
+               }
+               case BusQueryCompatibleIDs:
+               {
+                       /* We don't have any compatible ID */
+                       break;
+               }
+               case BusQueryInstanceID:
+               {
+                       /* We don't have any instance ID */
+                       break;
+               }
+               default:
+               {
+                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
+               }
+       }
+
+       return Status;
+}
+
+NTSTATUS
+GreenPnp(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       GREEN_DEVICE_TYPE Type;
+       PIO_STACK_LOCATION Stack;
+       ULONG_PTR Information = Irp->IoStatus.Information;
+       NTSTATUS Status = Irp->IoStatus.Status;
+
+       Type = ((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Type;
+       Stack = IoGetCurrentIrpStackLocation(Irp);
+
+       switch (Stack->MinorFunction)
+       {
+               case IRP_MN_START_DEVICE: /* 0x00 */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+                       if (Type == GreenFDO || Type == KeyboardPDO || Type == ScreenPDO)
+                               Status = STATUS_SUCCESS;
+                       else
+                       {
+                               DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE / Unknown type 0x%lx\n",
+                                       Type);
+                               ASSERT(FALSE);
+                       }
+                       break;
+               }
+               case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
+                       switch (Stack->Parameters.QueryDeviceRelations.Type)
+                       {
+                               case BusRelations:
+                               {
+                                       if (Type == GreenFDO)
+                                       {
+                                               PDEVICE_RELATIONS DeviceRelations = NULL;
+                                               Status = GreenQueryBusRelations(DeviceObject, &DeviceRelations);
+                                               Information = (ULONG_PTR)DeviceRelations;
+                                       }
+                                       else if (Type == KeyboardPDO || Type == ScreenPDO)
+                                       {
+                                               PDEVICE_RELATIONS DeviceRelations = NULL;
+                                               DeviceRelations = ExAllocatePool(PagedPool, FIELD_OFFSET(DEVICE_RELATIONS, Objects));
+                                               if (!DeviceRelations)
+                                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               else
+                                               {
+                                                       DeviceRelations->Count = 0;
+                                                       Status = STATUS_SUCCESS;
+                                                       Information = (ULONG_PTR)DeviceRelations;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations / Unknown type 0x%lx\n",
+                                                       Type);
+                                               ASSERT(FALSE);
+                                       }
+                                       break;
+                               }
+                               default:
+                               {
+                                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+                                               Stack->Parameters.QueryDeviceRelations.Type);
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case IRP_MN_QUERY_RESOURCES: /* 0x0a */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
+                       /* We don't need resources */
+                       break;
+               }
+               case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+                       /* We don't need resources */
+                       break;
+               }
+               case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT\n");
+                       switch (Stack->Parameters.QueryDeviceText.DeviceTextType)
+                       {
+                               case DeviceTextDescription:
+                               {
+                                       LPCWSTR Description = NULL;
+                                       if (Type == GreenFDO)
+                                               Description = L"Green device";
+                                       else if (Type == ScreenPDO)
+                                               Description = L"Green screen";
+                                       else if (Type == KeyboardPDO)
+                                               Description = L"Green keyboard";
+
+                                       if (Description != NULL)
+                                       {
+                                               LPWSTR Destination = ExAllocatePool(PagedPool, wcslen(Description) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+                                               if (!Destination)
+                                                       Status = STATUS_INSUFFICIENT_RESOURCES;
+                                               else
+                                               {
+                                                       wcscpy(Destination, Description);
+                                                       Information = (ULONG_PTR)Description;
+                                                       Status = STATUS_SUCCESS;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription / Unknown type 0x%lx\n",
+                                                       Type);
+                                               ASSERT(FALSE);
+                                       }
+                                       break;
+                               }
+                               case DeviceTextLocationInformation:
+                               {
+                                       /* We don't have any text location to report,
+                                        * and this query is optional, so ignore it.
+                                        */
+                                       break;
+                               }
+                               default:
+                               {
+                                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
+                                               Stack->Parameters.QueryDeviceText.DeviceTextType);
+                                       ASSERT(FALSE);
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case IRP_MN_QUERY_ID: /* 0x13 */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID\n");
+                       Status = GreenQueryId(DeviceObject, Irp, &Information);
+                       break;
+               }
+               default:
+               {
+                       DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
+                       break;
+               }
+       }
+
+       Irp->IoStatus.Status = Status;
+       Irp->IoStatus.Information = Information;
+       if (Status != STATUS_PENDING)
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+       return Status;
+}
+
diff --git a/reactos/drivers/base/green/power.c b/reactos/drivers/base/green/power.c
new file mode 100644 (file)
index 0000000..b4a7cb5
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/power.c
+ * PURPOSE:     IRP_MJ_POWER operations
+ * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#include "green.h"
+
+#define NDEBUG
+#include <debug.h>
+
+NTSTATUS
+GreenPower(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       GREEN_DEVICE_TYPE Type;
+       PIO_STACK_LOCATION Stack;
+       ULONG_PTR Information = Irp->IoStatus.Information;
+       NTSTATUS Status = Irp->IoStatus.Status;
+
+       Type = ((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Type;
+       Stack = IoGetCurrentIrpStackLocation(Irp);
+
+       switch (Stack->MinorFunction)
+       {
+               case IRP_MN_SET_POWER: /* 0x02 */
+               {
+                       DPRINT("IRP_MJ_POWER / IRP_MN_SET_POWER\n");
+                       if (Type == GreenFDO)
+                       {
+                               PoStartNextPowerIrp(Irp);
+                               Status = STATUS_SUCCESS;
+                       }
+                       else
+                       {
+                               DPRINT1("IRP_MJ_POWER / IRP_MN_SET_POWER / Unknown type 0x%lx\n",
+                                       Type);
+                               ASSERT(FALSE);
+                       }
+                       break;
+               }
+               default:
+               {
+                       DPRINT1("IRP_MJ_POWER / unknown minor function 0x%lx\n", Stack->MinorFunction);
+                       break;
+               }
+       }
+
+       Irp->IoStatus.Status = Status;
+       Irp->IoStatus.Information = Information;
+       if (Status != STATUS_PENDING)
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+       return Status;
+}
index 1f620e0..6851442 100644 (file)
@@ -1,19 +1,18 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS VT100 emulator
- * FILE:            drivers/dd/green/screen.c
- * PURPOSE:         Screen part of green management
- *
- * PROGRAMMERS:     Eric Kohl (ekohl@abo.rhein-zeitung.de)
- *                  Art Yerkes
- *                  Hervé Poussineau (hpoussin@reactos.org)
+ * PROJECT:     ReactOS VT100 emulator
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/base/green/screen.c
+ * PURPOSE:     IRP_MJ_PNP operations
+ * PROGRAMMERS: Copyright 2005 Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ *              Copyright 2005 Art Yerkes
+ *              Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
  */
 
+#include "green.h"
+
 #define NDEBUG
 #include <debug.h>
 
-#include "green.h"
-
 #define ESC       ((UCHAR)0x1b)
 
 /* Force a move of the cursor on each printer char.
@@ -38,9 +37,9 @@ AddToSendBuffer(
        int CurrentInt;
        UCHAR CurrentChar;
        NTSTATUS Status;
-        LARGE_INTEGER ZeroOffset;
+       LARGE_INTEGER ZeroOffset;
 
-        ZeroOffset.QuadPart = 0;
+       ZeroOffset.QuadPart = 0;
 
        SizeLeft = sizeof(DeviceExtension->SendBuffer) - DeviceExtension->SendBufferPosition;
        if (SizeLeft < NumberOfChars * 2 || NumberOfChars == 0)
@@ -50,12 +49,12 @@ AddToSendBuffer(
                        IRP_MJ_WRITE,
                        SerialDevice,
                        DeviceExtension->SendBuffer, DeviceExtension->SendBufferPosition,
-                        &ZeroOffset,
+                       &ZeroOffset,
                        NULL, /* Event */
                        &ioStatus);
                if (!Irp)
                {
-                       DPRINT1("Green: IoBuildSynchronousFsdRequest() failed. Unable to flush output buffer\n");
+                       DPRINT1("IoBuildSynchronousFsdRequest() failed. Unable to flush output buffer\n");
                        return;
                }
 
@@ -63,7 +62,7 @@ AddToSendBuffer(
 
                if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
                {
-                       DPRINT1("Green: IoCallDriver() failed. Status = 0x%08lx\n", Status);
+                       DPRINT1("IoCallDriver() failed. Status = 0x%08lx\n", Status);
                        return;
                }
                DeviceExtension->SendBufferPosition = 0;
@@ -109,73 +108,113 @@ AddToSendBuffer(
 }
 
 NTSTATUS
-ScreenInitialize(
+ScreenAddDevice(
        IN PDRIVER_OBJECT DriverObject,
-       OUT PDEVICE_OBJECT* ScreenFdo)
+       IN PDEVICE_OBJECT Pdo)
 {
-       PDEVICE_OBJECT Fdo, PreviousBlue = NULL;
-       PSCREEN_DEVICE_EXTENSION DeviceExtension;
-       UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen");
+       /* We want to be an upper filter of Blue, if it is existing.
+        * We also *have to* create a Fdo on top of the given Pdo.
+        * Hence, we have 2 cases:
+        * - Blue doesn't exist -> Create a unique Fdo (named Blue) at
+        *   the top of the given Pdo
+        * - Blue does exist -> Create a Fdo at the top of the existing
+        *   DO, and create a "pass to Green" FDO at the top of the Pdo
+        */
+       PDEVICE_OBJECT Fdo = NULL;
+       PDEVICE_OBJECT PassThroughFdo = NULL;
+       PDEVICE_OBJECT LowerDevice = NULL;
+       PDEVICE_OBJECT PreviousBlue = NULL;
+       PSCREEN_DEVICE_EXTENSION DeviceExtension = NULL;
+       UNICODE_STRING BlueScreenName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen");
        NTSTATUS Status;
 
-       DPRINT("Green: ScreenInitialize() called\n");
+       DPRINT("ScreenInitialize() called\n");
 
-       Status = IoCreateDevice(DriverObject,
+       /* Try to create a unique Fdo */
+       Status = IoCreateDevice(
+               DriverObject,
                sizeof(SCREEN_DEVICE_EXTENSION),
-               &DeviceName, /* FIXME: don't hardcode string */
+               &BlueScreenName,
                FILE_DEVICE_SCREEN,
                FILE_DEVICE_SECURE_OPEN,
                TRUE,
                &Fdo);
 
-        if (Status == STATUS_OBJECT_NAME_COLLISION)
-        {
-               DPRINT("Green: Attaching to old blue\n");
+       if (Status == STATUS_OBJECT_NAME_COLLISION)
+       {
+               DPRINT("Attaching to old blue\n");
 
                /* Suggested by hpoussin .. Hide previous blue device 
                 * This makes us able to coexist with blue, and install
                 * when loaded */
-               Status = IoCreateDevice(DriverObject,
+               Status = IoCreateDevice(
+                       DriverObject,
                        sizeof(SCREEN_DEVICE_EXTENSION),
                        NULL,
                        FILE_DEVICE_SCREEN,
                        FILE_DEVICE_SECURE_OPEN,
                        TRUE,
                        &Fdo);
-
                if (!NT_SUCCESS(Status))
-                       return Status;
+               {
+                       DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+                       goto cleanup;
+               }
 
+               /* Initialize some fields, as IoAttachDevice will trigger the
+                * sending of IRP_MJ_CLEANUP/IRP_MJ_CLOSE. We have to know where to
+                * dispatch these IRPs... */
+               ((PSCREEN_DEVICE_EXTENSION)Fdo->DeviceExtension)->Common.Type = ScreenPDO;
                Status = IoAttachDevice(
                        Fdo,
-                       &DeviceName, /* FIXME: don't hardcode string */
-                       &PreviousBlue);
+                       &BlueScreenName,
+                       &LowerDevice);
+               if (!NT_SUCCESS(Status))
+               {
+                       DPRINT("IoAttachDevice() failed with status 0x%08lx\n", Status);
+                       goto cleanup;
+               }
+               PreviousBlue = LowerDevice;
 
-               if (!NT_SUCCESS(Status)) {
-                       IoDeleteDevice(Fdo);
-                       return Status;
+               /* Attach a faked FDO to PDO */
+               Status = IoCreateDevice(
+                       DriverObject,
+                       sizeof(COMMON_FDO_DEVICE_EXTENSION),
+                       NULL,
+                       FILE_DEVICE_SCREEN,
+                       FILE_DEVICE_SECURE_OPEN,
+                       TRUE,
+                       &PassThroughFdo);
+               if (!NT_SUCCESS(Status))
+               {
+                       DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+                       goto cleanup;
                }
-        }
-       else if (!NT_SUCCESS(Status))
+               ((PCOMMON_FDO_DEVICE_EXTENSION)PassThroughFdo->DeviceExtension)->Type = PassThroughFDO;
+               ((PCOMMON_FDO_DEVICE_EXTENSION)PassThroughFdo->DeviceExtension)->LowerDevice = Fdo;
+               PassThroughFdo->StackSize = Fdo->StackSize + 1;
+       }
+       else if (NT_SUCCESS(Status))
+       {
+               /* Attach the named Fdo on top of Pdo */
+               LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo);
+       }
+       else
+       {
+               DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
                return Status;
+       }
 
-       /* We definately have a device object.  PreviousBlue may or may
+       /* We definately have a device object. PreviousBlue may or may
         * not be null */
-       
        DeviceExtension = (PSCREEN_DEVICE_EXTENSION)Fdo->DeviceExtension;
        RtlZeroMemory(DeviceExtension, sizeof(SCREEN_DEVICE_EXTENSION));
-       DeviceExtension->Common.Type = Screen;
+       DeviceExtension->Common.Type = ScreenFDO;
+       DeviceExtension->Common.LowerDevice = LowerDevice;
+       DeviceExtension->Green = ((PGREEN_DRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject, DriverObject))->GreenMainDO;
+       ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->ScreenFdo = Fdo;
        DeviceExtension->PreviousBlue = PreviousBlue;
-
-       if (!NT_SUCCESS(Status)) 
-       {
-               /* If a device was attached, detach it first */
-               if (DeviceExtension->PreviousBlue)
-                       IoDetachDevice(DeviceExtension->PreviousBlue);
-
-               IoDeleteDevice(Fdo);
-                return Status;
-       }
+       IoAttachDeviceToDeviceStack(PassThroughFdo ? PassThroughFdo : Fdo, Pdo);
 
        /* initialize screen */
        DeviceExtension->Columns = 80;
@@ -186,12 +225,9 @@ ScreenInitialize(
                2 * DeviceExtension->Columns * DeviceExtension->Rows * sizeof(UCHAR));
        if (!DeviceExtension->VideoMemory)
        {
-               /* If a device was attached, detach it first */
-               if (DeviceExtension->PreviousBlue)
-                       IoDetachDevice(DeviceExtension->PreviousBlue);
-
-               IoDeleteDevice(Fdo);
-               return STATUS_INSUFFICIENT_RESOURCES;
+               DPRINT("ExAllocatePool() failed\n");
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+               goto cleanup;
        }
        DeviceExtension->TabWidth = 8;
 
@@ -207,9 +243,22 @@ ScreenInitialize(
        Fdo->Flags |= DO_POWER_PAGABLE;
        Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
-       *ScreenFdo = Fdo;
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       if (!NT_SUCCESS(Status))
+       {
+               if (DeviceExtension)
+                       ExFreePool(DeviceExtension->VideoMemory);
+               if (LowerDevice)
+                       IoDetachDevice(LowerDevice);
+               if (Fdo)
+                       IoDeleteDevice(Fdo);
+               if (PassThroughFdo)
+                       IoDeleteDevice(PassThroughFdo);
+       }
 
-       return STATUS_SUCCESS;
+       return Status;
 }
 
 NTSTATUS
@@ -227,9 +276,8 @@ ScreenWrite(
        ULONG Columns, Rows;
        ULONG CursorX, CursorY;
        ULONG i, j;
-       NTSTATUS Status;
 
-       DPRINT("Green: IRP_MJ_WRITE\n");
+       DPRINT("ScreenWrite() called\n");
 
        Stack = IoGetCurrentIrpStackLocation (Irp);
        Buffer = Irp->UserBuffer;
@@ -250,14 +298,6 @@ ScreenWrite(
        CursorY = (DeviceExtension->LogicalOffset / 2) / Columns + 1;
        VideoMemorySize = Columns * Rows * 2 * sizeof(UCHAR);
 
-#if DBG
-       DPRINT("Y: %lu\n", CursorY);
-       DPRINT("Buffer =");
-       for (i = 0; i < Stack->Parameters.Write.Length; i++)
-               DbgPrint(" 0x%02x", Buffer[i]);
-       DbgPrint("\n");
-#endif
-
        if (!(DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT))
        {
                /* raw output mode */
@@ -358,11 +398,9 @@ ScreenWrite(
        /* flush output buffer */
        AddToSendBuffer(DeviceExtension, 0);
 
-       Status = STATUS_SUCCESS;
-       Irp->IoStatus.Status = Status;
-       IoCompleteRequest (Irp, IO_NO_INCREMENT);
-
-       return Status;
+       /* Call lower driver */
+       IoSkipCurrentIrpStackLocation(Irp);
+       return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp);
 }
 
 NTSTATUS
@@ -377,7 +415,6 @@ ScreenDeviceControl(
 
        Stack = IoGetCurrentIrpStackLocation(Irp);
        DeviceExtension = (PSCREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
        SerialDevice = ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->Serial;
        if (!SerialDevice)
        {
@@ -388,10 +425,11 @@ ScreenDeviceControl(
 
        switch (Stack->Parameters.DeviceIoControl.IoControlCode)
        {
+#if 0
                case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
                {
                        PCONSOLE_SCREEN_BUFFER_INFO pcsbi;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO\n");
 
                        pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
 
@@ -418,7 +456,7 @@ ScreenDeviceControl(
                case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
                {
                        PCONSOLE_SCREEN_BUFFER_INFO pcsbi;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO\n");
 
                        pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
                        /* FIXME: remove */ { pcsbi->dwCursorPosition.X++; }
@@ -447,7 +485,7 @@ ScreenDeviceControl(
                case IOCTL_CONSOLE_GET_CURSOR_INFO:
                {
                        PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_CURSOR_INFO\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_CURSOR_INFO\n");
 
                        pcci->dwSize = 1;
                        pcci->bVisible = TRUE;
@@ -459,7 +497,7 @@ ScreenDeviceControl(
                case IOCTL_CONSOLE_GET_MODE:
                {
                        PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_MODE\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_MODE\n");
 
                        pcm->dwMode = DeviceExtension->Mode;
 
@@ -470,7 +508,7 @@ ScreenDeviceControl(
                case IOCTL_CONSOLE_SET_MODE:
                {
                        PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_MODE\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_MODE\n");
 
                        DeviceExtension->Mode = pcm->dwMode;
 
@@ -480,25 +518,25 @@ ScreenDeviceControl(
                }
                case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE */
                        break;
                }
                case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE */
                        break;
                }
                case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE */
                        break;
                }
                case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
                {
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE\n");
 
                        DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer;
                        Irp->IoStatus.Information = 0;
@@ -507,19 +545,19 @@ ScreenDeviceControl(
                }
                case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME:IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER */
                        break;
                }
                case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_CHARACTER\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_CHARACTER\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_CHARACTER */
                        break;
                }
                case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
                {
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER\n");
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER\n");
                        Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER */
                        break;
                }
@@ -529,7 +567,7 @@ ScreenDeviceControl(
                        PUCHAR Video;
                        ULONG x, y;
                        BOOLEAN DoOptimization = FALSE;
-                       DPRINT("Green: IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_DRAW\n");
+                       DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_DRAW\n");
 
                        ConsoleDraw = (PCONSOLE_DRAW)MmGetSystemAddressForMdl(Irp->MdlAddress);
                        /* FIXME: remove */ { ConsoleDraw->X++; ConsoleDraw->CursorX++; }
@@ -609,13 +647,28 @@ ScreenDeviceControl(
                        Status = STATUS_SUCCESS;
                        break;
                }
+#endif
                default:
-                       DPRINT1("Green: IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
+               {
+                       DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
                                Stack->Parameters.DeviceIoControl.IoControlCode);
-                       Status = STATUS_NOT_IMPLEMENTED;
+                       /* Call lower driver */
+                       IoSkipCurrentIrpStackLocation(Irp);
+                       return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp);
+               }
        }
 
-       Irp->IoStatus.Status = Status;
-       IoCompleteRequest (Irp, IO_NO_INCREMENT);
-       return Status;
+       if (!NT_SUCCESS(Status))
+       {
+               /* Don't call blue (if any), as we encountered an error */
+               Irp->IoStatus.Status = Status;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+               return Status;
+       }
+       else
+       {
+               /* Call lower driver */
+               IoSkipCurrentIrpStackLocation(Irp);
+               return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp);
+       }
 }