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 // --------------------------------------------------------- File Statics
32 static GDIDEVICE PrimarySurface
;
33 PGDIDEVICE pPrimarySurface
= &PrimarySurface
;
34 static KEVENT VideoDriverNeedsPreparation
;
35 static KEVENT VideoDriverPrepared
;
36 PDC defaultDCstate
= NULL
;
42 KeInitializeEvent(&VideoDriverNeedsPreparation
, SynchronizationEvent
, TRUE
);
43 KeInitializeEvent(&VideoDriverPrepared
, NotificationEvent
, FALSE
);
44 return STATUS_SUCCESS
;
47 /* FIXME: DCs should probably be thread safe */
49 // ----------------------------------------------------- Public Functions
52 NtGdiCancelDC(HDC hDC
)
59 NtGdiCreateCompatibleDC(HDC hDC
)
62 PDC_ATTR nDc_Attr
, oDc_Attr
;
63 HDC hNewDC
, DisplayDC
= NULL
;
65 UNICODE_STRING DriverName
;
70 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
71 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
72 if (NULL
== DisplayDC
)
74 DPRINT1("Failed to create DisplayDC\n");
80 /* Allocate a new DC based on the original DC's device */
81 OrigDC
= DC_LockDc(hDC
);
84 if (NULL
!= DisplayDC
)
86 NtGdiDeleteObjectApp(DisplayDC
);
88 DPRINT1("Failed to lock hDC\n");
91 hNewDC
= DC_AllocDC(&OrigDC
->rosdc
.DriverName
);
94 DPRINT1("Failed to create hNewDC\n");
96 if (NULL
!= DisplayDC
)
98 NtGdiDeleteObjectApp(DisplayDC
);
102 NewDC
= DC_LockDc( hNewDC
);
106 DPRINT1("Failed to lock hNewDC\n");
107 NtGdiDeleteObjectApp(hNewDC
);
111 oDc_Attr
= OrigDC
->pdcattr
;
112 nDc_Attr
= NewDC
->pdcattr
;
114 /* Copy information from original DC to new DC */
115 NewDC
->DcLevel
.hdcSave
= hNewDC
;
117 NewDC
->dhpdev
= OrigDC
->dhpdev
;
119 NewDC
->rosdc
.bitsPerPixel
= OrigDC
->rosdc
.bitsPerPixel
;
121 /* DriverName is copied in the AllocDC routine */
122 nDc_Attr
->ptlWindowOrg
= oDc_Attr
->ptlWindowOrg
;
123 nDc_Attr
->szlWindowExt
= oDc_Attr
->szlWindowExt
;
124 nDc_Attr
->ptlViewportOrg
= oDc_Attr
->ptlViewportOrg
;
125 nDc_Attr
->szlViewportExt
= oDc_Attr
->szlViewportExt
;
127 NewDC
->dctype
= DC_TYPE_MEMORY
; // Always!
128 NewDC
->rosdc
.hBitmap
= NtGdiGetStockObject(DEFAULT_BITMAP
);
129 NewDC
->ppdev
= OrigDC
->ppdev
;
130 NewDC
->DcLevel
.hpal
= OrigDC
->DcLevel
.hpal
;
132 nDc_Attr
->lTextAlign
= oDc_Attr
->lTextAlign
;
133 nDc_Attr
->lBkMode
= oDc_Attr
->lBkMode
;
134 nDc_Attr
->jBkMode
= oDc_Attr
->jBkMode
;
135 nDc_Attr
->jROP2
= oDc_Attr
->jROP2
;
136 nDc_Attr
->dwLayout
= oDc_Attr
->dwLayout
;
137 if (oDc_Attr
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= oDc_Attr
->dwLayout
;
138 NewDC
->DcLevel
.flPath
= OrigDC
->DcLevel
.flPath
;
139 nDc_Attr
->ulDirty_
= oDc_Attr
->ulDirty_
;
140 nDc_Attr
->iCS_CP
= oDc_Attr
->iCS_CP
;
142 NewDC
->erclWindow
= (RECTL
){0,0,1,1};
146 if (NULL
!= DisplayDC
)
148 NtGdiDeleteObjectApp(DisplayDC
);
151 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
154 GdiSelectVisRgn(hNewDC
, hVisRgn
);
155 NtGdiDeleteObject(hVisRgn
);
157 if (Layout
) NtGdiSetLayout( hNewDC
, -1, Layout
);
163 static BOOLEAN FASTCALL
164 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
166 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
167 WCHAR DeviceNameBuffer
[20];
170 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%lu", DisplayNumber
);
171 RtlInitUnicodeString(RegistryPath
, NULL
);
172 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
173 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
174 QueryTable
[0].Name
= DeviceNameBuffer
;
175 QueryTable
[0].EntryContext
= RegistryPath
;
177 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
182 if (! NT_SUCCESS(Status
))
184 DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
188 DPRINT("RegistryPath %wZ\n", RegistryPath
);
194 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
196 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
197 UNICODE_STRING RegistryPath
;
200 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
202 DPRINT("GetRegistryPath failed\n");
206 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
207 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
208 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
209 QueryTable
[0].EntryContext
= DriverFileNames
;
211 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
216 ExFreePoolWithTag(RegistryPath
.Buffer
, TAG_RTLREGISTRY
);
217 if (! NT_SUCCESS(Status
))
219 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
223 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
228 static NTSTATUS APIENTRY
229 DevModeCallback(IN PWSTR ValueName
,
232 IN ULONG ValueLength
,
234 IN PVOID EntryContext
)
236 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
238 DPRINT("Found registry value for name %S: type %d, length %d\n",
239 ValueName
, ValueType
, ValueLength
);
241 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
243 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
245 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
247 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
249 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
251 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
253 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
255 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
257 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
259 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
261 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
263 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
265 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
267 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
269 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
273 return STATUS_SUCCESS
;
277 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
279 UNICODE_STRING RegistryPath
;
280 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
282 BOOLEAN Valid
= TRUE
;
284 if (!GetRegistryPath(&RegistryPath
, DisplayNumber
))
286 DPRINT("GetRegistryPath failed\n");
290 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
291 QueryTable
[0].QueryRoutine
= DevModeCallback
;
292 QueryTable
[0].Flags
= 0;
293 QueryTable
[0].Name
= NULL
;
294 QueryTable
[0].EntryContext
= NULL
;
295 QueryTable
[0].DefaultType
= REG_NONE
;
296 QueryTable
[0].DefaultData
= NULL
;
297 QueryTable
[0].DefaultLength
= 0;
299 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
304 if (! NT_SUCCESS(Status
))
306 DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
307 &RegistryPath
, Status
);
312 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
313 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
314 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
315 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
316 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
318 DPRINT("Not all required devmode members are set\n");
323 ExFreePoolWithTag(RegistryPath
.Buffer
, TAG_RTLREGISTRY
);
327 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
336 PGD_ENABLEDRIVER GDEnableDriver
;
338 UNICODE_STRING DriverFileNames
;
347 if (STATUS_SUCCESS
!= KeWaitForSingleObject(&VideoDriverNeedsPreparation
, Executive
, KernelMode
, TRUE
, &Zero
))
349 /* Concurrent access. Wait for VideoDriverPrepared event */
350 if (STATUS_SUCCESS
== KeWaitForSingleObject(&VideoDriverPrepared
, Executive
, KernelMode
, TRUE
, NULL
))
351 ret
= PrimarySurface
.PreparedDriver
;
354 // HAX! Fixme so I can support more than one! So how many?
355 for (DisplayNumber
= 0; ; DisplayNumber
++)
357 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
359 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
361 // if (!pPrimarySurface) pPrimarySurface = ExAllocatePoolWithTag(PagedPool, sizeof(GDIDEVICE), TAG_GDIPDEV);
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 ExFreePoolWithTag(DriverFileNames
.Buffer
, TAG_RTLREGISTRY
);
429 DPRINT1("No suitable DDI driver found\n");
433 DPRINT("Display driver %S loaded\n", CurrentName
);
435 ExFreePoolWithTag(DriverFileNames
.Buffer
, TAG_RTLREGISTRY
);
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 if (PrimarySurface
.DMW
.dmDriverExtra
!= 0)
518 DPRINT1("**** DMW extra = %u bytes. Please report to ros-dev@reactos.org ****\n", PrimarySurface
.DMW
.dmDriverExtra
);
521 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
523 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
524 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
526 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
528 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
529 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
532 PrimarySurface
.Pointer
.Exclude
.right
= -1;
534 DPRINT("calling completePDev\n");
536 /* Complete initialization of the physical device */
537 PrimarySurface
.DriverFunctions
.CompletePDEV(
538 PrimarySurface
.hPDev
,
539 (HDEV
)&PrimarySurface
);
541 DPRINT("calling DRIVER_ReferenceDriver\n");
543 DRIVER_ReferenceDriver(L
"DISPLAY");
545 PrimarySurface
.PreparedDriver
= TRUE
;
546 PrimarySurface
.DisplayNumber
= DisplayNumber
;
547 PrimarySurface
.flFlags
= PDEV_DISPLAY
; // Hard set,, add more flags.
548 PrimarySurface
.hsemDevLock
= (PERESOURCE
)EngCreateSemaphore();
549 // Should be null,, but make sure for now.
550 PrimarySurface
.pvGammaRamp
= NULL
;
551 PrimarySurface
.ppdevNext
= NULL
; // Fixme! We need to support more than display drvs.
552 PrimarySurface
.ppdevParent
= NULL
; // Always NULL if primary.
553 PrimarySurface
.pGraphicsDev
= NULL
; // Fixme!
554 PrimarySurface
.pEDDgpl
= ExAllocatePoolWithTag(PagedPool
, sizeof(EDD_DIRECTDRAW_GLOBAL
), TAG_EDDGBL
);
555 if (PrimarySurface
.pEDDgpl
)
557 RtlZeroMemory( PrimarySurface
.pEDDgpl
,sizeof(EDD_DIRECTDRAW_GLOBAL
));
564 KeSetEvent(&VideoDriverPrepared
, 1, FALSE
);
569 IntPrepareDriverIfNeeded()
571 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
579 IO_STATUS_BLOCK Iosb
;
581 ULONG Length
= sizeof(BOOL
);
582 PIO_STACK_LOCATION StackPtr
;
583 LARGE_INTEGER StartOffset
;
584 PFILE_OBJECT FileObject
= PrimarySurface
.VideoFileObject
;
585 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
587 DPRINT("PrepareVideoPrt() called\n");
589 KeClearEvent(&PrimarySurface
.VideoFileObject
->Event
);
591 ObReferenceObjectByPointer(FileObject
, 0, IoFileObjectType
, KernelMode
);
593 StartOffset
.QuadPart
= 0;
594 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
606 /* Set up IRP Data */
607 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
608 Irp
->RequestorMode
= KernelMode
;
609 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
610 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= NULL
;
611 Irp
->Flags
|= IRP_WRITE_OPERATION
;
613 /* Setup Stack Data */
614 StackPtr
= IoGetNextIrpStackLocation(Irp
);
615 StackPtr
->FileObject
= PrimarySurface
.VideoFileObject
;
616 StackPtr
->Parameters
.Write
.Key
= 0;
618 Status
= IoCallDriver(DeviceObject
, Irp
);
620 if (STATUS_PENDING
== Status
)
622 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, TRUE
, 0);
623 Status
= Iosb
.Status
;
626 return NT_SUCCESS(Status
);
631 IntCreatePrimarySurface()
638 if (! IntPrepareDriverIfNeeded())
643 if (! PrepareVideoPrt())
648 DPRINT("calling EnableSurface\n");
649 /* Enable the drawing surface */
650 PrimarySurface
.pSurface
=
651 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.hPDev
);
652 if (NULL
== PrimarySurface
.pSurface
)
654 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.hPDev, FALSE);*/
655 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
656 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
657 DPRINT1("DrvEnableSurface failed\n");
661 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, TRUE
);
663 calledFromUser
= UserIsEntered(); //fixme: possibly upgrade a shared lock
664 if (!calledFromUser
){
665 UserEnterExclusive();
669 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
671 SurfObj
= EngLockSurface(PrimarySurface
.pSurface
);
672 SurfObj
->dhpdev
= PrimarySurface
.hPDev
;
673 SurfSize
= SurfObj
->sizlBitmap
;
674 SurfaceRect
.left
= SurfaceRect
.top
= 0;
675 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
676 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
677 /* FIXME - why does EngEraseSurface() sometimes crash?
678 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
680 /* Put the pointer in the center of the screen */
681 gpsi
->ptCursor
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
682 gpsi
->ptCursor
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
684 EngUnlockSurface(SurfObj
);
685 co_IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
687 // Init Primary Displays Device Capabilities.
688 IntvGetDeviceCaps(&PrimarySurface
, &GdiHandleTable
->DevCaps
);
690 if (!calledFromUser
){
698 IntDestroyPrimarySurface()
702 DRIVER_UnreferenceDriver(L
"DISPLAY");
704 calledFromUser
= UserIsEntered();
705 if (!calledFromUser
){
706 UserEnterExclusive();
710 IntDetachMonitor(&PrimarySurface
);
712 if (!calledFromUser
){
717 * FIXME: Hide a mouse pointer there. Also because we have to prevent
718 * memory leaks with the Eng* mouse routines.
721 DPRINT("Reseting display\n" );
722 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.hPDev
, FALSE
);
723 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.hPDev
);
724 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.hPDev
);
725 PrimarySurface
.PreparedDriver
= FALSE
;
726 KeSetEvent(&VideoDriverNeedsPreparation
, 1, FALSE
);
727 KeResetEvent(&VideoDriverPrepared
);
731 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
735 IntGdiCreateDC(PUNICODE_STRING Driver
,
736 PUNICODE_STRING Device
,
738 CONST PDEVMODEW InitData
,
746 UNICODE_STRING StdDriver
;
749 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
751 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
753 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
757 if (! IntPrepareDriverIfNeeded())
759 /* Here, we have two possibilities:
760 * a) return NULL, and hope that the caller
761 * won't call us in a loop
762 * b) bugcheck, but caller is unable to
763 * react on the problem
765 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
767 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
772 calledFromUser
= UserIsEntered();
773 if (!calledFromUser
){
774 UserEnterExclusive();
777 if (! co_IntGraphicsCheck(TRUE
))
779 if (!calledFromUser
){
782 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
786 if (!calledFromUser
){
793 /* Check for existing DC object */
794 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
796 hDC
= NtGdiCreateCompatibleDC(hNewDC
);
798 DPRINT1("NtGdiCreateCompatibleDC() failed\n");
802 /* Allocate a DC object */
803 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
805 DPRINT1("DC_AllocDC() failed\n");
809 NewDC
= DC_LockDc( hNewDC
);
813 DPRINT1("DC_LockDc() failed\n");
817 nDc_Attr
= NewDC
->pdcattr
;
819 NewDC
->dctype
= DC_TYPE_DIRECT
;
821 NewDC
->dhpdev
= PrimarySurface
.hPDev
;
822 if(pUMdhpdev
) pUMdhpdev
= NewDC
->dhpdev
; // set DHPDEV for device.
823 NewDC
->ppdev
= (PVOID
)&PrimarySurface
;
824 NewDC
->rosdc
.hBitmap
= (HBITMAP
)PrimarySurface
.pSurface
;
825 // ATM we only have one display.
826 nDc_Attr
->ulDirty_
|= DC_PRIMARY_DISPLAY
;
828 NewDC
->rosdc
.bitsPerPixel
= ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.cBitsPixel
*
829 ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.cPlanes
;
830 DPRINT("Bits per pel: %u\n", NewDC
->rosdc
.bitsPerPixel
);
832 NewDC
->flGraphicsCaps
= PrimarySurface
.DevInfo
.flGraphicsCaps
;
833 NewDC
->flGraphicsCaps2
= PrimarySurface
.DevInfo
.flGraphicsCaps2
;
835 NewDC
->DcLevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
837 nDc_Attr
->jROP2
= R2_COPYPEN
;
839 NewDC
->erclWindow
.top
= NewDC
->erclWindow
.left
= 0;
840 NewDC
->erclWindow
.right
= ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.ulHorzRes
;
841 NewDC
->erclWindow
.bottom
= ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.ulVertRes
;
842 NewDC
->DcLevel
.flPath
&= ~DCPATH_CLOCKWISE
; // Default is CCW.
844 nDc_Attr
->iCS_CP
= ftGdiGetTextCharsetInfo(NewDC
,NULL
,0);
846 hVisRgn
= NtGdiCreateRectRgn(0, 0, ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.ulHorzRes
,
847 ((PGDIDEVICE
)NewDC
->ppdev
)->GDIInfo
.ulVertRes
);
851 NewDC
->pSurfInfo
= NULL
;
852 // NewDC->DcLevel.pSurface =
853 DC_UnlockDc( NewDC
);
855 /* Initialize the DC state */
857 IntGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
858 IntGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
863 The CreateIC function creates an information context for the specified device.
864 The information context provides a fast way to get information about the
865 device without creating a device context (DC). However, GDI drawing functions
866 cannot accept a handle to an information context.
868 NewDC
->dctype
= DC_TYPE_INFO
;
869 // NewDC->pSurfInfo =
870 NewDC
->DcLevel
.pSurface
= NULL
;
871 nDc_Attr
->crBackgroundClr
= nDc_Attr
->ulBackgroundClr
= RGB(255, 255, 255);
872 nDc_Attr
->crForegroundClr
= RGB(0, 0, 0);
873 DC_UnlockDc( NewDC
);
878 GdiSelectVisRgn(hNewDC
, hVisRgn
);
879 NtGdiDeleteObject(hVisRgn
);
882 IntGdiSetTextAlign(hNewDC
, TA_TOP
);
883 IntGdiSetBkMode(hNewDC
, OPAQUE
);
889 NtGdiOpenDCW( PUNICODE_STRING Device
,
891 PUNICODE_STRING pustrLogAddr
,
897 UNICODE_STRING SafeDevice
;
898 DEVMODEW SafeInitData
;
901 NTSTATUS Status
= STATUS_SUCCESS
;
909 ProbeForWrite(pUMdhpdev
,
913 ProbeForRead(InitData
,
916 RtlCopyMemory(&SafeInitData
,
920 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
922 Status
= _SEH2_GetExceptionCode();
925 if(!NT_SUCCESS(Status
))
927 SetLastNtError(Status
);
930 /* FIXME - InitData can have some more bytes! */
935 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
936 if(!NT_SUCCESS(Status
))
938 SetLastNtError(Status
);
943 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
945 pUMdhpdev
? &Dhpdev
: NULL
,
946 InitData
? &SafeInitData
: NULL
,
947 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
949 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
957 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
960 UNICODE_STRING DriverName
;
961 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
963 if (DcType
!= DC_TYPE_MEMORY
)
964 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));
966 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
968 // There is room to grow here~
972 // If NULL, first time through! Build the default (was window) dc!
974 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
975 { // This is a cheesy way to do this.
976 PDC dc
= DC_LockDc ( hDC
);
977 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
983 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
984 defaultDCstate
->pdcattr
= &defaultDCstate
->Dc_Attr
;
985 IntGdiCopyToSaveState(dc
, defaultDCstate
);
992 IntGdiCleanDC(HDC hDC
)
995 if (!hDC
) return FALSE
;
996 dc
= DC_LockDc ( hDC
);
997 if (!dc
) return FALSE
;
999 if (defaultDCstate
) IntGdiCopyFromSaveState(dc
, defaultDCstate
, hDC
);
1008 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
1010 PDC DCToDelete
= DC_LockDc(hDC
);
1012 if (DCToDelete
== NULL
)
1014 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1020 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
1022 DPRINT1("No! You Naughty Application!\n");
1023 DC_UnlockDc( DCToDelete
);
1024 return UserReleaseDC(NULL
, hDC
, FALSE
);
1028 /* First delete all saved DCs */
1029 while (DCToDelete
->DcLevel
.lSaveDepth
)
1034 savedHDC
= DC_GetNextDC (DCToDelete
);
1035 savedDC
= DC_LockDc (savedHDC
);
1036 if (savedDC
== NULL
)
1040 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
1041 DCToDelete
->DcLevel
.lSaveDepth
--;
1042 DC_UnlockDc( savedDC
);
1043 IntGdiDeleteDC(savedHDC
, Force
);
1046 /* Free GDI resources allocated to this DC */
1047 if (!(DCToDelete
->DcLevel
.flPath
& DCPATH_SAVESTATE
))
1050 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
1051 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
1052 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
1053 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
1054 if (DCToDelete
->rosdc
.XlateBrush
!= NULL
)
1055 EngDeleteXlate(DCToDelete
->rosdc
.XlateBrush
);
1056 if (DCToDelete
->rosdc
.XlatePen
!= NULL
)
1057 EngDeleteXlate(DCToDelete
->rosdc
.XlatePen
);
1059 if (DCToDelete
->rosdc
.hClipRgn
)
1061 NtGdiDeleteObject (DCToDelete
->rosdc
.hClipRgn
);
1063 if (DCToDelete
->rosdc
.hVisRgn
)
1065 NtGdiDeleteObject (DCToDelete
->rosdc
.hVisRgn
);
1067 if (NULL
!= DCToDelete
->rosdc
.CombinedClip
)
1069 IntEngDeleteClipRegion(DCToDelete
->rosdc
.CombinedClip
);
1071 if (DCToDelete
->rosdc
.hGCClipRgn
)
1073 NtGdiDeleteObject (DCToDelete
->rosdc
.hGCClipRgn
);
1075 PATH_Delete(DCToDelete
->DcLevel
.hPath
);
1077 DC_UnlockDc( DCToDelete
);
1084 NtGdiDeleteObjectApp(HANDLE DCHandle
)
1086 /* Complete all pending operations */
1087 NtGdiFlushUserBatch();
1089 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
1091 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
1092 return NtGdiDeleteObject((HGDIOBJ
) DCHandle
);
1094 if(IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
1096 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle
))
1098 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1102 return IntGdiDeleteDC(DCHandle
, FALSE
);
1111 IN OPTIONAL LPSTR pjIn
)
1123 OUT OPTIONAL PVOID pvBuf
)
1131 NtGdiGetDCObject(HDC hDC
, INT ObjectType
)
1137 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
1138 if(!hDC
) return NULL
;
1140 if(!(dc
= DC_LockDc(hDC
)))
1142 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1145 pdcattr
= dc
->pdcattr
;
1147 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
1148 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
1150 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
1151 IntGdiSelectPen(dc
,pdcattr
->hpen
);
1155 case GDI_OBJECT_TYPE_EXTPEN
:
1156 case GDI_OBJECT_TYPE_PEN
:
1157 SelObject
= pdcattr
->hpen
;
1159 case GDI_OBJECT_TYPE_BRUSH
:
1160 SelObject
= pdcattr
->hbrush
;
1162 case GDI_OBJECT_TYPE_PALETTE
:
1163 SelObject
= dc
->DcLevel
.hpal
;
1165 case GDI_OBJECT_TYPE_FONT
:
1166 SelObject
= pdcattr
->hlfntNew
;
1168 case GDI_OBJECT_TYPE_BITMAP
:
1169 SelObject
= dc
->rosdc
.hBitmap
;
1171 case GDI_OBJECT_TYPE_COLORSPACE
:
1172 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1173 // SelObject = dc->DcLevel.pColorSpace.BaseObject.hHmgr; ?
1178 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1187 IntCalcFillOrigin(PDC pdc
)
1189 pdc
->ptlFillOrigin
.x
= pdc
->DcLevel
.ptlBrushOrigin
.x
+ pdc
->ptlDCOrig
.x
;
1190 pdc
->ptlFillOrigin
.y
= pdc
->DcLevel
.ptlBrushOrigin
.y
+ pdc
->ptlDCOrig
.y
;
1192 return pdc
->ptlFillOrigin
.y
;
1197 GdiSetDCOrg(HDC hDC
, LONG Left
, LONG Top
, PRECTL prc
)
1201 pdc
= DC_LockDc(hDC
);
1204 pdc
->ptlDCOrig
.x
= Left
;
1205 pdc
->ptlDCOrig
.y
= Top
;
1207 IntCalcFillOrigin(pdc
);
1209 if (prc
) pdc
->erclWindow
= *prc
;
1216 IntGdiGetDCOrg(PDC pDc
, PPOINTL ppt
)
1218 *ppt
= pDc
->ptlDCOrig
;
1223 GdiGetDCOrgEx(HDC hDC
, PPOINTL ppt
, PRECTL prc
)
1227 pdc
= DC_LockDc(hDC
);
1228 if (!pdc
) return FALSE
;
1230 *prc
= pdc
->erclWindow
;
1231 *ppt
= pdc
->ptlDCOrig
;
1238 IntGetAspectRatioFilter(PDC pDC
,
1243 pdcattr
= pDC
->pdcattr
;
1245 if ( pdcattr
->flFontMapper
& 1 ) // TRUE assume 1.
1247 // "This specifies that Windows should only match fonts that have the
1248 // same aspect ratio as the display.", Programming Windows, Fifth Ed.
1249 AspectRatio
->cx
= ((PGDIDEVICE
)pDC
->ppdev
)->GDIInfo
.ulLogPixelsX
;
1250 AspectRatio
->cy
= ((PGDIDEVICE
)pDC
->ppdev
)->GDIInfo
.ulLogPixelsY
;
1254 AspectRatio
->cx
= 0;
1255 AspectRatio
->cy
= 0;
1262 IntGetViewportExtEx(PDC pdc
, LPSIZE pSize
)
1266 /* Get a pointer to the dc attribute */
1267 pdcattr
= pdc
->pdcattr
;
1269 /* Check if we need to recalculate */
1270 if (pdcattr
->flXform
& PAGE_EXTENTS_CHANGED
)
1272 /* Check if we need to do isotropic fixup */
1273 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
1275 IntFixIsotropicMapping(pdc
);
1278 /* Update xforms, CHECKME: really done here? */
1279 DC_UpdateXforms(pdc
);
1282 /* Copy the viewport extension */
1283 *pSize
= pdcattr
->szlViewportExt
;
1287 NtGdiGetDCPoint( HDC hDC
, UINT iPoint
, PPOINTL Point
)
1293 NTSTATUS Status
= STATUS_SUCCESS
;
1297 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1301 RtlZeroMemory(&SafePoint
, sizeof(POINT
));
1303 dc
= DC_LockDc(hDC
);
1306 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1312 case GdiGetViewPortExt
:
1313 IntGetViewportExtEx(dc
, &Size
);
1314 SafePoint
.x
= Size
.cx
;
1315 SafePoint
.y
= Size
.cy
;
1317 case GdiGetWindowExt
:
1318 IntGetWindowExtEx(dc
, &Size
);
1319 SafePoint
.x
= Size
.cx
;
1320 SafePoint
.y
= Size
.cy
;
1322 case GdiGetViewPortOrg
:
1323 IntGetViewportOrgEx(dc
, &SafePoint
);
1325 case GdiGetWindowOrg
:
1326 IntGetWindowOrgEx(dc
, &SafePoint
);
1329 Ret
= IntGdiGetDCOrg(dc
, &SafePoint
);
1331 case GdiGetAspectRatioFilter
:
1332 Ret
= IntGetAspectRatioFilter(dc
, &Size
);
1333 SafePoint
.x
= Size
.cx
;
1334 SafePoint
.y
= Size
.cy
;
1337 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1346 ProbeForWrite(Point
,
1351 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1353 Status
= _SEH2_GetExceptionCode();
1358 if(!NT_SUCCESS(Status
))
1360 SetLastNtError(Status
);
1371 IntGdiCopyToSaveState(PDC dc
, PDC newdc
)
1373 PDC_ATTR pdcattr
, nDc_Attr
;
1375 pdcattr
= dc
->pdcattr
;
1376 nDc_Attr
= newdc
->pdcattr
;
1378 newdc
->DcLevel
.flPath
= dc
->DcLevel
.flPath
| DCPATH_SAVESTATE
;
1380 nDc_Attr
->dwLayout
= pdcattr
->dwLayout
;
1381 nDc_Attr
->hpen
= pdcattr
->hpen
;
1382 nDc_Attr
->hbrush
= pdcattr
->hbrush
;
1383 nDc_Attr
->hlfntNew
= pdcattr
->hlfntNew
;
1384 newdc
->rosdc
.hBitmap
= dc
->rosdc
.hBitmap
;
1385 newdc
->DcLevel
.hpal
= dc
->DcLevel
.hpal
;
1386 newdc
->rosdc
.bitsPerPixel
= dc
->rosdc
.bitsPerPixel
;
1387 nDc_Attr
->jROP2
= pdcattr
->jROP2
;
1388 nDc_Attr
->jFillMode
= pdcattr
->jFillMode
;
1389 nDc_Attr
->jStretchBltMode
= pdcattr
->jStretchBltMode
;
1390 nDc_Attr
->lRelAbs
= pdcattr
->lRelAbs
;
1391 nDc_Attr
->jBkMode
= pdcattr
->jBkMode
;
1392 nDc_Attr
->lBkMode
= pdcattr
->lBkMode
;
1393 nDc_Attr
->crBackgroundClr
= pdcattr
->crBackgroundClr
;
1394 nDc_Attr
->crForegroundClr
= pdcattr
->crForegroundClr
;
1395 nDc_Attr
->ulBackgroundClr
= pdcattr
->ulBackgroundClr
;
1396 nDc_Attr
->ulForegroundClr
= pdcattr
->ulForegroundClr
;
1397 nDc_Attr
->ptlBrushOrigin
= pdcattr
->ptlBrushOrigin
;
1398 nDc_Attr
->lTextAlign
= pdcattr
->lTextAlign
;
1399 nDc_Attr
->lTextExtra
= pdcattr
->lTextExtra
;
1400 nDc_Attr
->cBreak
= pdcattr
->cBreak
;
1401 nDc_Attr
->lBreakExtra
= pdcattr
->lBreakExtra
;
1402 nDc_Attr
->iMapMode
= pdcattr
->iMapMode
;
1403 nDc_Attr
->iGraphicsMode
= pdcattr
->iGraphicsMode
;
1405 /* Apparently, the DC origin is not changed by [GS]etDCState */
1406 newdc
->ptlDCOrig
.x
= dc
->ptlDCOrig
.x
;
1407 newdc
->ptlDCOrig
.y
= dc
->ptlDCOrig
.y
;
1409 nDc_Attr
->ptlCurrent
= pdcattr
->ptlCurrent
;
1410 nDc_Attr
->ptfxCurrent
= pdcattr
->ptfxCurrent
;
1411 newdc
->DcLevel
.mxWorldToDevice
= dc
->DcLevel
.mxWorldToDevice
;
1412 newdc
->DcLevel
.mxDeviceToWorld
= dc
->DcLevel
.mxDeviceToWorld
;
1413 newdc
->DcLevel
.mxWorldToPage
= dc
->DcLevel
.mxWorldToPage
;
1414 nDc_Attr
->flXform
= pdcattr
->flXform
;
1415 nDc_Attr
->ptlWindowOrg
= pdcattr
->ptlWindowOrg
;
1416 nDc_Attr
->szlWindowExt
= pdcattr
->szlWindowExt
;
1417 nDc_Attr
->ptlViewportOrg
= pdcattr
->ptlViewportOrg
;
1418 nDc_Attr
->szlViewportExt
= pdcattr
->szlViewportExt
;
1420 newdc
->DcLevel
.lSaveDepth
= 0;
1421 newdc
->dctype
= dc
->dctype
;
1424 PATH_InitGdiPath( &newdc
->DcLevel
.hPath
);
1427 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1429 newdc
->rosdc
.hGCClipRgn
= newdc
->rosdc
.hVisRgn
= 0;
1430 if (dc
->rosdc
.hClipRgn
)
1432 newdc
->rosdc
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1433 NtGdiCombineRgn( newdc
->rosdc
.hClipRgn
, dc
->rosdc
.hClipRgn
, 0, RGN_COPY
);
1440 IntGdiCopyFromSaveState(PDC dc
, PDC dcs
, HDC hDC
)
1442 PDC_ATTR pdcattr
, sDc_Attr
;
1444 pdcattr
= dc
->pdcattr
;
1445 sDc_Attr
= dcs
->pdcattr
;
1447 dc
->DcLevel
.flPath
= dcs
->DcLevel
.flPath
& ~DCPATH_SAVESTATE
;
1449 pdcattr
->dwLayout
= sDc_Attr
->dwLayout
;
1450 pdcattr
->jROP2
= sDc_Attr
->jROP2
;
1451 pdcattr
->jFillMode
= sDc_Attr
->jFillMode
;
1452 pdcattr
->jStretchBltMode
= sDc_Attr
->jStretchBltMode
;
1453 pdcattr
->lRelAbs
= sDc_Attr
->lRelAbs
;
1454 pdcattr
->jBkMode
= sDc_Attr
->jBkMode
;
1455 pdcattr
->crBackgroundClr
= sDc_Attr
->crBackgroundClr
;
1456 pdcattr
->crForegroundClr
= sDc_Attr
->crForegroundClr
;
1457 pdcattr
->lBkMode
= sDc_Attr
->lBkMode
;
1458 pdcattr
->ulBackgroundClr
= sDc_Attr
->ulBackgroundClr
;
1459 pdcattr
->ulForegroundClr
= sDc_Attr
->ulForegroundClr
;
1460 pdcattr
->ptlBrushOrigin
= sDc_Attr
->ptlBrushOrigin
;
1462 pdcattr
->lTextAlign
= sDc_Attr
->lTextAlign
;
1463 pdcattr
->lTextExtra
= sDc_Attr
->lTextExtra
;
1464 pdcattr
->cBreak
= sDc_Attr
->cBreak
;
1465 pdcattr
->lBreakExtra
= sDc_Attr
->lBreakExtra
;
1466 pdcattr
->iMapMode
= sDc_Attr
->iMapMode
;
1467 pdcattr
->iGraphicsMode
= sDc_Attr
->iGraphicsMode
;
1469 /* Apparently, the DC origin is not changed by [GS]etDCState */
1470 dc
->ptlDCOrig
.x
= dcs
->ptlDCOrig
.x
;
1471 dc
->ptlDCOrig
.y
= dcs
->ptlDCOrig
.y
;
1473 pdcattr
->ptlCurrent
= sDc_Attr
->ptlCurrent
;
1474 pdcattr
->ptfxCurrent
= sDc_Attr
->ptfxCurrent
;
1475 dc
->DcLevel
.mxWorldToDevice
= dcs
->DcLevel
.mxWorldToDevice
;
1476 dc
->DcLevel
.mxDeviceToWorld
= dcs
->DcLevel
.mxDeviceToWorld
;
1477 dc
->DcLevel
.mxWorldToPage
= dcs
->DcLevel
.mxWorldToPage
;
1478 pdcattr
->flXform
= sDc_Attr
->flXform
;
1479 pdcattr
->ptlWindowOrg
= sDc_Attr
->ptlWindowOrg
;
1480 pdcattr
->szlWindowExt
= sDc_Attr
->szlWindowExt
;
1481 pdcattr
->ptlViewportOrg
= sDc_Attr
->ptlViewportOrg
;
1482 pdcattr
->szlViewportExt
= sDc_Attr
->szlViewportExt
;
1484 if (dc
->dctype
!= DC_TYPE_MEMORY
)
1486 dc
->rosdc
.bitsPerPixel
= dcs
->rosdc
.bitsPerPixel
;
1490 if (dcs
->rosdc
.hClipRgn
)
1492 if (!dc
->rosdc
.hClipRgn
)
1494 dc
->rosdc
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1496 NtGdiCombineRgn( dc
->rosdc
.hClipRgn
, dcs
->rosdc
.hClipRgn
, 0, RGN_COPY
);
1500 if (dc
->rosdc
.hClipRgn
)
1502 NtGdiDeleteObject( dc
->rosdc
.hClipRgn
);
1504 dc
->rosdc
.hClipRgn
= 0;
1508 res
= CLIPPING_UpdateGCRegion( dc
);
1509 ASSERT ( res
!= ERROR
);
1513 GdiExtSelectClipRgn(dc
, dcs
->rosdc
.hClipRgn
, RGN_COPY
);
1516 if(!hDC
) return; // Not a MemoryDC or SaveLevel DC, return.
1518 NtGdiSelectBitmap( hDC
, dcs
->rosdc
.hBitmap
);
1519 NtGdiSelectBrush( hDC
, sDc_Attr
->hbrush
);
1520 NtGdiSelectFont( hDC
, sDc_Attr
->hlfntNew
);
1521 NtGdiSelectPen( hDC
, sDc_Attr
->hpen
);
1523 IntGdiSetBkColor( hDC
, sDc_Attr
->crBackgroundClr
);
1524 IntGdiSetTextColor( hDC
, sDc_Attr
->crForegroundClr
);
1526 GdiSelectPalette( hDC
, dcs
->DcLevel
.hpal
, FALSE
);
1529 GDISelectPalette16( hDC
, dcs
->DcLevel
.hpal
, FALSE
);
1534 IntGdiGetDCState(HDC hDC
)
1539 dc
= DC_LockDc(hDC
);
1542 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1546 hnewdc
= DC_AllocDC(NULL
);
1552 newdc
= DC_LockDc( hnewdc
);
1553 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1556 newdc
->DcLevel
.hdcSave
= hnewdc
;
1557 IntGdiCopyToSaveState( dc
, newdc
);
1559 DC_UnlockDc( newdc
);
1567 IntGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1571 dc
= DC_LockDc ( hDC
);
1574 dcs
= DC_LockDc ( hDCSave
);
1577 if ( dcs
->DcLevel
.flPath
& DCPATH_SAVESTATE
)
1579 IntGdiCopyFromSaveState( dc
, dcs
, dc
->DcLevel
.hdcSave
);
1585 DC_UnlockDc ( dcs
);
1590 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1594 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1599 IntcFonts(PGDIDEVICE pDevObj
)
1602 // Msdn DrvQueryFont:
1603 // If the number of fonts in DEVINFO is -1 and iFace is zero, the driver
1604 // should return the number of fonts it supports.
1605 if ( pDevObj
->DevInfo
.cFonts
== -1)
1607 if (pDevObj
->DriverFunctions
.QueryFont
)
1608 pDevObj
->DevInfo
.cFonts
=
1609 (ULONG
)pDevObj
->DriverFunctions
.QueryFont(pDevObj
->hPDev
, 0, 0, &Junk
);
1611 pDevObj
->DevInfo
.cFonts
= 0;
1613 return pDevObj
->DevInfo
.cFonts
;
1618 IntGetColorManagementCaps(PGDIDEVICE pDevObj
)
1622 if ( pDevObj
->flFlags
& PDEV_DISPLAY
)
1624 if ( pDevObj
->DevInfo
.iDitherFormat
== BMF_8BPP
||
1625 pDevObj
->DevInfo
.flGraphicsCaps2
& GCAPS2_CHANGEGAMMARAMP
)
1626 ret
= CM_GAMMA_RAMP
;
1628 if (pDevObj
->DevInfo
.flGraphicsCaps
& GCAPS_CMYKCOLOR
)
1629 ret
|= CM_CMYK_COLOR
;
1630 if (pDevObj
->DevInfo
.flGraphicsCaps
& GCAPS_ICM
)
1631 ret
|= CM_DEVICE_ICM
;
1636 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1639 PGDIDEVICE ppdev
= dc
->ppdev
;
1640 /* Retrieve capability */
1644 ret
= ppdev
->GDIInfo
.ulVersion
;
1648 ret
= ppdev
->GDIInfo
.ulTechnology
;
1652 ret
= ppdev
->GDIInfo
.ulHorzSize
;
1656 ret
= ppdev
->GDIInfo
.ulVertSize
;
1660 ret
= ppdev
->GDIInfo
.ulHorzRes
;
1664 ret
= ppdev
->GDIInfo
.ulVertRes
;
1668 ret
= ppdev
->GDIInfo
.ulLogPixelsX
;
1672 ret
= ppdev
->GDIInfo
.ulLogPixelsY
;
1676 if ( ppdev
->pGraphicsDev
&&
1677 (((PGRAPHICS_DEVICE
)ppdev
->pGraphicsDev
)->StateFlags
&
1678 DISPLAY_DEVICE_MIRRORING_DRIVER
))
1683 ret
= ppdev
->GDIInfo
.cBitsPixel
;
1687 ret
= ppdev
->GDIInfo
.cPlanes
;
1695 ret
= ppdev
->GDIInfo
.ulNumColors
;
1696 if ( ret
!= -1 ) ret
*= 5;
1700 ret
= IntcFonts(ppdev
);
1704 ret
= ppdev
->GDIInfo
.ulNumColors
;
1708 ret
= ppdev
->GDIInfo
.ulAspectX
;
1712 ret
= ppdev
->GDIInfo
.ulAspectY
;
1716 ret
= ppdev
->GDIInfo
.ulAspectXY
;
1724 ret
= ppdev
->GDIInfo
.ulNumPalReg
;
1732 ret
= ppdev
->GDIInfo
.ulDACRed
+
1733 ppdev
->GDIInfo
.ulDACGreen
+
1734 ppdev
->GDIInfo
.ulDACBlue
;
1737 case DESKTOPVERTRES
:
1738 ret
= ppdev
->GDIInfo
.ulVertRes
;
1741 case DESKTOPHORZRES
:
1742 ret
= ppdev
->GDIInfo
.ulHorzRes
;
1746 ret
= ppdev
->GDIInfo
.ulBltAlignment
;
1749 case SHADEBLENDCAPS
:
1750 ret
= ppdev
->GDIInfo
.flShadeBlend
;
1754 ret
= IntGetColorManagementCaps(ppdev
);
1758 ret
= ppdev
->GDIInfo
.szlPhysSize
.cx
;
1761 case PHYSICALHEIGHT
:
1762 ret
= ppdev
->GDIInfo
.szlPhysSize
.cy
;
1765 case PHYSICALOFFSETX
:
1766 ret
= ppdev
->GDIInfo
.ptlPhysOffset
.x
;
1769 case PHYSICALOFFSETY
:
1770 ret
= ppdev
->GDIInfo
.ptlPhysOffset
.y
;
1774 ret
= ppdev
->GDIInfo
.ulVRefresh
;
1778 ret
= ppdev
->GDIInfo
.flRaster
;
1782 ret
= (CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
| CC_WIDE
|
1783 CC_STYLED
| CC_WIDESTYLED
| CC_INTERIORS
| CC_ROUNDRECT
);
1787 ret
= (LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
1788 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
);
1792 ret
= (PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
| PC_SCANLINE
|
1793 PC_WIDE
| PC_STYLED
| PC_WIDESTYLED
| PC_INTERIORS
);
1797 ret
= ppdev
->GDIInfo
.flTextCaps
;
1798 if (ppdev
->GDIInfo
.ulTechnology
) ret
|= TC_VA_ABLE
;
1799 ret
|= (TC_SO_ABLE
|TC_UA_ABLE
);
1803 case SCALINGFACTORX
:
1804 case SCALINGFACTORY
:
1814 NtGdiGetDeviceCaps(HDC hDC
,
1820 dc
= DC_LockDc(hDC
);
1823 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1827 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1829 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1842 PGDIINFO pGdiInfo
= &pDevObj
->GDIInfo
;
1844 pDevCaps
->ulVersion
= pGdiInfo
->ulVersion
;
1845 pDevCaps
->ulTechnology
= pGdiInfo
->ulTechnology
;
1846 pDevCaps
->ulHorzSizeM
= (pGdiInfo
->ulHorzSize
+ 500) / 1000;
1847 pDevCaps
->ulVertSizeM
= (pGdiInfo
->ulVertSize
+ 500) / 1000;
1848 pDevCaps
->ulHorzSize
= pGdiInfo
->ulHorzSize
;
1849 pDevCaps
->ulVertSize
= pGdiInfo
->ulVertSize
;
1850 pDevCaps
->ulHorzRes
= pGdiInfo
->ulHorzRes
;
1851 pDevCaps
->ulVertRes
= pGdiInfo
->ulVertRes
;
1852 pDevCaps
->ulVRefresh
= pGdiInfo
->ulVRefresh
;
1853 pDevCaps
->ulDesktopHorzRes
= pGdiInfo
->ulHorzRes
;
1854 pDevCaps
->ulDesktopVertRes
= pGdiInfo
->ulVertRes
;
1855 pDevCaps
->ulBltAlignment
= pGdiInfo
->ulBltAlignment
;
1856 pDevCaps
->ulPlanes
= pGdiInfo
->cPlanes
;
1858 pDevCaps
->ulBitsPixel
= pGdiInfo
->cBitsPixel
;
1859 if (pGdiInfo
->cBitsPixel
== 15) pDevCaps
->ulBitsPixel
= 16;
1861 Tmp
= pGdiInfo
->ulNumColors
;
1862 if ( Tmp
!= -1 ) Tmp
*= 5;
1863 pDevCaps
->ulNumPens
= Tmp
;
1864 pDevCaps
->ulNumColors
= pGdiInfo
->ulNumColors
;
1866 pDevCaps
->ulNumFonts
= IntcFonts(pDevObj
);
1868 pDevCaps
->ulRasterCaps
= pGdiInfo
->flRaster
;
1869 pDevCaps
->ulShadeBlend
= pGdiInfo
->flShadeBlend
;
1870 pDevCaps
->ulAspectX
= pGdiInfo
->ulAspectX
;
1871 pDevCaps
->ulAspectY
= pGdiInfo
->ulAspectY
;
1872 pDevCaps
->ulAspectXY
= pGdiInfo
->ulAspectXY
;
1873 pDevCaps
->ulLogPixelsX
= pGdiInfo
->ulLogPixelsX
;
1874 pDevCaps
->ulLogPixelsY
= pGdiInfo
->ulLogPixelsY
;
1875 pDevCaps
->ulSizePalette
= pGdiInfo
->ulNumPalReg
;
1876 pDevCaps
->ulColorRes
= pGdiInfo
->ulDACRed
+ pGdiInfo
->ulDACGreen
+ pGdiInfo
->ulDACBlue
;
1877 pDevCaps
->ulPhysicalWidth
= pGdiInfo
->szlPhysSize
.cx
;
1878 pDevCaps
->ulPhysicalHeight
= pGdiInfo
->szlPhysSize
.cy
;
1879 pDevCaps
->ulPhysicalOffsetX
= pGdiInfo
->ptlPhysOffset
.x
;
1880 pDevCaps
->ulPhysicalOffsetY
= pGdiInfo
->ptlPhysOffset
.y
;
1881 pDevCaps
->ulPanningHorzRes
= pGdiInfo
->ulPanningHorzRes
;
1882 pDevCaps
->ulPanningVertRes
= pGdiInfo
->ulPanningVertRes
;
1883 pDevCaps
->xPanningAlignment
= pGdiInfo
->xPanningAlignment
;
1884 pDevCaps
->yPanningAlignment
= pGdiInfo
->yPanningAlignment
;
1887 Tmp
= pGdiInfo
->flTextCaps
| (TC_SO_ABLE
|TC_UA_ABLE
|TC_CP_STROKE
|TC_OP_STROKE
|TC_OP_CHARACTER
);
1889 pDevCaps
->ulTextCaps
= pGdiInfo
->flTextCaps
| (TC_SO_ABLE
|TC_UA_ABLE
|TC_CP_STROKE
|TC_OP_STROKE
|TC_OP_CHARACTER
);
1891 if (pGdiInfo
->ulTechnology
)
1892 pDevCaps
->ulTextCaps
= Tmp
| TC_VA_ABLE
;
1894 pDevCaps
->ulColorMgmtCaps
= IntGetColorManagementCaps(pDevObj
);
1904 NtGdiGetDeviceCapsAll (
1906 OUT PDEVCAPS pDevCaps
)
1909 PDEVCAPS pSafeDevCaps
;
1910 NTSTATUS Status
= STATUS_SUCCESS
;
1912 dc
= DC_LockDc(hDC
);
1915 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1919 pSafeDevCaps
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVCAPS
), TAG_TEMP
);
1927 IntvGetDeviceCaps(dc
->ppdev
, pSafeDevCaps
);
1931 ProbeForWrite(pDevCaps
,
1934 RtlCopyMemory(pDevCaps
, pSafeDevCaps
, sizeof(DEVCAPS
));
1936 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1938 Status
= _SEH2_GetExceptionCode();
1942 ExFreePoolWithTag(pSafeDevCaps
, TAG_TEMP
);
1945 if (!NT_SUCCESS(Status
))
1947 SetLastNtError(Status
);
1960 OUT PBOOL pbBanding
,
1961 IN OPTIONAL VOID
*pDriverInfo2
,
1962 OUT VOID
*ppUMdhpdev
)
1969 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1974 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1976 dc
= DC_LockDc(hDC
);
1979 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1984 SaveLevel
= dc
->DcLevel
.lSaveDepth
+ SaveLevel
+ 1;
1986 if(SaveLevel
< 0 || dc
->DcLevel
.lSaveDepth
<SaveLevel
)
1993 while (dc
->DcLevel
.lSaveDepth
>= SaveLevel
)
1995 HDC hdcs
= DC_GetNextDC (dc
);
1997 dcs
= DC_LockDc (hdcs
);
2004 DC_SetNextDC (dc
, DC_GetNextDC (dcs
));
2007 if (--dc
->DcLevel
.lSaveDepth
< SaveLevel
)
2012 IntGdiSetDCState(hDC
, hdcs
);
2014 dc
= DC_LockDc(hDC
);
2019 // Restore Path by removing it, if the Save flag is set.
2020 // BeginPath will takecare of the rest.
2021 if ( dc
->DcLevel
.hPath
&& dc
->DcLevel
.flPath
& DCPATH_SAVE
)
2023 PATH_Delete(dc
->DcLevel
.hPath
);
2024 dc
->DcLevel
.hPath
= 0;
2025 dc
->DcLevel
.flPath
&= ~DCPATH_SAVE
;
2032 NtGdiDeleteObjectApp (hdcs
);
2040 NtGdiSaveDC(HDC hDC
)
2046 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
2048 if (!(hdcs
= IntGdiGetDCState(hDC
)))
2053 dcs
= DC_LockDc (hdcs
);
2056 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2059 dc
= DC_LockDc (hDC
);
2063 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2070 dcs
->DcLevel
.hPath
= dc
->DcLevel
.hPath
;
2071 if (dcs
->DcLevel
.hPath
) dcs
->DcLevel
.flPath
|= DCPATH_SAVE
;
2073 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
2074 DC_SetNextDC (dc
, hdcs
);
2075 ret
= ++dc
->DcLevel
.lSaveDepth
;
2085 GdiSelectPalette(HDC hDC
,
2087 BOOL ForceBackground
)
2090 HPALETTE oldPal
= NULL
;
2093 // FIXME: mark the palette as a [fore\back]ground pal
2094 dc
= DC_LockDc(hDC
);
2100 /* Check if this is a valid palette handle */
2101 PalGDI
= PALETTE_LockPalette(hpal
);
2108 /* Is this a valid palette for this depth? */
2109 if ((dc
->rosdc
.bitsPerPixel
<= 8 && PalGDI
->Mode
== PAL_INDEXED
) ||
2110 (dc
->rosdc
.bitsPerPixel
> 8 && PalGDI
->Mode
!= PAL_INDEXED
))
2112 oldPal
= dc
->DcLevel
.hpal
;
2113 dc
->DcLevel
.hpal
= hpal
;
2115 else if (8 < dc
->rosdc
.bitsPerPixel
&& PAL_INDEXED
== PalGDI
->Mode
)
2117 oldPal
= dc
->DcLevel
.hpal
;
2118 dc
->DcLevel
.hpal
= hpal
;
2121 PALETTE_UnlockPalette(PalGDI
);
2128 IntGdiSetHookFlags(HDC hDC
, WORD Flags
)
2131 DC
*dc
= DC_LockDc(hDC
);
2135 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2139 wRet
= dc
->fs
& DC_FLAG_DIRTY_RAO
; // Fixme wrong flag!
2141 /* "Undocumented Windows" info is slightly confusing.
2144 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2146 if (Flags
& DCHF_INVALIDATEVISRGN
)
2147 { /* hVisRgn has to be updated */
2148 dc
->fs
|= DC_FLAG_DIRTY_RAO
;
2150 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2152 dc
->fs
&= ~DC_FLAG_DIRTY_RAO
;
2173 DWORD SafeResult
= 0;
2174 NTSTATUS Status
= STATUS_SUCCESS
;
2178 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2182 dc
= DC_LockDc(hDC
);
2185 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2188 pdcattr
= dc
->pdcattr
;
2195 SafeResult
= pdcattr
->lRelAbs
;
2197 case GdiGetBreakExtra
:
2198 SafeResult
= pdcattr
->lBreakExtra
;
2200 case GdiGerCharBreak
:
2201 SafeResult
= pdcattr
->cBreak
;
2203 case GdiGetArcDirection
:
2204 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
2205 SafeResult
= AD_CLOCKWISE
- ((dc
->DcLevel
.flPath
& DCPATH_CLOCKWISE
) != 0);
2207 SafeResult
= ((dc
->DcLevel
.flPath
& DCPATH_CLOCKWISE
) != 0) + AD_COUNTERCLOCKWISE
;
2209 case GdiGetEMFRestorDc
:
2211 case GdiGetFontLanguageInfo
:
2212 SafeResult
= IntGetFontLanguageInfo(dc
);
2215 SafeResult
= dc
->dctype
;
2218 SafeResult
= pdcattr
->iMapMode
;
2220 case GdiGetTextCharExtra
:
2221 SafeResult
= pdcattr
->lTextExtra
;
2224 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2233 ProbeForWrite(Result
,
2236 *Result
= SafeResult
;
2238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2240 Status
= _SEH2_GetExceptionCode();
2245 if(!NT_SUCCESS(Status
))
2247 SetLastNtError(Status
);
2258 NtGdiGetAndSetDCDword(
2269 DWORD SafeResult
= 0;
2270 NTSTATUS Status
= STATUS_SUCCESS
;
2274 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2278 dc
= DC_LockDc(hDC
);
2281 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2284 pdcattr
= dc
->pdcattr
;
2288 case GdiGetSetCopyCount
:
2289 SafeResult
= dc
->ulCopyCount
;
2290 dc
->ulCopyCount
= dwIn
;
2292 case GdiGetSetTextAlign
:
2293 SafeResult
= pdcattr
->lTextAlign
;
2294 pdcattr
->lTextAlign
= dwIn
;
2295 // pdcattr->flTextAlign = dwIn; // Flags!
2297 case GdiGetSetRelAbs
:
2298 SafeResult
= pdcattr
->lRelAbs
;
2299 pdcattr
->lRelAbs
= dwIn
;
2301 case GdiGetSetTextCharExtra
:
2302 SafeResult
= pdcattr
->lTextExtra
;
2303 pdcattr
->lTextExtra
= dwIn
;
2305 case GdiGetSetSelectFont
:
2307 case GdiGetSetMapperFlagsInternal
:
2310 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2314 SafeResult
= pdcattr
->flFontMapper
;
2315 pdcattr
->flFontMapper
= dwIn
;
2317 case GdiGetSetMapMode
:
2318 SafeResult
= IntGdiSetMapMode( dc
, dwIn
);
2320 case GdiGetSetArcDirection
:
2321 if (dwIn
!= AD_COUNTERCLOCKWISE
&& dwIn
!= AD_CLOCKWISE
)
2323 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2327 if ( pdcattr
->dwLayout
& LAYOUT_RTL
) // Right to Left
2329 SafeResult
= AD_CLOCKWISE
- ((dc
->DcLevel
.flPath
& DCPATH_CLOCKWISE
) != 0);
2330 if ( dwIn
== AD_CLOCKWISE
)
2332 dc
->DcLevel
.flPath
&= ~DCPATH_CLOCKWISE
;
2335 dc
->DcLevel
.flPath
|= DCPATH_CLOCKWISE
;
2337 else // Left to Right
2339 SafeResult
= ((dc
->DcLevel
.flPath
& DCPATH_CLOCKWISE
) != 0) + AD_COUNTERCLOCKWISE
;
2340 if ( dwIn
== AD_COUNTERCLOCKWISE
)
2342 dc
->DcLevel
.flPath
&= ~DCPATH_CLOCKWISE
;
2345 dc
->DcLevel
.flPath
|= DCPATH_CLOCKWISE
;
2349 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2358 ProbeForWrite(Result
,
2361 *Result
= SafeResult
;
2363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2365 Status
= _SEH2_GetExceptionCode();
2370 if(!NT_SUCCESS(Status
))
2372 SetLastNtError(Status
);
2381 // ---------------------------------------------------- Private Interface
2384 DC_AllocDC(PUNICODE_STRING Driver
)
2390 XFORM xformTemplate
;
2394 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2397 DPRINT1("ExAllocatePoolWithTag failed\n");
2400 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2403 NewDC
= (PDC
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC
);
2408 ExFreePoolWithTag(Buf
, TAG_DC
);
2410 DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
2414 hDC
= NewDC
->BaseObject
.hHmgr
;
2416 NewDC
->pdcattr
= &NewDC
->Dc_Attr
;
2417 DC_AllocateDcAttr(hDC
);
2421 RtlCopyMemory(&NewDC
->rosdc
.DriverName
, Driver
, sizeof(UNICODE_STRING
));
2422 NewDC
->rosdc
.DriverName
.Buffer
= Buf
;
2424 pdcattr
= NewDC
->pdcattr
;
2426 NewDC
->BaseObject
.hHmgr
= (HGDIOBJ
) hDC
; // Save the handle for this DC object.
2428 xformTemplate
.eM11
= 1.0f
;
2429 xformTemplate
.eM12
= 0.0f
;
2430 xformTemplate
.eM21
= 0.0f
;
2431 xformTemplate
.eM22
= 1.0f
;
2432 xformTemplate
.eDx
= 0.0f
;
2433 xformTemplate
.eDy
= 0.0f
;
2434 XForm2MatrixS(&NewDC
->DcLevel
.mxWorldToDevice
, &xformTemplate
);
2435 XForm2MatrixS(&NewDC
->DcLevel
.mxDeviceToWorld
, &xformTemplate
);
2436 XForm2MatrixS(&NewDC
->DcLevel
.mxWorldToPage
, &xformTemplate
);
2438 // Setup syncing bits for the dcattr data packets.
2439 pdcattr
->flXform
= DEVICE_TO_PAGE_INVALID
;
2441 pdcattr
->ulDirty_
= 0; // Server side
2443 pdcattr
->iMapMode
= MM_TEXT
;
2444 pdcattr
->iGraphicsMode
= GM_COMPATIBLE
;
2445 pdcattr
->jFillMode
= ALTERNATE
;
2447 pdcattr
->szlWindowExt
.cx
= 1; // Float to Int,,, WRONG!
2448 pdcattr
->szlWindowExt
.cy
= 1;
2449 pdcattr
->szlViewportExt
.cx
= 1;
2450 pdcattr
->szlViewportExt
.cy
= 1;
2452 pdcattr
->crForegroundClr
= 0;
2453 pdcattr
->ulForegroundClr
= 0;
2455 pdcattr
->ulBackgroundClr
= 0xffffff;
2456 pdcattr
->crBackgroundClr
= 0xffffff;
2458 pdcattr
->ulPenClr
= RGB( 0, 0, 0 );
2459 pdcattr
->crPenClr
= RGB( 0, 0, 0 );
2461 pdcattr
->ulBrushClr
= RGB( 255, 255, 255 ); // Do this way too.
2462 pdcattr
->crBrushClr
= RGB( 255, 255, 255 );
2464 //// This fixes the default brush and pen settings. See DC_InitDC.
2465 pdcattr
->hbrush
= NtGdiGetStockObject( WHITE_BRUSH
);
2466 pdcattr
->hpen
= NtGdiGetStockObject( BLACK_PEN
);
2468 pdcattr
->hlfntNew
= NtGdiGetStockObject(SYSTEM_FONT
);
2469 TextIntRealizeFont(pdcattr
->hlfntNew
,NULL
);
2471 NewDC
->DcLevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2472 NewDC
->DcLevel
.laPath
.eMiterLimit
= 10.0;
2480 DC_FindOpenDC(PUNICODE_STRING Driver
)
2486 * Initialize some common fields in the Device Context structure.
2489 DC_InitDC(HDC DCHandle
)
2491 // NtGdiRealizeDefaultPalette(DCHandle);
2493 //// Removed for now.. See above brush and pen.
2494 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
2495 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
2497 //NtGdiSelectFont(DCHandle, hFont);
2502 res = CLIPPING_UpdateGCRegion(DCToInit);
2503 ASSERT ( res != ERROR );
2510 DC_AllocateDcAttr(HDC hDC
)
2512 PVOID NewMem
= NULL
;
2514 HANDLE Pid
= NtCurrentProcess();
2515 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE it will allocate that size
2517 NTSTATUS Status
= ZwAllocateVirtualMemory(Pid
,
2521 MEM_COMMIT
|MEM_RESERVE
,
2523 KeEnterCriticalRegion();
2525 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hDC
);
2526 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2527 // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
2528 if (NT_SUCCESS(Status
))
2530 RtlZeroMemory(NewMem
, MemSize
);
2531 Entry
->UserData
= NewMem
;
2532 DPRINT("DC_ATTR allocated! 0x%x\n",NewMem
);
2536 DPRINT("DC_ATTR not allocated!\n");
2539 KeLeaveCriticalRegion();
2540 pDC
= DC_LockDc(hDC
);
2541 ASSERT(pDC
->pdcattr
== &pDC
->Dc_Attr
);
2544 pDC
->pdcattr
= NewMem
; // Store pointer
2551 DC_FreeDcAttr(HDC DCToFree
)
2553 HANDLE Pid
= NtCurrentProcess();
2554 PDC pDC
= DC_LockDc(DCToFree
);
2555 if (pDC
->pdcattr
== &pDC
->Dc_Attr
) return; // Internal DC object!
2556 pDC
->pdcattr
= &pDC
->Dc_Attr
;
2559 KeEnterCriticalRegion();
2561 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)DCToFree
);
2562 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
2565 ULONG MemSize
= sizeof(DC_ATTR
); //PAGE_SIZE;
2566 NTSTATUS Status
= ZwFreeVirtualMemory(Pid
,
2570 if (NT_SUCCESS(Status
))
2572 DPRINT("DC_FreeDC DC_ATTR 0x%x\n", Entry
->UserData
);
2573 Entry
->UserData
= NULL
;
2577 KeLeaveCriticalRegion();
2581 DC_FreeDC(HDC DCToFree
)
2583 DC_FreeDcAttr(DCToFree
);
2584 if(!IsObjectDead( DCToFree
))
2586 if (!GDIOBJ_FreeObjByHandle(DCToFree
, GDI_OBJECT_TYPE_DC
))
2588 DPRINT1("DC_FreeDC failed\n");
2593 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree
);
2598 DC_Cleanup(PVOID ObjectBody
)
2600 PDC pDC
= (PDC
)ObjectBody
;
2601 if (pDC
->rosdc
.DriverName
.Buffer
)
2602 ExFreePoolWithTag(pDC
->rosdc
.DriverName
.Buffer
, TAG_DC
);
2607 DC_GetNextDC (PDC pDC
)
2609 return pDC
->hdcNext
;
2613 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2615 pDC
->hdcNext
= hNextDC
;
2619 DC_UpdateXforms(PDC dc
)
2621 XFORM xformWnd2Vport
;
2622 FLOAT scaleX
, scaleY
;
2623 PDC_ATTR pdcattr
= dc
->pdcattr
;
2624 XFORM xformWorld2Vport
, xformWorld2Wnd
, xformVport2World
;
2626 /* Construct a transformation to do the window-to-viewport conversion */
2627 scaleX
= (pdcattr
->szlWindowExt
.cx
? (FLOAT
)pdcattr
->szlViewportExt
.cx
/ (FLOAT
)pdcattr
->szlWindowExt
.cx
: 0.0f
);
2628 scaleY
= (pdcattr
->szlWindowExt
.cy
? (FLOAT
)pdcattr
->szlViewportExt
.cy
/ (FLOAT
)pdcattr
->szlWindowExt
.cy
: 0.0f
);
2629 xformWnd2Vport
.eM11
= scaleX
;
2630 xformWnd2Vport
.eM12
= 0.0;
2631 xformWnd2Vport
.eM21
= 0.0;
2632 xformWnd2Vport
.eM22
= scaleY
;
2633 xformWnd2Vport
.eDx
= (FLOAT
)pdcattr
->ptlViewportOrg
.x
- scaleX
* (FLOAT
)pdcattr
->ptlWindowOrg
.x
;
2634 xformWnd2Vport
.eDy
= (FLOAT
)pdcattr
->ptlViewportOrg
.y
- scaleY
* (FLOAT
)pdcattr
->ptlWindowOrg
.y
;
2636 /* Combine with the world transformation */
2637 MatrixS2XForm(&xformWorld2Vport
, &dc
->DcLevel
.mxWorldToDevice
);
2638 MatrixS2XForm(&xformWorld2Wnd
, &dc
->DcLevel
.mxWorldToPage
);
2639 IntGdiCombineTransform(&xformWorld2Vport
, &xformWorld2Wnd
, &xformWnd2Vport
);
2641 /* Create inverse of world-to-viewport transformation */
2642 MatrixS2XForm(&xformVport2World
, &dc
->DcLevel
.mxDeviceToWorld
);
2643 if (DC_InvertXform(&xformWorld2Vport
, &xformVport2World
))
2645 pdcattr
->flXform
&= ~DEVICE_TO_WORLD_INVALID
;
2649 pdcattr
->flXform
|= DEVICE_TO_WORLD_INVALID
;
2652 XForm2MatrixS(&dc
->DcLevel
.mxWorldToDevice
, &xformWorld2Vport
);
2657 DC_InvertXform(const XFORM
*xformSrc
,
2662 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2663 if (determinant
> -1e-12 && determinant
< 1e-12)
2668 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2669 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2670 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2671 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2672 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2673 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2680 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2684 if(!GDIOBJ_SetOwnership(hDC
, Owner
)) return FALSE
;
2685 pDC
= DC_LockDc(hDC
);
2688 if (pDC
->rosdc
.hClipRgn
)
2690 if(!GDIOBJ_SetOwnership(pDC
->rosdc
.hClipRgn
, Owner
)) return FALSE
;
2692 if (pDC
->rosdc
.hVisRgn
)
2694 if(!GDIOBJ_SetOwnership(pDC
->rosdc
.hVisRgn
, Owner
)) return FALSE
;
2696 if (pDC
->rosdc
.hGCClipRgn
)
2698 if(!GDIOBJ_SetOwnership(pDC
->rosdc
.hGCClipRgn
, Owner
)) return FALSE
;
2700 if (pDC
->DcLevel
.hPath
)
2702 if(!GDIOBJ_SetOwnership(pDC
->DcLevel
.hPath
, Owner
)) return FALSE
;
2710 // Support multi display/device locks.
2714 DC_LockDisplay(HDC hDC
)
2716 PERESOURCE Resource
;
2717 PDC dc
= DC_LockDc(hDC
);
2719 Resource
= ((PGDIDEVICE
)dc
->ppdev
)->hsemDevLock
;
2721 if (!Resource
) return;
2722 KeEnterCriticalRegion();
2723 ExAcquireResourceExclusiveLite( Resource
, TRUE
);
2728 DC_UnlockDisplay(HDC hDC
)
2730 PERESOURCE Resource
;
2731 PDC dc
= DC_LockDc(hDC
);
2733 Resource
= ((PGDIDEVICE
)dc
->ppdev
)->hsemDevLock
;
2735 if (!Resource
) return;
2736 ExReleaseResourceLite( Resource
);
2737 KeLeaveCriticalRegion();
2741 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2743 if (PrimarySurface
.pSurface
== NULL
)
2747 return SurfObj
->hsurf
== PrimarySurface
.pSurface
;
2756 // I guess we will soon have more than one primary surface.
2757 // This will do for now.
2758 return &PrimarySurface
;
2763 IntGdiReferencePdev(PGDIDEVICE ppdev
)
2765 if(!hsemDriverMgmt
) hsemDriverMgmt
= EngCreateSemaphore(); // Hax, should be in dllmain.c
2766 IntGdiAcquireSemaphore(hsemDriverMgmt
);
2768 IntGdiReleaseSemaphore(hsemDriverMgmt
);
2772 IntGdiUnreferencePdev(PGDIDEVICE ppdev
, DWORD CleanUpType
)
2774 IntGdiAcquireSemaphore(hsemDriverMgmt
);
2776 if (!ppdev
->cPdevRefs
)
2778 // Handle the destruction of ppdev or GDIDEVICE or PDEVOBJ or PDEV etc.
2780 IntGdiReleaseSemaphore(hsemDriverMgmt
);
2784 #define SIZEOF_DEVMODEW_300 188
2785 #define SIZEOF_DEVMODEW_400 212
2786 #define SIZEOF_DEVMODEW_500 220
2788 static NTSTATUS FASTCALL
2789 GetDisplayNumberFromDeviceName(
2790 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2791 OUT ULONG
*DisplayNumber
)
2793 UNICODE_STRING DisplayString
= RTL_CONSTANT_STRING(L
"\\\\.\\DISPLAY");
2794 NTSTATUS Status
= STATUS_SUCCESS
;
2799 if (DisplayNumber
== NULL
)
2800 return STATUS_INVALID_PARAMETER_2
;
2802 /* Check if DeviceName is valid */
2804 pDeviceName
->Length
> 0 && pDeviceName
->Length
<= DisplayString
.Length
)
2805 return STATUS_OBJECT_NAME_INVALID
;
2807 if (pDeviceName
== NULL
|| pDeviceName
->Length
== 0)
2809 PWINDOW_OBJECT DesktopObject
;
2813 DesktopObject
= UserGetDesktopWindow();
2814 DesktopHDC
= UserGetWindowDC(DesktopObject
);
2815 pDC
= DC_LockDc(DesktopHDC
);
2817 *DisplayNumber
= ((GDIDEVICE
*)pDC
->ppdev
)->DisplayNumber
;
2820 UserReleaseDC(DesktopObject
, DesktopHDC
, FALSE
);
2822 return STATUS_SUCCESS
;
2825 /* Hack to check if the first parts are equal, by faking the device name length */
2826 Length
= pDeviceName
->Length
;
2827 pDeviceName
->Length
= DisplayString
.Length
;
2828 if (RtlEqualUnicodeString(&DisplayString
, pDeviceName
, FALSE
) == FALSE
)
2829 Status
= STATUS_OBJECT_NAME_INVALID
;
2830 pDeviceName
->Length
= Length
;
2832 if (NT_SUCCESS(Status
))
2834 /* Convert the last part of pDeviceName to a number */
2836 Length
= pDeviceName
->Length
/ sizeof(WCHAR
);
2837 for (i
= DisplayString
.Length
/ sizeof(WCHAR
); i
< Length
; i
++)
2839 WCHAR Char
= pDeviceName
->Buffer
[i
];
2840 if (Char
>= L
'0' && Char
<= L
'9')
2841 Number
= Number
* 10 + Char
- L
'0';
2842 else if (Char
!= L
'\0')
2843 return STATUS_OBJECT_NAME_INVALID
;
2846 *DisplayNumber
= Number
- 1;
2852 /*! \brief Enumerate possible display settings for the given display...
2854 * \todo Make thread safe!?
2855 * \todo Don't ignore pDeviceName
2856 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2860 IntEnumDisplaySettings(
2861 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2863 IN OUT LPDEVMODEW pDevMode
,
2866 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2867 static DWORD SizeOfCachedDevModes
= 0;
2868 static UNICODE_STRING CachedDeviceName
;
2869 PDEVMODEW CachedMode
= NULL
;
2871 ULONG DisplayNumber
;
2874 Status
= GetDisplayNumberFromDeviceName(pDeviceName
, &DisplayNumber
);
2875 if (!NT_SUCCESS(Status
))
2880 DPRINT("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2881 DPRINT("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2882 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2883 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2884 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2886 return STATUS_BUFFER_TOO_SMALL
;
2889 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2891 CachedMode
= &PrimarySurface
.DMW
;
2892 ASSERT(CachedMode
->dmSize
> 0);
2894 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2896 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2897 DevMode
.dmSize
= sizeof (DevMode
);
2898 DevMode
.dmDriverExtra
= 0;
2899 if (SetupDevMode(&DevMode
, DisplayNumber
))
2900 CachedMode
= &DevMode
;
2903 return STATUS_UNSUCCESSFUL
; // FIXME: what status?
2905 /* FIXME: Maybe look for the matching devmode supplied by the
2906 * driver so we can provide driver private/extra data?
2911 BOOL IsCachedDevice
= (CachedDevModes
!= NULL
);
2913 if (CachedDevModes
&&
2914 ((pDeviceName
== NULL
&& CachedDeviceName
.Length
> 0) ||
2915 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
== 0) ||
2916 (pDeviceName
!= NULL
&& pDeviceName
->Buffer
!= NULL
&& CachedDeviceName
.Length
> 0 && RtlEqualUnicodeString(pDeviceName
, &CachedDeviceName
, TRUE
) == FALSE
)))
2918 IsCachedDevice
= FALSE
;
2921 if (iModeNum
== 0 || IsCachedDevice
== FALSE
) /* query modes from drivers */
2923 UNICODE_STRING DriverFileNames
;
2925 DRVENABLEDATA DrvEnableData
;
2927 /* Free resources from last driver cache */
2928 if (IsCachedDevice
== FALSE
&& CachedDeviceName
.Buffer
!= NULL
)
2930 RtlFreeUnicodeString(&CachedDeviceName
);
2933 /* Retrieve DDI driver names from registry */
2934 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2935 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2937 DPRINT1("FindDriverFileNames failed\n");
2938 return STATUS_UNSUCCESSFUL
;
2941 if (!IntPrepareDriverIfNeeded())
2943 DPRINT1("IntPrepareDriverIfNeeded failed\n");
2944 return STATUS_UNSUCCESSFUL
;
2948 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2949 * scan all of them until a good one found.
2951 CurrentName
= DriverFileNames
.Buffer
;
2952 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2953 CurrentName
+= wcslen(CurrentName
) + 1)
2956 PGD_ENABLEDRIVER GDEnableDriver
;
2957 PGD_GETMODES GetModes
= NULL
;
2958 INT SizeNeeded
, SizeUsed
;
2960 /* Get the DDI driver's entry point */
2961 //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
2962 GDEnableDriver
= DRIVER_FindExistingDDIDriver(L
"DISPLAY");
2963 if (NULL
== GDEnableDriver
)
2965 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2969 /* Call DDI driver's EnableDriver function */
2970 RtlZeroMemory(&DrvEnableData
, sizeof(DrvEnableData
));
2972 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2974 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2978 CachedDevModesEnd
= CachedDevModes
;
2980 /* find DrvGetModes function */
2981 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2983 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2985 if (DrvFn
->iFunc
== INDEX_DrvGetModes
)
2987 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2992 if (GetModes
== NULL
)
2994 DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName
);
2998 /* make sure we have enough memory to hold the modes */
2999 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
3000 if (SizeNeeded
<= 0)
3002 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
3006 SizeUsed
= (PCHAR
)CachedDevModesEnd
- (PCHAR
)CachedDevModes
;
3007 if (SizeOfCachedDevModes
< SizeUsed
+ SizeNeeded
)
3011 SizeOfCachedDevModes
+= SizeNeeded
;
3012 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
3013 if (NewBuffer
== NULL
)
3016 ExFreePool(CachedDevModes
);
3017 CachedDevModes
= NULL
;
3018 CachedDevModesEnd
= NULL
;
3019 SizeOfCachedDevModes
= 0;
3021 if (CachedDeviceName
.Buffer
!= NULL
)
3022 RtlFreeUnicodeString(&CachedDeviceName
);
3024 return STATUS_NO_MEMORY
;
3026 if (CachedDevModes
!= NULL
)
3028 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
3029 ExFreePool(CachedDevModes
);
3031 CachedDevModes
= NewBuffer
;
3032 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
3035 if (!IsCachedDevice
)
3037 if (CachedDeviceName
.Buffer
!= NULL
)
3038 RtlFreeUnicodeString(&CachedDeviceName
);
3041 IntSafeCopyUnicodeString(&CachedDeviceName
, pDeviceName
);
3043 IsCachedDevice
= TRUE
;
3047 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
3050 if (SizeNeeded
<= 0)
3052 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
3056 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
3060 ExFreePoolWithTag(DriverFileNames
.Buffer
, TAG_RTLREGISTRY
);
3063 /* return cached info */
3064 CachedMode
= CachedDevModes
;
3065 if (CachedMode
>= CachedDevModesEnd
)
3067 return STATUS_NO_MORE_ENTRIES
;
3069 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
3071 assert(CachedMode
->dmSize
> 0);
3072 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
3074 if (CachedMode
>= CachedDevModesEnd
)
3076 return STATUS_NO_MORE_ENTRIES
;
3080 ASSERT(CachedMode
!= NULL
);
3082 RtlCopyMemory(pDevMode
, CachedMode
, min(pDevMode
->dmSize
, CachedMode
->dmSize
));
3083 RtlZeroMemory(pDevMode
+ pDevMode
->dmSize
, pDevMode
->dmDriverExtra
);
3084 RtlCopyMemory(pDevMode
+ min(pDevMode
->dmSize
, CachedMode
->dmSize
), CachedMode
+ CachedMode
->dmSize
, min(pDevMode
->dmDriverExtra
, CachedMode
->dmDriverExtra
));
3086 return STATUS_SUCCESS
;
3089 static NTSTATUS FASTCALL
3091 OUT PUNICODE_STRING VideoDeviceName
,
3092 IN PCUNICODE_STRING DisplayDevice
) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
3094 UNICODE_STRING Prefix
= RTL_CONSTANT_STRING(L
"\\??\\");
3095 UNICODE_STRING ObjectName
;
3096 UNICODE_STRING KernelModeName
= { 0, };
3097 OBJECT_ATTRIBUTES ObjectAttributes
;
3100 HANDLE LinkHandle
= NULL
;
3103 RtlInitUnicodeString(VideoDeviceName
, NULL
);
3105 /* Get device name (DisplayDevice is "\.\xxx") */
3106 for (LastSlash
= DisplayDevice
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
3108 if (DisplayDevice
->Buffer
[LastSlash
- 1] == L
'\\')
3114 DPRINT1("Invalid device name '%wZ'\n", DisplayDevice
);
3115 Status
= STATUS_OBJECT_NAME_INVALID
;
3118 ObjectName
= *DisplayDevice
;
3119 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
3120 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
3121 ObjectName
.Buffer
+= LastSlash
;
3123 /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
3124 KernelModeName
.MaximumLength
= Prefix
.Length
+ ObjectName
.Length
+ sizeof(UNICODE_NULL
);
3125 KernelModeName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
3126 KernelModeName
.MaximumLength
,
3128 if (!KernelModeName
.Buffer
)
3130 Status
= STATUS_NO_MEMORY
;
3133 RtlCopyUnicodeString(&KernelModeName
, &Prefix
);
3134 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
3135 if (!NT_SUCCESS(Status
))
3138 /* Open \??\xxx (ex: "\??\DISPLAY1") */
3139 InitializeObjectAttributes(&ObjectAttributes
,
3144 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
3147 if (!NT_SUCCESS(Status
))
3149 DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3150 Status
= STATUS_NO_SUCH_DEVICE
;
3154 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, &Length
);
3155 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
3157 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3158 Status
= STATUS_NO_SUCH_DEVICE
;
3161 VideoDeviceName
->MaximumLength
= Length
;
3162 VideoDeviceName
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
3163 VideoDeviceName
->MaximumLength
+ sizeof(UNICODE_NULL
),
3165 if (!VideoDeviceName
->Buffer
)
3167 Status
= STATUS_NO_MEMORY
;
3170 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, NULL
);
3171 VideoDeviceName
->Buffer
[VideoDeviceName
->MaximumLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
3172 if (!NT_SUCCESS(Status
))
3174 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
3175 Status
= STATUS_NO_SUCH_DEVICE
;
3178 Status
= STATUS_SUCCESS
;
3181 if (!NT_SUCCESS(Status
) && VideoDeviceName
->Buffer
)
3182 ExFreePoolWithTag(VideoDeviceName
->Buffer
, TAG_DC
);
3183 if (KernelModeName
.Buffer
)
3184 ExFreePoolWithTag(KernelModeName
.Buffer
, TAG_DC
);
3186 ZwClose(LinkHandle
);
3190 static NTSTATUS FASTCALL
3191 GetVideoRegistryKey(
3192 OUT PUNICODE_STRING RegistryPath
,
3193 IN PCUNICODE_STRING DeviceName
) /* ex: "\Device\Video0" */
3195 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
3198 RtlInitUnicodeString(RegistryPath
, NULL
);
3199 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
3200 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
3201 QueryTable
[0].Name
= DeviceName
->Buffer
;
3202 QueryTable
[0].EntryContext
= RegistryPath
;
3204 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
3209 if (!NT_SUCCESS(Status
))
3211 DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName
, Status
);
3212 return STATUS_NO_SUCH_DEVICE
;
3215 DPRINT("RegistryPath %wZ\n", RegistryPath
);
3216 return STATUS_SUCCESS
;
3221 IntChangeDisplaySettings(
3222 IN PUNICODE_STRING pDeviceName OPTIONAL
,
3223 IN LPDEVMODEW DevMode
,
3225 IN PVOID lParam OPTIONAL
)
3227 BOOLEAN Global
= FALSE
;
3228 BOOLEAN NoReset
= FALSE
;
3229 BOOLEAN Reset
= FALSE
;
3230 BOOLEAN SetPrimary
= FALSE
;
3234 DPRINT1("display flags : %x\n",dwflags
);
3236 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3238 /* Check global, reset and noreset flags */
3239 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
3241 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
3243 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
3245 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
3247 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
3249 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
3251 if (Reset
&& NoReset
)
3252 return DISP_CHANGE_BADFLAGS
;
3256 /* Dynamically change graphics mode */
3257 DPRINT1("flag 0 UNIMPLEMENTED\n");
3258 return DISP_CHANGE_FAILED
;
3261 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
3263 /* Test reslution */
3264 dwflags
&= ~CDS_TEST
;
3265 DPRINT1("flag CDS_TEST UNIMPLEMENTED\n");
3266 Ret
= DISP_CHANGE_FAILED
;
3269 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
3273 dwflags
&= ~CDS_FULLSCREEN
;
3274 DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
3275 Ret
= DISP_CHANGE_FAILED
;
3277 RtlZeroMemory(&lpDevMode
, sizeof(DEVMODEW
));
3278 lpDevMode
.dmSize
= sizeof(DEVMODEW
);
3280 if (!IntEnumDisplaySettings(pDeviceName
, ENUM_CURRENT_SETTINGS
, &lpDevMode
, 0))
3281 return DISP_CHANGE_FAILED
;
3283 DPRINT1("Req Mode : %d x %d x %d\n", DevMode
->dmPelsWidth
,DevMode
->dmPelsHeight
,DevMode
->dmBitsPerPel
);
3284 DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode
.dmPelsWidth
,lpDevMode
.dmPelsHeight
, lpDevMode
.dmBitsPerPel
);
3287 if ((lpDevMode
.dmBitsPerPel
== DevMode
->dmBitsPerPel
) &&
3288 (lpDevMode
.dmPelsWidth
== DevMode
->dmPelsWidth
) &&
3289 (lpDevMode
.dmPelsHeight
== DevMode
->dmPelsHeight
))
3290 Ret
= DISP_CHANGE_SUCCESSFUL
;
3293 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
3295 dwflags
&= ~CDS_VIDEOPARAMETERS
;
3297 Ret
=DISP_CHANGE_BADPARAM
;
3300 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
3301 Ret
= DISP_CHANGE_FAILED
;
3306 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
3309 UNICODE_STRING DeviceName
;
3310 UNICODE_STRING RegistryKey
;
3311 UNICODE_STRING InDeviceName
;
3312 OBJECT_ATTRIBUTES ObjectAttributes
;
3313 HANDLE DevInstRegKey
;
3316 DPRINT1("set CDS_UPDATEREGISTRY\n");
3318 dwflags
&= ~CDS_UPDATEREGISTRY
;
3320 /* Check if pDeviceName is NULL, we need to retrieve it */
3321 if (pDeviceName
== NULL
)
3323 WCHAR szBuffer
[MAX_DRIVER_NAME
];
3325 PWINDOW_OBJECT Wnd
=NULL
;
3329 hWnd
= IntGetDesktopWindow();
3330 if (!(Wnd
= UserGetWindowObject(hWnd
)))
3335 hDC
= UserGetWindowDC(Wnd
);
3337 DC
= DC_LockDc(hDC
);
3342 swprintf (szBuffer
, L
"\\\\.\\DISPLAY%lu", ((GDIDEVICE
*)DC
->ppdev
)->DisplayNumber
);
3345 RtlInitUnicodeString(&InDeviceName
, szBuffer
);
3346 pDeviceName
= &InDeviceName
;
3349 Status
= GetVideoDeviceName(&DeviceName
, pDeviceName
);
3350 if (!NT_SUCCESS(Status
))
3352 DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName
, Status
);
3353 return DISP_CHANGE_FAILED
;
3355 Status
= GetVideoRegistryKey(&RegistryKey
, &DeviceName
);
3356 if (!NT_SUCCESS(Status
))
3358 DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName
, Status
);
3359 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3360 return DISP_CHANGE_FAILED
;
3362 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
3364 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
3365 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3366 Status
= ZwOpenKey(&DevInstRegKey
, KEY_SET_VALUE
, &ObjectAttributes
);
3367 if (!NT_SUCCESS(Status
))
3369 DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey
, Status
);
3370 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_RTLREGISTRY
);
3371 return DISP_CHANGE_FAILED
;
3373 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_RTLREGISTRY
);
3375 /* Update needed fields */
3376 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
3378 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
3379 NewValue
= DevMode
->dmBitsPerPel
;
3380 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3383 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
3385 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
3386 NewValue
= DevMode
->dmPelsWidth
;
3387 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3390 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
3392 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
3393 NewValue
= DevMode
->dmPelsHeight
;
3394 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3397 ZwClose(DevInstRegKey
);
3398 if (NT_SUCCESS(Status
))
3399 Ret
= DISP_CHANGE_RESTART
;
3401 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
3402 Ret
= DISP_CHANGE_NOTUPDATED
;
3406 Ret
= DISP_CHANGE_BADFLAGS
;
3419 return DCB_RESET
; /* bounding rectangle always empty */
3430 return DCB_DISABLE
; /* bounding rectangle always empty */
3441 PGDIDEVICE ppdev
, pGdiDevice
= (PGDIDEVICE
) hdev
;
3442 if (!pGdiDevice
) return NULL
;
3443 if ( pGdiDevice
< (PGDIDEVICE
)MmSystemRangeStart
) return NULL
;
3444 ppdev
= pPrimarySurface
;
3445 IntGdiAcquireSemaphore(hsemDriverMgmt
);
3448 if (pGdiDevice
== ppdev
) break;
3450 ppdev
= ppdev
->ppdevNext
;
3451 } while (ppdev
!= NULL
);
3452 IntGdiReleaseSemaphore(hsemDriverMgmt
);
3453 if (!ppdev
) return NULL
;
3454 return pGdiDevice
->hPDev
;