3 * ReactOS W32 Subsystem
4 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * DC.C - Device context functions
31 /* ROS Internal. Please deprecate */
35 HalQueryDisplayOwnership(
39 #ifndef OBJ_COLORSPACE
40 #define OBJ_COLORSPACE (14)
43 static GDIDEVICE PrimarySurface
;
44 static KEVENT VideoDriverNeedsPreparation
;
45 static KEVENT VideoDriverPrepared
;
51 KeInitializeEvent(&VideoDriverNeedsPreparation
, SynchronizationEvent
, TRUE
);
52 KeInitializeEvent(&VideoDriverPrepared
, NotificationEvent
, FALSE
);
53 return STATUS_SUCCESS
;
56 /* FIXME: DCs should probably be thread safe */
59 * DC device-independent Get/SetXXX functions
60 * (RJJ) swiped from WINE
63 #define DC_GET_VAL( func_type, func_name, dc_field ) \
64 func_type STDCALL func_name( HDC hdc ) \
67 PDC dc = DC_LockDc( hdc ); \
70 SetLastWin32Error(ERROR_INVALID_HANDLE); \
78 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
79 * important that the function has the right signature, for the implementation
80 * we can do whatever we want.
82 #define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
83 VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
90 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
92 NTSTATUS Status = STATUS_SUCCESS; \
97 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
100 if(!(dc = DC_LockDc(hdc))) \
102 SetLastWin32Error(ERROR_INVALID_HANDLE); \
105 Int##FuncName( dc, &Safept); \
116 Status = _SEH_GetExceptionCode(); \
119 if(!NT_SUCCESS(Status)) \
121 SetLastNtError(Status); \
127 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
128 INT STDCALL func_name( HDC hdc, INT mode ) \
132 if ((mode < min_val) || (mode > max_val)) \
134 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
137 dc = DC_LockDc ( hdc ); \
140 SetLastWin32Error(ERROR_INVALID_HANDLE); \
143 prevMode = dc->dc_field; \
144 dc->dc_field = mode; \
145 DC_UnlockDc ( dc ); \
150 // --------------------------------------------------------- File Statics
152 // ----------------------------------------------------- Public Functions
155 NtGdiCancelDC(HDC hDC
)
162 NtGdiCreateCompatibleDC(HDC hDC
)
166 HDC hNewDC
, DisplayDC
;
168 UNICODE_STRING DriverName
;
173 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
174 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
175 if (NULL
== DisplayDC
)
182 /* Allocate a new DC based on the original DC's device */
183 OrigDC
= DC_LockDc(hDC
);
186 if (NULL
!= DisplayDC
)
188 NtGdiDeleteObjectApp(DisplayDC
);
192 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
197 if (NULL
!= DisplayDC
)
199 NtGdiDeleteObjectApp(DisplayDC
);
203 NewDC
= DC_LockDc( hNewDC
);
205 /* Copy information from original DC to new DC */
206 NewDC
->hSelf
= hNewDC
;
209 NewDC
->PDev
= OrigDC
->PDev
;
210 memcpy(NewDC
->FillPatternSurfaces
,
211 OrigDC
->FillPatternSurfaces
,
212 sizeof OrigDC
->FillPatternSurfaces
);
213 NewDC
->GDIInfo
= OrigDC
->GDIInfo
;
214 NewDC
->DevInfo
= OrigDC
->DevInfo
;
215 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
217 /* DriverName is copied in the AllocDC routine */
218 NewDC
->DeviceDriver
= OrigDC
->DeviceDriver
;
219 NewDC
->wndOrgX
= OrigDC
->wndOrgX
;
220 NewDC
->wndOrgY
= OrigDC
->wndOrgY
;
221 NewDC
->wndExtX
= OrigDC
->wndExtX
;
222 NewDC
->wndExtY
= OrigDC
->wndExtY
;
223 NewDC
->vportOrgX
= OrigDC
->vportOrgX
;
224 NewDC
->vportOrgY
= OrigDC
->vportOrgY
;
225 NewDC
->vportExtX
= OrigDC
->vportExtX
;
226 NewDC
->vportExtY
= OrigDC
->vportExtY
;
228 /* Create default bitmap */
229 if (!(hBitmap
= NtGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
231 DC_UnlockDc( OrigDC
);
232 DC_UnlockDc( NewDC
);
234 if (NULL
!= DisplayDC
)
236 NtGdiDeleteObjectApp(DisplayDC
);
240 NewDC
->w
.flags
= DC_MEMORY
;
241 NewDC
->w
.hBitmap
= hBitmap
;
242 NewDC
->w
.hFirstBitmap
= hBitmap
;
243 NewDC
->GDIDevice
= OrigDC
->GDIDevice
;
245 NewDC
->PalIndexed
= OrigDC
->PalIndexed
;
246 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
247 NewDC
->w
.textColor
= OrigDC
->w
.textColor
;
248 NewDC
->w
.textAlign
= OrigDC
->w
.textAlign
;
249 NewDC
->w
.backgroundColor
= OrigDC
->w
.backgroundColor
;
250 NewDC
->w
.backgroundMode
= OrigDC
->w
.backgroundMode
;
251 NewDC
->w
.ROPmode
= OrigDC
->w
.ROPmode
;
254 if (NULL
!= DisplayDC
)
256 NtGdiDeleteObjectApp(DisplayDC
);
259 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
260 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
261 NtGdiDeleteObject(hVisRgn
);
268 static BOOLEAN FASTCALL
269 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
271 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
272 WCHAR DeviceNameBuffer
[20];
275 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%lu", DisplayNumber
);
276 RtlInitUnicodeString(RegistryPath
, NULL
);
277 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
278 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
279 QueryTable
[0].Name
= DeviceNameBuffer
;
280 QueryTable
[0].EntryContext
= RegistryPath
;
282 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
287 if (! NT_SUCCESS(Status
))
289 DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
293 DPRINT("RegistryPath %wZ\n", RegistryPath
);
299 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
301 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
302 UNICODE_STRING RegistryPath
;
305 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
307 DPRINT("GetRegistryPath failed\n");
311 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
312 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
313 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
314 QueryTable
[0].EntryContext
= DriverFileNames
;
316 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
321 RtlFreeUnicodeString(&RegistryPath
);
322 if (! NT_SUCCESS(Status
))
324 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
328 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
333 static NTSTATUS STDCALL
334 DevModeCallback(IN PWSTR ValueName
,
337 IN ULONG ValueLength
,
339 IN PVOID EntryContext
)
341 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
343 DPRINT("Found registry value for name %S: type %d, length %d\n",
344 ValueName
, ValueType
, ValueLength
);
346 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
348 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
350 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
352 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
354 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
356 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
358 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
360 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
362 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
364 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
366 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
368 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
370 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
372 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
374 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
378 return STATUS_SUCCESS
;
382 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
384 UNICODE_STRING RegistryPath
;
385 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
387 BOOLEAN Valid
= TRUE
;
389 if (!GetRegistryPath(&RegistryPath
, DisplayNumber
))
391 DPRINT("GetRegistryPath failed\n");
395 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
396 QueryTable
[0].QueryRoutine
= DevModeCallback
;
397 QueryTable
[0].Flags
= 0;
398 QueryTable
[0].Name
= NULL
;
399 QueryTable
[0].EntryContext
= NULL
;
400 QueryTable
[0].DefaultType
= REG_NONE
;
401 QueryTable
[0].DefaultData
= NULL
;
402 QueryTable
[0].DefaultLength
= 0;
404 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
409 if (! NT_SUCCESS(Status
))
411 DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
412 &RegistryPath
, Status
);
417 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
418 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
419 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
420 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
421 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
423 DPRINT("Not all required devmode members are set\n");
428 RtlFreeUnicodeString(&RegistryPath
);
432 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
441 PGD_ENABLEDRIVER GDEnableDriver
;
443 UNICODE_STRING DriverFileNames
;
452 if (STATUS_SUCCESS
!= KeWaitForSingleObject(&VideoDriverNeedsPreparation
, Executive
, KernelMode
, TRUE
, &Zero
))
454 /* Concurrent access. Wait for VideoDriverPrepared event */
455 if (STATUS_SUCCESS
== KeWaitForSingleObject(&VideoDriverPrepared
, Executive
, KernelMode
, TRUE
, NULL
))
456 ret
= PrimarySurface
.PreparedDriver
;
460 for (DisplayNumber
= 0; ; DisplayNumber
++)
462 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
464 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
466 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
468 /* Open the miniport driver */
469 if (PrimarySurface
.VideoFileObject
== NULL
)
471 DPRINT1("FindMPDriver failed\n");
475 /* Retrieve DDI driver names from registry */
476 RtlInitUnicodeString(&DriverFileNames
, NULL
);
477 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
479 DPRINT1("FindDriverFileNames failed\n");
484 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
485 * scan all of them until a good one found.
487 CurrentName
= DriverFileNames
.Buffer
;
490 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
492 /* Get the DDI driver's entry point */
493 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
494 if (NULL
== GDEnableDriver
)
496 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
500 /* Call DDI driver's EnableDriver function */
501 RtlZeroMemory(&DED
, sizeof(DED
));
503 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
505 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
515 /* Skip to the next name but never get past the Unicode string */
516 while (L
'\0' != *CurrentName
&&
517 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
521 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
528 RtlFreeUnicodeString(&DriverFileNames
);
532 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
533 DPRINT1("No suitable DDI driver found\n");
537 DPRINT("Display driver %S loaded\n", CurrentName
);
539 DPRINT("Building DDI Functions\n");
541 /* Construct DDI driver function dispatch table */
542 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
544 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
545 DPRINT1("BuildDDIFunctions failed\n");
549 /* Allocate a phyical device handle from the driver */
550 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
551 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
553 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
557 PrimarySurface
.FillPatterns
,
558 sizeof(PrimarySurface
.GDIInfo
),
559 (ULONG
*) &PrimarySurface
.GDIInfo
,
560 sizeof(PrimarySurface
.DevInfo
),
561 &PrimarySurface
.DevInfo
,
564 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
565 DoDefault
= (NULL
== PrimarySurface
.PDev
);
568 DPRINT1("DrvEnablePDev with registry parameters failed\n");
578 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
579 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
580 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
584 PrimarySurface
.FillPatterns
,
585 sizeof(PrimarySurface
.GDIInfo
),
586 (ULONG
*) &PrimarySurface
.GDIInfo
,
587 sizeof(PrimarySurface
.DevInfo
),
588 &PrimarySurface
.DevInfo
,
591 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
593 if (NULL
== PrimarySurface
.PDev
)
595 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
596 DPRINT1("DrvEnablePDEV with default parameters failed\n");
597 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
602 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
604 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
605 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
607 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
609 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
610 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
613 PrimarySurface
.Pointer
.Exclude
.right
= -1;
615 DPRINT("calling completePDev\n");
617 /* Complete initialization of the physical device */
618 PrimarySurface
.DriverFunctions
.CompletePDEV(
620 (HDEV
)&PrimarySurface
);
622 DPRINT("calling DRIVER_ReferenceDriver\n");
624 DRIVER_ReferenceDriver(L
"DISPLAY");
626 PrimarySurface
.PreparedDriver
= TRUE
;
627 PrimarySurface
.DisplayNumber
= DisplayNumber
;
634 KeSetEvent(&VideoDriverPrepared
, 1, FALSE
);
639 IntPrepareDriverIfNeeded()
641 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
649 IO_STATUS_BLOCK Iosb
;
651 ULONG Length
= sizeof(BOOL
);
652 PIO_STACK_LOCATION StackPtr
;
653 LARGE_INTEGER StartOffset
;
654 PFILE_OBJECT FileObject
= PrimarySurface
.VideoFileObject
;
655 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
657 DPRINT("PrepareVideoPrt() called\n");
659 KeClearEvent(&PrimarySurface
.VideoFileObject
->Event
);
661 ObReferenceObjectByPointer(FileObject
, 0, IoFileObjectType
, KernelMode
);
663 StartOffset
.QuadPart
= 0;
664 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
676 /* Set up IRP Data */
677 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
678 Irp
->RequestorMode
= KernelMode
;
679 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
680 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= NULL
;
681 Irp
->Flags
|= IRP_WRITE_OPERATION
;
683 /* Setup Stack Data */
684 StackPtr
= IoGetNextIrpStackLocation(Irp
);
685 StackPtr
->FileObject
= PrimarySurface
.VideoFileObject
;
686 StackPtr
->Parameters
.Write
.Key
= 0;
688 Status
= IoCallDriver(DeviceObject
, Irp
);
690 if (STATUS_PENDING
== Status
)
692 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, TRUE
, 0);
693 Status
= Iosb
.Status
;
696 return NT_SUCCESS(Status
);
700 IntCreatePrimarySurface()
707 if (! IntPrepareDriverIfNeeded())
712 if (! PrepareVideoPrt())
717 DPRINT("calling EnableSurface\n");
718 /* Enable the drawing surface */
719 PrimarySurface
.Handle
=
720 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
721 if (NULL
== PrimarySurface
.Handle
)
723 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
724 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
725 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
726 DPRINT1("DrvEnableSurface failed\n");
730 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, TRUE
);
732 calledFromUser
= UserIsEntered(); //fixme: possibly upgrade a shared lock
733 if (!calledFromUser
){
734 UserEnterExclusive();
738 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
740 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
741 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
742 SurfSize
= SurfObj
->sizlBitmap
;
743 SurfaceRect
.left
= SurfaceRect
.top
= 0;
744 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
745 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
746 /* FIXME - why does EngEraseSurface() sometimes crash?
747 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
749 /* Put the pointer in the center of the screen */
750 GDIDEV(SurfObj
)->Pointer
.Pos
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
751 GDIDEV(SurfObj
)->Pointer
.Pos
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
753 EngUnlockSurface(SurfObj
);
754 co_IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
756 if (!calledFromUser
){
764 IntDestroyPrimarySurface()
768 DRIVER_UnreferenceDriver(L
"DISPLAY");
770 calledFromUser
= UserIsEntered();
771 if (!calledFromUser
){
772 UserEnterExclusive();
776 IntDetachMonitor(&PrimarySurface
);
778 if (!calledFromUser
){
783 * FIXME: Hide a mouse pointer there. Also because we have to prevent
784 * memory leaks with the Eng* mouse routines.
787 DPRINT("Reseting display\n" );
788 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, FALSE
);
789 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.PDev
);
790 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
791 PrimarySurface
.PreparedDriver
= FALSE
;
795 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
799 IntGdiCreateDC(PUNICODE_STRING Driver
,
800 PUNICODE_STRING Device
,
801 PUNICODE_STRING Output
,
802 CONST PDEVMODEW InitData
,
809 UNICODE_STRING StdDriver
;
812 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
814 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
818 if (! IntPrepareDriverIfNeeded())
820 DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
826 calledFromUser
= UserIsEntered();
827 if (!calledFromUser
){
828 UserEnterExclusive();
831 if (! co_IntGraphicsCheck(TRUE
))
833 if (!calledFromUser
){
836 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
840 if (!calledFromUser
){
847 /* Check for existing DC object */
848 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
851 return NtGdiCreateCompatibleDC(hDC
);
854 if (Driver
!= NULL
&& Driver
->Buffer
!= NULL
)
856 DPRINT("NAME: %wZ\n", Driver
); // FIXME: Should not crash if NULL
859 /* Allocate a DC object */
860 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
865 NewDC
= DC_LockDc( hNewDC
);
866 /* FIXME - NewDC can be NULL!!! Don't assert here! */
873 NewDC
->IsIC
= CreateAsIC
;
874 NewDC
->DevInfo
= &PrimarySurface
.DevInfo
;
875 NewDC
->GDIInfo
= &PrimarySurface
.GDIInfo
;
876 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
877 sizeof(NewDC
->FillPatternSurfaces
));
878 NewDC
->PDev
= PrimarySurface
.PDev
;
879 NewDC
->GDIDevice
= (HDEV
)&PrimarySurface
;
880 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
881 NewDC
->w
.hBitmap
= PrimarySurface
.Handle
;
883 NewDC
->w
.bitsPerPixel
= NewDC
->GDIInfo
->cBitsPixel
* NewDC
->GDIInfo
->cPlanes
;
884 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
888 NewDC
->PalIndexed
= NtGdiGetStockObject(DEFAULT_PALETTE
);
889 NewDC
->w
.hPalette
= NewDC
->DevInfo
->hpalDefault
;
890 NewDC
->w
.ROPmode
= R2_COPYPEN
;
892 DC_UnlockDc( NewDC
);
894 hVisRgn
= NtGdiCreateRectRgn(0, 0, NewDC
->GDIInfo
->ulHorzRes
,
895 NewDC
->GDIInfo
->ulVertRes
);
896 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
897 NtGdiDeleteObject(hVisRgn
);
899 /* Initialize the DC state */
901 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
902 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
903 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
904 NtGdiSetBkMode(hNewDC
, OPAQUE
);
908 DC_UnlockDc( NewDC
);
915 NtGdiCreateDC(PUNICODE_STRING Driver
,
916 PUNICODE_STRING Device
,
917 PUNICODE_STRING Output
,
918 CONST PDEVMODEW InitData
)
920 UNICODE_STRING SafeDriver
, SafeDevice
;
921 DEVMODEW SafeInitData
;
923 NTSTATUS Status
= STATUS_SUCCESS
;
929 ProbeForRead(InitData
,
932 RtlCopyMemory(&SafeInitData
,
938 Status
= _SEH_GetExceptionCode();
942 if(!NT_SUCCESS(Status
))
944 SetLastNtError(Status
);
947 /* FIXME - InitData can have some more bytes! */
952 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
953 if(!NT_SUCCESS(Status
))
955 SetLastNtError(Status
);
962 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
963 if(!NT_SUCCESS(Status
))
965 RtlFreeUnicodeString(&SafeDriver
);
966 SetLastNtError(Status
);
971 Ret
= IntGdiCreateDC(NULL
== Driver
? NULL
: &SafeDriver
,
972 NULL
== Device
? NULL
: &SafeDevice
, NULL
,
973 NULL
== InitData
? NULL
: &SafeInitData
, FALSE
);
979 NtGdiCreateIC(PUNICODE_STRING Driver
,
980 PUNICODE_STRING Device
,
981 PUNICODE_STRING Output
,
982 CONST PDEVMODEW InitData
)
984 UNICODE_STRING SafeDriver
, SafeDevice
;
985 DEVMODEW SafeInitData
;
987 NTSTATUS Status
= STATUS_SUCCESS
;
993 ProbeForRead(InitData
,
996 RtlCopyMemory(&SafeInitData
,
1002 Status
= _SEH_GetExceptionCode();
1005 if(!NT_SUCCESS(Status
))
1007 SetLastNtError(Status
);
1010 /* FIXME - InitData can have some more bytes! */
1015 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
1016 if(!NT_SUCCESS(Status
))
1018 SetLastNtError(Status
);
1025 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
1026 if(!NT_SUCCESS(Status
))
1028 RtlFreeUnicodeString(&SafeDriver
);
1029 SetLastNtError(Status
);
1034 Ret
= IntGdiCreateDC(NULL
== Driver
? NULL
: &SafeDriver
,
1035 NULL
== Device
? NULL
: &SafeDevice
, NULL
,
1036 NULL
== InitData
? NULL
: &SafeInitData
, TRUE
);
1042 NtGdiOpenDCW( PUNICODE_STRING pustrDevice
,
1044 PUNICODE_STRING pustrLogAddr
,
1055 NtGdiDeleteObjectApp(HANDLE DCHandle
)
1059 if (!GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, DCHandle
))
1061 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1065 DCToDelete
= DC_LockDc(DCHandle
);
1066 if (DCToDelete
== NULL
)
1068 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1072 /* First delete all saved DCs */
1073 while (DCToDelete
->saveLevel
)
1078 savedHDC
= DC_GetNextDC (DCToDelete
);
1079 savedDC
= DC_LockDc (savedHDC
);
1080 if (savedDC
== NULL
)
1084 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
1085 DCToDelete
->saveLevel
--;
1086 DC_UnlockDc( savedDC
);
1087 NtGdiDeleteObjectApp (savedHDC
);
1090 /* Free GDI resources allocated to this DC */
1091 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
1094 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
1095 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
1096 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
1097 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
1098 if (DCToDelete
->w
.flags
& DC_MEMORY
)
1100 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
1102 if (DCToDelete
->XlateBrush
!= NULL
)
1103 EngDeleteXlate(DCToDelete
->XlateBrush
);
1104 if (DCToDelete
->XlatePen
!= NULL
)
1105 EngDeleteXlate(DCToDelete
->XlatePen
);
1107 if (DCToDelete
->w
.hClipRgn
)
1109 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
1111 if (DCToDelete
->w
.hVisRgn
)
1113 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
1115 if (NULL
!= DCToDelete
->CombinedClip
)
1117 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
1119 if (DCToDelete
->w
.hGCClipRgn
)
1121 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
1124 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
1127 if (DCToDelete
->emh
)
1129 EngFreeMem(DCToDelete
->emh
);
1132 DC_UnlockDc( DCToDelete
);
1133 DC_FreeDC ( DCHandle
);
1144 IN OPTIONAL LPSTR pjIn
)
1156 OUT OPTIONAL PVOID pvBuf
)
1162 DC_GET_VAL( COLORREF
, NtGdiGetBkColor
, w
.backgroundColor
)
1163 DC_GET_VAL( INT
, NtGdiGetBkMode
, w
.backgroundMode
)
1164 DC_GET_VAL_EX( GetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
, x
, y
)
1165 DC_GET_VAL( HRGN
, NtGdiGetClipRgn
, w
.hClipRgn
)
1168 NtGdiGetCurrentObject(HDC hDC
, UINT ObjectType
)
1173 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
1174 if(!hDC
) return NULL
;
1176 if(!(dc
= DC_LockDc(hDC
)))
1178 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1185 SelObject
= dc
->w
.hPen
;
1188 SelObject
= dc
->w
.hBrush
;
1191 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
1195 SelObject
= dc
->w
.hFont
;
1198 SelObject
= dc
->w
.hBitmap
;
1200 case OBJ_COLORSPACE
:
1201 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1206 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1214 DC_GET_VAL_EX ( GetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
, x
, y
)
1217 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1219 Point
->x
= dc
->w
.DCOrgX
;
1220 Point
->y
= dc
->w
.DCOrgY
;
1226 NtGdiGetDCOrgEx(HDC hDC
, LPPOINT Point
)
1231 NTSTATUS Status
= STATUS_SUCCESS
;
1235 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1239 dc
= DC_LockDc(hDC
);
1242 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1246 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1250 ProbeForWrite(Point
,
1257 Status
= _SEH_GetExceptionCode();
1261 if(!NT_SUCCESS(Status
))
1263 SetLastNtError(Status
);
1273 NtGdiSetBkColor(HDC hDC
, COLORREF color
)
1279 if (!(dc
= DC_LockDc(hDC
)))
1281 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1285 oldColor
= dc
->w
.backgroundColor
;
1286 dc
->w
.backgroundColor
= color
;
1287 hBrush
= dc
->w
.hBrush
;
1289 NtGdiSelectObject(hDC
, hBrush
);
1294 NtGdiGetDCState(HDC hDC
)
1299 dc
= DC_LockDc(hDC
);
1302 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1306 hnewdc
= DC_AllocDC(NULL
);
1312 newdc
= DC_LockDc( hnewdc
);
1313 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1316 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1317 newdc
->w
.hPen
= dc
->w
.hPen
;
1318 newdc
->w
.hBrush
= dc
->w
.hBrush
;
1319 newdc
->w
.hFont
= dc
->w
.hFont
;
1320 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1321 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1323 newdc
->w
.hDevice
= dc
->w
.hDevice
;
1325 newdc
->PalIndexed
= dc
->PalIndexed
;
1326 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1327 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1328 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1329 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
1330 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
1331 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
1332 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
1333 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
1334 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
1335 newdc
->w
.textColor
= dc
->w
.textColor
;
1336 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
1337 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
1338 newdc
->w
.textAlign
= dc
->w
.textAlign
;
1339 newdc
->w
.charExtra
= dc
->w
.charExtra
;
1340 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
1341 newdc
->w
.breakCount
= dc
->w
.breakCount
;
1342 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
1343 newdc
->w
.breakRem
= dc
->w
.breakRem
;
1344 newdc
->w
.MapMode
= dc
->w
.MapMode
;
1345 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
1347 /* Apparently, the DC origin is not changed by [GS]etDCState */
1348 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1349 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1351 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
1352 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
1353 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1354 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1355 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1356 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1357 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1358 newdc
->wndOrgX
= dc
->wndOrgX
;
1359 newdc
->wndOrgY
= dc
->wndOrgY
;
1360 newdc
->wndExtX
= dc
->wndExtX
;
1361 newdc
->wndExtY
= dc
->wndExtY
;
1362 newdc
->vportOrgX
= dc
->vportOrgX
;
1363 newdc
->vportOrgY
= dc
->vportOrgY
;
1364 newdc
->vportExtX
= dc
->vportExtX
;
1365 newdc
->vportExtY
= dc
->vportExtY
;
1367 newdc
->hSelf
= hnewdc
;
1368 newdc
->saveLevel
= 0;
1369 newdc
->IsIC
= dc
->IsIC
;
1372 PATH_InitGdiPath( &newdc
->w
.path
);
1375 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1377 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1380 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1381 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1383 DC_UnlockDc( newdc
);
1391 NtGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1395 dc
= DC_LockDc ( hDC
);
1398 dcs
= DC_LockDc ( hDCSave
);
1401 if ( dcs
->w
.flags
& DC_SAVED
)
1403 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1405 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1408 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1411 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1412 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1413 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1414 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1415 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1416 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1417 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1418 dc
->w
.textColor
= dcs
->w
.textColor
;
1419 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1420 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1421 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1422 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1423 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1424 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1425 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1426 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1427 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1428 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1430 /* Apparently, the DC origin is not changed by [GS]etDCState */
1431 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1432 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1434 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1435 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1436 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1438 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1439 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1440 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1441 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1443 dc
->wndOrgX
= dcs
->wndOrgX
;
1444 dc
->wndOrgY
= dcs
->wndOrgY
;
1445 dc
->wndExtX
= dcs
->wndExtX
;
1446 dc
->wndExtY
= dcs
->wndExtY
;
1447 dc
->vportOrgX
= dcs
->vportOrgX
;
1448 dc
->vportOrgY
= dcs
->vportOrgY
;
1449 dc
->vportExtX
= dcs
->vportExtX
;
1450 dc
->vportExtY
= dcs
->vportExtY
;
1451 dc
->PalIndexed
= dcs
->PalIndexed
;
1453 if (!(dc
->w
.flags
& DC_MEMORY
))
1455 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1459 if (dcs
->w
.hClipRgn
)
1461 if (!dc
->w
.hClipRgn
)
1463 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1465 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1471 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1478 res
= CLIPPING_UpdateGCRegion( dc
);
1479 ASSERT ( res
!= ERROR
);
1484 NtGdiSelectClipRgn(hDC
, dcs
->w
.hClipRgn
);
1487 NtGdiSelectObject( hDC
, dcs
->w
.hBitmap
);
1488 NtGdiSelectObject( hDC
, dcs
->w
.hBrush
);
1489 NtGdiSelectObject( hDC
, dcs
->w
.hFont
);
1490 NtGdiSelectObject( hDC
, dcs
->w
.hPen
);
1491 NtGdiSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1492 NtGdiSetTextColor( hDC
, dcs
->w
.textColor
);
1494 NtGdiSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1497 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1502 DC_UnlockDc ( dcs
);
1505 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1509 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1513 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1518 /* Retrieve capability */
1522 ret
= dc
->GDIInfo
->ulVersion
;
1526 ret
= dc
->GDIInfo
->ulTechnology
;
1530 ret
= dc
->GDIInfo
->ulHorzSize
;
1534 ret
= dc
->GDIInfo
->ulVertSize
;
1538 ret
= dc
->GDIInfo
->ulHorzRes
;
1542 ret
= dc
->GDIInfo
->ulVertRes
;
1546 ret
= dc
->GDIInfo
->ulLogPixelsX
;
1550 ret
= dc
->GDIInfo
->ulLogPixelsY
;
1554 ret
= dc
->GDIInfo
->cBitsPixel
;
1558 ret
= dc
->GDIInfo
->cPlanes
;
1562 UNIMPLEMENTED
; /* FIXME */
1566 UNIMPLEMENTED
; /* FIXME */
1570 UNIMPLEMENTED
; /* FIXME */
1574 ret
= dc
->GDIInfo
->ulNumColors
;
1578 ret
= dc
->GDIInfo
->ulAspectX
;
1582 ret
= dc
->GDIInfo
->ulAspectY
;
1586 ret
= dc
->GDIInfo
->ulAspectXY
;
1590 UNIMPLEMENTED
; /* FIXME */
1594 UNIMPLEMENTED
; /* FIXME */
1598 ret
= dc
->GDIInfo
->ulNumPalReg
; /* FIXME not sure */
1606 UNIMPLEMENTED
; /* FIXME */
1610 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1620 case PHYSICALHEIGHT
:
1621 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1631 case PHYSICALOFFSETX
:
1632 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1642 case PHYSICALOFFSETY
:
1643 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1654 UNIMPLEMENTED
; /* FIXME */
1657 case SCALINGFACTORX
:
1658 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1668 case SCALINGFACTORY
:
1669 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1680 ret
= dc
->GDIInfo
->flRaster
;
1684 UNIMPLEMENTED
; /* FIXME */
1688 UNIMPLEMENTED
; /* FIXME */
1692 UNIMPLEMENTED
; /* FIXME */
1696 ret
= dc
->GDIInfo
->flTextCaps
;
1708 NtGdiGetDeviceCaps(HDC hDC
,
1714 dc
= DC_LockDc(hDC
);
1717 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1721 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1723 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1729 DC_GET_VAL( INT
, NtGdiGetMapMode
, w
.MapMode
)
1730 DC_GET_VAL( INT
, NtGdiGetPolyFillMode
, w
.polyFillMode
)
1734 IntGdiGetObject(HANDLE Handle
, INT Count
, LPVOID Buffer
)
1740 GdiObject
= GDIOBJ_LockObj(GdiHandleTable
, Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1741 if (NULL
== GdiObject
)
1743 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1747 ObjectType
= GDIOBJ_GetObjectType(Handle
);
1751 case GDI_OBJECT_TYPE_PEN
:
1752 Result
= PEN_GetObject((PGDIBRUSHOBJ
) GdiObject
, Count
, (PLOGPEN
) Buffer
); // IntGdiCreatePenIndirect
1755 case GDI_OBJECT_TYPE_BRUSH
:
1756 Result
= BRUSH_GetObject((PGDIBRUSHOBJ
) GdiObject
, Count
, (LPLOGBRUSH
)Buffer
);
1759 case GDI_OBJECT_TYPE_BITMAP
:
1760 Result
= BITMAP_GetObject((BITMAPOBJ
*) GdiObject
, Count
, Buffer
);
1762 case GDI_OBJECT_TYPE_FONT
:
1763 Result
= FontGetObject((PTEXTOBJ
) GdiObject
, Count
, Buffer
);
1765 // Fix the LOGFONT structure for the stock fonts
1766 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1768 FixStockFontSizeW(Handle
, Count
, Buffer
);
1773 case GDI_OBJECT_TYPE_PALETTE
:
1774 Result
= PALETTE_GetObject((PALETTEOBJ
*) GdiObject
, Count
, Buffer
);
1778 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType
);
1782 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, GdiObject
);
1788 NtGdiGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
1792 NTSTATUS Status
= STATUS_SUCCESS
;
1795 /* From Wine: GetObject does not SetLastError() on a null object */
1796 if (!handle
) return Ret
;
1798 RetCount
= IntGdiGetObject(handle
, 0, NULL
);
1799 if ((count
<= 0) || (!buffer
))
1806 ProbeForWrite(buffer
, count
, 1);
1810 Status
= _SEH_GetExceptionCode();
1814 if(!NT_SUCCESS(Status
))
1816 SetLastNtError(Status
);
1820 if (RetCount
>= count
)
1822 SafeBuf
= ExAllocatePoolWithTag(PagedPool
, count
, TAG_GDIOBJ
);
1825 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1828 Ret
= IntGdiGetObject(handle
, count
, SafeBuf
);
1832 /* pointer already probed! */
1833 RtlCopyMemory(buffer
, SafeBuf
, count
);
1837 Status
= _SEH_GetExceptionCode();
1841 ExFreePool(SafeBuf
);
1843 if(!NT_SUCCESS(Status
))
1845 SetLastNtError(Status
);
1854 NtGdiGetObjectType(HANDLE handle
)
1860 ptr
= GDIOBJ_LockObj(GdiHandleTable
, handle
, GDI_OBJECT_TYPE_DONTCARE
);
1863 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1867 objectType
= GDIOBJ_GetObjectType(handle
);
1870 case GDI_OBJECT_TYPE_PEN
:
1873 case GDI_OBJECT_TYPE_BRUSH
:
1876 case GDI_OBJECT_TYPE_BITMAP
:
1877 result
= OBJ_BITMAP
;
1879 case GDI_OBJECT_TYPE_FONT
:
1882 case GDI_OBJECT_TYPE_PALETTE
:
1885 case GDI_OBJECT_TYPE_REGION
:
1886 result
= OBJ_REGION
;
1888 case GDI_OBJECT_TYPE_DC
:
1891 case GDI_OBJECT_TYPE_METADC
:
1892 result
= OBJ_METADC
;
1894 case GDI_OBJECT_TYPE_METAFILE
:
1895 result
= OBJ_METAFILE
;
1897 case GDI_OBJECT_TYPE_ENHMETAFILE
:
1898 result
= OBJ_ENHMETAFILE
;
1900 case GDI_OBJECT_TYPE_ENHMETADC
:
1901 result
= OBJ_ENHMETADC
;
1903 case GDI_OBJECT_TYPE_EXTPEN
:
1904 result
= OBJ_EXTPEN
;
1906 case GDI_OBJECT_TYPE_MEMDC
:
1911 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
1915 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, ptr
);
1919 DC_GET_VAL( INT
, NtGdiGetRelAbs
, w
.relAbsMode
)
1920 DC_GET_VAL( INT
, NtGdiGetROP2
, w
.ROPmode
)
1921 DC_GET_VAL( INT
, NtGdiGetStretchBltMode
, w
.stretchBltMode
)
1922 DC_GET_VAL( UINT
, NtGdiGetTextAlign
, w
.textAlign
)
1923 DC_GET_VAL( COLORREF
, NtGdiGetTextColor
, w
.textColor
)
1924 DC_GET_VAL_EX( GetViewportExtEx
, vportExtX
, vportExtY
, SIZE
, cx
, cy
)
1925 DC_GET_VAL_EX( GetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
, x
, y
)
1926 DC_GET_VAL_EX( GetWindowExtEx
, wndExtX
, wndExtY
, SIZE
, cx
, cy
)
1927 DC_GET_VAL_EX( GetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
, x
, y
)
1934 OUT PBOOL pbBanding
,
1935 IN OPTIONAL VOID
*pDriverInfo2
,
1936 OUT VOID
*ppUMdhpdev
)
1943 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1948 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1950 dc
= DC_LockDc(hDC
);
1953 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1957 if(abs(SaveLevel
) > dc
->saveLevel
|| SaveLevel
== 0)
1963 /* FIXME this calc are not 100% correct I think ??*/
1964 if (SaveLevel
< 0) SaveLevel
= dc
->saveLevel
+ SaveLevel
+ 1;
1967 while (dc
->saveLevel
>= SaveLevel
)
1969 HDC hdcs
= DC_GetNextDC (dc
);
1971 dcs
= DC_LockDc (hdcs
);
1978 DC_SetNextDC (dc
, DC_GetNextDC (dcs
));
1981 if (--dc
->saveLevel
< SaveLevel
)
1986 NtGdiSetDCState(hDC
, hdcs
);
1987 //if (!PATH_AssignGdiPath( &dc->path, &dcs->path ))
1988 /* FIXME: This might not be quite right, since we're
1989 * returning FALSE but still destroying the saved DC state
1992 dc
= DC_LockDc(hDC
);
2002 NtGdiDeleteObjectApp (hdcs
);
2010 NtGdiSaveDC(HDC hDC
)
2016 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
2018 if (!(hdcs
= NtGdiGetDCState(hDC
)))
2023 dcs
= DC_LockDc (hdcs
);
2026 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2029 dc
= DC_LockDc (hDC
);
2033 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2038 /* Copy path. The reason why path saving / restoring is in SaveDC/
2039 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
2040 * functions are only in Win16 (which doesn't have paths) and that
2041 * SetDCState doesn't allow us to signal an error (which can happen
2042 * when copying paths).
2044 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
2046 NtGdiDeleteObjectApp (hdcs
);
2051 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
2052 DC_SetNextDC (dc
, hdcs
);
2053 ret
= ++dc
->saveLevel
;
2062 NtGdiSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
2064 HGDIOBJ objOrg
= NULL
; // default to failure
2074 if (!hDC
|| !hGDIObj
)
2077 * SelectObject() with a NULL DC returns 0 and sets ERROR_INVALID_HANDLE.
2078 * Note: Under XP at least invalid ptrs can also be passed, not just NULL;
2079 * Don't test that here in case it crashes earlier win versions.
2081 if (!hDC
) SetLastWin32Error(ERROR_INVALID_HANDLE
);
2085 dc
= DC_LockDc(hDC
);
2088 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2092 objectType
= GDIOBJ_GetObjectType(hGDIObj
);
2096 case GDI_OBJECT_TYPE_PEN
:
2097 pen
= PENOBJ_LockPen((HPEN
) hGDIObj
);
2100 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2104 XlateObj
= IntGdiCreateBrushXlate(dc
, pen
, &Failed
);
2105 PENOBJ_UnlockPen(pen
);
2108 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2112 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
2113 dc
->w
.hPen
= hGDIObj
;
2114 if (dc
->XlatePen
!= NULL
)
2115 EngDeleteXlate(dc
->XlatePen
);
2116 dc
->XlatePen
= XlateObj
;
2119 case GDI_OBJECT_TYPE_BRUSH
:
2120 brush
= BRUSHOBJ_LockBrush((HPEN
) hGDIObj
);
2123 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2127 XlateObj
= IntGdiCreateBrushXlate(dc
, brush
, &Failed
);
2128 BRUSHOBJ_UnlockBrush(brush
);
2131 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2135 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
2136 dc
->w
.hBrush
= hGDIObj
;
2137 if (dc
->XlateBrush
!= NULL
)
2138 EngDeleteXlate(dc
->XlateBrush
);
2139 dc
->XlateBrush
= XlateObj
;
2142 case GDI_OBJECT_TYPE_FONT
:
2143 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hGDIObj
)))
2145 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
2146 dc
->w
.hFont
= (HFONT
) hGDIObj
;
2150 case GDI_OBJECT_TYPE_BITMAP
:
2151 // must be memory dc to select bitmap
2152 if (!(dc
->w
.flags
& DC_MEMORY
))
2157 pb
= BITMAPOBJ_LockBitmap(hGDIObj
);
2160 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2164 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
2166 /* Release the old bitmap, lock the new one and convert it to a SURF */
2167 dc
->w
.hBitmap
= hGDIObj
;
2169 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
2172 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
2173 dc
->w
.hPalette
= pb
->hDIBPalette
;
2177 dc
->w
.bitsPerPixel
= BitsPerFormat(pb
->SurfObj
.iBitmapFormat
);
2178 dc
->w
.hPalette
= dc
->DevInfo
->hpalDefault
;
2181 /* Reselect brush and pen to regenerate the XLATEOBJs. */
2182 NtGdiSelectObject ( hDC
, dc
->w
.hBrush
);
2183 NtGdiSelectObject ( hDC
, dc
->w
.hPen
);
2186 hVisRgn
= NtGdiCreateRectRgn ( 0, 0, pb
->SurfObj
.sizlBitmap
.cx
, pb
->SurfObj
.sizlBitmap
.cy
);
2187 BITMAPOBJ_UnlockBitmap( pb
);
2188 NtGdiSelectVisRgn ( hDC
, hVisRgn
);
2189 NtGdiDeleteObject ( hVisRgn
);
2193 case GDI_OBJECT_TYPE_REGION
:
2196 * The return value is one of the following values:
2201 return (HGDIOBJ
) NtGdiSelectClipRgn(hDC
, (HRGN
) hGDIObj
);
2211 NtGdiSetHookFlags(HDC hDC
, WORD Flags
)
2214 DC
*dc
= DC_LockDc(hDC
);
2218 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2222 wRet
= dc
->w
.flags
& DC_DIRTY
;
2224 /* "Undocumented Windows" info is slightly confusing.
2227 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2229 if (Flags
& DCHF_INVALIDATEVISRGN
)
2231 dc
->w
.flags
|= DC_DIRTY
;
2233 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2235 dc
->w
.flags
&= ~DC_DIRTY
;
2243 DC_SET_MODE( NtGdiSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
2244 DC_SET_MODE( NtGdiSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
2245 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
2246 DC_SET_MODE( NtGdiSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
2247 DC_SET_MODE( NtGdiSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
2249 // ---------------------------------------------------- Private Interface
2252 DC_AllocDC(PUNICODE_STRING Driver
)
2260 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2265 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2268 hDC
= (HDC
) GDIOBJ_AllocObj(GdiHandleTable
, GDI_OBJECT_TYPE_DC
);
2278 NewDC
= DC_LockDc(hDC
);
2279 /* FIXME - Handle NewDC == NULL! */
2283 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2284 NewDC
->DriverName
.Buffer
= Buf
;
2287 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2288 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2289 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2290 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2291 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2292 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2293 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2294 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2295 NewDC
->w
.vport2WorldValid
= TRUE
;
2296 NewDC
->w
.MapMode
= MM_TEXT
;
2297 NewDC
->wndExtX
= 1.0f
;
2298 NewDC
->wndExtY
= 1.0f
;
2299 NewDC
->vportExtX
= 1.0f
;
2300 NewDC
->vportExtY
= 1.0f
;
2301 NewDC
->w
.textColor
= 0;
2302 NewDC
->w
.backgroundColor
= 0xffffff;
2304 NewDC
->w
.hFont
= NtGdiGetStockObject(SYSTEM_FONT
);
2305 TextIntRealizeFont(NewDC
->w
.hFont
);
2307 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2315 DC_FindOpenDC(PUNICODE_STRING Driver
)
2321 * Initialize some common fields in the Device Context structure.
2324 DC_InitDC(HDC DCHandle
)
2326 // NtGdiRealizeDefaultPalette(DCHandle);
2328 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2329 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2330 //NtGdiSelectObject(DCHandle, hFont);
2335 res = CLIPPING_UpdateGCRegion(DCToInit);
2336 ASSERT ( res != ERROR );
2342 DC_FreeDC(HDC DCToFree
)
2344 if (!GDIOBJ_FreeObj(GdiHandleTable
, DCToFree
, GDI_OBJECT_TYPE_DC
))
2346 DPRINT("DC_FreeDC failed\n");
2351 DC_Cleanup(PVOID ObjectBody
)
2353 PDC pDC
= (PDC
)ObjectBody
;
2354 RtlFreeUnicodeString(&pDC
->DriverName
);
2359 DC_GetNextDC (PDC pDC
)
2365 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2367 pDC
->hNext
= hNextDC
;
2371 DC_UpdateXforms(PDC dc
)
2373 XFORM xformWnd2Vport
;
2374 FLOAT scaleX
, scaleY
;
2376 /* Construct a transformation to do the window-to-viewport conversion */
2377 scaleX
= (dc
->wndExtX
? (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
: 0.0f
);
2378 scaleY
= (dc
->wndExtY
? (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
: 0.0f
);
2379 xformWnd2Vport
.eM11
= scaleX
;
2380 xformWnd2Vport
.eM12
= 0.0;
2381 xformWnd2Vport
.eM21
= 0.0;
2382 xformWnd2Vport
.eM22
= scaleY
;
2383 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
2384 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
2386 /* Combine with the world transformation */
2387 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2389 /* Create inverse of world-to-viewport transformation */
2390 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2394 DC_InvertXform(const XFORM
*xformSrc
,
2399 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2400 if (determinant
> -1e-12 && determinant
< 1e-12)
2405 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2406 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2407 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2408 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2409 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2410 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2416 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2420 GDIOBJ_SetOwnership(GdiHandleTable
, hDC
, Owner
);
2421 DC
= DC_LockDc(hDC
);
2424 if (NULL
!= DC
->w
.hClipRgn
)
2426 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hClipRgn
);
2428 if (NULL
!= DC
->w
.hVisRgn
)
2430 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hVisRgn
);
2432 if (NULL
!= DC
->w
.hGCClipRgn
)
2434 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hGCClipRgn
);
2441 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2443 if (PrimarySurface
.Handle
== NULL
)
2447 return SurfObj
->hsurf
== PrimarySurface
.Handle
;
2451 * Returns the color of the brush or pen that is currently selected into the DC.
2452 * This function is called from GetDCBrushColor() and GetDCPenColor()
2455 IntGetDCColor(HDC hDC
, ULONG Object
)
2458 * The previous implementation was completly incorrect. It modified the
2459 * brush that was currently selected into the device context, but in fact
2460 * the DC pen/brush color should be stored directly in the device context
2461 * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
2462 * The actual color is then used when DC_BRUSH/DC_PEN object is selected
2463 * into the device context and BRUSHOBJ for drawing is composed (belongs
2464 * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
2465 * the implementation should be moved to user mode GDI32.dll when UM
2466 * mapped GDI objects will be implemented.
2469 DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
2470 return 0xFFFFFF; /* The default DC color. */
2474 * Changes the color of the brush or pen that is currently selected into the DC.
2475 * This function is called from SetDCBrushColor() and SetDCPenColor()
2478 IntSetDCColor(HDC hDC
, ULONG Object
, COLORREF Color
)
2480 /* See the comment in IntGetDCColor. */
2482 DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
2486 #define SIZEOF_DEVMODEW_300 188
2487 #define SIZEOF_DEVMODEW_400 212
2488 #define SIZEOF_DEVMODEW_500 220
2490 /*! \brief Enumerate possible display settings for the given display...
2492 * \todo Make thread safe!?
2493 * \todo Don't ignore pDeviceName
2494 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2497 IntEnumDisplaySettings(
2498 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2500 IN OUT LPDEVMODEW pDevMode
,
2503 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2504 static DWORD SizeOfCachedDevModes
= 0;
2505 PDEVMODEW CachedMode
= NULL
;
2508 ULONG DisplayNumber
= 0; /* only default display supported */
2510 DPRINT("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2511 DPRINT("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2512 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2513 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2514 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2516 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2520 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2522 CachedMode
= &PrimarySurface
.DMW
;
2523 ASSERT(CachedMode
->dmSize
> 0);
2525 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2527 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2528 DevMode
.dmSize
= sizeof (DevMode
);
2529 DevMode
.dmDriverExtra
= 0;
2530 if (SetupDevMode(&DevMode
, DisplayNumber
))
2531 CachedMode
= &DevMode
;
2534 SetLastWin32Error(0); /* FIXME: use error code */
2537 /* FIXME: Maybe look for the matching devmode supplied by the
2538 * driver so we can provide driver private/extra data?
2543 if (iModeNum
== 0 || CachedDevModes
== NULL
) /* query modes from drivers */
2545 UNICODE_STRING DriverFileNames
;
2547 DRVENABLEDATA DrvEnableData
;
2549 /* Retrieve DDI driver names from registry */
2550 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2551 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2553 DPRINT1("FindDriverFileNames failed\n");
2557 IntPrepareDriverIfNeeded();
2560 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2561 * scan all of them until a good one found.
2563 CurrentName
= DriverFileNames
.Buffer
;
2564 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2565 CurrentName
+= wcslen(CurrentName
) + 1)
2568 PGD_ENABLEDRIVER GDEnableDriver
;
2570 /* Get the DDI driver's entry point */
2571 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
2572 if (NULL
== GDEnableDriver
)
2574 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2578 /* Call DDI driver's EnableDriver function */
2579 RtlZeroMemory(&DrvEnableData
, sizeof (DrvEnableData
));
2581 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2583 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2587 CachedDevModesEnd
= CachedDevModes
;
2589 /* find DrvGetModes function */
2590 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2592 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2593 PGD_GETMODES GetModes
;
2594 INT SizeNeeded
, SizeUsed
;
2596 if (DrvFn
->iFunc
!= INDEX_DrvGetModes
)
2599 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2601 /* make sure we have enough memory to hold the modes */
2602 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2603 if (SizeNeeded
<= 0)
2605 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2609 SizeUsed
= CachedDevModesEnd
- CachedDevModes
;
2610 if (SizeOfCachedDevModes
- SizeUsed
< SizeNeeded
)
2614 SizeOfCachedDevModes
+= SizeNeeded
;
2615 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2616 if (NewBuffer
== NULL
)
2619 ExFreePool(CachedDevModes
);
2620 SizeOfCachedDevModes
= 0;
2621 CachedDevModes
= NULL
;
2622 CachedDevModesEnd
= NULL
;
2623 SetLastWin32Error(STATUS_NO_MEMORY
);
2626 if (CachedDevModes
!= NULL
)
2628 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2629 ExFreePool(CachedDevModes
);
2631 CachedDevModes
= NewBuffer
;
2632 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2636 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2637 SizeOfCachedDevModes
- SizeUsed
,
2639 if (SizeNeeded
<= 0)
2641 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2645 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2651 RtlFreeUnicodeString(&DriverFileNames
);
2654 /* return cached info */
2655 CachedMode
= CachedDevModes
;
2656 if (CachedMode
>= CachedDevModesEnd
)
2658 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2661 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2663 assert(CachedMode
->dmSize
> 0);
2664 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2666 if (CachedMode
>= CachedDevModesEnd
)
2668 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2673 ASSERT(CachedMode
!= NULL
);
2675 Size
= OldSize
= pDevMode
->dmSize
;
2676 if (Size
> CachedMode
->dmSize
)
2677 Size
= CachedMode
->dmSize
;
2678 RtlCopyMemory(pDevMode
, CachedMode
, Size
);
2679 RtlZeroMemory((PCHAR
)pDevMode
+ Size
, OldSize
- Size
);
2680 pDevMode
->dmSize
= OldSize
;
2682 Size
= OldSize
= pDevMode
->dmDriverExtra
;
2683 if (Size
> CachedMode
->dmDriverExtra
)
2684 Size
= CachedMode
->dmDriverExtra
;
2685 RtlCopyMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
,
2686 (PCHAR
)CachedMode
+ CachedMode
->dmSize
, Size
);
2687 RtlZeroMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
+ Size
, OldSize
- Size
);
2688 pDevMode
->dmDriverExtra
= OldSize
;
2693 static NTSTATUS FASTCALL
2695 OUT PUNICODE_STRING VideoDeviceName
,
2696 IN PCUNICODE_STRING DisplayDevice
) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
2698 UNICODE_STRING Prefix
= RTL_CONSTANT_STRING(L
"\\??\\");
2699 UNICODE_STRING ObjectName
;
2700 UNICODE_STRING KernelModeName
= { 0, };
2701 OBJECT_ATTRIBUTES ObjectAttributes
;
2704 HANDLE LinkHandle
= NULL
;
2707 RtlInitUnicodeString(VideoDeviceName
, NULL
);
2709 /* Get device name (DisplayDevice is "\.\xxx") */
2710 for (LastSlash
= DisplayDevice
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
2712 if (DisplayDevice
->Buffer
[LastSlash
- 1] == L
'\\')
2718 DPRINT1("Invalid device name '%wZ'\n", DisplayDevice
);
2719 Status
= STATUS_OBJECT_NAME_INVALID
;
2722 ObjectName
= *DisplayDevice
;
2723 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
2724 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
2725 ObjectName
.Buffer
+= LastSlash
;
2727 /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
2728 KernelModeName
.MaximumLength
= Prefix
.Length
+ ObjectName
.Length
+ sizeof(UNICODE_NULL
);
2729 KernelModeName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2730 KernelModeName
.MaximumLength
,
2732 if (!KernelModeName
.Buffer
)
2734 Status
= STATUS_NO_MEMORY
;
2737 RtlCopyUnicodeString(&KernelModeName
, &Prefix
);
2738 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
2739 if (!NT_SUCCESS(Status
))
2742 /* Open \??\xxx (ex: "\??\DISPLAY1") */
2743 InitializeObjectAttributes(&ObjectAttributes
,
2748 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
2751 if (!NT_SUCCESS(Status
))
2753 DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
2754 Status
= STATUS_NO_SUCH_DEVICE
;
2758 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, &Length
);
2759 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
2761 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
2762 Status
= STATUS_NO_SUCH_DEVICE
;
2765 VideoDeviceName
->MaximumLength
= Length
;
2766 VideoDeviceName
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
2767 VideoDeviceName
->MaximumLength
+ sizeof(UNICODE_NULL
),
2769 if (!VideoDeviceName
->Buffer
)
2771 Status
= STATUS_NO_MEMORY
;
2774 Status
= ZwQuerySymbolicLinkObject(LinkHandle
, VideoDeviceName
, NULL
);
2775 VideoDeviceName
->Buffer
[VideoDeviceName
->MaximumLength
/ sizeof(WCHAR
) - 1] = UNICODE_NULL
;
2776 if (!NT_SUCCESS(Status
))
2778 DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName
, Status
);
2779 Status
= STATUS_NO_SUCH_DEVICE
;
2782 Status
= STATUS_SUCCESS
;
2785 if (!NT_SUCCESS(Status
) && VideoDeviceName
->Buffer
)
2786 ExFreePoolWithTag(VideoDeviceName
->Buffer
, TAG_DC
);
2787 if (KernelModeName
.Buffer
)
2788 ExFreePoolWithTag(KernelModeName
.Buffer
, TAG_DC
);
2790 ZwClose(LinkHandle
);
2794 static NTSTATUS FASTCALL
2795 GetVideoRegistryKey(
2796 OUT PUNICODE_STRING RegistryPath
,
2797 IN PCUNICODE_STRING DeviceName
) /* ex: "\Device\Video0" */
2799 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
2802 RtlInitUnicodeString(RegistryPath
, NULL
);
2803 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2804 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
2805 QueryTable
[0].Name
= DeviceName
->Buffer
;
2806 QueryTable
[0].EntryContext
= RegistryPath
;
2808 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
2813 if (!NT_SUCCESS(Status
))
2815 DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName
, Status
);
2816 return STATUS_NO_SUCH_DEVICE
;
2819 DPRINT("RegistryPath %wZ\n", RegistryPath
);
2820 return STATUS_SUCCESS
;
2825 IntChangeDisplaySettings(
2826 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2827 IN LPDEVMODEW DevMode
,
2829 IN PVOID lParam OPTIONAL
)
2831 BOOLEAN Global
= FALSE
;
2832 BOOLEAN NoReset
= FALSE
;
2833 BOOLEAN Reset
= FALSE
;
2834 BOOLEAN SetPrimary
= FALSE
;
2838 DPRINT1("display flag : %x\n",dwflags
);
2840 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2842 /* Check global, reset and noreset flags */
2843 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
2845 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
2847 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
2849 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
2851 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
2853 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
2855 if (Reset
&& NoReset
)
2856 return DISP_CHANGE_BADFLAGS
;
2860 /* Dynamically change graphics mode */
2861 DPRINT1("flag 0 UNIMPLEMENT \n");
2862 return DISP_CHANGE_FAILED
;
2865 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
2867 /* Test reslution */
2868 dwflags
&= ~CDS_TEST
;
2869 DPRINT1("flag CDS_TEST UNIMPLEMENT");
2870 Ret
= DISP_CHANGE_FAILED
;
2873 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
2877 dwflags
&= ~CDS_FULLSCREEN
;
2878 DPRINT1("flag CDS_FULLSCREEN partially implemented");
2879 Ret
= DISP_CHANGE_FAILED
;
2881 lpDevMode
.dmBitsPerPel
=0;
2882 lpDevMode
.dmPelsWidth
=0;
2883 lpDevMode
.dmPelsHeight
=0;
2884 lpDevMode
.dmDriverExtra
=0;
2886 lpDevMode
.dmSize
= sizeof(DEVMODEW
);
2887 if (!IntEnumDisplaySettings(pDeviceName
, ENUM_CURRENT_SETTINGS
, &lpDevMode
, 0))
2888 return DISP_CHANGE_FAILED
;
2890 DPRINT1("Req Mode : %d x %d x %d\n", DevMode
->dmPelsWidth
,DevMode
->dmPelsHeight
,DevMode
->dmBitsPerPel
);
2891 DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode
.dmPelsWidth
,lpDevMode
.dmPelsHeight
, lpDevMode
.dmBitsPerPel
);
2894 if ((lpDevMode
.dmBitsPerPel
== DevMode
->dmBitsPerPel
) &&
2895 (lpDevMode
.dmPelsWidth
== DevMode
->dmPelsWidth
) &&
2896 (lpDevMode
.dmPelsHeight
== DevMode
->dmPelsHeight
))
2897 Ret
= DISP_CHANGE_SUCCESSFUL
;
2900 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
2902 dwflags
&= ~CDS_VIDEOPARAMETERS
;
2904 Ret
=DISP_CHANGE_BADPARAM
;
2907 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
2908 Ret
= DISP_CHANGE_FAILED
;
2913 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2916 UNICODE_STRING DeviceName
;
2917 UNICODE_STRING RegistryKey
;
2918 UNICODE_STRING InDeviceName
;
2919 OBJECT_ATTRIBUTES ObjectAttributes
;
2920 HANDLE DevInstRegKey
;
2923 DPRINT1("set CDS_UPDATEREGISTRY \n");
2925 dwflags
&= ~CDS_UPDATEREGISTRY
;
2927 /* Check if pDeviceName is NULL, we need to retrieve it */
2928 if (pDeviceName
== NULL
)
2930 WCHAR szBuffer
[MAX_DRIVER_NAME
];
2932 PWINDOW_OBJECT Wnd
=NULL
;
2936 hWnd
= IntGetDesktopWindow();
2937 if (!(Wnd
= UserGetWindowObject(hWnd
)))
2942 hDC
= (HDC
)UserGetWindowDC(Wnd
);
2944 DC
= DC_LockDc(hDC
);
2949 swprintf (szBuffer
, L
"\\\\.\\DISPLAY%lu", ((GDIDEVICE
*)DC
->GDIDevice
)->DisplayNumber
);
2952 RtlInitUnicodeString(&InDeviceName
, szBuffer
);
2953 pDeviceName
= &InDeviceName
;
2956 Status
= GetVideoDeviceName(&DeviceName
, pDeviceName
);
2957 if (!NT_SUCCESS(Status
))
2959 DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName
, Status
);
2960 return DISP_CHANGE_FAILED
;
2962 Status
= GetVideoRegistryKey(&RegistryKey
, &DeviceName
);
2963 if (!NT_SUCCESS(Status
))
2965 DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName
, Status
);
2966 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
2967 return DISP_CHANGE_FAILED
;
2969 ExFreePoolWithTag(DeviceName
.Buffer
, TAG_DC
);
2971 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
2972 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2973 Status
= ZwOpenKey(&DevInstRegKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
);
2974 if (!NT_SUCCESS(Status
))
2976 DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey
, Status
);
2977 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
2978 return DISP_CHANGE_FAILED
;
2980 ExFreePoolWithTag(RegistryKey
.Buffer
, TAG_DC
);
2982 /* Update needed fields */
2983 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
2985 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
2986 NewValue
= DevMode
->dmBitsPerPel
;
2987 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2990 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
2992 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
2993 NewValue
= DevMode
->dmPelsWidth
;
2994 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2997 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
2999 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
3000 NewValue
= DevMode
->dmPelsHeight
;
3001 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
3004 ZwClose(DevInstRegKey
);
3005 if (NT_SUCCESS(Status
))
3006 Ret
= DISP_CHANGE_RESTART
;
3008 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
3009 Ret
= DISP_CHANGE_NOTUPDATED
;
3013 Ret
= DISP_CHANGE_BADFLAGS
;