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