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.155 2004/12/24 17:45:59 weiden Exp $
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
);
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
;
173 NewDC
->PDev
= OrigDC
->PDev
;
174 NewDC
->DMW
= OrigDC
->DMW
;
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
;
216 if (NULL
!= DisplayDC
)
218 NtGdiDeleteDC(DisplayDC
);
222 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
223 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
224 NtGdiDeleteObject(hVisRgn
);
232 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
234 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
235 WCHAR DeviceNameBuffer
[20];
238 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%d", DisplayNumber
);
239 RtlInitUnicodeString(RegistryPath
, NULL
);
240 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
241 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
242 QueryTable
[0].Name
= DeviceNameBuffer
;
243 QueryTable
[0].EntryContext
= RegistryPath
;
245 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
250 if (! NT_SUCCESS(Status
))
252 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
256 DPRINT("RegistryPath %S\n", RegistryPath
->Buffer
);
262 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
264 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
265 UNICODE_STRING RegistryPath
;
268 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
270 DPRINT("GetRegistryPath failed\n");
274 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
275 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
276 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
277 QueryTable
[0].EntryContext
= DriverFileNames
;
279 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
284 RtlFreeUnicodeString(&RegistryPath
);
285 if (! NT_SUCCESS(Status
))
287 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
291 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
296 static NTSTATUS STDCALL
297 DevModeCallback(IN PWSTR ValueName
,
300 IN ULONG ValueLength
,
302 IN PVOID EntryContext
)
304 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
306 DPRINT("Found registry value for name %S: type %d, length %d\n",
307 ValueName
, ValueType
, ValueLength
);
309 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
311 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
313 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
315 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
317 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
319 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
321 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
323 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
325 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
327 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
329 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
331 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
333 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
335 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
337 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
341 return STATUS_SUCCESS
;
345 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
347 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
348 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
349 static WCHAR ControlSet
[] = L
"CONTROLSET";
350 static WCHAR Insert
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
351 UNICODE_STRING RegistryPath
;
353 PWCHAR AfterControlSet
;
355 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
358 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
360 DPRINT("GetRegistryPath failed\n");
364 Valid
= (0 == _wcsnicmp(RegistryPath
.Buffer
, RegistryMachineSystem
,
365 wcslen(RegistryMachineSystem
)));
368 AfterControlSet
= RegistryPath
.Buffer
+ wcslen(RegistryMachineSystem
);
369 if (0 == _wcsnicmp(AfterControlSet
, CurrentControlSet
, wcslen(CurrentControlSet
)))
371 AfterControlSet
+= wcslen(CurrentControlSet
);
373 else if (0 == _wcsnicmp(AfterControlSet
, ControlSet
, wcslen(ControlSet
)))
375 AfterControlSet
+= wcslen(ControlSet
);
376 while (L
'0' <= *AfterControlSet
&& L
'9' <= *AfterControlSet
)
380 Valid
= (L
'\\' == *AfterControlSet
);
391 ProfilePath
= ExAllocatePoolWithTag(PagedPool
,
392 (wcslen(RegistryPath
.Buffer
) +
393 wcslen(Insert
) + 1) * sizeof(WCHAR
),
395 if (NULL
!= ProfilePath
)
397 wcsncpy(ProfilePath
, RegistryPath
.Buffer
, AfterControlSet
- RegistryPath
.Buffer
);
398 wcscpy(ProfilePath
+ (AfterControlSet
- RegistryPath
.Buffer
), Insert
);
399 wcscat(ProfilePath
, AfterControlSet
);
401 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
402 QueryTable
[0].QueryRoutine
= DevModeCallback
;
403 QueryTable
[0].Flags
= 0;
404 QueryTable
[0].Name
= NULL
;
405 QueryTable
[0].EntryContext
= NULL
;
406 QueryTable
[0].DefaultType
= REG_NONE
;
407 QueryTable
[0].DefaultData
= NULL
;
408 QueryTable
[0].DefaultLength
= 0;
410 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
415 if (! NT_SUCCESS(Status
))
417 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
418 ProfilePath
, Status
);
423 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
424 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
425 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
426 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
427 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
429 DPRINT("Not all required devmode members are set\n");
434 ExFreePool(ProfilePath
);
443 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath
.Buffer
);
446 RtlFreeUnicodeString(&RegistryPath
);
450 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
457 IntCreatePrimarySurface()
459 PGD_ENABLEDRIVER GDEnableDriver
;
463 UNICODE_STRING DriverFileNames
;
470 for (DisplayNumber
= 0; ; DisplayNumber
++)
472 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
474 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
476 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
478 /* Open the miniport driver */
479 if (PrimarySurface
.VideoFileObject
== NULL
)
481 DPRINT1("FindMPDriver failed\n");
485 /* Retrieve DDI driver names from registry */
486 RtlInitUnicodeString(&DriverFileNames
, NULL
);
487 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
489 DPRINT1("FindDriverFileNames failed\n");
495 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
496 * scan all of them until a good one found.
498 CurrentName
= DriverFileNames
.Buffer
;
501 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
503 /* Get the DDI driver's entry point */
504 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
505 if (NULL
== GDEnableDriver
)
507 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
511 /* Call DDI driver's EnableDriver function */
512 RtlZeroMemory(&DED
, sizeof(DED
));
514 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
516 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
526 /* Skip to the next name but never get past the Unicode string */
527 while (L
'\0' != *CurrentName
&&
528 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
532 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
539 RtlFreeUnicodeString(&DriverFileNames
);
543 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
544 DPRINT1("No suitable DDI driver found\n");
549 DPRINT("Display driver %S loaded\n", CurrentName
);
551 DPRINT("Building DDI Functions\n");
553 /* Construct DDI driver function dispatch table */
554 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
556 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
557 DPRINT1("BuildDDIFunctions failed\n");
561 /* Allocate a phyical device handle from the driver */
562 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
563 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
565 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
569 PrimarySurface
.FillPatterns
,
570 sizeof(PrimarySurface
.GDIInfo
),
571 (ULONG
*) &PrimarySurface
.GDIInfo
,
572 sizeof(PrimarySurface
.DevInfo
),
573 &PrimarySurface
.DevInfo
,
576 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
577 DoDefault
= (NULL
== PrimarySurface
.PDev
);
580 DPRINT1("DrvEnablePDev with registry parameters failed\n");
590 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
591 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
592 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
596 PrimarySurface
.FillPatterns
,
597 sizeof(PrimarySurface
.GDIInfo
),
598 (ULONG
*) &PrimarySurface
.GDIInfo
,
599 sizeof(PrimarySurface
.DevInfo
),
600 &PrimarySurface
.DevInfo
,
603 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
605 if (NULL
== PrimarySurface
.PDev
)
607 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
608 DPRINT1("DrvEnablePDEV with default parameters failed\n");
609 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
615 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
617 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
618 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
620 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
622 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
623 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
626 PrimarySurface
.Pointer
.Exclude
.right
= -1;
628 DPRINT("calling completePDev\n");
630 /* Complete initialization of the physical device */
631 PrimarySurface
.DriverFunctions
.CompletePDEV(
633 (HDEV
)&PrimarySurface
);
635 DPRINT("calling DRIVER_ReferenceDriver\n");
637 DRIVER_ReferenceDriver(L
"DISPLAY");
639 DPRINT("calling EnableSurface\n");
641 /* Enable the drawing surface */
642 PrimarySurface
.Handle
=
643 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
644 if (NULL
== PrimarySurface
.Handle
)
646 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
647 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
648 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
649 DPRINT1("DrvEnableSurface failed\n");
655 IntAttachMonitor(&PrimarySurface
, DisplayNumber
);
657 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
658 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
659 SurfSize
= SurfObj
->sizlBitmap
;
660 SurfSize
= SurfObj
->sizlBitmap
;
661 SurfaceRect
.left
= SurfaceRect
.top
= 0;
662 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
663 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
664 /* FIXME - why does EngEraseSurface() sometimes crash?
665 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
666 EngUnlockSurface(SurfObj
);
667 IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
675 IntDestroyPrimarySurface()
677 DRIVER_UnreferenceDriver(L
"DISPLAY");
680 IntDetachMonitor(&PrimarySurface
);
683 * FIXME: Hide a mouse pointer there. Also because we have to prevent
684 * memory leaks with the Eng* mouse routines.
687 DPRINT("Reseting display\n" );
688 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, FALSE
);
689 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.PDev
);
690 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
694 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
698 IntGdiCreateDC(PUNICODE_STRING Driver
,
699 PUNICODE_STRING Device
,
700 PUNICODE_STRING Output
,
701 CONST PDEVMODEW InitData
)
708 UNICODE_STRING StdDriver
;
710 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
712 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
714 if (! IntGraphicsCheck(TRUE
))
716 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
721 /* Check for existing DC object */
722 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
725 return NtGdiCreateCompatableDC(hDC
);
728 if (Driver
!= NULL
&& Driver
->Buffer
!= NULL
)
730 DPRINT("NAME: %S\n", Driver
->Buffer
); // FIXME: Should not crash if NULL
733 /* Allocate a DC object */
734 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
739 NewDC
= DC_LockDc( hNewDC
);
740 /* FIXME - NewDC can be NULL!!! Don't assert here! */
747 NewDC
->DMW
= PrimarySurface
.DMW
;
748 NewDC
->DevInfo
= &PrimarySurface
.DevInfo
;
749 NewDC
->GDIInfo
= &PrimarySurface
.GDIInfo
;
750 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
751 sizeof(NewDC
->FillPatternSurfaces
));
752 NewDC
->PDev
= PrimarySurface
.PDev
;
753 NewDC
->GDIDevice
= (HDEV
)&PrimarySurface
;
754 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
755 NewDC
->w
.hBitmap
= PrimarySurface
.Handle
;
757 NewDC
->DMW
.dmSize
= sizeof(NewDC
->DMW
);
758 NewDC
->DMW
.dmFields
= 0x000fc000;
760 /* FIXME: get mode selection information from somewhere */
762 NewDC
->DMW
.dmLogPixels
= 96;
763 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
766 DC_UnlockDc ( hNewDC
);
767 DC_FreeDC ( hNewDC
) ;
770 NewDC
->DMW
.dmBitsPerPel
= BitsPerFormat(SurfObj
->iBitmapFormat
);
771 NewDC
->DMW
.dmPelsWidth
= SurfObj
->sizlBitmap
.cx
;
772 NewDC
->DMW
.dmPelsHeight
= SurfObj
->sizlBitmap
.cy
;
773 NewDC
->DMW
.dmDisplayFlags
= 0;
774 NewDC
->DMW
.dmDisplayFrequency
= 0;
776 NewDC
->w
.bitsPerPixel
= NewDC
->DMW
.dmBitsPerPel
; // FIXME: set this here??
778 NewDC
->w
.hPalette
= NewDC
->DevInfo
->hpalDefault
;
780 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
782 DC_UnlockDc( hNewDC
);
784 hVisRgn
= NtGdiCreateRectRgn(0, 0, SurfObj
->sizlBitmap
.cx
,
785 SurfObj
->sizlBitmap
.cy
);
786 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
787 NtGdiDeleteObject(hVisRgn
);
789 /* Initialize the DC state */
791 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
792 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
793 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
794 NtGdiSetBkMode(hNewDC
, OPAQUE
);
796 EngUnlockSurface(SurfObj
);
802 NtGdiCreateDC(PUNICODE_STRING Driver
,
803 PUNICODE_STRING Device
,
804 PUNICODE_STRING Output
,
805 CONST PDEVMODEW InitData
)
807 UNICODE_STRING SafeDriver
, SafeDevice
;
808 DEVMODEW SafeInitData
;
814 Status
= MmCopyFromCaller(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
815 if(!NT_SUCCESS(Status
))
817 SetLastNtError(Status
);
820 /* FIXME - InitData can have some more bytes! */
825 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
826 if(!NT_SUCCESS(Status
))
828 SetLastNtError(Status
);
835 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
836 if(!NT_SUCCESS(Status
))
838 RtlFreeUnicodeString(&SafeDriver
);
839 SetLastNtError(Status
);
844 Ret
= IntGdiCreateDC(&SafeDriver
, &SafeDevice
, NULL
, &SafeInitData
);
850 NtGdiCreateIC(PUNICODE_STRING Driver
,
851 PUNICODE_STRING Device
,
852 PUNICODE_STRING Output
,
853 CONST PDEVMODEW DevMode
)
855 /* FIXME: this should probably do something else... */
856 return NtGdiCreateDC(Driver
, Device
, Output
, DevMode
);
860 NtGdiDeleteDC(HDC DCHandle
)
864 DCToDelete
= DC_LockDc(DCHandle
);
865 if (DCToDelete
== NULL
)
870 /* First delete all saved DCs */
871 while (DCToDelete
->saveLevel
)
876 savedHDC
= DC_GetNextDC (DCToDelete
);
877 savedDC
= DC_LockDc (savedHDC
);
882 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
883 DCToDelete
->saveLevel
--;
884 DC_UnlockDc( savedHDC
);
885 NtGdiDeleteDC (savedHDC
);
888 /* Free GDI resources allocated to this DC */
889 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
892 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
893 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
894 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
895 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
896 if (DCToDelete
->w
.flags
& DC_MEMORY
)
898 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
900 if (DCToDelete
->XlateBrush
!= NULL
)
901 EngDeleteXlate(DCToDelete
->XlateBrush
);
902 if (DCToDelete
->XlatePen
!= NULL
)
903 EngDeleteXlate(DCToDelete
->XlatePen
);
905 if (DCToDelete
->w
.hClipRgn
)
907 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
909 if (DCToDelete
->w
.hVisRgn
)
911 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
913 if (NULL
!= DCToDelete
->CombinedClip
)
915 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
917 if (DCToDelete
->w
.hGCClipRgn
)
919 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
922 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
924 DC_UnlockDc( DCHandle
);
925 DC_FreeDC ( DCHandle
);
931 NtGdiDrawEscape(HDC hDC
,
941 NtGdiEnumObjects(HDC hDC
,
943 GOBJENUMPROC ObjectFunc
,
950 DC_GET_VAL( COLORREF
, NtGdiGetBkColor
, w
.backgroundColor
)
951 DC_GET_VAL( INT
, NtGdiGetBkMode
, w
.backgroundMode
)
952 DC_GET_VAL_EX( GetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
, x
, y
)
953 DC_GET_VAL( HRGN
, NtGdiGetClipRgn
, w
.hClipRgn
)
956 NtGdiGetCurrentObject(HDC hDC
, UINT ObjectType
)
961 if(!(dc
= DC_LockDc(hDC
)))
963 SetLastWin32Error(ERROR_INVALID_HANDLE
);
970 SelObject
= dc
->w
.hPen
;
973 SelObject
= dc
->w
.hBrush
;
976 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
980 SelObject
= dc
->w
.hFont
;
983 SelObject
= dc
->w
.hBitmap
;
986 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
991 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
999 DC_GET_VAL_EX ( GetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
, x
, y
)
1002 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1004 Point
->x
= dc
->w
.DCOrgX
;
1005 Point
->y
= dc
->w
.DCOrgY
;
1011 NtGdiGetDCOrgEx(HDC hDC
, LPPOINT Point
)
1020 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1024 dc
= DC_LockDc(hDC
);
1027 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1031 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1033 Status
= MmCopyToCaller(Point
, &SafePoint
, sizeof(POINT
));
1034 if(!NT_SUCCESS(Status
))
1036 SetLastNtError(Status
);
1046 NtGdiSetBkColor(HDC hDC
, COLORREF color
)
1052 if (!(dc
= DC_LockDc(hDC
)))
1054 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1058 oldColor
= dc
->w
.backgroundColor
;
1059 dc
->w
.backgroundColor
= color
;
1060 hBrush
= dc
->w
.hBrush
;
1061 DC_UnlockDc ( hDC
);
1062 NtGdiSelectObject(hDC
, hBrush
);
1067 NtGdiGetDCState(HDC hDC
)
1072 dc
= DC_LockDc(hDC
);
1075 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1079 hnewdc
= DC_AllocDC(NULL
);
1085 newdc
= DC_LockDc( hnewdc
);
1086 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1089 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1090 newdc
->w
.hPen
= dc
->w
.hPen
;
1091 newdc
->w
.hBrush
= dc
->w
.hBrush
;
1092 newdc
->w
.hFont
= dc
->w
.hFont
;
1093 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1094 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1096 newdc
->w
.hDevice
= dc
->w
.hDevice
;
1098 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1099 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1100 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1101 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
1102 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
1103 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
1104 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
1105 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
1106 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
1107 newdc
->w
.textColor
= dc
->w
.textColor
;
1108 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
1109 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
1110 newdc
->w
.textAlign
= dc
->w
.textAlign
;
1111 newdc
->w
.charExtra
= dc
->w
.charExtra
;
1112 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
1113 newdc
->w
.breakCount
= dc
->w
.breakCount
;
1114 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
1115 newdc
->w
.breakRem
= dc
->w
.breakRem
;
1116 newdc
->w
.MapMode
= dc
->w
.MapMode
;
1117 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
1119 /* Apparently, the DC origin is not changed by [GS]etDCState */
1120 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1121 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1123 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
1124 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
1125 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1126 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1127 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1128 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1129 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1130 newdc
->wndOrgX
= dc
->wndOrgX
;
1131 newdc
->wndOrgY
= dc
->wndOrgY
;
1132 newdc
->wndExtX
= dc
->wndExtX
;
1133 newdc
->wndExtY
= dc
->wndExtY
;
1134 newdc
->vportOrgX
= dc
->vportOrgX
;
1135 newdc
->vportOrgY
= dc
->vportOrgY
;
1136 newdc
->vportExtX
= dc
->vportExtX
;
1137 newdc
->vportExtY
= dc
->vportExtY
;
1139 newdc
->hSelf
= hnewdc
;
1140 newdc
->saveLevel
= 0;
1143 PATH_InitGdiPath( &newdc
->w
.path
);
1146 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1148 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1151 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1152 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1154 DC_UnlockDc( hnewdc
);
1162 NtGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1166 dc
= DC_LockDc ( hDC
);
1169 dcs
= DC_LockDc ( hDCSave
);
1172 if ( dcs
->w
.flags
& DC_SAVED
)
1174 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1176 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1179 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1182 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1183 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1184 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1185 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1186 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1187 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1188 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1189 dc
->w
.textColor
= dcs
->w
.textColor
;
1190 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1191 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1192 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1193 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1194 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1195 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1196 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1197 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1198 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1199 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1201 /* Apparently, the DC origin is not changed by [GS]etDCState */
1202 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1203 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1205 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1206 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1207 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1209 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1210 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1211 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1212 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1214 dc
->wndOrgX
= dcs
->wndOrgX
;
1215 dc
->wndOrgY
= dcs
->wndOrgY
;
1216 dc
->wndExtX
= dcs
->wndExtX
;
1217 dc
->wndExtY
= dcs
->wndExtY
;
1218 dc
->vportOrgX
= dcs
->vportOrgX
;
1219 dc
->vportOrgY
= dcs
->vportOrgY
;
1220 dc
->vportExtX
= dcs
->vportExtX
;
1221 dc
->vportExtY
= dcs
->vportExtY
;
1223 if (!(dc
->w
.flags
& DC_MEMORY
))
1225 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1229 if (dcs
->w
.hClipRgn
)
1231 if (!dc
->w
.hClipRgn
)
1233 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1235 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1241 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1248 res
= CLIPPING_UpdateGCRegion( dc
);
1249 ASSERT ( res
!= ERROR
);
1251 DC_UnlockDc ( hDC
);
1253 DC_UnlockDc ( hDC
);
1254 NtGdiSelectClipRgn(hDC
, dcs
->w
.hClipRgn
);
1257 NtGdiSelectObject( hDC
, dcs
->w
.hBitmap
);
1258 NtGdiSelectObject( hDC
, dcs
->w
.hBrush
);
1259 NtGdiSelectObject( hDC
, dcs
->w
.hFont
);
1260 NtGdiSelectObject( hDC
, dcs
->w
.hPen
);
1261 NtGdiSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1262 NtGdiSetTextColor( hDC
, dcs
->w
.textColor
);
1264 NtGdiSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1267 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1272 DC_UnlockDc ( hDCSave
);
1274 DC_UnlockDc ( hDC
);
1275 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1279 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1283 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1288 /* Retrieve capability */
1292 ret
= dc
->GDIInfo
->ulVersion
;
1296 ret
= dc
->GDIInfo
->ulTechnology
;
1300 ret
= dc
->GDIInfo
->ulHorzSize
;
1304 ret
= dc
->GDIInfo
->ulVertSize
;
1308 ret
= dc
->GDIInfo
->ulHorzRes
;
1312 ret
= dc
->GDIInfo
->ulVertRes
;
1316 ret
= dc
->GDIInfo
->ulLogPixelsX
;
1320 ret
= dc
->GDIInfo
->ulLogPixelsY
;
1324 ret
= dc
->GDIInfo
->cBitsPixel
;
1328 ret
= dc
->GDIInfo
->cPlanes
;
1332 UNIMPLEMENTED
; /* FIXME */
1336 UNIMPLEMENTED
; /* FIXME */
1340 UNIMPLEMENTED
; /* FIXME */
1344 ret
= dc
->GDIInfo
->ulNumColors
;
1348 ret
= dc
->GDIInfo
->ulAspectX
;
1352 ret
= dc
->GDIInfo
->ulAspectY
;
1356 ret
= dc
->GDIInfo
->ulAspectXY
;
1360 UNIMPLEMENTED
; /* FIXME */
1364 UNIMPLEMENTED
; /* FIXME */
1368 ret
= dc
->GDIInfo
->ulNumPalReg
; /* FIXME not sure */
1376 UNIMPLEMENTED
; /* FIXME */
1380 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1390 case PHYSICALHEIGHT
:
1391 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1401 case PHYSICALOFFSETX
:
1402 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1412 case PHYSICALOFFSETY
:
1413 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1424 UNIMPLEMENTED
; /* FIXME */
1427 case SCALINGFACTORX
:
1428 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1438 case SCALINGFACTORY
:
1439 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1450 ret
= dc
->GDIInfo
->flRaster
;
1454 UNIMPLEMENTED
; /* FIXME */
1458 UNIMPLEMENTED
; /* FIXME */
1462 UNIMPLEMENTED
; /* FIXME */
1466 ret
= dc
->GDIInfo
->flTextCaps
;
1478 NtGdiGetDeviceCaps(HDC hDC
,
1484 dc
= DC_LockDc(hDC
);
1487 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1491 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1493 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1499 DC_GET_VAL( INT
, NtGdiGetMapMode
, w
.MapMode
)
1500 DC_GET_VAL( INT
, NtGdiGetPolyFillMode
, w
.polyFillMode
)
1503 IntGdiGetObject(HANDLE Handle
, INT Count
, LPVOID Buffer
)
1509 GdiObject
= GDIOBJ_LockObj(Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1510 if (NULL
== GdiObject
)
1512 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1516 ObjectType
= GDIOBJ_GetObjectType(Handle
);
1520 case GDI_OBJECT_TYPE_PEN
:
1521 Result
= PEN_GetObject((PENOBJ
*) GdiObject
, Count
, Buffer
);
1523 case GDI_OBJECT_TYPE_BRUSH
:
1524 Result
= BRUSH_GetObject((BRUSHOBJ
*) GdiObject
, Count
, Buffer
);
1527 case GDI_OBJECT_TYPE_BITMAP
:
1528 Result
= BITMAP_GetObject((BITMAPOBJ
*) GdiObject
, Count
, Buffer
);
1530 case GDI_OBJECT_TYPE_FONT
:
1531 Result
= FontGetObject((PTEXTOBJ
) GdiObject
, Count
, Buffer
);
1533 // Fix the LOGFONT structure for the stock fonts
1534 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1536 FixStockFontSizeW(Handle
, Count
, Buffer
);
1541 case GDI_OBJECT_TYPE_PALETTE
:
1542 Result
= PALETTE_GetObject((PALETTEOBJ
*) GdiObject
, Count
, Buffer
);
1546 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType
);
1550 GDIOBJ_UnlockObj(Handle
);
1556 NtGdiGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
1567 SafeBuf
= ExAllocatePoolWithTag(PagedPool
, count
, TAG_GDIOBJ
);
1570 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1574 Ret
= IntGdiGetObject(handle
, count
, SafeBuf
);
1576 Status
= MmCopyToCaller(buffer
, SafeBuf
, count
);
1577 ExFreePool(SafeBuf
);
1578 if(!NT_SUCCESS(Status
))
1580 SetLastNtError(Status
);
1588 NtGdiGetObjectType(HANDLE handle
)
1594 ptr
= GDIOBJ_LockObj(handle
, GDI_OBJECT_TYPE_DONTCARE
);
1597 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1601 objectType
= GDIOBJ_GetObjectType(handle
);
1604 case GDI_OBJECT_TYPE_PEN
:
1607 case GDI_OBJECT_TYPE_BRUSH
:
1610 case GDI_OBJECT_TYPE_BITMAP
:
1611 result
= OBJ_BITMAP
;
1613 case GDI_OBJECT_TYPE_FONT
:
1616 case GDI_OBJECT_TYPE_PALETTE
:
1619 case GDI_OBJECT_TYPE_REGION
:
1620 result
= OBJ_REGION
;
1622 case GDI_OBJECT_TYPE_DC
:
1625 case GDI_OBJECT_TYPE_METADC
:
1626 result
= OBJ_METADC
;
1628 case GDI_OBJECT_TYPE_METAFILE
:
1629 result
= OBJ_METAFILE
;
1631 case GDI_OBJECT_TYPE_ENHMETAFILE
:
1632 result
= OBJ_ENHMETAFILE
;
1634 case GDI_OBJECT_TYPE_ENHMETADC
:
1635 result
= OBJ_ENHMETADC
;
1637 case GDI_OBJECT_TYPE_EXTPEN
:
1638 result
= OBJ_EXTPEN
;
1640 case GDI_OBJECT_TYPE_MEMDC
:
1645 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
1649 GDIOBJ_UnlockObj(handle
);
1653 DC_GET_VAL( INT
, NtGdiGetRelAbs
, w
.relAbsMode
)
1654 DC_GET_VAL( INT
, NtGdiGetROP2
, w
.ROPmode
)
1655 DC_GET_VAL( INT
, NtGdiGetStretchBltMode
, w
.stretchBltMode
)
1656 DC_GET_VAL( UINT
, NtGdiGetTextAlign
, w
.textAlign
)
1657 DC_GET_VAL( COLORREF
, NtGdiGetTextColor
, w
.textColor
)
1658 DC_GET_VAL_EX( GetViewportExtEx
, vportExtX
, vportExtY
, SIZE
, cx
, cy
)
1659 DC_GET_VAL_EX( GetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
, x
, y
)
1660 DC_GET_VAL_EX( GetWindowExtEx
, wndExtX
, wndExtY
, SIZE
, cx
, cy
)
1661 DC_GET_VAL_EX( GetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
, x
, y
)
1664 NtGdiResetDC(HDC hDC
, CONST DEVMODEW
*InitData
)
1671 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1676 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1678 dc
= DC_LockDc(hDC
);
1681 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1685 if (SaveLevel
== -1)
1686 SaveLevel
= dc
->saveLevel
;
1688 if ((SaveLevel
< 1) || (SaveLevel
> dc
->saveLevel
))
1695 while (dc
->saveLevel
>= SaveLevel
)
1697 HDC hdcs
= DC_GetNextDC (dc
);
1699 dcs
= DC_LockDc (hdcs
);
1705 DC_SetNextDC (dcs
, DC_GetNextDC (dcs
));
1706 if (--dc
->saveLevel
< SaveLevel
)
1709 DC_UnlockDc( hdcs
);
1710 NtGdiSetDCState(hDC
, hdcs
);
1712 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1714 /* FIXME: This might not be quite right, since we're
1715 * returning FALSE but still destroying the saved DC state */
1719 dc
= DC_LockDc(hDC
);
1727 DC_UnlockDc( hdcs
);
1729 NtGdiDeleteDC (hdcs
);
1736 NtGdiSaveDC(HDC hDC
)
1742 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
1744 if (!(hdcs
= NtGdiGetDCState(hDC
)))
1749 dcs
= DC_LockDc (hdcs
);
1752 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1755 dc
= DC_LockDc (hDC
);
1759 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1764 /* Copy path. The reason why path saving / restoring is in SaveDC/
1765 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1766 * functions are only in Win16 (which doesn't have paths) and that
1767 * SetDCState doesn't allow us to signal an error (which can happen
1768 * when copying paths).
1770 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
1772 NtGdiDeleteDC (hdcs
);
1777 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
1778 DC_SetNextDC (dc
, hdcs
);
1779 ret
= ++dc
->saveLevel
;
1780 DC_UnlockDc( hdcs
);
1788 NtGdiSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
1790 HGDIOBJ objOrg
= NULL
; // default to failure
1797 ULONG NumColors
= 0;
1801 if(!hDC
|| !hGDIObj
) return NULL
;
1803 dc
= DC_LockDc(hDC
);
1806 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1810 objectType
= GDIOBJ_GetObjectType(hGDIObj
);
1814 case GDI_OBJECT_TYPE_PEN
:
1815 pen
= PENOBJ_LockPen((HPEN
) hGDIObj
);
1818 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1822 XlateObj
= IntGdiCreateBrushXlate(dc
, pen
, &Failed
);
1823 PENOBJ_UnlockPen(hGDIObj
);
1826 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1830 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
1831 dc
->w
.hPen
= hGDIObj
;
1832 if (dc
->XlatePen
!= NULL
)
1833 EngDeleteXlate(dc
->XlatePen
);
1834 dc
->XlatePen
= XlateObj
;
1837 case GDI_OBJECT_TYPE_BRUSH
:
1838 brush
= BRUSHOBJ_LockBrush((HPEN
) hGDIObj
);
1841 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1845 XlateObj
= IntGdiCreateBrushXlate(dc
, brush
, &Failed
);
1846 BRUSHOBJ_UnlockBrush(hGDIObj
);
1849 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
1853 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
1854 dc
->w
.hBrush
= hGDIObj
;
1855 if (dc
->XlateBrush
!= NULL
)
1856 EngDeleteXlate(dc
->XlateBrush
);
1857 dc
->XlateBrush
= XlateObj
;
1860 case GDI_OBJECT_TYPE_FONT
:
1861 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hGDIObj
)))
1863 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
1864 dc
->w
.hFont
= (HFONT
) hGDIObj
;
1868 case GDI_OBJECT_TYPE_BITMAP
:
1869 // must be memory dc to select bitmap
1870 if (!(dc
->w
.flags
& DC_MEMORY
))
1875 pb
= BITMAPOBJ_LockBitmap(hGDIObj
);
1878 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1882 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
1884 /* Release the old bitmap, lock the new one and convert it to a SURF */
1885 dc
->w
.hBitmap
= hGDIObj
;
1887 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1890 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
1892 if(pb
->dib
->dsBmih
.biBitCount
<= 8)
1894 if(pb
->dib
->dsBmih
.biBitCount
== 1) { NumColors
= 2; } else
1895 if(pb
->dib
->dsBmih
.biBitCount
== 4) { NumColors
= 16; } else
1896 if(pb
->dib
->dsBmih
.biBitCount
== 8) { NumColors
= 256; }
1897 dc
->w
.hPalette
= PALETTE_AllocPaletteIndexedRGB(NumColors
, pb
->ColorMap
);
1901 dc
->w
.hPalette
= PALETTE_AllocPalette(PAL_BITFIELDS
, 0, NULL
,
1902 pb
->dib
->dsBitfields
[0],
1903 pb
->dib
->dsBitfields
[1],
1904 pb
->dib
->dsBitfields
[2]);
1909 dc
->w
.bitsPerPixel
= BitsPerFormat(pb
->SurfObj
.iBitmapFormat
);
1910 dc
->w
.hPalette
= dc
->DevInfo
->hpalDefault
;
1913 /* Reselect brush and pen to regenerate the XLATEOBJs. */
1914 NtGdiSelectObject ( hDC
, dc
->w
.hBrush
);
1915 NtGdiSelectObject ( hDC
, dc
->w
.hPen
);
1917 DC_UnlockDc ( hDC
);
1918 hVisRgn
= NtGdiCreateRectRgn ( 0, 0, pb
->SurfObj
.sizlBitmap
.cx
, pb
->SurfObj
.sizlBitmap
.cy
);
1919 BITMAPOBJ_UnlockBitmap( hGDIObj
);
1920 NtGdiSelectVisRgn ( hDC
, hVisRgn
);
1921 NtGdiDeleteObject ( hVisRgn
);
1925 case GDI_OBJECT_TYPE_REGION
:
1928 * The return value is one of the following values:
1933 return (HGDIOBJ
) NtGdiSelectClipRgn(hDC
, (HRGN
) hGDIObj
);
1943 NtGdiSetHookFlags(HDC hDC
, WORD Flags
)
1946 DC
*dc
= DC_LockDc(hDC
);
1950 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1954 wRet
= dc
->w
.flags
& DC_DIRTY
;
1956 /* "Undocumented Windows" info is slightly confusing.
1959 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
1961 if (Flags
& DCHF_INVALIDATEVISRGN
)
1963 dc
->w
.flags
|= DC_DIRTY
;
1965 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
1967 dc
->w
.flags
&= ~DC_DIRTY
;
1975 DC_SET_MODE( NtGdiSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
1976 DC_SET_MODE( NtGdiSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
1977 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1978 DC_SET_MODE( NtGdiSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
1979 DC_SET_MODE( NtGdiSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
1981 // ---------------------------------------------------- Private Interface
1984 DC_AllocDC(PUNICODE_STRING Driver
)
1992 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
1997 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2000 hDC
= (HDC
) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_DC
);
2010 NewDC
= DC_LockDc(hDC
);
2011 /* FIXME - Handle NewDC == NULL! */
2015 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2016 NewDC
->DriverName
.Buffer
= Buf
;
2019 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2020 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2021 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2022 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2023 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2024 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2025 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2026 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2027 NewDC
->w
.vport2WorldValid
= TRUE
;
2028 NewDC
->w
.MapMode
= MM_TEXT
;
2029 NewDC
->wndExtX
= 1.0f
;
2030 NewDC
->wndExtY
= 1.0f
;
2031 NewDC
->vportExtX
= 1.0f
;
2032 NewDC
->vportExtY
= 1.0f
;
2033 NewDC
->w
.textColor
= 0;
2034 NewDC
->w
.backgroundColor
= 0xffffff;
2036 NewDC
->w
.hFont
= NtGdiGetStockObject(SYSTEM_FONT
);
2037 TextIntRealizeFont(NewDC
->w
.hFont
);
2039 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2047 DC_FindOpenDC(PUNICODE_STRING Driver
)
2053 * Initialize some common fields in the Device Context structure.
2056 DC_InitDC(HDC DCHandle
)
2058 // NtGdiRealizeDefaultPalette(DCHandle);
2060 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2061 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2062 //NtGdiSelectObject(DCHandle, hFont);
2067 res = CLIPPING_UpdateGCRegion(DCToInit);
2068 ASSERT ( res != ERROR );
2074 DC_FreeDC(HDC DCToFree
)
2076 if (!GDIOBJ_FreeObj(DCToFree
, GDI_OBJECT_TYPE_DC
))
2078 DPRINT("DC_FreeDC failed\n");
2083 DC_Cleanup(PVOID ObjectBody
)
2085 PDC pDC
= (PDC
)ObjectBody
;
2086 RtlFreeUnicodeString(&pDC
->DriverName
);
2091 DC_GetNextDC (PDC pDC
)
2097 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2099 pDC
->hNext
= hNextDC
;
2103 DC_UpdateXforms(PDC dc
)
2105 XFORM xformWnd2Vport
;
2106 FLOAT scaleX
, scaleY
;
2108 /* Construct a transformation to do the window-to-viewport conversion */
2109 scaleX
= (dc
->wndExtX
? (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
: 0.0f
);
2110 scaleY
= (dc
->wndExtY
? (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
: 0.0f
);
2111 xformWnd2Vport
.eM11
= scaleX
;
2112 xformWnd2Vport
.eM12
= 0.0;
2113 xformWnd2Vport
.eM21
= 0.0;
2114 xformWnd2Vport
.eM22
= scaleY
;
2115 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
2116 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
2118 /* Combine with the world transformation */
2119 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2121 /* Create inverse of world-to-viewport transformation */
2122 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2126 DC_InvertXform(const XFORM
*xformSrc
,
2131 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2132 if (determinant
> -1e-12 && determinant
< 1e-12)
2137 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2138 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2139 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2140 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2141 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2142 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2148 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2152 GDIOBJ_SetOwnership(hDC
, Owner
);
2153 DC
= DC_LockDc(hDC
);
2156 if (NULL
!= DC
->w
.hClipRgn
)
2158 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hClipRgn
);
2160 if (NULL
!= DC
->w
.hVisRgn
)
2162 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hVisRgn
);
2164 if (NULL
!= DC
->w
.hGCClipRgn
)
2166 GDIOBJ_CopyOwnership(hDC
, DC
->w
.hGCClipRgn
);
2173 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2175 if (PrimarySurface
.Handle
== NULL
)
2179 return SurfObj
->hsurf
== PrimarySurface
.Handle
;
2183 * Returns the color of the brush or pen that is currently selected into the DC.
2184 * This function is called from GetDCBrushColor() and GetDCPenColor()
2187 IntGetDCColor(HDC hDC
, ULONG Object
)
2190 * The previous implementation was completly incorrect. It modified the
2191 * brush that was currently selected into the device context, but in fact
2192 * the DC pen/brush color should be stored directly in the device context
2193 * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
2194 * The actual color is then used when DC_BRUSH/DC_PEN object is selected
2195 * into the device context and BRUSHOBJ for drawing is composed (belongs
2196 * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
2197 * the implementation should be moved to user mode GDI32.dll when UM
2198 * mapped GDI objects will be implemented.
2201 DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
2202 return 0xFFFFFF; /* The default DC color. */
2206 * Changes the color of the brush or pen that is currently selected into the DC.
2207 * This function is called from SetDCBrushColor() and SetDCPenColor()
2210 IntSetDCColor(HDC hDC
, ULONG Object
, COLORREF Color
)
2212 /* See the comment in IntGetDCColor. */
2214 DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
2218 #define SIZEOF_DEVMODEW_300 188
2219 #define SIZEOF_DEVMODEW_400 212
2220 #define SIZEOF_DEVMODEW_500 220
2222 /*! \brief Enumerate possible display settings for the given display...
2224 * \todo Make thread safe!?
2225 * \todo Don't ignore lpszDeviceName
2226 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2229 IntEnumDisplaySettings(
2230 PUNICODE_STRING lpszDeviceName
,
2232 LPDEVMODEW lpDevMode
,
2235 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2236 static DWORD SizeOfCachedDevModes
= 0;
2237 LPDEVMODEW CachedMode
= NULL
;
2240 ULONG DisplayNumber
= 0; /* only default display supported */
2242 if (lpDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2243 lpDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2244 lpDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2246 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2250 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2252 CachedMode
= &PrimarySurface
.DMW
;
2253 assert(CachedMode
->dmSize
> 0);
2255 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2257 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2258 DevMode
.dmSize
= sizeof (DevMode
);
2259 DevMode
.dmDriverExtra
= 0;
2260 if (SetupDevMode(&DevMode
, DisplayNumber
))
2261 CachedMode
= &DevMode
;
2264 SetLastWin32Error(0); /* FIXME: use error code */
2267 /* FIXME: Maybe look for the matching devmode supplied by the
2268 * driver so we can provide driver private/extra data?
2273 if (iModeNum
== 0 || CachedDevModes
== NULL
) /* query modes from drivers */
2275 BOOL PrimarySurfaceCreated
= FALSE
;
2276 UNICODE_STRING DriverFileNames
;
2278 DRVENABLEDATA DrvEnableData
;
2280 /* Retrieve DDI driver names from registry */
2281 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2282 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2284 DPRINT1("FindDriverFileNames failed\n");
2288 if (!HalQueryDisplayOwnership())
2290 IntCreatePrimarySurface();
2291 PrimarySurfaceCreated
= TRUE
;
2295 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2296 * scan all of them until a good one found.
2298 CurrentName
= DriverFileNames
.Buffer
;
2299 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2300 CurrentName
+= wcslen(CurrentName
) + 1)
2303 PGD_ENABLEDRIVER GDEnableDriver
;
2305 /* Get the DDI driver's entry point */
2306 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
2307 if (NULL
== GDEnableDriver
)
2309 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2313 /* Call DDI driver's EnableDriver function */
2314 RtlZeroMemory(&DrvEnableData
, sizeof (DrvEnableData
));
2316 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2318 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2322 CachedDevModesEnd
= CachedDevModes
;
2324 /* find DrvGetModes function */
2325 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2327 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2328 PGD_GETMODES GetModes
;
2329 INT SizeNeeded
, SizeUsed
;
2331 if (DrvFn
->iFunc
!= INDEX_DrvGetModes
)
2334 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2336 /* make sure we have enough memory to hold the modes */
2337 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2338 if (SizeNeeded
<= 0)
2340 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2344 SizeUsed
= CachedDevModesEnd
- CachedDevModes
;
2345 if (SizeOfCachedDevModes
- SizeUsed
< SizeNeeded
)
2349 SizeOfCachedDevModes
+= SizeNeeded
;
2350 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2351 if (NewBuffer
== NULL
)
2354 ExFreePool(CachedDevModes
);
2355 SizeOfCachedDevModes
= 0;
2356 CachedDevModes
= NULL
;
2357 CachedDevModesEnd
= NULL
;
2358 if (PrimarySurfaceCreated
)
2360 IntDestroyPrimarySurface();
2362 SetLastWin32Error(STATUS_NO_MEMORY
);
2365 if (CachedDevModes
!= NULL
)
2367 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2368 ExFreePool(CachedDevModes
);
2370 CachedDevModes
= NewBuffer
;
2371 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2375 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2376 SizeOfCachedDevModes
- SizeUsed
,
2378 if (SizeNeeded
<= 0)
2380 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2384 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2390 if (PrimarySurfaceCreated
)
2392 IntDestroyPrimarySurface();
2395 RtlFreeUnicodeString(&DriverFileNames
);
2398 /* return cached info */
2399 CachedMode
= CachedDevModes
;
2400 if (CachedMode
>= CachedDevModesEnd
)
2402 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2405 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2407 assert(CachedMode
->dmSize
> 0);
2408 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2410 if (CachedMode
>= CachedDevModesEnd
)
2412 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2417 assert(CachedMode
!= NULL
);
2419 Size
= OldSize
= lpDevMode
->dmSize
;
2420 if (Size
> CachedMode
->dmSize
)
2421 Size
= CachedMode
->dmSize
;
2422 RtlCopyMemory(lpDevMode
, CachedMode
, Size
);
2423 RtlZeroMemory((PCHAR
)lpDevMode
+ Size
, OldSize
- Size
);
2424 lpDevMode
->dmSize
= OldSize
;
2426 Size
= OldSize
= lpDevMode
->dmDriverExtra
;
2427 if (Size
> CachedMode
->dmDriverExtra
)
2428 Size
= CachedMode
->dmDriverExtra
;
2429 RtlCopyMemory((PCHAR
)lpDevMode
+ lpDevMode
->dmSize
,
2430 (PCHAR
)CachedMode
+ CachedMode
->dmSize
, Size
);
2431 RtlZeroMemory((PCHAR
)lpDevMode
+ lpDevMode
->dmSize
+ Size
, OldSize
- Size
);
2432 lpDevMode
->dmDriverExtra
= OldSize
;