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.
20 * DC.C - Device context functions
30 static GDIDEVICE PrimarySurface
;
31 static KEVENT VideoDriverNeedsPreparation
;
32 static KEVENT VideoDriverPrepared
;
38 KeInitializeEvent(&VideoDriverNeedsPreparation
, SynchronizationEvent
, TRUE
);
39 KeInitializeEvent(&VideoDriverPrepared
, NotificationEvent
, FALSE
);
40 return STATUS_SUCCESS
;
43 /* FIXME: DCs should probably be thread safe */
45 // --------------------------------------------------------- File Statics
47 // ----------------------------------------------------- Public Functions
50 NtGdiCancelDC(HDC hDC
)
57 NtGdiCreateCompatibleDC(HDC hDC
)
60 PDC_ATTR nDc_Attr
, oDc_Attr
;
62 HDC hNewDC
, DisplayDC
;
64 UNICODE_STRING DriverName
;
70 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
71 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
72 if (NULL
== DisplayDC
)
79 /* Allocate a new DC based on the original DC's device */
80 OrigDC
= DC_LockDc(hDC
);
83 if (NULL
!= DisplayDC
)
85 NtGdiDeleteObjectApp(DisplayDC
);
89 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
93 if (NULL
!= DisplayDC
)
95 NtGdiDeleteObjectApp(DisplayDC
);
99 NewDC
= DC_LockDc( hNewDC
);
101 oDc_Attr
= OrigDC
->pDc_Attr
;
102 if(!oDc_Attr
) oDc_Attr
= &OrigDC
->Dc_Attr
;
103 nDc_Attr
= NewDC
->pDc_Attr
;
104 if(!nDc_Attr
) nDc_Attr
= &NewDC
->Dc_Attr
;
106 /* Copy information from original DC to new DC */
107 NewDC
->hSelf
= hNewDC
;
109 NewDC
->PDev
= OrigDC
->PDev
;
111 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
113 /* DriverName is copied in the AllocDC routine */
114 nDc_Attr
->ptlWindowOrg
= oDc_Attr
->ptlWindowOrg
;
115 nDc_Attr
->szlWindowExt
= oDc_Attr
->szlWindowExt
;
116 nDc_Attr
->ptlViewportOrg
= oDc_Attr
->ptlViewportOrg
;
117 nDc_Attr
->szlViewportExt
= oDc_Attr
->szlViewportExt
;
119 /* Create default bitmap */
120 if (!(hBitmap
= IntGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
122 DC_UnlockDc( OrigDC
);
123 DC_UnlockDc( NewDC
);
125 if (NULL
!= DisplayDC
)
127 NtGdiDeleteObjectApp(DisplayDC
);
131 NewDC
->DC_Type
= DC_TYPE_MEMORY
; // Always!
132 NewDC
->w
.hBitmap
= hBitmap
;
133 NewDC
->w
.hFirstBitmap
= hBitmap
;
134 NewDC
->pPDev
= OrigDC
->pPDev
;
136 NewDC
->PalIndexed
= OrigDC
->PalIndexed
;
137 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
138 nDc_Attr
->lTextAlign
= oDc_Attr
->lTextAlign
;
139 nDc_Attr
->ulForegroundClr
= oDc_Attr
->ulForegroundClr
;
140 nDc_Attr
->ulBackgroundClr
= oDc_Attr
->ulBackgroundClr
;
141 nDc_Attr
->lBkMode
= oDc_Attr
->lBkMode
;
142 nDc_Attr
->crForegroundClr
= oDc_Attr
->crForegroundClr
;
143 nDc_Attr
->crBackgroundClr
= oDc_Attr
->crBackgroundClr
;
144 nDc_Attr
->jBkMode
= oDc_Attr
->jBkMode
;
145 nDc_Attr
->jROP2
= oDc_Attr
->jROP2
;
146 nDc_Attr
->dwLayout
= oDc_Attr
->dwLayout
;
147 if (oDc_Attr
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= oDc_Attr
->dwLayout
;
151 if (NULL
!= DisplayDC
)
153 NtGdiDeleteObjectApp(DisplayDC
);
156 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
157 IntGdiSelectVisRgn(hNewDC
, hVisRgn
);
158 NtGdiDeleteObject(hVisRgn
);
159 if (Layout
) NtGdiSetLayout( hNewDC
, -1, Layout
);
165 static BOOLEAN FASTCALL
166 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
168 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
169 WCHAR DeviceNameBuffer
[20];
172 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%lu", DisplayNumber
);
173 RtlInitUnicodeString(RegistryPath
, NULL
);
174 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
175 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
176 QueryTable
[0].Name
= DeviceNameBuffer
;
177 QueryTable
[0].EntryContext
= RegistryPath
;
179 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
184 if (! NT_SUCCESS(Status
))
186 DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
190 DPRINT("RegistryPath %wZ\n", RegistryPath
);
196 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
198 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
199 UNICODE_STRING RegistryPath
;
202 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
204 DPRINT("GetRegistryPath failed\n");
208 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
209 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
210 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
211 QueryTable
[0].EntryContext
= DriverFileNames
;
213 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
218 RtlFreeUnicodeString(&RegistryPath
);
219 if (! NT_SUCCESS(Status
))
221 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
225 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
230 static NTSTATUS STDCALL
231 DevModeCallback(IN PWSTR ValueName
,
234 IN ULONG ValueLength
,
236 IN PVOID EntryContext
)
238 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
240 DPRINT("Found registry value for name %S: type %d, length %d\n",
241 ValueName
, ValueType
, ValueLength
);
243 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
245 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
247 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
249 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
251 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
253 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
255 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
257 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
259 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
261 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
263 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
265 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
267 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
269 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
271 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
275 return STATUS_SUCCESS
;
279 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
281 UNICODE_STRING RegistryPath
;
282 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
284 BOOLEAN Valid
= TRUE
;
286 if (!GetRegistryPath(&RegistryPath
, DisplayNumber
))
288 DPRINT("GetRegistryPath failed\n");
292 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
293 QueryTable
[0].QueryRoutine
= DevModeCallback
;
294 QueryTable
[0].Flags
= 0;
295 QueryTable
[0].Name
= NULL
;
296 QueryTable
[0].EntryContext
= NULL
;
297 QueryTable
[0].DefaultType
= REG_NONE
;
298 QueryTable
[0].DefaultData
= NULL
;
299 QueryTable
[0].DefaultLength
= 0;
301 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
306 if (! NT_SUCCESS(Status
))
308 DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
309 &RegistryPath
, Status
);
314 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
315 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
316 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
317 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
318 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
320 DPRINT("Not all required devmode members are set\n");
325 RtlFreeUnicodeString(&RegistryPath
);
329 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
338 PGD_ENABLEDRIVER GDEnableDriver
;
340 UNICODE_STRING DriverFileNames
;
349 if (STATUS_SUCCESS
!= KeWaitForSingleObject(&VideoDriverNeedsPreparation
, Executive
, KernelMode
, TRUE
, &Zero
))
351 /* Concurrent access. Wait for VideoDriverPrepared event */
352 if (STATUS_SUCCESS
== KeWaitForSingleObject(&VideoDriverPrepared
, Executive
, KernelMode
, TRUE
, NULL
))
353 ret
= PrimarySurface
.PreparedDriver
;
356 // HAX! Fixme so I can support more than one! So how many?
357 for (DisplayNumber
= 0; ; DisplayNumber
++)
359 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
361 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
363 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
365 /* Open the miniport driver */
366 if (PrimarySurface
.VideoFileObject
== NULL
)
368 DPRINT1("FindMPDriver failed\n");
372 /* Retrieve DDI driver names from registry */
373 RtlInitUnicodeString(&DriverFileNames
, NULL
);
374 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
376 DPRINT1("FindDriverFileNames failed\n");
381 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
382 * scan all of them until a good one found.
384 CurrentName
= DriverFileNames
.Buffer
;
387 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
389 /* Get the DDI driver's entry point */
390 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
391 if (NULL
== GDEnableDriver
)
393 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
397 /* Call DDI driver's EnableDriver function */
398 RtlZeroMemory(&DED
, sizeof(DED
));
400 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
402 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
412 /* Skip to the next name but never get past the Unicode string */
413 while (L
'\0' != *CurrentName
&&
414 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
418 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
427 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
428 RtlFreeUnicodeString(&DriverFileNames
);
429 DPRINT1("No suitable DDI driver found\n");
433 DPRINT("Display driver %S loaded\n", CurrentName
);
435 RtlFreeUnicodeString(&DriverFileNames
);
437 DPRINT("Building DDI Functions\n");
439 /* Construct DDI driver function dispatch table */
440 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
442 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
443 DPRINT1("BuildDDIFunctions failed\n");
447 /* Allocate a phyical device handle from the driver */
448 // Support DMW.dmSize + DMW.dmDriverExtra & Alloc DMW then set prt pdmwDev.
449 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
450 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
452 PrimarySurface
.hPDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
456 PrimarySurface
.FillPatterns
,
457 sizeof(PrimarySurface
.GDIInfo
),
458 (ULONG
*) &PrimarySurface
.GDIInfo
,
459 sizeof(PrimarySurface
.DevInfo
),
460 &PrimarySurface
.DevInfo
,
463 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
464 DoDefault
= (NULL
== PrimarySurface
.hPDev
);
467 DPRINT1("DrvEnablePDev with registry parameters failed\n");
477 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
478 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
479 PrimarySurface
.hPDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
483 PrimarySurface
.FillPatterns
,
484 sizeof(PrimarySurface
.GDIInfo
),
485 (ULONG
*) &PrimarySurface
.GDIInfo
,
486 sizeof(PrimarySurface
.DevInfo
),
487 &PrimarySurface
.DevInfo
,
490 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
492 if (NULL
== PrimarySurface
.hPDev
)
494 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
495 DPRINT1("DrvEnablePDEV with default parameters failed\n");
496 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
500 // Update the primary surface with what we really got
501 PrimarySurface
.DMW
.dmPelsWidth
= PrimarySurface
.GDIInfo
.ulHorzRes
;
502 PrimarySurface
.DMW
.dmPelsHeight
= PrimarySurface
.GDIInfo
.ulVertRes
;
503 PrimarySurface
.DMW
.dmBitsPerPel
= PrimarySurface
.GDIInfo
.cBitsPixel
;
504 PrimarySurface
.DMW
.dmDisplayFrequency
= PrimarySurface
.GDIInfo
.ulVRefresh
;
507 if (!PrimarySurface
.DMW
.dmDriverExtra
)
509 PrimarySurface
.pdmwDev
= &PrimarySurface
.DMW
; // HAX!
513 DPRINT1("WARNING!!! Need to Alloc DMW !!!!!!\n");
515 // Dont remove until we finish testing other drivers.
516 DPRINT1("DMW extra %x !!!!!!\n",PrimarySurface
.DMW
.dmDriverExtra
);
518 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
520 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
521 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
523 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
525 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
526 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
529 PrimarySurface
.Pointer
.Exclude
.right
= -1;
531 DPRINT("calling completePDev\n");
533 /* Complete initialization of the physical device */
534 PrimarySurface
.DriverFunctions
.CompletePDEV(
535 PrimarySurface
.hPDev
,
536 (HDEV
)&PrimarySurface
);
538 DPRINT("calling DRIVER_ReferenceDriver\n");
540 DRIVER_ReferenceDriver(L
"DISPLAY");
542 PrimarySurface
.PreparedDriver
= TRUE
;
543 PrimarySurface
.DisplayNumber
= DisplayNumber
;
544 PrimarySurface
.flFlags
= PDEV_DISPLAY
; // Hard set,, add more flags.
545 PrimarySurface
.hsemDevLock
= (PERESOURCE
)EngCreateSemaphore();
546 // Should be null,, but make sure for now.
547 PrimarySurface
.pvGammaRamp
= NULL
;
548 PrimarySurface
.ppdevNext
= NULL
; // Fixme! We need to support more than display drvs.
549 PrimarySurface
.ppdevParent
= NULL
; // Always NULL if primary.
550 PrimarySurface
.pGraphicsDev
= NULL
; // Fixme!
556 KeSetEvent(&VideoDriverPrepared
, 1, FALSE
);
561 IntPrepareDriverIfNeeded()
563 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
571 IO_STATUS_BLOCK Iosb
;
573 ULONG Length
= sizeof(BOOL
);
574 PIO_STACK_LOCATION StackPtr
;
575 LARGE_INTEGER StartOffset
;
576 PFILE_OBJECT FileObject
= PrimarySurface
.VideoFileObject
;
577 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
579 DPRINT("PrepareVideoPrt() called\n");
581 KeClearEvent(&PrimarySurface
.VideoFileObject
->Event
);
583 ObReferenceObjectByPointer(FileObject
, 0, IoFileObjectType
, KernelMode
);
585 StartOffset
.QuadPart
= 0;
586 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
598 /* Set up IRP Data */
599 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
600 Irp
->RequestorMode
= KernelMode
;
601 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
602 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= NULL
;
603 Irp
->Flags
|= IRP_WRITE_OPERATION
;
605 /* Setup Stack Data */
606 StackPtr
= IoGetNextIrpStackLocation(Irp
);
607 StackPtr
->FileObject
= PrimarySurface
.VideoFileObject
;
608 StackPtr
->Parameters
.Write
.Key
= 0;
610 Status
= IoCallDriver(DeviceObject
, Irp
);
612 if (STATUS_PENDING
== Status
)
614 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, TRUE
, 0);
615 Status
= Iosb
.Status
;
618 return NT_SUCCESS(Status
);
622 IntCreatePrimarySurface()
629 if (! IntPrepareDriverIfNeeded())
634 if (! PrepareVideoPrt())
639 DPRINT("calling EnableSurface\n");
640 /* Enable the drawing surface */
641 PrimarySurface
.pSurface
=
642 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.hPDev
);
643 if (NULL
== PrimarySurface
.pSurface
)
645 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.hPDev, FALSE);*/
646 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
647 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
648 DPRINT1("DrvEnableSurface failed\n");
652 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, TRUE
);
654 calledFromUser
= UserIsEntered(); //fixme: possibly upgrade a shared lock
655 if (!calledFromUser
){
656 UserEnterExclusive();
660 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
662 SurfObj
= EngLockSurface(PrimarySurface
.pSurface
);
663 SurfObj
->dhpdev
= PrimarySurface
.hPDev
;
664 SurfSize
= SurfObj
->sizlBitmap
;
665 SurfaceRect
.left
= SurfaceRect
.top
= 0;
666 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
667 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
668 /* FIXME - why does EngEraseSurface() sometimes crash?
669 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
671 /* Put the pointer in the center of the screen */
672 GDIDEV(SurfObj
)->Pointer
.Pos
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
673 GDIDEV(SurfObj
)->Pointer
.Pos
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
675 EngUnlockSurface(SurfObj
);
676 co_IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
678 if (!calledFromUser
){
686 IntDestroyPrimarySurface()
690 DRIVER_UnreferenceDriver(L
"DISPLAY");
692 calledFromUser
= UserIsEntered();
693 if (!calledFromUser
){
694 UserEnterExclusive();
698 IntDetachMonitor(&PrimarySurface
);
700 if (!calledFromUser
){
705 * FIXME: Hide a mouse pointer there. Also because we have to prevent
706 * memory leaks with the Eng* mouse routines.
709 DPRINT("Reseting display\n" );
710 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, FALSE
);
711 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.hPDev
);
712 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
713 PrimarySurface
.PreparedDriver
= FALSE
;
714 KeSetEvent(&VideoDriverNeedsPreparation
, 1, FALSE
);
715 KeResetEvent(&VideoDriverPrepared
);
719 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
723 IntGdiCreateDC(PUNICODE_STRING Driver
,
724 PUNICODE_STRING Device
,
726 CONST PDEVMODEW InitData
,
734 UNICODE_STRING StdDriver
;
737 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
739 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
741 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
745 if (! IntPrepareDriverIfNeeded())
747 /* Here, we have two possibilities:
748 * a) return NULL, and hope that the caller
749 * won't call us in a loop
750 * b) bugcheck, but caller is unable to
751 * react on the problem
753 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
755 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
760 calledFromUser
= UserIsEntered();
761 if (!calledFromUser
){
762 UserEnterExclusive();
765 if (! co_IntGraphicsCheck(TRUE
))
767 if (!calledFromUser
){
770 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
774 if (!calledFromUser
){
781 /* Check for existing DC object */
782 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
785 return NtGdiCreateCompatibleDC(hDC
);
788 /* Allocate a DC object */
789 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
794 NewDC
= DC_LockDc( hNewDC
);
801 nDc_Attr
= NewDC
->pDc_Attr
;
802 if(!nDc_Attr
) nDc_Attr
= &NewDC
->Dc_Attr
;
804 NewDC
->DC_Type
= DC_TYPE_DIRECT
;
806 NewDC
->PDev
= PrimarySurface
.hPDev
;
807 if(pUMdhpdev
) pUMdhpdev
= NewDC
->PDev
; // set DHPDEV for device.
808 NewDC
->pPDev
= (PVOID
)&PrimarySurface
;
809 NewDC
->w
.hBitmap
= (HBITMAP
)PrimarySurface
.pSurface
;
811 NewDC
->w
.bitsPerPixel
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.cBitsPixel
*
812 ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.cPlanes
;
813 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
815 NewDC
->flGraphics
= PrimarySurface
.DevInfo
.flGraphicsCaps
;
816 NewDC
->flGraphics2
= PrimarySurface
.DevInfo
.flGraphicsCaps2
;
820 NewDC
->PalIndexed
= NtGdiGetStockObject(DEFAULT_PALETTE
);
821 NewDC
->w
.hPalette
= PrimarySurface
.DevInfo
.hpalDefault
;
822 nDc_Attr
->jROP2
= R2_COPYPEN
;
824 NewDC
->erclWindow
.top
= NewDC
->erclWindow
.left
= 0;
825 NewDC
->erclWindow
.right
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulHorzRes
;
826 NewDC
->erclWindow
.bottom
= ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulVertRes
;
828 DC_UnlockDc( NewDC
);
830 hVisRgn
= NtGdiCreateRectRgn(0, 0, ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulHorzRes
,
831 ((PGDIDEVICE
)NewDC
->pPDev
)->GDIInfo
.ulVertRes
);
832 IntGdiSelectVisRgn(hNewDC
, hVisRgn
);
833 NtGdiDeleteObject(hVisRgn
);
835 /* Initialize the DC state */
837 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
838 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
839 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
840 NtGdiSetBkMode(hNewDC
, OPAQUE
);
845 The CreateIC function creates an information context for the specified device.
846 The information context provides a fast way to get information about the
847 device without creating a device context (DC). However, GDI drawing functions
848 cannot accept a handle to an information context.
850 NewDC
->DC_Type
= DC_TYPE_INFO
;
851 DC_UnlockDc( NewDC
);
857 NtGdiOpenDCW( PUNICODE_STRING Device
,
859 PUNICODE_STRING pustrLogAddr
,
865 UNICODE_STRING SafeDevice
;
866 DEVMODEW SafeInitData
;
869 NTSTATUS Status
= STATUS_SUCCESS
;
877 ProbeForWrite(pUMdhpdev
,
881 ProbeForRead(InitData
,
884 RtlCopyMemory(&SafeInitData
,
890 Status
= _SEH_GetExceptionCode();
893 if(!NT_SUCCESS(Status
))
895 SetLastNtError(Status
);
898 /* FIXME - InitData can have some more bytes! */
903 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
904 if(!NT_SUCCESS(Status
))
906 SetLastNtError(Status
);
911 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
913 pUMdhpdev
? &Dhpdev
: NULL
,
914 InitData
? &SafeInitData
: NULL
,
915 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
917 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
928 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 // if(!UserReleaseDC(NULL, hDC, FALSE)) Ret = FALSE;
950 /* First delete all saved DCs */
951 while (DCToDelete
->saveLevel
)
956 savedHDC
= DC_GetNextDC (DCToDelete
);
957 savedDC
= DC_LockDc (savedHDC
);
962 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
963 DCToDelete
->saveLevel
--;
964 DC_UnlockDc( savedDC
);
965 NtGdiDeleteObjectApp (savedHDC
);
968 /* Free GDI resources allocated to this DC */
969 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
972 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
973 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
974 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
975 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
976 if (DCToDelete
->DC_Type
== DC_TYPE_MEMORY
)
978 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
980 if (DCToDelete
->XlateBrush
!= NULL
)
981 EngDeleteXlate(DCToDelete
->XlateBrush
);
982 if (DCToDelete
->XlatePen
!= NULL
)
983 EngDeleteXlate(DCToDelete
->XlatePen
);
985 if (DCToDelete
->w
.hClipRgn
)
987 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
989 if (DCToDelete
->w
.hVisRgn
)
991 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
993 if (NULL
!= DCToDelete
->CombinedClip
)
995 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
997 if (DCToDelete
->w
.hGCClipRgn
)
999 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
1002 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
1005 DC_UnlockDc( DCToDelete
);
1012 NtGdiDeleteObjectApp(HANDLE DCHandle
)
1015 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
1017 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
1018 return NtGdiDeleteObject((HGDIOBJ
) DCHandle
);
1020 if(IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
1022 if (!GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, DCHandle
))
1024 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1028 return IntGdiDeleteDC(DCHandle
, FALSE
);
1037 IN OPTIONAL LPSTR pjIn
)
1049 OUT OPTIONAL PVOID pvBuf
)
1057 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
1063 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
1064 if(!hDC
) return NULL
;
1066 if(!(dc
= DC_LockDc(hDC
)))
1068 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1071 Dc_Attr
= dc
->pDc_Attr
;
1072 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1075 case GDI_OBJECT_TYPE_EXTPEN
:
1076 case GDI_OBJECT_TYPE_PEN
:
1077 SelObject
= Dc_Attr
->hpen
;
1079 case GDI_OBJECT_TYPE_BRUSH
:
1080 SelObject
= Dc_Attr
->hbrush
;
1082 case GDI_OBJECT_TYPE_PALETTE
:
1083 SelObject
= dc
->w
.hPalette
;
1085 case GDI_OBJECT_TYPE_FONT
:
1086 SelObject
= Dc_Attr
->hlfntNew
;
1088 case GDI_OBJECT_TYPE_BITMAP
:
1089 SelObject
= dc
->w
.hBitmap
;
1091 case GDI_OBJECT_TYPE_COLORSPACE
:
1092 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1097 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1106 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1108 Point
->x
= dc
->w
.DCOrgX
;
1109 Point
->y
= dc
->w
.DCOrgY
;
1115 NtGdiGetDCPoint( HDC hDC
, UINT iPoint
, PPOINTL Point
)
1121 NTSTATUS Status
= STATUS_SUCCESS
;
1125 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1129 RtlZeroMemory(&SafePoint
, sizeof(POINT
));
1131 dc
= DC_LockDc(hDC
);
1134 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1140 case GdiGetViewPortExt
:
1141 IntGetViewportExtEx(dc
, &Size
);
1142 SafePoint
.x
= Size
.cx
;
1143 SafePoint
.y
= Size
.cy
;
1145 case GdiGetWindowExt
:
1146 IntGetWindowExtEx(dc
, &Size
);
1147 SafePoint
.x
= Size
.cx
;
1148 SafePoint
.y
= Size
.cy
;
1150 case GdiGetViewPortOrg
:
1151 IntGetViewportOrgEx(dc
, &SafePoint
);
1153 case GdiGetWindowOrg
:
1154 IntGetWindowOrgEx(dc
, &SafePoint
);
1157 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1159 case GdiGetAspectRatioFilter
:
1161 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1170 ProbeForWrite(Point
,
1177 Status
= _SEH_GetExceptionCode();
1182 if(!NT_SUCCESS(Status
))
1184 SetLastNtError(Status
);
1195 IntGdiCopyToSaveState(PDC dc
, PDC newdc
)
1197 PDC_ATTR Dc_Attr
, nDc_Attr
;
1199 Dc_Attr
= dc
->pDc_Attr
;
1200 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1201 nDc_Attr
= newdc
->pDc_Attr
;
1202 if(!nDc_Attr
) nDc_Attr
= &newdc
->Dc_Attr
;
1204 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1205 nDc_Attr
->dwLayout
= Dc_Attr
->dwLayout
;
1206 nDc_Attr
->hpen
= Dc_Attr
->hpen
;
1207 nDc_Attr
->hbrush
= Dc_Attr
->hbrush
;
1208 nDc_Attr
->hlfntNew
= Dc_Attr
->hlfntNew
;
1209 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1210 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1211 newdc
->PalIndexed
= dc
->PalIndexed
;
1212 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1213 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1214 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1215 nDc_Attr
->jROP2
= Dc_Attr
->jROP2
;
1216 nDc_Attr
->jFillMode
= Dc_Attr
->jFillMode
;
1217 nDc_Attr
->jStretchBltMode
= Dc_Attr
->jStretchBltMode
;
1218 nDc_Attr
->lRelAbs
= Dc_Attr
->lRelAbs
;
1219 nDc_Attr
->jBkMode
= Dc_Attr
->jBkMode
;
1220 nDc_Attr
->lBkMode
= Dc_Attr
->lBkMode
;
1221 nDc_Attr
->crBackgroundClr
= Dc_Attr
->crBackgroundClr
;
1222 nDc_Attr
->crForegroundClr
= Dc_Attr
->crForegroundClr
;
1223 nDc_Attr
->ulBackgroundClr
= Dc_Attr
->ulBackgroundClr
;
1224 nDc_Attr
->ulForegroundClr
= Dc_Attr
->ulForegroundClr
;
1225 nDc_Attr
->ptlBrushOrigin
= Dc_Attr
->ptlBrushOrigin
;
1226 nDc_Attr
->lTextAlign
= Dc_Attr
->lTextAlign
;
1227 nDc_Attr
->lTextExtra
= Dc_Attr
->lTextExtra
;
1228 nDc_Attr
->cBreak
= Dc_Attr
->cBreak
;
1229 nDc_Attr
->lBreakExtra
= Dc_Attr
->lBreakExtra
;
1230 nDc_Attr
->iMapMode
= Dc_Attr
->iMapMode
;
1231 nDc_Attr
->iGraphicsMode
= Dc_Attr
->iGraphicsMode
;
1233 /* Apparently, the DC origin is not changed by [GS]etDCState */
1234 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1235 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1237 nDc_Attr
->ptlCurrent
= Dc_Attr
->ptlCurrent
;
1238 nDc_Attr
->ptfxCurrent
= Dc_Attr
->ptfxCurrent
;
1239 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1240 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1241 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1242 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1243 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1244 nDc_Attr
->ptlWindowOrg
= Dc_Attr
->ptlWindowOrg
;
1245 nDc_Attr
->szlWindowExt
= Dc_Attr
->szlWindowExt
;
1246 nDc_Attr
->ptlViewportOrg
= Dc_Attr
->ptlViewportOrg
;
1247 nDc_Attr
->szlViewportExt
= Dc_Attr
->szlViewportExt
;
1249 newdc
->saveLevel
= 0;
1250 newdc
->DC_Type
= dc
->DC_Type
;
1253 PATH_InitGdiPath( &newdc
->w
.path
);
1256 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1258 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1261 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1262 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1269 IntGdiCopyFromSaveState(PDC dc
, PDC dcs
, HDC hDC
)
1271 PDC_ATTR Dc_Attr
, sDc_Attr
;
1273 Dc_Attr
= dc
->pDc_Attr
;
1274 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
1275 sDc_Attr
= dcs
->pDc_Attr
;
1276 if(!sDc_Attr
) sDc_Attr
= &dcs
->Dc_Attr
;
1278 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1280 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1282 Dc_Attr
->dwLayout
= sDc_Attr
->dwLayout
;
1283 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1284 Dc_Attr
->jROP2
= sDc_Attr
->jROP2
;
1285 Dc_Attr
->jFillMode
= sDc_Attr
->jFillMode
;
1286 Dc_Attr
->jStretchBltMode
= sDc_Attr
->jStretchBltMode
;
1287 Dc_Attr
->lRelAbs
= sDc_Attr
->lRelAbs
;
1288 Dc_Attr
->jBkMode
= sDc_Attr
->jBkMode
;
1289 Dc_Attr
->crBackgroundClr
= sDc_Attr
->crBackgroundClr
;
1290 Dc_Attr
->crForegroundClr
= sDc_Attr
->crForegroundClr
;
1291 Dc_Attr
->lBkMode
= sDc_Attr
->lBkMode
;
1292 Dc_Attr
->ulBackgroundClr
= sDc_Attr
->ulBackgroundClr
;
1293 Dc_Attr
->ulForegroundClr
= sDc_Attr
->ulForegroundClr
;
1294 Dc_Attr
->ptlBrushOrigin
= sDc_Attr
->ptlBrushOrigin
;
1296 Dc_Attr
->lTextAlign
= sDc_Attr
->lTextAlign
;
1297 Dc_Attr
->lTextExtra
= sDc_Attr
->lTextExtra
;
1298 Dc_Attr
->cBreak
= sDc_Attr
->cBreak
;
1299 Dc_Attr
->lBreakExtra
= sDc_Attr
->lBreakExtra
;
1300 Dc_Attr
->iMapMode
= sDc_Attr
->iMapMode
;
1301 Dc_Attr
->iGraphicsMode
= sDc_Attr
->iGraphicsMode
;
1303 /* Apparently, the DC origin is not changed by [GS]etDCState */
1304 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1305 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1307 Dc_Attr
->ptlCurrent
= sDc_Attr
->ptlCurrent
;
1308 Dc_Attr
->ptfxCurrent
= sDc_Attr
->ptfxCurrent
;
1309 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1310 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1311 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1312 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1313 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1314 Dc_Attr
->ptlWindowOrg
= sDc_Attr
->ptlWindowOrg
;
1315 Dc_Attr
->szlWindowExt
= sDc_Attr
->szlWindowExt
;
1316 Dc_Attr
->ptlViewportOrg
= sDc_Attr
->ptlViewportOrg
;
1317 Dc_Attr
->szlViewportExt
= sDc_Attr
->szlViewportExt
;
1318 dc
->PalIndexed
= dcs
->PalIndexed
;
1320 if (dc
->DC_Type
!= DC_TYPE_MEMORY
)
1322 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1326 if (dcs
->w
.hClipRgn
)
1328 if (!dc
->w
.hClipRgn
)
1330 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1332 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1338 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1344 res
= CLIPPING_UpdateGCRegion( dc
);
1345 ASSERT ( res
!= ERROR
);
1349 IntGdiExtSelectClipRgn(dc
, dcs
->w
.hClipRgn
, RGN_COPY
);
1352 if(!hDC
) return; // Not a MemoryDC or SaveLevel DC, return.
1354 NtGdiSelectBitmap( hDC
, dcs
->w
.hBitmap
);
1355 NtGdiSelectBrush( hDC
, sDc_Attr
->hbrush
);
1356 NtGdiSelectFont( hDC
, sDc_Attr
->hlfntNew
);
1357 NtGdiSelectPen( hDC
, sDc_Attr
->hpen
);
1359 NtGdiSetBkColor( hDC
, sDc_Attr
->crBackgroundClr
);
1360 NtGdiSetTextColor( hDC
, sDc_Attr
->crForegroundClr
);
1362 NtUserSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1365 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1370 IntGdiGetDCState(HDC hDC
)
1375 dc
= DC_LockDc(hDC
);
1378 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1382 hnewdc
= DC_AllocDC(NULL
);
1388 newdc
= DC_LockDc( hnewdc
);
1389 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1392 newdc
->hSelf
= hnewdc
;
1393 IntGdiCopyToSaveState( dc
, newdc
);
1395 DC_UnlockDc( newdc
);
1403 IntGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1407 dc
= DC_LockDc ( hDC
);
1410 dcs
= DC_LockDc ( hDCSave
);
1413 if ( dcs
->w
.flags
& DC_SAVED
)
1415 IntGdiCopyFromSaveState( dc
, dcs
, dc
->hSelf
);
1421 DC_UnlockDc ( dcs
);
1426 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1430 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1434 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1439 /* Retrieve capability */
1443 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVersion
;
1447 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulTechnology
;
1451 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
;
1455 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
;
1459 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
1463 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
1467 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulLogPixelsX
;
1471 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulLogPixelsY
;
1475 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.cBitsPixel
;
1479 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.cPlanes
;
1483 UNIMPLEMENTED
; /* FIXME */
1487 UNIMPLEMENTED
; /* FIXME */
1491 UNIMPLEMENTED
; /* FIXME */
1495 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulNumColors
;
1499 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectX
;
1503 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectY
;
1507 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulAspectXY
;
1511 UNIMPLEMENTED
; /* FIXME */
1515 UNIMPLEMENTED
; /* FIXME */
1519 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulNumPalReg
; /* FIXME not sure */
1527 UNIMPLEMENTED
; /* FIXME */
1531 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1541 case PHYSICALHEIGHT
:
1542 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1552 case PHYSICALOFFSETX
:
1553 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1563 case PHYSICALOFFSETY
:
1564 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1575 UNIMPLEMENTED
; /* FIXME */
1578 case SCALINGFACTORX
:
1579 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1589 case SCALINGFACTORY
:
1590 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1601 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.flRaster
;
1605 UNIMPLEMENTED
; /* FIXME */
1609 UNIMPLEMENTED
; /* FIXME */
1613 UNIMPLEMENTED
; /* FIXME */
1617 ret
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.flTextCaps
;
1629 NtGdiGetDeviceCaps(HDC hDC
,
1635 dc
= DC_LockDc(hDC
);
1638 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1642 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1644 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1652 IntGdiGetObject(IN HANDLE Handle
,
1660 pGdiObject
= GDIOBJ_LockObj(GdiHandleTable
, Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1663 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1667 dwObjectType
= GDIOBJ_GetObjectType(Handle
);
1668 switch (dwObjectType
)
1670 case GDI_OBJECT_TYPE_PEN
:
1671 case GDI_OBJECT_TYPE_EXTPEN
:
1672 Result
= PEN_GetObject((PGDIBRUSHOBJ
) pGdiObject
, cbCount
, (PLOGPEN
) lpBuffer
); // IntGdiCreatePenIndirect
1675 case GDI_OBJECT_TYPE_BRUSH
:
1676 Result
= BRUSH_GetObject((PGDIBRUSHOBJ
) pGdiObject
, cbCount
, (LPLOGBRUSH
)lpBuffer
);
1679 case GDI_OBJECT_TYPE_BITMAP
:
1680 Result
= BITMAP_GetObject((BITMAPOBJ
*) pGdiObject
, cbCount
, lpBuffer
);
1682 case GDI_OBJECT_TYPE_FONT
:
1683 Result
= FontGetObject((PTEXTOBJ
) pGdiObject
, cbCount
, lpBuffer
);
1685 // Fix the LOGFONT structure for the stock fonts
1686 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1688 FixStockFontSizeW(Handle
, cbCount
, lpBuffer
);
1693 case GDI_OBJECT_TYPE_PALETTE
:
1694 Result
= PALETTE_GetObject((PPALGDI
) pGdiObject
, cbCount
, lpBuffer
);
1698 DPRINT1("GDI object type 0x%08x not implemented\n", dwObjectType
);
1702 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, pGdiObject
);
1709 NtGdiExtGetObjectW(IN HANDLE hGdiObj
,
1711 OUT LPVOID lpBuffer
)
1718 DIBSECTION dibsection
;
1722 EXTLOGFONTW extlogfontw
;
1723 ENUMLOGFONTEXDVW enumlogfontexdvw
;
1726 // Normalize to the largest supported object size
1727 cbCount
= min((UINT
)cbCount
, sizeof(Object
));
1729 // Now do the actual call
1730 iRetCount
= IntGdiGetObject(hGdiObj
, cbCount
, lpBuffer
? &Object
: NULL
);
1731 cbCopyCount
= min((UINT
)cbCount
, (UINT
)iRetCount
);
1733 // Make sure we have a buffer and a copy size
1734 if ((cbCopyCount
) && (lpBuffer
))
1736 // Enter SEH for buffer transfer
1739 // Probe the buffer and copy it
1740 ProbeForWrite(lpBuffer
, cbCopyCount
, sizeof(WORD
));
1741 RtlCopyMemory(lpBuffer
, &Object
, cbCopyCount
);
1745 // Clear the return value.
1746 // Do *NOT* set last error here!
1760 OUT PBOOL pbBanding
,
1761 IN OPTIONAL VOID
*pDriverInfo2
,
1762 OUT VOID
*ppUMdhpdev
)
1769 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1774 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1776 dc
= DC_LockDc(hDC
);
1779 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1784 SaveLevel
= dc
->saveLevel
+ SaveLevel
+ 1;
1786 if(SaveLevel
< 0 || dc
->saveLevel
<SaveLevel
)
1793 while (dc
->saveLevel
>= SaveLevel
)
1795 HDC hdcs
= DC_GetNextDC (dc
);
1797 dcs
= DC_LockDc (hdcs
);
1804 DC_SetNextDC (dc
, DC_GetNextDC (dcs
));
1807 if (--dc
->saveLevel
< SaveLevel
)
1812 IntGdiSetDCState(hDC
, hdcs
);
1814 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1816 /* FIXME: This might not be quite right, since we're
1817 * returning FALSE but still destroying the saved DC state */
1820 dc
= DC_LockDc(hDC
);
1830 NtGdiDeleteObjectApp (hdcs
);
1838 NtGdiSaveDC(HDC hDC
)
1844 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
1846 if (!(hdcs
= IntGdiGetDCState(hDC
)))
1851 dcs
= DC_LockDc (hdcs
);
1854 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1857 dc
= DC_LockDc (hDC
);
1861 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1866 /* Copy path. The reason why path saving / restoring is in SaveDC/
1867 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1868 * functions are only in Win16 (which doesn't have paths) and that
1869 * SetDCState doesn't allow us to signal an error (which can happen
1870 * when copying paths).
1872 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
1874 NtGdiDeleteObjectApp (hdcs
);
1880 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
1881 DC_SetNextDC (dc
, hdcs
);
1882 ret
= ++dc
->saveLevel
;
1904 PGDIBRUSHOBJ pBrush
;
1906 if (hDC
== NULL
|| hBmp
== NULL
) return NULL
;
1908 pDC
= DC_LockDc(hDC
);
1914 pDc_Attr
= pDC
->pDc_Attr
;
1915 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
1917 /* must be memory dc to select bitmap */
1918 if (pDC
->DC_Type
!= DC_TYPE_MEMORY
)
1924 pBmp
= BITMAPOBJ_LockBitmap(hBmp
);
1930 hOrgBmp
= pDC
->w
.hBitmap
;
1932 /* Release the old bitmap, lock the new one and convert it to a SURF */
1933 pDC
->w
.hBitmap
= hBmp
;
1935 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1938 pDC
->w
.bitsPerPixel
= pBmp
->dib
->dsBmih
.biBitCount
;
1939 pDC
->w
.hPalette
= pBmp
->hDIBPalette
;
1943 pDC
->w
.bitsPerPixel
= BitsPerFormat(pBmp
->SurfObj
.iBitmapFormat
);
1944 pDC
->w
.hPalette
= ((GDIDEVICE
*)pDC
->pPDev
)->DevInfo
.hpalDefault
;
1947 /* Regenerate the XLATEOBJs. */
1948 pBrush
= BRUSHOBJ_LockBrush(pDc_Attr
->hbrush
);
1951 if (pDC
->XlateBrush
)
1953 EngDeleteXlate(pDC
->XlateBrush
);
1955 pDC
->XlateBrush
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
1956 BRUSHOBJ_UnlockBrush(pBrush
);
1959 pBrush
= PENOBJ_LockPen(pDc_Attr
->hpen
);
1964 EngDeleteXlate(pDC
->XlatePen
);
1966 pDC
->XlatePen
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
1967 PENOBJ_UnlockPen(pBrush
);
1972 hVisRgn
= NtGdiCreateRectRgn(0, 0, pBmp
->SurfObj
.sizlBitmap
.cx
, pBmp
->SurfObj
.sizlBitmap
.cy
);
1973 BITMAPOBJ_UnlockBitmap(pBmp
);
1974 IntGdiSelectVisRgn(hDC
, hVisRgn
);
1975 NtGdiDeleteObject(hVisRgn
);
1992 PGDIBRUSHOBJ pBrush
;
1996 if (hDC
== NULL
|| hBrush
== NULL
) return NULL
;
1998 pDC
= DC_LockDc(hDC
);
2004 pDc_Attr
= pDC
->pDc_Attr
;
2005 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2007 pBrush
= BRUSHOBJ_LockBrush(hBrush
);
2010 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2014 XlateObj
= IntGdiCreateBrushXlate(pDC
, pBrush
, &bFailed
);
2015 BRUSHOBJ_UnlockBrush(pBrush
);
2021 hOrgBrush
= pDc_Attr
->hbrush
;
2022 pDc_Attr
->hbrush
= hBrush
;
2023 if (pDC
->XlateBrush
!= NULL
)
2025 EngDeleteXlate(pDC
->XlateBrush
);
2027 pDC
->XlateBrush
= XlateObj
;
2044 HFONT hOrgFont
= NULL
;
2046 if (hDC
== NULL
|| hFont
== NULL
) return NULL
;
2048 pDC
= DC_LockDc(hDC
);
2054 pDc_Attr
= pDC
->pDc_Attr
;
2055 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2057 /* FIXME: what if not successful? */
2058 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hFont
)))
2060 hOrgFont
= pDc_Attr
->hlfntNew
;
2061 pDc_Attr
->hlfntNew
= hFont
;
2080 HPEN hOrgPen
= NULL
;
2085 if (hDC
== NULL
|| hPen
== NULL
) return NULL
;
2087 pDC
= DC_LockDc(hDC
);
2093 pDc_Attr
= pDC
->pDc_Attr
;
2094 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
2096 pPen
= PENOBJ_LockPen(hPen
);
2102 XlateObj
= IntGdiCreateBrushXlate(pDC
, pPen
, &bFailed
);
2103 PENOBJ_UnlockPen(pPen
);
2106 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2110 hOrgPen
= pDc_Attr
->hpen
;
2111 pDc_Attr
->hpen
= hPen
;
2112 if (pDC
->XlatePen
!= NULL
)
2114 EngDeleteXlate(pDC
->XlatePen
);
2116 pDC
->XlatePen
= XlateObj
;
2124 IntGdiSetHookFlags(HDC hDC
, WORD Flags
)
2127 DC
*dc
= DC_LockDc(hDC
);
2131 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2135 wRet
= dc
->w
.flags
& DC_DIRTY
;
2137 /* "Undocumented Windows" info is slightly confusing.
2140 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2142 if (Flags
& DCHF_INVALIDATEVISRGN
)
2144 dc
->w
.flags
|= DC_DIRTY
;
2146 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2148 dc
->w
.flags
&= ~DC_DIRTY
;
2169 DWORD SafeResult
= 0;
2170 NTSTATUS Status
= STATUS_SUCCESS
;
2174 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2178 dc
= DC_LockDc(hDC
);
2181 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2184 Dc_Attr
= dc
->pDc_Attr
;
2185 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2192 SafeResult
= Dc_Attr
->lRelAbs
;
2194 case GdiGetBreakExtra
:
2195 SafeResult
= Dc_Attr
->lBreakExtra
;
2197 case GdiGerCharBreak
:
2198 SafeResult
= Dc_Attr
->cBreak
;
2200 case GdiGetArcDirection
:
2201 SafeResult
= dc
->w
.ArcDirection
;
2203 case GdiGetEMFRestorDc
:
2205 case GdiGetFontLanguageInfo
:
2208 SafeResult
= dc
->DC_Type
;
2211 SafeResult
= Dc_Attr
->iMapMode
;
2213 case GdiGetTextCharExtra
:
2214 SafeResult
= Dc_Attr
->lTextExtra
;
2217 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2226 ProbeForWrite(Result
,
2229 *Result
= SafeResult
;
2233 Status
= _SEH_GetExceptionCode();
2238 if(!NT_SUCCESS(Status
))
2240 SetLastNtError(Status
);
2251 NtGdiGetAndSetDCDword(
2262 DWORD SafeResult
= 0;
2263 NTSTATUS Status
= STATUS_SUCCESS
;
2267 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2271 dc
= DC_LockDc(hDC
);
2274 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2277 Dc_Attr
= dc
->pDc_Attr
;
2278 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2282 case GdtGetSetCopyCount
:
2284 case GdiGetSetTextAlign
:
2285 SafeResult
= Dc_Attr
->lTextAlign
;
2286 Dc_Attr
->lTextAlign
= dwIn
;
2287 // Dc_Attr->flTextAlign = dwIn; // Flags!
2289 case GdiGetSetRelAbs
:
2290 SafeResult
= Dc_Attr
->lRelAbs
;
2291 Dc_Attr
->lRelAbs
= dwIn
;
2293 case GdiGetSetTextCharExtra
:
2294 SafeResult
= Dc_Attr
->lTextExtra
;
2295 Dc_Attr
->lTextExtra
= dwIn
;
2297 case GdiGetSetSelectFont
:
2299 case GdiGetSetMapperFlagsInternal
:
2301 case GdiGetSetMapMode
:
2302 SafeResult
= IntGdiSetMapMode( dc
, dwIn
);
2304 case GdiGetSetArcDirection
:
2305 if (dwIn
!= AD_COUNTERCLOCKWISE
&& dwIn
!= AD_CLOCKWISE
)
2307 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2310 SafeResult
= dc
->w
.ArcDirection
;
2311 dc
->w
.ArcDirection
= dwIn
;
2314 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2323 ProbeForWrite(Result
,
2326 *Result
= SafeResult
;
2330 Status
= _SEH_GetExceptionCode();
2335 if(!NT_SUCCESS(Status
))
2337 SetLastNtError(Status
);
2346 // ---------------------------------------------------- Private Interface
2349 DC_AllocDC(PUNICODE_STRING Driver
)
2358 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2363 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2366 hDC
= (HDC
) GDIOBJ_AllocObj(GdiHandleTable
, GDI_OBJECT_TYPE_DC
);
2376 DC_AllocateDcAttr(hDC
);
2378 NewDC
= DC_LockDc(hDC
);
2379 /* FIXME - Handle NewDC == NULL! */
2382 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2383 NewDC
->DriverName
.Buffer
= Buf
;
2385 Dc_Attr
= NewDC
->pDc_Attr
;
2386 if(!Dc_Attr
) Dc_Attr
= &NewDC
->Dc_Attr
;
2388 NewDC
->hHmgr
= (HGDIOBJ
) hDC
; // Save the handle for this DC object.
2389 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2390 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2391 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2392 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2393 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2394 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2395 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2396 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2397 NewDC
->w
.vport2WorldValid
= TRUE
;
2399 // Setup syncing bits for the dcattr data packets.
2400 Dc_Attr
->flXform
= DEVICE_TO_PAGE_INVALID
;
2402 Dc_Attr
->ulDirty_
= 0; // Server side
2404 Dc_Attr
->iMapMode
= MM_TEXT
;
2406 Dc_Attr
->szlWindowExt
.cx
= 1; // Float to Int,,, WRONG!
2407 Dc_Attr
->szlWindowExt
.cy
= 1;
2408 Dc_Attr
->szlViewportExt
.cx
= 1;
2409 Dc_Attr
->szlViewportExt
.cy
= 1;
2411 Dc_Attr
->crForegroundClr
= 0;
2412 Dc_Attr
->ulForegroundClr
= 0;
2414 Dc_Attr
->ulBackgroundClr
= 0xffffff;
2415 Dc_Attr
->crBackgroundClr
= 0xffffff;
2417 Dc_Attr
->ulPenClr
= RGB( 0, 0, 0 );
2418 Dc_Attr
->crPenClr
= RGB( 0, 0, 0 );
2420 Dc_Attr
->ulBrushClr
= RGB( 255, 255, 255 ); // Do this way too.
2421 Dc_Attr
->crBrushClr
= RGB( 255, 255, 255 );
2423 Dc_Attr
->hlfntNew
= NtGdiGetStockObject(SYSTEM_FONT
);
2424 TextIntRealizeFont(Dc_Attr
->hlfntNew
);
2426 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2434 DC_FindOpenDC(PUNICODE_STRING Driver
)
2440 * Initialize some common fields in the Device Context structure.
2443 DC_InitDC(HDC DCHandle
)
2445 // NtGdiRealizeDefaultPalette(DCHandle);
2447 NtGdiSelectBrush(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2448 NtGdiSelectPen(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2449 //NtGdiSelectFont(DCHandle, hFont);
2454 res = CLIPPING_UpdateGCRegion(DCToInit);
2455 ASSERT ( res != ERROR );
2462 DC_AllocateDcAttr(HDC hDC
)
2464 PVOID NewMem
= NULL
;
2466 HANDLE Pid
= NtCurrentProcess();
2467 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE it will allocate that size
2469 NTSTATUS Status
= ZwAllocateVirtualMemory(Pid
,
2473 MEM_COMMIT
|MEM_RESERVE
,
2475 KeEnterCriticalRegion();
2477 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hDC
);
2478 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2480 if (NT_SUCCESS(Status
))
2482 RtlZeroMemory(NewMem
, MemSize
);
2483 Entry
->UserData
= NewMem
;
2484 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem
);
2488 DPRINT("DC_ATTR not allocated!\n");
2491 KeLeaveCriticalRegion();
2492 pDC
= DC_LockDc(hDC
);
2495 pDC
->pDc_Attr
= NewMem
; // Store pointer
2502 DC_FreeDcAttr(HDC DCToFree
)
2504 HANDLE Pid
= NtCurrentProcess();
2505 PDC pDC
= DC_LockDc(DCToFree
);
2506 if (pDC
->pDc_Attr
== &pDC
->Dc_Attr
) return; // Internal DC object!
2507 pDC
->pDc_Attr
= NULL
;
2510 KeEnterCriticalRegion();
2512 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)DCToFree
);
2513 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2516 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE;
2517 NTSTATUS Status
= ZwFreeVirtualMemory(Pid
,
2521 if (NT_SUCCESS(Status
))
2523 DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry
->UserData
);
2524 Entry
->UserData
= NULL
;
2528 KeLeaveCriticalRegion();
2532 DC_FreeDC(HDC DCToFree
)
2534 DC_FreeDcAttr(DCToFree
);
2535 if(!IsObjectDead( DCToFree
))
2537 if (!GDIOBJ_FreeObj(GdiHandleTable
, DCToFree
, GDI_OBJECT_TYPE_DC
))
2539 DPRINT1("DC_FreeDC failed\n");
2544 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree
);
2549 DC_Cleanup(PVOID ObjectBody
)
2551 PDC pDC
= (PDC
)ObjectBody
;
2552 RtlFreeUnicodeString(&pDC
->DriverName
);
2557 DC_GetNextDC (PDC pDC
)
2563 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2565 pDC
->hNext
= hNextDC
;
2569 DC_UpdateXforms(PDC dc
)
2571 XFORM xformWnd2Vport
;
2572 FLOAT scaleX
, scaleY
;
2573 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
2574 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
2576 /* Construct a transformation to do the window-to-viewport conversion */
2577 scaleX
= (Dc_Attr
->szlWindowExt
.cx
? (FLOAT
)Dc_Attr
->szlViewportExt
.cx
/ (FLOAT
)Dc_Attr
->szlWindowExt
.cx
: 0.0f
);
2578 scaleY
= (Dc_Attr
->szlWindowExt
.cy
? (FLOAT
)Dc_Attr
->szlViewportExt
.cy
/ (FLOAT
)Dc_Attr
->szlWindowExt
.cy
: 0.0f
);
2579 xformWnd2Vport
.eM11
= scaleX
;
2580 xformWnd2Vport
.eM12
= 0.0;
2581 xformWnd2Vport
.eM21
= 0.0;
2582 xformWnd2Vport
.eM22
= scaleY
;
2583 xformWnd2Vport
.eDx
= (FLOAT
)Dc_Attr
->ptlViewportOrg
.x
- scaleX
* (FLOAT
)Dc_Attr
->ptlWindowOrg
.x
;
2584 xformWnd2Vport
.eDy
= (FLOAT
)Dc_Attr
->ptlViewportOrg
.y
- scaleY
* (FLOAT
)Dc_Attr
->ptlWindowOrg
.y
;
2586 /* Combine with the world transformation */
2587 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2589 /* Create inverse of world-to-viewport transformation */
2590 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2594 DC_InvertXform(const XFORM
*xformSrc
,
2599 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2600 if (determinant
> -1e-12 && determinant
< 1e-12)
2605 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2606 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2607 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2608 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2609 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2610 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2616 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2620 GDIOBJ_SetOwnership(GdiHandleTable
, hDC
, Owner
);
2621 DC
= DC_LockDc(hDC
);
2624 if (NULL
!= DC
->w
.hClipRgn
)
2626 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hClipRgn
);
2628 if (NULL
!= DC
->w
.hVisRgn
)
2630 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hVisRgn
);
2632 if (NULL
!= DC
->w
.hGCClipRgn
)
2634 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hGCClipRgn
);
2641 // Support multi display/device locks.
2645 DC_LockDisplay(HDC hDC
)
2647 PERESOURCE Resource
;
2648 PDC dc
= DC_LockDc(hDC
);
2650 Resource
= ((PGDIDEVICE
)dc
->pPDev
)->hsemDevLock
;
2652 if (!Resource
) return;
2653 KeEnterCriticalRegion();
2654 ExAcquireResourceExclusiveLite( Resource
, TRUE
);
2659 DC_UnlockDisplay(HDC hDC
)
2661 PERESOURCE Resource
;
2662 PDC dc
= DC_LockDc(hDC
);
2664 Resource
= ((PGDIDEVICE
)dc
->pPDev
)->hsemDevLock
;
2666 if (!Resource
) return;
2667 ExReleaseResourceLite( Resource
);
2668 KeLeaveCriticalRegion();
2672 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2674 if (PrimarySurface
.pSurface
== NULL
)
2678 return SurfObj
->hsurf
== PrimarySurface
.pSurface
;
2687 // I guess we will soon have more than one primary surface.
2688 // This will do for now.
2689 return &PrimarySurface
;
2692 #define SIZEOF_DEVMODEW_300 188
2693 #define SIZEOF_DEVMODEW_400 212
2694 #define SIZEOF_DEVMODEW_500 220
2696 static NTSTATUS FASTCALL
2697 GetDisplayNumberFromDeviceName(
2698 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2699 OUT ULONG
*DisplayNumber
)
2701 UNICODE_STRING DisplayString
= RTL_CONSTANT_STRING(L
"\\\\.\\DISPLAY");
2702 NTSTATUS Status
= STATUS_SUCCESS
;
2707 if (DisplayNumber
== NULL
)
2708 return STATUS_INVALID_PARAMETER_2
;
2710 if (pDeviceName
&& pDeviceName
->Length
<= DisplayString
.Length
)
2711 return STATUS_OBJECT_NAME_INVALID
;
2713 if (pDeviceName
== NULL
|| pDeviceName
->Length
== 0)
2715 PWINDOW_OBJECT DesktopObject
;
2719 DesktopObject
= UserGetDesktopWindow();
2720 DesktopHDC
= (HDC
)UserGetWindowDC(DesktopObject
);
2721 pDC
= DC_LockDc(DesktopHDC
);
2723 *DisplayNumber
= ((GDIDEVICE
*)pDC
->pPDev
)->DisplayNumber
;
2726 UserReleaseDC(DesktopObject
, DesktopHDC
, FALSE
);
2728 return STATUS_SUCCESS
;
2731 /* Hack to check if the first parts are equal, by faking the device name length */
2732 Length
= pDeviceName
->Length
;
2733 pDeviceName
->Length
= DisplayString
.Length
;
2734 if (RtlEqualUnicodeString(&DisplayString
, pDeviceName
, FALSE
) == FALSE
)
2735 Status
= STATUS_OBJECT_NAME_INVALID
;
2736 pDeviceName
->Length
= Length
;
2738 if (NT_SUCCESS(Status
))
2740 /* Convert the last part of pDeviceName to a number */
2742 Length
= pDeviceName
->Length
/ sizeof(WCHAR
);
2743 for (i
= DisplayString
.Length
/ sizeof(WCHAR
); i
< Length
; i
++)
2745 WCHAR Char
= pDeviceName
->Buffer
[i
];
2746 if (Char
>= L
'0' && Char
<= L
'9')
2747 Number
= Number
* 10 + Char
- L
'0';
2748 else if (Char
!= L
'\0')
2749 return STATUS_OBJECT_NAME_INVALID
;
2752 *DisplayNumber
= Number
- 1;
2758 /*! \brief Enumerate possible display settings for the given display...
2760 * \todo Make thread safe!?
2761 * \todo Don't ignore pDeviceName
2762 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2765 IntEnumDisplaySettings(
2766 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2768 IN OUT LPDEVMODEW pDevMode
,
2771 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2772 static DWORD SizeOfCachedDevModes
= 0;
2773 static UNICODE_STRING CachedDeviceName
;
2774 PDEVMODEW CachedMode
= NULL
;
2776 ULONG DisplayNumber
;
2778 if (!NT_SUCCESS(GetDisplayNumberFromDeviceName(pDeviceName
, &DisplayNumber
)))
2780 SetLastWin32Error(STATUS_NO_SUCH_DEVICE
);
2784 DPRINT("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2785 DPRINT("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2786 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2787 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2788 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2790 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2794 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2796 CachedMode
= &PrimarySurface
.DMW
;
2797 ASSERT(CachedMode
->dmSize
> 0);
2799 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2801 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2802 DevMode
.dmSize
= sizeof (DevMode
);
2803 DevMode
.dmDriverExtra
= 0;
2804 if (SetupDevMode(&DevMode
, DisplayNumber
))
2805 CachedMode
= &DevMode
;
2808 SetLastWin32Error(0); /* FIXME: use error code */
2811 /* FIXME: Maybe look for the matching devmode supplied by the
2812 * driver so we can provide driver private/extra data?
2817 BOOL IsCachedDevice
= (CachedDevModes
!= NULL
);
2819 if (CachedDevModes
&&
2820 ((pDeviceName
== NULL
&& CachedDeviceName
.Length
> 0) ||
2821 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
== 0) ||
2822 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
> 0 && RtlEqualUnicodeString(pDeviceName
, &CachedDeviceName
, TRUE
) == FALSE
)))
2824 IsCachedDevice
= FALSE
;
2827 if (iModeNum
== 0 || IsCachedDevice
== FALSE
) /* query modes from drivers */
2829 UNICODE_STRING DriverFileNames
;
2831 DRVENABLEDATA DrvEnableData
;
2833 /* Free resources from last driver cache */
2834 if (IsCachedDevice
== FALSE
&& CachedDeviceName
.Buffer
!= NULL
)
2836 RtlFreeUnicodeString(&CachedDeviceName
);
2839 /* Retrieve DDI driver names from registry */
2840 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2841 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2843 DPRINT1("FindDriverFileNames failed\n");
2847 if (!IntPrepareDriverIfNeeded())
2849 DPRINT1("IntPrepareDriverIfNeeded failed\n");
2854 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2855 * scan all of them until a good one found.
2857 CurrentName
= DriverFileNames
.Buffer
;
2858 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2859 CurrentName
+= wcslen(CurrentName
) + 1)
2862 PGD_ENABLEDRIVER GDEnableDriver
;
2863 PGD_GETMODES GetModes
= NULL
;
2864 INT SizeNeeded
, SizeUsed
;
2866 /* Get the DDI driver's entry point */
2867 //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
2868 GDEnableDriver
= DRIVER_FindExistingDDIDriver(L
"DISPLAY");
2869 if (NULL
== GDEnableDriver
)
2871 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2875 /* Call DDI driver's EnableDriver function */
2876 RtlZeroMemory(&DrvEnableData
, sizeof(DrvEnableData
));
2878 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2880 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2884 CachedDevModesEnd
= CachedDevModes
;
2886 /* find DrvGetModes function */
2887 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2889 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2891 if (DrvFn
->iFunc
== INDEX_DrvGetModes
)
2893 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2898 if (GetModes
== NULL
)
2900 DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName
);
2904 /* make sure we have enough memory to hold the modes */
2905 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2906 if (SizeNeeded
<= 0)
2908 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2912 SizeUsed
= (PCHAR
)CachedDevModesEnd
- (PCHAR
)CachedDevModes
;
2913 if (SizeOfCachedDevModes
< SizeUsed
+ SizeNeeded
)
2917 SizeOfCachedDevModes
+= SizeNeeded
;
2918 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2919 if (NewBuffer
== NULL
)
2922 ExFreePool(CachedDevModes
);
2923 CachedDevModes
= NULL
;
2924 CachedDevModesEnd
= NULL
;
2925 SizeOfCachedDevModes
= 0;
2927 if (CachedDeviceName
.Buffer
!= NULL
)
2928 RtlFreeUnicodeString(&CachedDeviceName
);
2930 SetLastWin32Error(STATUS_NO_MEMORY
);
2933 if (CachedDevModes
!= NULL
)
2935 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2936 ExFreePool(CachedDevModes
);
2938 CachedDevModes
= NewBuffer
;
2939 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2942 if (!IsCachedDevice
)
2944 if (CachedDeviceName
.Buffer
!= NULL
)
2945 RtlFreeUnicodeString(&CachedDeviceName
);
2948 IntSafeCopyUnicodeString(&CachedDeviceName
, pDeviceName
);
2950 IsCachedDevice
= TRUE
;
2954 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2957 if (SizeNeeded
<= 0)
2959 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2963 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2967 RtlFreeUnicodeString(&DriverFileNames
);
2970 /* return cached info */
2971 CachedMode
= CachedDevModes
;
2972 if (CachedMode
>= CachedDevModesEnd
)
2974 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2977 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2979 assert(CachedMode
->dmSize
> 0);
2980 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2982 if (CachedMode
>= CachedDevModesEnd
)
2984 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2989 ASSERT(CachedMode
!= NULL
);
2991 RtlCopyMemory(pDevMode
, CachedMode
, min(pDevMode
->dmSize
, CachedMode
->dmSize
));
2992 RtlZeroMemory(pDevMode
+ pDevMode
->dmSize
, pDevMode
->dmDriverExtra
);
2993 RtlCopyMemory(pDevMode
+ min(pDevMode
->dmSize
, CachedMode
->dmSize
), CachedMode
+ CachedMode
->dmSize
, min(pDevMode
->dmDriverExtra
, CachedMode
->dmDriverExtra
));
2998 static NTSTATUS FASTCALL
3000 OUT PUNICODE_STRING VideoDeviceName
,
3001 IN PCUNICODE_STRING DisplayDevice
) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
3003 UNICODE_STRING Prefix
= RTL_CONSTANT_STRING(L
"\\??\\");
3004 UNICODE_STRING ObjectName
;
3005 UNICODE_STRING KernelModeName
= { 0, };
3006 OBJECT_ATTRIBUTES ObjectAttributes
;
3009 HANDLE LinkHandle
= NULL
;
3012 RtlInitUnicodeString(VideoDeviceName
, NULL
);
3014 /* Get device name (DisplayDevice is "\.\xxx") */
3015 for (LastSlash
= DisplayDevice
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
3017 if (DisplayDevice
->Buffer
[LastSlash
- 1] == L
'\\')
3023 DPRINT1("Invalid device name '%wZ'\n", DisplayDevice
);
3024 Status
= STATUS_OBJECT_NAME_INVALID
;
3027 ObjectName
= *DisplayDevice
;
3028 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
3029 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
3030 ObjectName
.Buffer
+= LastSlash
;
3032 /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
3033 KernelModeName
.MaximumLength
= Prefix
.Length
+ ObjectName
.Length
+ sizeof(UNICODE_NULL
);
3034 KernelModeName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
3035 KernelModeName
.MaximumLength
,
3037 if (!KernelModeName
.Buffer
)
3039 Status
= STATUS_NO_MEMORY
;
3042 RtlCopyUnicodeString(&KernelModeName
, &Prefix
);
3043 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
3044 if (!NT_SUCCESS(Status
))
3047 /* Open \??\xxx (ex: "\??\DISPLAY1") */
3048 InitializeObjectAttributes(&ObjectAttributes
,
3053 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
3056 if (!NT_SUCCESS(Status
))
3058 DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3059 Status
= STATUS_NO_SUCH_DEVICE
;
3063 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, &Length
);
3064 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
3066 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3067 Status
= STATUS_NO_SUCH_DEVICE
;
3070 VideoDeviceName
->MaximumLength
= Length
;
3071 VideoDeviceName
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
3072 VideoDeviceName
->MaximumLength
+ sizeof(UNICODE_NULL
),
3074 if (!VideoDeviceName
->Buffer
)
3076 Status
= STATUS_NO_MEMORY
;
3079 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, NULL
);
3080 VideoDeviceName
->Buffer
[VideoDeviceName
->MaximumLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
3081 if (!NT_SUCCESS(Status
))
3083 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3084 Status
= STATUS_NO_SUCH_DEVICE
;
3087 Status
= STATUS_SUCCESS
;
3090 if (!NT_SUCCESS(Status
) && VideoDeviceName
->Buffer
)
3091 ExFreePoolWithTag(VideoDeviceName
->Buffer
, TAG_DC
);
3092 if (KernelModeName
.Buffer
)
3093 ExFreePoolWithTag(KernelModeName
.Buffer
, TAG_DC
);
3095 ZwClose(LinkHandle
);
3099 static NTSTATUS FASTCALL
3100 GetVideoRegistryKey(
3101 OUT PUNICODE_STRING RegistryPath
,
3102 IN PCUNICODE_STRING DeviceName
) /* ex: "\Device\Video0" */
3104 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
3107 RtlInitUnicodeString(RegistryPath
, NULL
);
3108 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
3109 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
3110 QueryTable
[0].Name
= DeviceName
->Buffer
;
3111 QueryTable
[0].EntryContext
= RegistryPath
;
3113 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
3118 if (!NT_SUCCESS(Status
))
3120 DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName
, Status
);
3121 return STATUS_NO_SUCH_DEVICE
;
3124 DPRINT("RegistryPath %wZ\n", RegistryPath
);
3125 return STATUS_SUCCESS
;
3130 IntChangeDisplaySettings(
3131 IN PUNICODE_STRING pDeviceName OPTIONAL
,
3132 IN LPDEVMODEW DevMode
,
3134 IN PVOID lParam OPTIONAL
)
3136 BOOLEAN Global
= FALSE
;
3137 BOOLEAN NoReset
= FALSE
;
3138 BOOLEAN Reset
= FALSE
;
3139 BOOLEAN SetPrimary
= FALSE
;
3143 DPRINT1("display flags : %x\n",dwflags
);
3145 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3147 /* Check global, reset and noreset flags */
3148 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
3150 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
3152 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
3154 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
3156 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
3158 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
3160 if (Reset
&& NoReset
)
3161 return DISP_CHANGE_BADFLAGS
;
3165 /* Dynamically change graphics mode */
3166 DPRINT1("flag 0 UNIMPLEMENTED\n");
3167 return DISP_CHANGE_FAILED
;
3170 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
3172 /* Test reslution */
3173 dwflags
&= ~CDS_TEST
;
3174 DPRINT1("flag CDS_TEST UNIMPLEMENTED\n");
3175 Ret
= DISP_CHANGE_FAILED
;
3178 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
3182 dwflags
&= ~CDS_FULLSCREEN
;
3183 DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
3184 Ret
= DISP_CHANGE_FAILED
;
3186 RtlZeroMemory(&lpDevMode
, sizeof(DEVMODEW
));
3187 lpDevMode
.dmSize
= sizeof(DEVMODEW
);
3189 if (!IntEnumDisplaySettings(pDeviceName
, ENUM_CURRENT_SETTINGS
, &lpDevMode
, 0))
3190 return DISP_CHANGE_FAILED
;
3192 DPRINT1("Req Mode : %d x %d x %d\n", DevMode
->dmPelsWidth
,DevMode
->dmPelsHeight
,DevMode
->dmBitsPerPel
);
3193 DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode
.dmPelsWidth
,lpDevMode
.dmPelsHeight
, lpDevMode
.dmBitsPerPel
);
3196 if ((lpDevMode
.dmBitsPerPel
== DevMode
->dmBitsPerPel
) &&
3197 (lpDevMode
.dmPelsWidth
== DevMode
->dmPelsWidth
) &&
3198 (lpDevMode
.dmPelsHeight
== DevMode
->dmPelsHeight
))
3199 Ret
= DISP_CHANGE_SUCCESSFUL
;
3202 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
3204 dwflags
&= ~CDS_VIDEOPARAMETERS
;
3206 Ret
=DISP_CHANGE_BADPARAM
;
3209 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
3210 Ret
= DISP_CHANGE_FAILED
;
3215 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3218 UNICODE_STRING DeviceName
;
3219 UNICODE_STRING RegistryKey
;
3220 UNICODE_STRING InDeviceName
;
3221 OBJECT_ATTRIBUTES ObjectAttributes
;
3222 HANDLE DevInstRegKey
;
3225 DPRINT1("set CDS_UPDATEREGISTRY\n");
3227 dwflags
&= ~CDS_UPDATEREGISTRY
;
3229 /* Check if pDeviceName is NULL, we need to retrieve it */
3230 if (pDeviceName
== NULL
)
3232 WCHAR szBuffer
[MAX_DRIVER_NAME
];
3234 PWINDOW_OBJECT Wnd
=NULL
;
3238 hWnd
= IntGetDesktopWindow();
3239 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3244 hDC
= (HDC
)UserGetWindowDC(Wnd
);
3246 DC
= DC_LockDc(hDC
);
3251 swprintf (szBuffer
, L
"\\\\.\\DISPLAY%lu", ((GDIDEVICE
*)DC
->pPDev
)->DisplayNumber
);
3254 RtlInitUnicodeString(&InDeviceName
, szBuffer
);
3255 pDeviceName
= &InDeviceName
;
3258 Status
= GetVideoDeviceName(&DeviceName
, pDeviceName
);
3259 if (!NT_SUCCESS(Status
))
3261 DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName
, Status
);
3262 return DISP_CHANGE_FAILED
;
3264 Status
= GetVideoRegistryKey(&RegistryKey
, &DeviceName
);
3265 if (!NT_SUCCESS(Status
))
3267 DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName
, Status
);
3268 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3269 return DISP_CHANGE_FAILED
;
3271 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3273 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
3274 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3275 Status
= ZwOpenKey(&DevInstRegKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
);
3276 if (!NT_SUCCESS(Status
))
3278 DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey
, Status
);
3279 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
3280 return DISP_CHANGE_FAILED
;
3282 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
3284 /* Update needed fields */
3285 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
3287 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
3288 NewValue
= DevMode
->dmBitsPerPel
;
3289 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3292 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
3294 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
3295 NewValue
= DevMode
->dmPelsWidth
;
3296 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3299 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
3301 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
3302 NewValue
= DevMode
->dmPelsHeight
;
3303 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3306 ZwClose(DevInstRegKey
);
3307 if (NT_SUCCESS(Status
))
3308 Ret
= DISP_CHANGE_RESTART
;
3310 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
3311 Ret
= DISP_CHANGE_NOTUPDATED
;
3315 Ret
= DISP_CHANGE_BADFLAGS
;
3328 return DCB_RESET
; /* bounding rectangle always empty */
3339 return DCB_DISABLE
; /* bounding rectangle always empty */
3344 NtGdiGetAspectRatioFilterEx(HDC hDC
,
3358 PGDIDEVICE pPDev
, pGdiDevice
= (PGDIDEVICE
) hdev
;
3359 if (!pGdiDevice
) return NULL
;
3360 if ( pGdiDevice
< (PGDIDEVICE
)MmSystemRangeStart
) return NULL
;
3361 pPDev
= &PrimarySurface
;
3362 KeEnterCriticalRegion();
3365 if (pGdiDevice
== pPDev
) break;
3367 pPDev
= pPDev
->ppdevNext
;
3368 } while (pPDev
!= NULL
);
3369 KeLeaveCriticalRegion();
3370 if (!pPDev
) return NULL
;
3371 return pGdiDevice
->hPDev
;