3 * ReactOS W32 Subsystem
4 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * DC.C - Device context functions
31 static GDIDEVICE PrimarySurface
;
32 static KEVENT VideoDriverNeedsPreparation
;
33 static KEVENT VideoDriverPrepared
;
39 KeInitializeEvent(&VideoDriverNeedsPreparation
, SynchronizationEvent
, TRUE
);
40 KeInitializeEvent(&VideoDriverPrepared
, NotificationEvent
, FALSE
);
41 return STATUS_SUCCESS
;
44 /* FIXME: DCs should probably be thread safe */
46 // --------------------------------------------------------- File Statics
48 // ----------------------------------------------------- Public Functions
51 NtGdiCancelDC(HDC hDC
)
58 NtGdiCreateCompatibleDC(HDC hDC
)
61 PDC_ATTR nDc_Attr
, oDc_Attr
;
63 HDC hNewDC
, DisplayDC
;
65 UNICODE_STRING DriverName
;
71 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
72 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
73 if (NULL
== DisplayDC
)
80 /* Allocate a new DC based on the original DC's device */
81 OrigDC
= DC_LockDc(hDC
);
84 if (NULL
!= DisplayDC
)
86 NtGdiDeleteObjectApp(DisplayDC
);
90 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
94 if (NULL
!= DisplayDC
)
96 NtGdiDeleteObjectApp(DisplayDC
);
100 NewDC
= DC_LockDc( hNewDC
);
102 oDc_Attr
= OrigDC
->pDc_Attr
;
103 if(!oDc_Attr
) oDc_Attr
= &OrigDC
->Dc_Attr
;
104 nDc_Attr
= NewDC
->pDc_Attr
;
105 if(!nDc_Attr
) nDc_Attr
= &NewDC
->Dc_Attr
;
107 /* Copy information from original DC to new DC */
108 NewDC
->hSelf
= hNewDC
;
110 NewDC
->PDev
= OrigDC
->PDev
;
112 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
114 /* DriverName is copied in the AllocDC routine */
115 nDc_Attr
->ptlWindowOrg
= oDc_Attr
->ptlWindowOrg
;
116 nDc_Attr
->szlWindowExt
= oDc_Attr
->szlWindowExt
;
117 nDc_Attr
->ptlViewportOrg
= oDc_Attr
->ptlViewportOrg
;
118 nDc_Attr
->szlViewportExt
= oDc_Attr
->szlViewportExt
;
120 /* Create default bitmap */
121 if (!(hBitmap
= IntGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
123 DC_UnlockDc( OrigDC
);
124 DC_UnlockDc( NewDC
);
126 if (NULL
!= DisplayDC
)
128 NtGdiDeleteObjectApp(DisplayDC
);
132 NewDC
->DC_Type
= DC_TYPE_MEMORY
; // Always!
133 NewDC
->w
.hBitmap
= hBitmap
;
134 NewDC
->w
.hFirstBitmap
= hBitmap
;
135 NewDC
->pPDev
= OrigDC
->pPDev
;
137 NewDC
->PalIndexed
= OrigDC
->PalIndexed
;
138 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
139 nDc_Attr
->lTextAlign
= oDc_Attr
->lTextAlign
;
140 nDc_Attr
->ulForegroundClr
= oDc_Attr
->ulForegroundClr
;
141 nDc_Attr
->ulBackgroundClr
= oDc_Attr
->ulBackgroundClr
;
142 nDc_Attr
->lBkMode
= oDc_Attr
->lBkMode
;
143 nDc_Attr
->crForegroundClr
= oDc_Attr
->crForegroundClr
;
144 nDc_Attr
->crBackgroundClr
= oDc_Attr
->crBackgroundClr
;
145 nDc_Attr
->jBkMode
= oDc_Attr
->jBkMode
;
146 nDc_Attr
->jROP2
= oDc_Attr
->jROP2
;
147 nDc_Attr
->dwLayout
= oDc_Attr
->dwLayout
;
148 if (oDc_Attr
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= oDc_Attr
->dwLayout
;
152 if (NULL
!= DisplayDC
)
154 NtGdiDeleteObjectApp(DisplayDC
);
157 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
158 IntGdiSelectVisRgn(hNewDC
, hVisRgn
);
159 NtGdiDeleteObject(hVisRgn
);
160 if (Layout
) NtGdiSetLayout( hNewDC
, -1, Layout
);
166 static BOOLEAN FASTCALL
167 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
169 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
170 WCHAR DeviceNameBuffer
[20];
173 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%lu", DisplayNumber
);
174 RtlInitUnicodeString(RegistryPath
, NULL
);
175 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
176 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
177 QueryTable
[0].Name
= DeviceNameBuffer
;
178 QueryTable
[0].EntryContext
= RegistryPath
;
180 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
185 if (! NT_SUCCESS(Status
))
187 DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
191 DPRINT("RegistryPath %wZ\n", RegistryPath
);
197 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
199 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
200 UNICODE_STRING RegistryPath
;
203 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
205 DPRINT("GetRegistryPath failed\n");
209 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
210 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
211 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
212 QueryTable
[0].EntryContext
= DriverFileNames
;
214 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
219 RtlFreeUnicodeString(&RegistryPath
);
220 if (! NT_SUCCESS(Status
))
222 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
226 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
231 static NTSTATUS STDCALL
232 DevModeCallback(IN PWSTR ValueName
,
235 IN ULONG ValueLength
,
237 IN PVOID EntryContext
)
239 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
241 DPRINT("Found registry value for name %S: type %d, length %d\n",
242 ValueName
, ValueType
, ValueLength
);
244 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
246 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
248 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
250 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
252 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
254 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
256 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
258 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
260 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
262 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
264 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
266 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
268 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
270 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
272 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
276 return STATUS_SUCCESS
;
280 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
282 UNICODE_STRING RegistryPath
;
283 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
285 BOOLEAN Valid
= TRUE
;
287 if (!GetRegistryPath(&RegistryPath
, DisplayNumber
))
289 DPRINT("GetRegistryPath failed\n");
293 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
294 QueryTable
[0].QueryRoutine
= DevModeCallback
;
295 QueryTable
[0].Flags
= 0;
296 QueryTable
[0].Name
= NULL
;
297 QueryTable
[0].EntryContext
= NULL
;
298 QueryTable
[0].DefaultType
= REG_NONE
;
299 QueryTable
[0].DefaultData
= NULL
;
300 QueryTable
[0].DefaultLength
= 0;
302 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
307 if (! NT_SUCCESS(Status
))
309 DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
310 &RegistryPath
, Status
);
315 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
316 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
317 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
318 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
319 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
321 DPRINT("Not all required devmode members are set\n");
326 RtlFreeUnicodeString(&RegistryPath
);
330 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
339 PGD_ENABLEDRIVER GDEnableDriver
;
341 UNICODE_STRING DriverFileNames
;
350 if (STATUS_SUCCESS
!= KeWaitForSingleObject(&VideoDriverNeedsPreparation
, Executive
, KernelMode
, TRUE
, &Zero
))
352 /* Concurrent access. Wait for VideoDriverPrepared event */
353 if (STATUS_SUCCESS
== KeWaitForSingleObject(&VideoDriverPrepared
, Executive
, KernelMode
, TRUE
, NULL
))
354 ret
= PrimarySurface
.PreparedDriver
;
357 // HAX! Fixme so I can support more than one! So how many?
358 for (DisplayNumber
= 0; ; DisplayNumber
++)
360 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
362 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
364 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
366 /* Open the miniport driver */
367 if (PrimarySurface
.VideoFileObject
== NULL
)
369 DPRINT1("FindMPDriver failed\n");
373 /* Retrieve DDI driver names from registry */
374 RtlInitUnicodeString(&DriverFileNames
, NULL
);
375 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
377 DPRINT1("FindDriverFileNames failed\n");
382 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
383 * scan all of them until a good one found.
385 CurrentName
= DriverFileNames
.Buffer
;
388 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
390 /* Get the DDI driver's entry point */
391 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
392 if (NULL
== GDEnableDriver
)
394 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
398 /* Call DDI driver's EnableDriver function */
399 RtlZeroMemory(&DED
, sizeof(DED
));
401 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
403 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
413 /* Skip to the next name but never get past the Unicode string */
414 while (L
'\0' != *CurrentName
&&
415 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
419 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
428 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
429 RtlFreeUnicodeString(&DriverFileNames
);
430 DPRINT1("No suitable DDI driver found\n");
434 DPRINT("Display driver %S loaded\n", CurrentName
);
436 RtlFreeUnicodeString(&DriverFileNames
);
438 DPRINT("Building DDI Functions\n");
440 /* Construct DDI driver function dispatch table */
441 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
443 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
444 DPRINT1("BuildDDIFunctions failed\n");
448 /* Allocate a phyical device handle from the driver */
449 // Support DMW.dmSize + DMW.dmDriverExtra & Alloc DMW then set prt pdmwDev.
450 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
451 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
453 PrimarySurface
.hPDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
457 PrimarySurface
.FillPatterns
,
458 sizeof(PrimarySurface
.GDIInfo
),
459 (ULONG
*) &PrimarySurface
.GDIInfo
,
460 sizeof(PrimarySurface
.DevInfo
),
461 &PrimarySurface
.DevInfo
,
464 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
465 DoDefault
= (NULL
== PrimarySurface
.hPDev
);
468 DPRINT1("DrvEnablePDev with registry parameters failed\n");
478 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
479 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
480 PrimarySurface
.hPDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
484 PrimarySurface
.FillPatterns
,
485 sizeof(PrimarySurface
.GDIInfo
),
486 (ULONG
*) &PrimarySurface
.GDIInfo
,
487 sizeof(PrimarySurface
.DevInfo
),
488 &PrimarySurface
.DevInfo
,
491 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
493 if (NULL
== PrimarySurface
.hPDev
)
495 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
496 DPRINT1("DrvEnablePDEV with default parameters failed\n");
497 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
501 // Update the primary surface with what we really got
502 PrimarySurface
.DMW
.dmPelsWidth
= PrimarySurface
.GDIInfo
.ulHorzRes
;
503 PrimarySurface
.DMW
.dmPelsHeight
= PrimarySurface
.GDIInfo
.ulVertRes
;
504 PrimarySurface
.DMW
.dmBitsPerPel
= PrimarySurface
.GDIInfo
.cBitsPixel
;
505 PrimarySurface
.DMW
.dmDisplayFrequency
= PrimarySurface
.GDIInfo
.ulVRefresh
;
508 if (!PrimarySurface
.DMW
.dmDriverExtra
)
510 PrimarySurface
.pdmwDev
= &PrimarySurface
.DMW
; // HAX!
514 DPRINT1("WARNING!!! Need to Alloc DMW !!!!!!\n");
516 // Dont remove until we finish testing other drivers.
517 DPRINT1("DMW extra %x !!!!!!\n",PrimarySurface
.DMW
.dmDriverExtra
);
519 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
521 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
522 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
524 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
526 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
527 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
530 PrimarySurface
.Pointer
.Exclude
.right
= -1;
532 DPRINT("calling completePDev\n");
534 /* Complete initialization of the physical device */
535 PrimarySurface
.DriverFunctions
.CompletePDEV(
536 PrimarySurface
.hPDev
,
537 (HDEV
)&PrimarySurface
);
539 DPRINT("calling DRIVER_ReferenceDriver\n");
541 DRIVER_ReferenceDriver(L
"DISPLAY");
543 PrimarySurface
.PreparedDriver
= TRUE
;
544 PrimarySurface
.DisplayNumber
= DisplayNumber
;
545 PrimarySurface
.flFlags
= PDEV_DISPLAY
; // Hard set,, add more flags.
546 PrimarySurface
.hsemDevLock
= (PERESOURCE
)EngCreateSemaphore();
547 // Should be null,, but make sure for now.
548 PrimarySurface
.pvGammaRamp
= NULL
;
549 PrimarySurface
.ppdevNext
= NULL
; // Fixme! We need to support more than display drvs.
550 PrimarySurface
.ppdevParent
= NULL
; // Always NULL if primary.
551 PrimarySurface
.pGraphicsDev
= NULL
; // Fixme!
557 KeSetEvent(&VideoDriverPrepared
, 1, FALSE
);
562 IntPrepareDriverIfNeeded()
564 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
572 IO_STATUS_BLOCK Iosb
;
574 ULONG Length
= sizeof(BOOL
);
575 PIO_STACK_LOCATION StackPtr
;
576 LARGE_INTEGER StartOffset
;
577 PFILE_OBJECT FileObject
= PrimarySurface
.VideoFileObject
;
578 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
580 DPRINT("PrepareVideoPrt() called\n");
582 KeClearEvent(&PrimarySurface
.VideoFileObject
->Event
);
584 ObReferenceObjectByPointer(FileObject
, 0, IoFileObjectType
, KernelMode
);
586 StartOffset
.QuadPart
= 0;
587 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
599 /* Set up IRP Data */
600 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
601 Irp
->RequestorMode
= KernelMode
;
602 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
603 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= NULL
;
604 Irp
->Flags
|= IRP_WRITE_OPERATION
;
606 /* Setup Stack Data */
607 StackPtr
= IoGetNextIrpStackLocation(Irp
);
608 StackPtr
->FileObject
= PrimarySurface
.VideoFileObject
;
609 StackPtr
->Parameters
.Write
.Key
= 0;
611 Status
= IoCallDriver(DeviceObject
, Irp
);
613 if (STATUS_PENDING
== Status
)
615 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, TRUE
, 0);
616 Status
= Iosb
.Status
;
619 return NT_SUCCESS(Status
);
623 IntCreatePrimarySurface()
630 if (! IntPrepareDriverIfNeeded())
635 if (! PrepareVideoPrt())
640 DPRINT("calling EnableSurface\n");
641 /* Enable the drawing surface */
642 PrimarySurface
.pSurface
=
643 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.hPDev
);
644 if (NULL
== PrimarySurface
.pSurface
)
646 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.hPDev, FALSE);*/
647 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
648 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
649 DPRINT1("DrvEnableSurface failed\n");
653 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, TRUE
);
655 calledFromUser
= UserIsEntered(); //fixme: possibly upgrade a shared lock
656 if (!calledFromUser
){
657 UserEnterExclusive();
661 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
663 SurfObj
= EngLockSurface(PrimarySurface
.pSurface
);
664 SurfObj
->dhpdev
= PrimarySurface
.hPDev
;
665 SurfSize
= SurfObj
->sizlBitmap
;
666 SurfaceRect
.left
= SurfaceRect
.top
= 0;
667 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
668 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
669 /* FIXME - why does EngEraseSurface() sometimes crash?
670 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
672 /* Put the pointer in the center of the screen */
673 GDIDEV(SurfObj
)->Pointer
.Pos
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
674 GDIDEV(SurfObj
)->Pointer
.Pos
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
676 EngUnlockSurface(SurfObj
);
677 co_IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
679 if (!calledFromUser
){
687 IntDestroyPrimarySurface()
691 DRIVER_UnreferenceDriver(L
"DISPLAY");
693 calledFromUser
= UserIsEntered();
694 if (!calledFromUser
){
695 UserEnterExclusive();
699 IntDetachMonitor(&PrimarySurface
);
701 if (!calledFromUser
){
706 * FIXME: Hide a mouse pointer there. Also because we have to prevent
707 * memory leaks with the Eng* mouse routines.
710 DPRINT("Reseting display\n" );
711 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, FALSE
);
712 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.hPDev
);
713 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
714 PrimarySurface
.PreparedDriver
= FALSE
;
715 KeSetEvent(&VideoDriverNeedsPreparation
, 1, FALSE
);
716 KeResetEvent(&VideoDriverPrepared
);
720 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
724 IntGdiCreateDC(PUNICODE_STRING Driver
,
725 PUNICODE_STRING Device
,
727 CONST PDEVMODEW InitData
,
735 UNICODE_STRING StdDriver
;
738 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
740 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
742 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
746 if (! IntPrepareDriverIfNeeded())
748 /* Here, we have two possibilities:
749 * a) return NULL, and hope that the caller
750 * won't call us in a loop
751 * b) bugcheck, but caller is unable to
752 * react on the problem
754 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
756 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
761 calledFromUser
= UserIsEntered();
762 if (!calledFromUser
){
763 UserEnterExclusive();
766 if (! co_IntGraphicsCheck(TRUE
))
768 if (!calledFromUser
){
771 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
775 if (!calledFromUser
){
782 /* Check for existing DC object */
783 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
786 return NtGdiCreateCompatibleDC(hDC
);
789 /* Allocate a DC object */
790 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
795 NewDC
= DC_LockDc( hNewDC
);
802 nDc_Attr
= NewDC
->pDc_Attr
;
803 if(!nDc_Attr
) nDc_Attr
= &NewDC
->Dc_Attr
;
805 NewDC
->DC_Type
= DC_TYPE_DIRECT
;
807 NewDC
->PDev
= PrimarySurface
.hPDev
;
808 if(pUMdhpdev
) pUMdhpdev
= NewDC
->PDev
; // set DHPDEV for device.
809 NewDC
->pPDev
= (PVOID
)&PrimarySurface
;
810 NewDC
->w
.hBitmap
= (HBITMAP
)PrimarySurface
.pSurface
;
812 NewDC
->w
.bitsPerPixel
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.cBitsPixel
*
813 ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.cPlanes
;
814 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
816 NewDC
->flGraphics
= PrimarySurface
.DevInfo
.flGraphicsCaps
;
817 NewDC
->flGraphics2
= PrimarySurface
.DevInfo
.flGraphicsCaps2
;
821 NewDC
->PalIndexed
= NtGdiGetStockObject(DEFAULT_PALETTE
);
822 NewDC
->w
.hPalette
= PrimarySurface
.DevInfo
.hpalDefault
;
823 nDc_Attr
->jROP2
= R2_COPYPEN
;
825 NewDC
->erclWindow
.top
= NewDC
->erclWindow
.left
= 0;
826 NewDC
->erclWindow
.right
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulHorzRes
;
827 NewDC
->erclWindow
.bottom
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulVertRes
;
829 DC_UnlockDc( NewDC
);
831 hVisRgn
= NtGdiCreateRectRgn(0, 0, ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulHorzRes
,
832 ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulVertRes
);
833 IntGdiSelectVisRgn(hNewDC
, hVisRgn
);
834 NtGdiDeleteObject(hVisRgn
);
836 /* Initialize the DC state */
838 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
839 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
840 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
841 NtGdiSetBkMode(hNewDC
, OPAQUE
);
846 The CreateIC function creates an information context for the specified device.
847 The information context provides a fast way to get information about the
848 device without creating a device context (DC). However, GDI drawing functions
849 cannot accept a handle to an information context.
851 NewDC
->DC_Type
= DC_TYPE_INFO
;
852 DC_UnlockDc( NewDC
);
858 NtGdiOpenDCW( PUNICODE_STRING Device
,
860 PUNICODE_STRING pustrLogAddr
,
866 UNICODE_STRING SafeDevice
;
867 DEVMODEW SafeInitData
;
870 NTSTATUS Status
= STATUS_SUCCESS
;
878 ProbeForWrite(pUMdhpdev
,
882 ProbeForRead(InitData
,
885 RtlCopyMemory(&SafeInitData
,
891 Status
= _SEH_GetExceptionCode();
894 if(!NT_SUCCESS(Status
))
896 SetLastNtError(Status
);
899 /* FIXME - InitData can have some more bytes! */
904 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
905 if(!NT_SUCCESS(Status
))
907 SetLastNtError(Status
);
912 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
914 pUMdhpdev
? &Dhpdev
: NULL
,
915 InitData
? &SafeInitData
: NULL
,
916 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
918 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
929 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
931 PDC DCToDelete
= DC_LockDc(hDC
);
933 if (DCToDelete
== NULL
)
935 SetLastWin32Error(ERROR_INVALID_HANDLE
);
941 if (DCToDelete
->DC_Flags
& DC_FLAG_PERMANENT
)
943 DPRINT1("No! You Naughty Application!\n");
944 DC_UnlockDc( DCToDelete
);
945 return UserReleaseDC(NULL
, hDC
, FALSE
);
949 /* First delete all saved DCs */
950 while (DCToDelete
->saveLevel
)
955 savedHDC
= DC_GetNextDC (DCToDelete
);
956 savedDC
= DC_LockDc (savedHDC
);
961 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
962 DCToDelete
->saveLevel
--;
963 DC_UnlockDc( savedDC
);
964 NtGdiDeleteObjectApp (savedHDC
);
967 /* Free GDI resources allocated to this DC */
968 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
971 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
972 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
973 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
974 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
975 if (DCToDelete
->DC_Type
== DC_TYPE_MEMORY
)
977 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
979 if (DCToDelete
->XlateBrush
!= NULL
)
980 EngDeleteXlate(DCToDelete
->XlateBrush
);
981 if (DCToDelete
->XlatePen
!= NULL
)
982 EngDeleteXlate(DCToDelete
->XlatePen
);
984 if (DCToDelete
->w
.hClipRgn
)
986 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
988 if (DCToDelete
->w
.hVisRgn
)
990 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
992 if (NULL
!= DCToDelete
->CombinedClip
)
994 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
996 if (DCToDelete
->w
.hGCClipRgn
)
998 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
1001 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
1004 DC_UnlockDc( DCToDelete
);
1011 NtGdiDeleteObjectApp(HANDLE DCHandle
)
1014 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
1016 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
1017 return NtGdiDeleteObject((HGDIOBJ
) DCHandle
);
1019 if(IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
1021 if (!GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, DCHandle
))
1023 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1027 return IntGdiDeleteDC(DCHandle
, FALSE
);
1036 IN OPTIONAL LPSTR pjIn
)
1048 OUT OPTIONAL PVOID pvBuf
)
1056 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
1062 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
1063 if(!hDC
) return NULL
;
1065 if(!(dc
= DC_LockDc(hDC
)))
1067 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1070 Dc_Attr
= dc
->pDc_Attr
;
1071 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1074 case GDI_OBJECT_TYPE_EXTPEN
:
1075 case GDI_OBJECT_TYPE_PEN
:
1076 SelObject
= Dc_Attr
->hpen
;
1078 case GDI_OBJECT_TYPE_BRUSH
:
1079 SelObject
= Dc_Attr
->hbrush
;
1081 case GDI_OBJECT_TYPE_PALETTE
:
1082 SelObject
= dc
->w
.hPalette
;
1084 case GDI_OBJECT_TYPE_FONT
:
1085 SelObject
= Dc_Attr
->hlfntNew
;
1087 case GDI_OBJECT_TYPE_BITMAP
:
1088 SelObject
= dc
->w
.hBitmap
;
1090 case GDI_OBJECT_TYPE_COLORSPACE
:
1091 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1096 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1105 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1107 Point
->x
= dc
->w
.DCOrgX
;
1108 Point
->y
= dc
->w
.DCOrgY
;
1114 NtGdiGetDCPoint( HDC hDC
, UINT iPoint
, PPOINTL Point
)
1120 NTSTATUS Status
= STATUS_SUCCESS
;
1124 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1128 RtlZeroMemory(&SafePoint
, sizeof(POINT
));
1130 dc
= DC_LockDc(hDC
);
1133 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1139 case GdiGetViewPortExt
:
1140 IntGetViewportExtEx(dc
, &Size
);
1141 SafePoint
.x
= Size
.cx
;
1142 SafePoint
.y
= Size
.cy
;
1144 case GdiGetWindowExt
:
1145 IntGetWindowExtEx(dc
, &Size
);
1146 SafePoint
.x
= Size
.cx
;
1147 SafePoint
.y
= Size
.cy
;
1149 case GdiGetViewPortOrg
:
1150 IntGetViewportOrgEx(dc
, &SafePoint
);
1152 case GdiGetWindowOrg
:
1153 IntGetWindowOrgEx(dc
, &SafePoint
);
1156 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1158 case GdiGetAspectRatioFilter
:
1160 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1169 ProbeForWrite(Point
,
1176 Status
= _SEH_GetExceptionCode();
1181 if(!NT_SUCCESS(Status
))
1183 SetLastNtError(Status
);
1194 IntGdiCopyToSaveState(PDC dc
, PDC newdc
)
1196 PDC_ATTR Dc_Attr
, nDc_Attr
;
1198 Dc_Attr
= dc
->pDc_Attr
;
1199 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1200 nDc_Attr
= newdc
->pDc_Attr
;
1201 if(!nDc_Attr
) nDc_Attr
= &newdc
->Dc_Attr
;
1203 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1204 nDc_Attr
->dwLayout
= Dc_Attr
->dwLayout
;
1205 nDc_Attr
->hpen
= Dc_Attr
->hpen
;
1206 nDc_Attr
->hbrush
= Dc_Attr
->hbrush
;
1207 nDc_Attr
->hlfntNew
= Dc_Attr
->hlfntNew
;
1208 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1209 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1210 newdc
->PalIndexed
= dc
->PalIndexed
;
1211 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1212 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1213 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1214 nDc_Attr
->jROP2
= Dc_Attr
->jROP2
;
1215 nDc_Attr
->jFillMode
= Dc_Attr
->jFillMode
;
1216 nDc_Attr
->jStretchBltMode
= Dc_Attr
->jStretchBltMode
;
1217 nDc_Attr
->lRelAbs
= Dc_Attr
->lRelAbs
;
1218 nDc_Attr
->jBkMode
= Dc_Attr
->jBkMode
;
1219 nDc_Attr
->lBkMode
= Dc_Attr
->lBkMode
;
1220 nDc_Attr
->crBackgroundClr
= Dc_Attr
->crBackgroundClr
;
1221 nDc_Attr
->crForegroundClr
= Dc_Attr
->crForegroundClr
;
1222 nDc_Attr
->ulBackgroundClr
= Dc_Attr
->ulBackgroundClr
;
1223 nDc_Attr
->ulForegroundClr
= Dc_Attr
->ulForegroundClr
;
1224 nDc_Attr
->ptlBrushOrigin
= Dc_Attr
->ptlBrushOrigin
;
1225 nDc_Attr
->lTextAlign
= Dc_Attr
->lTextAlign
;
1226 nDc_Attr
->lTextExtra
= Dc_Attr
->lTextExtra
;
1227 nDc_Attr
->cBreak
= Dc_Attr
->cBreak
;
1228 nDc_Attr
->lBreakExtra
= Dc_Attr
->lBreakExtra
;
1229 nDc_Attr
->iMapMode
= Dc_Attr
->iMapMode
;
1230 nDc_Attr
->iGraphicsMode
= Dc_Attr
->iGraphicsMode
;
1232 /* Apparently, the DC origin is not changed by [GS]etDCState */
1233 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1234 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1236 nDc_Attr
->ptlCurrent
= Dc_Attr
->ptlCurrent
;
1237 nDc_Attr
->ptfxCurrent
= Dc_Attr
->ptfxCurrent
;
1238 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1239 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1240 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1241 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1242 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1243 nDc_Attr
->ptlWindowOrg
= Dc_Attr
->ptlWindowOrg
;
1244 nDc_Attr
->szlWindowExt
= Dc_Attr
->szlWindowExt
;
1245 nDc_Attr
->ptlViewportOrg
= Dc_Attr
->ptlViewportOrg
;
1246 nDc_Attr
->szlViewportExt
= Dc_Attr
->szlViewportExt
;
1248 newdc
->saveLevel
= 0;
1249 newdc
->DC_Type
= dc
->DC_Type
;
1252 PATH_InitGdiPath( &newdc
->w
.path
);
1255 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1257 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1260 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1261 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1268 IntGdiCopyFromSaveState(PDC dc
, PDC dcs
, HDC hDC
)
1270 PDC_ATTR Dc_Attr
, sDc_Attr
;
1272 Dc_Attr
= dc
->pDc_Attr
;
1273 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1274 sDc_Attr
= dcs
->pDc_Attr
;
1275 if(!sDc_Attr
) sDc_Attr
= &dcs
->Dc_Attr
;
1277 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1279 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1281 Dc_Attr
->dwLayout
= sDc_Attr
->dwLayout
;
1282 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1283 Dc_Attr
->jROP2
= sDc_Attr
->jROP2
;
1284 Dc_Attr
->jFillMode
= sDc_Attr
->jFillMode
;
1285 Dc_Attr
->jStretchBltMode
= sDc_Attr
->jStretchBltMode
;
1286 Dc_Attr
->lRelAbs
= sDc_Attr
->lRelAbs
;
1287 Dc_Attr
->jBkMode
= sDc_Attr
->jBkMode
;
1288 Dc_Attr
->crBackgroundClr
= sDc_Attr
->crBackgroundClr
;
1289 Dc_Attr
->crForegroundClr
= sDc_Attr
->crForegroundClr
;
1290 Dc_Attr
->lBkMode
= sDc_Attr
->lBkMode
;
1291 Dc_Attr
->ulBackgroundClr
= sDc_Attr
->ulBackgroundClr
;
1292 Dc_Attr
->ulForegroundClr
= sDc_Attr
->ulForegroundClr
;
1293 Dc_Attr
->ptlBrushOrigin
= sDc_Attr
->ptlBrushOrigin
;
1295 Dc_Attr
->lTextAlign
= sDc_Attr
->lTextAlign
;
1296 Dc_Attr
->lTextExtra
= sDc_Attr
->lTextExtra
;
1297 Dc_Attr
->cBreak
= sDc_Attr
->cBreak
;
1298 Dc_Attr
->lBreakExtra
= sDc_Attr
->lBreakExtra
;
1299 Dc_Attr
->iMapMode
= sDc_Attr
->iMapMode
;
1300 Dc_Attr
->iGraphicsMode
= sDc_Attr
->iGraphicsMode
;
1302 /* Apparently, the DC origin is not changed by [GS]etDCState */
1303 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1304 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1306 Dc_Attr
->ptlCurrent
= sDc_Attr
->ptlCurrent
;
1307 Dc_Attr
->ptfxCurrent
= sDc_Attr
->ptfxCurrent
;
1308 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1309 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1310 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1311 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1312 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1313 Dc_Attr
->ptlWindowOrg
= sDc_Attr
->ptlWindowOrg
;
1314 Dc_Attr
->szlWindowExt
= sDc_Attr
->szlWindowExt
;
1315 Dc_Attr
->ptlViewportOrg
= sDc_Attr
->ptlViewportOrg
;
1316 Dc_Attr
->szlViewportExt
= sDc_Attr
->szlViewportExt
;
1317 dc
->PalIndexed
= dcs
->PalIndexed
;
1319 if (dc
->DC_Type
!= DC_TYPE_MEMORY
)
1321 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1325 if (dcs
->w
.hClipRgn
)
1327 if (!dc
->w
.hClipRgn
)
1329 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1331 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1337 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1343 res
= CLIPPING_UpdateGCRegion( dc
);
1344 ASSERT ( res
!= ERROR
);
1348 IntGdiExtSelectClipRgn(dc
, dcs
->w
.hClipRgn
, RGN_COPY
);
1351 if(!hDC
) return; // Not a MemoryDC or SaveLevel DC, return.
1353 NtGdiSelectBitmap( hDC
, dcs
->w
.hBitmap
);
1354 NtGdiSelectBrush( hDC
, sDc_Attr
->hbrush
);
1355 NtGdiSelectFont( hDC
, sDc_Attr
->hlfntNew
);
1356 NtGdiSelectPen( hDC
, sDc_Attr
->hpen
);
1358 NtGdiSetBkColor( hDC
, sDc_Attr
->crBackgroundClr
);
1359 NtGdiSetTextColor( hDC
, sDc_Attr
->crForegroundClr
);
1361 NtUserSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1364 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1369 IntGdiGetDCState(HDC hDC
)
1374 dc
= DC_LockDc(hDC
);
1377 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1381 hnewdc
= DC_AllocDC(NULL
);
1387 newdc
= DC_LockDc( hnewdc
);
1388 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1391 newdc
->hSelf
= hnewdc
;
1392 IntGdiCopyToSaveState( dc
, newdc
);
1394 DC_UnlockDc( newdc
);
1402 IntGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1406 dc
= DC_LockDc ( hDC
);
1409 dcs
= DC_LockDc ( hDCSave
);
1412 if ( dcs
->w
.flags
& DC_SAVED
)
1414 IntGdiCopyFromSaveState( dc
, dcs
, dc
->hSelf
);
1420 DC_UnlockDc ( dcs
);
1425 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1429 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1433 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1438 /* Retrieve capability */
1442 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVersion
;
1446 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulTechnology
;
1450 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
;
1454 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
;
1458 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
1462 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
1466 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulLogPixelsX
;
1470 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulLogPixelsY
;
1474 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.cBitsPixel
;
1478 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.cPlanes
;
1482 UNIMPLEMENTED
; /* FIXME */
1486 UNIMPLEMENTED
; /* FIXME */
1490 UNIMPLEMENTED
; /* FIXME */
1494 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulNumColors
;
1498 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectX
;
1502 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectY
;
1506 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectXY
;
1510 UNIMPLEMENTED
; /* FIXME */
1514 UNIMPLEMENTED
; /* FIXME */
1518 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulNumPalReg
; /* FIXME not sure */
1526 UNIMPLEMENTED
; /* FIXME */
1530 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1540 case PHYSICALHEIGHT
:
1541 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1551 case PHYSICALOFFSETX
:
1552 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1562 case PHYSICALOFFSETY
:
1563 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1574 UNIMPLEMENTED
; /* FIXME */
1577 case SCALINGFACTORX
:
1578 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1588 case SCALINGFACTORY
:
1589 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1600 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.flRaster
;
1604 UNIMPLEMENTED
; /* FIXME */
1608 UNIMPLEMENTED
; /* FIXME */
1612 UNIMPLEMENTED
; /* FIXME */
1616 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.flTextCaps
;
1628 NtGdiGetDeviceCaps(HDC hDC
,
1634 dc
= DC_LockDc(hDC
);
1637 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1641 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1643 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1651 IntGdiGetObject(IN HANDLE Handle
,
1659 pGdiObject
= GDIOBJ_LockObj(GdiHandleTable
, Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1662 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1666 dwObjectType
= GDIOBJ_GetObjectType(Handle
);
1667 switch (dwObjectType
)
1669 case GDI_OBJECT_TYPE_PEN
:
1670 case GDI_OBJECT_TYPE_EXTPEN
:
1671 Result
= PEN_GetObject((PGDIBRUSHOBJ
) pGdiObject
, cbCount
, (PLOGPEN
) lpBuffer
); // IntGdiCreatePenIndirect
1674 case GDI_OBJECT_TYPE_BRUSH
:
1675 Result
= BRUSH_GetObject((PGDIBRUSHOBJ
) pGdiObject
, cbCount
, (LPLOGBRUSH
)lpBuffer
);
1678 case GDI_OBJECT_TYPE_BITMAP
:
1679 Result
= BITMAP_GetObject((BITMAPOBJ
*) pGdiObject
, cbCount
, lpBuffer
);
1681 case GDI_OBJECT_TYPE_FONT
:
1682 Result
= FontGetObject((PTEXTOBJ
) pGdiObject
, cbCount
, lpBuffer
);
1684 // Fix the LOGFONT structure for the stock fonts
1685 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1687 FixStockFontSizeW(Handle
, cbCount
, lpBuffer
);
1692 case GDI_OBJECT_TYPE_PALETTE
:
1693 Result
= PALETTE_GetObject((PPALGDI
) pGdiObject
, cbCount
, lpBuffer
);
1697 DPRINT1("GDI object type 0x%08x not implemented\n", dwObjectType
);
1701 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, pGdiObject
);
1708 NtGdiExtGetObjectW(IN HANDLE hGdiObj
,
1710 OUT LPVOID lpBuffer
)
1717 DIBSECTION dibsection
;
1721 EXTLOGFONTW extlogfontw
;
1722 ENUMLOGFONTEXDVW enumlogfontexdvw
;
1725 // Normalize to the largest supported object size
1726 cbCount
= min((UINT
)cbCount
, sizeof(Object
));
1728 // Now do the actual call
1729 iRetCount
= IntGdiGetObject(hGdiObj
, cbCount
, lpBuffer
? &Object
: NULL
);
1730 cbCopyCount
= min((UINT
)cbCount
, (UINT
)iRetCount
);
1732 // Make sure we have a buffer and a copy size
1733 if ((cbCopyCount
) && (lpBuffer
))
1735 // Enter SEH for buffer transfer
1738 // Probe the buffer and copy it
1739 ProbeForWrite(lpBuffer
, cbCopyCount
, sizeof(WORD
));
1740 RtlCopyMemory(lpBuffer
, &Object
, cbCopyCount
);
1744 // Clear the return value.
1745 // Do *NOT* set last error here!
1759 OUT PBOOL pbBanding
,
1760 IN OPTIONAL VOID
*pDriverInfo2
,
1761 OUT VOID
*ppUMdhpdev
)
1768 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1773 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1775 dc
= DC_LockDc(hDC
);
1778 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1783 SaveLevel
= dc
->saveLevel
+ SaveLevel
+ 1;
1785 if(SaveLevel
< 0 || dc
->saveLevel
<SaveLevel
)
1792 while (dc
->saveLevel
>= SaveLevel
)
1794 HDC hdcs
= DC_GetNextDC (dc
);
1796 dcs
= DC_LockDc (hdcs
);
1803 DC_SetNextDC (dc
, DC_GetNextDC (dcs
));
1806 if (--dc
->saveLevel
< SaveLevel
)
1811 IntGdiSetDCState(hDC
, hdcs
);
1813 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1815 /* FIXME: This might not be quite right, since we're
1816 * returning FALSE but still destroying the saved DC state */
1819 dc
= DC_LockDc(hDC
);
1829 NtGdiDeleteObjectApp (hdcs
);
1837 NtGdiSaveDC(HDC hDC
)
1843 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
1845 if (!(hdcs
= IntGdiGetDCState(hDC
)))
1850 dcs
= DC_LockDc (hdcs
);
1853 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1856 dc
= DC_LockDc (hDC
);
1860 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1865 /* Copy path. The reason why path saving / restoring is in SaveDC/
1866 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1867 * functions are only in Win16 (which doesn't have paths) and that
1868 * SetDCState doesn't allow us to signal an error (which can happen
1869 * when copying paths).
1871 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
1873 NtGdiDeleteObjectApp (hdcs
);
1879 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
1880 DC_SetNextDC (dc
, hdcs
);
1881 ret
= ++dc
->saveLevel
;
1903 PGDIBRUSHOBJ pBrush
;
1905 if (hDC
== NULL
|| hBmp
== NULL
) return NULL
;
1907 pDC
= DC_LockDc(hDC
);
1913 pDc_Attr
= pDC
->pDc_Attr
;
1914 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
1916 /* must be memory dc to select bitmap */
1917 if (pDC
->DC_Type
!= DC_TYPE_MEMORY
)
1923 pBmp
= BITMAPOBJ_LockBitmap(hBmp
);
1929 hOrgBmp
= pDC
->w
.hBitmap
;
1931 /* Release the old bitmap, lock the new one and convert it to a SURF */
1932 pDC
->w
.hBitmap
= hBmp
;
1934 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1937 pDC
->w
.bitsPerPixel
= pBmp
->dib
->dsBmih
.biBitCount
;
1938 pDC
->w
.hPalette
= pBmp
->hDIBPalette
;
1942 pDC
->w
.bitsPerPixel
= BitsPerFormat(pBmp
->SurfObj
.iBitmapFormat
);
1943 pDC
->w
.hPalette
= ((GDIDEVICE
*)pDC
->pPDev
)->DevInfo
.hpalDefault
;
1946 /* Regenerate the XLATEOBJs. */
1947 pBrush
= BRUSHOBJ_LockBrush(pDc_Attr
->hbrush
);
1950 if (pDC
->XlateBrush
)
1952 EngDeleteXlate(pDC
->XlateBrush
);
1954 pDC
->XlateBrush
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
1955 BRUSHOBJ_UnlockBrush(pBrush
);
1958 pBrush
= PENOBJ_LockPen(pDc_Attr
->hpen
);
1963 EngDeleteXlate(pDC
->XlatePen
);
1965 pDC
->XlatePen
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
1966 PENOBJ_UnlockPen(pBrush
);
1971 hVisRgn
= NtGdiCreateRectRgn(0, 0, pBmp
->SurfObj
.sizlBitmap
.cx
, pBmp
->SurfObj
.sizlBitmap
.cy
);
1972 BITMAPOBJ_UnlockBitmap(pBmp
);
1973 IntGdiSelectVisRgn(hDC
, hVisRgn
);
1974 NtGdiDeleteObject(hVisRgn
);
1991 PGDIBRUSHOBJ pBrush
;
1995 if (hDC
== NULL
|| hBrush
== NULL
) return NULL
;
1997 pDC
= DC_LockDc(hDC
);
2003 pDc_Attr
= pDC
->pDc_Attr
;
2004 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2006 pBrush
= BRUSHOBJ_LockBrush(hBrush
);
2009 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2013 XlateObj
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
2014 BRUSHOBJ_UnlockBrush(pBrush
);
2020 hOrgBrush
= pDc_Attr
->hbrush
;
2021 pDc_Attr
->hbrush
= hBrush
;
2022 if (pDC
->XlateBrush
!= NULL
)
2024 EngDeleteXlate(pDC
->XlateBrush
);
2026 pDC
->XlateBrush
= XlateObj
;
2043 HFONT hOrgFont
= NULL
;
2045 if (hDC
== NULL
|| hFont
== NULL
) return NULL
;
2047 pDC
= DC_LockDc(hDC
);
2053 pDc_Attr
= pDC
->pDc_Attr
;
2054 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2056 /* FIXME: what if not successful? */
2057 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hFont
)))
2059 hOrgFont
= pDc_Attr
->hlfntNew
;
2060 pDc_Attr
->hlfntNew
= hFont
;
2079 HPEN hOrgPen
= NULL
;
2084 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
2086 pDC
= DC_LockDc(hDC
);
2092 pDc_Attr
= pDC
->pDc_Attr
;
2093 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2095 pPen
= PENOBJ_LockPen(hPen
);
2101 XlateObj
= IntGdiCreateBrushXlate(pDC
, pPen
, &bFailed
);
2102 PENOBJ_UnlockPen(pPen
);
2105 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2109 hOrgPen
= pDc_Attr
->hpen
;
2110 pDc_Attr
->hpen
= hPen
;
2111 if (pDC
->XlatePen
!= NULL
)
2113 EngDeleteXlate(pDC
->XlatePen
);
2115 pDC
->XlatePen
= XlateObj
;
2123 IntGdiSetHookFlags(HDC hDC
, WORD Flags
)
2126 DC
*dc
= DC_LockDc(hDC
);
2130 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2134 wRet
= dc
->w
.flags
& DC_DIRTY
;
2136 /* "Undocumented Windows" info is slightly confusing.
2139 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2141 if (Flags
& DCHF_INVALIDATEVISRGN
)
2143 dc
->w
.flags
|= DC_DIRTY
;
2145 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2147 dc
->w
.flags
&= ~DC_DIRTY
;
2168 DWORD SafeResult
= 0;
2169 NTSTATUS Status
= STATUS_SUCCESS
;
2173 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2177 dc
= DC_LockDc(hDC
);
2180 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2183 Dc_Attr
= dc
->pDc_Attr
;
2184 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2191 SafeResult
= Dc_Attr
->lRelAbs
;
2193 case GdiGetBreakExtra
:
2194 SafeResult
= Dc_Attr
->lBreakExtra
;
2196 case GdiGerCharBreak
:
2197 SafeResult
= Dc_Attr
->cBreak
;
2199 case GdiGetArcDirection
:
2200 SafeResult
= dc
->w
.ArcDirection
;
2202 case GdiGetEMFRestorDc
:
2204 case GdiGetFontLanguageInfo
:
2207 SafeResult
= dc
->DC_Type
;
2210 SafeResult
= Dc_Attr
->iMapMode
;
2212 case GdiGetTextCharExtra
:
2213 SafeResult
= Dc_Attr
->lTextExtra
;
2216 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2225 ProbeForWrite(Result
,
2228 *Result
= SafeResult
;
2232 Status
= _SEH_GetExceptionCode();
2237 if(!NT_SUCCESS(Status
))
2239 SetLastNtError(Status
);
2250 NtGdiGetAndSetDCDword(
2261 DWORD SafeResult
= 0;
2262 NTSTATUS Status
= STATUS_SUCCESS
;
2266 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2270 dc
= DC_LockDc(hDC
);
2273 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2276 Dc_Attr
= dc
->pDc_Attr
;
2277 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2281 case GdtGetSetCopyCount
:
2283 case GdiGetSetTextAlign
:
2284 SafeResult
= Dc_Attr
->lTextAlign
;
2285 Dc_Attr
->lTextAlign
= dwIn
;
2286 // Dc_Attr->flTextAlign = dwIn; // Flags!
2288 case GdiGetSetRelAbs
:
2289 SafeResult
= Dc_Attr
->lRelAbs
;
2290 Dc_Attr
->lRelAbs
= dwIn
;
2292 case GdiGetSetTextCharExtra
:
2293 SafeResult
= Dc_Attr
->lTextExtra
;
2294 Dc_Attr
->lTextExtra
= dwIn
;
2296 case GdiGetSetSelectFont
:
2298 case GdiGetSetMapperFlagsInternal
:
2300 case GdiGetSetMapMode
:
2301 SafeResult
= IntGdiSetMapMode( dc
, dwIn
);
2303 case GdiGetSetArcDirection
:
2304 if (dwIn
!= AD_COUNTERCLOCKWISE
&& dwIn
!= AD_CLOCKWISE
)
2306 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2309 SafeResult
= dc
->w
.ArcDirection
;
2310 dc
->w
.ArcDirection
= dwIn
;
2313 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2322 ProbeForWrite(Result
,
2325 *Result
= SafeResult
;
2329 Status
= _SEH_GetExceptionCode();
2334 if(!NT_SUCCESS(Status
))
2336 SetLastNtError(Status
);
2345 // ---------------------------------------------------- Private Interface
2348 DC_AllocDC(PUNICODE_STRING Driver
)
2357 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2362 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2365 hDC
= (HDC
) GDIOBJ_AllocObj(GdiHandleTable
, GDI_OBJECT_TYPE_DC
);
2375 DC_AllocateDcAttr(hDC
);
2377 NewDC
= DC_LockDc(hDC
);
2378 /* FIXME - Handle NewDC == NULL! */
2381 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2382 NewDC
->DriverName
.Buffer
= Buf
;
2384 Dc_Attr
= NewDC
->pDc_Attr
;
2385 if(!Dc_Attr
) Dc_Attr
= &NewDC
->Dc_Attr
;
2387 NewDC
->hHmgr
= (HGDIOBJ
) hDC
; // Save the handle for this DC object.
2388 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2389 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2390 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2391 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2392 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2393 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2394 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2395 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2396 NewDC
->w
.vport2WorldValid
= TRUE
;
2398 // Setup syncing bits for the dcattr data packets.
2399 Dc_Attr
->flXform
= DEVICE_TO_PAGE_INVALID
;
2401 Dc_Attr
->ulDirty_
= 0; // Server side
2403 Dc_Attr
->iMapMode
= MM_TEXT
;
2405 Dc_Attr
->szlWindowExt
.cx
= 1; // Float to Int,,, WRONG!
2406 Dc_Attr
->szlWindowExt
.cy
= 1;
2407 Dc_Attr
->szlViewportExt
.cx
= 1;
2408 Dc_Attr
->szlViewportExt
.cy
= 1;
2410 Dc_Attr
->crForegroundClr
= 0;
2411 Dc_Attr
->ulForegroundClr
= 0;
2413 Dc_Attr
->ulBackgroundClr
= 0xffffff;
2414 Dc_Attr
->crBackgroundClr
= 0xffffff;
2416 Dc_Attr
->ulPenClr
= RGB( 0, 0, 0 );
2417 Dc_Attr
->crPenClr
= RGB( 0, 0, 0 );
2419 Dc_Attr
->ulBrushClr
= RGB( 255, 255, 255 ); // Do this way too.
2420 Dc_Attr
->crBrushClr
= RGB( 255, 255, 255 );
2422 Dc_Attr
->hlfntNew
= NtGdiGetStockObject(SYSTEM_FONT
);
2423 TextIntRealizeFont(Dc_Attr
->hlfntNew
);
2425 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2433 DC_FindOpenDC(PUNICODE_STRING Driver
)
2439 * Initialize some common fields in the Device Context structure.
2442 DC_InitDC(HDC DCHandle
)
2444 // NtGdiRealizeDefaultPalette(DCHandle);
2446 NtGdiSelectBrush(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2447 NtGdiSelectPen(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2448 //NtGdiSelectFont(DCHandle, hFont);
2453 res = CLIPPING_UpdateGCRegion(DCToInit);
2454 ASSERT ( res != ERROR );
2461 DC_AllocateDcAttr(HDC hDC
)
2463 PVOID NewMem
= NULL
;
2465 HANDLE Pid
= NtCurrentProcess();
2466 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE it will allocate that size
2468 NTSTATUS Status
= ZwAllocateVirtualMemory(Pid
,
2472 MEM_COMMIT
|MEM_RESERVE
,
2474 KeEnterCriticalRegion();
2476 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hDC
);
2477 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2479 if (NT_SUCCESS(Status
))
2481 RtlZeroMemory(NewMem
, MemSize
);
2482 Entry
->UserData
= NewMem
;
2483 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem
);
2487 DPRINT("DC_ATTR not allocated!\n");
2490 KeLeaveCriticalRegion();
2491 pDC
= DC_LockDc(hDC
);
2494 pDC
->pDc_Attr
= NewMem
; // Store pointer
2501 DC_FreeDcAttr(HDC DCToFree
)
2503 HANDLE Pid
= NtCurrentProcess();
2504 PDC pDC
= DC_LockDc(DCToFree
);
2505 if (pDC
->pDc_Attr
== &pDC
->Dc_Attr
) return; // Internal DC object!
2506 pDC
->pDc_Attr
= NULL
;
2509 KeEnterCriticalRegion();
2511 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)DCToFree
);
2512 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2515 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE;
2516 NTSTATUS Status
= ZwFreeVirtualMemory(Pid
,
2520 if (NT_SUCCESS(Status
))
2522 DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry
->UserData
);
2523 Entry
->UserData
= NULL
;
2527 KeLeaveCriticalRegion();
2531 DC_FreeDC(HDC DCToFree
)
2533 DC_FreeDcAttr(DCToFree
);
2534 if(!IsObjectDead( DCToFree
))
2536 if (!GDIOBJ_FreeObj(GdiHandleTable
, DCToFree
, GDI_OBJECT_TYPE_DC
))
2538 DPRINT1("DC_FreeDC failed\n");
2543 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree
);
2548 DC_Cleanup(PVOID ObjectBody
)
2550 PDC pDC
= (PDC
)ObjectBody
;
2551 RtlFreeUnicodeString(&pDC
->DriverName
);
2556 DC_GetNextDC (PDC pDC
)
2562 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2564 pDC
->hNext
= hNextDC
;
2568 DC_UpdateXforms(PDC dc
)
2570 XFORM xformWnd2Vport
;
2571 FLOAT scaleX
, scaleY
;
2572 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
2573 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2575 /* Construct a transformation to do the window-to-viewport conversion */
2576 scaleX
= (Dc_Attr
->szlWindowExt
.cx
? (FLOAT
)Dc_Attr
->szlViewportExt
.cx
/ (FLOAT
)Dc_Attr
->szlWindowExt
.cx
: 0.0f
);
2577 scaleY
= (Dc_Attr
->szlWindowExt
.cy
? (FLOAT
)Dc_Attr
->szlViewportExt
.cy
/ (FLOAT
)Dc_Attr
->szlWindowExt
.cy
: 0.0f
);
2578 xformWnd2Vport
.eM11
= scaleX
;
2579 xformWnd2Vport
.eM12
= 0.0;
2580 xformWnd2Vport
.eM21
= 0.0;
2581 xformWnd2Vport
.eM22
= scaleY
;
2582 xformWnd2Vport
.eDx
= (FLOAT
)Dc_Attr
->ptlViewportOrg
.x
- scaleX
* (FLOAT
)Dc_Attr
->ptlWindowOrg
.x
;
2583 xformWnd2Vport
.eDy
= (FLOAT
)Dc_Attr
->ptlViewportOrg
.y
- scaleY
* (FLOAT
)Dc_Attr
->ptlWindowOrg
.y
;
2585 /* Combine with the world transformation */
2586 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2588 /* Create inverse of world-to-viewport transformation */
2589 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2593 DC_InvertXform(const XFORM
*xformSrc
,
2598 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2599 if (determinant
> -1e-12 && determinant
< 1e-12)
2604 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2605 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2606 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2607 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2608 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2609 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2615 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2619 GDIOBJ_SetOwnership(GdiHandleTable
, hDC
, Owner
);
2620 DC
= DC_LockDc(hDC
);
2623 if (NULL
!= DC
->w
.hClipRgn
)
2625 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hClipRgn
);
2627 if (NULL
!= DC
->w
.hVisRgn
)
2629 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hVisRgn
);
2631 if (NULL
!= DC
->w
.hGCClipRgn
)
2633 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hGCClipRgn
);
2640 // Support multi display/device locks.
2644 DC_LockDisplay(HDC hDC
)
2646 PERESOURCE Resource
;
2647 PDC dc
= DC_LockDc(hDC
);
2649 Resource
= ((PGDIDEVICE
)dc
->pPDev
)->hsemDevLock
;
2651 if (!Resource
) return;
2652 KeEnterCriticalRegion();
2653 ExAcquireResourceExclusiveLite( Resource
, TRUE
);
2658 DC_UnlockDisplay(HDC hDC
)
2660 PERESOURCE Resource
;
2661 PDC dc
= DC_LockDc(hDC
);
2663 Resource
= ((PGDIDEVICE
)dc
->pPDev
)->hsemDevLock
;
2665 if (!Resource
) return;
2666 ExReleaseResourceLite( Resource
);
2667 KeLeaveCriticalRegion();
2671 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2673 if (PrimarySurface
.pSurface
== NULL
)
2677 return SurfObj
->hsurf
== PrimarySurface
.pSurface
;
2686 // I guess we will soon have more than one primary surface.
2687 // This will do for now.
2688 return &PrimarySurface
;
2691 #define SIZEOF_DEVMODEW_300 188
2692 #define SIZEOF_DEVMODEW_400 212
2693 #define SIZEOF_DEVMODEW_500 220
2695 static NTSTATUS FASTCALL
2696 GetDisplayNumberFromDeviceName(
2697 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2698 OUT ULONG
*DisplayNumber
)
2700 UNICODE_STRING DisplayString
= RTL_CONSTANT_STRING(L
"\\\\.\\DISPLAY");
2701 NTSTATUS Status
= STATUS_SUCCESS
;
2706 if (DisplayNumber
== NULL
)
2707 return STATUS_INVALID_PARAMETER_2
;
2709 if (pDeviceName
&& pDeviceName
->Length
<= DisplayString
.Length
)
2710 return STATUS_OBJECT_NAME_INVALID
;
2712 if (pDeviceName
== NULL
|| pDeviceName
->Length
== 0)
2714 PWINDOW_OBJECT DesktopObject
;
2718 DesktopObject
= UserGetDesktopWindow();
2719 DesktopHDC
= (HDC
)UserGetWindowDC(DesktopObject
);
2720 pDC
= DC_LockDc(DesktopHDC
);
2722 *DisplayNumber
= ((GDIDEVICE
*)pDC
->pPDev
)->DisplayNumber
;
2725 UserReleaseDC(DesktopObject
, DesktopHDC
, FALSE
);
2727 return STATUS_SUCCESS
;
2730 /* Hack to check if the first parts are equal, by faking the device name length */
2731 Length
= pDeviceName
->Length
;
2732 pDeviceName
->Length
= DisplayString
.Length
;
2733 if (RtlEqualUnicodeString(&DisplayString
, pDeviceName
, FALSE
) == FALSE
)
2734 Status
= STATUS_OBJECT_NAME_INVALID
;
2735 pDeviceName
->Length
= Length
;
2737 if (NT_SUCCESS(Status
))
2739 /* Convert the last part of pDeviceName to a number */
2741 Length
= pDeviceName
->Length
/ sizeof(WCHAR
);
2742 for (i
= DisplayString
.Length
/ sizeof(WCHAR
); i
< Length
; i
++)
2744 WCHAR Char
= pDeviceName
->Buffer
[i
];
2745 if (Char
>= L
'0' && Char
<= L
'9')
2746 Number
= Number
* 10 + Char
- L
'0';
2747 else if (Char
!= L
'\0')
2748 return STATUS_OBJECT_NAME_INVALID
;
2751 *DisplayNumber
= Number
- 1;
2757 /*! \brief Enumerate possible display settings for the given display...
2759 * \todo Make thread safe!?
2760 * \todo Don't ignore pDeviceName
2761 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2764 IntEnumDisplaySettings(
2765 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2767 IN OUT LPDEVMODEW pDevMode
,
2770 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2771 static DWORD SizeOfCachedDevModes
= 0;
2772 static UNICODE_STRING CachedDeviceName
;
2773 PDEVMODEW CachedMode
= NULL
;
2775 ULONG DisplayNumber
;
2777 if (!NT_SUCCESS(GetDisplayNumberFromDeviceName(pDeviceName
, &DisplayNumber
)))
2779 SetLastWin32Error(STATUS_NO_SUCH_DEVICE
);
2783 DPRINT("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2784 DPRINT("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2785 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2786 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2787 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2789 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2793 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2795 CachedMode
= &PrimarySurface
.DMW
;
2796 ASSERT(CachedMode
->dmSize
> 0);
2798 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2800 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2801 DevMode
.dmSize
= sizeof (DevMode
);
2802 DevMode
.dmDriverExtra
= 0;
2803 if (SetupDevMode(&DevMode
, DisplayNumber
))
2804 CachedMode
= &DevMode
;
2807 SetLastWin32Error(0); /* FIXME: use error code */
2810 /* FIXME: Maybe look for the matching devmode supplied by the
2811 * driver so we can provide driver private/extra data?
2816 BOOL IsCachedDevice
= (CachedDevModes
!= NULL
);
2818 if (CachedDevModes
&&
2819 ((pDeviceName
== NULL
&& CachedDeviceName
.Length
> 0) ||
2820 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
== 0) ||
2821 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
> 0 && RtlEqualUnicodeString(pDeviceName
, &CachedDeviceName
, TRUE
) == FALSE
)))
2823 IsCachedDevice
= FALSE
;
2826 if (iModeNum
== 0 || IsCachedDevice
== FALSE
) /* query modes from drivers */
2828 UNICODE_STRING DriverFileNames
;
2830 DRVENABLEDATA DrvEnableData
;
2832 /* Free resources from last driver cache */
2833 if (IsCachedDevice
== FALSE
&& CachedDeviceName
.Buffer
!= NULL
)
2835 RtlFreeUnicodeString(&CachedDeviceName
);
2838 /* Retrieve DDI driver names from registry */
2839 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2840 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2842 DPRINT1("FindDriverFileNames failed\n");
2846 if (!IntPrepareDriverIfNeeded())
2848 DPRINT1("IntPrepareDriverIfNeeded failed\n");
2853 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2854 * scan all of them until a good one found.
2856 CurrentName
= DriverFileNames
.Buffer
;
2857 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2858 CurrentName
+= wcslen(CurrentName
) + 1)
2861 PGD_ENABLEDRIVER GDEnableDriver
;
2862 PGD_GETMODES GetModes
= NULL
;
2863 INT SizeNeeded
, SizeUsed
;
2865 /* Get the DDI driver's entry point */
2866 //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
2867 GDEnableDriver
= DRIVER_FindExistingDDIDriver(L
"DISPLAY");
2868 if (NULL
== GDEnableDriver
)
2870 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2874 /* Call DDI driver's EnableDriver function */
2875 RtlZeroMemory(&DrvEnableData
, sizeof(DrvEnableData
));
2877 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2879 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2883 CachedDevModesEnd
= CachedDevModes
;
2885 /* find DrvGetModes function */
2886 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2888 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2890 if (DrvFn
->iFunc
== INDEX_DrvGetModes
)
2892 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2897 if (GetModes
== NULL
)
2899 DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName
);
2903 /* make sure we have enough memory to hold the modes */
2904 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2905 if (SizeNeeded
<= 0)
2907 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2911 SizeUsed
= (PCHAR
)CachedDevModesEnd
- (PCHAR
)CachedDevModes
;
2912 if (SizeOfCachedDevModes
< SizeUsed
+ SizeNeeded
)
2916 SizeOfCachedDevModes
+= SizeNeeded
;
2917 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2918 if (NewBuffer
== NULL
)
2921 ExFreePool(CachedDevModes
);
2922 CachedDevModes
= NULL
;
2923 CachedDevModesEnd
= NULL
;
2924 SizeOfCachedDevModes
= 0;
2926 if (CachedDeviceName
.Buffer
!= NULL
)
2927 RtlFreeUnicodeString(&CachedDeviceName
);
2929 SetLastWin32Error(STATUS_NO_MEMORY
);
2932 if (CachedDevModes
!= NULL
)
2934 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2935 ExFreePool(CachedDevModes
);
2937 CachedDevModes
= NewBuffer
;
2938 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2941 if (!IsCachedDevice
)
2943 if (CachedDeviceName
.Buffer
!= NULL
)
2944 RtlFreeUnicodeString(&CachedDeviceName
);
2947 IntSafeCopyUnicodeString(&CachedDeviceName
, pDeviceName
);
2949 IsCachedDevice
= TRUE
;
2953 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2956 if (SizeNeeded
<= 0)
2958 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2962 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2966 RtlFreeUnicodeString(&DriverFileNames
);
2969 /* return cached info */
2970 CachedMode
= CachedDevModes
;
2971 if (CachedMode
>= CachedDevModesEnd
)
2973 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2976 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2978 assert(CachedMode
->dmSize
> 0);
2979 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2981 if (CachedMode
>= CachedDevModesEnd
)
2983 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2988 ASSERT(CachedMode
!= NULL
);
2990 RtlCopyMemory(pDevMode
, CachedMode
, min(pDevMode
->dmSize
, CachedMode
->dmSize
));
2991 RtlZeroMemory(pDevMode
+ pDevMode
->dmSize
, pDevMode
->dmDriverExtra
);
2992 RtlCopyMemory(pDevMode
+ min(pDevMode
->dmSize
, CachedMode
->dmSize
), CachedMode
+ CachedMode
->dmSize
, min(pDevMode
->dmDriverExtra
, CachedMode
->dmDriverExtra
));
2997 static NTSTATUS FASTCALL
2999 OUT PUNICODE_STRING VideoDeviceName
,
3000 IN PCUNICODE_STRING DisplayDevice
) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
3002 UNICODE_STRING Prefix
= RTL_CONSTANT_STRING(L
"\\??\\");
3003 UNICODE_STRING ObjectName
;
3004 UNICODE_STRING KernelModeName
= { 0, };
3005 OBJECT_ATTRIBUTES ObjectAttributes
;
3008 HANDLE LinkHandle
= NULL
;
3011 RtlInitUnicodeString(VideoDeviceName
, NULL
);
3013 /* Get device name (DisplayDevice is "\.\xxx") */
3014 for (LastSlash
= DisplayDevice
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
3016 if (DisplayDevice
->Buffer
[LastSlash
- 1] == L
'\\')
3022 DPRINT1("Invalid device name '%wZ'\n", DisplayDevice
);
3023 Status
= STATUS_OBJECT_NAME_INVALID
;
3026 ObjectName
= *DisplayDevice
;
3027 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
3028 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
3029 ObjectName
.Buffer
+= LastSlash
;
3031 /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
3032 KernelModeName
.MaximumLength
= Prefix
.Length
+ ObjectName
.Length
+ sizeof(UNICODE_NULL
);
3033 KernelModeName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
3034 KernelModeName
.MaximumLength
,
3036 if (!KernelModeName
.Buffer
)
3038 Status
= STATUS_NO_MEMORY
;
3041 RtlCopyUnicodeString(&KernelModeName
, &Prefix
);
3042 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
3043 if (!NT_SUCCESS(Status
))
3046 /* Open \??\xxx (ex: "\??\DISPLAY1") */
3047 InitializeObjectAttributes(&ObjectAttributes
,
3052 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
3055 if (!NT_SUCCESS(Status
))
3057 DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3058 Status
= STATUS_NO_SUCH_DEVICE
;
3062 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, &Length
);
3063 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
3065 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3066 Status
= STATUS_NO_SUCH_DEVICE
;
3069 VideoDeviceName
->MaximumLength
= Length
;
3070 VideoDeviceName
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
3071 VideoDeviceName
->MaximumLength
+ sizeof(UNICODE_NULL
),
3073 if (!VideoDeviceName
->Buffer
)
3075 Status
= STATUS_NO_MEMORY
;
3078 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, NULL
);
3079 VideoDeviceName
->Buffer
[VideoDeviceName
->MaximumLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
3080 if (!NT_SUCCESS(Status
))
3082 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3083 Status
= STATUS_NO_SUCH_DEVICE
;
3086 Status
= STATUS_SUCCESS
;
3089 if (!NT_SUCCESS(Status
) && VideoDeviceName
->Buffer
)
3090 ExFreePoolWithTag(VideoDeviceName
->Buffer
, TAG_DC
);
3091 if (KernelModeName
.Buffer
)
3092 ExFreePoolWithTag(KernelModeName
.Buffer
, TAG_DC
);
3094 ZwClose(LinkHandle
);
3098 static NTSTATUS FASTCALL
3099 GetVideoRegistryKey(
3100 OUT PUNICODE_STRING RegistryPath
,
3101 IN PCUNICODE_STRING DeviceName
) /* ex: "\Device\Video0" */
3103 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
3106 RtlInitUnicodeString(RegistryPath
, NULL
);
3107 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
3108 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
3109 QueryTable
[0].Name
= DeviceName
->Buffer
;
3110 QueryTable
[0].EntryContext
= RegistryPath
;
3112 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
3117 if (!NT_SUCCESS(Status
))
3119 DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName
, Status
);
3120 return STATUS_NO_SUCH_DEVICE
;
3123 DPRINT("RegistryPath %wZ\n", RegistryPath
);
3124 return STATUS_SUCCESS
;
3129 IntChangeDisplaySettings(
3130 IN PUNICODE_STRING pDeviceName OPTIONAL
,
3131 IN LPDEVMODEW DevMode
,
3133 IN PVOID lParam OPTIONAL
)
3135 BOOLEAN Global
= FALSE
;
3136 BOOLEAN NoReset
= FALSE
;
3137 BOOLEAN Reset
= FALSE
;
3138 BOOLEAN SetPrimary
= FALSE
;
3142 DPRINT1("display flags : %x\n",dwflags
);
3144 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3146 /* Check global, reset and noreset flags */
3147 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
3149 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
3151 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
3153 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
3155 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
3157 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
3159 if (Reset
&& NoReset
)
3160 return DISP_CHANGE_BADFLAGS
;
3164 /* Dynamically change graphics mode */
3165 DPRINT1("flag 0 UNIMPLEMENTED\n");
3166 return DISP_CHANGE_FAILED
;
3169 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
3171 /* Test reslution */
3172 dwflags
&= ~CDS_TEST
;
3173 DPRINT1("flag CDS_TEST UNIMPLEMENTED\n");
3174 Ret
= DISP_CHANGE_FAILED
;
3177 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
3181 dwflags
&= ~CDS_FULLSCREEN
;
3182 DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
3183 Ret
= DISP_CHANGE_FAILED
;
3185 RtlZeroMemory(&lpDevMode
, sizeof(DEVMODEW
));
3186 lpDevMode
.dmSize
= sizeof(DEVMODEW
);
3188 if (!IntEnumDisplaySettings(pDeviceName
, ENUM_CURRENT_SETTINGS
, &lpDevMode
, 0))
3189 return DISP_CHANGE_FAILED
;
3191 DPRINT1("Req Mode : %d x %d x %d\n", DevMode
->dmPelsWidth
,DevMode
->dmPelsHeight
,DevMode
->dmBitsPerPel
);
3192 DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode
.dmPelsWidth
,lpDevMode
.dmPelsHeight
, lpDevMode
.dmBitsPerPel
);
3195 if ((lpDevMode
.dmBitsPerPel
== DevMode
->dmBitsPerPel
) &&
3196 (lpDevMode
.dmPelsWidth
== DevMode
->dmPelsWidth
) &&
3197 (lpDevMode
.dmPelsHeight
== DevMode
->dmPelsHeight
))
3198 Ret
= DISP_CHANGE_SUCCESSFUL
;
3201 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
3203 dwflags
&= ~CDS_VIDEOPARAMETERS
;
3205 Ret
=DISP_CHANGE_BADPARAM
;
3208 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
3209 Ret
= DISP_CHANGE_FAILED
;
3214 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3217 UNICODE_STRING DeviceName
;
3218 UNICODE_STRING RegistryKey
;
3219 UNICODE_STRING InDeviceName
;
3220 OBJECT_ATTRIBUTES ObjectAttributes
;
3221 HANDLE DevInstRegKey
;
3224 DPRINT1("set CDS_UPDATEREGISTRY\n");
3226 dwflags
&= ~CDS_UPDATEREGISTRY
;
3228 /* Check if pDeviceName is NULL, we need to retrieve it */
3229 if (pDeviceName
== NULL
)
3231 WCHAR szBuffer
[MAX_DRIVER_NAME
];
3233 PWINDOW_OBJECT Wnd
=NULL
;
3237 hWnd
= IntGetDesktopWindow();
3238 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3243 hDC
= (HDC
)UserGetWindowDC(Wnd
);
3245 DC
= DC_LockDc(hDC
);
3250 swprintf (szBuffer
, L
"\\\\.\\DISPLAY%lu", ((GDIDEVICE
*)DC
->pPDev
)->DisplayNumber
);
3253 RtlInitUnicodeString(&InDeviceName
, szBuffer
);
3254 pDeviceName
= &InDeviceName
;
3257 Status
= GetVideoDeviceName(&DeviceName
, pDeviceName
);
3258 if (!NT_SUCCESS(Status
))
3260 DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName
, Status
);
3261 return DISP_CHANGE_FAILED
;
3263 Status
= GetVideoRegistryKey(&RegistryKey
, &DeviceName
);
3264 if (!NT_SUCCESS(Status
))
3266 DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName
, Status
);
3267 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3268 return DISP_CHANGE_FAILED
;
3270 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3272 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
3273 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3274 Status
= ZwOpenKey(&DevInstRegKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
);
3275 if (!NT_SUCCESS(Status
))
3277 DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey
, Status
);
3278 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
3279 return DISP_CHANGE_FAILED
;
3281 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
3283 /* Update needed fields */
3284 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
3286 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
3287 NewValue
= DevMode
->dmBitsPerPel
;
3288 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3291 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
3293 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
3294 NewValue
= DevMode
->dmPelsWidth
;
3295 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3298 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
3300 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
3301 NewValue
= DevMode
->dmPelsHeight
;
3302 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3305 ZwClose(DevInstRegKey
);
3306 if (NT_SUCCESS(Status
))
3307 Ret
= DISP_CHANGE_RESTART
;
3309 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
3310 Ret
= DISP_CHANGE_NOTUPDATED
;
3314 Ret
= DISP_CHANGE_BADFLAGS
;
3327 return DCB_RESET
; /* bounding rectangle always empty */
3338 return DCB_DISABLE
; /* bounding rectangle always empty */
3343 NtGdiGetAspectRatioFilterEx(HDC hDC
,
3357 PGDIDEVICE pPDev
, pGdiDevice
= (PGDIDEVICE
) hdev
;
3358 if (!pGdiDevice
) return NULL
;
3359 if ( pGdiDevice
< (PGDIDEVICE
)MmSystemRangeStart
) return NULL
;
3360 pPDev
= &PrimarySurface
;
3361 KeEnterCriticalRegion();
3364 if (pGdiDevice
== pPDev
) break;
3366 pPDev
= pPDev
->ppdevNext
;
3367 } while (pPDev
!= NULL
);
3368 KeLeaveCriticalRegion();
3369 if (!pPDev
) return NULL
;
3370 return pGdiDevice
->hPDev
;