2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
37 /* GLOBALS *******************************************************************/
39 /* NOTE - I think we should store this per window station (including gdi objects) */
41 static PDCE FirstDce
= NULL
;
42 static PDC defaultDCstate
= NULL
;
43 //static INT DCECount = 0;
45 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
46 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
48 /* FUNCTIONS *****************************************************************/
51 DceCreateDisplayDC(VOID
)
54 UNICODE_STRING DriverName
;
55 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
56 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
68 DceGetVisRgn(PWINDOW_OBJECT Window
, ULONG Flags
, HWND hWndChild
, ULONG CFlags
)
72 VisRgn
= VIS_ComputeVisibleRegion(Window
,
73 0 == (Flags
& DCX_WINDOW
),
74 0 != (Flags
& DCX_CLIPCHILDREN
),
75 0 != (Flags
& DCX_CLIPSIBLINGS
));
78 VisRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
86 * The NtUserGetWindowDC function retrieves the device context (DC) for the
87 * entire window, including title bar, menus, and scroll bars. A window device
88 * context permits painting anywhere in a window, because the origin of the
89 * device context is the upper-left corner of the window instead of the client
97 NtUserGetWindowDC(HWND hWnd
)
99 return (DWORD
)NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
103 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
105 return (DWORD
)UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
109 NtUserGetDC(HWND hWnd
)
111 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
115 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
123 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
127 pDce
->hDC
= DceCreateDisplayDC();
130 ExFreePoolWithTag(pDce
, TAG_PDCE
);
134 // If NULL, first time through! Build the default window dc!
136 if (NULL
== defaultDCstate
) // Ultra HAX! Dedicated to GvG!
137 { // This is a cheesy way to do this.
138 PDC dc
= DC_LockDc ( pDce
->hDC
);
139 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
140 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
141 IntGdiCopyToSaveState(dc
, defaultDCstate
);
145 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
146 pDce
->hClipRgn
= NULL
;
147 pDce
->pProcess
= NULL
;
149 KeEnterCriticalRegion();
150 pDce
->next
= FirstDce
;
152 KeLeaveCriticalRegion();
154 if (Type
== DCE_WINDOW_DC
) //Window DCE have ownership.
155 { // Process should already own it.
156 pDce
->pProcess
= PsGetCurrentProcess();
160 PDC dc
= DC_LockDc ( pDce
->hDC
);
161 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
162 MmCopyFromCaller(&dc
->Dc_Attr
, dc
->pDc_Attr
, sizeof(DC_ATTR
));
164 DC_FreeDcAttr(pDce
->hDC
); // Free the dcattr!
165 DC_SetOwnership(pDce
->hDC
, NULL
); // This hDC is inaccessible!
168 if (Type
!= DCE_CACHE_DC
)
170 pDce
->DCXFlags
= DCX_DCEBUSY
;
174 if (Wnd
->Style
& WS_CLIPCHILDREN
)
176 pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
178 if (Wnd
->Style
& WS_CLIPSIBLINGS
)
180 pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
186 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
193 DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL
, HDC hDC
, ULONG Flags
,
197 DC
*dc
= DC_LockDc(hDC
);
209 if (Flags
& DCX_WINDOW
)
211 dc
->w
.DCOrgX
= Wnd
->WindowRect
.left
;
212 dc
->w
.DCOrgY
= Wnd
->WindowRect
.top
;
216 dc
->w
.DCOrgX
= Wnd
->ClientRect
.left
;
217 dc
->w
.DCOrgY
= Wnd
->ClientRect
.top
;
225 DceDeleteClipRgn(DCE
* Dce
)
227 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
229 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
231 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
233 else if (Dce
->hClipRgn
!= NULL
)
235 NtGdiDeleteObject(Dce
->hClipRgn
);
238 Dce
->hClipRgn
= NULL
;
240 /* make it dirty so that the vis rgn gets recomputed next time */
241 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
245 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
247 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
252 /* restore previous visible region */
254 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
255 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
257 DceDeleteClipRgn(dce
);
260 if (dce
->DCXFlags
& DCX_CACHE
)
262 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
264 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
265 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
267 PDC dc
= DC_LockDc ( dce
->hDC
);
268 IntGdiCopyFromSaveState(dc
, defaultDCstate
, dce
->hDC
); // Was SetDCState.
270 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
271 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
273 /* don't keep around invalidated entries
274 * because SetDCState() disables hVisRgn updates
275 * by removing dirty bit. */
276 dce
->hwndCurrent
= 0;
277 dce
->DCXFlags
&= DCX_CACHE
;
278 dce
->DCXFlags
|= DCX_DCEEMPTY
;
282 { // Save Users Dc_Attr.
283 PDC dc
= DC_LockDc(dce
->hDC
);
286 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
287 if(Dc_Attr
) MmCopyFromCaller(&dc
->Dc_Attr
, Dc_Attr
, sizeof(DC_ATTR
));
291 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
292 DC_FreeDcAttr(dce
->hDC
); // Free the dcattr.
293 DC_SetOwnership(dce
->hDC
, NULL
); // Set hDC inaccessible mode.
294 dce
->pProcess
= NULL
; // Reset ownership.
300 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
302 HANDLE hRgnVisible
= NULL
;
304 PWINDOW_OBJECT DesktopWindow
;
306 if (Flags
& DCX_PARENTCLIP
)
308 PWINDOW_OBJECT Parent
;
311 Parent
= Window
->Parent
;
318 ParentWnd
= Parent
->Wnd
;
320 if (ParentWnd
->Style
& WS_CLIPSIBLINGS
)
322 DcxFlags
= DCX_CLIPSIBLINGS
|
323 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
327 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
329 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
331 else if (Window
== NULL
)
333 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
334 if (NULL
!= DesktopWindow
)
336 hRgnVisible
= UnsafeIntCreateRectRgnIndirect(&DesktopWindow
->Wnd
->WindowRect
);
345 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
349 if (Flags
& DCX_INTERSECTRGN
)
351 if(Dce
->hClipRgn
!= NULL
)
353 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_AND
);
357 if(hRgnVisible
!= NULL
)
359 NtGdiDeleteObject(hRgnVisible
);
361 hRgnVisible
= NtGdiCreateRectRgn(0, 0, 0, 0);
365 if (Flags
& DCX_EXCLUDERGN
&& Dce
->hClipRgn
!= NULL
)
367 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_DIFF
);
370 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
371 IntGdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
375 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
378 if (hRgnVisible
!= NULL
)
380 NtGdiDeleteObject(hRgnVisible
);
385 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
387 PWINDOW_OBJECT Parent
;
390 BOOL UpdateVisRgn
= TRUE
;
391 BOOL UpdateClipOrigin
= FALSE
;
396 Flags
&= ~DCX_USESTYLE
;
401 if (NULL
== Window
|| NULL
== Window
->Dce
)
406 if (Flags
& DCX_USESTYLE
)
408 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
410 if (Wnd
->Style
& WS_CLIPSIBLINGS
)
412 Flags
|= DCX_CLIPSIBLINGS
;
415 if (!(Flags
& DCX_WINDOW
))
417 if (Wnd
->Class
->Style
& CS_PARENTDC
)
419 Flags
|= DCX_PARENTCLIP
;
422 if (Wnd
->Style
& WS_CLIPCHILDREN
&&
423 !(Wnd
->Style
& WS_MINIMIZE
))
425 Flags
|= DCX_CLIPCHILDREN
;
434 if (Flags
& DCX_NOCLIPCHILDREN
)
437 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
440 if (Flags
& DCX_WINDOW
)
442 Flags
= (Flags
& ~DCX_CLIPCHILDREN
) | DCX_CACHE
;
445 Parent
= (Window
? Window
->Parent
: NULL
);
447 if (NULL
== Window
|| !(Wnd
->Style
& WS_CHILD
) || NULL
== Parent
)
449 Flags
&= ~DCX_PARENTCLIP
;
451 else if (Flags
& DCX_PARENTCLIP
)
454 if ((Wnd
->Style
& WS_VISIBLE
) &&
455 (Parent
->Wnd
->Style
& WS_VISIBLE
))
457 Flags
&= ~DCX_CLIPCHILDREN
;
458 if (Parent
->Wnd
->Style
& WS_CLIPSIBLINGS
)
460 Flags
|= DCX_CLIPSIBLINGS
;
465 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
467 if (Flags
& DCX_CACHE
)
469 DCE
* DceEmpty
= NULL
;
470 DCE
* DceUnused
= NULL
;
471 KeEnterCriticalRegion();
472 for (Dce
= FirstDce
; Dce
!= NULL
; Dce
= Dce
->next
)
474 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
477 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
481 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
482 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
485 UpdateVisRgn
= FALSE
;
488 UpdateClipOrigin
= TRUE
;
493 KeLeaveCriticalRegion();
497 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
502 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
508 if (NULL
!= Dce
&& Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
))
510 UpdateVisRgn
= FALSE
; /* updated automatically, via DCHook() */
514 /* we should free dce->clip_rgn here, but Windows apparently doesn't */
515 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
516 Dce
->hClipRgn
= NULL
;
529 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
530 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
532 if (0 == (Flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
)) && NULL
!= ClipRegion
)
534 if (Flags
& DCX_KEEPCLIPRGN
)
535 NtGdiDeleteObject(ClipRegion
);
540 if (NULL
!= Dce
->hClipRgn
)
542 DceDeleteClipRgn(Dce
);
543 Dce
->hClipRgn
= NULL
;
547 if (0 != (Flags
& DCX_INTERSECTUPDATE
) && NULL
== ClipRegion
)
549 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
550 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
551 ClipRegion
= Window
->UpdateRegion
;
554 if (ClipRegion
== (HRGN
) 1)
556 if (!(Flags
& DCX_WINDOW
))
558 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->ClientRect
);
562 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->WindowRect
);
565 else if (ClipRegion
!= NULL
)
567 Dce
->hClipRgn
= ClipRegion
;
570 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
574 DceUpdateVisRgn(Dce
, Window
, Flags
);
577 if (Dce
->DCXFlags
& DCX_CACHE
)
579 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
580 // Need to set ownership so Sync dcattr will work.
581 DC_SetOwnership( Dce
->hDC
, PsGetCurrentProcess());
582 DC_AllocateDcAttr( Dce
->hDC
); // Allocate new dcattr
583 DCU_SynchDcAttrtoUser( Dce
->hDC
, -1); // Copy data from dc to dcattr
584 Dce
->pProcess
= PsGetCurrentProcess(); // Set the temp owning process
592 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
594 PWINDOW_OBJECT Wnd
=NULL
;
597 DPRINT("Enter NtUserGetDCEx\n");
598 UserEnterExclusive();
600 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
605 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
608 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
615 DCE_Cleanup(PDCE pDce
)
618 KeEnterCriticalRegion();
619 if (pDce
== FirstDce
)
621 FirstDce
= pDce
->next
;
626 for (PrevInList
= FirstDce
; NULL
!= PrevInList
; PrevInList
= PrevInList
->next
)
628 if (pDce
== PrevInList
->next
)
630 PrevInList
->next
= pDce
->next
;
634 assert(NULL
!= PrevInList
);
636 KeLeaveCriticalRegion();
637 return NULL
!= PrevInList
;
641 IntWindowFromDC(HDC hDc
)
645 KeEnterCriticalRegion();
646 for (Dce
= FirstDce
; Dce
!= NULL
; Dce
= Dce
->next
)
650 Ret
= Dce
->hwndCurrent
;
654 KeLeaveCriticalRegion();
660 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
667 DPRINT("%p %p\n", Window
, hDc
);
668 KeEnterCriticalRegion();
669 while (dce
&& (dce
->hDC
!= hDc
))
673 KeLeaveCriticalRegion();
674 if (dce
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
676 nRet
= DceReleaseDC(dce
, EndPaint
);
683 /***********************************************************************
687 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
700 SetDCHook(pdce
->hDC
, NULL
, 0L);
703 if(Force
&& !GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, pdce
->hDC
))
705 DPRINT1("Change ownership for DCE!\n");
706 INT Index
= GDI_HANDLE_GET_INDEX(pdce
->hDC
);
707 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
709 // Must take control of handles that are not in the process of going away.
710 if ((Entry
->Type
& ~GDI_ENTRY_REUSE_MASK
) != 0 && Entry
->KernelData
!= NULL
)
712 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
716 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
720 NtGdiDeleteObjectApp(pdce
->hDC
);
721 if (pdce
->hClipRgn
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
723 NtGdiDeleteObject(pdce
->hClipRgn
);
727 ExFreePoolWithTag(pdce
, TAG_PDCE
);
729 if (FirstDce
== NULL
)
731 ExFreePoolWithTag(defaultDCstate
, TAG_DC
);
732 defaultDCstate
= NULL
;
737 /***********************************************************************
740 * Remove owned DCE and reset unreleased cache DCEs.
743 DceFreeWindowDCE(PWINDOW_OBJECT Window
)
748 KeEnterCriticalRegion();
751 if (pDCE
->hwndCurrent
== Window
->hSelf
)
753 if (pDCE
== Window
->Dce
) /* owned or Class DCE*/
755 if (Window
->Wnd
->Class
->Style
& CS_OWNDC
) /* owned DCE*/
757 pDCE
= DceFreeDCE(pDCE
, FALSE
);
761 else if (pDCE
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) /* Class DCE*/
763 DceDeleteClipRgn(pDCE
);
764 pDCE
->hwndCurrent
= 0;
769 if (pDCE
->DCXFlags
& DCX_DCEBUSY
) /* shared cache DCE */
771 /* FIXME: AFAICS we are doing the right thing here so
772 * this should be a DPRINT. But this is best left as an ERR
773 * because the 'application error' is likely to come from
774 * another part of Wine (i.e. it's our fault after all).
775 * We should change this to DPRINT when ReactOS is more stable
778 DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window
->hSelf
);
779 DceReleaseDC(pDCE
, FALSE
);
782 pDCE
->DCXFlags
&= DCX_CACHE
;
783 pDCE
->DCXFlags
|= DCX_DCEEMPTY
;
784 pDCE
->hwndCurrent
= 0;
789 KeLeaveCriticalRegion();
795 while (FirstDce
!= NULL
)
797 FirstDce
= DceFreeDCE(FirstDce
, TRUE
);
802 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
806 PWINDOW_OBJECT CurrentWindow
;
817 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
819 if (Window
->hSelf
== pDCE
->hwndCurrent
)
821 CurrentWindow
= Window
;
825 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
826 if (NULL
== CurrentWindow
)
833 dc
= DC_LockDc(pDCE
->hDC
);
836 // if (Window->hSelf != pDCE->hwndCurrent)
838 // UserDerefObject(CurrentWindow);
843 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
845 if (pDCE
->DCXFlags
& DCX_WINDOW
)
847 DeltaX
= CurrentWindow
->Wnd
->WindowRect
.left
- dc
->w
.DCOrgX
;
848 DeltaY
= CurrentWindow
->Wnd
->WindowRect
.top
- dc
->w
.DCOrgY
;
849 dc
->w
.DCOrgX
= CurrentWindow
->Wnd
->WindowRect
.left
;
850 dc
->w
.DCOrgY
= CurrentWindow
->Wnd
->WindowRect
.top
;
854 DeltaX
= CurrentWindow
->Wnd
->ClientRect
.left
- dc
->w
.DCOrgX
;
855 DeltaY
= CurrentWindow
->Wnd
->ClientRect
.top
- dc
->w
.DCOrgY
;
856 dc
->w
.DCOrgX
= CurrentWindow
->Wnd
->ClientRect
.left
;
857 dc
->w
.DCOrgY
= CurrentWindow
->Wnd
->ClientRect
.top
;
859 if (NULL
!= dc
->w
.hClipRgn
)
861 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
862 NtGdiOffsetRgn(dc
->w
.hClipRgn
, DeltaX
, DeltaY
);
863 CLIPPING_UpdateGCRegion(dc
);
865 if (NULL
!= pDCE
->hClipRgn
)
867 NtGdiOffsetRgn(pDCE
->hClipRgn
, DeltaX
, DeltaY
);
872 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
874 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
876 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
877 // UserDerefObject(CurrentWindow);
885 #define COPY_DEVMODE_VALUE_TO_CALLER(dst, src, member) \
886 Status = MmCopyToCaller(&(dst)->member, &(src)->member, sizeof ((src)->member)); \
887 if (!NT_SUCCESS(Status)) \
889 SetLastNtError(Status); \
896 NtUserEnumDisplaySettings(
897 PUNICODE_STRING lpszDeviceName
,
899 LPDEVMODEW lpDevMode
, /* FIXME is this correct? */
903 LPDEVMODEW pSafeDevMode
;
904 PUNICODE_STRING pSafeDeviceName
= NULL
;
905 UNICODE_STRING SafeDeviceName
;
906 USHORT Size
= 0, ExtraSize
= 0;
908 /* Copy the devmode */
909 Status
= MmCopyFromCaller(&Size
, &lpDevMode
->dmSize
, sizeof (Size
));
910 if (!NT_SUCCESS(Status
))
912 SetLastNtError(Status
);
915 Status
= MmCopyFromCaller(&ExtraSize
, &lpDevMode
->dmDriverExtra
, sizeof (ExtraSize
));
916 if (!NT_SUCCESS(Status
))
918 SetLastNtError(Status
);
921 pSafeDevMode
= ExAllocatePool(PagedPool
, Size
+ ExtraSize
);
922 if (pSafeDevMode
== NULL
)
924 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
927 pSafeDevMode
->dmSize
= Size
;
928 pSafeDevMode
->dmDriverExtra
= ExtraSize
;
930 /* Copy the device name */
931 if (lpszDeviceName
!= NULL
)
933 Status
= IntSafeCopyUnicodeString(&SafeDeviceName
, lpszDeviceName
);
934 if (!NT_SUCCESS(Status
))
936 ExFreePool(pSafeDevMode
);
937 SetLastNtError(Status
);
940 pSafeDeviceName
= &SafeDeviceName
;
943 /* Call internal function */
944 if (!IntEnumDisplaySettings(pSafeDeviceName
, iModeNum
, pSafeDevMode
, dwFlags
))
946 if (pSafeDeviceName
!= NULL
)
947 RtlFreeUnicodeString(pSafeDeviceName
);
948 ExFreePool(pSafeDevMode
);
951 if (pSafeDeviceName
!= NULL
)
952 RtlFreeUnicodeString(pSafeDeviceName
);
954 /* Copy some information back */
955 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmPelsWidth
);
956 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmPelsHeight
);
957 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmBitsPerPel
);
958 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmDisplayFrequency
);
959 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmDisplayFlags
);
961 /* output private/extra driver data */
964 Status
= MmCopyToCaller((PCHAR
)lpDevMode
+ Size
, (PCHAR
)pSafeDevMode
+ Size
, ExtraSize
);
965 if (!NT_SUCCESS(Status
))
967 SetLastNtError(Status
);
968 ExFreePool(pSafeDevMode
);
973 ExFreePool(pSafeDevMode
);
977 #undef COPY_DEVMODE_VALUE_TO_CALLER
982 NtUserChangeDisplaySettings(
983 PUNICODE_STRING lpszDeviceName
,
984 LPDEVMODEW lpDevMode
,
991 PUNICODE_STRING pSafeDeviceName
= NULL
;
992 UNICODE_STRING SafeDeviceName
;
995 /* Check arguments */
996 #ifdef CDS_VIDEOPARAMETERS
998 if (dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
)
1005 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1006 return DISP_CHANGE_BADPARAM
;
1010 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1011 return DISP_CHANGE_BADPARAM
;
1015 Status
= MmCopyFromCaller(&DevMode
.dmSize
, &lpDevMode
->dmSize
, sizeof (DevMode
.dmSize
));
1016 if (!NT_SUCCESS(Status
))
1018 SetLastNtError(Status
);
1019 return DISP_CHANGE_BADPARAM
;
1021 DevMode
.dmSize
= min(sizeof (DevMode
), DevMode
.dmSize
);
1022 Status
= MmCopyFromCaller(&DevMode
, lpDevMode
, DevMode
.dmSize
);
1023 if (!NT_SUCCESS(Status
))
1025 SetLastNtError(Status
);
1026 return DISP_CHANGE_BADPARAM
;
1028 if (DevMode
.dmDriverExtra
> 0)
1030 DbgPrint("(%s:%i) WIN32K: %s lpDevMode->dmDriverExtra is IGNORED!\n", __FILE__
, __LINE__
, __FUNCTION__
);
1031 DevMode
.dmDriverExtra
= 0;
1034 /* Copy the device name */
1035 if (lpszDeviceName
!= NULL
)
1037 Status
= IntSafeCopyUnicodeString(&SafeDeviceName
, lpszDeviceName
);
1038 if (!NT_SUCCESS(Status
))
1040 SetLastNtError(Status
);
1041 return DISP_CHANGE_BADPARAM
;
1043 pSafeDeviceName
= &SafeDeviceName
;
1046 /* Call internal function */
1047 Ret
= IntChangeDisplaySettings(pSafeDeviceName
, &DevMode
, dwflags
, lParam
);
1049 if (pSafeDeviceName
!= NULL
)
1050 RtlFreeUnicodeString(pSafeDeviceName
);
1056 * Select logical palette into device context.
1057 * \param hDC handle to the device context
1058 * \param hpal handle to the palette
1059 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
1060 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
1061 * palette colors in the best way.
1062 * \return old palette
1064 * \todo implement ForceBackground == TRUE
1066 HPALETTE STDCALL
NtUserSelectPalette(HDC hDC
,
1068 BOOL ForceBackground
)
1071 HPALETTE oldPal
= NULL
;
1074 // FIXME: mark the palette as a [fore\back]ground pal
1075 dc
= DC_LockDc(hDC
);
1078 /* Check if this is a valid palette handle */
1079 PalGDI
= PALETTE_LockPalette(hpal
);
1082 /* Is this a valid palette for this depth? */
1083 if ((dc
->w
.bitsPerPixel
<= 8 && PAL_INDEXED
== PalGDI
->Mode
)
1084 || (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
!= PalGDI
->Mode
))
1086 PALETTE_UnlockPalette(PalGDI
);
1087 oldPal
= dc
->w
.hPalette
;
1088 dc
->w
.hPalette
= hpal
;
1090 else if (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
== PalGDI
->Mode
)
1092 PALETTE_UnlockPalette(PalGDI
);
1093 oldPal
= dc
->PalIndexed
;
1094 dc
->PalIndexed
= hpal
;
1098 PALETTE_UnlockPalette(PalGDI
);