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
;
45 /* FIXME: DCs should probably be thread safe */
48 * DC device-independent Get/SetXXX functions
49 * (RJJ) swiped from WINE
52 #define DC_GET_VAL( func_type, func_name, dc_field ) \
53 func_type STDCALL func_name( HDC hdc ) \
56 PDC dc = DC_LockDc( hdc ); \
59 SetLastWin32Error(ERROR_INVALID_HANDLE); \
67 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
68 * important that the function has the right signature, for the implementation
69 * we can do whatever we want.
71 #define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
72 VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
79 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
81 NTSTATUS Status = STATUS_SUCCESS; \
86 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
89 if(!(dc = DC_LockDc(hdc))) \
91 SetLastWin32Error(ERROR_INVALID_HANDLE); \
94 Int##FuncName( dc, &Safept); \
105 Status = _SEH_GetExceptionCode(); \
108 if(!NT_SUCCESS(Status)) \
110 SetLastNtError(Status); \
116 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
117 INT STDCALL func_name( HDC hdc, INT mode ) \
121 if ((mode < min_val) || (mode > max_val)) \
123 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
126 dc = DC_LockDc ( hdc ); \
129 SetLastWin32Error(ERROR_INVALID_HANDLE); \
132 prevMode = dc->dc_field; \
133 dc->dc_field = mode; \
134 DC_UnlockDc ( dc ); \
139 // --------------------------------------------------------- File Statics
141 // ----------------------------------------------------- Public Functions
144 NtGdiCancelDC(HDC hDC
)
151 NtGdiCreateCompatibleDC(HDC hDC
)
155 HDC hNewDC
, DisplayDC
;
157 UNICODE_STRING DriverName
;
162 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
163 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
164 if (NULL
== DisplayDC
)
171 /* Allocate a new DC based on the original DC's device */
172 OrigDC
= DC_LockDc(hDC
);
175 if (NULL
!= DisplayDC
)
177 NtGdiDeleteObjectApp(DisplayDC
);
181 hNewDC
= DC_AllocDC(&OrigDC
->DriverName
);
186 if (NULL
!= DisplayDC
)
188 NtGdiDeleteObjectApp(DisplayDC
);
192 NewDC
= DC_LockDc( hNewDC
);
194 /* Copy information from original DC to new DC */
195 NewDC
->hSelf
= hNewDC
;
198 NewDC
->PDev
= OrigDC
->PDev
;
199 memcpy(NewDC
->FillPatternSurfaces
,
200 OrigDC
->FillPatternSurfaces
,
201 sizeof OrigDC
->FillPatternSurfaces
);
202 NewDC
->GDIInfo
= OrigDC
->GDIInfo
;
203 NewDC
->DevInfo
= OrigDC
->DevInfo
;
204 NewDC
->w
.bitsPerPixel
= OrigDC
->w
.bitsPerPixel
;
206 /* DriverName is copied in the AllocDC routine */
207 NewDC
->DeviceDriver
= OrigDC
->DeviceDriver
;
208 NewDC
->wndOrgX
= OrigDC
->wndOrgX
;
209 NewDC
->wndOrgY
= OrigDC
->wndOrgY
;
210 NewDC
->wndExtX
= OrigDC
->wndExtX
;
211 NewDC
->wndExtY
= OrigDC
->wndExtY
;
212 NewDC
->vportOrgX
= OrigDC
->vportOrgX
;
213 NewDC
->vportOrgY
= OrigDC
->vportOrgY
;
214 NewDC
->vportExtX
= OrigDC
->vportExtX
;
215 NewDC
->vportExtY
= OrigDC
->vportExtY
;
217 /* Create default bitmap */
218 if (!(hBitmap
= NtGdiCreateBitmap( 1, 1, 1, NewDC
->w
.bitsPerPixel
, NULL
)))
220 DC_UnlockDc( OrigDC
);
221 DC_UnlockDc( NewDC
);
223 if (NULL
!= DisplayDC
)
225 NtGdiDeleteObjectApp(DisplayDC
);
229 NewDC
->w
.flags
= DC_MEMORY
;
230 NewDC
->w
.hBitmap
= hBitmap
;
231 NewDC
->w
.hFirstBitmap
= hBitmap
;
232 NewDC
->GDIDevice
= OrigDC
->GDIDevice
;
234 NewDC
->PalIndexed
= OrigDC
->PalIndexed
;
235 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
236 NewDC
->w
.textColor
= OrigDC
->w
.textColor
;
237 NewDC
->w
.textAlign
= OrigDC
->w
.textAlign
;
238 NewDC
->w
.backgroundColor
= OrigDC
->w
.backgroundColor
;
239 NewDC
->w
.backgroundMode
= OrigDC
->w
.backgroundMode
;
240 NewDC
->w
.ROPmode
= OrigDC
->w
.ROPmode
;
243 if (NULL
!= DisplayDC
)
245 NtGdiDeleteObjectApp(DisplayDC
);
248 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
249 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
250 NtGdiDeleteObject(hVisRgn
);
258 GetRegistryPath(PUNICODE_STRING RegistryPath
, ULONG DisplayNumber
)
260 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
261 WCHAR DeviceNameBuffer
[20];
264 swprintf(DeviceNameBuffer
, L
"\\Device\\Video%d", DisplayNumber
);
265 RtlInitUnicodeString(RegistryPath
, NULL
);
266 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
267 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
268 QueryTable
[0].Name
= DeviceNameBuffer
;
269 QueryTable
[0].EntryContext
= RegistryPath
;
271 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
276 if (! NT_SUCCESS(Status
))
278 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber
);
282 DPRINT("RegistryPath %S\n", RegistryPath
->Buffer
);
288 FindDriverFileNames(PUNICODE_STRING DriverFileNames
, ULONG DisplayNumber
)
290 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
291 UNICODE_STRING RegistryPath
;
294 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
296 DPRINT("GetRegistryPath failed\n");
300 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
301 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
| RTL_QUERY_REGISTRY_DIRECT
;
302 QueryTable
[0].Name
= L
"InstalledDisplayDrivers";
303 QueryTable
[0].EntryContext
= DriverFileNames
;
305 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
310 RtlFreeUnicodeString(&RegistryPath
);
311 if (! NT_SUCCESS(Status
))
313 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
317 DPRINT("DriverFileNames %S\n", DriverFileNames
->Buffer
);
322 static NTSTATUS STDCALL
323 DevModeCallback(IN PWSTR ValueName
,
326 IN ULONG ValueLength
,
328 IN PVOID EntryContext
)
330 PDEVMODEW DevMode
= (PDEVMODEW
) Context
;
332 DPRINT("Found registry value for name %S: type %d, length %d\n",
333 ValueName
, ValueType
, ValueLength
);
335 if (REG_DWORD
== ValueType
&& sizeof(DWORD
) == ValueLength
)
337 if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.BitsPerPel"))
339 DevMode
->dmBitsPerPel
= *((DWORD
*) ValueData
);
341 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.Flags"))
343 DevMode
->dmDisplayFlags
= *((DWORD
*) ValueData
);
345 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.VRefresh"))
347 DevMode
->dmDisplayFrequency
= *((DWORD
*) ValueData
);
349 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XPanning"))
351 DevMode
->dmPanningWidth
= *((DWORD
*) ValueData
);
353 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.XResolution"))
355 DevMode
->dmPelsWidth
= *((DWORD
*) ValueData
);
357 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YPanning"))
359 DevMode
->dmPanningHeight
= *((DWORD
*) ValueData
);
361 else if (0 == _wcsicmp(ValueName
, L
"DefaultSettings.YResolution"))
363 DevMode
->dmPelsHeight
= *((DWORD
*) ValueData
);
367 return STATUS_SUCCESS
;
371 SetupDevMode(PDEVMODEW DevMode
, ULONG DisplayNumber
)
373 static WCHAR RegistryMachineSystem
[] = L
"\\REGISTRY\\MACHINE\\SYSTEM\\";
374 static WCHAR CurrentControlSet
[] = L
"CURRENTCONTROLSET\\";
375 static WCHAR ControlSet
[] = L
"CONTROLSET";
376 static WCHAR Insert
[] = L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
377 UNICODE_STRING RegistryPath
;
379 PWCHAR AfterControlSet
;
381 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
384 if (! GetRegistryPath(&RegistryPath
, DisplayNumber
))
386 DPRINT("GetRegistryPath failed\n");
390 Valid
= (0 == _wcsnicmp(RegistryPath
.Buffer
, RegistryMachineSystem
,
391 wcslen(RegistryMachineSystem
)));
394 AfterControlSet
= RegistryPath
.Buffer
+ wcslen(RegistryMachineSystem
);
395 if (0 == _wcsnicmp(AfterControlSet
, CurrentControlSet
, wcslen(CurrentControlSet
)))
397 AfterControlSet
+= wcslen(CurrentControlSet
);
399 else if (0 == _wcsnicmp(AfterControlSet
, ControlSet
, wcslen(ControlSet
)))
401 AfterControlSet
+= wcslen(ControlSet
);
402 while (L
'0' <= *AfterControlSet
&& L
'9' <= *AfterControlSet
)
406 Valid
= (L
'\\' == *AfterControlSet
);
417 ProfilePath
= ExAllocatePoolWithTag(PagedPool
,
418 (wcslen(RegistryPath
.Buffer
) +
419 wcslen(Insert
) + 1) * sizeof(WCHAR
),
421 if (NULL
!= ProfilePath
)
423 wcsncpy(ProfilePath
, RegistryPath
.Buffer
, AfterControlSet
- RegistryPath
.Buffer
);
424 wcscpy(ProfilePath
+ (AfterControlSet
- RegistryPath
.Buffer
), Insert
);
425 wcscat(ProfilePath
, AfterControlSet
);
427 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
428 QueryTable
[0].QueryRoutine
= DevModeCallback
;
429 QueryTable
[0].Flags
= 0;
430 QueryTable
[0].Name
= NULL
;
431 QueryTable
[0].EntryContext
= NULL
;
432 QueryTable
[0].DefaultType
= REG_NONE
;
433 QueryTable
[0].DefaultData
= NULL
;
434 QueryTable
[0].DefaultLength
= 0;
436 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
441 if (! NT_SUCCESS(Status
))
443 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
444 ProfilePath
, Status
);
449 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
450 DevMode
->dmBitsPerPel
, DevMode
->dmDisplayFrequency
,
451 DevMode
->dmPelsWidth
, DevMode
->dmPelsHeight
);
452 if (0 == DevMode
->dmBitsPerPel
|| 0 == DevMode
->dmDisplayFrequency
453 || 0 == DevMode
->dmPelsWidth
|| 0 == DevMode
->dmPelsHeight
)
455 DPRINT("Not all required devmode members are set\n");
460 ExFreePool(ProfilePath
);
469 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath
.Buffer
);
472 RtlFreeUnicodeString(&RegistryPath
);
476 RtlZeroMemory(DevMode
, sizeof(DEVMODEW
));
485 PGD_ENABLEDRIVER GDEnableDriver
;
487 UNICODE_STRING DriverFileNames
;
493 for (DisplayNumber
= 0; ; DisplayNumber
++)
495 DPRINT("Trying to load display driver no. %d\n", DisplayNumber
);
497 RtlZeroMemory(&PrimarySurface
, sizeof(PrimarySurface
));
499 PrimarySurface
.VideoFileObject
= DRIVER_FindMPDriver(DisplayNumber
);
501 /* Open the miniport driver */
502 if (PrimarySurface
.VideoFileObject
== NULL
)
504 DPRINT1("FindMPDriver failed\n");
508 /* Retrieve DDI driver names from registry */
509 RtlInitUnicodeString(&DriverFileNames
, NULL
);
510 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
512 DPRINT1("FindDriverFileNames failed\n");
517 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
518 * scan all of them until a good one found.
520 CurrentName
= DriverFileNames
.Buffer
;
523 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
525 /* Get the DDI driver's entry point */
526 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
527 if (NULL
== GDEnableDriver
)
529 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
533 /* Call DDI driver's EnableDriver function */
534 RtlZeroMemory(&DED
, sizeof(DED
));
536 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof(DED
), &DED
))
538 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
548 /* Skip to the next name but never get past the Unicode string */
549 while (L
'\0' != *CurrentName
&&
550 CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
554 if (CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
)))
561 RtlFreeUnicodeString(&DriverFileNames
);
565 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
566 DPRINT1("No suitable DDI driver found\n");
570 DPRINT("Display driver %S loaded\n", CurrentName
);
572 DPRINT("Building DDI Functions\n");
574 /* Construct DDI driver function dispatch table */
575 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
577 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
578 DPRINT1("BuildDDIFunctions failed\n");
582 /* Allocate a phyical device handle from the driver */
583 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
584 if (SetupDevMode(&PrimarySurface
.DMW
, DisplayNumber
))
586 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
590 PrimarySurface
.FillPatterns
,
591 sizeof(PrimarySurface
.GDIInfo
),
592 (ULONG
*) &PrimarySurface
.GDIInfo
,
593 sizeof(PrimarySurface
.DevInfo
),
594 &PrimarySurface
.DevInfo
,
597 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
598 DoDefault
= (NULL
== PrimarySurface
.PDev
);
601 DPRINT1("DrvEnablePDev with registry parameters failed\n");
611 RtlZeroMemory(&(PrimarySurface
.DMW
), sizeof(DEVMODEW
));
612 PrimarySurface
.DMW
.dmSize
= sizeof (PrimarySurface
.DMW
);
613 PrimarySurface
.PDev
= PrimarySurface
.DriverFunctions
.EnablePDEV(
617 PrimarySurface
.FillPatterns
,
618 sizeof(PrimarySurface
.GDIInfo
),
619 (ULONG
*) &PrimarySurface
.GDIInfo
,
620 sizeof(PrimarySurface
.DevInfo
),
621 &PrimarySurface
.DevInfo
,
624 (HANDLE
) (PrimarySurface
.VideoFileObject
->DeviceObject
));
626 if (NULL
== PrimarySurface
.PDev
)
628 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
629 DPRINT1("DrvEnablePDEV with default parameters failed\n");
630 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
635 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsX
)
637 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
638 PrimarySurface
.GDIInfo
.ulLogPixelsX
= 96;
640 if (0 == PrimarySurface
.GDIInfo
.ulLogPixelsY
)
642 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
643 PrimarySurface
.GDIInfo
.ulLogPixelsY
= 96;
646 PrimarySurface
.Pointer
.Exclude
.right
= -1;
648 DPRINT("calling completePDev\n");
650 /* Complete initialization of the physical device */
651 PrimarySurface
.DriverFunctions
.CompletePDEV(
653 (HDEV
)&PrimarySurface
);
655 DPRINT("calling DRIVER_ReferenceDriver\n");
657 DRIVER_ReferenceDriver(L
"DISPLAY");
659 PrimarySurface
.PreparedDriver
= TRUE
;
660 PrimarySurface
.DisplayNumber
= DisplayNumber
;
669 IntPrepareDriverIfNeeded()
671 return (PrimarySurface
.PreparedDriver
? TRUE
: IntPrepareDriver());
679 IO_STATUS_BLOCK Iosb
;
681 ULONG Length
= sizeof(BOOL
);
682 PIO_STACK_LOCATION StackPtr
;
683 LARGE_INTEGER StartOffset
;
684 PFILE_OBJECT FileObject
= PrimarySurface
.VideoFileObject
;
685 PDEVICE_OBJECT DeviceObject
= FileObject
->DeviceObject
;
687 DPRINT("PrepareVideoPrt() called\n");
689 KeClearEvent(&PrimarySurface
.VideoFileObject
->Event
);
691 ObReferenceObjectByPointer(FileObject
, 0, IoFileObjectType
, KernelMode
);
693 StartOffset
.QuadPart
= 0;
694 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
706 /* Set up IRP Data */
707 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
708 Irp
->RequestorMode
= KernelMode
;
709 Irp
->Overlay
.AsynchronousParameters
.UserApcRoutine
= NULL
;
710 Irp
->Overlay
.AsynchronousParameters
.UserApcContext
= NULL
;
711 Irp
->Flags
|= IRP_WRITE_OPERATION
;
713 /* Setup Stack Data */
714 StackPtr
= IoGetNextIrpStackLocation(Irp
);
715 StackPtr
->FileObject
= PrimarySurface
.VideoFileObject
;
716 StackPtr
->Parameters
.Write
.Key
= 0;
718 Status
= IoCallDriver(DeviceObject
, Irp
);
720 if (STATUS_PENDING
== Status
)
722 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, TRUE
, 0);
723 Status
= Iosb
.Status
;
726 return NT_SUCCESS(Status
);
730 IntCreatePrimarySurface()
737 if (! IntPrepareDriverIfNeeded())
742 if (! PrepareVideoPrt())
747 DPRINT("calling EnableSurface\n");
748 /* Enable the drawing surface */
749 PrimarySurface
.Handle
=
750 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
751 if (NULL
== PrimarySurface
.Handle
)
753 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
754 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
755 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
756 DPRINT1("DrvEnableSurface failed\n");
760 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, TRUE
);
762 calledFromUser
= UserIsEntered(); //fixme: possibly upgrade a shared lock
763 if (!calledFromUser
){
764 UserEnterExclusive();
768 IntAttachMonitor(&PrimarySurface
, PrimarySurface
.DisplayNumber
);
770 SurfObj
= EngLockSurface((HSURF
)PrimarySurface
.Handle
);
771 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
772 SurfSize
= SurfObj
->sizlBitmap
;
773 SurfaceRect
.left
= SurfaceRect
.top
= 0;
774 SurfaceRect
.right
= SurfObj
->sizlBitmap
.cx
;
775 SurfaceRect
.bottom
= SurfObj
->sizlBitmap
.cy
;
776 /* FIXME - why does EngEraseSurface() sometimes crash?
777 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
779 /* Put the pointer in the center of the screen */
780 GDIDEV(SurfObj
)->Pointer
.Pos
.x
= (SurfaceRect
.right
- SurfaceRect
.left
) / 2;
781 GDIDEV(SurfObj
)->Pointer
.Pos
.y
= (SurfaceRect
.bottom
- SurfaceRect
.top
) / 2;
783 EngUnlockSurface(SurfObj
);
784 co_IntShowDesktop(IntGetActiveDesktop(), SurfSize
.cx
, SurfSize
.cy
);
786 if (!calledFromUser
){
794 IntDestroyPrimarySurface()
798 DRIVER_UnreferenceDriver(L
"DISPLAY");
800 calledFromUser
= UserIsEntered();
801 if (!calledFromUser
){
802 UserEnterExclusive();
806 IntDetachMonitor(&PrimarySurface
);
808 if (!calledFromUser
){
813 * FIXME: Hide a mouse pointer there. Also because we have to prevent
814 * memory leaks with the Eng* mouse routines.
817 DPRINT("Reseting display\n" );
818 PrimarySurface
.DriverFunctions
.AssertMode(PrimarySurface
.PDev
, FALSE
);
819 PrimarySurface
.DriverFunctions
.DisableSurface(PrimarySurface
.PDev
);
820 PrimarySurface
.DriverFunctions
.DisablePDEV(PrimarySurface
.PDev
);
821 PrimarySurface
.PreparedDriver
= FALSE
;
825 ObDereferenceObject(PrimarySurface
.VideoFileObject
);
829 IntGdiCreateDC(PUNICODE_STRING Driver
,
830 PUNICODE_STRING Device
,
831 PUNICODE_STRING Output
,
832 CONST PDEVMODEW InitData
,
839 UNICODE_STRING StdDriver
;
842 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
844 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
848 if (! IntPrepareDriverIfNeeded())
850 DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
856 calledFromUser
= UserIsEntered();
857 if (!calledFromUser
){
858 UserEnterExclusive();
861 if (! co_IntGraphicsCheck(TRUE
))
863 if (!calledFromUser
){
866 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
870 if (!calledFromUser
){
877 /* Check for existing DC object */
878 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
881 return NtGdiCreateCompatibleDC(hDC
);
884 if (Driver
!= NULL
&& Driver
->Buffer
!= NULL
)
886 DPRINT("NAME: %wZ\n", Driver
); // FIXME: Should not crash if NULL
889 /* Allocate a DC object */
890 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
895 NewDC
= DC_LockDc( hNewDC
);
896 /* FIXME - NewDC can be NULL!!! Don't assert here! */
903 NewDC
->IsIC
= CreateAsIC
;
904 NewDC
->DevInfo
= &PrimarySurface
.DevInfo
;
905 NewDC
->GDIInfo
= &PrimarySurface
.GDIInfo
;
906 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
907 sizeof(NewDC
->FillPatternSurfaces
));
908 NewDC
->PDev
= PrimarySurface
.PDev
;
909 NewDC
->GDIDevice
= (HDEV
)&PrimarySurface
;
910 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
911 NewDC
->w
.hBitmap
= PrimarySurface
.Handle
;
913 NewDC
->w
.bitsPerPixel
= NewDC
->GDIInfo
->cBitsPixel
* NewDC
->GDIInfo
->cPlanes
;
914 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
918 NewDC
->PalIndexed
= NtGdiGetStockObject(DEFAULT_PALETTE
);
919 NewDC
->w
.hPalette
= NewDC
->DevInfo
->hpalDefault
;
920 NewDC
->w
.ROPmode
= R2_COPYPEN
;
922 DC_UnlockDc( NewDC
);
924 hVisRgn
= NtGdiCreateRectRgn(0, 0, NewDC
->GDIInfo
->ulHorzRes
,
925 NewDC
->GDIInfo
->ulVertRes
);
926 NtGdiSelectVisRgn(hNewDC
, hVisRgn
);
927 NtGdiDeleteObject(hVisRgn
);
929 /* Initialize the DC state */
931 NtGdiSetTextColor(hNewDC
, RGB(0, 0, 0));
932 NtGdiSetTextAlign(hNewDC
, TA_TOP
);
933 NtGdiSetBkColor(hNewDC
, RGB(255, 255, 255));
934 NtGdiSetBkMode(hNewDC
, OPAQUE
);
938 DC_UnlockDc( NewDC
);
945 NtGdiCreateDC(PUNICODE_STRING Driver
,
946 PUNICODE_STRING Device
,
947 PUNICODE_STRING Output
,
948 CONST PDEVMODEW InitData
)
950 UNICODE_STRING SafeDriver
, SafeDevice
;
951 DEVMODEW SafeInitData
;
953 NTSTATUS Status
= STATUS_SUCCESS
;
959 ProbeForRead(InitData
,
962 RtlCopyMemory(&SafeInitData
,
968 Status
= _SEH_GetExceptionCode();
972 if(!NT_SUCCESS(Status
))
974 SetLastNtError(Status
);
977 /* FIXME - InitData can have some more bytes! */
982 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
983 if(!NT_SUCCESS(Status
))
985 SetLastNtError(Status
);
992 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
993 if(!NT_SUCCESS(Status
))
995 RtlFreeUnicodeString(&SafeDriver
);
996 SetLastNtError(Status
);
1001 Ret
= IntGdiCreateDC(NULL
== Driver
? NULL
: &SafeDriver
,
1002 NULL
== Device
? NULL
: &SafeDevice
, NULL
,
1003 NULL
== InitData
? NULL
: &SafeInitData
, FALSE
);
1009 NtGdiCreateIC(PUNICODE_STRING Driver
,
1010 PUNICODE_STRING Device
,
1011 PUNICODE_STRING Output
,
1012 CONST PDEVMODEW InitData
)
1014 UNICODE_STRING SafeDriver
, SafeDevice
;
1015 DEVMODEW SafeInitData
;
1017 NTSTATUS Status
= STATUS_SUCCESS
;
1023 ProbeForRead(InitData
,
1026 RtlCopyMemory(&SafeInitData
,
1032 Status
= _SEH_GetExceptionCode();
1035 if(!NT_SUCCESS(Status
))
1037 SetLastNtError(Status
);
1040 /* FIXME - InitData can have some more bytes! */
1045 Status
= IntSafeCopyUnicodeString(&SafeDriver
, Driver
);
1046 if(!NT_SUCCESS(Status
))
1048 SetLastNtError(Status
);
1055 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
1056 if(!NT_SUCCESS(Status
))
1058 RtlFreeUnicodeString(&SafeDriver
);
1059 SetLastNtError(Status
);
1064 Ret
= IntGdiCreateDC(NULL
== Driver
? NULL
: &SafeDriver
,
1065 NULL
== Device
? NULL
: &SafeDevice
, NULL
,
1066 NULL
== InitData
? NULL
: &SafeInitData
, TRUE
);
1072 NtGdiDeleteObjectApp(HANDLE DCHandle
)
1076 if (!GDIOBJ_OwnedByCurrentProcess(GdiHandleTable
, DCHandle
))
1078 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1082 DCToDelete
= DC_LockDc(DCHandle
);
1083 if (DCToDelete
== NULL
)
1085 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1089 /* First delete all saved DCs */
1090 while (DCToDelete
->saveLevel
)
1095 savedHDC
= DC_GetNextDC (DCToDelete
);
1096 savedDC
= DC_LockDc (savedHDC
);
1097 if (savedDC
== NULL
)
1101 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
1102 DCToDelete
->saveLevel
--;
1103 DC_UnlockDc( savedDC
);
1104 NtGdiDeleteObjectApp (savedHDC
);
1107 /* Free GDI resources allocated to this DC */
1108 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
1111 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
1112 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
1113 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
1114 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
1115 if (DCToDelete
->w
.flags
& DC_MEMORY
)
1117 NtGdiDeleteObject (DCToDelete
->w
.hFirstBitmap
);
1119 if (DCToDelete
->XlateBrush
!= NULL
)
1120 EngDeleteXlate(DCToDelete
->XlateBrush
);
1121 if (DCToDelete
->XlatePen
!= NULL
)
1122 EngDeleteXlate(DCToDelete
->XlatePen
);
1124 if (DCToDelete
->w
.hClipRgn
)
1126 NtGdiDeleteObject (DCToDelete
->w
.hClipRgn
);
1128 if (DCToDelete
->w
.hVisRgn
)
1130 NtGdiDeleteObject (DCToDelete
->w
.hVisRgn
);
1132 if (NULL
!= DCToDelete
->CombinedClip
)
1134 IntEngDeleteClipRegion(DCToDelete
->CombinedClip
);
1136 if (DCToDelete
->w
.hGCClipRgn
)
1138 NtGdiDeleteObject (DCToDelete
->w
.hGCClipRgn
);
1141 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
1143 DC_UnlockDc( DCToDelete
);
1144 DC_FreeDC ( DCHandle
);
1155 IN OPTIONAL LPSTR pjIn
)
1167 OUT OPTIONAL PVOID pvBuf
)
1173 DC_GET_VAL( COLORREF
, NtGdiGetBkColor
, w
.backgroundColor
)
1174 DC_GET_VAL( INT
, NtGdiGetBkMode
, w
.backgroundMode
)
1175 DC_GET_VAL_EX( GetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
, x
, y
)
1176 DC_GET_VAL( HRGN
, NtGdiGetClipRgn
, w
.hClipRgn
)
1179 NtGdiGetCurrentObject(HDC hDC
, UINT ObjectType
)
1184 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
1185 if(!hDC
) return NULL
;
1187 if(!(dc
= DC_LockDc(hDC
)))
1189 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1196 SelObject
= dc
->w
.hPen
;
1199 SelObject
= dc
->w
.hBrush
;
1202 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
1206 SelObject
= dc
->w
.hFont
;
1209 SelObject
= dc
->w
.hBitmap
;
1211 case OBJ_COLORSPACE
:
1212 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1217 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1225 DC_GET_VAL_EX ( GetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
, x
, y
)
1228 IntGdiGetDCOrgEx(DC
*dc
, LPPOINT Point
)
1230 Point
->x
= dc
->w
.DCOrgX
;
1231 Point
->y
= dc
->w
.DCOrgY
;
1237 NtGdiGetDCOrgEx(HDC hDC
, LPPOINT Point
)
1242 NTSTATUS Status
= STATUS_SUCCESS
;
1246 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1250 dc
= DC_LockDc(hDC
);
1253 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1257 Ret
= IntGdiGetDCOrgEx(dc
, &SafePoint
);
1261 ProbeForWrite(Point
,
1268 Status
= _SEH_GetExceptionCode();
1272 if(!NT_SUCCESS(Status
))
1274 SetLastNtError(Status
);
1284 NtGdiSetBkColor(HDC hDC
, COLORREF color
)
1290 if (!(dc
= DC_LockDc(hDC
)))
1292 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1296 oldColor
= dc
->w
.backgroundColor
;
1297 dc
->w
.backgroundColor
= color
;
1298 hBrush
= dc
->w
.hBrush
;
1300 NtGdiSelectObject(hDC
, hBrush
);
1305 NtGdiGetDCState(HDC hDC
)
1310 dc
= DC_LockDc(hDC
);
1313 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1317 hnewdc
= DC_AllocDC(NULL
);
1323 newdc
= DC_LockDc( hnewdc
);
1324 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1327 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
1328 newdc
->w
.hPen
= dc
->w
.hPen
;
1329 newdc
->w
.hBrush
= dc
->w
.hBrush
;
1330 newdc
->w
.hFont
= dc
->w
.hFont
;
1331 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
1332 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
1334 newdc
->w
.hDevice
= dc
->w
.hDevice
;
1336 newdc
->PalIndexed
= dc
->PalIndexed
;
1337 newdc
->w
.hPalette
= dc
->w
.hPalette
;
1338 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
1339 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
1340 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
1341 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
1342 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
1343 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
1344 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
1345 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
1346 newdc
->w
.textColor
= dc
->w
.textColor
;
1347 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
1348 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
1349 newdc
->w
.textAlign
= dc
->w
.textAlign
;
1350 newdc
->w
.charExtra
= dc
->w
.charExtra
;
1351 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
1352 newdc
->w
.breakCount
= dc
->w
.breakCount
;
1353 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
1354 newdc
->w
.breakRem
= dc
->w
.breakRem
;
1355 newdc
->w
.MapMode
= dc
->w
.MapMode
;
1356 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
1358 /* Apparently, the DC origin is not changed by [GS]etDCState */
1359 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
1360 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
1362 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
1363 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
1364 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
1365 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
1366 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
1367 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
1368 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
1369 newdc
->wndOrgX
= dc
->wndOrgX
;
1370 newdc
->wndOrgY
= dc
->wndOrgY
;
1371 newdc
->wndExtX
= dc
->wndExtX
;
1372 newdc
->wndExtY
= dc
->wndExtY
;
1373 newdc
->vportOrgX
= dc
->vportOrgX
;
1374 newdc
->vportOrgY
= dc
->vportOrgY
;
1375 newdc
->vportExtX
= dc
->vportExtX
;
1376 newdc
->vportExtY
= dc
->vportExtY
;
1378 newdc
->hSelf
= hnewdc
;
1379 newdc
->saveLevel
= 0;
1380 newdc
->IsIC
= dc
->IsIC
;
1383 PATH_InitGdiPath( &newdc
->w
.path
);
1386 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1388 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
1391 newdc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1392 NtGdiCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
1394 DC_UnlockDc( newdc
);
1402 NtGdiSetDCState ( HDC hDC
, HDC hDCSave
)
1406 dc
= DC_LockDc ( hDC
);
1409 dcs
= DC_LockDc ( hDCSave
);
1412 if ( dcs
->w
.flags
& DC_SAVED
)
1414 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1416 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1419 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1422 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1423 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1424 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1425 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1426 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1427 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1428 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1429 dc
->w
.textColor
= dcs
->w
.textColor
;
1430 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1431 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1432 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1433 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1434 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1435 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1436 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1437 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1438 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1439 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1441 /* Apparently, the DC origin is not changed by [GS]etDCState */
1442 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1443 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1445 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1446 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1447 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1449 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1450 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1451 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1452 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1454 dc
->wndOrgX
= dcs
->wndOrgX
;
1455 dc
->wndOrgY
= dcs
->wndOrgY
;
1456 dc
->wndExtX
= dcs
->wndExtX
;
1457 dc
->wndExtY
= dcs
->wndExtY
;
1458 dc
->vportOrgX
= dcs
->vportOrgX
;
1459 dc
->vportOrgY
= dcs
->vportOrgY
;
1460 dc
->vportExtX
= dcs
->vportExtX
;
1461 dc
->vportExtY
= dcs
->vportExtY
;
1462 dc
->PalIndexed
= dcs
->PalIndexed
;
1464 if (!(dc
->w
.flags
& DC_MEMORY
))
1466 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1470 if (dcs
->w
.hClipRgn
)
1472 if (!dc
->w
.hClipRgn
)
1474 dc
->w
.hClipRgn
= NtGdiCreateRectRgn( 0, 0, 0, 0 );
1476 NtGdiCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1482 NtGdiDeleteObject( dc
->w
.hClipRgn
);
1489 res
= CLIPPING_UpdateGCRegion( dc
);
1490 ASSERT ( res
!= ERROR
);
1495 NtGdiSelectClipRgn(hDC
, dcs
->w
.hClipRgn
);
1498 NtGdiSelectObject( hDC
, dcs
->w
.hBitmap
);
1499 NtGdiSelectObject( hDC
, dcs
->w
.hBrush
);
1500 NtGdiSelectObject( hDC
, dcs
->w
.hFont
);
1501 NtGdiSelectObject( hDC
, dcs
->w
.hPen
);
1502 NtGdiSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1503 NtGdiSetTextColor( hDC
, dcs
->w
.textColor
);
1505 NtGdiSelectPalette( hDC
, dcs
->w
.hPalette
, FALSE
);
1508 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1513 DC_UnlockDc ( dcs
);
1516 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1520 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1524 IntGdiGetDeviceCaps(PDC dc
, INT Index
)
1529 /* Retrieve capability */
1533 ret
= dc
->GDIInfo
->ulVersion
;
1537 ret
= dc
->GDIInfo
->ulTechnology
;
1541 ret
= dc
->GDIInfo
->ulHorzSize
;
1545 ret
= dc
->GDIInfo
->ulVertSize
;
1549 ret
= dc
->GDIInfo
->ulHorzRes
;
1553 ret
= dc
->GDIInfo
->ulVertRes
;
1557 ret
= dc
->GDIInfo
->ulLogPixelsX
;
1561 ret
= dc
->GDIInfo
->ulLogPixelsY
;
1565 ret
= dc
->GDIInfo
->cBitsPixel
;
1569 ret
= dc
->GDIInfo
->cPlanes
;
1573 UNIMPLEMENTED
; /* FIXME */
1577 UNIMPLEMENTED
; /* FIXME */
1581 UNIMPLEMENTED
; /* FIXME */
1585 ret
= dc
->GDIInfo
->ulNumColors
;
1589 ret
= dc
->GDIInfo
->ulAspectX
;
1593 ret
= dc
->GDIInfo
->ulAspectY
;
1597 ret
= dc
->GDIInfo
->ulAspectXY
;
1601 UNIMPLEMENTED
; /* FIXME */
1605 UNIMPLEMENTED
; /* FIXME */
1609 ret
= dc
->GDIInfo
->ulNumPalReg
; /* FIXME not sure */
1617 UNIMPLEMENTED
; /* FIXME */
1621 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1631 case PHYSICALHEIGHT
:
1632 if(IntGdiEscape(dc
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
1642 case PHYSICALOFFSETX
:
1643 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1653 case PHYSICALOFFSETY
:
1654 if(IntGdiEscape(dc
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
1665 UNIMPLEMENTED
; /* FIXME */
1668 case SCALINGFACTORX
:
1669 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1679 case SCALINGFACTORY
:
1680 if(IntGdiEscape(dc
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
1691 ret
= dc
->GDIInfo
->flRaster
;
1695 UNIMPLEMENTED
; /* FIXME */
1699 UNIMPLEMENTED
; /* FIXME */
1703 UNIMPLEMENTED
; /* FIXME */
1707 ret
= dc
->GDIInfo
->flTextCaps
;
1719 NtGdiGetDeviceCaps(HDC hDC
,
1725 dc
= DC_LockDc(hDC
);
1728 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1732 ret
= IntGdiGetDeviceCaps(dc
, Index
);
1734 DPRINT("(%04x,%d): returning %d\n", hDC
, Index
, ret
);
1740 DC_GET_VAL( INT
, NtGdiGetMapMode
, w
.MapMode
)
1741 DC_GET_VAL( INT
, NtGdiGetPolyFillMode
, w
.polyFillMode
)
1744 IntGdiGetObject(HANDLE Handle
, INT Count
, LPVOID Buffer
)
1750 GdiObject
= GDIOBJ_LockObj(GdiHandleTable
, Handle
, GDI_OBJECT_TYPE_DONTCARE
);
1751 if (NULL
== GdiObject
)
1753 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1757 ObjectType
= GDIOBJ_GetObjectType(Handle
);
1761 case GDI_OBJECT_TYPE_PEN
:
1762 Result
= PEN_GetObject((PENOBJ
*) GdiObject
, Count
, Buffer
);
1764 case GDI_OBJECT_TYPE_BRUSH
:
1765 Result
= BRUSH_GetObject((BRUSHOBJ
*) GdiObject
, Count
, Buffer
);
1768 case GDI_OBJECT_TYPE_BITMAP
:
1769 Result
= BITMAP_GetObject((BITMAPOBJ
*) GdiObject
, Count
, Buffer
);
1771 case GDI_OBJECT_TYPE_FONT
:
1772 Result
= FontGetObject((PTEXTOBJ
) GdiObject
, Count
, Buffer
);
1774 // Fix the LOGFONT structure for the stock fonts
1775 if (FIRST_STOCK_HANDLE
<= Handle
&& Handle
<= LAST_STOCK_HANDLE
)
1777 FixStockFontSizeW(Handle
, Count
, Buffer
);
1782 case GDI_OBJECT_TYPE_PALETTE
:
1783 Result
= PALETTE_GetObject((PALETTEOBJ
*) GdiObject
, Count
, Buffer
);
1787 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType
);
1791 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, GdiObject
);
1797 NtGdiGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
1801 NTSTATUS Status
= STATUS_SUCCESS
;
1803 /* From Wine: GetObject does not SetLastError() on a null object */
1804 if (!handle
) return 0;
1813 ProbeForWrite(buffer
,
1819 Status
= _SEH_GetExceptionCode();
1823 if(!NT_SUCCESS(Status
))
1825 SetLastNtError(Status
);
1829 SafeBuf
= ExAllocatePoolWithTag(PagedPool
, count
, TAG_GDIOBJ
);
1832 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1836 Ret
= IntGdiGetObject(handle
, count
, SafeBuf
);
1840 /* pointer already probed! */
1841 RtlCopyMemory(buffer
,
1847 Status
= _SEH_GetExceptionCode();
1851 ExFreePool(SafeBuf
);
1852 if(!NT_SUCCESS(Status
))
1854 SetLastNtError(Status
);
1862 NtGdiGetObjectType(HANDLE handle
)
1868 ptr
= GDIOBJ_LockObj(GdiHandleTable
, handle
, GDI_OBJECT_TYPE_DONTCARE
);
1871 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1875 objectType
= GDIOBJ_GetObjectType(handle
);
1878 case GDI_OBJECT_TYPE_PEN
:
1881 case GDI_OBJECT_TYPE_BRUSH
:
1884 case GDI_OBJECT_TYPE_BITMAP
:
1885 result
= OBJ_BITMAP
;
1887 case GDI_OBJECT_TYPE_FONT
:
1890 case GDI_OBJECT_TYPE_PALETTE
:
1893 case GDI_OBJECT_TYPE_REGION
:
1894 result
= OBJ_REGION
;
1896 case GDI_OBJECT_TYPE_DC
:
1899 case GDI_OBJECT_TYPE_METADC
:
1900 result
= OBJ_METADC
;
1902 case GDI_OBJECT_TYPE_METAFILE
:
1903 result
= OBJ_METAFILE
;
1905 case GDI_OBJECT_TYPE_ENHMETAFILE
:
1906 result
= OBJ_ENHMETAFILE
;
1908 case GDI_OBJECT_TYPE_ENHMETADC
:
1909 result
= OBJ_ENHMETADC
;
1911 case GDI_OBJECT_TYPE_EXTPEN
:
1912 result
= OBJ_EXTPEN
;
1914 case GDI_OBJECT_TYPE_MEMDC
:
1919 DPRINT1("Magic 0x%08x not implemented\n", objectType
);
1923 GDIOBJ_UnlockObjByPtr(GdiHandleTable
, ptr
);
1927 DC_GET_VAL( INT
, NtGdiGetRelAbs
, w
.relAbsMode
)
1928 DC_GET_VAL( INT
, NtGdiGetROP2
, w
.ROPmode
)
1929 DC_GET_VAL( INT
, NtGdiGetStretchBltMode
, w
.stretchBltMode
)
1930 DC_GET_VAL( UINT
, NtGdiGetTextAlign
, w
.textAlign
)
1931 DC_GET_VAL( COLORREF
, NtGdiGetTextColor
, w
.textColor
)
1932 DC_GET_VAL_EX( GetViewportExtEx
, vportExtX
, vportExtY
, SIZE
, cx
, cy
)
1933 DC_GET_VAL_EX( GetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
, x
, y
)
1934 DC_GET_VAL_EX( GetWindowExtEx
, wndExtX
, wndExtY
, SIZE
, cx
, cy
)
1935 DC_GET_VAL_EX( GetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
, x
, y
)
1942 OUT PBOOL pbBanding
,
1943 IN OPTIONAL VOID
*pDriverInfo2
,
1944 OUT VOID
*ppUMdhpdev
)
1951 NtGdiRestoreDC(HDC hDC
, INT SaveLevel
)
1956 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC
, SaveLevel
);
1958 dc
= DC_LockDc(hDC
);
1961 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1965 if (SaveLevel
== -1)
1966 SaveLevel
= dc
->saveLevel
;
1968 if ((SaveLevel
< 1) || (SaveLevel
> dc
->saveLevel
))
1975 while (dc
->saveLevel
>= SaveLevel
)
1977 HDC hdcs
= DC_GetNextDC (dc
);
1979 dcs
= DC_LockDc (hdcs
);
1985 DC_SetNextDC (dcs
, DC_GetNextDC (dcs
));
1986 if (--dc
->saveLevel
< SaveLevel
)
1990 NtGdiSetDCState(hDC
, hdcs
);
1992 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
1994 /* FIXME: This might not be quite right, since we're
1995 * returning FALSE but still destroying the saved DC state */
1999 dc
= DC_LockDc(hDC
);
2009 NtGdiDeleteObjectApp (hdcs
);
2016 NtGdiSaveDC(HDC hDC
)
2022 DPRINT("NtGdiSaveDC(%lx)\n", hDC
);
2024 if (!(hdcs
= NtGdiGetDCState(hDC
)))
2029 dcs
= DC_LockDc (hdcs
);
2032 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2035 dc
= DC_LockDc (hDC
);
2039 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2044 /* Copy path. The reason why path saving / restoring is in SaveDC/
2045 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
2046 * functions are only in Win16 (which doesn't have paths) and that
2047 * SetDCState doesn't allow us to signal an error (which can happen
2048 * when copying paths).
2050 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
2052 NtGdiDeleteObjectApp (hdcs
);
2057 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
2058 DC_SetNextDC (dc
, hdcs
);
2059 ret
= ++dc
->saveLevel
;
2068 NtGdiSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
2070 HGDIOBJ objOrg
= NULL
; // default to failure
2080 if (!hDC
|| !hGDIObj
)
2083 * SelectObject() with a NULL DC returns 0 and sets ERROR_INVALID_HANDLE.
2084 * Note: Under XP at least invalid ptrs can also be passed, not just NULL;
2085 * Don't test that here in case it crashes earlier win versions.
2087 if (!hDC
) SetLastWin32Error(ERROR_INVALID_HANDLE
);
2091 dc
= DC_LockDc(hDC
);
2094 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2098 objectType
= GDIOBJ_GetObjectType(hGDIObj
);
2102 case GDI_OBJECT_TYPE_PEN
:
2103 pen
= PENOBJ_LockPen((HPEN
) hGDIObj
);
2106 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2110 XlateObj
= IntGdiCreateBrushXlate(dc
, pen
, &Failed
);
2111 PENOBJ_UnlockPen(pen
);
2114 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2118 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
2119 dc
->w
.hPen
= hGDIObj
;
2120 if (dc
->XlatePen
!= NULL
)
2121 EngDeleteXlate(dc
->XlatePen
);
2122 dc
->XlatePen
= XlateObj
;
2125 case GDI_OBJECT_TYPE_BRUSH
:
2126 brush
= BRUSHOBJ_LockBrush((HPEN
) hGDIObj
);
2129 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2133 XlateObj
= IntGdiCreateBrushXlate(dc
, brush
, &Failed
);
2134 BRUSHOBJ_UnlockBrush(brush
);
2137 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES
);
2141 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
2142 dc
->w
.hBrush
= hGDIObj
;
2143 if (dc
->XlateBrush
!= NULL
)
2144 EngDeleteXlate(dc
->XlateBrush
);
2145 dc
->XlateBrush
= XlateObj
;
2148 case GDI_OBJECT_TYPE_FONT
:
2149 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hGDIObj
)))
2151 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
2152 dc
->w
.hFont
= (HFONT
) hGDIObj
;
2156 case GDI_OBJECT_TYPE_BITMAP
:
2157 // must be memory dc to select bitmap
2158 if (!(dc
->w
.flags
& DC_MEMORY
))
2163 pb
= BITMAPOBJ_LockBitmap(hGDIObj
);
2166 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2170 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
2172 /* Release the old bitmap, lock the new one and convert it to a SURF */
2173 dc
->w
.hBitmap
= hGDIObj
;
2175 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
2178 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
2179 dc
->w
.hPalette
= pb
->hDIBPalette
;
2183 dc
->w
.bitsPerPixel
= BitsPerFormat(pb
->SurfObj
.iBitmapFormat
);
2184 dc
->w
.hPalette
= dc
->DevInfo
->hpalDefault
;
2187 /* Reselect brush and pen to regenerate the XLATEOBJs. */
2188 NtGdiSelectObject ( hDC
, dc
->w
.hBrush
);
2189 NtGdiSelectObject ( hDC
, dc
->w
.hPen
);
2192 hVisRgn
= NtGdiCreateRectRgn ( 0, 0, pb
->SurfObj
.sizlBitmap
.cx
, pb
->SurfObj
.sizlBitmap
.cy
);
2193 BITMAPOBJ_UnlockBitmap( pb
);
2194 NtGdiSelectVisRgn ( hDC
, hVisRgn
);
2195 NtGdiDeleteObject ( hVisRgn
);
2199 case GDI_OBJECT_TYPE_REGION
:
2202 * The return value is one of the following values:
2207 return (HGDIOBJ
) NtGdiSelectClipRgn(hDC
, (HRGN
) hGDIObj
);
2217 NtGdiSetHookFlags(HDC hDC
, WORD Flags
)
2220 DC
*dc
= DC_LockDc(hDC
);
2224 SetLastWin32Error(ERROR_INVALID_HANDLE
);
2228 wRet
= dc
->w
.flags
& DC_DIRTY
;
2230 /* "Undocumented Windows" info is slightly confusing.
2233 DPRINT("DC %p, Flags %04x\n", hDC
, Flags
);
2235 if (Flags
& DCHF_INVALIDATEVISRGN
)
2237 dc
->w
.flags
|= DC_DIRTY
;
2239 else if (Flags
& DCHF_VALIDATEVISRGN
|| 0 == Flags
)
2241 dc
->w
.flags
&= ~DC_DIRTY
;
2249 DC_SET_MODE( NtGdiSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
2250 DC_SET_MODE( NtGdiSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
2251 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
2252 DC_SET_MODE( NtGdiSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
2253 DC_SET_MODE( NtGdiSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
2255 // ---------------------------------------------------- Private Interface
2258 DC_AllocDC(PUNICODE_STRING Driver
)
2266 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
2271 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
2274 hDC
= (HDC
) GDIOBJ_AllocObj(GdiHandleTable
, GDI_OBJECT_TYPE_DC
);
2284 NewDC
= DC_LockDc(hDC
);
2285 /* FIXME - Handle NewDC == NULL! */
2289 RtlCopyMemory(&NewDC
->DriverName
, Driver
, sizeof(UNICODE_STRING
));
2290 NewDC
->DriverName
.Buffer
= Buf
;
2293 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
2294 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
2295 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
2296 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
2297 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
2298 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
2299 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
2300 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
2301 NewDC
->w
.vport2WorldValid
= TRUE
;
2302 NewDC
->w
.MapMode
= MM_TEXT
;
2303 NewDC
->wndExtX
= 1.0f
;
2304 NewDC
->wndExtY
= 1.0f
;
2305 NewDC
->vportExtX
= 1.0f
;
2306 NewDC
->vportExtY
= 1.0f
;
2307 NewDC
->w
.textColor
= 0;
2308 NewDC
->w
.backgroundColor
= 0xffffff;
2310 NewDC
->w
.hFont
= NtGdiGetStockObject(SYSTEM_FONT
);
2311 TextIntRealizeFont(NewDC
->w
.hFont
);
2313 NewDC
->w
.hPalette
= NtGdiGetStockObject(DEFAULT_PALETTE
);
2321 DC_FindOpenDC(PUNICODE_STRING Driver
)
2327 * Initialize some common fields in the Device Context structure.
2330 DC_InitDC(HDC DCHandle
)
2332 // NtGdiRealizeDefaultPalette(DCHandle);
2334 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( WHITE_BRUSH
));
2335 NtGdiSelectObject(DCHandle
, NtGdiGetStockObject( BLACK_PEN
));
2336 //NtGdiSelectObject(DCHandle, hFont);
2341 res = CLIPPING_UpdateGCRegion(DCToInit);
2342 ASSERT ( res != ERROR );
2348 DC_FreeDC(HDC DCToFree
)
2350 if (!GDIOBJ_FreeObj(GdiHandleTable
, DCToFree
, GDI_OBJECT_TYPE_DC
))
2352 DPRINT("DC_FreeDC failed\n");
2357 DC_Cleanup(PVOID ObjectBody
)
2359 PDC pDC
= (PDC
)ObjectBody
;
2360 RtlFreeUnicodeString(&pDC
->DriverName
);
2365 DC_GetNextDC (PDC pDC
)
2371 DC_SetNextDC (PDC pDC
, HDC hNextDC
)
2373 pDC
->hNext
= hNextDC
;
2377 DC_UpdateXforms(PDC dc
)
2379 XFORM xformWnd2Vport
;
2380 FLOAT scaleX
, scaleY
;
2382 /* Construct a transformation to do the window-to-viewport conversion */
2383 scaleX
= (dc
->wndExtX
? (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
: 0.0f
);
2384 scaleY
= (dc
->wndExtY
? (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
: 0.0f
);
2385 xformWnd2Vport
.eM11
= scaleX
;
2386 xformWnd2Vport
.eM12
= 0.0;
2387 xformWnd2Vport
.eM21
= 0.0;
2388 xformWnd2Vport
.eM22
= scaleY
;
2389 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
2390 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
2392 /* Combine with the world transformation */
2393 IntGdiCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
2395 /* Create inverse of world-to-viewport transformation */
2396 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
2400 DC_InvertXform(const XFORM
*xformSrc
,
2405 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
2406 if (determinant
> -1e-12 && determinant
< 1e-12)
2411 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
2412 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
2413 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
2414 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
2415 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
2416 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
2422 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
2426 GDIOBJ_SetOwnership(GdiHandleTable
, hDC
, Owner
);
2427 DC
= DC_LockDc(hDC
);
2430 if (NULL
!= DC
->w
.hClipRgn
)
2432 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hClipRgn
);
2434 if (NULL
!= DC
->w
.hVisRgn
)
2436 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hVisRgn
);
2438 if (NULL
!= DC
->w
.hGCClipRgn
)
2440 GDIOBJ_CopyOwnership(GdiHandleTable
, hDC
, DC
->w
.hGCClipRgn
);
2447 IntIsPrimarySurface(SURFOBJ
*SurfObj
)
2449 if (PrimarySurface
.Handle
== NULL
)
2453 return SurfObj
->hsurf
== PrimarySurface
.Handle
;
2457 * Returns the color of the brush or pen that is currently selected into the DC.
2458 * This function is called from GetDCBrushColor() and GetDCPenColor()
2461 IntGetDCColor(HDC hDC
, ULONG Object
)
2464 * The previous implementation was completly incorrect. It modified the
2465 * brush that was currently selected into the device context, but in fact
2466 * the DC pen/brush color should be stored directly in the device context
2467 * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
2468 * The actual color is then used when DC_BRUSH/DC_PEN object is selected
2469 * into the device context and BRUSHOBJ for drawing is composed (belongs
2470 * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
2471 * the implementation should be moved to user mode GDI32.dll when UM
2472 * mapped GDI objects will be implemented.
2475 DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
2476 return 0xFFFFFF; /* The default DC color. */
2480 * Changes the color of the brush or pen that is currently selected into the DC.
2481 * This function is called from SetDCBrushColor() and SetDCPenColor()
2484 IntSetDCColor(HDC hDC
, ULONG Object
, COLORREF Color
)
2486 /* See the comment in IntGetDCColor. */
2488 DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
2492 #define SIZEOF_DEVMODEW_300 188
2493 #define SIZEOF_DEVMODEW_400 212
2494 #define SIZEOF_DEVMODEW_500 220
2496 /*! \brief Enumerate possible display settings for the given display...
2498 * \todo Make thread safe!?
2499 * \todo Don't ignore pDeviceName
2500 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2503 IntEnumDisplaySettings(
2504 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2506 IN OUT LPDEVMODEW pDevMode
,
2509 static DEVMODEW
*CachedDevModes
= NULL
, *CachedDevModesEnd
= NULL
;
2510 static DWORD SizeOfCachedDevModes
= 0;
2511 PDEVMODEW CachedMode
= NULL
;
2514 ULONG DisplayNumber
= 0; /* only default display supported */
2516 DPRINT("DevMode->dmSize = %d\n", pDevMode
->dmSize
);
2517 DPRINT("DevMode->dmExtraSize = %d\n", pDevMode
->dmDriverExtra
);
2518 if (pDevMode
->dmSize
!= SIZEOF_DEVMODEW_300
&&
2519 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_400
&&
2520 pDevMode
->dmSize
!= SIZEOF_DEVMODEW_500
)
2522 SetLastWin32Error(STATUS_INVALID_PARAMETER
);
2526 if (iModeNum
== ENUM_CURRENT_SETTINGS
)
2528 CachedMode
= &PrimarySurface
.DMW
;
2529 ASSERT(CachedMode
->dmSize
> 0);
2531 else if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
2533 RtlZeroMemory(&DevMode
, sizeof (DevMode
));
2534 DevMode
.dmSize
= sizeof (DevMode
);
2535 DevMode
.dmDriverExtra
= 0;
2536 if (SetupDevMode(&DevMode
, DisplayNumber
))
2537 CachedMode
= &DevMode
;
2540 SetLastWin32Error(0); /* FIXME: use error code */
2543 /* FIXME: Maybe look for the matching devmode supplied by the
2544 * driver so we can provide driver private/extra data?
2549 if (iModeNum
== 0 || CachedDevModes
== NULL
) /* query modes from drivers */
2551 BOOL PrimarySurfaceCreated
= FALSE
;
2552 UNICODE_STRING DriverFileNames
;
2554 DRVENABLEDATA DrvEnableData
;
2556 /* Retrieve DDI driver names from registry */
2557 RtlInitUnicodeString(&DriverFileNames
, NULL
);
2558 if (!FindDriverFileNames(&DriverFileNames
, DisplayNumber
))
2560 DPRINT1("FindDriverFileNames failed\n");
2564 if (!HalQueryDisplayOwnership())
2566 IntCreatePrimarySurface();
2567 PrimarySurfaceCreated
= TRUE
;
2571 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2572 * scan all of them until a good one found.
2574 CurrentName
= DriverFileNames
.Buffer
;
2575 for (;CurrentName
< DriverFileNames
.Buffer
+ (DriverFileNames
.Length
/ sizeof (WCHAR
));
2576 CurrentName
+= wcslen(CurrentName
) + 1)
2579 PGD_ENABLEDRIVER GDEnableDriver
;
2581 /* Get the DDI driver's entry point */
2582 GDEnableDriver
= DRIVER_FindDDIDriver(CurrentName
);
2583 if (NULL
== GDEnableDriver
)
2585 DPRINT("FindDDIDriver failed for %S\n", CurrentName
);
2589 /* Call DDI driver's EnableDriver function */
2590 RtlZeroMemory(&DrvEnableData
, sizeof (DrvEnableData
));
2592 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01
, sizeof (DrvEnableData
), &DrvEnableData
))
2594 DPRINT("DrvEnableDriver failed for %S\n", CurrentName
);
2598 CachedDevModesEnd
= CachedDevModes
;
2600 /* find DrvGetModes function */
2601 for (i
= 0; i
< DrvEnableData
.c
; i
++)
2603 PDRVFN DrvFn
= DrvEnableData
.pdrvfn
+ i
;
2604 PGD_GETMODES GetModes
;
2605 INT SizeNeeded
, SizeUsed
;
2607 if (DrvFn
->iFunc
!= INDEX_DrvGetModes
)
2610 GetModes
= (PGD_GETMODES
)DrvFn
->pfn
;
2612 /* make sure we have enough memory to hold the modes */
2613 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
), 0, NULL
);
2614 if (SizeNeeded
<= 0)
2616 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2620 SizeUsed
= CachedDevModesEnd
- CachedDevModes
;
2621 if (SizeOfCachedDevModes
- SizeUsed
< SizeNeeded
)
2625 SizeOfCachedDevModes
+= SizeNeeded
;
2626 NewBuffer
= ExAllocatePool(PagedPool
, SizeOfCachedDevModes
);
2627 if (NewBuffer
== NULL
)
2630 ExFreePool(CachedDevModes
);
2631 SizeOfCachedDevModes
= 0;
2632 CachedDevModes
= NULL
;
2633 CachedDevModesEnd
= NULL
;
2634 if (PrimarySurfaceCreated
)
2636 IntDestroyPrimarySurface();
2638 SetLastWin32Error(STATUS_NO_MEMORY
);
2641 if (CachedDevModes
!= NULL
)
2643 RtlCopyMemory(NewBuffer
, CachedDevModes
, SizeUsed
);
2644 ExFreePool(CachedDevModes
);
2646 CachedDevModes
= NewBuffer
;
2647 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)NewBuffer
+ SizeUsed
);
2651 SizeNeeded
= GetModes((HANDLE
)(PrimarySurface
.VideoFileObject
->DeviceObject
),
2652 SizeOfCachedDevModes
- SizeUsed
,
2654 if (SizeNeeded
<= 0)
2656 DPRINT("DrvGetModes failed for %S\n", CurrentName
);
2660 CachedDevModesEnd
= (DEVMODEW
*)((PCHAR
)CachedDevModesEnd
+ SizeNeeded
);
2666 if (PrimarySurfaceCreated
)
2668 IntDestroyPrimarySurface();
2671 RtlFreeUnicodeString(&DriverFileNames
);
2674 /* return cached info */
2675 CachedMode
= CachedDevModes
;
2676 if (CachedMode
>= CachedDevModesEnd
)
2678 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2681 while (iModeNum
-- > 0 && CachedMode
< CachedDevModesEnd
)
2683 assert(CachedMode
->dmSize
> 0);
2684 CachedMode
= (DEVMODEW
*)((PCHAR
)CachedMode
+ CachedMode
->dmSize
+ CachedMode
->dmDriverExtra
);
2686 if (CachedMode
>= CachedDevModesEnd
)
2688 SetLastWin32Error(STATUS_NO_MORE_ENTRIES
);
2693 ASSERT(CachedMode
!= NULL
);
2695 Size
= OldSize
= pDevMode
->dmSize
;
2696 if (Size
> CachedMode
->dmSize
)
2697 Size
= CachedMode
->dmSize
;
2698 RtlCopyMemory(pDevMode
, CachedMode
, Size
);
2699 RtlZeroMemory((PCHAR
)pDevMode
+ Size
, OldSize
- Size
);
2700 pDevMode
->dmSize
= OldSize
;
2702 Size
= OldSize
= pDevMode
->dmDriverExtra
;
2703 if (Size
> CachedMode
->dmDriverExtra
)
2704 Size
= CachedMode
->dmDriverExtra
;
2705 RtlCopyMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
,
2706 (PCHAR
)CachedMode
+ CachedMode
->dmSize
, Size
);
2707 RtlZeroMemory((PCHAR
)pDevMode
+ pDevMode
->dmSize
+ Size
, OldSize
- Size
);
2708 pDevMode
->dmDriverExtra
= OldSize
;
2714 IntChangeDisplaySettings(
2715 IN PUNICODE_STRING pDeviceName OPTIONAL
,
2716 IN LPDEVMODEW DevMode
,
2718 IN PVOID lParam OPTIONAL
)
2720 BOOLEAN Global
= FALSE
;
2721 BOOLEAN NoReset
= FALSE
;
2722 BOOLEAN Reset
= FALSE
;
2723 BOOLEAN SetPrimary
= FALSE
;
2727 DPRINT1("display flag : %x\n",dwflags
);
2729 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2731 /* Check global, reset and noreset flags */
2732 if ((dwflags
& CDS_GLOBAL
) == CDS_GLOBAL
)
2734 if ((dwflags
& CDS_NORESET
) == CDS_NORESET
)
2736 dwflags
&= ~(CDS_GLOBAL
| CDS_NORESET
);
2738 if ((dwflags
& CDS_RESET
) == CDS_RESET
)
2740 if ((dwflags
& CDS_SET_PRIMARY
) == CDS_SET_PRIMARY
)
2742 dwflags
&= ~(CDS_RESET
| CDS_SET_PRIMARY
);
2744 if (Reset
&& NoReset
)
2745 return DISP_CHANGE_BADFLAGS
;
2749 /* Dynamically change graphics mode */
2750 DPRINT1("flag 0 UNIMPLEMENT \n");
2751 return DISP_CHANGE_FAILED
;
2754 if ((dwflags
& CDS_TEST
) == CDS_TEST
)
2756 /* Test reslution */
2757 dwflags
&= ~CDS_TEST
;
2758 DPRINT1("flag CDS_TEST UNIMPLEMENT");
2759 Ret
= DISP_CHANGE_FAILED
;
2762 if ((dwflags
& CDS_FULLSCREEN
) == CDS_FULLSCREEN
)
2766 dwflags
&= ~CDS_FULLSCREEN
;
2767 DPRINT1("flag CDS_FULLSCREEN partially implemented");
2768 Ret
= DISP_CHANGE_FAILED
;
2770 lpDevMode
.dmBitsPerPel
=0;
2771 lpDevMode
.dmPelsWidth
=0;
2772 lpDevMode
.dmPelsHeight
=0;
2773 lpDevMode
.dmDriverExtra
=0;
2775 lpDevMode
.dmSize
= sizeof(DEVMODE
);
2776 Status
= IntEnumDisplaySettings(pDeviceName
, ENUM_CURRENT_SETTINGS
, &lpDevMode
, 0);
2777 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2779 DPRINT1("Req Mode : %d x %d x %d\n", DevMode
->dmPelsWidth
,DevMode
->dmPelsHeight
,DevMode
->dmBitsPerPel
);
2780 DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode
.dmPelsWidth
,lpDevMode
.dmPelsHeight
, lpDevMode
.dmBitsPerPel
);
2783 if ((lpDevMode
.dmBitsPerPel
== DevMode
->dmBitsPerPel
) &&
2784 (lpDevMode
.dmPelsWidth
== DevMode
->dmPelsWidth
) &&
2785 (lpDevMode
.dmPelsHeight
== DevMode
->dmPelsHeight
))
2786 Ret
= DISP_CHANGE_SUCCESSFUL
;
2789 if ((dwflags
& CDS_VIDEOPARAMETERS
) == CDS_VIDEOPARAMETERS
)
2791 dwflags
&= ~CDS_VIDEOPARAMETERS
;
2793 Ret
=DISP_CHANGE_BADPARAM
;
2796 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
2797 Ret
= DISP_CHANGE_FAILED
;
2802 if ((dwflags
& CDS_UPDATEREGISTRY
) == CDS_UPDATEREGISTRY
)
2805 UNICODE_STRING ObjectName
;
2806 UNICODE_STRING KernelModeName
;
2807 WCHAR KernelModeNameBuffer
[256];
2808 UNICODE_STRING RegistryKey
;
2809 WCHAR RegistryKeyBuffer
[512];
2810 PDEVICE_OBJECT DeviceObject
;
2812 OBJECT_ATTRIBUTES ObjectAttributes
;
2813 HANDLE DevInstRegKey
;
2816 DPRINT1("set CDS_UPDATEREGISTRY \n");
2818 dwflags
&= ~CDS_UPDATEREGISTRY
;
2820 /* Get device name (pDeviceName is "\.\xxx") */
2821 for (LastSlash
= pDeviceName
->Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
2823 if (pDeviceName
->Buffer
[LastSlash
- 1] == L
'\\')
2827 if (LastSlash
== 0) return DISP_CHANGE_RESTART
;
2828 ObjectName
= *pDeviceName
;
2829 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
2830 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
2831 ObjectName
.Buffer
+= LastSlash
;
2833 KernelModeName
.Length
= 0;
2834 KernelModeName
.MaximumLength
= sizeof(KernelModeNameBuffer
);
2835 KernelModeName
.Buffer
= KernelModeNameBuffer
;
2837 /* Open \??\xxx (ex: "\??\DISPLAY1") */
2838 Status
= RtlAppendUnicodeToString(&KernelModeName
, L
"\\??\\");
2840 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2841 Status
= RtlAppendUnicodeStringToString(&KernelModeName
, &ObjectName
);
2843 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2844 Status
= ObReferenceObjectByName(
2846 OBJ_CASE_INSENSITIVE
,
2852 (PVOID
*)&DeviceObject
);
2854 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2855 /* Get associated driver name (ex: "VBE") */
2856 for (LastSlash
= DeviceObject
->DriverObject
->DriverName
.Length
/ sizeof(WCHAR
); LastSlash
> 0; LastSlash
--)
2858 if (DeviceObject
->DriverObject
->DriverName
.Buffer
[LastSlash
- 1] == L
'\\')
2862 if (LastSlash
== 0) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2863 ObjectName
= DeviceObject
->DriverObject
->DriverName
;
2864 ObjectName
.Length
-= LastSlash
* sizeof(WCHAR
);
2865 ObjectName
.MaximumLength
-= LastSlash
* sizeof(WCHAR
);
2866 ObjectName
.Buffer
+= LastSlash
;
2868 RegistryKey
.Length
= 0;
2869 RegistryKey
.MaximumLength
= sizeof(RegistryKeyBuffer
);
2870 RegistryKey
.Buffer
= RegistryKeyBuffer
;
2872 /* Open registry key */
2873 Status
= RtlAppendUnicodeToString(&RegistryKey
,
2874 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
2876 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2877 Status
= RtlAppendUnicodeStringToString(&RegistryKey
, &ObjectName
);
2879 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2880 Status
= RtlAppendUnicodeToString(&RegistryKey
,
2883 if (!NT_SUCCESS(Status
)) { ObDereferenceObject(DeviceObject
); return DISP_CHANGE_FAILED
; }
2885 InitializeObjectAttributes(&ObjectAttributes
, &RegistryKey
,
2886 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2887 Status
= ZwOpenKey(&DevInstRegKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
);
2888 ObDereferenceObject(DeviceObject
);
2889 if (!NT_SUCCESS(Status
)) return DISP_CHANGE_FAILED
;
2891 /* Update needed fields */
2892 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_BITSPERPEL
)
2894 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.BitsPerPel");
2895 NewValue
= DevMode
->dmBitsPerPel
;
2896 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2899 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSWIDTH
)
2901 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.XResolution");
2902 NewValue
= DevMode
->dmPelsWidth
;
2903 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2906 if (NT_SUCCESS(Status
) && DevMode
->dmFields
& DM_PELSHEIGHT
)
2908 RtlInitUnicodeString(&RegistryKey
, L
"DefaultSettings.YResolution");
2909 NewValue
= DevMode
->dmPelsHeight
;
2910 Status
= ZwSetValueKey(DevInstRegKey
, &RegistryKey
, 0, REG_DWORD
, &NewValue
, sizeof(NewValue
));
2913 ZwClose(DevInstRegKey
);
2914 if (NT_SUCCESS(Status
))
2915 Ret
= DISP_CHANGE_RESTART
;
2917 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
2918 Ret
= DISP_CHANGE_NOTUPDATED
;
2922 Ret
= DISP_CHANGE_BADFLAGS
;