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 * DC.C - Device context functions
26 #ifndef OBJ_COLORSPACE
27 #define OBJ_COLORSPACE (14)
30 static GDIDEVICE PrimarySurface
;
32 /* FIXME: DCs should probably be thread safe */
35 * DC device-independent Get/SetXXX functions
36 * (RJJ) swiped from WINE
39 #define DC_GET_VAL( func_type, func_name, dc_field ) \
40 func_type STDCALL func_name( HDC hdc ) \
43 PDC dc = DC_LockDc( hdc ); \
46 SetLastWin32Error(ERROR_INVALID_HANDLE); \
54 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
55 * important that the function has the right signature, for the implementation
56 * we can do whatever we want.
58 #define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
59 VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
66 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
73 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
76 if(!(dc = DC_LockDc(hdc))) \
78 SetLastWin32Error(ERROR_INVALID_HANDLE); \
81 Int##FuncName( dc, &Safept); \
83 Status = MmCopyToCaller(pt, &Safept, sizeof( type )); \
84 if(!NT_SUCCESS(Status)) \
86 SetLastNtError(Status); \
92 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
93 INT STDCALL func_name( HDC hdc, INT mode ) \
97 if ((mode < min_val) || (mode > max_val)) \
99 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
102 dc = DC_LockDc ( hdc ); \
105 SetLastWin32Error(ERROR_INVALID_HANDLE); \
108 prevMode = dc->dc_field; \
109 dc->dc_field = mode; \
110 DC_UnlockDc ( hdc ); \
115 // --------------------------------------------------------- File Statics
117 // ----------------------------------------------------- Public Functions
120 NtGdiCancelDC(HDC hDC
)
127 NtGdiCreateCompatableDC(HDC hDC
)
131 HDC hNewDC
, DisplayDC
;
133 UNICODE_STRING DriverName
;
138 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
139 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
140 if (NULL
== DisplayDC
)
147 /* Allocate a new DC based on the original DC's device */
148 OrigDC
= DC_LockDc(hDC
);
151 if (NULL
!= DisplayDC
)
153 NtGdiDeleteDC(DisplayDC
);
157 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
162 if (NULL
!= DisplayDC
)
164 NtGdiDeleteDC(DisplayDC
);
168 NewDC
= DC_LockDc( hNewDC
);
170 /* Copy information from original DC to new DC */
171 NewDC
->hSelf
= hNewDC
;
174 NewDC
->PDev
= OrigDC
->PDev
;
175 memcpy(NewDC
->FillPatternSurfaces
,
176 OrigDC
->FillPatternSurfaces
,
177 sizeof OrigDC
->FillPatternSurfaces
);
178 NewDC
->GDIInfo
= OrigDC
->GDIInfo
;
179 NewDC
->DevInfo
= OrigDC
->DevInfo
;
180 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
182 /* DriverName is copied in the AllocDC routine */
183 NewDC
->DeviceDriver
= OrigDC
->DeviceDriver
;
184 NewDC
->wndOrgX
= OrigDC
->wndOrgX
;
185 NewDC
->wndOrgY
= OrigDC
->wndOrgY
;
186 NewDC
->wndExtX
= OrigDC
->wndExtX
;
187 NewDC
->wndExtY
= OrigDC
->wndExtY
;
188 NewDC
->vportOrgX
= OrigDC
->vportOrgX
;
189 NewDC
->vportOrgY
= OrigDC
->vportOrgY
;
190 NewDC
->vportExtX
= OrigDC
->vportExtX
;
191 NewDC
->vportExtY
= OrigDC
->vportExtY
;
193 /* Create default bitmap */
194 if (!(hBitmap
= NtGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
197 DC_UnlockDc( hNewDC
);
199 if (NULL
!= DisplayDC
)
201 NtGdiDeleteDC(DisplayDC
);
205 NewDC
->w
.flags
= DC_MEMORY
;
206 NewDC
->w
.hBitmap
= hBitmap
;
207 NewDC
->w
.hFirstBitmap
= hBitmap
;
208 NewDC
->GDIDevice
= OrigDC
->GDIDevice
;
210 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
211 NewDC
->w
.textColor
= OrigDC
->w
.textColor
;
212 NewDC
->w
.textAlign
= OrigDC
->w
.textAlign
;
213 NewDC
->w
.backgroundColor
= OrigDC
->w
.backgroundColor
;
214 NewDC
->w
.backgroundMode
= OrigDC
->w
.backgroundMode
;
215 NewDC
->w
.ROPmode
= OrigDC
->w
.ROPmode
;
217 if (NULL
!= DisplayDC
)
219 NtGdiDeleteDC(DisplayDC
);
223 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
224 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
225 NtGdiDeleteObject(hVisRgn
);
233 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
235 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
236 WCHAR DeviceNameBuffer
[20];
239 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%d", DisplayNumber
);
240 RtlInitUnicodeString(RegistryPath
, NULL
);
241 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
242 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
243 QueryTable
[0].Name
= DeviceNameBuffer
;
244 QueryTable
[0].EntryContext
= RegistryPath
;
246 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
251 if (! NT_SUCCESS(Status
))
253 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
257 DPRINT("RegistryPath %S\n", RegistryPath
->Buffer
);
263 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
265 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
266 UNICODE_STRING RegistryPath
;
269 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
271 DPRINT("GetRegistryPath failed\n");
275 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
276 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
277 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
278 QueryTable
[0].EntryContext
= DriverFileNames
;
280 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
285 RtlFreeUnicodeString(&RegistryPath
);
286 if (! NT_SUCCESS(Status
))
288 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
292 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
297 static NTSTATUS STDCALL
298 DevModeCallback(IN PWSTR ValueName
,
301 IN ULONG ValueLength
,
303 IN PVOID EntryContext
)
305 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
307 DPRINT("Found registry value for name %S: type %d, length %d\n",
308 ValueName
, ValueType
, ValueLength
);
310 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
312 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
314 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
316 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
318 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
320 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
322 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
324 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
326 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
328 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
330 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
332 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
334 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
336 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
338 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
342 return STATUS_SUCCESS
;
346 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
348 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
349 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
350 static WCHAR ControlSet
[] = L
"CONTROLSET";
351 static WCHAR Insert
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
352 UNICODE_STRING RegistryPath
;
354 PWCHAR AfterControlSet
;
356 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
359 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
361 DPRINT("GetRegistryPath failed\n");
365 Valid
= (0 == _wcsnicmp(RegistryPath
.Buffer
, RegistryMachineSystem
,
366 wcslen(RegistryMachineSystem
)));
369 AfterControlSet
= RegistryPath
.Buffer
+ wcslen(RegistryMachineSystem
);
370 if (0 == _wcsnicmp(AfterControlSet
, CurrentControlSet
, wcslen(CurrentControlSet
)))
372 AfterControlSet
+= wcslen(CurrentControlSet
);
374 else if (0 == _wcsnicmp(AfterControlSet
, ControlSet
, wcslen(ControlSet
)))
376 AfterControlSet
+= wcslen(ControlSet
);
377 while (L
'0' <= *AfterControlSet
&& L
'9' <= *AfterControlSet
)
381 Valid
= (L
'\\' == *AfterControlSet
);
392 ProfilePath
= ExAllocatePoolWithTag(PagedPool
,
393 (wcslen(RegistryPath
.Buffer
) +
394 wcslen(Insert
) + 1) * sizeof(WCHAR
),
396 if (NULL
!= ProfilePath
)
398 wcsncpy(ProfilePath
, RegistryPath
.Buffer
, AfterControlSet
- RegistryPath
.Buffer
);
399 wcscpy(ProfilePath
+ (AfterControlSet
- RegistryPath
.Buffer
), Insert
);
400 wcscat(ProfilePath
, AfterControlSet
);
402 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
403 QueryTable
[0].QueryRoutine
= DevModeCallback
;
404 QueryTable
[0].Flags
= 0;
405 QueryTable
[0].Name
= NULL
;
406 QueryTable
[0].EntryContext
= NULL
;
407 QueryTable
[0].DefaultType
= REG_NONE
;
408 QueryTable
[0].DefaultData
= NULL
;
409 QueryTable
[0].DefaultLength
= 0;
411 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
416 if (! NT_SUCCESS(Status
))
418 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
419 ProfilePath
, Status
);
424 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
425 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
426 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
427 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
428 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
430 DPRINT("Not all required devmode members are set\n");
435 ExFreePool(ProfilePath
);
444 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath
.Buffer
);
447 RtlFreeUnicodeString(&RegistryPath
);
451 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
460 PGD_ENABLEDRIVER GDEnableDriver
;
462 UNICODE_STRING DriverFileNames
;
468 for (DisplayNumber
= 0; ; DisplayNumber
++)
470 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
472 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
474 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
476 /* Open the miniport driver */
477 if (PrimarySurface
.VideoFileObject
== NULL
)
479 DPRINT1("FindMPDriver failed\n");
483 /* Retrieve DDI driver names from registry */
484 RtlInitUnicodeString(&DriverFileNames
, NULL
);
485 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
487 DPRINT1("FindDriverFileNames failed\n");
492 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
493 * scan all of them until a good one found.
495 CurrentName
= DriverFileNames
.Buffer
;
498 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
500 /* Get the DDI driver's entry point */
501 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
502 if (NULL
== GDEnableDriver
)
504 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
508 /* Call DDI driver's EnableDriver function */
509 RtlZeroMemory(&DED
, sizeof(DED
));
511 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
513 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
523 /* Skip to the next name but never get past the Unicode string */
524 while (L
'\0' != *CurrentName
&&
525 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
529 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
536 RtlFreeUnicodeString(&DriverFileNames
);
540 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
541 DPRINT1("No suitable DDI driver found\n");
545 DPRINT("Display driver %S loaded\n", CurrentName
);
547 DPRINT("Building DDI Functions\n");
549 /* Construct DDI driver function dispatch table */
550 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
552 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
553 DPRINT1("BuildDDIFunctions failed\n");
557 /* Allocate a phyical device handle from the driver */
558 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
559 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
561 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
565 PrimarySurface
.FillPatterns
,
566 sizeof(PrimarySurface
.GDIInfo
),
567 (ULONG
*) &PrimarySurface
.GDIInfo
,
568 sizeof(PrimarySurface
.DevInfo
),
569 &PrimarySurface
.DevInfo
,
572 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
573 DoDefault
= (NULL
== PrimarySurface
.PDev
);
576 DPRINT1("DrvEnablePDev with registry parameters failed\n");
586 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
587 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
588 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
592 PrimarySurface
.FillPatterns
,
593 sizeof(PrimarySurface
.GDIInfo
),
594 (ULONG
*) &PrimarySurface
.GDIInfo
,
595 sizeof(PrimarySurface
.DevInfo
),
596 &PrimarySurface
.DevInfo
,
599 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
601 if (NULL
== PrimarySurface
.PDev
)
603 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
604 DPRINT1("DrvEnablePDEV with default parameters failed\n");
605 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
610 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
612 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
613 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
615 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
617 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
618 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
621 PrimarySurface
.Pointer
.Exclude
.right
= -1;
623 DPRINT("calling completePDev\n");
625 /* Complete initialization of the physical device */
626 PrimarySurface
.DriverFunctions
.CompletePDEV(
628 (HDEV
)&PrimarySurface
);
630 DPRINT("calling DRIVER_ReferenceDriver\n");
632 DRIVER_ReferenceDriver(L
"DISPLAY");
634 PrimarySurface
.PreparedDriver
= TRUE
;
635 PrimarySurface
.DisplayNumber
= DisplayNumber
;
644 IntPrepareDriverIfNeeded()
646 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
650 IntCreatePrimarySurface()
656 if (! IntPrepareDriverIfNeeded())
661 DPRINT("calling EnableSurface\n");
662 /* Enable the drawing surface */
663 PrimarySurface
.Handle
=
664 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
665 if (NULL
== PrimarySurface
.Handle
)
667 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
668 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
669 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
670 DPRINT1("DrvEnableSurface failed\n");
674 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, TRUE
);
677 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
679 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
680 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
681 SurfSize
= SurfObj
->sizlBitmap
;
682 SurfaceRect
.left
= SurfaceRect
.top
= 0;
683 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
684 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
685 /* FIXME - why does EngEraseSurface() sometimes crash?
686 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
688 /* Put the pointer in the center of the screen */
689 GDIDEV(SurfObj
)->Pointer
.Pos
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
690 GDIDEV(SurfObj
)->Pointer
.Pos
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
692 EngUnlockSurface(SurfObj
);
693 IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
699 IntDestroyPrimarySurface()
701 DRIVER_UnreferenceDriver(L
"DISPLAY");
704 IntDetachMonitor(&PrimarySurface
);
707 * FIXME: Hide a mouse pointer there. Also because we have to prevent
708 * memory leaks with the Eng* mouse routines.
711 DPRINT("Reseting display\n" );
712 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, FALSE
);
713 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.PDev
);
714 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
715 PrimarySurface
.PreparedDriver
= FALSE
;
719 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
723 IntGdiCreateDC(PUNICODE_STRING Driver
,
724 PUNICODE_STRING Device
,
725 PUNICODE_STRING Output
,
726 CONST PDEVMODEW InitData
,
734 UNICODE_STRING StdDriver
;
736 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
738 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
742 if (! IntPrepareDriverIfNeeded())
744 DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
748 else if (! IntGraphicsCheck(TRUE
))
750 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
755 /* Check for existing DC object */
756 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
759 return NtGdiCreateCompatableDC(hDC
);
762 if (Driver
!= NULL
&& Driver
->Buffer
!= NULL
)
764 DPRINT("NAME: %wZ\n", Driver
); // FIXME: Should not crash if NULL
767 /* Allocate a DC object */
768 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
773 NewDC
= DC_LockDc( hNewDC
);
774 /* FIXME - NewDC can be NULL!!! Don't assert here! */
781 NewDC
->IsIC
= CreateAsIC
;
782 NewDC
->DevInfo
= &PrimarySurface
.DevInfo
;
783 NewDC
->GDIInfo
= &PrimarySurface
.GDIInfo
;
784 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
785 sizeof(NewDC
->FillPatternSurfaces
));
786 NewDC
->PDev
= PrimarySurface
.PDev
;
787 NewDC
->GDIDevice
= (HDEV
)&PrimarySurface
;
788 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
789 NewDC
->w
.hBitmap
= PrimarySurface
.Handle
;
791 NewDC
->w
.bitsPerPixel
= NewDC
->GDIInfo
->cBitsPixel
* NewDC
->GDIInfo
->cPlanes
;
792 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
796 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
799 DC_UnlockDc ( hNewDC
);
800 DC_FreeDC ( hNewDC
) ;
803 ASSERT(NewDC
->GDIInfo
->cBitsPixel
* NewDC
->GDIInfo
->cPlanes
== BitsPerFormat(SurfObj
->iBitmapFormat
));
804 ASSERT(NewDC
->GDIInfo
->ulHorzRes
== SurfObj
->sizlBitmap
.cx
);
805 ASSERT(NewDC
->GDIInfo
->ulVertRes
== SurfObj
->sizlBitmap
.cy
);
807 NewDC
->w
.hPalette
= NewDC
->DevInfo
->hpalDefault
;
808 NewDC
->w
.ROPmode
= R2_COPYPEN
;
810 DC_UnlockDc( hNewDC
);
812 hVisRgn
= NtGdiCreateRectRgn(0, 0, SurfObj
->sizlBitmap
.cx
,
813 SurfObj
->sizlBitmap
.cy
);
814 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
815 NtGdiDeleteObject(hVisRgn
);
817 /* Initialize the DC state */
819 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
820 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
821 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
822 NtGdiSetBkMode(hNewDC
, OPAQUE
);
824 EngUnlockSurface(SurfObj
);
828 DC_UnlockDc( hNewDC
);
835 NtGdiCreateDC(PUNICODE_STRING Driver
,
836 PUNICODE_STRING Device
,
837 PUNICODE_STRING Output
,
838 CONST PDEVMODEW InitData
)
840 UNICODE_STRING SafeDriver
, SafeDevice
;
841 DEVMODEW SafeInitData
;
847 Status
= MmCopyFromCaller(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
848 if(!NT_SUCCESS(Status
))
850 SetLastNtError(Status
);
853 /* FIXME - InitData can have some more bytes! */
858 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
859 if(!NT_SUCCESS(Status
))
861 SetLastNtError(Status
);
868 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
869 if(!NT_SUCCESS(Status
))
871 RtlFreeUnicodeString(&SafeDriver
);
872 SetLastNtError(Status
);
877 Ret
= IntGdiCreateDC(&SafeDriver
, &SafeDevice
, NULL
, &SafeInitData
, FALSE
);
883 NtGdiCreateIC(PUNICODE_STRING Driver
,
884 PUNICODE_STRING Device
,
885 PUNICODE_STRING Output
,
886 CONST PDEVMODEW InitData
)
888 UNICODE_STRING SafeDriver
, SafeDevice
;
889 DEVMODEW SafeInitData
;
895 Status
= MmCopyFromCaller(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
896 if(!NT_SUCCESS(Status
))
898 SetLastNtError(Status
);
901 /* FIXME - InitData can have some more bytes! */
906 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
907 if(!NT_SUCCESS(Status
))
909 SetLastNtError(Status
);
916 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
917 if(!NT_SUCCESS(Status
))
919 RtlFreeUnicodeString(&SafeDriver
);
920 SetLastNtError(Status
);
925 Ret
= IntGdiCreateDC(NULL
== Driver
? NULL
: &SafeDriver
,
926 NULL
== Device
? NULL
: &SafeDevice
, NULL
,
927 NULL
== InitData
? NULL
: &SafeInitData
, TRUE
);
933 NtGdiDeleteDC(HDC DCHandle
)
937 DCToDelete
= DC_LockDc(DCHandle
);
938 if (DCToDelete
== NULL
)
943 /* First delete all saved DCs */
944 while (DCToDelete
->saveLevel
)
949 savedHDC
= DC_GetNextDC (DCToDelete
);
950 savedDC
= DC_LockDc (savedHDC
);
955 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
956 DCToDelete
->saveLevel
--;
957 DC_UnlockDc( savedHDC
);
958 NtGdiDeleteDC (savedHDC
);
961 /* Free GDI resources allocated to this DC */
962 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
965 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
966 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
967 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
968 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
969 if (DCToDelete
->w
.flags
& DC_MEMORY
)
971 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
973 if (DCToDelete
->XlateBrush
!= NULL
)
974 EngDeleteXlate(DCToDelete
->XlateBrush
);
975 if (DCToDelete
->XlatePen
!= NULL
)
976 EngDeleteXlate(DCToDelete
->XlatePen
);
978 if (DCToDelete
->w
.hClipRgn
)
980 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
982 if (DCToDelete
->w
.hVisRgn
)
984 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
986 if (NULL
!= DCToDelete
->CombinedClip
)
988 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
990 if (DCToDelete
->w
.hGCClipRgn
)
992 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
995 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
997 DC_UnlockDc( DCHandle
);
998 DC_FreeDC ( DCHandle
);
1004 NtGdiDrawEscape(HDC hDC
,
1014 NtGdiEnumObjects(HDC hDC
,
1016 GOBJENUMPROC ObjectFunc
,
1023 DC_GET_VAL( COLORREF
, NtGdiGetBkColor
, w
.backgroundColor
)
1024 DC_GET_VAL( INT
, NtGdiGetBkMode
, w
.backgroundMode
)
1025 DC_GET_VAL_EX( GetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
, x
, y
)
1026 DC_GET_VAL( HRGN
, NtGdiGetClipRgn
, w
.hClipRgn
)
1029 NtGdiGetCurrentObject(HDC hDC
, UINT ObjectType
)
1034 if(!(dc
= DC_LockDc(hDC
)))
1036 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1043 SelObject
= dc
->w
.hPen
;
1046 SelObject
= dc
->w
.hBrush
;
1049 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
1053 SelObject
= dc
->w
.hFont
;
1056 SelObject
= dc
->w
.hBitmap
;
1058 case OBJ_COLORSPACE
:
1059 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1064 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1072 DC_GET_VAL_EX ( GetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
, x
, y
)
1075 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1077 Point
->x
= dc
->w
.DCOrgX
;
1078 Point
->y
= dc
->w
.DCOrgY
;
1084 NtGdiGetDCOrgEx(HDC hDC
, LPPOINT Point
)
1093 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1097 dc
= DC_LockDc(hDC
);
1100 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1104 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1106 Status
= MmCopyToCaller(Point
, &SafePoint
, sizeof(POINT
));
1107 if(!NT_SUCCESS(Status
))
1109 SetLastNtError(Status
);
1119 NtGdiSetBkColor(HDC hDC
, COLORREF color
)
1125 if (!(dc
= DC_LockDc(hDC
)))
1127 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1131 oldColor
= dc
->w
.backgroundColor
;
1132 dc
->w
.backgroundColor
= color
;
1133 hBrush
= dc
->w
.hBrush
;
1134 DC_UnlockDc ( hDC
);
1135 NtGdiSelectObject(hDC
, hBrush
);
1140 NtGdiGetDCState(HDC hDC
)
1145 dc
= DC_LockDc(hDC
);
1148 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1152 hnewdc
= DC_AllocDC(NULL
);
1158 newdc
= DC_LockDc( hnewdc
);
1159 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1162 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1163 newdc
->w
.hPen
= dc
->w
.hPen
;
1164 newdc
->w
.hBrush
= dc
->w
.hBrush
;
1165 newdc
->w
.hFont
= dc
->w
.hFont
;
1166 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1167 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1169 newdc
->w
.hDevice
= dc
->w
.hDevice
;
1171 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1172 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1173 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1174 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
1175 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
1176 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
1177 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
1178 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
1179 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
1180 newdc
->w
.textColor
= dc
->w
.textColor
;
1181 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
1182 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
1183 newdc
->w
.textAlign
= dc
->w
.textAlign
;
1184 newdc
->w
.charExtra
= dc
->w
.charExtra
;
1185 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
1186 newdc
->w
.breakCount
= dc
->w
.breakCount
;
1187 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
1188 newdc
->w
.breakRem
= dc
->w
.breakRem
;
1189 newdc
->w
.MapMode
= dc
->w
.MapMode
;
1190 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
1192 /* Apparently, the DC origin is not changed by [GS]etDCState */
1193 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1194 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1196 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
1197 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
1198 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1199 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1200 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1201 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1202 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1203 newdc
->wndOrgX
= dc
->wndOrgX
;
1204 newdc
->wndOrgY
= dc
->wndOrgY
;
1205 newdc
->wndExtX
= dc
->wndExtX
;
1206 newdc
->wndExtY
= dc
->wndExtY
;
1207 newdc
->vportOrgX
= dc
->vportOrgX
;
1208 newdc
->vportOrgY
= dc
->vportOrgY
;
1209 newdc
->vportExtX
= dc
->vportExtX
;
1210 newdc
->vportExtY
= dc
->vportExtY
;
1212 newdc
->hSelf
= hnewdc
;
1213 newdc
->saveLevel
= 0;
1214 newdc
->IsIC
= dc
->IsIC
;
1217 PATH_InitGdiPath( &newdc
->w
.path
);
1220 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1222 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1225 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1226 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1228 DC_UnlockDc( hnewdc
);
1236 NtGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1240 dc
= DC_LockDc ( hDC
);
1243 dcs
= DC_LockDc ( hDCSave
);
1246 if ( dcs
->w
.flags
& DC_SAVED
)
1248 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1250 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1253 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1256 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1257 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1258 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1259 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1260 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1261 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1262 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1263 dc
->w
.textColor
= dcs
->w
.textColor
;
1264 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1265 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1266 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1267 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1268 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1269 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1270 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1271 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1272 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1273 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1275 /* Apparently, the DC origin is not changed by [GS]etDCState */
1276 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1277 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1279 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1280 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1281 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1283 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1284 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1285 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1286 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1288 dc
->wndOrgX
= dcs
->wndOrgX
;
1289 dc
->wndOrgY
= dcs
->wndOrgY
;
1290 dc
->wndExtX
= dcs
->wndExtX
;
1291 dc
->wndExtY
= dcs
->wndExtY
;
1292 dc
->vportOrgX
= dcs
->vportOrgX
;
1293 dc
->vportOrgY
= dcs
->vportOrgY
;
1294 dc
->vportExtX
= dcs
->vportExtX
;
1295 dc
->vportExtY
= dcs
->vportExtY
;
1297 if (!(dc
->w
.flags
& DC_MEMORY
))
1299 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1303 if (dcs
->w
.hClipRgn
)
1305 if (!dc
->w
.hClipRgn
)
1307 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1309 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1315 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1322 res
= CLIPPING_UpdateGCRegion( dc
);
1323 ASSERT ( res
!= ERROR
);
1325 DC_UnlockDc ( hDC
);
1327 DC_UnlockDc ( hDC
);
1328 NtGdiSelectClipRgn(hDC
, dcs
->w
.hClipRgn
);
1331 NtGdiSelectObject( hDC
, dcs
->w
.hBitmap
);
1332 NtGdiSelectObject( hDC
, dcs
->w
.hBrush
);
1333 NtGdiSelectObject( hDC
, dcs
->w
.hFont
);
1334 NtGdiSelectObject( hDC
, dcs
->w
.hPen
);
1335 NtGdiSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1336 NtGdiSetTextColor( hDC
, dcs
->w
.textColor
);
1338 NtGdiSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1341 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1346 DC_UnlockDc ( hDCSave
);
1348 DC_UnlockDc ( hDC
);
1349 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1353 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1357 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1362 /* Retrieve capability */
1366 ret
= dc
->GDIInfo
->ulVersion
;
1370 ret
= dc
->GDIInfo
->ulTechnology
;
1374 ret
= dc
->GDIInfo
->ulHorzSize
;
1378 ret
= dc
->GDIInfo
->ulVertSize
;
1382 ret
= dc
->GDIInfo
->ulHorzRes
;
1386 ret
= dc
->GDIInfo
->ulVertRes
;
1390 ret
= dc
->GDIInfo
->ulLogPixelsX
;
1394 ret
= dc
->GDIInfo
->ulLogPixelsY
;
1398 ret
= dc
->GDIInfo
->cBitsPixel
;
1402 ret
= dc
->GDIInfo
->cPlanes
;
1406 UNIMPLEMENTED
; /* FIXME */
1410 UNIMPLEMENTED
; /* FIXME */
1414 UNIMPLEMENTED
; /* FIXME */
1418 ret
= dc
->GDIInfo
->ulNumColors
;
1422 ret
= dc
->GDIInfo
->ulAspectX
;
1426 ret
= dc
->GDIInfo
->ulAspectY
;
1430 ret
= dc
->GDIInfo
->ulAspectXY
;
1434 UNIMPLEMENTED
; /* FIXME */
1438 UNIMPLEMENTED
; /* FIXME */
1442 ret
= dc
->GDIInfo
->ulNumPalReg
; /* FIXME not sure */
1450 UNIMPLEMENTED
; /* FIXME */
1454 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1464 case PHYSICALHEIGHT
:
1465 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1475 case PHYSICALOFFSETX
:
1476 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1486 case PHYSICALOFFSETY
:
1487 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1498 UNIMPLEMENTED
; /* FIXME */
1501 case SCALINGFACTORX
:
1502 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1512 case SCALINGFACTORY
:
1513 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1524 ret
= dc
->GDIInfo
->flRaster
;
1528 UNIMPLEMENTED
; /* FIXME */
1532 UNIMPLEMENTED
; /* FIXME */
1536 UNIMPLEMENTED
; /* FIXME */
1540 ret
= dc
->GDIInfo
->flTextCaps
;
1552 NtGdiGetDeviceCaps(HDC hDC
,
1558 dc
= DC_LockDc(hDC
);
1561 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1565 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1567 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1573 DC_GET_VAL( INT
, NtGdiGetMapMode
, w
.MapMode
)
1574 DC_GET_VAL( INT
, NtGdiGetPolyFillMode
, w
.polyFillMode
)
1577 IntGdiGetObject(HANDLE Handle
, INT Count
, LPVOID Buffer
)
1583 GdiObject
= GDIOBJ_LockObj(Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1584 if (NULL
== GdiObject
)
1586 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1590 ObjectType
= GDIOBJ_GetObjectType(Handle
);
1594 case GDI_OBJECT_TYPE_PEN
:
1595 Result
= PEN_GetObject((PENOBJ
*) GdiObject
, Count
, Buffer
);
1597 case GDI_OBJECT_TYPE_BRUSH
:
1598 Result
= BRUSH_GetObject((BRUSHOBJ
*) GdiObject
, Count
, Buffer
);
1601 case GDI_OBJECT_TYPE_BITMAP
:
1602 Result
= BITMAP_GetObject((BITMAPOBJ
*) GdiObject
, Count
, Buffer
);
1604 case GDI_OBJECT_TYPE_FONT
:
1605 Result
= FontGetObject((PTEXTOBJ
) GdiObject
, Count
, Buffer
);
1607 // Fix the LOGFONT structure for the stock fonts
1608 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1610 FixStockFontSizeW(Handle
, Count
, Buffer
);
1615 case GDI_OBJECT_TYPE_PALETTE
:
1616 Result
= PALETTE_GetObject((PALETTEOBJ
*) GdiObject
, Count
, Buffer
);
1620 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType
);
1624 GDIOBJ_UnlockObj(Handle
);
1630 NtGdiGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
1641 SafeBuf
= ExAllocatePoolWithTag(PagedPool
, count
, TAG_GDIOBJ
);
1644 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1648 Ret
= IntGdiGetObject(handle
, count
, SafeBuf
);
1650 Status
= MmCopyToCaller(buffer
, SafeBuf
, count
);
1651 ExFreePool(SafeBuf
);
1652 if(!NT_SUCCESS(Status
))
1654 SetLastNtError(Status
);
1662 NtGdiGetObjectType(HANDLE handle
)
1668 ptr
= GDIOBJ_LockObj(handle
, GDI_OBJECT_TYPE_DONTCARE
);
1671 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1675 objectType
= GDIOBJ_GetObjectType(handle
);
1678 case GDI_OBJECT_TYPE_PEN
:
1681 case GDI_OBJECT_TYPE_BRUSH
:
1684 case GDI_OBJECT_TYPE_BITMAP
:
1685 result
= OBJ_BITMAP
;
1687 case GDI_OBJECT_TYPE_FONT
:
1690 case GDI_OBJECT_TYPE_PALETTE
:
1693 case GDI_OBJECT_TYPE_REGION
:
1694 result
= OBJ_REGION
;
1696 case GDI_OBJECT_TYPE_DC
:
1699 case GDI_OBJECT_TYPE_METADC
:
1700 result
= OBJ_METADC
;
1702 case GDI_OBJECT_TYPE_METAFILE
:
1703 result
= OBJ_METAFILE
;
1705 case GDI_OBJECT_TYPE_ENHMETAFILE
:
1706 result
= OBJ_ENHMETAFILE
;
1708 case GDI_OBJECT_TYPE_ENHMETADC
:
1709 result
= OBJ_ENHMETADC
;
1711 case GDI_OBJECT_TYPE_EXTPEN
:
1712 result
= OBJ_EXTPEN
;
1714 case GDI_OBJECT_TYPE_MEMDC
:
1719 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
1723 GDIOBJ_UnlockObj(handle
);
1727 DC_GET_VAL( INT
, NtGdiGetRelAbs
, w
.relAbsMode
)
1728 DC_GET_VAL( INT
, NtGdiGetROP2
, w
.ROPmode
)
1729 DC_GET_VAL( INT
, NtGdiGetStretchBltMode
, w
.stretchBltMode
)
1730 DC_GET_VAL( UINT
, NtGdiGetTextAlign
, w
.textAlign
)
1731 DC_GET_VAL( COLORREF
, NtGdiGetTextColor
, w
.textColor
)
1732 DC_GET_VAL_EX( GetViewportExtEx
, vportExtX
, vportExtY
, SIZE
, cx
, cy
)
1733 DC_GET_VAL_EX( GetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
, x
, y
)
1734 DC_GET_VAL_EX( GetWindowExtEx
, wndExtX
, wndExtY
, SIZE
, cx
, cy
)
1735 DC_GET_VAL_EX( GetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
, x
, y
)
1738 NtGdiResetDC(HDC hDC
, CONST DEVMODEW
*InitData
)
1745 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1750 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1752 dc
= DC_LockDc(hDC
);
1755 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1759 if (SaveLevel
== -1)
1760 SaveLevel
= dc
->saveLevel
;
1762 if ((SaveLevel
< 1) || (SaveLevel
> dc
->saveLevel
))
1769 while (dc
->saveLevel
>= SaveLevel
)
1771 HDC hdcs
= DC_GetNextDC (dc
);
1773 dcs
= DC_LockDc (hdcs
);
1779 DC_SetNextDC (dcs
, DC_GetNextDC (dcs
));
1780 if (--dc
->saveLevel
< SaveLevel
)
1783 DC_UnlockDc( hdcs
);
1784 NtGdiSetDCState(hDC
, hdcs
);
1786 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1788 /* FIXME: This might not be quite right, since we're
1789 * returning FALSE but still destroying the saved DC state */
1793 dc
= DC_LockDc(hDC
);
1801 DC_UnlockDc( hdcs
);
1803 NtGdiDeleteDC (hdcs
);
1810 NtGdiSaveDC(HDC hDC
)
1816 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
1818 if (!(hdcs
= NtGdiGetDCState(hDC
)))
1823 dcs
= DC_LockDc (hdcs
);
1826 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1829 dc
= DC_LockDc (hDC
);
1833 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1838 /* Copy path. The reason why path saving / restoring is in SaveDC/
1839 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1840 * functions are only in Win16 (which doesn't have paths) and that
1841 * SetDCState doesn't allow us to signal an error (which can happen
1842 * when copying paths).
1844 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
1846 NtGdiDeleteDC (hdcs
);
1851 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
1852 DC_SetNextDC (dc
, hdcs
);
1853 ret
= ++dc
->saveLevel
;
1854 DC_UnlockDc( hdcs
);
1862 NtGdiSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
1864 HGDIOBJ objOrg
= NULL
; // default to failure
1874 if(!hDC
|| !hGDIObj
) return NULL
;
1876 dc
= DC_LockDc(hDC
);
1879 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1883 objectType
= GDIOBJ_GetObjectType(hGDIObj
);
1887 case GDI_OBJECT_TYPE_PEN
:
1888 pen
= PENOBJ_LockPen((HPEN
) hGDIObj
);
1891 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1895 XlateObj
= IntGdiCreateBrushXlate(dc
, pen
, &Failed
);
1896 PENOBJ_UnlockPen(hGDIObj
);
1899 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1903 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
1904 dc
->w
.hPen
= hGDIObj
;
1905 if (dc
->XlatePen
!= NULL
)
1906 EngDeleteXlate(dc
->XlatePen
);
1907 dc
->XlatePen
= XlateObj
;
1910 case GDI_OBJECT_TYPE_BRUSH
:
1911 brush
= BRUSHOBJ_LockBrush((HPEN
) hGDIObj
);
1914 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1918 XlateObj
= IntGdiCreateBrushXlate(dc
, brush
, &Failed
);
1919 BRUSHOBJ_UnlockBrush(hGDIObj
);
1922 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1926 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
1927 dc
->w
.hBrush
= hGDIObj
;
1928 if (dc
->XlateBrush
!= NULL
)
1929 EngDeleteXlate(dc
->XlateBrush
);
1930 dc
->XlateBrush
= XlateObj
;
1933 case GDI_OBJECT_TYPE_FONT
:
1934 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hGDIObj
)))
1936 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
1937 dc
->w
.hFont
= (HFONT
) hGDIObj
;
1941 case GDI_OBJECT_TYPE_BITMAP
:
1942 // must be memory dc to select bitmap
1943 if (!(dc
->w
.flags
& DC_MEMORY
))
1948 pb
= BITMAPOBJ_LockBitmap(hGDIObj
);
1951 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1955 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
1957 /* Release the old bitmap, lock the new one and convert it to a SURF */
1958 dc
->w
.hBitmap
= hGDIObj
;
1960 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1963 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
1964 dc
->w
.hPalette
= pb
->hDIBPalette
;
1968 dc
->w
.bitsPerPixel
= BitsPerFormat(pb
->SurfObj
.iBitmapFormat
);
1969 dc
->w
.hPalette
= dc
->DevInfo
->hpalDefault
;
1972 /* Reselect brush and pen to regenerate the XLATEOBJs. */
1973 NtGdiSelectObject ( hDC
, dc
->w
.hBrush
);
1974 NtGdiSelectObject ( hDC
, dc
->w
.hPen
);
1976 DC_UnlockDc ( hDC
);
1977 hVisRgn
= NtGdiCreateRectRgn ( 0, 0, pb
->SurfObj
.sizlBitmap
.cx
, pb
->SurfObj
.sizlBitmap
.cy
);
1978 BITMAPOBJ_UnlockBitmap( hGDIObj
);
1979 NtGdiSelectVisRgn ( hDC
, hVisRgn
);
1980 NtGdiDeleteObject ( hVisRgn
);
1984 case GDI_OBJECT_TYPE_REGION
:
1987 * The return value is one of the following values:
1992 return (HGDIOBJ
) NtGdiSelectClipRgn(hDC
, (HRGN
) hGDIObj
);
2002 NtGdiSetHookFlags(HDC hDC
, WORD Flags
)
2005 DC
*dc
= DC_LockDc(hDC
);
2009 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2013 wRet
= dc
->w
.flags
& DC_DIRTY
;
2015 /* "Undocumented Windows" info is slightly confusing.
2018 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2020 if (Flags
& DCHF_INVALIDATEVISRGN
)
2022 dc
->w
.flags
|= DC_DIRTY
;
2024 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2026 dc
->w
.flags
&= ~DC_DIRTY
;
2034 DC_SET_MODE( NtGdiSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
2035 DC_SET_MODE( NtGdiSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
2036 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
2037 DC_SET_MODE( NtGdiSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
2038 DC_SET_MODE( NtGdiSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
2040 // ---------------------------------------------------- Private Interface
2043 DC_AllocDC(PUNICODE_STRING Driver
)
2051 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2056 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2059 hDC
= (HDC
) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_DC
);
2069 NewDC
= DC_LockDc(hDC
);
2070 /* FIXME - Handle NewDC == NULL! */
2074 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2075 NewDC
->DriverName
.Buffer
= Buf
;
2078 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2079 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2080 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2081 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2082 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2083 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2084 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2085 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2086 NewDC
->w
.vport2WorldValid
= TRUE
;
2087 NewDC
->w
.MapMode
= MM_TEXT
;
2088 NewDC
->wndExtX
= 1.0f
;
2089 NewDC
->wndExtY
= 1.0f
;
2090 NewDC
->vportExtX
= 1.0f
;
2091 NewDC
->vportExtY
= 1.0f
;
2092 NewDC
->w
.textColor
= 0;
2093 NewDC
->w
.backgroundColor
= 0xffffff;
2095 NewDC
->w
.hFont
= NtGdiGetStockObject(SYSTEM_FONT
);
2096 TextIntRealizeFont(NewDC
->w
.hFont
);
2098 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2106 DC_FindOpenDC(PUNICODE_STRING Driver
)
2112 * Initialize some common fields in the Device Context structure.
2115 DC_InitDC(HDC DCHandle
)
2117 // NtGdiRealizeDefaultPalette(DCHandle);
2119 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2120 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2121 //NtGdiSelectObject(DCHandle, hFont);
2126 res = CLIPPING_UpdateGCRegion(DCToInit);
2127 ASSERT ( res != ERROR );
2133 DC_FreeDC(HDC DCToFree
)
2135 if (!GDIOBJ_FreeObj(DCToFree
, GDI_OBJECT_TYPE_DC
))
2137 DPRINT("DC_FreeDC failed\n");
2142 DC_Cleanup(PVOID ObjectBody
)
2144 PDC pDC
= (PDC
)ObjectBody
;
2145 RtlFreeUnicodeString(&pDC
->DriverName
);
2150 DC_GetNextDC (PDC pDC
)
2156 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2158 pDC
->hNext
= hNextDC
;
2162 DC_UpdateXforms(PDC dc
)
2164 XFORM xformWnd2Vport
;
2165 FLOAT scaleX
, scaleY
;
2167 /* Construct a transformation to do the window-to-viewport conversion */
2168 scaleX
= (dc
->wndExtX
? (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
: 0.0f
);
2169 scaleY
= (dc
->wndExtY
? (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
: 0.0f
);
2170 xformWnd2Vport
.eM11
= scaleX
;
2171 xformWnd2Vport
.eM12
= 0.0;
2172 xformWnd2Vport
.eM21
= 0.0;
2173 xformWnd2Vport
.eM22
= scaleY
;
2174 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
2175 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
2177 /* Combine with the world transformation */
2178 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2180 /* Create inverse of world-to-viewport transformation */
2181 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2185 DC_InvertXform(const XFORM
*xformSrc
,
2190 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2191 if (determinant
> -1e-12 && determinant
< 1e-12)
2196 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2197 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2198 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2199 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2200 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2201 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2207 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2211 GDIOBJ_SetOwnership(hDC
, Owner
);
2212 DC
= DC_LockDc(hDC
);
2215 if (NULL
!= DC
->w
.hClipRgn
)
2217 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hClipRgn
);
2219 if (NULL
!= DC
->w
.hVisRgn
)
2221 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hVisRgn
);
2223 if (NULL
!= DC
->w
.hGCClipRgn
)
2225 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hGCClipRgn
);
2232 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2234 if (PrimarySurface
.Handle
== NULL
)
2238 return SurfObj
->hsurf
== PrimarySurface
.Handle
;
2242 * Returns the color of the brush or pen that is currently selected into the DC.
2243 * This function is called from GetDCBrushColor() and GetDCPenColor()
2246 IntGetDCColor(HDC hDC
, ULONG Object
)
2249 * The previous implementation was completly incorrect. It modified the
2250 * brush that was currently selected into the device context, but in fact
2251 * the DC pen/brush color should be stored directly in the device context
2252 * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
2253 * The actual color is then used when DC_BRUSH/DC_PEN object is selected
2254 * into the device context and BRUSHOBJ for drawing is composed (belongs
2255 * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
2256 * the implementation should be moved to user mode GDI32.dll when UM
2257 * mapped GDI objects will be implemented.
2260 DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
2261 return 0xFFFFFF; /* The default DC color. */
2265 * Changes the color of the brush or pen that is currently selected into the DC.
2266 * This function is called from SetDCBrushColor() and SetDCPenColor()
2269 IntSetDCColor(HDC hDC
, ULONG Object
, COLORREF Color
)
2271 /* See the comment in IntGetDCColor. */
2273 DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
2277 #define SIZEOF_DEVMODEW_300 188
2278 #define SIZEOF_DEVMODEW_400 212
2279 #define SIZEOF_DEVMODEW_500 220
2281 /*! \brief Enumerate possible display settings for the given display...
2283 * \todo Make thread safe!?
2284 * \todo Don't ignore pDeviceName
2285 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2288 IntEnumDisplaySettings(
2289 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2291 IN OUT LPDEVMODEW pDevMode
,
2294 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2295 static DWORD SizeOfCachedDevModes
= 0;
2296 PDEVMODEW CachedMode
= NULL
;
2299 ULONG DisplayNumber
= 0; /* only default display supported */
2301 DPRINT1("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2302 DPRINT1("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2303 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2304 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2305 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2307 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2311 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2313 CachedMode
= &PrimarySurface
.DMW
;
2314 ASSERT(CachedMode
->dmSize
> 0);
2316 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2318 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2319 DevMode
.dmSize
= sizeof (DevMode
);
2320 DevMode
.dmDriverExtra
= 0;
2321 if (SetupDevMode(&DevMode
, DisplayNumber
))
2322 CachedMode
= &DevMode
;
2325 SetLastWin32Error(0); /* FIXME: use error code */
2328 /* FIXME: Maybe look for the matching devmode supplied by the
2329 * driver so we can provide driver private/extra data?
2334 if (iModeNum
== 0 || CachedDevModes
== NULL
) /* query modes from drivers */
2336 BOOL PrimarySurfaceCreated
= FALSE
;
2337 UNICODE_STRING DriverFileNames
;
2339 DRVENABLEDATA DrvEnableData
;
2341 /* Retrieve DDI driver names from registry */
2342 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2343 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2345 DPRINT1("FindDriverFileNames failed\n");
2349 if (!HalQueryDisplayOwnership())
2351 IntCreatePrimarySurface();
2352 PrimarySurfaceCreated
= TRUE
;
2356 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2357 * scan all of them until a good one found.
2359 CurrentName
= DriverFileNames
.Buffer
;
2360 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2361 CurrentName
+= wcslen(CurrentName
) + 1)
2364 PGD_ENABLEDRIVER GDEnableDriver
;
2366 /* Get the DDI driver's entry point */
2367 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
2368 if (NULL
== GDEnableDriver
)
2370 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2374 /* Call DDI driver's EnableDriver function */
2375 RtlZeroMemory(&DrvEnableData
, sizeof (DrvEnableData
));
2377 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2379 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2383 CachedDevModesEnd
= CachedDevModes
;
2385 /* find DrvGetModes function */
2386 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2388 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2389 PGD_GETMODES GetModes
;
2390 INT SizeNeeded
, SizeUsed
;
2392 if (DrvFn
->iFunc
!= INDEX_DrvGetModes
)
2395 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2397 /* make sure we have enough memory to hold the modes */
2398 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2399 if (SizeNeeded
<= 0)
2401 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2405 SizeUsed
= CachedDevModesEnd
- CachedDevModes
;
2406 if (SizeOfCachedDevModes
- SizeUsed
< SizeNeeded
)
2410 SizeOfCachedDevModes
+= SizeNeeded
;
2411 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2412 if (NewBuffer
== NULL
)
2415 ExFreePool(CachedDevModes
);
2416 SizeOfCachedDevModes
= 0;
2417 CachedDevModes
= NULL
;
2418 CachedDevModesEnd
= NULL
;
2419 if (PrimarySurfaceCreated
)
2421 IntDestroyPrimarySurface();
2423 SetLastWin32Error(STATUS_NO_MEMORY
);
2426 if (CachedDevModes
!= NULL
)
2428 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2429 ExFreePool(CachedDevModes
);
2431 CachedDevModes
= NewBuffer
;
2432 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2436 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2437 SizeOfCachedDevModes
- SizeUsed
,
2439 if (SizeNeeded
<= 0)
2441 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2445 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2451 if (PrimarySurfaceCreated
)
2453 IntDestroyPrimarySurface();
2456 RtlFreeUnicodeString(&DriverFileNames
);
2459 /* return cached info */
2460 CachedMode
= CachedDevModes
;
2461 if (CachedMode
>= CachedDevModesEnd
)
2463 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2466 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2468 assert(CachedMode
->dmSize
> 0);
2469 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2471 if (CachedMode
>= CachedDevModesEnd
)
2473 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2478 ASSERT(CachedMode
!= NULL
);
2480 Size
= OldSize
= pDevMode
->dmSize
;
2481 if (Size
> CachedMode
->dmSize
)
2482 Size
= CachedMode
->dmSize
;
2483 RtlCopyMemory(pDevMode
, CachedMode
, Size
);
2484 RtlZeroMemory((PCHAR
)pDevMode
+ Size
, OldSize
- Size
);
2485 pDevMode
->dmSize
= OldSize
;
2487 Size
= OldSize
= pDevMode
->dmDriverExtra
;
2488 if (Size
> CachedMode
->dmDriverExtra
)
2489 Size
= CachedMode
->dmDriverExtra
;
2490 RtlCopyMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
,
2491 (PCHAR
)CachedMode
+ CachedMode
->dmSize
, Size
);
2492 RtlZeroMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
+ Size
, OldSize
- Size
);
2493 pDevMode
->dmDriverExtra
= OldSize
;
2499 IntChangeDisplaySettings(
2500 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2501 IN LPDEVMODEW DevMode
,
2503 IN PVOID lParam OPTIONAL
)
2505 BOOLEAN Global
= FALSE
;
2506 BOOLEAN NoReset
= FALSE
;
2507 BOOLEAN Reset
= FALSE
;
2508 BOOLEAN SetPrimary
= FALSE
;
2511 DPRINT1("display flag : %x\n",dwflags
);
2513 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2515 /* Check global, reset and noreset flags */
2516 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
2518 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
2520 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
2522 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
2524 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
2526 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
2528 if (Reset
&& NoReset
)
2529 return DISP_CHANGE_BADFLAGS
;
2533 /* Dynamically change graphics mode */
2534 DPRINT1("flag 0 UNIMPLEMENT \n");
2535 return DISP_CHANGE_FAILED
;
2538 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
2540 /* Test reslution */
2541 dwflags
&= ~CDS_TEST
;
2542 DPRINT1("flag CDS_TEST UNIMPLEMENT");
2543 Ret
= DISP_CHANGE_FAILED
;
2546 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
2549 dwflags
&= ~CDS_FULLSCREEN
;
2550 DPRINT1("flag CDS_FULLSCREEN UNIMPLEMENT");
2551 Ret
= DISP_CHANGE_FAILED
;
2554 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
2556 dwflags
&= ~CDS_VIDEOPARAMETERS
;
2557 if (lParam
== NULL
) Ret
=DISP_CHANGE_BADPARAM
;
2560 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
2561 Ret
= DISP_CHANGE_FAILED
;
2566 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2569 UNICODE_STRING ObjectName
;
2570 UNICODE_STRING KernelModeName
;
2571 WCHAR KernelModeNameBuffer
[256];
2572 UNICODE_STRING RegistryKey
;
2573 WCHAR RegistryKeyBuffer
[512];
2574 PDEVICE_OBJECT DeviceObject
;
2577 OBJECT_ATTRIBUTES ObjectAttributes
;
2578 HANDLE DevInstRegKey
;
2582 DPRINT1("set CDS_UPDATEREGISTRY \n");
2584 dwflags
&= ~CDS_UPDATEREGISTRY
;
2586 /* Get device name (pDeviceName is "\.\xxx") */
2587 for (LastSlash
= pDeviceName
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
2589 if (pDeviceName
->Buffer
[LastSlash
- 1] == L
'\\')
2593 if (LastSlash
== 0) return DISP_CHANGE_RESTART
;
2594 ObjectName
= *pDeviceName
;
2595 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
2596 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
2597 ObjectName
.Buffer
+= LastSlash
;
2599 KernelModeName
.Length
= 0;
2600 KernelModeName
.MaximumLength
= sizeof(KernelModeNameBuffer
);
2601 KernelModeName
.Buffer
= KernelModeNameBuffer
;
2603 /* Open \??\xxx (ex: "\??\DISPLAY1") */
2604 Status
= RtlAppendUnicodeToString(&KernelModeName
, L
"\\??\\");
2606 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2607 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
2609 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2610 Status
= ObReferenceObjectByName(
2612 OBJ_CASE_INSENSITIVE
,
2618 (PVOID
*)&DeviceObject
);
2620 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2621 /* Get associated driver name (ex: "VBE") */
2622 for (LastSlash
= DeviceObject
->DriverObject
->DriverName
.Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
2624 if (DeviceObject
->DriverObject
->DriverName
.Buffer
[LastSlash
- 1] == L
'\\')
2628 if (LastSlash
== 0) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2629 ObjectName
= DeviceObject
->DriverObject
->DriverName
;
2630 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
2631 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
2632 ObjectName
.Buffer
+= LastSlash
;
2634 RegistryKey
.Length
= 0;
2635 RegistryKey
.MaximumLength
= sizeof(RegistryKeyBuffer
);
2636 RegistryKey
.Buffer
= RegistryKeyBuffer
;
2638 /* Open registry key */
2639 Status
= RtlAppendUnicodeToString(&RegistryKey
,
2640 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
2642 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2643 Status
= RtlAppendUnicodeStringToString(&RegistryKey
, &ObjectName
);
2645 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2646 Status
= RtlAppendUnicodeToString(&RegistryKey
,
2649 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2651 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
2652 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2653 Status
= ZwOpenKey(&DevInstRegKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
);
2654 ObDereferenceObject(DeviceObject
);
2655 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2657 /* Update needed fields */
2658 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
2660 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
2661 NewValue
= DevMode
->dmBitsPerPel
;
2662 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2665 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
2667 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
2668 NewValue
= DevMode
->dmPelsWidth
;
2669 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2672 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
2674 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
2675 NewValue
= DevMode
->dmPelsHeight
;
2676 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2679 ZwClose(DevInstRegKey
);
2680 if (NT_SUCCESS(Status
))
2681 Ret
= DISP_CHANGE_RESTART
;
2683 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only vaild for NT */
2684 Ret
= DISP_CHANGE_NOTUPDATED
;
2689 Ret
= DISP_CHANGE_BADFLAGS
;