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