Improve the WNDOBJ implementation a bit... There are still some problems with the visible area when a window is overlapped by another one...
Modified: trunk/reactos/subsys/win32k/eng/objects.h
Modified: trunk/reactos/subsys/win32k/eng/window.c
Modified: trunk/reactos/subsys/win32k/include/eng.h
Modified: trunk/reactos/subsys/win32k/include/intgdi.h
Modified: trunk/reactos/subsys/win32k/include/window.h
Modified: trunk/reactos/subsys/win32k/ntuser/stubs.c
Modified: trunk/reactos/subsys/win32k/ntuser/windc.c
Modified: trunk/reactos/subsys/win32k/ntuser/window.c
Modified: trunk/reactos/subsys/win32k/ntuser/winpos.c
Modified: trunk/reactos/subsys/win32k/objects/dc.c

Modified: trunk/reactos/subsys/win32k/eng/objects.h
--- trunk/reactos/subsys/win32k/eng/objects.h	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/eng/objects.h	2005-03-15 22:26:12 UTC (rev 14111)
@@ -130,6 +130,8 @@
 
 typedef struct _WNDGDI {
   WNDOBJ            WndObj;
+  LIST_ENTRY        ListEntry;
+  HWND              Hwnd;
   CLIPOBJ           *ClientClipObj;
   WNDOBJCHANGEPROC  ChangeProc;
   FLONG             Flags;

Modified: trunk/reactos/subsys/win32k/eng/window.c
--- trunk/reactos/subsys/win32k/eng/window.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/eng/window.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -26,6 +26,9 @@
  * REVISION HISTORY:
  *                 16/11/2004: Created
  */
+
+/* TODO: Check how the WNDOBJ implementation should behave with a driver on windows. */
+ 
 #include <w32k.h>
 
 /*
@@ -33,9 +36,9 @@
  */
 VOID
 FASTCALL
-IntEngWndChanged(
-        IN WNDOBJ *pwo,
-        IN FLONG   flChanged)
+IntEngWndCallChangeProc(
+  IN WNDOBJ *pwo,
+  IN FLONG   flChanged)
 {
   WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
   
@@ -63,22 +66,144 @@
 }
 
 /*
+ * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WINDOW_OBJECT
+ */
+BOOLEAN
+FASTCALL
+IntEngWndUpdateClipObj(
+  WNDGDI *WndObjInt,
+  PWINDOW_OBJECT Window)
+{
+  HRGN hVisRgn;
+  PROSRGNDATA visRgn;
+  CLIPOBJ *ClipObj = NULL;
+  CLIPOBJ *OldClipObj;
+
+  hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
+  if (hVisRgn != NULL)
+  {
+    NtGdiOffsetRgn(hVisRgn, Window->ClientRect.left, Window->ClientRect.top);
+    visRgn = RGNDATA_LockRgn(hVisRgn);
+    if (visRgn != NULL)
+    {
+      if (visRgn->rdh.nCount > 0)
+      {
+        ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, (PRECTL)visRgn->Buffer,
+                                         (PRECTL)&visRgn->rdh.rcBound);
+        DPRINT("Created visible region with %d rects\n", visRgn->rdh.nCount);
+        DPRINT("  BoundingRect: %d, %d  %d, %d\n",
+               visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
+               visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
+        {
+          INT i;
+          for (i = 0; i < visRgn->rdh.nCount; i++)
+          {
+            DPRINT("  Rect #%d: %d,%d  %d,%d\n", i+1,
+                   visRgn->Buffer[i].left, visRgn->Buffer[i].top,
+                   visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
+          }
+        }
+      }
+      RGNDATA_UnlockRgn(hVisRgn);
+    }
+    else
+    {
+      DPRINT1("Warning: Couldn't lock visible region of window DC\n");
+    }
+  }
+  else
+  {
+    DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n");
+  }
+
+  if (ClipObj == NULL)
+  {
+    /* Fall back to client rect */
+    ClipObj = IntEngCreateClipRegion(1, (PRECTL)&Window->ClientRect,
+                                     (PRECTL)&Window->ClientRect);
+  }
+  
+  if (ClipObj == NULL)
+  {
+    DPRINT1("Warning: IntEngCreateClipRegion() failed!\n");
+    return FALSE;
+  }
+
+  RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ));
+  RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->ClientRect, sizeof (RECT));
+  OldClipObj = InterlockedExchangePointer(&WndObjInt->ClientClipObj, ClipObj);
+  if (OldClipObj != NULL)
+    IntEngDeleteClipRegion(OldClipObj);
+  
+  return TRUE;
+}
+
+/*
+ * Updates all WNDOBJs of the given WINDOW_OBJECT and calls the change-procs.
+ */
+VOID
+FASTCALL
+IntEngWindowChanged(
+  PWINDOW_OBJECT  Window,
+  FLONG           flChanged)
+{
+  PLIST_ENTRY CurrentEntry;
+  WNDGDI *Current;
+
+  ASSERT_IRQL(PASSIVE_LEVEL);
+
+  ExAcquireFastMutex(&Window->WndObjListLock);
+  CurrentEntry = Window->WndObjListHead.Flink;
+  while (CurrentEntry != &Window->WndObjListHead)
+    {
+      Current = CONTAINING_RECORD(CurrentEntry, WNDGDI, ListEntry);
+      
+      if (Current->WndObj.pvConsumer != NULL)
+        {
+          /* Update the WNDOBJ */
+          switch (flChanged)
+            {
+            case WOC_RGN_CLIENT:
+              /* Update the clipobj and client rect of the WNDOBJ */
+              IntEngWndUpdateClipObj(Current, Window);
+              break;
+          
+            case WOC_DELETE:
+              /* FIXME: Should the WNDOBJs be deleted by win32k or by the driver? */
+              break;
+            }
+
+          /* Call the change proc */
+          IntEngWndCallChangeProc(&Current->WndObj, flChanged);
+      
+          /* HACK: Send WOC_CHANGED after WOC_RGN_CLIENT */
+          if (flChanged == WOC_RGN_CLIENT)
+            {
+              IntEngWndCallChangeProc(&Current->WndObj, WOC_CHANGED);
+            }
+
+          CurrentEntry = CurrentEntry->Flink;
+        }
+    }
+
+  ExReleaseFastMutex(&Window->WndObjListLock);
+}
+
+/*
  * @implemented
  */
 WNDOBJ*
 STDCALL
 EngCreateWnd(
-	SURFOBJ          *pso,
-	HWND              hwnd,
-	WNDOBJCHANGEPROC  pfn,
-	FLONG             fl,
-	int               iPixelFormat
-	)
+  SURFOBJ          *pso,
+  HWND              hwnd,
+  WNDOBJCHANGEPROC  pfn,
+  FLONG             fl,
+  int               iPixelFormat)
 {
   WNDGDI *WndObjInt = NULL;
   WNDOBJ *WndObjUser = NULL;
   PWINDOW_OBJECT Window;
-  CLIPOBJ *ClientClipObj;
 
   DPRINT("EngCreateWnd: pso = 0x%x, hwnd = 0x%x, pfn = 0x%x, fl = 0x%x, pixfmt = %d\n",
          pso, hwnd, pfn, fl, iPixelFormat);
@@ -99,28 +224,31 @@
       return NULL;
     }
 
-  ClientClipObj = IntEngCreateClipRegion(1, (PRECTL)&Window->ClientRect,
-                                         (PRECTL)&Window->ClientRect);
-  if (ClientClipObj == NULL)
+  /* Fill the clipobj */
+  WndObjInt->ClientClipObj = NULL;
+  if (!IntEngWndUpdateClipObj(WndObjInt, Window))
     {
       IntReleaseWindowObject(Window);
       EngFreeMem(WndObjInt);
       return NULL;
     }
 
-  /* fill user object */
+  /* Fill user object */
   WndObjUser = GDIToObj(WndObjInt, WND);
   WndObjUser->psoOwner = pso;
   WndObjUser->pvConsumer = NULL;
-  RtlCopyMemory(&WndObjUser->rclClient, &Window->ClientRect, sizeof (RECT));
-  RtlCopyMemory(&WndObjUser->coClient, ClientClipObj, sizeof (CLIPOBJ));
 
-  /* fill internal object */
+  /* Fill internal object */
+  WndObjInt->Hwnd = hwnd;
   WndObjInt->ChangeProc = pfn;
   WndObjInt->Flags = fl;
   WndObjInt->PixelFormat = iPixelFormat;
-  WndObjInt->ClientClipObj = ClientClipObj;
 
+  /* associate object with window */
+  ExAcquireFastMutex(&Window->WndObjListLock);
+  InsertTailList(&Window->WndObjListHead, &WndObjInt->ListEntry);
+  ExReleaseFastMutex(&Window->WndObjListLock);
+
   /* release resources */
   IntReleaseWindowObject(Window);
 
@@ -135,12 +263,31 @@
  */
 VOID
 STDCALL
-EngDeleteWnd ( IN WNDOBJ *pwo )
+EngDeleteWnd(
+  IN WNDOBJ *pwo)
 {
   WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
-  
+  PWINDOW_OBJECT Window;
+
   DPRINT("EngDeleteWnd: pwo = 0x%x\n", pwo);
 
+  /* Get window object */
+  Window = IntGetWindowObject(WndObjInt->Hwnd);
+  if (Window == NULL)
+    {
+      DPRINT1("Warning: Couldnt get window object for WndObjInt->Hwnd!!!\n");
+      RemoveEntryList(&WndObjInt->ListEntry);
+    }
+  else
+    {
+      /* Remove object from window */
+      ExAcquireFastMutex(&Window->WndObjListLock);
+      RemoveEntryList(&WndObjInt->ListEntry);
+      ExReleaseFastMutex(&Window->WndObjListLock);
+      IntReleaseWindowObject(Window);
+    }
+
+  /* Free resources */
   IntEngDeleteClipRegion(WndObjInt->ClientClipObj);
   EngFreeMem(WndObjInt);
 }
@@ -152,10 +299,9 @@
 BOOL
 STDCALL
 WNDOBJ_bEnum(
-	IN WNDOBJ  *pwo,
-	IN ULONG  cj,
-	OUT ULONG  *pul
-	)
+  IN WNDOBJ  *pwo,
+  IN ULONG  cj,
+  OUT ULONG  *pul)
 {
   WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
   BOOL Ret;
@@ -174,11 +320,10 @@
 ULONG
 STDCALL
 WNDOBJ_cEnumStart(
-	IN WNDOBJ  *pwo,
-	IN ULONG  iType,
-	IN ULONG  iDirection,
-	IN ULONG  cLimit
-	)
+  IN WNDOBJ  *pwo,
+  IN ULONG  iType,
+  IN ULONG  iDirection,
+  IN ULONG  cLimit)
 {
   WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
   ULONG Ret;
@@ -200,9 +345,8 @@
 VOID
 STDCALL
 WNDOBJ_vSetConsumer(
-	IN WNDOBJ  *pwo,
-	IN PVOID  pvConsumer
-	)
+  IN WNDOBJ  *pwo,
+  IN PVOID  pvConsumer)
 {
   BOOL Hack;
 
@@ -211,12 +355,19 @@
   Hack = (pwo->pvConsumer == NULL);
   pwo->pvConsumer = pvConsumer;
 
-  /* HACKHACKHACK */
+  /* HACKHACKHACK
+   *
+   * MSDN says that the WNDOBJCHANGEPROC will be called with the most recent state
+   * when a WNDOBJ is created - we do it here because most drivers will need pvConsumer
+   * in the callback to identify the WNDOBJ I think.
+   *
+   *  - blight
+   */
   if (Hack)
     {
-      IntEngWndChanged(pwo, WOC_RGN_CLIENT);
-      IntEngWndChanged(pwo, WOC_CHANGED);
-      IntEngWndChanged(pwo, WOC_DRAWN);
+      IntEngWndCallChangeProc(pwo, WOC_RGN_CLIENT);
+      IntEngWndCallChangeProc(pwo, WOC_CHANGED);
+      IntEngWndCallChangeProc(pwo, WOC_DRAWN);
     }
 }
 

Modified: trunk/reactos/subsys/win32k/include/eng.h
--- trunk/reactos/subsys/win32k/include/eng.h	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/include/eng.h	2005-03-15 22:26:12 UTC (rev 14111)
@@ -15,4 +15,9 @@
              BRUSHOBJ *Brush,
              POINTL *BrushOrigin);
 
+VOID FASTCALL
+IntEngWindowChanged(
+        PWINDOW_OBJECT Window,
+        FLONG flChanged);
+
 #endif /* _WIN32K_ENG_H */

Modified: trunk/reactos/subsys/win32k/include/intgdi.h
--- trunk/reactos/subsys/win32k/include/intgdi.h	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/include/intgdi.h	2005-03-15 22:26:12 UTC (rev 14111)
@@ -193,5 +193,21 @@
              LPCSTR InData,
              LPVOID OutData);
 
+BOOL
+FASTCALL
+IntEnumDisplaySettings(
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN DWORD iModeNum,
+  IN OUT LPDEVMODEW pDevMode,
+  IN DWORD dwFlags);
+  
+LONG
+FASTCALL
+IntChangeDisplaySettings(
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN LPDEVMODEW pDevMode,
+  IN DWORD dwflags,
+  IN PVOID lParam  OPTIONAL);
+
 #endif /* _WIN32K_INTGDI_H */
 

Modified: trunk/reactos/subsys/win32k/include/window.h
--- trunk/reactos/subsys/win32k/include/window.h	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/include/window.h	2005-03-15 22:26:12 UTC (rev 14111)
@@ -99,6 +99,9 @@
   ULONG Status;
   /* counter for tiled child windows */
   ULONG TiledCounter;
+  /* WNDOBJ list */
+  LIST_ENTRY WndObjListHead;
+  FAST_MUTEX WndObjListLock;
 } WINDOW_OBJECT; /* PWINDOW_OBJECT already declared at top of file */
 
 /* Window flags. */

Modified: trunk/reactos/subsys/win32k/ntuser/stubs.c
--- trunk/reactos/subsys/win32k/ntuser/stubs.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/ntuser/stubs.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -110,20 +110,6 @@
   return 0;
 }
 
-LONG
-STDCALL
-NtUserChangeDisplaySettings(
-  PUNICODE_STRING lpszDeviceName,
-  LPDEVMODEW lpDevMode,
-  HWND hwnd,
-  DWORD dwflags,
-  LPVOID lParam)
-{
-  // UNIMPLEMENTED
-  DbgPrint("(%s:%i) WIN32K: %s UNIMPLEMENTED\n", __FILE__, __LINE__, __FUNCTION__ );
-  return DISP_CHANGE_BADMODE;
-}
-
 DWORD
 STDCALL
 NtUserConvertMemHandle(

Modified: trunk/reactos/subsys/win32k/ntuser/windc.c
--- trunk/reactos/subsys/win32k/ntuser/windc.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/ntuser/windc.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -354,6 +354,11 @@
    Dce->DCXFlags &= ~DCX_DCEDIRTY;
    NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
 
+   if (Window != NULL)
+   {
+      IntEngWindowChanged(Window, WOC_RGN_CLIENT);
+   }
+
    if (hRgnVisible != NULL)
    {
       NtGdiDeleteObject(hRgnVisible);
@@ -856,6 +861,7 @@
 
           if (Window->Self != pDCE->hwndCurrent)
             {
+//              IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
               IntReleaseWindowObject(CurrentWindow);
             }
         }
@@ -866,13 +872,6 @@
   DCE_UnlockList();
 }
 
-/* FIXME: find header file for this prototype. */
-extern BOOL FASTCALL
-IntEnumDisplaySettings(
-  PUNICODE_STRING lpszDeviceName,
-  DWORD iModeNum,
-  LPDEVMODEW lpDevMode,
-  DWORD dwFlags);
 
 #define COPY_DEVMODE_VALUE_TO_CALLER(dst, src, member) \
     Status = MmCopyToCaller(&(dst)->member, &(src)->member, sizeof ((src)->member)); \
@@ -893,15 +892,18 @@
 {
   NTSTATUS Status;
   LPDEVMODEW pSafeDevMode;
-  DWORD Size = 0, ExtraSize = 0;
+  PUNICODE_STRING pSafeDeviceName = NULL;
+  UNICODE_STRING SafeDeviceName;
+  USHORT Size = 0, ExtraSize = 0;
   
-  Status = MmCopyFromCaller(&Size, &lpDevMode->dmSize, sizeof (lpDevMode->dmSize));
+  /* Copy the devmode */
+  Status = MmCopyFromCaller(&Size, &lpDevMode->dmSize, sizeof (Size));
   if (!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
     return FALSE;
   }
-  Status = MmCopyFromCaller(&ExtraSize, &lpDevMode->dmDriverExtra, sizeof (lpDevMode->dmDriverExtra));
+  Status = MmCopyFromCaller(&ExtraSize, &lpDevMode->dmDriverExtra, sizeof (ExtraSize));
   if (!NT_SUCCESS(Status))
   {
     SetLastNtError(Status);
@@ -911,17 +913,36 @@
   if (pSafeDevMode == NULL)
   {
     SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-    return DISP_CHANGE_FAILED;
+    return FALSE;
   }
   pSafeDevMode->dmSize = Size;
   pSafeDevMode->dmDriverExtra = ExtraSize;
 
-  if (!IntEnumDisplaySettings(lpszDeviceName, iModeNum, pSafeDevMode, dwFlags))
+  /* Copy the device name */
+  if (lpszDeviceName != NULL)
   {
+    Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
+    if (!NT_SUCCESS(Status))
+    {
+      ExFreePool(pSafeDevMode);
+      SetLastNtError(Status);
+      return FALSE;
+    }
+    pSafeDeviceName = &SafeDeviceName;
+  }
+
+  /* Call internal function */
+  if (!IntEnumDisplaySettings(pSafeDeviceName, iModeNum, pSafeDevMode, dwFlags))
+  {
+    if (pSafeDeviceName != NULL)
+      RtlFreeUnicodeString(pSafeDeviceName);
     ExFreePool(pSafeDevMode);
     return FALSE;
   }
+  if (pSafeDeviceName != NULL)
+    RtlFreeUnicodeString(pSafeDeviceName);
 
+  /* Copy some information back */
   COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode, pSafeDevMode, dmPelsWidth);
   COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode, pSafeDevMode, dmPelsHeight);
   COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode, pSafeDevMode, dmBitsPerPel);
@@ -940,9 +961,84 @@
     }
   }
 
+  ExFreePool(pSafeDevMode);
   return TRUE;
 }
 
 #undef COPY_DEVMODE_VALUE_TO_CALLER
 
+
+LONG
+STDCALL
+NtUserChangeDisplaySettings(
+  PUNICODE_STRING lpszDeviceName,
+  LPDEVMODEW lpDevMode,
+  HWND hwnd,
+  DWORD dwflags,
+  LPVOID lParam)
+{
+  NTSTATUS Status;
+  DEVMODEW DevMode;
+  PUNICODE_STRING pSafeDeviceName = NULL;
+  UNICODE_STRING SafeDeviceName;
+  LONG Ret;
+
+  /* Check arguments */
+#ifdef CDS_VIDEOPARAMETERS
+  if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
+#else
+  if (lParam != NULL)
+#endif
+  {
+    SetLastWin32Error(ERROR_INVALID_PARAMETER);
+    return DISP_CHANGE_BADPARAM;
+  }
+  if (hwnd != NULL)
+  {
+    SetLastWin32Error(ERROR_INVALID_PARAMETER);
+    return DISP_CHANGE_BADPARAM;
+  }
+  
+  /* Copy devmode */
+  Status = MmCopyFromCaller(&DevMode.dmSize, &lpDevMode->dmSize, sizeof (DevMode.dmSize));
+  if (!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    return DISP_CHANGE_BADPARAM;
+  }
+  DevMode.dmSize = min(sizeof (DevMode), DevMode.dmSize);
+  Status = MmCopyFromCaller(&DevMode, lpDevMode, DevMode.dmSize);
+  if (!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    return DISP_CHANGE_BADPARAM;
+  }
+  if (DevMode.dmDriverExtra > 0)
+  {
+    DbgPrint("(%s:%i) WIN32K: %s lpDevMode->dmDriverExtra is IGNORED!\n", __FILE__, __LINE__, __FUNCTION__);
+    DevMode.dmDriverExtra = 0;
+  }
+
+  /* Copy the device name */
+  if (lpszDeviceName != NULL)
+  {
+    Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
+    if (!NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      return DISP_CHANGE_BADPARAM;
+    }
+    pSafeDeviceName = &SafeDeviceName;
+  }
+
+  /* Call internal function */
+  Ret = IntChangeDisplaySettings(pSafeDeviceName, &DevMode, dwflags, lParam);
+  
+  if (pSafeDeviceName != NULL)
+    RtlFreeUnicodeString(pSafeDeviceName);
+    
+  return Ret;
+}
+
+
 /* EOF */

Modified: trunk/reactos/subsys/win32k/ntuser/window.c
--- trunk/reactos/subsys/win32k/ntuser/window.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/ntuser/window.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -1618,6 +1618,8 @@
   ExInitializeFastMutex(&WindowObject->PropListLock);
   ExInitializeFastMutex(&WindowObject->RelativesLock);
   ExInitializeFastMutex(&WindowObject->UpdateLock);
+  InitializeListHead(&WindowObject->WndObjListHead);
+  ExInitializeFastMutex(&WindowObject->WndObjListLock);
 
   if (NULL != WindowName->Buffer)
     {  
@@ -1975,6 +1977,9 @@
 	      WindowObject->ClientRect.top);
 	}
       IntSendMessage(WindowObject->Self, WM_MOVE, 0, lParam);
+
+      /* Call WNDOBJ change procs */
+      IntEngWindowChanged(WindowObject, WOC_RGN_CLIENT);
     }
 
   /* Show or maybe minimize or maximize the window. */
@@ -2180,6 +2185,7 @@
     }
 #endif
 
+  IntEngWindowChanged(Window, WOC_DELETE);
   isChild = (0 != (Window->Style & WS_CHILD));
 
 #if 0 /* FIXME */

Modified: trunk/reactos/subsys/win32k/ntuser/winpos.c
--- trunk/reactos/subsys/win32k/ntuser/winpos.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/ntuser/winpos.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -1341,6 +1341,7 @@
       IntSendMessage(Wnd, WM_MOVE, 0,
                      MAKELONG(Window->ClientRect.left,
                               Window->ClientRect.top));
+      IntEngWindowChanged(Window, WOC_RGN_CLIENT);
     }
 
   /* Activate the window if activation is not requested and the window is not minimized */

Modified: trunk/reactos/subsys/win32k/objects/dc.c
--- trunk/reactos/subsys/win32k/objects/dc.c	2005-03-15 22:14:22 UTC (rev 14110)
+++ trunk/reactos/subsys/win32k/objects/dc.c	2005-03-15 22:26:12 UTC (rev 14111)
@@ -2296,26 +2296,28 @@
 /*! \brief Enumerate possible display settings for the given display...
  *
  * \todo Make thread safe!?
- * \todo Don't ignore lpszDeviceName
+ * \todo Don't ignore pDeviceName
  * \todo Implement non-raw mode (only return settings valid for driver and monitor)
  */
 BOOL FASTCALL
 IntEnumDisplaySettings(
-  PUNICODE_STRING lpszDeviceName,
-  DWORD iModeNum,
-  LPDEVMODEW lpDevMode,
-  DWORD dwFlags)
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN DWORD iModeNum,
+  IN OUT LPDEVMODEW pDevMode,
+  IN DWORD dwFlags)
 {
   static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
   static DWORD SizeOfCachedDevModes = 0;
-  LPDEVMODEW CachedMode = NULL;
+  PDEVMODEW CachedMode = NULL;
   DEVMODEW DevMode;
   INT Size, OldSize;
   ULONG DisplayNumber = 0; /* only default display supported */
   
-  if (lpDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
-      lpDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
-      lpDevMode->dmSize != SIZEOF_DEVMODEW_500)
+  DPRINT1("DevMode->dmSize = %d\n", pDevMode->dmSize);
+  DPRINT1("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
+  if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
+      pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
+      pDevMode->dmSize != SIZEOF_DEVMODEW_500)
   {
     SetLastWin32Error(STATUS_INVALID_PARAMETER);
     return FALSE;
@@ -2324,7 +2326,7 @@
   if (iModeNum == ENUM_CURRENT_SETTINGS)
   {
     CachedMode = &PrimarySurface.DMW;    
-    assert(CachedMode->dmSize > 0);
+    ASSERT(CachedMode->dmSize > 0);
   }
   else if (iModeNum == ENUM_REGISTRY_SETTINGS)
   {
@@ -2488,24 +2490,90 @@
     }
   }
 
-  assert(CachedMode != NULL);
+  ASSERT(CachedMode != NULL);
 
-  Size = OldSize = lpDevMode->dmSize;
+  Size = OldSize = pDevMode->dmSize;
   if (Size > CachedMode->dmSize)
     Size = CachedMode->dmSize;
-  RtlCopyMemory(lpDevMode, CachedMode, Size);
-  RtlZeroMemory((PCHAR)lpDevMode + Size, OldSize - Size);
-  lpDevMode->dmSize = OldSize;
+  RtlCopyMemory(pDevMode, CachedMode, Size);
+  RtlZeroMemory((PCHAR)pDevMode + Size, OldSize - Size);
+  pDevMode->dmSize = OldSize;
   
-  Size = OldSize = lpDevMode->dmDriverExtra;
+  Size = OldSize = pDevMode->dmDriverExtra;
   if (Size > CachedMode->dmDriverExtra)
     Size = CachedMode->dmDriverExtra;
-  RtlCopyMemory((PCHAR)lpDevMode + lpDevMode->dmSize,
+  RtlCopyMemory((PCHAR)pDevMode + pDevMode->dmSize,
                 (PCHAR)CachedMode + CachedMode->dmSize, Size);
-  RtlZeroMemory((PCHAR)lpDevMode + lpDevMode->dmSize + Size, OldSize - Size);
-  lpDevMode->dmDriverExtra = OldSize;
+  RtlZeroMemory((PCHAR)pDevMode + pDevMode->dmSize + Size, OldSize - Size);
+  pDevMode->dmDriverExtra = OldSize;
 
   return TRUE;
 }
 
+LONG
+FASTCALL
+IntChangeDisplaySettings(
+  IN PUNICODE_STRING pDeviceName  OPTIONAL,
+  IN LPDEVMODEW DevMode,
+  IN DWORD dwflags,
+  IN PVOID lParam  OPTIONAL)
+{
+  BOOLEAN Global = FALSE;
+  BOOLEAN NoReset = FALSE;
+  BOOLEAN Reset = FALSE;
+  BOOLEAN SetPrimary = FALSE;
+  LONG Ret;
+
+  if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+  {
+    /* Check global, reset and noreset flags */
+    if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
+      Global = TRUE;
+    if ((dwflags & CDS_NORESET) == CDS_NORESET)
+      NoReset = TRUE;
+    dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
+  }
+  if ((dwflags & CDS_RESET) == CDS_RESET)
+    Reset = TRUE;
+  if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
+    SetPrimary = TRUE;
+  dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
+
+  if (Reset && NoReset)
+    return DISP_CHANGE_BADFLAGS;
+
+  switch (dwflags)
+  {
+  case 0: /* Dynamically change graphics mode */
+    Ret = DISP_CHANGE_FAILED;
+    break;
+    
+  case CDS_FULLSCREEN: /* Given mode is temporary */
+    Ret = DISP_CHANGE_FAILED;
+    break;
+    
+  case CDS_UPDATEREGISTRY:
+    Ret = DISP_CHANGE_FAILED;
+    break;
+     
+  case CDS_TEST: /* Test if the mode could be set */
+    Ret = DISP_CHANGE_FAILED;
+    break;
+    
+#ifdef CDS_VIDEOPARAMETERS
+  case CDS_VIDEOPARAMETERS:
+    if (lParam == NULL)
+      return DISP_CHANGE_BADPARAM;
+    Ret = DISP_CHANGE_FAILED;
+    break;
+#endif
+    
+  default:
+    Ret = DISP_CHANGE_BADFLAGS;
+    break;
+  }
+  
+  return Ret;
+}
+
 /* EOF */