Fix more bugs in change display. when you press on aply in desk.cpl later on ok you...
[reactos.git] / reactos / subsys / win32k / objects / dc.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * DC.C - Device context functions
22 *
23 */
24 #include <w32k.h>
25
26 #ifndef OBJ_COLORSPACE
27 #define OBJ_COLORSPACE (14)
28 #endif
29
30 static GDIDEVICE PrimarySurface;
31
32 /* FIXME: DCs should probably be thread safe */
33
34 /*
35 * DC device-independent Get/SetXXX functions
36 * (RJJ) swiped from WINE
37 */
38
39 #define DC_GET_VAL( func_type, func_name, dc_field ) \
40 func_type STDCALL func_name( HDC hdc ) \
41 { \
42 func_type ft; \
43 PDC dc = DC_LockDc( hdc ); \
44 if (!dc) \
45 { \
46 SetLastWin32Error(ERROR_INVALID_HANDLE); \
47 return 0; \
48 } \
49 ft = dc->dc_field; \
50 DC_UnlockDc( hdc ); \
51 return ft; \
52 }
53
54 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
55 * important that the function has the right signature, for the implementation
56 * we can do whatever we want.
57 */
58 #define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
59 VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
60 { \
61 ASSERT(dc); \
62 ASSERT(pt); \
63 pt->ax = dc->ret_x; \
64 pt->ay = dc->ret_y; \
65 } \
66 BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
67 { \
68 NTSTATUS Status; \
69 type Safept; \
70 PDC dc; \
71 if(!pt) \
72 { \
73 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
74 return FALSE; \
75 } \
76 if(!(dc = DC_LockDc(hdc))) \
77 { \
78 SetLastWin32Error(ERROR_INVALID_HANDLE); \
79 return FALSE; \
80 } \
81 Int##FuncName( dc, &Safept); \
82 DC_UnlockDc(hdc); \
83 Status = MmCopyToCaller(pt, &Safept, sizeof( type )); \
84 if(!NT_SUCCESS(Status)) \
85 { \
86 SetLastNtError(Status); \
87 return FALSE; \
88 } \
89 return TRUE; \
90 }
91
92 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
93 INT STDCALL func_name( HDC hdc, INT mode ) \
94 { \
95 INT prevMode; \
96 PDC dc; \
97 if ((mode < min_val) || (mode > max_val)) \
98 { \
99 SetLastWin32Error(ERROR_INVALID_PARAMETER); \
100 return 0; \
101 } \
102 dc = DC_LockDc ( hdc ); \
103 if ( !dc ) \
104 { \
105 SetLastWin32Error(ERROR_INVALID_HANDLE); \
106 return 0; \
107 } \
108 prevMode = dc->dc_field; \
109 dc->dc_field = mode; \
110 DC_UnlockDc ( hdc ); \
111 return prevMode; \
112 }
113
114
115 // --------------------------------------------------------- File Statics
116
117 // ----------------------------------------------------- Public Functions
118
119 BOOL STDCALL
120 NtGdiCancelDC(HDC hDC)
121 {
122 UNIMPLEMENTED;
123 return FALSE;
124 }
125
126 HDC STDCALL
127 NtGdiCreateCompatableDC(HDC hDC)
128 {
129 PDC NewDC, OrigDC;
130 HBITMAP hBitmap;
131 HDC hNewDC, DisplayDC;
132 HRGN hVisRgn;
133 UNICODE_STRING DriverName;
134
135 DisplayDC = NULL;
136 if (hDC == NULL)
137 {
138 RtlInitUnicodeString(&DriverName, L"DISPLAY");
139 DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
140 if (NULL == DisplayDC)
141 {
142 return NULL;
143 }
144 hDC = DisplayDC;
145 }
146
147 /* Allocate a new DC based on the original DC's device */
148 OrigDC = DC_LockDc(hDC);
149 if (NULL == OrigDC)
150 {
151 if (NULL != DisplayDC)
152 {
153 NtGdiDeleteDC(DisplayDC);
154 }
155 return NULL;
156 }
157 hNewDC = DC_AllocDC(&OrigDC->DriverName);
158
159 if (NULL == hNewDC)
160 {
161 DC_UnlockDc(hDC);
162 if (NULL != DisplayDC)
163 {
164 NtGdiDeleteDC(DisplayDC);
165 }
166 return NULL;
167 }
168 NewDC = DC_LockDc( hNewDC );
169
170 /* Copy information from original DC to new DC */
171 NewDC->hSelf = hNewDC;
172 NewDC->IsIC = FALSE;
173
174 NewDC->PDev = OrigDC->PDev;
175 memcpy(NewDC->FillPatternSurfaces,
176 OrigDC->FillPatternSurfaces,
177 sizeof OrigDC->FillPatternSurfaces);
178 NewDC->GDIInfo = OrigDC->GDIInfo;
179 NewDC->DevInfo = OrigDC->DevInfo;
180 NewDC->w.bitsPerPixel = OrigDC->w.bitsPerPixel;
181
182 /* DriverName is copied in the AllocDC routine */
183 NewDC->DeviceDriver = OrigDC->DeviceDriver;
184 NewDC->wndOrgX = OrigDC->wndOrgX;
185 NewDC->wndOrgY = OrigDC->wndOrgY;
186 NewDC->wndExtX = OrigDC->wndExtX;
187 NewDC->wndExtY = OrigDC->wndExtY;
188 NewDC->vportOrgX = OrigDC->vportOrgX;
189 NewDC->vportOrgY = OrigDC->vportOrgY;
190 NewDC->vportExtX = OrigDC->vportExtX;
191 NewDC->vportExtY = OrigDC->vportExtY;
192
193 /* Create default bitmap */
194 if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
195 {
196 DC_UnlockDc( hDC );
197 DC_UnlockDc( hNewDC );
198 DC_FreeDC( hNewDC );
199 if (NULL != DisplayDC)
200 {
201 NtGdiDeleteDC(DisplayDC);
202 }
203 return NULL;
204 }
205 NewDC->w.flags = DC_MEMORY;
206 NewDC->w.hBitmap = hBitmap;
207 NewDC->w.hFirstBitmap = hBitmap;
208 NewDC->GDIDevice = OrigDC->GDIDevice;
209
210 NewDC->w.hPalette = OrigDC->w.hPalette;
211 NewDC->w.textColor = OrigDC->w.textColor;
212 NewDC->w.textAlign = OrigDC->w.textAlign;
213 NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
214 NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
215 NewDC->w.ROPmode = OrigDC->w.ROPmode;
216 DC_UnlockDc( hDC );
217 if (NULL != DisplayDC)
218 {
219 NtGdiDeleteDC(DisplayDC);
220 }
221 DC_UnlockDc(hNewDC);
222
223 hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
224 NtGdiSelectVisRgn(hNewDC, hVisRgn);
225 NtGdiDeleteObject(hVisRgn);
226
227 DC_InitDC(hNewDC);
228
229 return hNewDC;
230 }
231
232 static BOOL FASTCALL
233 GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
234 {
235 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
236 WCHAR DeviceNameBuffer[20];
237 NTSTATUS Status;
238
239 swprintf(DeviceNameBuffer, L"\\Device\\Video%d", DisplayNumber);
240 RtlInitUnicodeString(RegistryPath, NULL);
241 RtlZeroMemory(QueryTable, sizeof(QueryTable));
242 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
243 QueryTable[0].Name = DeviceNameBuffer;
244 QueryTable[0].EntryContext = RegistryPath;
245
246 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
247 L"VIDEO",
248 QueryTable,
249 NULL,
250 NULL);
251 if (! NT_SUCCESS(Status))
252 {
253 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
254 return FALSE;
255 }
256
257 DPRINT("RegistryPath %S\n", RegistryPath->Buffer);
258
259 return TRUE;
260 }
261
262 static BOOL FASTCALL
263 FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
264 {
265 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
266 UNICODE_STRING RegistryPath;
267 NTSTATUS Status;
268
269 if (! GetRegistryPath(&RegistryPath, DisplayNumber))
270 {
271 DPRINT("GetRegistryPath failed\n");
272 return FALSE;
273 }
274
275 RtlZeroMemory(QueryTable, sizeof(QueryTable));
276 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
277 QueryTable[0].Name = L"InstalledDisplayDrivers";
278 QueryTable[0].EntryContext = DriverFileNames;
279
280 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
281 RegistryPath.Buffer,
282 QueryTable,
283 NULL,
284 NULL);
285 RtlFreeUnicodeString(&RegistryPath);
286 if (! NT_SUCCESS(Status))
287 {
288 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
289 return FALSE;
290 }
291
292 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
293
294 return TRUE;
295 }
296
297 static NTSTATUS STDCALL
298 DevModeCallback(IN PWSTR ValueName,
299 IN ULONG ValueType,
300 IN PVOID ValueData,
301 IN ULONG ValueLength,
302 IN PVOID Context,
303 IN PVOID EntryContext)
304 {
305 PDEVMODEW DevMode = (PDEVMODEW) Context;
306
307 DPRINT("Found registry value for name %S: type %d, length %d\n",
308 ValueName, ValueType, ValueLength);
309
310 if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
311 {
312 if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
313 {
314 DevMode->dmBitsPerPel = *((DWORD *) ValueData);
315 }
316 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
317 {
318 DevMode->dmDisplayFlags = *((DWORD *) ValueData);
319 }
320 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
321 {
322 DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
323 }
324 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
325 {
326 DevMode->dmPanningWidth = *((DWORD *) ValueData);
327 }
328 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
329 {
330 DevMode->dmPelsWidth = *((DWORD *) ValueData);
331 }
332 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
333 {
334 DevMode->dmPanningHeight = *((DWORD *) ValueData);
335 }
336 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
337 {
338 DevMode->dmPelsHeight = *((DWORD *) ValueData);
339 }
340 }
341
342 return STATUS_SUCCESS;
343 }
344
345 static BOOL FASTCALL
346 SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
347 {
348 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
349 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
350 static WCHAR ControlSet[] = L"CONTROLSET";
351 static WCHAR Insert[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
352 UNICODE_STRING RegistryPath;
353 BOOL Valid;
354 PWCHAR AfterControlSet;
355 PWCHAR ProfilePath;
356 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
357 NTSTATUS Status;
358
359 if (! GetRegistryPath(&RegistryPath, DisplayNumber))
360 {
361 DPRINT("GetRegistryPath failed\n");
362 return FALSE;
363 }
364
365 Valid = (0 == _wcsnicmp(RegistryPath.Buffer, RegistryMachineSystem,
366 wcslen(RegistryMachineSystem)));
367 if (Valid)
368 {
369 AfterControlSet = RegistryPath.Buffer + wcslen(RegistryMachineSystem);
370 if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
371 {
372 AfterControlSet += wcslen(CurrentControlSet);
373 }
374 else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
375 {
376 AfterControlSet += wcslen(ControlSet);
377 while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
378 {
379 AfterControlSet++;
380 }
381 Valid = (L'\\' == *AfterControlSet);
382 AfterControlSet++;
383 }
384 else
385 {
386 Valid = FALSE;
387 }
388 }
389
390 if (Valid)
391 {
392 ProfilePath = ExAllocatePoolWithTag(PagedPool,
393 (wcslen(RegistryPath.Buffer) +
394 wcslen(Insert) + 1) * sizeof(WCHAR),
395 TAG_DC);
396 if (NULL != ProfilePath)
397 {
398 wcsncpy(ProfilePath, RegistryPath.Buffer, AfterControlSet - RegistryPath.Buffer);
399 wcscpy(ProfilePath + (AfterControlSet - RegistryPath.Buffer), Insert);
400 wcscat(ProfilePath, AfterControlSet);
401
402 RtlZeroMemory(QueryTable, sizeof(QueryTable));
403 QueryTable[0].QueryRoutine = DevModeCallback;
404 QueryTable[0].Flags = 0;
405 QueryTable[0].Name = NULL;
406 QueryTable[0].EntryContext = NULL;
407 QueryTable[0].DefaultType = REG_NONE;
408 QueryTable[0].DefaultData = NULL;
409 QueryTable[0].DefaultLength = 0;
410
411 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
412 ProfilePath,
413 QueryTable,
414 DevMode,
415 NULL);
416 if (! NT_SUCCESS(Status))
417 {
418 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
419 ProfilePath, Status);
420 Valid = FALSE;
421 }
422 else
423 {
424 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
425 DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
426 DevMode->dmPelsWidth, DevMode->dmPelsHeight);
427 if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
428 || 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
429 {
430 DPRINT("Not all required devmode members are set\n");
431 Valid = FALSE;
432 }
433 }
434
435 ExFreePool(ProfilePath);
436 }
437 else
438 {
439 Valid = FALSE;
440 }
441 }
442 else
443 {
444 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath.Buffer);
445 }
446
447 RtlFreeUnicodeString(&RegistryPath);
448
449 if (! Valid)
450 {
451 RtlZeroMemory(DevMode, sizeof(DEVMODEW));
452 }
453
454 return Valid;
455 }
456
457 static BOOL FASTCALL
458 IntPrepareDriver()
459 {
460 PGD_ENABLEDRIVER GDEnableDriver;
461 DRVENABLEDATA DED;
462 UNICODE_STRING DriverFileNames;
463 PWSTR CurrentName;
464 BOOL GotDriver;
465 BOOL DoDefault;
466 ULONG DisplayNumber;
467
468 for (DisplayNumber = 0; ; DisplayNumber++)
469 {
470 DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
471
472 RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
473
474 PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
475
476 /* Open the miniport driver */
477 if (PrimarySurface.VideoFileObject == NULL)
478 {
479 DPRINT1("FindMPDriver failed\n");
480 return FALSE;
481 }
482
483 /* Retrieve DDI driver names from registry */
484 RtlInitUnicodeString(&DriverFileNames, NULL);
485 if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
486 {
487 DPRINT1("FindDriverFileNames failed\n");
488 continue;
489 }
490
491 /*
492 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
493 * scan all of them until a good one found.
494 */
495 CurrentName = DriverFileNames.Buffer;
496 GotDriver = FALSE;
497 while (!GotDriver &&
498 CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
499 {
500 /* Get the DDI driver's entry point */
501 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
502 if (NULL == GDEnableDriver)
503 {
504 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
505 }
506 else
507 {
508 /* Call DDI driver's EnableDriver function */
509 RtlZeroMemory(&DED, sizeof(DED));
510
511 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof(DED), &DED))
512 {
513 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
514 }
515 else
516 {
517 GotDriver = TRUE;
518 }
519 }
520
521 if (! GotDriver)
522 {
523 /* Skip to the next name but never get past the Unicode string */
524 while (L'\0' != *CurrentName &&
525 CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
526 {
527 CurrentName++;
528 }
529 if (CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
530 {
531 CurrentName++;
532 }
533 }
534 }
535
536 RtlFreeUnicodeString(&DriverFileNames);
537
538 if (!GotDriver)
539 {
540 ObDereferenceObject(PrimarySurface.VideoFileObject);
541 DPRINT1("No suitable DDI driver found\n");
542 continue;
543 }
544
545 DPRINT("Display driver %S loaded\n", CurrentName);
546
547 DPRINT("Building DDI Functions\n");
548
549 /* Construct DDI driver function dispatch table */
550 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
551 {
552 ObDereferenceObject(PrimarySurface.VideoFileObject);
553 DPRINT1("BuildDDIFunctions failed\n");
554 return FALSE;
555 }
556
557 /* Allocate a phyical device handle from the driver */
558 PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
559 if (SetupDevMode(&PrimarySurface.DMW, DisplayNumber))
560 {
561 PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
562 &PrimarySurface.DMW,
563 L"",
564 HS_DDI_MAX,
565 PrimarySurface.FillPatterns,
566 sizeof(PrimarySurface.GDIInfo),
567 (ULONG *) &PrimarySurface.GDIInfo,
568 sizeof(PrimarySurface.DevInfo),
569 &PrimarySurface.DevInfo,
570 NULL,
571 L"",
572 (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
573 DoDefault = (NULL == PrimarySurface.PDev);
574 if (DoDefault)
575 {
576 DPRINT1("DrvEnablePDev with registry parameters failed\n");
577 }
578 }
579 else
580 {
581 DoDefault = TRUE;
582 }
583
584 if (DoDefault)
585 {
586 RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
587 PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
588 PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDEV(
589 &PrimarySurface.DMW,
590 L"",
591 HS_DDI_MAX,
592 PrimarySurface.FillPatterns,
593 sizeof(PrimarySurface.GDIInfo),
594 (ULONG *) &PrimarySurface.GDIInfo,
595 sizeof(PrimarySurface.DevInfo),
596 &PrimarySurface.DevInfo,
597 NULL,
598 L"",
599 (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
600
601 if (NULL == PrimarySurface.PDev)
602 {
603 ObDereferenceObject(PrimarySurface.VideoFileObject);
604 DPRINT1("DrvEnablePDEV with default parameters failed\n");
605 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
606 continue;
607 }
608 }
609
610 if (0 == PrimarySurface.GDIInfo.ulLogPixelsX)
611 {
612 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
613 PrimarySurface.GDIInfo.ulLogPixelsX = 96;
614 }
615 if (0 == PrimarySurface.GDIInfo.ulLogPixelsY)
616 {
617 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
618 PrimarySurface.GDIInfo.ulLogPixelsY = 96;
619 }
620
621 PrimarySurface.Pointer.Exclude.right = -1;
622
623 DPRINT("calling completePDev\n");
624
625 /* Complete initialization of the physical device */
626 PrimarySurface.DriverFunctions.CompletePDEV(
627 PrimarySurface.PDev,
628 (HDEV)&PrimarySurface);
629
630 DPRINT("calling DRIVER_ReferenceDriver\n");
631
632 DRIVER_ReferenceDriver(L"DISPLAY");
633
634 PrimarySurface.PreparedDriver = TRUE;
635 PrimarySurface.DisplayNumber = DisplayNumber;
636
637 return TRUE;
638 }
639
640 return FALSE;
641 }
642
643 static BOOL FASTCALL
644 IntPrepareDriverIfNeeded()
645 {
646 return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
647 }
648
649 BOOL FASTCALL
650 IntCreatePrimarySurface()
651 {
652 SIZEL SurfSize;
653 RECTL SurfaceRect;
654 SURFOBJ *SurfObj;
655
656 if (! IntPrepareDriverIfNeeded())
657 {
658 return FALSE;
659 }
660
661 DPRINT("calling EnableSurface\n");
662 /* Enable the drawing surface */
663 PrimarySurface.Handle =
664 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
665 if (NULL == PrimarySurface.Handle)
666 {
667 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
668 PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.PDev);
669 ObDereferenceObject(PrimarySurface.VideoFileObject);
670 DPRINT1("DrvEnableSurface failed\n");
671 return FALSE;
672 }
673
674 PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, TRUE);
675
676 /* attach monitor */
677 IntAttachMonitor(&PrimarySurface, PrimarySurface.DisplayNumber);
678
679 SurfObj = EngLockSurface((HSURF)PrimarySurface.Handle);
680 SurfObj->dhpdev = PrimarySurface.PDev;
681 SurfSize = SurfObj->sizlBitmap;
682 SurfaceRect.left = SurfaceRect.top = 0;
683 SurfaceRect.right = SurfObj->sizlBitmap.cx;
684 SurfaceRect.bottom = SurfObj->sizlBitmap.cy;
685 /* FIXME - why does EngEraseSurface() sometimes crash?
686 EngEraseSurface(SurfObj, &SurfaceRect, 0); */
687
688 /* Put the pointer in the center of the screen */
689 GDIDEV(SurfObj)->Pointer.Pos.x = (SurfaceRect.right - SurfaceRect.left) / 2;
690 GDIDEV(SurfObj)->Pointer.Pos.y = (SurfaceRect.bottom - SurfaceRect.top) / 2;
691
692 EngUnlockSurface(SurfObj);
693 IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
694
695 return TRUE;
696 }
697
698 VOID FASTCALL
699 IntDestroyPrimarySurface()
700 {
701 DRIVER_UnreferenceDriver(L"DISPLAY");
702
703 /* detach monitor */
704 IntDetachMonitor(&PrimarySurface);
705
706 /*
707 * FIXME: Hide a mouse pointer there. Also because we have to prevent
708 * memory leaks with the Eng* mouse routines.
709 */
710
711 DPRINT("Reseting display\n" );
712 PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);
713 PrimarySurface.DriverFunctions.DisableSurface(PrimarySurface.PDev);
714 PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.PDev);
715 PrimarySurface.PreparedDriver = FALSE;
716
717 DceEmptyCache();
718
719 ObDereferenceObject(PrimarySurface.VideoFileObject);
720 }
721
722 HDC FASTCALL
723 IntGdiCreateDC(PUNICODE_STRING Driver,
724 PUNICODE_STRING Device,
725 PUNICODE_STRING Output,
726 CONST PDEVMODEW InitData,
727 BOOL CreateAsIC)
728 {
729 HDC hNewDC;
730 PDC NewDC;
731 HDC hDC = NULL;
732 SURFOBJ *SurfObj;
733 HRGN hVisRgn;
734 UNICODE_STRING StdDriver;
735
736 RtlInitUnicodeString(&StdDriver, L"DISPLAY");
737
738 if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
739 {
740 if (CreateAsIC)
741 {
742 if (! IntPrepareDriverIfNeeded())
743 {
744 DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
745 return NULL;
746 }
747 }
748 else if (! IntGraphicsCheck(TRUE))
749 {
750 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
751 return NULL;
752 }
753 }
754
755 /* Check for existing DC object */
756 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
757 {
758 hDC = hNewDC;
759 return NtGdiCreateCompatableDC(hDC);
760 }
761
762 if (Driver != NULL && Driver->Buffer != NULL)
763 {
764 DPRINT("NAME: %wZ\n", Driver); // FIXME: Should not crash if NULL
765 }
766
767 /* Allocate a DC object */
768 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
769 {
770 return NULL;
771 }
772
773 NewDC = DC_LockDc( hNewDC );
774 /* FIXME - NewDC can be NULL!!! Don't assert here! */
775 if ( !NewDC )
776 {
777 DC_FreeDC( hNewDC );
778 return NULL;
779 }
780
781 NewDC->IsIC = CreateAsIC;
782 NewDC->DevInfo = &PrimarySurface.DevInfo;
783 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
784 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
785 sizeof(NewDC->FillPatternSurfaces));
786 NewDC->PDev = PrimarySurface.PDev;
787 NewDC->GDIDevice = (HDEV)&PrimarySurface;
788 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
789 NewDC->w.hBitmap = PrimarySurface.Handle;
790
791 NewDC->w.bitsPerPixel = NewDC->GDIInfo->cBitsPixel * NewDC->GDIInfo->cPlanes;
792 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
793
794 if (! CreateAsIC)
795 {
796 SurfObj = EngLockSurface((HSURF)PrimarySurface.Handle);
797 if ( !SurfObj )
798 {
799 DC_UnlockDc ( hNewDC );
800 DC_FreeDC ( hNewDC) ;
801 return NULL;
802 }
803 ASSERT(NewDC->GDIInfo->cBitsPixel * NewDC->GDIInfo->cPlanes == BitsPerFormat(SurfObj->iBitmapFormat));
804 ASSERT(NewDC->GDIInfo->ulHorzRes == SurfObj->sizlBitmap.cx);
805 ASSERT(NewDC->GDIInfo->ulVertRes == SurfObj->sizlBitmap.cy);
806
807 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
808 NewDC->w.ROPmode = R2_COPYPEN;
809
810 DC_UnlockDc( hNewDC );
811
812 hVisRgn = NtGdiCreateRectRgn(0, 0, SurfObj->sizlBitmap.cx,
813 SurfObj->sizlBitmap.cy);
814 NtGdiSelectVisRgn(hNewDC, hVisRgn);
815 NtGdiDeleteObject(hVisRgn);
816
817 /* Initialize the DC state */
818 DC_InitDC(hNewDC);
819 NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
820 NtGdiSetTextAlign(hNewDC, TA_TOP);
821 NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
822 NtGdiSetBkMode(hNewDC, OPAQUE);
823
824 EngUnlockSurface(SurfObj);
825 }
826 else
827 {
828 DC_UnlockDc( hNewDC );
829 }
830
831 return hNewDC;
832 }
833
834 HDC STDCALL
835 NtGdiCreateDC(PUNICODE_STRING Driver,
836 PUNICODE_STRING Device,
837 PUNICODE_STRING Output,
838 CONST PDEVMODEW InitData)
839 {
840 UNICODE_STRING SafeDriver, SafeDevice;
841 DEVMODEW SafeInitData;
842 HDC Ret;
843 NTSTATUS Status;
844
845 if(InitData)
846 {
847 Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
848 if(!NT_SUCCESS(Status))
849 {
850 SetLastNtError(Status);
851 return NULL;
852 }
853 /* FIXME - InitData can have some more bytes! */
854 }
855
856 if(Driver)
857 {
858 Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
859 if(!NT_SUCCESS(Status))
860 {
861 SetLastNtError(Status);
862 return NULL;
863 }
864 }
865
866 if(Device)
867 {
868 Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
869 if(!NT_SUCCESS(Status))
870 {
871 RtlFreeUnicodeString(&SafeDriver);
872 SetLastNtError(Status);
873 return NULL;
874 }
875 }
876
877 Ret = IntGdiCreateDC(&SafeDriver, &SafeDevice, NULL, &SafeInitData, FALSE);
878
879 return Ret;
880 }
881
882 HDC STDCALL
883 NtGdiCreateIC(PUNICODE_STRING Driver,
884 PUNICODE_STRING Device,
885 PUNICODE_STRING Output,
886 CONST PDEVMODEW InitData)
887 {
888 UNICODE_STRING SafeDriver, SafeDevice;
889 DEVMODEW SafeInitData;
890 HDC Ret;
891 NTSTATUS Status;
892
893 if(InitData)
894 {
895 Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
896 if(!NT_SUCCESS(Status))
897 {
898 SetLastNtError(Status);
899 return NULL;
900 }
901 /* FIXME - InitData can have some more bytes! */
902 }
903
904 if(Driver)
905 {
906 Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
907 if(!NT_SUCCESS(Status))
908 {
909 SetLastNtError(Status);
910 return NULL;
911 }
912 }
913
914 if(Device)
915 {
916 Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
917 if(!NT_SUCCESS(Status))
918 {
919 RtlFreeUnicodeString(&SafeDriver);
920 SetLastNtError(Status);
921 return NULL;
922 }
923 }
924
925 Ret = IntGdiCreateDC(NULL == Driver ? NULL : &SafeDriver,
926 NULL == Device ? NULL : &SafeDevice, NULL,
927 NULL == InitData ? NULL : &SafeInitData, TRUE);
928
929 return Ret;
930 }
931
932 BOOL STDCALL
933 NtGdiDeleteDC(HDC DCHandle)
934 {
935 PDC DCToDelete;
936
937 DCToDelete = DC_LockDc(DCHandle);
938 if (DCToDelete == NULL)
939 {
940 return FALSE;
941 }
942
943 /* First delete all saved DCs */
944 while (DCToDelete->saveLevel)
945 {
946 PDC savedDC;
947 HDC savedHDC;
948
949 savedHDC = DC_GetNextDC (DCToDelete);
950 savedDC = DC_LockDc (savedHDC);
951 if (savedDC == NULL)
952 {
953 break;
954 }
955 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
956 DCToDelete->saveLevel--;
957 DC_UnlockDc( savedHDC );
958 NtGdiDeleteDC (savedHDC);
959 }
960
961 /* Free GDI resources allocated to this DC */
962 if (!(DCToDelete->w.flags & DC_SAVED))
963 {
964 /*
965 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
966 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
967 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
968 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
969 if (DCToDelete->w.flags & DC_MEMORY)
970 {
971 NtGdiDeleteObject (DCToDelete->w.hFirstBitmap);
972 }
973 if (DCToDelete->XlateBrush != NULL)
974 EngDeleteXlate(DCToDelete->XlateBrush);
975 if (DCToDelete->XlatePen != NULL)
976 EngDeleteXlate(DCToDelete->XlatePen);
977 }
978 if (DCToDelete->w.hClipRgn)
979 {
980 NtGdiDeleteObject (DCToDelete->w.hClipRgn);
981 }
982 if (DCToDelete->w.hVisRgn)
983 {
984 NtGdiDeleteObject (DCToDelete->w.hVisRgn);
985 }
986 if (NULL != DCToDelete->CombinedClip)
987 {
988 IntEngDeleteClipRegion(DCToDelete->CombinedClip);
989 }
990 if (DCToDelete->w.hGCClipRgn)
991 {
992 NtGdiDeleteObject (DCToDelete->w.hGCClipRgn);
993 }
994 #if 0 /* FIXME */
995 PATH_DestroyGdiPath (&DCToDelete->w.path);
996 #endif
997 DC_UnlockDc( DCHandle );
998 DC_FreeDC ( DCHandle );
999
1000 return TRUE;
1001 }
1002
1003 INT STDCALL
1004 NtGdiDrawEscape(HDC hDC,
1005 INT nEscape,
1006 INT cbInput,
1007 LPCSTR lpszInData)
1008 {
1009 UNIMPLEMENTED;
1010 return 0;
1011 }
1012
1013 INT STDCALL
1014 NtGdiEnumObjects(HDC hDC,
1015 INT ObjectType,
1016 GOBJENUMPROC ObjectFunc,
1017 LPARAM lParam)
1018 {
1019 UNIMPLEMENTED;
1020 return 0;
1021 }
1022
1023 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
1024 DC_GET_VAL( INT, NtGdiGetBkMode, w.backgroundMode )
1025 DC_GET_VAL_EX( GetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT, x, y )
1026 DC_GET_VAL( HRGN, NtGdiGetClipRgn, w.hClipRgn )
1027
1028 HGDIOBJ STDCALL
1029 NtGdiGetCurrentObject(HDC hDC, UINT ObjectType)
1030 {
1031 HGDIOBJ SelObject;
1032 DC *dc;
1033
1034 if(!(dc = DC_LockDc(hDC)))
1035 {
1036 SetLastWin32Error(ERROR_INVALID_HANDLE);
1037 return NULL;
1038 }
1039
1040 switch(ObjectType)
1041 {
1042 case OBJ_PEN:
1043 SelObject = dc->w.hPen;
1044 break;
1045 case OBJ_BRUSH:
1046 SelObject = dc->w.hBrush;
1047 break;
1048 case OBJ_PAL:
1049 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_PAL not supported yet!\n");
1050 SelObject = NULL;
1051 break;
1052 case OBJ_FONT:
1053 SelObject = dc->w.hFont;
1054 break;
1055 case OBJ_BITMAP:
1056 SelObject = dc->w.hBitmap;
1057 break;
1058 case OBJ_COLORSPACE:
1059 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
1060 SelObject = NULL;
1061 break;
1062 default:
1063 SelObject = NULL;
1064 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1065 break;
1066 }
1067
1068 DC_UnlockDc(hDC);
1069 return SelObject;
1070 }
1071
1072 DC_GET_VAL_EX ( GetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT, x, y )
1073
1074 BOOL FASTCALL
1075 IntGdiGetDCOrgEx(DC *dc, LPPOINT Point)
1076 {
1077 Point->x = dc->w.DCOrgX;
1078 Point->y = dc->w.DCOrgY;
1079
1080 return TRUE;
1081 }
1082
1083 BOOL STDCALL
1084 NtGdiGetDCOrgEx(HDC hDC, LPPOINT Point)
1085 {
1086 BOOL Ret;
1087 DC *dc;
1088 POINT SafePoint;
1089 NTSTATUS Status;
1090
1091 if(!Point)
1092 {
1093 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1094 return FALSE;
1095 }
1096
1097 dc = DC_LockDc(hDC);
1098 if(!dc)
1099 {
1100 SetLastWin32Error(ERROR_INVALID_HANDLE);
1101 return FALSE;
1102 }
1103
1104 Ret = IntGdiGetDCOrgEx(dc, &SafePoint);
1105
1106 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
1107 if(!NT_SUCCESS(Status))
1108 {
1109 SetLastNtError(Status);
1110 DC_UnlockDc(hDC);
1111 return FALSE;
1112 }
1113
1114 DC_UnlockDc(hDC);
1115 return Ret;
1116 }
1117
1118 COLORREF STDCALL
1119 NtGdiSetBkColor(HDC hDC, COLORREF color)
1120 {
1121 COLORREF oldColor;
1122 PDC dc;
1123 HBRUSH hBrush;
1124
1125 if (!(dc = DC_LockDc(hDC)))
1126 {
1127 SetLastWin32Error(ERROR_INVALID_HANDLE);
1128 return CLR_INVALID;
1129 }
1130
1131 oldColor = dc->w.backgroundColor;
1132 dc->w.backgroundColor = color;
1133 hBrush = dc->w.hBrush;
1134 DC_UnlockDc ( hDC );
1135 NtGdiSelectObject(hDC, hBrush);
1136 return oldColor;
1137 }
1138
1139 HDC STDCALL
1140 NtGdiGetDCState(HDC hDC)
1141 {
1142 PDC newdc, dc;
1143 HDC hnewdc;
1144
1145 dc = DC_LockDc(hDC);
1146 if (dc == NULL)
1147 {
1148 SetLastWin32Error(ERROR_INVALID_HANDLE);
1149 return 0;
1150 }
1151
1152 hnewdc = DC_AllocDC(NULL);
1153 if (hnewdc == NULL)
1154 {
1155 DC_UnlockDc( hDC );
1156 return 0;
1157 }
1158 newdc = DC_LockDc( hnewdc );
1159 /* FIXME - newdc can be NULL!!!! Don't assert here!!! */
1160 ASSERT( newdc );
1161
1162 newdc->w.flags = dc->w.flags | DC_SAVED;
1163 newdc->w.hPen = dc->w.hPen;
1164 newdc->w.hBrush = dc->w.hBrush;
1165 newdc->w.hFont = dc->w.hFont;
1166 newdc->w.hBitmap = dc->w.hBitmap;
1167 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
1168 #if 0
1169 newdc->w.hDevice = dc->w.hDevice;
1170 #endif
1171 newdc->w.hPalette = dc->w.hPalette;
1172 newdc->w.totalExtent = dc->w.totalExtent;
1173 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
1174 newdc->w.ROPmode = dc->w.ROPmode;
1175 newdc->w.polyFillMode = dc->w.polyFillMode;
1176 newdc->w.stretchBltMode = dc->w.stretchBltMode;
1177 newdc->w.relAbsMode = dc->w.relAbsMode;
1178 newdc->w.backgroundMode = dc->w.backgroundMode;
1179 newdc->w.backgroundColor = dc->w.backgroundColor;
1180 newdc->w.textColor = dc->w.textColor;
1181 newdc->w.brushOrgX = dc->w.brushOrgX;
1182 newdc->w.brushOrgY = dc->w.brushOrgY;
1183 newdc->w.textAlign = dc->w.textAlign;
1184 newdc->w.charExtra = dc->w.charExtra;
1185 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
1186 newdc->w.breakCount = dc->w.breakCount;
1187 newdc->w.breakExtra = dc->w.breakExtra;
1188 newdc->w.breakRem = dc->w.breakRem;
1189 newdc->w.MapMode = dc->w.MapMode;
1190 newdc->w.GraphicsMode = dc->w.GraphicsMode;
1191 #if 0
1192 /* Apparently, the DC origin is not changed by [GS]etDCState */
1193 newdc->w.DCOrgX = dc->w.DCOrgX;
1194 newdc->w.DCOrgY = dc->w.DCOrgY;
1195 #endif
1196 newdc->w.CursPosX = dc->w.CursPosX;
1197 newdc->w.CursPosY = dc->w.CursPosY;
1198 newdc->w.ArcDirection = dc->w.ArcDirection;
1199 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
1200 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
1201 newdc->w.xformVport2World = dc->w.xformVport2World;
1202 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
1203 newdc->wndOrgX = dc->wndOrgX;
1204 newdc->wndOrgY = dc->wndOrgY;
1205 newdc->wndExtX = dc->wndExtX;
1206 newdc->wndExtY = dc->wndExtY;
1207 newdc->vportOrgX = dc->vportOrgX;
1208 newdc->vportOrgY = dc->vportOrgY;
1209 newdc->vportExtX = dc->vportExtX;
1210 newdc->vportExtY = dc->vportExtY;
1211
1212 newdc->hSelf = hnewdc;
1213 newdc->saveLevel = 0;
1214 newdc->IsIC = dc->IsIC;
1215
1216 #if 0
1217 PATH_InitGdiPath( &newdc->w.path );
1218 #endif
1219
1220 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1221
1222 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
1223 if (dc->w.hClipRgn)
1224 {
1225 newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1226 NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
1227 }
1228 DC_UnlockDc( hnewdc );
1229 DC_UnlockDc( hDC );
1230 return hnewdc;
1231 }
1232
1233
1234 VOID
1235 STDCALL
1236 NtGdiSetDCState ( HDC hDC, HDC hDCSave )
1237 {
1238 PDC dc, dcs;
1239
1240 dc = DC_LockDc ( hDC );
1241 if ( dc )
1242 {
1243 dcs = DC_LockDc ( hDCSave );
1244 if ( dcs )
1245 {
1246 if ( dcs->w.flags & DC_SAVED )
1247 {
1248 dc->w.flags = dcs->w.flags & ~DC_SAVED;
1249
1250 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
1251
1252 #if 0
1253 dc->w.hDevice = dcs->w.hDevice;
1254 #endif
1255
1256 dc->w.totalExtent = dcs->w.totalExtent;
1257 dc->w.ROPmode = dcs->w.ROPmode;
1258 dc->w.polyFillMode = dcs->w.polyFillMode;
1259 dc->w.stretchBltMode = dcs->w.stretchBltMode;
1260 dc->w.relAbsMode = dcs->w.relAbsMode;
1261 dc->w.backgroundMode = dcs->w.backgroundMode;
1262 dc->w.backgroundColor = dcs->w.backgroundColor;
1263 dc->w.textColor = dcs->w.textColor;
1264 dc->w.brushOrgX = dcs->w.brushOrgX;
1265 dc->w.brushOrgY = dcs->w.brushOrgY;
1266 dc->w.textAlign = dcs->w.textAlign;
1267 dc->w.charExtra = dcs->w.charExtra;
1268 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
1269 dc->w.breakCount = dcs->w.breakCount;
1270 dc->w.breakExtra = dcs->w.breakExtra;
1271 dc->w.breakRem = dcs->w.breakRem;
1272 dc->w.MapMode = dcs->w.MapMode;
1273 dc->w.GraphicsMode = dcs->w.GraphicsMode;
1274 #if 0
1275 /* Apparently, the DC origin is not changed by [GS]etDCState */
1276 dc->w.DCOrgX = dcs->w.DCOrgX;
1277 dc->w.DCOrgY = dcs->w.DCOrgY;
1278 #endif
1279 dc->w.CursPosX = dcs->w.CursPosX;
1280 dc->w.CursPosY = dcs->w.CursPosY;
1281 dc->w.ArcDirection = dcs->w.ArcDirection;
1282
1283 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
1284 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1285 dc->w.xformVport2World = dcs->w.xformVport2World;
1286 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1287
1288 dc->wndOrgX = dcs->wndOrgX;
1289 dc->wndOrgY = dcs->wndOrgY;
1290 dc->wndExtX = dcs->wndExtX;
1291 dc->wndExtY = dcs->wndExtY;
1292 dc->vportOrgX = dcs->vportOrgX;
1293 dc->vportOrgY = dcs->vportOrgY;
1294 dc->vportExtX = dcs->vportExtX;
1295 dc->vportExtY = dcs->vportExtY;
1296
1297 if (!(dc->w.flags & DC_MEMORY))
1298 {
1299 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1300 }
1301
1302 #if 0
1303 if (dcs->w.hClipRgn)
1304 {
1305 if (!dc->w.hClipRgn)
1306 {
1307 dc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1308 }
1309 NtGdiCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1310 }
1311 else
1312 {
1313 if (dc->w.hClipRgn)
1314 {
1315 NtGdiDeleteObject( dc->w.hClipRgn );
1316 }
1317
1318 dc->w.hClipRgn = 0;
1319 }
1320 {
1321 int res;
1322 res = CLIPPING_UpdateGCRegion( dc );
1323 ASSERT ( res != ERROR );
1324 }
1325 DC_UnlockDc ( hDC );
1326 #else
1327 DC_UnlockDc ( hDC );
1328 NtGdiSelectClipRgn(hDC, dcs->w.hClipRgn);
1329 #endif
1330
1331 NtGdiSelectObject( hDC, dcs->w.hBitmap );
1332 NtGdiSelectObject( hDC, dcs->w.hBrush );
1333 NtGdiSelectObject( hDC, dcs->w.hFont );
1334 NtGdiSelectObject( hDC, dcs->w.hPen );
1335 NtGdiSetBkColor( hDC, dcs->w.backgroundColor);
1336 NtGdiSetTextColor( hDC, dcs->w.textColor);
1337
1338 NtGdiSelectPalette( hDC, dcs->w.hPalette, FALSE );
1339
1340 #if 0
1341 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1342 #endif
1343 } else {
1344 DC_UnlockDc(hDC);
1345 }
1346 DC_UnlockDc ( hDCSave );
1347 } else {
1348 DC_UnlockDc ( hDC );
1349 SetLastWin32Error(ERROR_INVALID_HANDLE);
1350 }
1351 }
1352 else
1353 SetLastWin32Error(ERROR_INVALID_HANDLE);
1354 }
1355
1356 INT FASTCALL
1357 IntGdiGetDeviceCaps(PDC dc, INT Index)
1358 {
1359 INT ret;
1360 POINT pt;
1361
1362 /* Retrieve capability */
1363 switch (Index)
1364 {
1365 case DRIVERVERSION:
1366 ret = dc->GDIInfo->ulVersion;
1367 break;
1368
1369 case TECHNOLOGY:
1370 ret = dc->GDIInfo->ulTechnology;
1371 break;
1372
1373 case HORZSIZE:
1374 ret = dc->GDIInfo->ulHorzSize;
1375 break;
1376
1377 case VERTSIZE:
1378 ret = dc->GDIInfo->ulVertSize;
1379 break;
1380
1381 case HORZRES:
1382 ret = dc->GDIInfo->ulHorzRes;
1383 break;
1384
1385 case VERTRES:
1386 ret = dc->GDIInfo->ulVertRes;
1387 break;
1388
1389 case LOGPIXELSX:
1390 ret = dc->GDIInfo->ulLogPixelsX;
1391 break;
1392
1393 case LOGPIXELSY:
1394 ret = dc->GDIInfo->ulLogPixelsY;
1395 break;
1396
1397 case BITSPIXEL:
1398 ret = dc->GDIInfo->cBitsPixel;
1399 break;
1400
1401 case PLANES:
1402 ret = dc->GDIInfo->cPlanes;
1403 break;
1404
1405 case NUMBRUSHES:
1406 UNIMPLEMENTED; /* FIXME */
1407 break;
1408
1409 case NUMPENS:
1410 UNIMPLEMENTED; /* FIXME */
1411 break;
1412
1413 case NUMFONTS:
1414 UNIMPLEMENTED; /* FIXME */
1415 break;
1416
1417 case NUMCOLORS:
1418 ret = dc->GDIInfo->ulNumColors;
1419 break;
1420
1421 case ASPECTX:
1422 ret = dc->GDIInfo->ulAspectX;
1423 break;
1424
1425 case ASPECTY:
1426 ret = dc->GDIInfo->ulAspectY;
1427 break;
1428
1429 case ASPECTXY:
1430 ret = dc->GDIInfo->ulAspectXY;
1431 break;
1432
1433 case PDEVICESIZE:
1434 UNIMPLEMENTED; /* FIXME */
1435 break;
1436
1437 case CLIPCAPS:
1438 UNIMPLEMENTED; /* FIXME */
1439 break;
1440
1441 case SIZEPALETTE:
1442 ret = dc->GDIInfo->ulNumPalReg; /* FIXME not sure */
1443 break;
1444
1445 case NUMRESERVED:
1446 ret = 0;
1447 break;
1448
1449 case COLORRES:
1450 UNIMPLEMENTED; /* FIXME */
1451 break;
1452
1453 case PHYSICALWIDTH:
1454 if(IntGdiEscape(dc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1455 {
1456 ret = pt.x;
1457 }
1458 else
1459 {
1460 ret = 0;
1461 }
1462 break;
1463
1464 case PHYSICALHEIGHT:
1465 if(IntGdiEscape(dc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1466 {
1467 ret = pt.y;
1468 }
1469 else
1470 {
1471 ret = 0;
1472 }
1473 break;
1474
1475 case PHYSICALOFFSETX:
1476 if(IntGdiEscape(dc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1477 {
1478 ret = pt.x;
1479 }
1480 else
1481 {
1482 ret = 0;
1483 }
1484 break;
1485
1486 case PHYSICALOFFSETY:
1487 if(IntGdiEscape(dc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1488 {
1489 ret = pt.y;
1490 }
1491 else
1492 {
1493 ret = 0;
1494 }
1495 break;
1496
1497 case VREFRESH:
1498 UNIMPLEMENTED; /* FIXME */
1499 break;
1500
1501 case SCALINGFACTORX:
1502 if(IntGdiEscape(dc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1503 {
1504 ret = pt.x;
1505 }
1506 else
1507 {
1508 ret = 0;
1509 }
1510 break;
1511
1512 case SCALINGFACTORY:
1513 if(IntGdiEscape(dc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1514 {
1515 ret = pt.y;
1516 }
1517 else
1518 {
1519 ret = 0;
1520 }
1521 break;
1522
1523 case RASTERCAPS:
1524 ret = dc->GDIInfo->flRaster;
1525 break;
1526
1527 case CURVECAPS:
1528 UNIMPLEMENTED; /* FIXME */
1529 break;
1530
1531 case LINECAPS:
1532 UNIMPLEMENTED; /* FIXME */
1533 break;
1534
1535 case POLYGONALCAPS:
1536 UNIMPLEMENTED; /* FIXME */
1537 break;
1538
1539 case TEXTCAPS:
1540 ret = dc->GDIInfo->flTextCaps;
1541 break;
1542
1543 default:
1544 ret = 0;
1545 break;
1546 }
1547
1548 return ret;
1549 }
1550
1551 INT STDCALL
1552 NtGdiGetDeviceCaps(HDC hDC,
1553 INT Index)
1554 {
1555 PDC dc;
1556 INT ret;
1557
1558 dc = DC_LockDc(hDC);
1559 if (dc == NULL)
1560 {
1561 SetLastWin32Error(ERROR_INVALID_HANDLE);
1562 return 0;
1563 }
1564
1565 ret = IntGdiGetDeviceCaps(dc, Index);
1566
1567 DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
1568
1569 DC_UnlockDc( hDC );
1570 return ret;
1571 }
1572
1573 DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
1574 DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
1575
1576 INT FASTCALL
1577 IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
1578 {
1579 PVOID GdiObject;
1580 INT Result = 0;
1581 DWORD ObjectType;
1582
1583 GdiObject = GDIOBJ_LockObj(Handle, GDI_OBJECT_TYPE_DONTCARE);
1584 if (NULL == GdiObject)
1585 {
1586 SetLastWin32Error(ERROR_INVALID_HANDLE);
1587 return 0;
1588 }
1589
1590 ObjectType = GDIOBJ_GetObjectType(Handle);
1591 switch (ObjectType)
1592 {
1593 #if 0
1594 case GDI_OBJECT_TYPE_PEN:
1595 Result = PEN_GetObject((PENOBJ *) GdiObject, Count, Buffer);
1596 break;
1597 case GDI_OBJECT_TYPE_BRUSH:
1598 Result = BRUSH_GetObject((BRUSHOBJ *) GdiObject, Count, Buffer);
1599 break;
1600 #endif
1601 case GDI_OBJECT_TYPE_BITMAP:
1602 Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer);
1603 break;
1604 case GDI_OBJECT_TYPE_FONT:
1605 Result = FontGetObject((PTEXTOBJ) GdiObject, Count, Buffer);
1606 #if 0
1607 // Fix the LOGFONT structure for the stock fonts
1608 if (FIRST_STOCK_HANDLE <= Handle && Handle <= LAST_STOCK_HANDLE)
1609 {
1610 FixStockFontSizeW(Handle, Count, Buffer);
1611 }
1612 #endif
1613 break;
1614 #if 0
1615 case GDI_OBJECT_TYPE_PALETTE:
1616 Result = PALETTE_GetObject((PALETTEOBJ *) GdiObject, Count, Buffer);
1617 break;
1618 #endif
1619 default:
1620 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType);
1621 break;
1622 }
1623
1624 GDIOBJ_UnlockObj(Handle);
1625
1626 return Result;
1627 }
1628
1629 INT STDCALL
1630 NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
1631 {
1632 INT Ret;
1633 LPVOID SafeBuf;
1634 NTSTATUS Status;
1635
1636 if (count <= 0)
1637 {
1638 return 0;
1639 }
1640
1641 SafeBuf = ExAllocatePoolWithTag(PagedPool, count, TAG_GDIOBJ);
1642 if(!SafeBuf)
1643 {
1644 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1645 return 0;
1646 }
1647
1648 Ret = IntGdiGetObject(handle, count, SafeBuf);
1649
1650 Status = MmCopyToCaller(buffer, SafeBuf, count);
1651 ExFreePool(SafeBuf);
1652 if(!NT_SUCCESS(Status))
1653 {
1654 SetLastNtError(Status);
1655 return 0;
1656 }
1657
1658 return Ret;
1659 }
1660
1661 DWORD STDCALL
1662 NtGdiGetObjectType(HANDLE handle)
1663 {
1664 GDIOBJHDR * ptr;
1665 INT result;
1666 DWORD objectType;
1667
1668 ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1669 if (ptr == 0)
1670 {
1671 SetLastWin32Error(ERROR_INVALID_HANDLE);
1672 return 0;
1673 }
1674
1675 objectType = GDIOBJ_GetObjectType(handle);
1676 switch(objectType)
1677 {
1678 case GDI_OBJECT_TYPE_PEN:
1679 result = OBJ_PEN;
1680 break;
1681 case GDI_OBJECT_TYPE_BRUSH:
1682 result = OBJ_BRUSH;
1683 break;
1684 case GDI_OBJECT_TYPE_BITMAP:
1685 result = OBJ_BITMAP;
1686 break;
1687 case GDI_OBJECT_TYPE_FONT:
1688 result = OBJ_FONT;
1689 break;
1690 case GDI_OBJECT_TYPE_PALETTE:
1691 result = OBJ_PAL;
1692 break;
1693 case GDI_OBJECT_TYPE_REGION:
1694 result = OBJ_REGION;
1695 break;
1696 case GDI_OBJECT_TYPE_DC:
1697 result = OBJ_DC;
1698 break;
1699 case GDI_OBJECT_TYPE_METADC:
1700 result = OBJ_METADC;
1701 break;
1702 case GDI_OBJECT_TYPE_METAFILE:
1703 result = OBJ_METAFILE;
1704 break;
1705 case GDI_OBJECT_TYPE_ENHMETAFILE:
1706 result = OBJ_ENHMETAFILE;
1707 break;
1708 case GDI_OBJECT_TYPE_ENHMETADC:
1709 result = OBJ_ENHMETADC;
1710 break;
1711 case GDI_OBJECT_TYPE_EXTPEN:
1712 result = OBJ_EXTPEN;
1713 break;
1714 case GDI_OBJECT_TYPE_MEMDC:
1715 result = OBJ_MEMDC;
1716 break;
1717
1718 default:
1719 DPRINT1("Magic 0x%08x not implemented\n", objectType);
1720 result = 0;
1721 break;
1722 }
1723 GDIOBJ_UnlockObj(handle);
1724 return result;
1725 }
1726
1727 DC_GET_VAL( INT, NtGdiGetRelAbs, w.relAbsMode )
1728 DC_GET_VAL( INT, NtGdiGetROP2, w.ROPmode )
1729 DC_GET_VAL( INT, NtGdiGetStretchBltMode, w.stretchBltMode )
1730 DC_GET_VAL( UINT, NtGdiGetTextAlign, w.textAlign )
1731 DC_GET_VAL( COLORREF, NtGdiGetTextColor, w.textColor )
1732 DC_GET_VAL_EX( GetViewportExtEx, vportExtX, vportExtY, SIZE, cx, cy )
1733 DC_GET_VAL_EX( GetViewportOrgEx, vportOrgX, vportOrgY, POINT, x, y )
1734 DC_GET_VAL_EX( GetWindowExtEx, wndExtX, wndExtY, SIZE, cx, cy )
1735 DC_GET_VAL_EX( GetWindowOrgEx, wndOrgX, wndOrgY, POINT, x, y )
1736
1737 HDC STDCALL
1738 NtGdiResetDC(HDC hDC, CONST DEVMODEW *InitData)
1739 {
1740 UNIMPLEMENTED;
1741 return 0;
1742 }
1743
1744 BOOL STDCALL
1745 NtGdiRestoreDC(HDC hDC, INT SaveLevel)
1746 {
1747 PDC dc, dcs;
1748 BOOL success;
1749
1750 DPRINT("NtGdiRestoreDC(%lx, %d)\n", hDC, SaveLevel);
1751
1752 dc = DC_LockDc(hDC);
1753 if (!dc)
1754 {
1755 SetLastWin32Error(ERROR_INVALID_HANDLE);
1756 return FALSE;
1757 }
1758
1759 if (SaveLevel == -1)
1760 SaveLevel = dc->saveLevel;
1761
1762 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
1763 {
1764 DC_UnlockDc(hDC);
1765 return FALSE;
1766 }
1767
1768 success = TRUE;
1769 while (dc->saveLevel >= SaveLevel)
1770 {
1771 HDC hdcs = DC_GetNextDC (dc);
1772
1773 dcs = DC_LockDc (hdcs);
1774 if (dcs == NULL)
1775 {
1776 DC_UnlockDc(hDC);
1777 return FALSE;
1778 }
1779 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
1780 if (--dc->saveLevel < SaveLevel)
1781 {
1782 DC_UnlockDc( hDC );
1783 DC_UnlockDc( hdcs );
1784 NtGdiSetDCState(hDC, hdcs);
1785 #if 0
1786 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
1787 {
1788 /* FIXME: This might not be quite right, since we're
1789 * returning FALSE but still destroying the saved DC state */
1790 success = FALSE;
1791 }
1792 #endif
1793 dc = DC_LockDc(hDC);
1794 if(!dc)
1795 {
1796 return FALSE;
1797 }
1798 }
1799 else
1800 {
1801 DC_UnlockDc( hdcs );
1802 }
1803 NtGdiDeleteDC (hdcs);
1804 }
1805 DC_UnlockDc( hDC );
1806 return success;
1807 }
1808
1809 INT STDCALL
1810 NtGdiSaveDC(HDC hDC)
1811 {
1812 HDC hdcs;
1813 PDC dc, dcs;
1814 INT ret;
1815
1816 DPRINT("NtGdiSaveDC(%lx)\n", hDC);
1817
1818 if (!(hdcs = NtGdiGetDCState(hDC)))
1819 {
1820 return 0;
1821 }
1822
1823 dcs = DC_LockDc (hdcs);
1824 if (dcs == NULL)
1825 {
1826 SetLastWin32Error(ERROR_INVALID_HANDLE);
1827 return 0;
1828 }
1829 dc = DC_LockDc (hDC);
1830 if (dc == NULL)
1831 {
1832 DC_UnlockDc(hdcs);
1833 SetLastWin32Error(ERROR_INVALID_HANDLE);
1834 return 0;
1835 }
1836
1837 #if 0
1838 /* Copy path. The reason why path saving / restoring is in SaveDC/
1839 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1840 * functions are only in Win16 (which doesn't have paths) and that
1841 * SetDCState doesn't allow us to signal an error (which can happen
1842 * when copying paths).
1843 */
1844 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1845 {
1846 NtGdiDeleteDC (hdcs);
1847 return 0;
1848 }
1849 #endif
1850
1851 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1852 DC_SetNextDC (dc, hdcs);
1853 ret = ++dc->saveLevel;
1854 DC_UnlockDc( hdcs );
1855 DC_UnlockDc( hDC );
1856
1857 return ret;
1858 }
1859
1860 HGDIOBJ
1861 STDCALL
1862 NtGdiSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1863 {
1864 HGDIOBJ objOrg = NULL; // default to failure
1865 BITMAPOBJ *pb;
1866 PDC dc;
1867 PGDIBRUSHOBJ pen;
1868 PGDIBRUSHOBJ brush;
1869 XLATEOBJ *XlateObj;
1870 DWORD objectType;
1871 HRGN hVisRgn;
1872 BOOLEAN Failed;
1873
1874 if(!hDC || !hGDIObj) return NULL;
1875
1876 dc = DC_LockDc(hDC);
1877 if (NULL == dc)
1878 {
1879 SetLastWin32Error(ERROR_INVALID_HANDLE);
1880 return NULL;
1881 }
1882
1883 objectType = GDIOBJ_GetObjectType(hGDIObj);
1884
1885 switch (objectType)
1886 {
1887 case GDI_OBJECT_TYPE_PEN:
1888 pen = PENOBJ_LockPen((HPEN) hGDIObj);
1889 if (pen == NULL)
1890 {
1891 SetLastWin32Error(ERROR_INVALID_HANDLE);
1892 break;
1893 }
1894
1895 XlateObj = IntGdiCreateBrushXlate(dc, pen, &Failed);
1896 PENOBJ_UnlockPen(hGDIObj);
1897 if (Failed)
1898 {
1899 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1900 break;
1901 }
1902
1903 objOrg = (HGDIOBJ)dc->w.hPen;
1904 dc->w.hPen = hGDIObj;
1905 if (dc->XlatePen != NULL)
1906 EngDeleteXlate(dc->XlatePen);
1907 dc->XlatePen = XlateObj;
1908 break;
1909
1910 case GDI_OBJECT_TYPE_BRUSH:
1911 brush = BRUSHOBJ_LockBrush((HPEN) hGDIObj);
1912 if (brush == NULL)
1913 {
1914 SetLastWin32Error(ERROR_INVALID_HANDLE);
1915 break;
1916 }
1917
1918 XlateObj = IntGdiCreateBrushXlate(dc, brush, &Failed);
1919 BRUSHOBJ_UnlockBrush(hGDIObj);
1920 if (Failed)
1921 {
1922 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1923 break;
1924 }
1925
1926 objOrg = (HGDIOBJ)dc->w.hBrush;
1927 dc->w.hBrush = hGDIObj;
1928 if (dc->XlateBrush != NULL)
1929 EngDeleteXlate(dc->XlateBrush);
1930 dc->XlateBrush = XlateObj;
1931 break;
1932
1933 case GDI_OBJECT_TYPE_FONT:
1934 if(NT_SUCCESS(TextIntRealizeFont((HFONT)hGDIObj)))
1935 {
1936 objOrg = (HGDIOBJ)dc->w.hFont;
1937 dc->w.hFont = (HFONT) hGDIObj;
1938 }
1939 break;
1940
1941 case GDI_OBJECT_TYPE_BITMAP:
1942 // must be memory dc to select bitmap
1943 if (!(dc->w.flags & DC_MEMORY))
1944 {
1945 DC_UnlockDc(hDC);
1946 return NULL;
1947 }
1948 pb = BITMAPOBJ_LockBitmap(hGDIObj);
1949 if (NULL == pb)
1950 {
1951 SetLastWin32Error(ERROR_INVALID_HANDLE);
1952 DC_UnlockDc(hDC);
1953 return NULL;
1954 }
1955 objOrg = (HGDIOBJ)dc->w.hBitmap;
1956
1957 /* Release the old bitmap, lock the new one and convert it to a SURF */
1958 dc->w.hBitmap = hGDIObj;
1959
1960 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1961 if(pb->dib)
1962 {
1963 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1964 dc->w.hPalette = pb->hDIBPalette;
1965 }
1966 else
1967 {
1968 dc->w.bitsPerPixel = BitsPerFormat(pb->SurfObj.iBitmapFormat);
1969 dc->w.hPalette = dc->DevInfo->hpalDefault;
1970 }
1971
1972 /* Reselect brush and pen to regenerate the XLATEOBJs. */
1973 NtGdiSelectObject ( hDC, dc->w.hBrush );
1974 NtGdiSelectObject ( hDC, dc->w.hPen );
1975
1976 DC_UnlockDc ( hDC );
1977 hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->SurfObj.sizlBitmap.cx, pb->SurfObj.sizlBitmap.cy );
1978 BITMAPOBJ_UnlockBitmap( hGDIObj );
1979 NtGdiSelectVisRgn ( hDC, hVisRgn );
1980 NtGdiDeleteObject ( hVisRgn );
1981
1982 return objOrg;
1983
1984 case GDI_OBJECT_TYPE_REGION:
1985 DC_UnlockDc (hDC);
1986 /*
1987 * The return value is one of the following values:
1988 * SIMPLEREGION
1989 * COMPLEXREGION
1990 * NULLREGION
1991 */
1992 return (HGDIOBJ) NtGdiSelectClipRgn(hDC, (HRGN) hGDIObj);
1993
1994 default:
1995 break;
1996 }
1997 DC_UnlockDc( hDC );
1998 return objOrg;
1999 }
2000
2001 WORD STDCALL
2002 NtGdiSetHookFlags(HDC hDC, WORD Flags)
2003 {
2004 WORD wRet;
2005 DC *dc = DC_LockDc(hDC);
2006
2007 if (NULL == dc)
2008 {
2009 SetLastWin32Error(ERROR_INVALID_HANDLE);
2010 return 0;
2011 }
2012
2013 wRet = dc->w.flags & DC_DIRTY;
2014
2015 /* "Undocumented Windows" info is slightly confusing.
2016 */
2017
2018 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
2019
2020 if (Flags & DCHF_INVALIDATEVISRGN)
2021 {
2022 dc->w.flags |= DC_DIRTY;
2023 }
2024 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
2025 {
2026 dc->w.flags &= ~DC_DIRTY;
2027 }
2028
2029 DC_UnlockDc(hDC);
2030
2031 return wRet;
2032 }
2033
2034 DC_SET_MODE( NtGdiSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
2035 DC_SET_MODE( NtGdiSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
2036 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
2037 DC_SET_MODE( NtGdiSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
2038 DC_SET_MODE( NtGdiSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
2039
2040 // ---------------------------------------------------- Private Interface
2041
2042 HDC FASTCALL
2043 DC_AllocDC(PUNICODE_STRING Driver)
2044 {
2045 PDC NewDC;
2046 HDC hDC;
2047 PWSTR Buf = NULL;
2048
2049 if (Driver != NULL)
2050 {
2051 Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
2052 if(!Buf)
2053 {
2054 return NULL;
2055 }
2056 RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
2057 }
2058
2059 hDC = (HDC) GDIOBJ_AllocObj(GDI_OBJECT_TYPE_DC);
2060 if (hDC == NULL)
2061 {
2062 if(Buf)
2063 {
2064 ExFreePool(Buf);
2065 }
2066 return NULL;
2067 }
2068
2069 NewDC = DC_LockDc(hDC);
2070 /* FIXME - Handle NewDC == NULL! */
2071
2072 if (Driver != NULL)
2073 {
2074 RtlCopyMemory(&NewDC->DriverName, Driver, sizeof(UNICODE_STRING));
2075 NewDC->DriverName.Buffer = Buf;
2076 }
2077
2078 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
2079 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
2080 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
2081 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
2082 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
2083 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
2084 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
2085 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
2086 NewDC->w.vport2WorldValid = TRUE;
2087 NewDC->w.MapMode = MM_TEXT;
2088 NewDC->wndExtX = 1.0f;
2089 NewDC->wndExtY = 1.0f;
2090 NewDC->vportExtX = 1.0f;
2091 NewDC->vportExtY = 1.0f;
2092 NewDC->w.textColor = 0;
2093 NewDC->w.backgroundColor = 0xffffff;
2094
2095 NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
2096 TextIntRealizeFont(NewDC->w.hFont);
2097
2098 NewDC->w.hPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
2099
2100 DC_UnlockDc(hDC);
2101
2102 return hDC;
2103 }
2104
2105 HDC FASTCALL
2106 DC_FindOpenDC(PUNICODE_STRING Driver)
2107 {
2108 return NULL;
2109 }
2110
2111 /*!
2112 * Initialize some common fields in the Device Context structure.
2113 */
2114 VOID FASTCALL
2115 DC_InitDC(HDC DCHandle)
2116 {
2117 // NtGdiRealizeDefaultPalette(DCHandle);
2118
2119 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
2120 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
2121 //NtGdiSelectObject(DCHandle, hFont);
2122
2123 /*
2124 {
2125 int res;
2126 res = CLIPPING_UpdateGCRegion(DCToInit);
2127 ASSERT ( res != ERROR );
2128 }
2129 */
2130 }
2131
2132 VOID FASTCALL
2133 DC_FreeDC(HDC DCToFree)
2134 {
2135 if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC))
2136 {
2137 DPRINT("DC_FreeDC failed\n");
2138 }
2139 }
2140
2141 BOOL INTERNAL_CALL
2142 DC_Cleanup(PVOID ObjectBody)
2143 {
2144 PDC pDC = (PDC)ObjectBody;
2145 RtlFreeUnicodeString(&pDC->DriverName);
2146 return TRUE;
2147 }
2148
2149 HDC FASTCALL
2150 DC_GetNextDC (PDC pDC)
2151 {
2152 return pDC->hNext;
2153 }
2154
2155 VOID FASTCALL
2156 DC_SetNextDC (PDC pDC, HDC hNextDC)
2157 {
2158 pDC->hNext = hNextDC;
2159 }
2160
2161 VOID FASTCALL
2162 DC_UpdateXforms(PDC dc)
2163 {
2164 XFORM xformWnd2Vport;
2165 FLOAT scaleX, scaleY;
2166
2167 /* Construct a transformation to do the window-to-viewport conversion */
2168 scaleX = (dc->wndExtX ? (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX : 0.0f);
2169 scaleY = (dc->wndExtY ? (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY : 0.0f);
2170 xformWnd2Vport.eM11 = scaleX;
2171 xformWnd2Vport.eM12 = 0.0;
2172 xformWnd2Vport.eM21 = 0.0;
2173 xformWnd2Vport.eM22 = scaleY;
2174 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
2175 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
2176
2177 /* Combine with the world transformation */
2178 IntGdiCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
2179
2180 /* Create inverse of world-to-viewport transformation */
2181 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
2182 }
2183
2184 BOOL FASTCALL
2185 DC_InvertXform(const XFORM *xformSrc,
2186 XFORM *xformDest)
2187 {
2188 FLOAT determinant;
2189
2190 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
2191 if (determinant > -1e-12 && determinant < 1e-12)
2192 {
2193 return FALSE;
2194 }
2195
2196 xformDest->eM11 = xformSrc->eM22 / determinant;
2197 xformDest->eM12 = -xformSrc->eM12 / determinant;
2198 xformDest->eM21 = -xformSrc->eM21 / determinant;
2199 xformDest->eM22 = xformSrc->eM11 / determinant;
2200 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
2201 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
2202
2203 return TRUE;
2204 }
2205
2206 VOID FASTCALL
2207 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
2208 {
2209 PDC DC;
2210
2211 GDIOBJ_SetOwnership(hDC, Owner);
2212 DC = DC_LockDc(hDC);
2213 if (NULL != DC)
2214 {
2215 if (NULL != DC->w.hClipRgn)
2216 {
2217 GDIOBJ_CopyOwnership(hDC, DC->w.hClipRgn);
2218 }
2219 if (NULL != DC->w.hVisRgn)
2220 {
2221 GDIOBJ_CopyOwnership(hDC, DC->w.hVisRgn);
2222 }
2223 if (NULL != DC->w.hGCClipRgn)
2224 {
2225 GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
2226 }
2227 DC_UnlockDc(hDC);
2228 }
2229 }
2230
2231 BOOL FASTCALL
2232 IntIsPrimarySurface(SURFOBJ *SurfObj)
2233 {
2234 if (PrimarySurface.Handle == NULL)
2235 {
2236 return FALSE;
2237 }
2238 return SurfObj->hsurf == PrimarySurface.Handle;
2239 }
2240
2241 /*
2242 * Returns the color of the brush or pen that is currently selected into the DC.
2243 * This function is called from GetDCBrushColor() and GetDCPenColor()
2244 */
2245 COLORREF FASTCALL
2246 IntGetDCColor(HDC hDC, ULONG Object)
2247 {
2248 /*
2249 * The previous implementation was completly incorrect. It modified the
2250 * brush that was currently selected into the device context, but in fact
2251 * the DC pen/brush color should be stored directly in the device context
2252 * (at address 0x2C of the user mode DC object memory on Windows 2K/XP).
2253 * The actual color is then used when DC_BRUSH/DC_PEN object is selected
2254 * into the device context and BRUSHOBJ for drawing is composed (belongs
2255 * to IntGdiInitBrushInstance in the current ReactOS implementation). Also
2256 * the implementation should be moved to user mode GDI32.dll when UM
2257 * mapped GDI objects will be implemented.
2258 */
2259
2260 DPRINT("WIN32K:IntGetDCColor is unimplemented\n");
2261 return 0xFFFFFF; /* The default DC color. */
2262 }
2263
2264 /*
2265 * Changes the color of the brush or pen that is currently selected into the DC.
2266 * This function is called from SetDCBrushColor() and SetDCPenColor()
2267 */
2268 COLORREF FASTCALL
2269 IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color)
2270 {
2271 /* See the comment in IntGetDCColor. */
2272
2273 DPRINT("WIN32K:IntSetDCColor is unimplemented\n");
2274 return CLR_INVALID;
2275 }
2276
2277 #define SIZEOF_DEVMODEW_300 188
2278 #define SIZEOF_DEVMODEW_400 212
2279 #define SIZEOF_DEVMODEW_500 220
2280
2281 /*! \brief Enumerate possible display settings for the given display...
2282 *
2283 * \todo Make thread safe!?
2284 * \todo Don't ignore pDeviceName
2285 * \todo Implement non-raw mode (only return settings valid for driver and monitor)
2286 */
2287 BOOL FASTCALL
2288 IntEnumDisplaySettings(
2289 IN PUNICODE_STRING pDeviceName OPTIONAL,
2290 IN DWORD iModeNum,
2291 IN OUT LPDEVMODEW pDevMode,
2292 IN DWORD dwFlags)
2293 {
2294 static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
2295 static DWORD SizeOfCachedDevModes = 0;
2296 PDEVMODEW CachedMode = NULL;
2297 DEVMODEW DevMode;
2298 INT Size, OldSize;
2299 ULONG DisplayNumber = 0; /* only default display supported */
2300
2301 DPRINT1("DevMode->dmSize = %d\n", pDevMode->dmSize);
2302 DPRINT1("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
2303 if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
2304 pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
2305 pDevMode->dmSize != SIZEOF_DEVMODEW_500)
2306 {
2307 SetLastWin32Error(STATUS_INVALID_PARAMETER);
2308 return FALSE;
2309 }
2310
2311 if (iModeNum == ENUM_CURRENT_SETTINGS)
2312 {
2313 CachedMode = &PrimarySurface.DMW;
2314 ASSERT(CachedMode->dmSize > 0);
2315 }
2316 else if (iModeNum == ENUM_REGISTRY_SETTINGS)
2317 {
2318 RtlZeroMemory(&DevMode, sizeof (DevMode));
2319 DevMode.dmSize = sizeof (DevMode);
2320 DevMode.dmDriverExtra = 0;
2321 if (SetupDevMode(&DevMode, DisplayNumber))
2322 CachedMode = &DevMode;
2323 else
2324 {
2325 SetLastWin32Error(0); /* FIXME: use error code */
2326 return FALSE;
2327 }
2328 /* FIXME: Maybe look for the matching devmode supplied by the
2329 * driver so we can provide driver private/extra data?
2330 */
2331 }
2332 else
2333 {
2334 if (iModeNum == 0 || CachedDevModes == NULL) /* query modes from drivers */
2335 {
2336 BOOL PrimarySurfaceCreated = FALSE;
2337 UNICODE_STRING DriverFileNames;
2338 LPWSTR CurrentName;
2339 DRVENABLEDATA DrvEnableData;
2340
2341 /* Retrieve DDI driver names from registry */
2342 RtlInitUnicodeString(&DriverFileNames, NULL);
2343 if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
2344 {
2345 DPRINT1("FindDriverFileNames failed\n");
2346 return FALSE;
2347 }
2348
2349 if (!HalQueryDisplayOwnership())
2350 {
2351 IntCreatePrimarySurface();
2352 PrimarySurfaceCreated = TRUE;
2353 }
2354
2355 /*
2356 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
2357 * scan all of them until a good one found.
2358 */
2359 CurrentName = DriverFileNames.Buffer;
2360 for (;CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR));
2361 CurrentName += wcslen(CurrentName) + 1)
2362 {
2363 INT i;
2364 PGD_ENABLEDRIVER GDEnableDriver;
2365
2366 /* Get the DDI driver's entry point */
2367 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
2368 if (NULL == GDEnableDriver)
2369 {
2370 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
2371 continue;
2372 }
2373
2374 /* Call DDI driver's EnableDriver function */
2375 RtlZeroMemory(&DrvEnableData, sizeof (DrvEnableData));
2376
2377 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData), &DrvEnableData))
2378 {
2379 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
2380 continue;
2381 }
2382
2383 CachedDevModesEnd = CachedDevModes;
2384
2385 /* find DrvGetModes function */
2386 for (i = 0; i < DrvEnableData.c; i++)
2387 {
2388 PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
2389 PGD_GETMODES GetModes;
2390 INT SizeNeeded, SizeUsed;
2391
2392 if (DrvFn->iFunc != INDEX_DrvGetModes)
2393 continue;
2394
2395 GetModes = (PGD_GETMODES)DrvFn->pfn;
2396
2397 /* make sure we have enough memory to hold the modes */
2398 SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
2399 if (SizeNeeded <= 0)
2400 {
2401 DPRINT("DrvGetModes failed for %S\n", CurrentName);
2402 break;
2403 }
2404
2405 SizeUsed = CachedDevModesEnd - CachedDevModes;
2406 if (SizeOfCachedDevModes - SizeUsed < SizeNeeded)
2407 {
2408 PVOID NewBuffer;
2409
2410 SizeOfCachedDevModes += SizeNeeded;
2411 NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes);
2412 if (NewBuffer == NULL)
2413 {
2414 /* clean up */
2415 ExFreePool(CachedDevModes);
2416 SizeOfCachedDevModes = 0;
2417 CachedDevModes = NULL;
2418 CachedDevModesEnd = NULL;
2419 if (PrimarySurfaceCreated)
2420 {
2421 IntDestroyPrimarySurface();
2422 }
2423 SetLastWin32Error(STATUS_NO_MEMORY);
2424 return FALSE;
2425 }
2426 if (CachedDevModes != NULL)
2427 {
2428 RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed);
2429 ExFreePool(CachedDevModes);
2430 }
2431 CachedDevModes = NewBuffer;
2432 CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
2433 }
2434
2435 /* query modes */
2436 SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
2437 SizeOfCachedDevModes - SizeUsed,
2438 CachedDevModesEnd);
2439 if (SizeNeeded <= 0)
2440 {
2441 DPRINT("DrvGetModes failed for %S\n", CurrentName);
2442 }
2443 else
2444 {
2445 CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded);
2446 }
2447 break;
2448 }
2449 }
2450
2451 if (PrimarySurfaceCreated)
2452 {
2453 IntDestroyPrimarySurface();
2454 }
2455
2456 RtlFreeUnicodeString(&DriverFileNames);
2457 }
2458
2459 /* return cached info */
2460 CachedMode = CachedDevModes;
2461 if (CachedMode >= CachedDevModesEnd)
2462 {
2463 SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
2464 return FALSE;
2465 }
2466 while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
2467 {
2468 assert(CachedMode->dmSize > 0);
2469 CachedMode = (DEVMODEW *)((PCHAR)CachedMode + CachedMode->dmSize + CachedMode->dmDriverExtra);
2470 }
2471 if (CachedMode >= CachedDevModesEnd)
2472 {
2473 SetLastWin32Error(STATUS_NO_MORE_ENTRIES);
2474 return FALSE;
2475 }
2476 }
2477
2478 ASSERT(CachedMode != NULL);
2479
2480 Size = OldSize = pDevMode->dmSize;
2481 if (Size > CachedMode->dmSize)
2482 Size = CachedMode->dmSize;
2483 RtlCopyMemory(pDevMode, CachedMode, Size);
2484 RtlZeroMemory((PCHAR)pDevMode + Size, OldSize - Size);
2485 pDevMode->dmSize = OldSize;
2486
2487 Size = OldSize = pDevMode->dmDriverExtra;
2488 if (Size > CachedMode->dmDriverExtra)
2489 Size = CachedMode->dmDriverExtra;
2490 RtlCopyMemory((PCHAR)pDevMode + pDevMode->dmSize,
2491 (PCHAR)CachedMode + CachedMode->dmSize, Size);
2492 RtlZeroMemory((PCHAR)pDevMode + pDevMode->dmSize + Size, OldSize - Size);
2493 pDevMode->dmDriverExtra = OldSize;
2494
2495 return TRUE;
2496 }
2497 LONG
2498 FASTCALL
2499 IntChangeDisplaySettings(
2500 IN PUNICODE_STRING pDeviceName OPTIONAL,
2501 IN LPDEVMODEW DevMode,
2502 IN DWORD dwflags,
2503 IN PVOID lParam OPTIONAL)
2504 {
2505 BOOLEAN Global = FALSE;
2506 BOOLEAN NoReset = FALSE;
2507 BOOLEAN Reset = FALSE;
2508 BOOLEAN SetPrimary = FALSE;
2509 LONG Ret;
2510
2511 DPRINT1("display flag : %x\n",dwflags);
2512
2513 if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
2514 {
2515 /* Check global, reset and noreset flags */
2516 if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
2517 Global = TRUE;
2518 if ((dwflags & CDS_NORESET) == CDS_NORESET)
2519 NoReset = TRUE;
2520 dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
2521 }
2522 if ((dwflags & CDS_RESET) == CDS_RESET)
2523 Reset = TRUE;
2524 if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
2525 SetPrimary = TRUE;
2526 dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
2527
2528 if (Reset && NoReset)
2529 return DISP_CHANGE_BADFLAGS;
2530
2531 if (dwflags == 0)
2532 {
2533 /* Dynamically change graphics mode */
2534 DPRINT1("flag 0 UNIMPLEMENT \n");
2535 return DISP_CHANGE_FAILED;
2536 }
2537
2538 if ((dwflags & CDS_TEST) == CDS_TEST)
2539 {
2540 /* Test reslution */
2541 dwflags &= ~CDS_TEST;
2542 DPRINT1("flag CDS_TEST UNIMPLEMENT");
2543 Ret = DISP_CHANGE_FAILED;
2544 }
2545
2546 if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
2547 {
2548 /* Full Screen */
2549 dwflags &= ~CDS_FULLSCREEN;
2550 DPRINT1("flag CDS_FULLSCREEN UNIMPLEMENT");
2551 Ret = DISP_CHANGE_FAILED;
2552 }
2553
2554 if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
2555 {
2556 dwflags &= ~CDS_VIDEOPARAMETERS;
2557 if (lParam == NULL) Ret=DISP_CHANGE_BADPARAM;
2558 else
2559 {
2560 DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENT");
2561 Ret = DISP_CHANGE_FAILED;
2562 }
2563
2564 }
2565
2566 if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
2567 {
2568
2569 UNICODE_STRING ObjectName;
2570 UNICODE_STRING KernelModeName;
2571 WCHAR KernelModeNameBuffer[256];
2572 UNICODE_STRING RegistryKey;
2573 WCHAR RegistryKeyBuffer[512];
2574 PDEVICE_OBJECT DeviceObject;
2575 NTSTATUS Status;
2576 ULONG LastSlash;
2577 OBJECT_ATTRIBUTES ObjectAttributes;
2578 HANDLE DevInstRegKey;
2579 ULONG NewValue;
2580
2581
2582 DPRINT1("set CDS_UPDATEREGISTRY \n");
2583
2584 dwflags &= ~CDS_UPDATEREGISTRY;
2585
2586 /* Get device name (pDeviceName is "\.\xxx") */
2587 for (LastSlash = pDeviceName->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
2588 {
2589 if (pDeviceName->Buffer[LastSlash - 1] == L'\\')
2590 break;
2591 }
2592
2593 if (LastSlash == 0) return DISP_CHANGE_RESTART;
2594 ObjectName = *pDeviceName;
2595 ObjectName.Length -= LastSlash * sizeof(WCHAR);
2596 ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
2597 ObjectName.Buffer += LastSlash;
2598
2599 KernelModeName.Length = 0;
2600 KernelModeName.MaximumLength = sizeof(KernelModeNameBuffer);
2601 KernelModeName.Buffer = KernelModeNameBuffer;
2602
2603 /* Open \??\xxx (ex: "\??\DISPLAY1") */
2604 Status = RtlAppendUnicodeToString(&KernelModeName, L"\\??\\");
2605
2606 if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
2607 Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
2608
2609 if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
2610 Status = ObReferenceObjectByName(
2611 &KernelModeName,
2612 OBJ_CASE_INSENSITIVE,
2613 NULL,
2614 0,
2615 IoDeviceObjectType,
2616 KernelMode,
2617 NULL,
2618 (PVOID*)&DeviceObject);
2619
2620 if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
2621 /* Get associated driver name (ex: "VBE") */
2622 for (LastSlash = DeviceObject->DriverObject->DriverName.Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
2623 {
2624 if (DeviceObject->DriverObject->DriverName.Buffer[LastSlash - 1] == L'\\')
2625 break;
2626 }
2627
2628 if (LastSlash == 0) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
2629 ObjectName = DeviceObject->DriverObject->DriverName;
2630 ObjectName.Length -= LastSlash * sizeof(WCHAR);
2631 ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
2632 ObjectName.Buffer += LastSlash;
2633
2634 RegistryKey.Length = 0;
2635 RegistryKey.MaximumLength = sizeof(RegistryKeyBuffer);
2636 RegistryKey.Buffer = RegistryKeyBuffer;
2637
2638 /* Open registry key */
2639 Status = RtlAppendUnicodeToString(&RegistryKey,
2640 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\");
2641
2642 if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
2643 Status = RtlAppendUnicodeStringToString(&RegistryKey, &ObjectName);
2644
2645 if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
2646 Status = RtlAppendUnicodeToString(&RegistryKey,
2647 L"\\Device0");
2648
2649 if (!NT_SUCCESS(Status)) { ObDereferenceObject(DeviceObject); return DISP_CHANGE_FAILED; }
2650
2651 InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
2652 OBJ_CASE_INSENSITIVE, NULL, NULL);
2653 Status = ZwOpenKey(&DevInstRegKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes);
2654 ObDereferenceObject(DeviceObject);
2655 if (!NT_SUCCESS(Status)) return DISP_CHANGE_FAILED;
2656
2657 /* Update needed fields */
2658 if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
2659 {
2660 RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel");
2661 NewValue = DevMode->dmBitsPerPel;
2662 Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
2663 }
2664
2665 if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
2666 {
2667 RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution");
2668 NewValue = DevMode->dmPelsWidth;
2669 Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
2670 }
2671
2672 if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
2673 {
2674 RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution");
2675 NewValue = DevMode->dmPelsHeight;
2676 Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
2677 }
2678
2679 ZwClose(DevInstRegKey);
2680 if (NT_SUCCESS(Status))
2681 Ret = DISP_CHANGE_RESTART;
2682 else
2683 /* return DISP_CHANGE_NOTUPDATED when we can save to reg only vaild for NT */
2684 Ret = DISP_CHANGE_NOTUPDATED;
2685
2686 }
2687
2688 if (dwflags != 0)
2689 Ret = DISP_CHANGE_BADFLAGS;
2690
2691 return Ret;
2692 }
2693
2694 /* EOF */