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.
19 /* $Id: dc.c,v 1.129 2004/04/25 11:34:13 weiden Exp $
21 * DC.C - Device context functions
25 #undef WIN32_LEAN_AND_MEAN
27 #include <ddk/ntddk.h>
28 #include <ddk/ntddvdeo.h>
29 #include <internal/safe.h>
30 #include <win32k/bitmaps.h>
31 #include <win32k/brush.h>
32 #include <win32k/cliprgn.h>
33 #include <win32k/coord.h>
34 #include <win32k/dc.h>
35 #include <win32k/misc.h>
36 #include <win32k/print.h>
37 #include <win32k/region.h>
38 #include <win32k/gdiobj.h>
39 #include <win32k/paint.h>
40 #include <win32k/pen.h>
41 #include <win32k/text.h>
42 #include "../eng/clip.h"
43 #include "../eng/handle.h"
44 #include <include/dce.h>
45 #include <include/error.h>
46 #include <include/inteng.h>
47 #include <include/eng.h>
48 #include <include/palette.h>
49 #include <include/guicheck.h>
50 #include <include/desktop.h>
51 #include <include/intgdi.h>
52 #include <include/cleanup.h>
53 #include <include/tags.h>
54 #include <include/text.h>
57 #include <win32k/debug1.h>
59 static GDIDEVICE PrimarySurface
;
61 /* FIXME: DCs should probably be thread safe */
64 * DC device-independent Get/SetXXX functions
65 * (RJJ) swiped from WINE
68 #define DC_GET_VAL( func_type, func_name, dc_field ) \
69 func_type STDCALL func_name( HDC hdc ) \
72 PDC dc = DC_LockDc( hdc ); \
82 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
83 * important that the function has the right signature, for the implementation
84 * we can do whatever we want.
86 #define DC_GET_VAL_EX( NtGdiFuncName, IntFuncName, ret_x, ret_y, type ) \
87 VOID FASTCALL IntFuncName ( PDC dc, LP##type pt ) \
91 ((LPPOINT)pt)->x = dc->ret_x; \
92 ((LPPOINT)pt)->y = dc->ret_y; \
94 BOOL STDCALL NtGdiFuncName ( HDC hdc, LP##type pt ) \
96 PDC dc = DC_LockDc ( hdc ); \
99 IntFuncName ( dc, pt ); \
100 DC_UnlockDc ( hdc ); \
104 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
105 INT STDCALL func_name( HDC hdc, INT mode ) \
109 if ((mode < min_val) || (mode > max_val)) \
111 dc = DC_LockDc ( hdc ); \
114 prevMode = dc->dc_field; \
115 dc->dc_field = mode; \
116 DC_UnlockDc ( hdc ); \
121 // --------------------------------------------------------- File Statics
123 // ----------------------------------------------------- Public Functions
126 NtGdiCancelDC(HDC hDC
)
132 NtGdiCreateCompatableDC(HDC hDC
)
136 HDC hNewDC
, DisplayDC
;
139 UNICODE_STRING DriverName
;
144 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
145 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
);
146 if (NULL
== DisplayDC
)
153 /* Allocate a new DC based on the original DC's device */
154 OrigDC
= DC_LockDc(hDC
);
157 if (NULL
!= DisplayDC
)
159 NtGdiDeleteDC(DisplayDC
);
163 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
168 if (NULL
!= DisplayDC
)
170 NtGdiDeleteDC(DisplayDC
);
174 NewDC
= DC_LockDc( hNewDC
);
176 /* Copy information from original DC to new DC */
177 NewDC
->hSelf
= hNewDC
;
179 NewDC
->PDev
= OrigDC
->PDev
;
180 NewDC
->DMW
= OrigDC
->DMW
;
181 memcpy(NewDC
->FillPatternSurfaces
,
182 OrigDC
->FillPatternSurfaces
,
183 sizeof OrigDC
->FillPatternSurfaces
);
184 NewDC
->GDIInfo
= OrigDC
->GDIInfo
;
185 NewDC
->DevInfo
= OrigDC
->DevInfo
;
186 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
188 /* DriverName is copied in the AllocDC routine */
189 NewDC
->DeviceDriver
= OrigDC
->DeviceDriver
;
190 NewDC
->wndOrgX
= OrigDC
->wndOrgX
;
191 NewDC
->wndOrgY
= OrigDC
->wndOrgY
;
192 NewDC
->wndExtX
= OrigDC
->wndExtX
;
193 NewDC
->wndExtY
= OrigDC
->wndExtY
;
194 NewDC
->vportOrgX
= OrigDC
->vportOrgX
;
195 NewDC
->vportOrgY
= OrigDC
->vportOrgY
;
196 NewDC
->vportExtX
= OrigDC
->vportExtX
;
197 NewDC
->vportExtY
= OrigDC
->vportExtY
;
199 /* Create default bitmap */
200 if (!(hBitmap
= NtGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
203 DC_UnlockDc( hNewDC
);
205 if (NULL
!= DisplayDC
)
207 NtGdiDeleteDC(DisplayDC
);
211 NewDC
->w
.flags
= DC_MEMORY
;
212 NewDC
->w
.hBitmap
= hBitmap
;
213 NewDC
->w
.hFirstBitmap
= hBitmap
;
214 NewDC
->GDIDevice
= OrigDC
->GDIDevice
;
215 pb
= BITMAPOBJ_LockBitmap(hBitmap
);
216 NewDC
->Surface
= (HSURF
)BitmapToSurf(pb
, NewDC
->GDIDevice
);
217 BITMAPOBJ_UnlockBitmap(hBitmap
);
219 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
220 NewDC
->w
.textColor
= OrigDC
->w
.textColor
;
221 NewDC
->w
.textAlign
= OrigDC
->w
.textAlign
;
222 NewDC
->w
.backgroundColor
= OrigDC
->w
.backgroundColor
;
223 NewDC
->w
.backgroundMode
= OrigDC
->w
.backgroundMode
;
225 if (NULL
!= DisplayDC
)
227 NtGdiDeleteDC(DisplayDC
);
231 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
232 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
233 NtGdiDeleteObject(hVisRgn
);
241 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
243 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
244 WCHAR DeviceNameBuffer
[20];
247 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%d", DisplayNumber
);
248 RtlInitUnicodeString(RegistryPath
, NULL
);
249 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
250 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
251 QueryTable
[0].Name
= DeviceNameBuffer
;
252 QueryTable
[0].EntryContext
= RegistryPath
;
254 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
259 if (! NT_SUCCESS(Status
))
261 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
265 DPRINT("RegistryPath %S\n", RegistryPath
->Buffer
);
271 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
273 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
274 UNICODE_STRING RegistryPath
;
277 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
279 DPRINT("GetRegistryPath failed\n");
283 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
284 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
285 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
286 QueryTable
[0].EntryContext
= DriverFileNames
;
288 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
293 RtlFreeUnicodeString(&RegistryPath
);
294 if (! NT_SUCCESS(Status
))
296 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
300 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
305 static NTSTATUS STDCALL
306 DevModeCallback(IN PWSTR ValueName
,
309 IN ULONG ValueLength
,
311 IN PVOID EntryContext
)
313 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
315 DPRINT("Found registry value for name %S: type %d, length %d\n",
316 ValueName
, ValueType
, ValueLength
);
318 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
320 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
322 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
324 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
326 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
328 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
330 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
332 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
334 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
336 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
338 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
340 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
342 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
344 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
346 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
350 return STATUS_SUCCESS
;
354 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
356 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
357 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
358 static WCHAR ControlSet
[] = L
"CONTROLSET";
359 static WCHAR Insert
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
360 UNICODE_STRING RegistryPath
;
362 PWCHAR AfterControlSet
;
364 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
367 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
369 DPRINT("GetRegistryPath failed\n");
373 Valid
= (0 == _wcsnicmp(RegistryPath
.Buffer
, RegistryMachineSystem
,
374 wcslen(RegistryMachineSystem
)));
377 AfterControlSet
= RegistryPath
.Buffer
+ wcslen(RegistryMachineSystem
);
378 if (0 == _wcsnicmp(AfterControlSet
, CurrentControlSet
, wcslen(CurrentControlSet
)))
380 AfterControlSet
+= wcslen(CurrentControlSet
);
382 else if (0 == _wcsnicmp(AfterControlSet
, ControlSet
, wcslen(ControlSet
)))
384 AfterControlSet
+= wcslen(ControlSet
);
385 while (L
'0' <= *AfterControlSet
&& L
'9' <= *AfterControlSet
)
389 Valid
= (L
'\\' == *AfterControlSet
);
400 ProfilePath
= ExAllocatePoolWithTag(PagedPool
,
401 (wcslen(RegistryPath
.Buffer
) +
402 wcslen(Insert
) + 1) * sizeof(WCHAR
),
404 if (NULL
!= ProfilePath
)
406 wcsncpy(ProfilePath
, RegistryPath
.Buffer
, AfterControlSet
- RegistryPath
.Buffer
);
407 wcscpy(ProfilePath
+ (AfterControlSet
- RegistryPath
.Buffer
), Insert
);
408 wcscat(ProfilePath
, AfterControlSet
);
410 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
411 QueryTable
[0].QueryRoutine
= DevModeCallback
;
412 QueryTable
[0].Flags
= 0;
413 QueryTable
[0].Name
= NULL
;
414 QueryTable
[0].EntryContext
= NULL
;
415 QueryTable
[0].DefaultType
= REG_NONE
;
416 QueryTable
[0].DefaultData
= NULL
;
417 QueryTable
[0].DefaultLength
= 0;
419 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
424 if (! NT_SUCCESS(Status
))
426 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
427 ProfilePath
, Status
);
432 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
433 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
434 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
435 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
436 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
438 DPRINT("Not all required devmode members are set\n");
443 ExFreePool(ProfilePath
);
452 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath
.Buffer
);
455 RtlFreeUnicodeString(&RegistryPath
);
459 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
466 IntCreatePrimarySurface()
468 PGD_ENABLEDRIVER GDEnableDriver
;
472 UNICODE_STRING DriverFileNames
;
478 for (DisplayNumber
= 0; ; DisplayNumber
++)
480 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
482 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
483 ExInitializeFastMutex(&PrimarySurface
.DriverLock
);
485 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
487 /* Open the miniport driver */
488 if (PrimarySurface
.VideoFileObject
== NULL
)
490 DPRINT1("FindMPDriver failed\n");
494 /* Retrieve DDI driver names from registry */
495 RtlInitUnicodeString(&DriverFileNames
, NULL
);
496 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
498 DPRINT1("FindDriverFileNames failed\n");
504 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
505 * scan all of them until a good one found.
507 CurrentName
= DriverFileNames
.Buffer
;
510 CurrentName
< DriverFileNames
.Buffer
+ DriverFileNames
.Length
)
512 /* Get the DDI driver's entry point */
513 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
514 if (NULL
== GDEnableDriver
)
516 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
520 /* Call DDI driver's EnableDriver function */
521 RtlZeroMemory(&DED
, sizeof(DED
));
523 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
525 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
535 /* Skip to the next name but never get past the Unicode string */
536 while (L
'\0' != *CurrentName
&&
537 CurrentName
< DriverFileNames
.Buffer
+ DriverFileNames
.Length
)
541 if (CurrentName
< DriverFileNames
.Buffer
+ DriverFileNames
.Length
)
548 RtlFreeUnicodeString(&DriverFileNames
);
552 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
553 DPRINT1("No suitable DDI driver found\n");
558 DPRINT("Display driver %S loaded\n", CurrentName
);
560 DPRINT("Building DDI Functions\n");
562 /* Construct DDI driver function dispatch table */
563 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
565 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
566 DPRINT1("BuildDDIFunctions failed\n");
570 /* Allocate a phyical device handle from the driver */
571 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
573 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDev(
577 PrimarySurface
.FillPatterns
,
578 sizeof(PrimarySurface
.GDIInfo
),
579 (ULONG
*) &PrimarySurface
.GDIInfo
,
580 sizeof(PrimarySurface
.DevInfo
),
581 &PrimarySurface
.DevInfo
,
584 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
585 DoDefault
= (NULL
== PrimarySurface
.PDev
);
588 DPRINT1("DrvEnablePDev with registry parameters failed\n");
598 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
599 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDev(
603 PrimarySurface
.FillPatterns
,
604 sizeof(PrimarySurface
.GDIInfo
),
605 (ULONG
*) &PrimarySurface
.GDIInfo
,
606 sizeof(PrimarySurface
.DevInfo
),
607 &PrimarySurface
.DevInfo
,
610 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
612 if (NULL
== PrimarySurface
.PDev
)
614 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
615 DPRINT1("DrvEnablePDEV with default parameters failed\n");
616 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
622 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
624 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
625 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
627 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
629 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
630 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
633 DPRINT("calling completePDev\n");
635 /* Complete initialization of the physical device */
636 PrimarySurface
.DriverFunctions
.CompletePDev(
638 (HDEV
)&PrimarySurface
);
640 DPRINT("calling DRIVER_ReferenceDriver\n");
642 DRIVER_ReferenceDriver(L
"DISPLAY");
644 DPRINT("calling EnableSurface\n");
646 /* Enable the drawing surface */
647 PrimarySurface
.Handle
=
648 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
649 if (NULL
== PrimarySurface
.Handle
)
651 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
652 PrimarySurface
.DriverFunctions
.DisablePDev(PrimarySurface
.PDev
);
653 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
654 DPRINT1("DrvEnableSurface failed\n");
659 SurfObj
= (SURFOBJ
*)AccessUserObject((ULONG
) PrimarySurface
.Handle
);
660 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
661 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) PrimarySurface
.Handle
);
663 IntGetActiveDesktop(),
664 SurfGDI
->SurfObj
.sizlBitmap
.cx
,
665 SurfGDI
->SurfObj
.sizlBitmap
.cy
);
673 IntDestroyPrimarySurface()
680 DRIVER_UnreferenceDriver(L
"DISPLAY");
683 DPRINT("Hiding mouse pointer\n" );
684 SurfObj
= (SURFOBJ
*)AccessUserObject((ULONG
) PrimarySurface
.Handle
);
685 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) PrimarySurface
.Handle
);
686 SurfGDI
->SetPointerShape(SurfObj
, NULL
, NULL
, NULL
, 0, 0, 0, 0, 0, 0);
688 DPRINT("Reseting display\n" );
689 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, FALSE
);
690 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.PDev
);
691 PrimarySurface
.DriverFunctions
.DisablePDev(PrimarySurface
.PDev
);
695 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
699 IntGdiCreateDC(PUNICODE_STRING Driver
,
700 PUNICODE_STRING Device
,
701 PUNICODE_STRING Output
,
702 CONST PDEVMODEW InitData
)
709 UNICODE_STRING StdDriver
;
711 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
713 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
715 if (! IntGraphicsCheck(TRUE
))
717 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
722 /* Check for existing DC object */
723 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
726 return NtGdiCreateCompatableDC(hDC
);
729 if (Driver
!= NULL
&& Driver
->Buffer
!= NULL
)
731 DPRINT("NAME: %S\n", Driver
->Buffer
); // FIXME: Should not crash if NULL
734 /* Allocate a DC object */
735 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
740 NewDC
= DC_LockDc( hNewDC
);
743 NewDC
->DMW
= PrimarySurface
.DMW
;
744 NewDC
->DevInfo
= &PrimarySurface
.DevInfo
;
745 NewDC
->GDIInfo
= &PrimarySurface
.GDIInfo
;
746 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
747 sizeof(NewDC
->FillPatternSurfaces
));
748 NewDC
->PDev
= PrimarySurface
.PDev
;
749 NewDC
->Surface
= PrimarySurface
.Handle
;
750 NewDC
->GDIDevice
= (HDEV
)&PrimarySurface
;
751 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
753 NewDC
->DMW
.dmSize
= sizeof(NewDC
->DMW
);
754 NewDC
->DMW
.dmFields
= 0x000fc000;
756 /* FIXME: get mode selection information from somewhere */
758 NewDC
->DMW
.dmLogPixels
= 96;
759 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) PrimarySurface
.Handle
);
760 NewDC
->DMW
.dmBitsPerPel
= SurfGDI
->BitsPerPixel
;
761 NewDC
->DMW
.dmPelsWidth
= SurfGDI
->SurfObj
.sizlBitmap
.cx
;
762 NewDC
->DMW
.dmPelsHeight
= SurfGDI
->SurfObj
.sizlBitmap
.cy
;
763 NewDC
->DMW
.dmDisplayFlags
= 0;
764 NewDC
->DMW
.dmDisplayFrequency
= 0;
766 NewDC
->w
.bitsPerPixel
= SurfGDI
->BitsPerPixel
; // FIXME: set this here??
768 NewDC
->w
.hPalette
= NewDC
->DevInfo
->hpalDefault
;
770 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
772 DC_UnlockDc( hNewDC
);
774 hVisRgn
= NtGdiCreateRectRgn(0, 0, SurfGDI
->SurfObj
.sizlBitmap
.cx
,
775 SurfGDI
->SurfObj
.sizlBitmap
.cy
);
776 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
777 NtGdiDeleteObject(hVisRgn
);
779 /* Initialize the DC state */
781 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
782 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
783 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
784 NtGdiSetBkMode(hNewDC
, OPAQUE
);
790 NtGdiCreateDC(PUNICODE_STRING Driver
,
791 PUNICODE_STRING Device
,
792 PUNICODE_STRING Output
,
793 CONST PDEVMODEW InitData
)
795 UNICODE_STRING SafeDriver
, SafeDevice
;
796 DEVMODEW SafeInitData
;
802 Status
= MmCopyFromCaller(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
803 if(!NT_SUCCESS(Status
))
805 SetLastNtError(Status
);
808 /* FIXME - InitData can have some more bytes! */
813 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
814 if(!NT_SUCCESS(Status
))
816 SetLastNtError(Status
);
823 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
824 if(!NT_SUCCESS(Status
))
826 RtlFreeUnicodeString(&SafeDriver
);
827 SetLastNtError(Status
);
832 Ret
= IntGdiCreateDC(&SafeDriver
, &SafeDevice
, NULL
, &SafeInitData
);
838 NtGdiCreateIC(PUNICODE_STRING Driver
,
839 PUNICODE_STRING Device
,
840 PUNICODE_STRING Output
,
841 CONST PDEVMODEW DevMode
)
843 /* FIXME: this should probably do something else... */
844 return NtGdiCreateDC(Driver
, Device
, Output
, DevMode
);
848 NtGdiDeleteDC(HDC DCHandle
)
852 DCToDelete
= DC_LockDc(DCHandle
);
853 if (DCToDelete
== NULL
)
857 DPRINT( "Deleting DC\n" );
859 /* First delete all saved DCs */
860 while (DCToDelete
->saveLevel
)
865 savedHDC
= DC_GetNextDC (DCToDelete
);
866 savedDC
= DC_LockDc (savedHDC
);
871 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
872 DCToDelete
->saveLevel
--;
873 DC_UnlockDc( savedHDC
);
874 NtGdiDeleteDC (savedHDC
);
877 /* Free GDI resources allocated to this DC */
878 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
881 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
882 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
883 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
884 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
885 if (DCToDelete
->w
.flags
& DC_MEMORY
)
887 EngDeleteSurface (DCToDelete
->Surface
);
888 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
891 if (DCToDelete
->w
.hClipRgn
)
893 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
895 if (DCToDelete
->w
.hVisRgn
)
897 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
899 if (NULL
!= DCToDelete
->CombinedClip
)
901 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
903 if (DCToDelete
->w
.hGCClipRgn
)
905 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
908 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
910 DC_UnlockDc( DCHandle
);
911 DC_FreeDC ( DCHandle
);
917 NtGdiDrawEscape(HDC hDC
,
926 NtGdiEnumObjects(HDC hDC
,
928 GOBJENUMPROC ObjectFunc
,
934 DC_GET_VAL( COLORREF
, NtGdiGetBkColor
, w
.backgroundColor
)
935 DC_GET_VAL( INT
, NtGdiGetBkMode
, w
.backgroundMode
)
936 DC_GET_VAL_EX( NtGdiGetBrushOrgEx
, IntGetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
)
937 DC_GET_VAL( HRGN
, NtGdiGetClipRgn
, w
.hClipRgn
)
940 NtGdiGetCurrentObject(HDC hDC
, UINT ObjectType
)
945 DC_GET_VAL_EX ( NtGdiGetCurrentPositionEx
, IntGetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
)
948 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
950 Point
->x
= dc
->w
.DCOrgX
;
951 Point
->y
= dc
->w
.DCOrgY
;
957 NtGdiGetDCOrgEx(HDC hDC
, LPPOINT Point
)
966 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
973 SetLastWin32Error(ERROR_INVALID_HANDLE
);
977 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
979 Status
= MmCopyToCaller(Point
, &SafePoint
, sizeof(POINT
));
980 if(!NT_SUCCESS(Status
))
982 SetLastNtError(Status
);
992 NtGdiSetBkColor(HDC hDC
, COLORREF color
)
995 PDC dc
= DC_LockDc(hDC
);
1001 oldColor
= dc
->w
.backgroundColor
;
1002 dc
->w
.backgroundColor
= color
;
1003 hBrush
= dc
->w
.hBrush
;
1004 DC_UnlockDc ( hDC
);
1005 NtGdiSelectObject(hDC
, hBrush
);
1010 NtGdiGetDCState(HDC hDC
)
1015 dc
= DC_LockDc(hDC
);
1021 hnewdc
= DC_AllocDC(NULL
);
1027 newdc
= DC_LockDc( hnewdc
);
1030 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1031 newdc
->w
.hPen
= dc
->w
.hPen
;
1032 newdc
->w
.hBrush
= dc
->w
.hBrush
;
1033 newdc
->w
.hFont
= dc
->w
.hFont
;
1034 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1035 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1037 newdc
->w
.hDevice
= dc
->w
.hDevice
;
1038 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1040 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1041 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1042 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
1043 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
1044 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
1045 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
1046 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
1047 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
1048 newdc
->w
.textColor
= dc
->w
.textColor
;
1049 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
1050 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
1051 newdc
->w
.textAlign
= dc
->w
.textAlign
;
1052 newdc
->w
.charExtra
= dc
->w
.charExtra
;
1053 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
1054 newdc
->w
.breakCount
= dc
->w
.breakCount
;
1055 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
1056 newdc
->w
.breakRem
= dc
->w
.breakRem
;
1057 newdc
->w
.MapMode
= dc
->w
.MapMode
;
1058 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
1060 /* Apparently, the DC origin is not changed by [GS]etDCState */
1061 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1062 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1064 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
1065 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
1066 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1067 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1068 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1069 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1070 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1071 newdc
->wndOrgX
= dc
->wndOrgX
;
1072 newdc
->wndOrgY
= dc
->wndOrgY
;
1073 newdc
->wndExtX
= dc
->wndExtX
;
1074 newdc
->wndExtY
= dc
->wndExtY
;
1075 newdc
->vportOrgX
= dc
->vportOrgX
;
1076 newdc
->vportOrgY
= dc
->vportOrgY
;
1077 newdc
->vportExtX
= dc
->vportExtX
;
1078 newdc
->vportExtY
= dc
->vportExtY
;
1080 newdc
->hSelf
= hnewdc
;
1081 newdc
->saveLevel
= 0;
1084 PATH_InitGdiPath( &newdc
->w
.path
);
1087 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1090 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1094 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1095 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1099 newdc
->w
.hClipRgn
= 0;
1101 DC_UnlockDc( hnewdc
);
1109 NtGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1113 dc
= DC_LockDc ( hDC
);
1116 dcs
= DC_LockDc ( hDCSave
);
1119 if ( dcs
->w
.flags
& DC_SAVED
)
1121 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1123 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1126 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1129 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1130 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1131 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1132 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1133 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1134 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1135 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1136 dc
->w
.textColor
= dcs
->w
.textColor
;
1137 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1138 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1139 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1140 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1141 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1142 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1143 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1144 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1145 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1146 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1148 /* Apparently, the DC origin is not changed by [GS]etDCState */
1149 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1150 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1152 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1153 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1154 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1156 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1157 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1158 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1159 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1161 dc
->wndOrgX
= dcs
->wndOrgX
;
1162 dc
->wndOrgY
= dcs
->wndOrgY
;
1163 dc
->wndExtX
= dcs
->wndExtX
;
1164 dc
->wndExtY
= dcs
->wndExtY
;
1165 dc
->vportOrgX
= dcs
->vportOrgX
;
1166 dc
->vportOrgY
= dcs
->vportOrgY
;
1167 dc
->vportExtX
= dcs
->vportExtX
;
1168 dc
->vportExtY
= dcs
->vportExtY
;
1170 if (!(dc
->w
.flags
& DC_MEMORY
))
1172 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1176 if (dcs
->w
.hClipRgn
)
1178 if (!dc
->w
.hClipRgn
)
1180 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1182 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1188 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1193 CLIPPING_UpdateGCRegion( dc
);
1194 DC_UnlockDc ( hDC
);
1196 DC_UnlockDc ( hDC
);
1197 NtGdiSelectClipRgn(hDC
, dcs
->w
.hClipRgn
);
1200 NtGdiSelectObject( hDC
, dcs
->w
.hBitmap
);
1201 NtGdiSelectObject( hDC
, dcs
->w
.hBrush
);
1202 NtGdiSelectObject( hDC
, dcs
->w
.hFont
);
1203 NtGdiSelectObject( hDC
, dcs
->w
.hPen
);
1204 NtGdiSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1205 NtGdiSetTextColor( hDC
, dcs
->w
.textColor
);
1208 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1213 DC_UnlockDc ( hDCSave
);
1215 DC_UnlockDc ( hDC
);
1221 NtGdiGetDeviceCaps(HDC hDC
,
1228 dc
= DC_LockDc(hDC
);
1234 /* Retrieve capability */
1238 ret
= dc
->GDIInfo
->ulVersion
;
1242 ret
= dc
->GDIInfo
->ulTechnology
;
1246 ret
= dc
->GDIInfo
->ulHorzSize
;
1250 ret
= dc
->GDIInfo
->ulVertSize
;
1254 ret
= dc
->GDIInfo
->ulHorzRes
;
1258 ret
= dc
->GDIInfo
->ulVertRes
;
1262 ret
= dc
->GDIInfo
->ulLogPixelsX
;
1266 ret
= dc
->GDIInfo
->ulLogPixelsY
;
1270 ret
= dc
->GDIInfo
->cBitsPixel
;
1274 ret
= dc
->GDIInfo
->cPlanes
;
1278 UNIMPLEMENTED
; /* FIXME */
1282 UNIMPLEMENTED
; /* FIXME */
1286 UNIMPLEMENTED
; /* FIXME */
1290 ret
= dc
->GDIInfo
->ulNumColors
;
1294 ret
= dc
->GDIInfo
->ulAspectX
;
1298 ret
= dc
->GDIInfo
->ulAspectY
;
1302 ret
= dc
->GDIInfo
->ulAspectXY
;
1306 UNIMPLEMENTED
; /* FIXME */
1310 UNIMPLEMENTED
; /* FIXME */
1314 ret
= dc
->GDIInfo
->ulNumPalReg
; /* FIXME not sure */
1322 UNIMPLEMENTED
; /* FIXME */
1326 if(NtGdiEscape(hDC
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1336 case PHYSICALHEIGHT
:
1337 if(NtGdiEscape(hDC
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1347 case PHYSICALOFFSETX
:
1348 if(NtGdiEscape(hDC
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1358 case PHYSICALOFFSETY
:
1359 if(NtGdiEscape(hDC
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1370 UNIMPLEMENTED
; /* FIXME */
1373 case SCALINGFACTORX
:
1374 if(NtGdiEscape(hDC
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1384 case SCALINGFACTORY
:
1385 if(NtGdiEscape(hDC
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1396 ret
= dc
->GDIInfo
->flRaster
;
1400 UNIMPLEMENTED
; /* FIXME */
1404 UNIMPLEMENTED
; /* FIXME */
1408 UNIMPLEMENTED
; /* FIXME */
1412 ret
= dc
->GDIInfo
->flTextCaps
;
1420 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1426 DC_GET_VAL( INT
, NtGdiGetMapMode
, w
.MapMode
)
1427 DC_GET_VAL( INT
, NtGdiGetPolyFillMode
, w
.polyFillMode
)
1430 IntGdiGetObject(HANDLE Handle
, INT Count
, LPVOID Buffer
)
1432 PGDIOBJHDR GdiObject
;
1436 GdiObject
= GDIOBJ_LockObj(Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1437 if (NULL
== GdiObject
)
1442 ObjectType
= GDIOBJ_GetObjectType(Handle
);
1446 case GDI_OBJECT_TYPE_PEN
:
1447 Result
= PEN_GetObject((PENOBJ
*) GdiObject
, Count
, Buffer
);
1449 case GDI_OBJECT_TYPE_BRUSH
:
1450 Result
= BRUSH_GetObject((BRUSHOBJ
*) GdiObject
, Count
, Buffer
);
1453 case GDI_OBJECT_TYPE_BITMAP
:
1454 Result
= BITMAP_GetObject((BITMAPOBJ
*) GdiObject
, Count
, Buffer
);
1456 case GDI_OBJECT_TYPE_FONT
:
1457 Result
= FontGetObject((PTEXTOBJ
) GdiObject
, Count
, Buffer
);
1459 // Fix the LOGFONT structure for the stock fonts
1460 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1462 FixStockFontSizeW(Handle
, Count
, Buffer
);
1467 case GDI_OBJECT_TYPE_PALETTE
:
1468 Result
= PALETTE_GetObject((PALETTEOBJ
*) GdiObject
, Count
, Buffer
);
1472 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType
);
1476 GDIOBJ_UnlockObj(Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1482 NtGdiGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
1493 SafeBuf
= ExAllocatePoolWithTag(NonPagedPool
, count
, TAG_GDIOBJ
);
1496 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1500 Ret
= IntGdiGetObject(handle
, count
, SafeBuf
);
1502 Status
= MmCopyToCaller(buffer
, SafeBuf
, count
);
1503 ExFreePool(SafeBuf
);
1504 if(!NT_SUCCESS(Status
))
1506 SetLastNtError(Status
);
1514 NtGdiGetObjectType(HANDLE handle
)
1520 ptr
= GDIOBJ_LockObj(handle
, GDI_OBJECT_TYPE_DONTCARE
);
1524 objectType
= GDIOBJ_GetObjectType(handle
);
1527 case GDI_OBJECT_TYPE_PEN
:
1530 case GDI_OBJECT_TYPE_BRUSH
:
1533 case GDI_OBJECT_TYPE_BITMAP
:
1534 result
= OBJ_BITMAP
;
1536 case GDI_OBJECT_TYPE_FONT
:
1539 case GDI_OBJECT_TYPE_PALETTE
:
1542 case GDI_OBJECT_TYPE_REGION
:
1543 result
= OBJ_REGION
;
1545 case GDI_OBJECT_TYPE_DC
:
1548 case GDI_OBJECT_TYPE_METADC
:
1549 result
= OBJ_METADC
;
1551 case GDI_OBJECT_TYPE_METAFILE
:
1552 result
= OBJ_METAFILE
;
1554 case GDI_OBJECT_TYPE_ENHMETAFILE
:
1555 result
= OBJ_ENHMETAFILE
;
1557 case GDI_OBJECT_TYPE_ENHMETADC
:
1558 result
= OBJ_ENHMETADC
;
1560 case GDI_OBJECT_TYPE_EXTPEN
:
1561 result
= OBJ_EXTPEN
;
1563 case GDI_OBJECT_TYPE_MEMDC
:
1567 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
1570 GDIOBJ_UnlockObj(handle
, GDI_OBJECT_TYPE_DONTCARE
);
1574 DC_GET_VAL( INT
, NtGdiGetRelAbs
, w
.relAbsMode
)
1575 DC_GET_VAL( INT
, NtGdiGetROP2
, w
.ROPmode
)
1576 DC_GET_VAL( INT
, NtGdiGetStretchBltMode
, w
.stretchBltMode
)
1577 DC_GET_VAL( UINT
, NtGdiGetTextAlign
, w
.textAlign
)
1578 DC_GET_VAL( COLORREF
, NtGdiGetTextColor
, w
.textColor
)
1579 DC_GET_VAL_EX( NtGdiGetViewportExtEx
, IntGetViewportExtEx
, vportExtX
, vportExtY
, SIZE
)
1580 DC_GET_VAL_EX( NtGdiGetViewportOrgEx
, IntGetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
)
1581 DC_GET_VAL_EX( NtGdiGetWindowExtEx
, IntGetWindowExtEx
, wndExtX
, wndExtY
, SIZE
)
1582 DC_GET_VAL_EX( NtGdiGetWindowOrgEx
, IntGetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
)
1585 NtGdiResetDC(HDC hDC
, CONST DEVMODEW
*InitData
)
1591 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1596 dc
= DC_LockDc(hDC
);
1602 if (SaveLevel
== -1)
1604 SaveLevel
= dc
->saveLevel
;
1607 if ((SaveLevel
< 1) || (SaveLevel
> dc
->saveLevel
))
1613 while (dc
->saveLevel
>= SaveLevel
)
1615 HDC hdcs
= DC_GetNextDC (dc
);
1617 dcs
= DC_LockDc (hdcs
);
1622 DC_SetNextDC (dcs
, DC_GetNextDC (dcs
));
1623 if (--dc
->saveLevel
< SaveLevel
)
1626 DC_UnlockDc( hdcs
);
1627 NtGdiSetDCState(hDC
, hdcs
);
1629 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1631 /* FIXME: This might not be quite right, since we're
1632 * returning FALSE but still destroying the saved DC state */
1636 dc
= DC_LockDc(hDC
);
1644 DC_UnlockDc( hdcs
);
1646 NtGdiDeleteDC (hdcs
);
1653 NtGdiSaveDC(HDC hDC
)
1659 if (!(hdcs
= NtGdiGetDCState(hDC
)))
1664 dcs
= DC_LockDc (hdcs
);
1669 dc
= DC_LockDc (hDC
);
1677 /* Copy path. The reason why path saving / restoring is in SaveDC/
1678 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1679 * functions are only in Win16 (which doesn't have paths) and that
1680 * SetDCState doesn't allow us to signal an error (which can happen
1681 * when copying paths).
1683 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
1685 NtGdiDeleteDC (hdcs
);
1690 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
1691 DC_SetNextDC (dc
, hdcs
);
1692 ret
= ++dc
->saveLevel
;
1693 DC_UnlockDc( hdcs
);
1701 NtGdiSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
1703 HGDIOBJ objOrg
= NULL
; // default to failure
1712 COLORREF MonoColorMap
[2];
1713 ULONG NumColors
, Index
;
1717 if(!hDC
|| !hGDIObj
) return NULL
;
1719 dc
= DC_LockDc(hDC
);
1722 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1726 objectType
= GDIOBJ_GetObjectType(hGDIObj
);
1730 case GDI_OBJECT_TYPE_PEN
:
1732 /* Convert the color of the pen to the format of the DC */
1733 PalGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
1736 Mode
= PalGDI
->Mode
;
1737 PALETTE_UnlockPalette(dc
->w
.hPalette
);
1738 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
1739 if (NULL
!= XlateObj
)
1741 pen
= PENOBJ_LockPen((HPEN
) hGDIObj
);
1744 if (pen
->flAttrs
& GDIBRUSH_IS_SOLID
)
1746 pen
->BrushObject
.iSolidColor
=
1747 XLATEOBJ_iXlate(XlateObj
, pen
->BrushAttr
.lbColor
);
1751 pen
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
1753 pen
->crBack
= XLATEOBJ_iXlate(XlateObj
, dc
->w
.backgroundColor
);
1754 pen
->crFore
= XLATEOBJ_iXlate(XlateObj
, dc
->w
.textColor
);
1755 PENOBJ_UnlockPen((HPEN
) hGDIObj
);
1756 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
1757 dc
->w
.hPen
= hGDIObj
;
1761 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1763 EngDeleteXlate(XlateObj
);
1767 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1772 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1776 case GDI_OBJECT_TYPE_BRUSH
:
1778 /* Convert the color of the brush to the format of the DC */
1779 PalGDI
= PALETTE_LockPalette(dc
->w
.hPalette
);
1782 Mode
= PalGDI
->Mode
;
1783 PALETTE_UnlockPalette(dc
->w
.hPalette
);
1784 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
1785 if (NULL
!= XlateObj
)
1787 brush
= BRUSHOBJ_LockBrush((HBRUSH
) hGDIObj
);
1790 if (brush
->flAttrs
& GDIBRUSH_IS_SOLID
)
1792 brush
->BrushObject
.iSolidColor
=
1793 XLATEOBJ_iXlate(XlateObj
, brush
->BrushAttr
.lbColor
);
1797 brush
->BrushObject
.iSolidColor
= 0xFFFFFFFF;
1799 brush
->crBack
= XLATEOBJ_iXlate(XlateObj
, dc
->w
.backgroundColor
);
1800 brush
->crFore
= XLATEOBJ_iXlate(XlateObj
, ((brush
->flAttrs
& GDIBRUSH_IS_HATCH
) ?
1801 brush
->BrushAttr
.lbColor
: dc
->w
.textColor
));
1802 /* according to the documentation of SetBrushOrgEx(), the origin is assigned to the
1803 next brush selected into the DC, so we should set it here */
1804 brush
->ptOrigin
.x
= dc
->w
.brushOrgX
;
1805 brush
->ptOrigin
.y
= dc
->w
.brushOrgY
;
1807 BRUSHOBJ_UnlockBrush((HBRUSH
) hGDIObj
);
1808 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
1809 dc
->w
.hBrush
= (HBRUSH
) hGDIObj
;
1813 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1815 EngDeleteXlate(XlateObj
);
1819 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1824 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1828 case GDI_OBJECT_TYPE_FONT
:
1829 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
1830 dc
->w
.hFont
= (HFONT
) hGDIObj
;
1831 TextIntRealizeFont(dc
->w
.hFont
);
1834 case GDI_OBJECT_TYPE_BITMAP
:
1835 // must be memory dc to select bitmap
1836 if (!(dc
->w
.flags
& DC_MEMORY
))
1841 pb
= BITMAPOBJ_LockBitmap(hGDIObj
);
1844 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1848 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
1850 /* Release the old bitmap, lock the new one and convert it to a SURF */
1851 EngDeleteSurface(dc
->Surface
);
1852 dc
->w
.hBitmap
= hGDIObj
;
1853 dc
->Surface
= (HSURF
)BitmapToSurf(pb
, dc
->GDIDevice
);
1855 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1858 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
1860 if(pb
->dib
->dsBmih
.biBitCount
<= 8)
1862 if(pb
->dib
->dsBmih
.biBitCount
== 1) { NumColors
= 2; } else
1863 if(pb
->dib
->dsBmih
.biBitCount
== 4) { NumColors
= 16; } else
1864 if(pb
->dib
->dsBmih
.biBitCount
== 8) { NumColors
= 256; }
1866 ColorMap
= ExAllocatePoolWithTag(PagedPool
, sizeof(COLORREF
) * NumColors
, TAG_DC
);
1868 for (Index
= 0; Index
< NumColors
; Index
++)
1870 ColorMap
[Index
] = RGB(pb
->ColorMap
[Index
].rgbRed
,
1871 pb
->ColorMap
[Index
].rgbGreen
,
1872 pb
->ColorMap
[Index
].rgbBlue
);
1874 dc
->w
.hPalette
= PALETTE_AllocPalette(PAL_INDEXED
, NumColors
, (ULONG
*) ColorMap
, 0, 0, 0);
1875 ExFreePool(ColorMap
);
1877 else if ( 16 == pb
->dib
->dsBmih
.biBitCount
)
1879 dc
->w
.hPalette
= PALETTE_AllocPalette(PAL_BITFIELDS
, pb
->dib
->dsBmih
.biClrUsed
, NULL
, 0x7c00, 0x03e0, 0x001f);
1881 else if(pb
->dib
->dsBmih
.biBitCount
>= 24)
1883 dc
->w
.hPalette
= PALETTE_AllocPalette(PAL_RGB
, pb
->dib
->dsBmih
.biClrUsed
, NULL
, 0, 0, 0);
1888 dc
->w
.bitsPerPixel
= pb
->bitmap
.bmBitsPixel
;
1889 if (1 == dc
->w
.bitsPerPixel
)
1891 MonoColorMap
[0] = RGB(0, 0, 0);
1892 MonoColorMap
[1] = RGB(255, 255, 255);
1893 dc
->w
.hPalette
= PALETTE_AllocPalette(PAL_INDEXED
, 2, MonoColorMap
, 0, 0, 0);
1897 dc
->w
.hPalette
= dc
->DevInfo
->hpalDefault
;
1901 DC_UnlockDc ( hDC
);
1902 hVisRgn
= NtGdiCreateRectRgn ( 0, 0, pb
->bitmap
.bmWidth
, pb
->bitmap
.bmHeight
);
1903 NtGdiSelectVisRgn ( hDC
, hVisRgn
);
1904 NtGdiDeleteObject ( hVisRgn
);
1905 BITMAPOBJ_UnlockBitmap(hGDIObj
);
1909 case GDI_OBJECT_TYPE_REGION
:
1911 return (HGDIOBJ
) NtGdiSelectClipRgn(hDC
, (HRGN
) hGDIObj
);
1921 NtGdiSetHookFlags(HDC hDC
, WORD Flags
)
1924 DC
*dc
= DC_LockDc(hDC
);
1931 wRet
= dc
->w
.flags
& DC_DIRTY
;
1933 /* "Undocumented Windows" info is slightly confusing.
1936 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
1938 if (Flags
& DCHF_INVALIDATEVISRGN
)
1940 dc
->w
.flags
|= DC_DIRTY
;
1942 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
1944 dc
->w
.flags
&= ~DC_DIRTY
;
1952 DC_SET_MODE( NtGdiSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
1953 DC_SET_MODE( NtGdiSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
1954 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1955 DC_SET_MODE( NtGdiSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
1956 DC_SET_MODE( NtGdiSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
1958 // ---------------------------------------------------- Private Interface
1961 DC_AllocDC(PUNICODE_STRING Driver
)
1969 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
1974 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
1977 hDC
= (HDC
) GDIOBJ_AllocObj(sizeof(DC
), GDI_OBJECT_TYPE_DC
, (GDICLEANUPPROC
) DC_InternalDeleteDC
);
1987 NewDC
= DC_LockDc(hDC
);
1991 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
1992 NewDC
->DriverName
.Buffer
= Buf
;
1995 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
1996 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
1997 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
1998 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
1999 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2000 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2001 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2002 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2003 NewDC
->w
.vport2WorldValid
= TRUE
;
2004 NewDC
->w
.MapMode
= MM_TEXT
;
2006 NewDC
->w
.hFont
= NtGdiGetStockObject(SYSTEM_FONT
);
2007 TextIntRealizeFont(NewDC
->w
.hFont
);
2015 DC_FindOpenDC(PUNICODE_STRING Driver
)
2021 * Initialize some common fields in the Device Context structure.
2024 DC_InitDC(HDC DCHandle
)
2026 // NtGdiRealizeDefaultPalette(DCHandle);
2028 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2029 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2030 //NtGdiSelectObject(DCHandle, hFont);
2032 // CLIPPING_UpdateGCRegion(DCToInit);
2037 DC_FreeDC(HDC DCToFree
)
2039 if (!GDIOBJ_FreeObj(DCToFree
, GDI_OBJECT_TYPE_DC
, GDIOBJFLAG_DEFAULT
))
2041 DPRINT("DC_FreeDC failed\n");
2046 DC_InternalDeleteDC( PDC DCToDelete
)
2049 RtlFreeUnicodeString(&DCToDelete
->DriverName
);
2054 DC_GetNextDC (PDC pDC
)
2060 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2062 pDC
->hNext
= hNextDC
;
2066 DC_UpdateXforms(PDC dc
)
2068 XFORM xformWnd2Vport
;
2069 FLOAT scaleX
, scaleY
;
2071 /* Construct a transformation to do the window-to-viewport conversion */
2072 scaleX
= (dc
->wndExtX
? (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
: 0.0);
2073 scaleY
= (dc
->wndExtY
? (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
: 0.0);
2074 xformWnd2Vport
.eM11
= scaleX
;
2075 xformWnd2Vport
.eM12
= 0.0;
2076 xformWnd2Vport
.eM21
= 0.0;
2077 xformWnd2Vport
.eM22
= scaleY
;
2078 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
2079 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
2081 /* Combine with the world transformation */
2082 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2084 /* Create inverse of world-to-viewport transformation */
2085 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2089 DC_InvertXform(const XFORM
*xformSrc
,
2094 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2095 if (determinant
> -1e-12 && determinant
< 1e-12)
2100 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2101 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2102 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2103 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2104 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2105 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2111 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2115 GDIOBJ_SetOwnership(hDC
, Owner
);
2116 DC
= DC_LockDc(hDC
);
2119 if (NULL
!= DC
->w
.hClipRgn
)
2121 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hClipRgn
);
2123 if (NULL
!= DC
->w
.hVisRgn
)
2125 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hVisRgn
);
2127 if (NULL
!= DC
->w
.hGCClipRgn
)
2129 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hGCClipRgn
);
2136 IntIsPrimarySurface(PSURFGDI SurfGDI
)
2138 if (PrimarySurface
.Handle
== NULL
)
2142 return SurfGDI
== (PSURFGDI
)AccessInternalObject((ULONG
) PrimarySurface
.Handle
) ? TRUE
: FALSE
;