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