2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/ntuser/windc.c
5 * PURPOSE: Keyboard layout management
6 * COPYRIGHT: Copyright 2007 ReactOS
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 /* NOTE - I think we should store this per window station (including gdi objects) */
21 static PDCE FirstDce
= NULL
;
22 static PDC defaultDCstate
= NULL
;
23 //static INT DCECount = 0; // Count of DCE in system.
25 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
26 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
28 /* FUNCTIONS *****************************************************************/
31 // This should be moved to dc.c or dcutil.c.
34 DceCreateDisplayDC(VOID
)
37 UNICODE_STRING DriverName
;
38 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
39 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
41 // If NULL, first time through! Build the default window dc!
43 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
44 { // This is a cheesy way to do this.
45 PDC dc
= DC_LockDc ( hDC
);
46 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
47 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
48 IntGdiCopyToSaveState(dc
, defaultDCstate
);
56 DceGetVisRgn(PWINDOW_OBJECT Window
, ULONG Flags
, HWND hWndChild
, ULONG CFlags
)
60 VisRgn
= VIS_ComputeVisibleRegion( Window
,
61 0 == (Flags
& DCX_WINDOW
),
62 0 != (Flags
& DCX_CLIPCHILDREN
),
63 0 != (Flags
& DCX_CLIPSIBLINGS
));
66 VisRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
73 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
79 if (Window
) Wnd
= Window
->Wnd
;
81 if (Wnd
) Class
= Wnd
->Class
;
83 if (Type
== DCE_CLASS_DC
)
86 KeEnterCriticalRegion();
90 if (pdce
->Class
== Class
)
93 KeLeaveCriticalRegion();
96 pdce
= (PDCE
)pdce
->List
.Flink
;
97 } while (pdce
!= FirstDce
);
98 KeLeaveCriticalRegion();
101 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
105 pDce
->hDC
= DceCreateDisplayDC();
108 ExFreePoolWithTag(pDce
, TAG_PDCE
);
112 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
113 pDce
->hClipRgn
= NULL
;
114 pDce
->pProcess
= NULL
;
118 KeEnterCriticalRegion();
119 if (FirstDce
== NULL
)
122 InitializeListHead(&FirstDce
->List
);
125 InsertTailList(&FirstDce
->List
, &pDce
->List
);
126 KeLeaveCriticalRegion();
128 DCU_SetDcUndeletable(pDce
->hDC
);
130 if (Type
== DCE_WINDOW_DC
|| Type
== DCE_CLASS_DC
) //Window DCE have ownership.
131 { // Process should already own it.
132 pDce
->pProcess
= PsGetCurrentProcess();
136 PDC dc
= DC_LockDc ( pDce
->hDC
);
137 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
138 MmCopyFromCaller(&dc
->Dc_Attr
, dc
->pDc_Attr
, sizeof(DC_ATTR
));
140 DC_FreeDcAttr(pDce
->hDC
); // Free the dcattr!
141 DC_SetOwnership(pDce
->hDC
, NULL
); // This hDC is inaccessible!
144 if (Type
== DCE_CACHE_DC
)
146 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
150 pDce
->DCXFlags
= DCX_DCEBUSY
;
153 if (Type
== DCE_WINDOW_DC
)
155 if (Wnd
->Style
& WS_CLIPCHILDREN
) pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
156 if (Wnd
->Style
& WS_CLIPSIBLINGS
) pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
164 DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL
, HDC hDC
, ULONG Flags
,
168 DC
*dc
= DC_LockDc(hDC
);
180 if (Flags
& DCX_WINDOW
)
182 dc
->w
.DCOrgX
= Wnd
->WindowRect
.left
;
183 dc
->w
.DCOrgY
= Wnd
->WindowRect
.top
;
187 dc
->w
.DCOrgX
= Wnd
->ClientRect
.left
;
188 dc
->w
.DCOrgY
= Wnd
->ClientRect
.top
;
196 DceDeleteClipRgn(DCE
* Dce
)
198 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
200 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
202 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
204 else if (Dce
->hClipRgn
!= NULL
)
206 NtGdiDeleteObject(Dce
->hClipRgn
);
209 Dce
->hClipRgn
= NULL
;
211 /* make it dirty so that the vis rgn gets recomputed next time */
212 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
216 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
218 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
223 /* restore previous visible region */
225 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
226 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
228 DceDeleteClipRgn(dce
);
231 if (dce
->DCXFlags
& DCX_CACHE
)
233 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
236 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
237 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
239 dc
= DC_LockDc ( dce
->hDC
);
241 IntGdiCopyFromSaveState(dc
, defaultDCstate
, dce
->hDC
); // Was SetDCState.
243 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
244 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
246 /* don't keep around invalidated entries
247 * because SetDCState() disables hVisRgn updates
248 * by removing dirty bit. */
249 dce
->hwndCurrent
= 0;
250 dce
->DCXFlags
&= DCX_CACHE
;
251 dce
->DCXFlags
|= DCX_DCEEMPTY
;
255 { // Save Users Dc_Attr.
256 PDC dc
= DC_LockDc(dce
->hDC
);
259 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
260 if(Dc_Attr
) MmCopyFromCaller(&dc
->Dc_Attr
, Dc_Attr
, sizeof(DC_ATTR
));
264 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
265 DC_FreeDcAttr(dce
->hDC
); // Free the dcattr.
266 DC_SetOwnership(dce
->hDC
, NULL
); // Set hDC inaccessible mode.
267 dce
->pProcess
= NULL
; // Reset ownership.
273 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
275 HANDLE hRgnVisible
= NULL
;
277 PWINDOW_OBJECT DesktopWindow
;
279 if (Flags
& DCX_PARENTCLIP
)
281 PWINDOW_OBJECT Parent
;
284 Parent
= Window
->Parent
;
291 ParentWnd
= Parent
->Wnd
;
293 if (ParentWnd
->Style
& WS_CLIPSIBLINGS
)
295 DcxFlags
= DCX_CLIPSIBLINGS
|
296 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
300 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
302 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
304 else if (Window
== NULL
)
306 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
307 if (NULL
!= DesktopWindow
)
309 hRgnVisible
= UnsafeIntCreateRectRgnIndirect(&DesktopWindow
->Wnd
->WindowRect
);
318 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
322 if (Flags
& DCX_INTERSECTRGN
)
324 if(Dce
->hClipRgn
!= NULL
)
326 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_AND
);
330 if(hRgnVisible
!= NULL
)
332 NtGdiDeleteObject(hRgnVisible
);
334 hRgnVisible
= NtGdiCreateRectRgn(0, 0, 0, 0);
338 if (Flags
& DCX_EXCLUDERGN
&& Dce
->hClipRgn
!= NULL
)
340 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_DIFF
);
343 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
344 IntGdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
348 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
351 if (hRgnVisible
!= NULL
)
353 NtGdiDeleteObject(hRgnVisible
);
358 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
360 PWINDOW_OBJECT Parent
;
363 BOOL UpdateVisRgn
= TRUE
;
364 BOOL UpdateClipOrigin
= FALSE
;
368 { // Do the same as GetDC with a NULL.
369 // Window = UserGetWindowObject(IntGetDesktopWindow());
370 // if (Window) Wnd = Window->Wnd;
372 Flags
&= ~DCX_USESTYLE
;
377 if (NULL
== Window
|| NULL
== Window
->Dce
)
382 if (Flags
& DCX_USESTYLE
)
384 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
386 if (Wnd
->Style
& WS_CLIPSIBLINGS
)
388 Flags
|= DCX_CLIPSIBLINGS
;
391 if (!(Flags
& DCX_WINDOW
))
393 if (Wnd
->Class
->Style
& CS_PARENTDC
)
395 Flags
|= DCX_PARENTCLIP
;
398 if (Wnd
->Style
& WS_CLIPCHILDREN
&&
399 !(Wnd
->Style
& WS_MINIMIZE
))
401 Flags
|= DCX_CLIPCHILDREN
;
410 if (Flags
& DCX_NOCLIPCHILDREN
)
413 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
416 if (Flags
& DCX_WINDOW
)
418 Flags
= (Flags
& ~DCX_CLIPCHILDREN
) | DCX_CACHE
;
421 Parent
= (Window
? Window
->Parent
: NULL
);
423 if (NULL
== Window
|| !(Wnd
->Style
& WS_CHILD
) || NULL
== Parent
)
425 Flags
&= ~DCX_PARENTCLIP
;
427 else if (Flags
& DCX_PARENTCLIP
)
430 if ((Wnd
->Style
& WS_VISIBLE
) &&
431 (Parent
->Wnd
->Style
& WS_VISIBLE
))
433 Flags
&= ~DCX_CLIPCHILDREN
;
434 if (Parent
->Wnd
->Style
& WS_CLIPSIBLINGS
)
436 Flags
|= DCX_CLIPSIBLINGS
;
441 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
443 if (Flags
& DCX_CACHE
)
445 DCE
* DceEmpty
= NULL
;
446 DCE
* DceUnused
= NULL
;
447 KeEnterCriticalRegion();
451 // The reason for this you may ask?
452 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
453 // Need to test for null here. Not sure if this is a bug or a feature.
456 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
459 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
463 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
464 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
467 UpdateVisRgn
= FALSE
;
470 UpdateClipOrigin
= TRUE
;
474 Dce
= (PDCE
)Dce
->List
.Flink
;
475 } while (Dce
!= FirstDce
);
476 KeLeaveCriticalRegion();
478 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
482 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
488 if (NULL
!= Dce
&& Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
))
490 UpdateVisRgn
= FALSE
; /* updated automatically, via DCHook() */
494 /* we should free dce->clip_rgn here, but Windows apparently doesn't */
495 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
496 Dce
->hClipRgn
= NULL
;
509 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
510 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
512 if (0 == (Flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
)) && NULL
!= ClipRegion
)
514 if (Flags
& DCX_KEEPCLIPRGN
)
515 NtGdiDeleteObject(ClipRegion
);
520 if (NULL
!= Dce
->hClipRgn
)
522 DceDeleteClipRgn(Dce
);
523 Dce
->hClipRgn
= NULL
;
527 if (0 != (Flags
& DCX_INTERSECTUPDATE
) && NULL
== ClipRegion
)
529 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
530 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
531 ClipRegion
= Window
->UpdateRegion
;
534 if (ClipRegion
== (HRGN
) 1)
536 if (!(Flags
& DCX_WINDOW
))
538 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->ClientRect
);
542 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->WindowRect
);
545 else if (ClipRegion
!= NULL
)
547 Dce
->hClipRgn
= ClipRegion
;
550 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
554 DceUpdateVisRgn(Dce
, Window
, Flags
);
557 if (Dce
->DCXFlags
& DCX_CACHE
)
559 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
560 // Need to set ownership so Sync dcattr will work.
561 DC_SetOwnership( Dce
->hDC
, PsGetCurrentProcess());
562 DC_AllocateDcAttr( Dce
->hDC
); // Allocate new dcattr
563 DCU_SynchDcAttrtoUser( Dce
->hDC
); // Copy data from dc to dcattr
564 Dce
->pProcess
= PsGetCurrentProcess(); // Set the temp owning process
569 /***********************************************************************
573 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
578 if (NULL
== pdce
) return NULL
;
580 ret
= (PDCE
) pdce
->List
.Flink
;
583 SetDCHook(pdce
->hDC
, NULL
, 0L);
586 if (Force
&& !GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, pdce
->hDC
))
588 DPRINT1("Change ownership for DCE!\n");
590 if (!IsObjectDead((HGDIOBJ
) pdce
->hDC
))
591 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
594 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
599 if (!Hit
) IntGdiDeleteDC(pdce
->hDC
, TRUE
);
601 if (pdce
->hClipRgn
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
603 NtGdiDeleteObject(pdce
->hClipRgn
);
606 RemoveEntryList(&pdce
->List
);
607 ExFreePoolWithTag(pdce
, TAG_PDCE
);
612 /***********************************************************************
615 * Remove owned DCE and reset unreleased cache DCEs.
618 DceFreeWindowDCE(PWINDOW_OBJECT Window
)
623 KeEnterCriticalRegion();
626 if (pDCE
->hwndCurrent
== Window
->hSelf
)
628 if (!(pDCE
->DCXFlags
& DCX_CACHE
)) /* owned or Class DCE*/
630 if (Window
->Wnd
->Class
->Style
& CS_CLASSDC
||
631 Window
->Wnd
->Style
& CS_CLASSDC
) /* Test Class first */
633 PWINDOW_OBJECT CurrentWindow
;
634 if (pDCE
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) /* Class DCE*/
635 DceDeleteClipRgn(pDCE
);
636 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
638 { // Update and reset Vis Rgn and clear the dirty bit.
639 // Should release VisRgn than reset it to default.
640 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
642 pDCE
->DCXFlags
= DCX_DCEEMPTY
;
643 pDCE
->hwndCurrent
= 0;
645 else if (Window
->Wnd
->Class
->Style
& CS_OWNDC
||
646 Window
->Wnd
->Style
& CS_OWNDC
) /* owned DCE*/
648 pDCE
= DceFreeDCE(pDCE
, FALSE
);
659 if (pDCE
->DCXFlags
& DCX_DCEBUSY
) /* shared cache DCE */
661 /* FIXME: AFAICS we are doing the right thing here so
662 * this should be a DPRINT. But this is best left as an ERR
663 * because the 'application error' is likely to come from
664 * another part of Wine (i.e. it's our fault after all).
665 * We should change this to DPRINT when ReactOS is more stable
668 DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window
->hSelf
);
669 DceReleaseDC(pDCE
, FALSE
);
671 pDCE
->DCXFlags
|= DCX_DCEEMPTY
;
672 pDCE
->hwndCurrent
= 0;
675 pDCE
= (PDCE
) pDCE
->List
.Flink
;
676 } while (pDCE
!= FirstDce
);
677 KeLeaveCriticalRegion();
683 while (FirstDce
!= NULL
)
685 FirstDce
= DceFreeDCE(FirstDce
, TRUE
);
690 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
694 PWINDOW_OBJECT CurrentWindow
;
703 if(!pDCE
) return; // Another null test!
706 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
708 if (Window
->hSelf
== pDCE
->hwndCurrent
)
710 CurrentWindow
= Window
;
714 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
715 if (NULL
== CurrentWindow
)
717 pDCE
= (PDCE
) pDCE
->List
.Flink
;
722 dc
= DC_LockDc(pDCE
->hDC
);
725 pDCE
= (PDCE
) pDCE
->List
.Flink
;
728 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
730 if (pDCE
->DCXFlags
& DCX_WINDOW
)
732 DeltaX
= CurrentWindow
->Wnd
->WindowRect
.left
- dc
->w
.DCOrgX
;
733 DeltaY
= CurrentWindow
->Wnd
->WindowRect
.top
- dc
->w
.DCOrgY
;
734 dc
->w
.DCOrgX
= CurrentWindow
->Wnd
->WindowRect
.left
;
735 dc
->w
.DCOrgY
= CurrentWindow
->Wnd
->WindowRect
.top
;
739 DeltaX
= CurrentWindow
->Wnd
->ClientRect
.left
- dc
->w
.DCOrgX
;
740 DeltaY
= CurrentWindow
->Wnd
->ClientRect
.top
- dc
->w
.DCOrgY
;
741 dc
->w
.DCOrgX
= CurrentWindow
->Wnd
->ClientRect
.left
;
742 dc
->w
.DCOrgY
= CurrentWindow
->Wnd
->ClientRect
.top
;
744 if (NULL
!= dc
->w
.hClipRgn
)
746 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
747 NtGdiOffsetRgn(dc
->w
.hClipRgn
, DeltaX
, DeltaY
);
748 CLIPPING_UpdateGCRegion(dc
);
750 if (NULL
!= pDCE
->hClipRgn
)
752 NtGdiOffsetRgn(pDCE
->hClipRgn
, DeltaX
, DeltaY
);
757 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
759 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
761 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
762 // UserDerefObject(CurrentWindow);
765 pDCE
=(PDCE
) pDCE
->List
.Flink
;
766 } while (pDCE
!= FirstDce
);
771 IntGetDC(PWINDOW_OBJECT Window
)
775 //"hWnd [in] Handle to the window whose DC is to be retrieved.
776 // If this value is NULL, GetDC retrieves the DC for the entire screen."
777 Window
= UserGetWindowObject(IntGetDesktopWindow());
779 return UserGetDCEx(Window
, NULL
, DCX_CACHE
| DCX_WINDOW
);
783 return UserGetDCEx(Window
, NULL
, DCX_USESTYLE
);
787 IntWindowFromDC(HDC hDc
)
791 KeEnterCriticalRegion();
797 Ret
= Dce
->hwndCurrent
;
800 Dce
= (PDCE
)Dce
->List
.Flink
;
801 } while (Dce
!= FirstDce
);
802 KeLeaveCriticalRegion();
807 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
813 DPRINT("%p %p\n", Window
, hDc
);
815 KeEnterCriticalRegion();
824 dce
= (PDCE
) dce
->List
.Flink
;
826 while (dce
!= FirstDce
);
827 KeLeaveCriticalRegion();
829 if ( Hit
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
831 nRet
= DceReleaseDC(dce
, EndPaint
);
838 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
840 return (DWORD
)UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
844 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
846 PWINDOW_OBJECT Wnd
=NULL
;
849 DPRINT("Enter NtUserGetDCEx\n");
850 UserEnterExclusive();
852 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
857 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
860 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
868 * The NtUserGetWindowDC function retrieves the device context (DC) for the
869 * entire window, including title bar, menus, and scroll bars. A window device
870 * context permits painting anywhere in a window, because the origin of the
871 * device context is the upper-left corner of the window instead of the client
878 NtUserGetWindowDC(HWND hWnd
)
880 return (DWORD
)NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
884 NtUserGetDC(HWND hWnd
)
886 // We have a problem here! Should call IntGetDC.
887 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
890 #define COPY_DEVMODE_VALUE_TO_CALLER(dst, src, member) \
891 Status = MmCopyToCaller(&(dst)->member, &(src)->member, sizeof ((src)->member)); \
892 if (!NT_SUCCESS(Status)) \
894 SetLastNtError(Status); \
901 NtUserEnumDisplaySettings(
902 PUNICODE_STRING lpszDeviceName
,
904 LPDEVMODEW lpDevMode
, /* FIXME is this correct? */
908 LPDEVMODEW pSafeDevMode
;
909 PUNICODE_STRING pSafeDeviceName
= NULL
;
910 UNICODE_STRING SafeDeviceName
;
911 USHORT Size
= 0, ExtraSize
= 0;
913 /* Copy the devmode */
914 Status
= MmCopyFromCaller(&Size
, &lpDevMode
->dmSize
, sizeof (Size
));
915 if (!NT_SUCCESS(Status
))
917 SetLastNtError(Status
);
920 Status
= MmCopyFromCaller(&ExtraSize
, &lpDevMode
->dmDriverExtra
, sizeof (ExtraSize
));
921 if (!NT_SUCCESS(Status
))
923 SetLastNtError(Status
);
926 pSafeDevMode
= ExAllocatePool(PagedPool
, Size
+ ExtraSize
);
927 if (pSafeDevMode
== NULL
)
929 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
932 pSafeDevMode
->dmSize
= Size
;
933 pSafeDevMode
->dmDriverExtra
= ExtraSize
;
935 /* Copy the device name */
936 if (lpszDeviceName
!= NULL
)
938 Status
= IntSafeCopyUnicodeString(&SafeDeviceName
, lpszDeviceName
);
939 if (!NT_SUCCESS(Status
))
941 ExFreePool(pSafeDevMode
);
942 SetLastNtError(Status
);
945 pSafeDeviceName
= &SafeDeviceName
;
948 /* Call internal function */
949 if (!IntEnumDisplaySettings(pSafeDeviceName
, iModeNum
, pSafeDevMode
, dwFlags
))
951 if (pSafeDeviceName
!= NULL
)
952 RtlFreeUnicodeString(pSafeDeviceName
);
953 ExFreePool(pSafeDevMode
);
956 if (pSafeDeviceName
!= NULL
)
957 RtlFreeUnicodeString(pSafeDeviceName
);
959 /* Copy some information back */
960 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmPelsWidth
);
961 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmPelsHeight
);
962 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmBitsPerPel
);
963 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmDisplayFrequency
);
964 COPY_DEVMODE_VALUE_TO_CALLER(lpDevMode
, pSafeDevMode
, dmDisplayFlags
);
966 /* output private/extra driver data */
969 Status
= MmCopyToCaller((PCHAR
)lpDevMode
+ Size
, (PCHAR
)pSafeDevMode
+ Size
, ExtraSize
);
970 if (!NT_SUCCESS(Status
))
972 SetLastNtError(Status
);
973 ExFreePool(pSafeDevMode
);
978 ExFreePool(pSafeDevMode
);
982 #undef COPY_DEVMODE_VALUE_TO_CALLER
986 NtUserChangeDisplaySettings(
987 PUNICODE_STRING lpszDeviceName
,
988 LPDEVMODEW lpDevMode
,
995 PUNICODE_STRING pSafeDeviceName
= NULL
;
996 UNICODE_STRING SafeDeviceName
;
999 /* Check arguments */
1000 #ifdef CDS_VIDEOPARAMETERS
1002 if (dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
)
1009 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1010 return DISP_CHANGE_BADPARAM
;
1014 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1015 return DISP_CHANGE_BADPARAM
;
1019 Status
= MmCopyFromCaller(&DevMode
.dmSize
, &lpDevMode
->dmSize
, sizeof (DevMode
.dmSize
));
1020 if (!NT_SUCCESS(Status
))
1022 SetLastNtError(Status
);
1023 return DISP_CHANGE_BADPARAM
;
1025 DevMode
.dmSize
= min(sizeof (DevMode
), DevMode
.dmSize
);
1026 Status
= MmCopyFromCaller(&DevMode
, lpDevMode
, DevMode
.dmSize
);
1027 if (!NT_SUCCESS(Status
))
1029 SetLastNtError(Status
);
1030 return DISP_CHANGE_BADPARAM
;
1032 if (DevMode
.dmDriverExtra
> 0)
1034 DbgPrint("(%s:%i) WIN32K: %s lpDevMode->dmDriverExtra is IGNORED!\n", __FILE__
, __LINE__
, __FUNCTION__
);
1035 DevMode
.dmDriverExtra
= 0;
1038 /* Copy the device name */
1039 if (lpszDeviceName
!= NULL
)
1041 Status
= IntSafeCopyUnicodeString(&SafeDeviceName
, lpszDeviceName
);
1042 if (!NT_SUCCESS(Status
))
1044 SetLastNtError(Status
);
1045 return DISP_CHANGE_BADPARAM
;
1047 pSafeDeviceName
= &SafeDeviceName
;
1050 /* Call internal function */
1051 Ret
= IntChangeDisplaySettings(pSafeDeviceName
, &DevMode
, dwflags
, lParam
);
1053 if (pSafeDeviceName
!= NULL
)
1054 RtlFreeUnicodeString(pSafeDeviceName
);
1060 * Select logical palette into device context.
1061 * \param hDC handle to the device context
1062 * \param hpal handle to the palette
1063 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
1064 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
1065 * palette colors in the best way.
1066 * \return old palette
1068 * \todo implement ForceBackground == TRUE
1070 HPALETTE STDCALL
NtUserSelectPalette(HDC hDC
,
1072 BOOL ForceBackground
)
1075 HPALETTE oldPal
= NULL
;
1078 // FIXME: mark the palette as a [fore\back]ground pal
1079 dc
= DC_LockDc(hDC
);
1082 /* Check if this is a valid palette handle */
1083 PalGDI
= PALETTE_LockPalette(hpal
);
1086 /* Is this a valid palette for this depth? */
1087 if ((dc
->w
.bitsPerPixel
<= 8 && PAL_INDEXED
== PalGDI
->Mode
)
1088 || (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
!= PalGDI
->Mode
))
1090 PALETTE_UnlockPalette(PalGDI
);
1091 oldPal
= dc
->w
.hPalette
;
1092 dc
->w
.hPalette
= hpal
;
1094 else if (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
== PalGDI
->Mode
)
1096 PALETTE_UnlockPalette(PalGDI
);
1097 oldPal
= dc
->PalIndexed
;
1098 dc
->PalIndexed
= hpal
;
1102 PALETTE_UnlockPalette(PalGDI
);