diff --git a/reactos/subsys/win32k/eng/objects.h b/reactos/subsys/win32k/eng/objects.h index bf10f1c4cf5..a8b8d5fe55c 100644 --- a/reactos/subsys/win32k/eng/objects.h +++ b/reactos/subsys/win32k/eng/objects.h @@ -130,6 +130,8 @@ typedef BOOL STDCALL (*PFN_GradientFill)(SURFOBJ*, CLIPOBJ*, XLATEOBJ*, TRIVERTE typedef struct _WNDGDI { WNDOBJ WndObj; + LIST_ENTRY ListEntry; + HWND Hwnd; CLIPOBJ *ClientClipObj; WNDOBJCHANGEPROC ChangeProc; FLONG Flags; diff --git a/reactos/subsys/win32k/eng/window.c b/reactos/subsys/win32k/eng/window.c index 4831da45563..1882b2e44a4 100644 --- a/reactos/subsys/win32k/eng/window.c +++ b/reactos/subsys/win32k/eng/window.c @@ -26,6 +26,9 @@ * REVISION HISTORY: * 16/11/2004: Created */ + +/* TODO: Check how the WNDOBJ implementation should behave with a driver on windows. */ + #include /* @@ -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); @@ -62,23 +65,145 @@ IntEngWndChanged( WndObjInt->ChangeProc(pwo, flChanged); } +/* + * 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,27 +224,30 @@ EngCreateWnd( 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 @@ EngCreateWnd( */ 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 @@ EngDeleteWnd ( IN WNDOBJ *pwo ) 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 @@ WNDOBJ_bEnum( 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 @@ WNDOBJ_cEnumStart( VOID STDCALL WNDOBJ_vSetConsumer( - IN WNDOBJ *pwo, - IN PVOID pvConsumer - ) + IN WNDOBJ *pwo, + IN PVOID pvConsumer) { BOOL Hack; @@ -211,12 +355,19 @@ WNDOBJ_vSetConsumer( 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); } } diff --git a/reactos/subsys/win32k/include/eng.h b/reactos/subsys/win32k/include/eng.h index cafed3f9bff..c0bde5fc228 100644 --- a/reactos/subsys/win32k/include/eng.h +++ b/reactos/subsys/win32k/include/eng.h @@ -15,4 +15,9 @@ IntEngMaskBlt(SURFOBJ *DestObj, BRUSHOBJ *Brush, POINTL *BrushOrigin); +VOID FASTCALL +IntEngWindowChanged( + PWINDOW_OBJECT Window, + FLONG flChanged); + #endif /* _WIN32K_ENG_H */ diff --git a/reactos/subsys/win32k/include/intgdi.h b/reactos/subsys/win32k/include/intgdi.h index 8c62a8c18d5..66c422977ba 100644 --- a/reactos/subsys/win32k/include/intgdi.h +++ b/reactos/subsys/win32k/include/intgdi.h @@ -193,5 +193,21 @@ IntGdiEscape(PDC dc, 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 */ diff --git a/reactos/subsys/win32k/include/window.h b/reactos/subsys/win32k/include/window.h index cd39b35172b..e6529dade61 100644 --- a/reactos/subsys/win32k/include/window.h +++ b/reactos/subsys/win32k/include/window.h @@ -99,6 +99,9 @@ typedef struct _WINDOW_OBJECT 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. */ diff --git a/reactos/subsys/win32k/ntuser/stubs.c b/reactos/subsys/win32k/ntuser/stubs.c index b655279cc1f..9de232c2217 100644 --- a/reactos/subsys/win32k/ntuser/stubs.c +++ b/reactos/subsys/win32k/ntuser/stubs.c @@ -110,20 +110,6 @@ NtUserCallMsgFilter( 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( diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index 370d6a8badd..ab5911fba00 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -354,6 +354,11 @@ noparent: 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 @@ DceResetActiveDCEs(PWINDOW_OBJECT Window) if (Window->Self != pDCE->hwndCurrent) { +// IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT); IntReleaseWindowObject(CurrentWindow); } } @@ -866,13 +872,6 @@ DceResetActiveDCEs(PWINDOW_OBJECT Window) 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 @@ NtUserEnumDisplaySettings( { 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 @@ NtUserEnumDisplaySettings( 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 @@ NtUserEnumDisplaySettings( } } + 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 */ diff --git a/reactos/subsys/win32k/ntuser/window.c b/reactos/subsys/win32k/ntuser/window.c index 9058250b0c7..3dab0ce0d4c 100644 --- a/reactos/subsys/win32k/ntuser/window.c +++ b/reactos/subsys/win32k/ntuser/window.c @@ -1618,6 +1618,8 @@ IntCreateWindowEx(DWORD dwExStyle, ExInitializeFastMutex(&WindowObject->PropListLock); ExInitializeFastMutex(&WindowObject->RelativesLock); ExInitializeFastMutex(&WindowObject->UpdateLock); + InitializeListHead(&WindowObject->WndObjListHead); + ExInitializeFastMutex(&WindowObject->WndObjListLock); if (NULL != WindowName->Buffer) { @@ -1975,6 +1977,9 @@ IntCreateWindowEx(DWORD dwExStyle, 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 @@ NtUserDestroyWindow(HWND Wnd) } #endif + IntEngWindowChanged(Window, WOC_DELETE); isChild = (0 != (Window->Style & WS_CHILD)); #if 0 /* FIXME */ diff --git a/reactos/subsys/win32k/ntuser/winpos.c b/reactos/subsys/win32k/ntuser/winpos.c index 1d31e8528e4..f432429fc40 100644 --- a/reactos/subsys/win32k/ntuser/winpos.c +++ b/reactos/subsys/win32k/ntuser/winpos.c @@ -1341,6 +1341,7 @@ WinPosShowWindow(HWND Wnd, INT Cmd) 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 */ diff --git a/reactos/subsys/win32k/objects/dc.c b/reactos/subsys/win32k/objects/dc.c index 8f351a75782..07164a7a6ba 100644 --- a/reactos/subsys/win32k/objects/dc.c +++ b/reactos/subsys/win32k/objects/dc.c @@ -2296,26 +2296,28 @@ IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color) /*! \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 @@ IntEnumDisplaySettings( 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 @@ IntEnumDisplaySettings( } } - 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 */