Merge from trunk.
Inform HAL about the switch to graphics modeas late as possible. Fixes bug 880.
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c
Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h
Modified: branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c

Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c
--- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c	2005-10-17 21:47:17 UTC (rev 18532)
+++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/dispatch.c	2005-10-17 21:48:12 UTC (rev 18533)
@@ -18,7 +18,6 @@
  * If not, write to the Free Software Foundation,
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * $Id$
  */
 
 #include "videoprt.h"
@@ -133,18 +132,6 @@
       Irp->IoStatus.Status = STATUS_SUCCESS;
 
       InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
-
-      /*
-       * Storing the device extension pointer in a static variable is an
-       * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters
-       * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
-       * parameter. On the bright side, the DISPLAY device is opened
-       * exclusively, so there can be only one device extension active at
-       * any point in time.
-       */
-
-      ResetDisplayParametersDeviceExtension = DeviceExtension;
-      HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters);
    }
    else
    {
@@ -264,7 +251,57 @@
    return Status;
 }
 
+/*
+ * IntVideoPortWrite
+ *
+ * This is a bit of a hack. We want to take ownership of the display as late
+ * as possible, just before the switch to graphics mode. Win32k knows when
+ * this happens, we don't. So we need Win32k to inform us. This could be done
+ * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
+ * in the communication between GDI driver and miniport driver. So we use
+ * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
+ * since we know for certain that there is no read/write activity going on
+ * between GDI and miniport drivers.
+ * We don't actually need the data that is passed, we just trigger on the fact
+ * that an IRP_MJ_WRITE was sent.
+ *
+ * Run Level
+ *    PASSIVE_LEVEL
+ */
+
 NTSTATUS NTAPI
+IntVideoPortDispatchWrite(
+   IN PDEVICE_OBJECT DeviceObject,
+   IN PIRP Irp)
+{
+   PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
+   NTSTATUS nErrCode;
+
+   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+   /*
+    * Storing the device extension pointer in a static variable is an
+    * ugly hack. Unfortunately, we need it in VideoPortResetDisplayParameters
+    * and HalAcquireDisplayOwnership doesn't allow us to pass a userdata
+    * parameter. On the bright side, the DISPLAY device is opened
+    * exclusively, so there can be only one device extension active at
+    * any point in time.
+    */
+
+   ResetDisplayParametersDeviceExtension = DeviceExtension;
+   HalAcquireDisplayOwnership(IntVideoPortResetDisplayParameters);
+
+   nErrCode = STATUS_SUCCESS;
+   Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
+   Irp->IoStatus.Status = nErrCode;
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+   return nErrCode;
+}
+
+
+NTSTATUS NTAPI
 IntVideoPortPnPStartDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)

Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c
--- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c	2005-10-17 21:47:17 UTC (rev 18532)
+++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.c	2005-10-17 21:48:12 UTC (rev 18533)
@@ -646,6 +646,7 @@
    DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IntVideoPortDispatchDeviceControl;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = IntVideoPortDispatchWrite;
    DriverObject->DriverUnload = IntVideoPortUnload;
 
    /*

Modified: branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h
--- branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h	2005-10-17 21:47:17 UTC (rev 18532)
+++ branches/ros-branch-0_2_8/reactos/drivers/video/videoprt/videoprt.h	2005-10-17 21:48:12 UTC (rev 18533)
@@ -148,6 +148,11 @@
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp);
 
+NTSTATUS NTAPI
+IntVideoPortDispatchWrite(
+   IN PDEVICE_OBJECT DeviceObject,
+   IN PIRP Irp);
+
 VOID NTAPI
 IntVideoPortUnload(PDRIVER_OBJECT DriverObject);
 

Modified: branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c
--- branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c	2005-10-17 21:47:17 UTC (rev 18532)
+++ branches/ros-branch-0_2_8/reactos/subsys/win32k/objects/dc.c	2005-10-17 21:48:12 UTC (rev 18533)
@@ -661,6 +661,61 @@
    return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
 }
 
+static BOOL FASTCALL
+PrepareVideoPrt()
+{
+   PIRP Irp;
+   NTSTATUS Status;
+   IO_STATUS_BLOCK Iosb;
+   BOOL Prepare = TRUE;
+   ULONG Length = sizeof(BOOL);
+   PIO_STACK_LOCATION StackPtr;
+   LARGE_INTEGER StartOffset;
+   PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject;
+   PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
+
+   DPRINT("PrepareVideoPrt() called\n");
+
+   KeClearEvent(&PrimarySurface.VideoFileObject->Event);
+
+   ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode);
+
+   StartOffset.QuadPart = 0;
+   Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+                                      DeviceObject,
+                                      (PVOID) &Prepare,
+                                      Length,
+                                      &StartOffset,
+                                      NULL,
+                                      &Iosb);
+   if (NULL == Irp)
+   {
+      return FALSE;
+   }
+
+   /* Set up IRP Data */
+   Irp->Tail.Overlay.OriginalFileObject = FileObject;
+   Irp->RequestorMode = KernelMode;
+   Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+   Irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
+   Irp->Flags |= IRP_WRITE_OPERATION;
+
+   /* Setup Stack Data */
+   StackPtr = IoGetNextIrpStackLocation(Irp);
+   StackPtr->FileObject = PrimarySurface.VideoFileObject;
+   StackPtr->Parameters.Write.Key = 0;
+
+   Status = IoCallDriver(DeviceObject, Irp);
+
+   if (STATUS_PENDING == Status)
+   {
+      KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0);
+      Status = Iosb.Status;
+   }
+
+   return NT_SUCCESS(Status);
+}
+
 BOOL FASTCALL
 IntCreatePrimarySurface()
 {
@@ -674,6 +729,11 @@
       return FALSE;
    }
 
+   if (! PrepareVideoPrt())
+   {
+      return FALSE;
+   }
+
    DPRINT("calling EnableSurface\n");
    /* Enable the drawing surface */
    PrimarySurface.Handle =