Implement GetObjectA/W() for fonts
[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.125 2004/03/23 19:46:50 gvg Exp $
20 *
21 * DC.C - Device context functions
22 *
23 */
24
25 #undef WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27 #include <ddk/ntddk.h>
28 #include <ddk/ntddvid.h>
29
30 #include <internal/safe.h>
31 #include <win32k/bitmaps.h>
32 #include <win32k/brush.h>
33 #include <win32k/cliprgn.h>
34 #include <win32k/coord.h>
35 #include <win32k/driver.h>
36 #include <win32k/dc.h>
37 #include <win32k/misc.h>
38 #include <win32k/print.h>
39 #include <win32k/region.h>
40 #include <win32k/gdiobj.h>
41 #include <win32k/paint.h>
42 #include <win32k/pen.h>
43 #include <win32k/text.h>
44 #include "../eng/clip.h"
45 #include "../eng/handle.h"
46 #include <include/dce.h>
47 #include <include/error.h>
48 #include <include/inteng.h>
49 #include <include/eng.h>
50 #include <include/palette.h>
51 #include <include/guicheck.h>
52 #include <include/desktop.h>
53 #include <include/intgdi.h>
54 #include <include/cleanup.h>
55 #include <include/tags.h>
56 #include <include/text.h>
57
58 #define NDEBUG
59 #include <win32k/debug1.h>
60
61 static GDIDEVICE PrimarySurface;
62
63 /* FIXME: DCs should probably be thread safe */
64
65 /*
66 * DC device-independent Get/SetXXX functions
67 * (RJJ) swiped from WINE
68 */
69
70 #define DC_GET_VAL( func_type, func_name, dc_field ) \
71 func_type STDCALL func_name( HDC hdc ) \
72 { \
73 func_type ft; \
74 PDC dc = DC_LockDc( hdc ); \
75 if (!dc) \
76 { \
77 return 0; \
78 } \
79 ft = dc->dc_field; \
80 DC_UnlockDc( hdc ); \
81 return ft; \
82 }
83
84 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
85 * important that the function has the right signature, for the implementation
86 * we can do whatever we want.
87 */
88 #define DC_GET_VAL_EX( NtGdiFuncName, IntFuncName, ret_x, ret_y, type ) \
89 VOID FASTCALL IntFuncName ( PDC dc, LP##type pt ) \
90 { \
91 ASSERT ( dc ); \
92 ASSERT ( pt ); \
93 ((LPPOINT)pt)->x = dc->ret_x; \
94 ((LPPOINT)pt)->y = dc->ret_y; \
95 } \
96 BOOL STDCALL NtGdiFuncName ( HDC hdc, LP##type pt ) \
97 { \
98 PDC dc = DC_LockDc ( hdc ); \
99 if ( !dc ) \
100 return FALSE; \
101 IntFuncName ( dc, pt ); \
102 DC_UnlockDc ( hdc ); \
103 return TRUE; \
104 }
105
106 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
107 INT STDCALL func_name( HDC hdc, INT mode ) \
108 { \
109 INT prevMode; \
110 PDC dc; \
111 if ((mode < min_val) || (mode > max_val)) \
112 return 0; \
113 dc = DC_LockDc ( hdc ); \
114 if ( !dc ) \
115 return 0; \
116 prevMode = dc->dc_field; \
117 dc->dc_field = mode; \
118 DC_UnlockDc ( hdc ); \
119 return prevMode; \
120 }
121
122
123 // --------------------------------------------------------- File Statics
124
125 // ----------------------------------------------------- Public Functions
126
127 BOOL STDCALL
128 NtGdiCancelDC(HDC hDC)
129 {
130 UNIMPLEMENTED;
131 }
132
133 HDC STDCALL
134 NtGdiCreateCompatableDC(HDC hDC)
135 {
136 PDC NewDC, OrigDC;
137 HBITMAP hBitmap;
138 HDC hNewDC, DisplayDC;
139 HRGN hVisRgn;
140 BITMAPOBJ *pb;
141 UNICODE_STRING DriverName;
142
143 DisplayDC = NULL;
144 if (hDC == NULL)
145 {
146 RtlInitUnicodeString(&DriverName, L"DISPLAY");
147 DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL);
148 if (NULL == DisplayDC)
149 {
150 return NULL;
151 }
152 hDC = DisplayDC;
153 }
154
155 /* Allocate a new DC based on the original DC's device */
156 OrigDC = DC_LockDc(hDC);
157 if (NULL == OrigDC)
158 {
159 if (NULL != DisplayDC)
160 {
161 NtGdiDeleteDC(DisplayDC);
162 }
163 return NULL;
164 }
165 hNewDC = DC_AllocDC(&OrigDC->DriverName);
166
167 if (NULL == hNewDC)
168 {
169 DC_UnlockDc(hDC);
170 if (NULL != DisplayDC)
171 {
172 NtGdiDeleteDC(DisplayDC);
173 }
174 return NULL;
175 }
176 NewDC = DC_LockDc( hNewDC );
177
178 /* Copy information from original DC to new DC */
179 NewDC->hSelf = hNewDC;
180
181 NewDC->PDev = OrigDC->PDev;
182 NewDC->DMW = OrigDC->DMW;
183 memcpy(NewDC->FillPatternSurfaces,
184 OrigDC->FillPatternSurfaces,
185 sizeof OrigDC->FillPatternSurfaces);
186 NewDC->GDIInfo = OrigDC->GDIInfo;
187 NewDC->DevInfo = OrigDC->DevInfo;
188 NewDC->w.bitsPerPixel = OrigDC->w.bitsPerPixel;
189
190 /* DriverName is copied in the AllocDC routine */
191 NewDC->DeviceDriver = OrigDC->DeviceDriver;
192 NewDC->wndOrgX = OrigDC->wndOrgX;
193 NewDC->wndOrgY = OrigDC->wndOrgY;
194 NewDC->wndExtX = OrigDC->wndExtX;
195 NewDC->wndExtY = OrigDC->wndExtY;
196 NewDC->vportOrgX = OrigDC->vportOrgX;
197 NewDC->vportOrgY = OrigDC->vportOrgY;
198 NewDC->vportExtX = OrigDC->vportExtX;
199 NewDC->vportExtY = OrigDC->vportExtY;
200
201 /* Create default bitmap */
202 if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
203 {
204 DC_UnlockDc( hDC );
205 DC_UnlockDc( hNewDC );
206 DC_FreeDC( hNewDC );
207 if (NULL != DisplayDC)
208 {
209 NtGdiDeleteDC(DisplayDC);
210 }
211 return NULL;
212 }
213 NewDC->w.flags = DC_MEMORY;
214 NewDC->w.hBitmap = hBitmap;
215 NewDC->w.hFirstBitmap = hBitmap;
216 NewDC->GDIDevice = OrigDC->GDIDevice;
217 pb = BITMAPOBJ_LockBitmap(hBitmap);
218 NewDC->Surface = BitmapToSurf(pb, NewDC->GDIDevice);
219 BITMAPOBJ_UnlockBitmap(hBitmap);
220
221 NewDC->w.hPalette = OrigDC->w.hPalette;
222 NewDC->w.textColor = OrigDC->w.textColor;
223 NewDC->w.textAlign = OrigDC->w.textAlign;
224 NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
225 NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
226 DC_UnlockDc( hDC );
227 if (NULL != DisplayDC)
228 {
229 NtGdiDeleteDC(DisplayDC);
230 }
231 DC_UnlockDc(hNewDC);
232
233 hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
234 NtGdiSelectVisRgn(hNewDC, hVisRgn);
235 NtGdiDeleteObject(hVisRgn);
236
237 DC_InitDC(hNewDC);
238
239 return hNewDC;
240 }
241
242 static BOOL FASTCALL
243 GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
244 {
245 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
246 WCHAR DeviceNameBuffer[20];
247 NTSTATUS Status;
248
249 swprintf(DeviceNameBuffer, L"\\Device\\Video%d", DisplayNumber);
250 RtlInitUnicodeString(RegistryPath, NULL);
251 RtlZeroMemory(QueryTable, sizeof(QueryTable));
252 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
253 QueryTable[0].Name = DeviceNameBuffer;
254 QueryTable[0].EntryContext = RegistryPath;
255
256 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
257 L"VIDEO",
258 QueryTable,
259 NULL,
260 NULL);
261 if (! NT_SUCCESS(Status))
262 {
263 DPRINT1("No \\Device\\Video%d value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
264 return FALSE;
265 }
266
267 DPRINT("RegistryPath %S\n", RegistryPath->Buffer);
268
269 return TRUE;
270 }
271
272 static BOOL FASTCALL
273 FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
274 {
275 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
276 UNICODE_STRING RegistryPath;
277 NTSTATUS Status;
278
279 if (! GetRegistryPath(&RegistryPath, DisplayNumber))
280 {
281 DPRINT("GetRegistryPath failed\n");
282 return FALSE;
283 }
284
285 RtlZeroMemory(QueryTable, sizeof(QueryTable));
286 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
287 QueryTable[0].Name = L"InstalledDisplayDrivers";
288 QueryTable[0].EntryContext = DriverFileNames;
289
290 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
291 RegistryPath.Buffer,
292 QueryTable,
293 NULL,
294 NULL);
295 RtlFreeUnicodeString(&RegistryPath);
296 if (! NT_SUCCESS(Status))
297 {
298 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
299 return FALSE;
300 }
301
302 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
303
304 return TRUE;
305 }
306
307 static NTSTATUS STDCALL
308 DevModeCallback(IN PWSTR ValueName,
309 IN ULONG ValueType,
310 IN PVOID ValueData,
311 IN ULONG ValueLength,
312 IN PVOID Context,
313 IN PVOID EntryContext)
314 {
315 PDEVMODEW DevMode = (PDEVMODEW) Context;
316
317 DPRINT("Found registry value for name %S: type %d, length %d\n",
318 ValueName, ValueType, ValueLength);
319
320 if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
321 {
322 if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
323 {
324 DevMode->dmBitsPerPel = *((DWORD *) ValueData);
325 }
326 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
327 {
328 DevMode->dmDisplayFlags = *((DWORD *) ValueData);
329 }
330 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
331 {
332 DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
333 }
334 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
335 {
336 DevMode->dmPanningWidth = *((DWORD *) ValueData);
337 }
338 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
339 {
340 DevMode->dmPelsWidth = *((DWORD *) ValueData);
341 }
342 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
343 {
344 DevMode->dmPanningHeight = *((DWORD *) ValueData);
345 }
346 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
347 {
348 DevMode->dmPelsHeight = *((DWORD *) ValueData);
349 }
350 }
351
352 return STATUS_SUCCESS;
353 }
354
355 static BOOL FASTCALL
356 SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
357 {
358 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
359 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
360 static WCHAR ControlSet[] = L"CONTROLSET";
361 static WCHAR Insert[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
362 UNICODE_STRING RegistryPath;
363 BOOL Valid;
364 PWCHAR AfterControlSet;
365 PWCHAR ProfilePath;
366 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
367 NTSTATUS Status;
368
369 if (! GetRegistryPath(&RegistryPath, DisplayNumber))
370 {
371 DPRINT("GetRegistryPath failed\n");
372 return FALSE;
373 }
374
375 Valid = (0 == _wcsnicmp(RegistryPath.Buffer, RegistryMachineSystem,
376 wcslen(RegistryMachineSystem)));
377 if (Valid)
378 {
379 AfterControlSet = RegistryPath.Buffer + wcslen(RegistryMachineSystem);
380 if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
381 {
382 AfterControlSet += wcslen(CurrentControlSet);
383 }
384 else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
385 {
386 AfterControlSet += wcslen(ControlSet);
387 while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
388 {
389 AfterControlSet++;
390 }
391 Valid = (L'\\' == *AfterControlSet);
392 AfterControlSet++;
393 }
394 else
395 {
396 Valid = FALSE;
397 }
398 }
399
400 if (Valid)
401 {
402 ProfilePath = ExAllocatePoolWithTag(PagedPool,
403 (wcslen(RegistryPath.Buffer) +
404 wcslen(Insert) + 1) * sizeof(WCHAR),
405 TAG_DC);
406 if (NULL != ProfilePath)
407 {
408 wcsncpy(ProfilePath, RegistryPath.Buffer, AfterControlSet - RegistryPath.Buffer);
409 wcscpy(ProfilePath + (AfterControlSet - RegistryPath.Buffer), Insert);
410 wcscat(ProfilePath, AfterControlSet);
411
412 RtlZeroMemory(QueryTable, sizeof(QueryTable));
413 QueryTable[0].QueryRoutine = DevModeCallback;
414 QueryTable[0].Flags = 0;
415 QueryTable[0].Name = NULL;
416 QueryTable[0].EntryContext = NULL;
417 QueryTable[0].DefaultType = REG_NONE;
418 QueryTable[0].DefaultData = NULL;
419 QueryTable[0].DefaultLength = 0;
420
421 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
422 ProfilePath,
423 QueryTable,
424 DevMode,
425 NULL);
426 if (! NT_SUCCESS(Status))
427 {
428 DPRINT("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
429 ProfilePath, Status);
430 Valid = FALSE;
431 }
432 else
433 {
434 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
435 DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
436 DevMode->dmPelsWidth, DevMode->dmPelsHeight);
437 if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
438 || 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
439 {
440 DPRINT("Not all required devmode members are set\n");
441 Valid = FALSE;
442 }
443 }
444
445 ExFreePool(ProfilePath);
446 }
447 else
448 {
449 Valid = FALSE;
450 }
451 }
452 else
453 {
454 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath.Buffer);
455 }
456
457 RtlFreeUnicodeString(&RegistryPath);
458
459 if (! Valid)
460 {
461 RtlZeroMemory(DevMode, sizeof(DEVMODEW));
462 }
463
464 return Valid;
465 }
466
467 BOOL FASTCALL
468 IntCreatePrimarySurface()
469 {
470 PGD_ENABLEDRIVER GDEnableDriver;
471 DRVENABLEDATA DED;
472 PSURFOBJ SurfObj;
473 PSURFGDI SurfGDI;
474 UNICODE_STRING DriverFileNames;
475 PWSTR CurrentName;
476 BOOL GotDriver;
477 BOOL DoDefault;
478 ULONG DisplayNumber;
479
480 for (DisplayNumber = 0; ; DisplayNumber++)
481 {
482 DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
483
484 RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
485 ExInitializeFastMutex(&PrimarySurface.DriverLock);
486
487 PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
488
489 /* Open the miniport driver */
490 if (PrimarySurface.VideoFileObject == NULL)
491 {
492 DPRINT1("FindMPDriver failed\n");
493 return FALSE;
494 }
495
496 /* Retrieve DDI driver names from registry */
497 RtlInitUnicodeString(&DriverFileNames, NULL);
498 if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
499 {
500 DPRINT1("FindDriverFileNames failed\n");
501 /* return FALSE; */
502 continue;
503 }
504
505 /*
506 * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
507 * scan all of them until a good one found.
508 */
509 CurrentName = DriverFileNames.Buffer;
510 GotDriver = FALSE;
511 while (!GotDriver &&
512 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
513 {
514 /* Get the DDI driver's entry point */
515 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
516 if (NULL == GDEnableDriver)
517 {
518 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
519 }
520 else
521 {
522 /* Call DDI driver's EnableDriver function */
523 RtlZeroMemory(&DED, sizeof(DED));
524
525 if (! GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
526 {
527 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
528 }
529 else
530 {
531 GotDriver = TRUE;
532 }
533 }
534
535 if (! GotDriver)
536 {
537 /* Skip to the next name but never get past the Unicode string */
538 while (L'\0' != *CurrentName &&
539 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
540 {
541 CurrentName++;
542 }
543 if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
544 {
545 CurrentName++;
546 }
547 }
548 }
549
550 RtlFreeUnicodeString(&DriverFileNames);
551
552 if (!GotDriver)
553 {
554 ObDereferenceObject(PrimarySurface.VideoFileObject);
555 DPRINT1("No suitable DDI driver found\n");
556 /* return FALSE; */
557 continue;
558 }
559
560 DPRINT("Display driver %S loaded\n", CurrentName);
561
562 DPRINT("Building DDI Functions\n");
563
564 /* Construct DDI driver function dispatch table */
565 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
566 {
567 ObDereferenceObject(PrimarySurface.VideoFileObject);
568 DPRINT1("BuildDDIFunctions failed\n");
569 return FALSE;
570 }
571
572 /* Allocate a phyical device handle from the driver */
573 if (SetupDevMode(&PrimarySurface.DMW, DisplayNumber))
574 {
575 PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDev(
576 &PrimarySurface.DMW,
577 L"",
578 HS_DDI_MAX,
579 PrimarySurface.FillPatterns,
580 sizeof(PrimarySurface.GDIInfo),
581 (ULONG *) &PrimarySurface.GDIInfo,
582 sizeof(PrimarySurface.DevInfo),
583 &PrimarySurface.DevInfo,
584 NULL,
585 L"",
586 (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
587 DoDefault = (NULL == PrimarySurface.PDev);
588 if (DoDefault)
589 {
590 DPRINT1("DrvEnablePDev with registry parameters failed\n");
591 }
592 }
593 else
594 {
595 DoDefault = TRUE;
596 }
597
598 if (DoDefault)
599 {
600 RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
601 PrimarySurface.PDev = PrimarySurface.DriverFunctions.EnablePDev(
602 &PrimarySurface.DMW,
603 L"",
604 HS_DDI_MAX,
605 PrimarySurface.FillPatterns,
606 sizeof(PrimarySurface.GDIInfo),
607 (ULONG *) &PrimarySurface.GDIInfo,
608 sizeof(PrimarySurface.DevInfo),
609 &PrimarySurface.DevInfo,
610 NULL,
611 L"",
612 (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
613
614 if (NULL == PrimarySurface.PDev)
615 {
616 ObDereferenceObject(PrimarySurface.VideoFileObject);
617 DPRINT1("DrvEnablePDEV with default parameters failed\n");
618 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
619 /* return FALSE; */
620 continue;
621 }
622 }
623
624 if (0 == PrimarySurface.GDIInfo.ulLogPixelsX)
625 {
626 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
627 PrimarySurface.GDIInfo.ulLogPixelsX = 96;
628 }
629 if (0 == PrimarySurface.GDIInfo.ulLogPixelsY)
630 {
631 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
632 PrimarySurface.GDIInfo.ulLogPixelsY = 96;
633 }
634
635 DPRINT("calling completePDev\n");
636
637 /* Complete initialization of the physical device */
638 PrimarySurface.DriverFunctions.CompletePDev(
639 PrimarySurface.PDev,
640 &PrimarySurface);
641
642 DPRINT("calling DRIVER_ReferenceDriver\n");
643
644 DRIVER_ReferenceDriver(L"DISPLAY");
645
646 DPRINT("calling EnableSurface\n");
647
648 /* Enable the drawing surface */
649 PrimarySurface.Handle =
650 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
651 if (NULL == PrimarySurface.Handle)
652 {
653 /* PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);*/
654 PrimarySurface.DriverFunctions.DisablePDev(PrimarySurface.PDev);
655 ObDereferenceObject(PrimarySurface.VideoFileObject);
656 DPRINT1("DrvEnableSurface failed\n");
657 /* return FALSE; */
658 continue;
659 }
660
661 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
662 SurfObj->dhpdev = PrimarySurface.PDev;
663 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
664 IntShowDesktop(
665 IntGetActiveDesktop(),
666 SurfGDI->SurfObj.sizlBitmap.cx,
667 SurfGDI->SurfObj.sizlBitmap.cy);
668 break;
669 }
670
671 return TRUE;
672 }
673
674 VOID FASTCALL
675 IntDestroyPrimarySurface()
676 {
677 #if 0
678 PSURFOBJ SurfObj;
679 PSURFGDI SurfGDI;
680 #endif
681
682 DRIVER_UnreferenceDriver(L"DISPLAY");
683
684 #if 0
685 DPRINT("Hiding mouse pointer\n" );
686 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
687 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
688 SurfGDI->SetPointerShape(SurfObj, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0);
689 #endif
690 DPRINT("Reseting display\n" );
691 PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.PDev, FALSE);
692 PrimarySurface.DriverFunctions.DisableSurface(PrimarySurface.PDev);
693 PrimarySurface.DriverFunctions.DisablePDev(PrimarySurface.PDev);
694
695 DceEmptyCache();
696
697 ObDereferenceObject(PrimarySurface.VideoFileObject);
698 }
699
700 HDC FASTCALL
701 IntGdiCreateDC(PUNICODE_STRING Driver,
702 PUNICODE_STRING Device,
703 PUNICODE_STRING Output,
704 CONST PDEVMODEW InitData)
705 {
706 HDC hNewDC;
707 PDC NewDC;
708 HDC hDC = NULL;
709 PSURFGDI SurfGDI;
710 HRGN hVisRgn;
711 UNICODE_STRING StdDriver;
712
713 RtlInitUnicodeString(&StdDriver, L"DISPLAY");
714
715 if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
716 {
717 if (! IntGraphicsCheck(TRUE))
718 {
719 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
720 return NULL;
721 }
722 }
723
724 /* Check for existing DC object */
725 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
726 {
727 hDC = hNewDC;
728 return NtGdiCreateCompatableDC(hDC);
729 }
730
731 if (Driver != NULL && Driver->Buffer != NULL)
732 {
733 DPRINT("NAME: %S\n", Driver->Buffer); // FIXME: Should not crash if NULL
734 }
735
736 /* Allocate a DC object */
737 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
738 {
739 return NULL;
740 }
741
742 NewDC = DC_LockDc( hNewDC );
743 ASSERT( NewDC );
744
745 NewDC->DMW = PrimarySurface.DMW;
746 NewDC->DevInfo = &PrimarySurface.DevInfo;
747 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
748 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
749 sizeof(NewDC->FillPatternSurfaces));
750 NewDC->PDev = PrimarySurface.PDev;
751 NewDC->Surface = PrimarySurface.Handle;
752 NewDC->GDIDevice = &PrimarySurface;
753 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
754
755 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
756 NewDC->DMW.dmFields = 0x000fc000;
757
758 /* FIXME: get mode selection information from somewhere */
759
760 NewDC->DMW.dmLogPixels = 96;
761 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
762 NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
763 NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
764 NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
765 NewDC->DMW.dmDisplayFlags = 0;
766 NewDC->DMW.dmDisplayFrequency = 0;
767
768 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
769
770 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
771
772 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
773
774 DC_UnlockDc( hNewDC );
775
776 hVisRgn = NtGdiCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
777 SurfGDI->SurfObj.sizlBitmap.cy);
778 NtGdiSelectVisRgn(hNewDC, hVisRgn);
779 NtGdiDeleteObject(hVisRgn);
780
781 /* Initialize the DC state */
782 DC_InitDC(hNewDC);
783 NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
784 NtGdiSetTextAlign(hNewDC, TA_TOP);
785 NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
786 NtGdiSetBkMode(hNewDC, OPAQUE);
787
788 return hNewDC;
789 }
790
791 HDC STDCALL
792 NtGdiCreateDC(PUNICODE_STRING Driver,
793 PUNICODE_STRING Device,
794 PUNICODE_STRING Output,
795 CONST PDEVMODEW InitData)
796 {
797 UNICODE_STRING SafeDriver, SafeDevice;
798 DEVMODEW SafeInitData;
799 HDC Ret;
800 NTSTATUS Status;
801
802 if(InitData)
803 {
804 Status = MmCopyFromCaller(&SafeInitData, InitData, sizeof(DEVMODEW));
805 if(!NT_SUCCESS(Status))
806 {
807 SetLastNtError(Status);
808 return NULL;
809 }
810 /* FIXME - InitData can have some more bytes! */
811 }
812
813 if(Driver)
814 {
815 Status = IntSafeCopyUnicodeString(&SafeDriver, Driver);
816 if(!NT_SUCCESS(Status))
817 {
818 SetLastNtError(Status);
819 return NULL;
820 }
821 }
822
823 if(Device)
824 {
825 Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
826 if(!NT_SUCCESS(Status))
827 {
828 RtlFreeUnicodeString(&SafeDriver);
829 SetLastNtError(Status);
830 return NULL;
831 }
832 }
833
834 Ret = IntGdiCreateDC(&SafeDriver, &SafeDevice, NULL, &SafeInitData);
835
836 return Ret;
837 }
838
839 HDC STDCALL
840 NtGdiCreateIC(PUNICODE_STRING Driver,
841 PUNICODE_STRING Device,
842 PUNICODE_STRING Output,
843 CONST PDEVMODEW DevMode)
844 {
845 /* FIXME: this should probably do something else... */
846 return NtGdiCreateDC(Driver, Device, Output, DevMode);
847 }
848
849 BOOL STDCALL
850 NtGdiDeleteDC(HDC DCHandle)
851 {
852 PDC DCToDelete;
853
854 DCToDelete = DC_LockDc(DCHandle);
855 if (DCToDelete == NULL)
856 {
857 return FALSE;
858 }
859 DPRINT( "Deleting DC\n" );
860 CHECKPOINT;
861 /* First delete all saved DCs */
862 while (DCToDelete->saveLevel)
863 {
864 PDC savedDC;
865 HDC savedHDC;
866
867 savedHDC = DC_GetNextDC (DCToDelete);
868 savedDC = DC_LockDc (savedHDC);
869 if (savedDC == NULL)
870 {
871 break;
872 }
873 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
874 DCToDelete->saveLevel--;
875 DC_UnlockDc( savedHDC );
876 NtGdiDeleteDC (savedHDC);
877 }
878
879 /* Free GDI resources allocated to this DC */
880 if (!(DCToDelete->w.flags & DC_SAVED))
881 {
882 /*
883 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
884 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
885 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
886 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
887 if (DCToDelete->w.flags & DC_MEMORY)
888 {
889 EngDeleteSurface (DCToDelete->Surface);
890 NtGdiDeleteObject (DCToDelete->w.hFirstBitmap);
891 }
892 }
893 if (DCToDelete->w.hClipRgn)
894 {
895 NtGdiDeleteObject (DCToDelete->w.hClipRgn);
896 }
897 if (DCToDelete->w.hVisRgn)
898 {
899 NtGdiDeleteObject (DCToDelete->w.hVisRgn);
900 }
901 if (NULL != DCToDelete->CombinedClip)
902 {
903 IntEngDeleteClipRegion(DCToDelete->CombinedClip);
904 }
905 if (DCToDelete->w.hGCClipRgn)
906 {
907 NtGdiDeleteObject (DCToDelete->w.hGCClipRgn);
908 }
909 #if 0 /* FIXME */
910 PATH_DestroyGdiPath (&DCToDelete->w.path);
911 #endif
912 DC_UnlockDc( DCHandle );
913 DC_FreeDC ( DCHandle );
914
915 return TRUE;
916 }
917
918 INT STDCALL
919 NtGdiDrawEscape(HDC hDC,
920 INT nEscape,
921 INT cbInput,
922 LPCSTR lpszInData)
923 {
924 UNIMPLEMENTED;
925 }
926
927 INT STDCALL
928 NtGdiEnumObjects(HDC hDC,
929 INT ObjectType,
930 GOBJENUMPROC ObjectFunc,
931 LPARAM lParam)
932 {
933 UNIMPLEMENTED;
934 }
935
936 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
937 DC_GET_VAL( INT, NtGdiGetBkMode, w.backgroundMode )
938 DC_GET_VAL_EX( NtGdiGetBrushOrgEx, IntGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
939 DC_GET_VAL( HRGN, NtGdiGetClipRgn, w.hClipRgn )
940
941 HGDIOBJ STDCALL
942 NtGdiGetCurrentObject(HDC hDC, UINT ObjectType)
943 {
944 UNIMPLEMENTED;
945 }
946
947 DC_GET_VAL_EX ( NtGdiGetCurrentPositionEx, IntGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
948
949 BOOL FASTCALL
950 IntGdiGetDCOrgEx(DC *dc, LPPOINT Point)
951 {
952 Point->x = dc->w.DCOrgX;
953 Point->y = dc->w.DCOrgY;
954
955 return TRUE;
956 }
957
958 BOOL STDCALL
959 NtGdiGetDCOrgEx(HDC hDC, LPPOINT Point)
960 {
961 BOOL Ret;
962 DC *dc;
963 POINT SafePoint;
964 NTSTATUS Status;
965
966 if(!Point)
967 {
968 SetLastWin32Error(ERROR_INVALID_PARAMETER);
969 return FALSE;
970 }
971
972 dc = DC_LockDc(hDC);
973 if(!dc)
974 {
975 SetLastWin32Error(ERROR_INVALID_HANDLE);
976 return FALSE;
977 }
978
979 Ret = IntGdiGetDCOrgEx(dc, &SafePoint);
980
981 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
982 if(!NT_SUCCESS(Status))
983 {
984 SetLastNtError(Status);
985 DC_UnlockDc(hDC);
986 return FALSE;
987 }
988
989 DC_UnlockDc(hDC);
990 return Ret;
991 }
992
993 COLORREF STDCALL
994 NtGdiSetBkColor(HDC hDC, COLORREF color)
995 {
996 COLORREF oldColor;
997 PDC dc = DC_LockDc(hDC);
998
999 if ( !dc )
1000 return 0x80000000;
1001
1002 oldColor = dc->w.backgroundColor;
1003 dc->w.backgroundColor = color;
1004 DC_UnlockDc ( hDC );
1005 return oldColor;
1006 }
1007
1008 HDC STDCALL
1009 NtGdiGetDCState(HDC hDC)
1010 {
1011 PDC newdc, dc;
1012 HDC hnewdc;
1013
1014 dc = DC_LockDc(hDC);
1015 if (dc == NULL)
1016 {
1017 return 0;
1018 }
1019
1020 hnewdc = DC_AllocDC(NULL);
1021 if (hnewdc == NULL)
1022 {
1023 DC_UnlockDc( hDC );
1024 return 0;
1025 }
1026 newdc = DC_LockDc( hnewdc );
1027 ASSERT( newdc );
1028
1029 newdc->w.flags = dc->w.flags | DC_SAVED;
1030 newdc->w.hPen = dc->w.hPen;
1031 newdc->w.hBrush = dc->w.hBrush;
1032 newdc->w.hFont = dc->w.hFont;
1033 newdc->w.hBitmap = dc->w.hBitmap;
1034 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
1035 #if 0
1036 newdc->w.hDevice = dc->w.hDevice;
1037 newdc->w.hPalette = dc->w.hPalette;
1038 #endif
1039 newdc->w.totalExtent = dc->w.totalExtent;
1040 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
1041 newdc->w.ROPmode = dc->w.ROPmode;
1042 newdc->w.polyFillMode = dc->w.polyFillMode;
1043 newdc->w.stretchBltMode = dc->w.stretchBltMode;
1044 newdc->w.relAbsMode = dc->w.relAbsMode;
1045 newdc->w.backgroundMode = dc->w.backgroundMode;
1046 newdc->w.backgroundColor = dc->w.backgroundColor;
1047 newdc->w.textColor = dc->w.textColor;
1048 newdc->w.brushOrgX = dc->w.brushOrgX;
1049 newdc->w.brushOrgY = dc->w.brushOrgY;
1050 newdc->w.textAlign = dc->w.textAlign;
1051 newdc->w.charExtra = dc->w.charExtra;
1052 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
1053 newdc->w.breakCount = dc->w.breakCount;
1054 newdc->w.breakExtra = dc->w.breakExtra;
1055 newdc->w.breakRem = dc->w.breakRem;
1056 newdc->w.MapMode = dc->w.MapMode;
1057 newdc->w.GraphicsMode = dc->w.GraphicsMode;
1058 #if 0
1059 /* Apparently, the DC origin is not changed by [GS]etDCState */
1060 newdc->w.DCOrgX = dc->w.DCOrgX;
1061 newdc->w.DCOrgY = dc->w.DCOrgY;
1062 #endif
1063 newdc->w.CursPosX = dc->w.CursPosX;
1064 newdc->w.CursPosY = dc->w.CursPosY;
1065 newdc->w.ArcDirection = dc->w.ArcDirection;
1066 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
1067 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
1068 newdc->w.xformVport2World = dc->w.xformVport2World;
1069 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
1070 newdc->wndOrgX = dc->wndOrgX;
1071 newdc->wndOrgY = dc->wndOrgY;
1072 newdc->wndExtX = dc->wndExtX;
1073 newdc->wndExtY = dc->wndExtY;
1074 newdc->vportOrgX = dc->vportOrgX;
1075 newdc->vportOrgY = dc->vportOrgY;
1076 newdc->vportExtX = dc->vportExtX;
1077 newdc->vportExtY = dc->vportExtY;
1078
1079 newdc->hSelf = hnewdc;
1080 newdc->saveLevel = 0;
1081
1082 #if 0
1083 PATH_InitGdiPath( &newdc->w.path );
1084 #endif
1085
1086 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1087
1088 #if 0
1089 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
1090 #endif
1091 if (dc->w.hClipRgn)
1092 {
1093 newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1094 NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
1095 }
1096 else
1097 {
1098 newdc->w.hClipRgn = 0;
1099 }
1100 DC_UnlockDc( hnewdc );
1101 DC_UnlockDc( hDC );
1102 return hnewdc;
1103 }
1104
1105
1106 VOID
1107 STDCALL
1108 NtGdiSetDCState ( HDC hDC, HDC hDCSave )
1109 {
1110 PDC dc, dcs;
1111
1112 dc = DC_LockDc ( hDC );
1113 if ( dc )
1114 {
1115 dcs = DC_LockDc ( hDCSave );
1116 if ( dcs )
1117 {
1118 if ( dcs->w.flags & DC_SAVED )
1119 {
1120 dc->w.flags = dcs->w.flags & ~DC_SAVED;
1121
1122 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
1123
1124 #if 0
1125 dc->w.hDevice = dcs->w.hDevice;
1126 #endif
1127
1128 dc->w.totalExtent = dcs->w.totalExtent;
1129 dc->w.ROPmode = dcs->w.ROPmode;
1130 dc->w.polyFillMode = dcs->w.polyFillMode;
1131 dc->w.stretchBltMode = dcs->w.stretchBltMode;
1132 dc->w.relAbsMode = dcs->w.relAbsMode;
1133 dc->w.backgroundMode = dcs->w.backgroundMode;
1134 dc->w.backgroundColor = dcs->w.backgroundColor;
1135 dc->w.textColor = dcs->w.textColor;
1136 dc->w.brushOrgX = dcs->w.brushOrgX;
1137 dc->w.brushOrgY = dcs->w.brushOrgY;
1138 dc->w.textAlign = dcs->w.textAlign;
1139 dc->w.charExtra = dcs->w.charExtra;
1140 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
1141 dc->w.breakCount = dcs->w.breakCount;
1142 dc->w.breakExtra = dcs->w.breakExtra;
1143 dc->w.breakRem = dcs->w.breakRem;
1144 dc->w.MapMode = dcs->w.MapMode;
1145 dc->w.GraphicsMode = dcs->w.GraphicsMode;
1146 #if 0
1147 /* Apparently, the DC origin is not changed by [GS]etDCState */
1148 dc->w.DCOrgX = dcs->w.DCOrgX;
1149 dc->w.DCOrgY = dcs->w.DCOrgY;
1150 #endif
1151 dc->w.CursPosX = dcs->w.CursPosX;
1152 dc->w.CursPosY = dcs->w.CursPosY;
1153 dc->w.ArcDirection = dcs->w.ArcDirection;
1154
1155 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
1156 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1157 dc->w.xformVport2World = dcs->w.xformVport2World;
1158 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1159
1160 dc->wndOrgX = dcs->wndOrgX;
1161 dc->wndOrgY = dcs->wndOrgY;
1162 dc->wndExtX = dcs->wndExtX;
1163 dc->wndExtY = dcs->wndExtY;
1164 dc->vportOrgX = dcs->vportOrgX;
1165 dc->vportOrgY = dcs->vportOrgY;
1166 dc->vportExtX = dcs->vportExtX;
1167 dc->vportExtY = dcs->vportExtY;
1168
1169 if (!(dc->w.flags & DC_MEMORY))
1170 {
1171 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1172 }
1173
1174 #if 0
1175 if (dcs->w.hClipRgn)
1176 {
1177 if (!dc->w.hClipRgn)
1178 {
1179 dc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1180 }
1181 NtGdiCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1182 }
1183 else
1184 {
1185 if (dc->w.hClipRgn)
1186 {
1187 NtGdiDeleteObject( dc->w.hClipRgn );
1188 }
1189
1190 dc->w.hClipRgn = 0;
1191 }
1192 CLIPPING_UpdateGCRegion( dc );
1193 DC_UnlockDc ( hDC );
1194 #else
1195 DC_UnlockDc ( hDC );
1196 NtGdiSelectClipRgn(hDC, dcs->w.hClipRgn);
1197 #endif
1198
1199 NtGdiSelectObject( hDC, dcs->w.hBitmap );
1200 NtGdiSelectObject( hDC, dcs->w.hBrush );
1201 NtGdiSelectObject( hDC, dcs->w.hFont );
1202 NtGdiSelectObject( hDC, dcs->w.hPen );
1203 NtGdiSetBkColor( hDC, dcs->w.backgroundColor);
1204 NtGdiSetTextColor( hDC, dcs->w.textColor);
1205
1206 #if 0
1207 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1208 #endif
1209 } else {
1210 DC_UnlockDc(hDC);
1211 }
1212 DC_UnlockDc ( hDCSave );
1213 } else {
1214 DC_UnlockDc ( hDC );
1215 }
1216 }
1217 }
1218
1219 INT STDCALL
1220 NtGdiGetDeviceCaps(HDC hDC,
1221 INT Index)
1222 {
1223 PDC dc;
1224 INT ret;
1225 POINT pt;
1226
1227 dc = DC_LockDc(hDC);
1228 if (dc == NULL)
1229 {
1230 return 0;
1231 }
1232
1233 /* Retrieve capability */
1234 switch (Index)
1235 {
1236 case DRIVERVERSION:
1237 ret = dc->GDIInfo->ulVersion;
1238 break;
1239
1240 case TECHNOLOGY:
1241 ret = dc->GDIInfo->ulTechnology;
1242 break;
1243
1244 case HORZSIZE:
1245 ret = dc->GDIInfo->ulHorzSize;
1246 break;
1247
1248 case VERTSIZE:
1249 ret = dc->GDIInfo->ulVertSize;
1250 break;
1251
1252 case HORZRES:
1253 ret = dc->GDIInfo->ulHorzRes;
1254 break;
1255
1256 case VERTRES:
1257 ret = dc->GDIInfo->ulVertRes;
1258 break;
1259
1260 case LOGPIXELSX:
1261 ret = dc->GDIInfo->ulLogPixelsX;
1262 break;
1263
1264 case LOGPIXELSY:
1265 ret = dc->GDIInfo->ulLogPixelsY;
1266 break;
1267
1268 case BITSPIXEL:
1269 ret = dc->GDIInfo->cBitsPixel;
1270 break;
1271
1272 case PLANES:
1273 ret = dc->GDIInfo->cPlanes;
1274 break;
1275
1276 case NUMBRUSHES:
1277 UNIMPLEMENTED; /* FIXME */
1278 break;
1279
1280 case NUMPENS:
1281 UNIMPLEMENTED; /* FIXME */
1282 break;
1283
1284 case NUMFONTS:
1285 UNIMPLEMENTED; /* FIXME */
1286 break;
1287
1288 case NUMCOLORS:
1289 ret = dc->GDIInfo->ulNumColors;
1290 break;
1291
1292 case ASPECTX:
1293 ret = dc->GDIInfo->ulAspectX;
1294 break;
1295
1296 case ASPECTY:
1297 ret = dc->GDIInfo->ulAspectY;
1298 break;
1299
1300 case ASPECTXY:
1301 ret = dc->GDIInfo->ulAspectXY;
1302 break;
1303
1304 case PDEVICESIZE:
1305 UNIMPLEMENTED; /* FIXME */
1306 break;
1307
1308 case CLIPCAPS:
1309 UNIMPLEMENTED; /* FIXME */
1310 break;
1311
1312 case SIZEPALETTE:
1313 ret = dc->GDIInfo->ulNumPalReg; /* FIXME not sure */
1314 break;
1315
1316 case NUMRESERVED:
1317 ret = 0;
1318 break;
1319
1320 case COLORRES:
1321 UNIMPLEMENTED; /* FIXME */
1322 break;
1323
1324 case PHYSICALWIDTH:
1325 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1326 {
1327 ret = pt.x;
1328 }
1329 else
1330 {
1331 ret = 0;
1332 }
1333 break;
1334
1335 case PHYSICALHEIGHT:
1336 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1337 {
1338 ret = pt.y;
1339 }
1340 else
1341 {
1342 ret = 0;
1343 }
1344 break;
1345
1346 case PHYSICALOFFSETX:
1347 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1348 {
1349 ret = pt.x;
1350 }
1351 else
1352 {
1353 ret = 0;
1354 }
1355 break;
1356
1357 case PHYSICALOFFSETY:
1358 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1359 {
1360 ret = pt.y;
1361 }
1362 else
1363 {
1364 ret = 0;
1365 }
1366 break;
1367
1368 case VREFRESH:
1369 UNIMPLEMENTED; /* FIXME */
1370 break;
1371
1372 case SCALINGFACTORX:
1373 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1374 {
1375 ret = pt.x;
1376 }
1377 else
1378 {
1379 ret = 0;
1380 }
1381 break;
1382
1383 case SCALINGFACTORY:
1384 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1385 {
1386 ret = pt.y;
1387 }
1388 else
1389 {
1390 ret = 0;
1391 }
1392 break;
1393
1394 case RASTERCAPS:
1395 ret = dc->GDIInfo->flRaster;
1396 break;
1397
1398 case CURVECAPS:
1399 UNIMPLEMENTED; /* FIXME */
1400 break;
1401
1402 case LINECAPS:
1403 UNIMPLEMENTED; /* FIXME */
1404 break;
1405
1406 case POLYGONALCAPS:
1407 UNIMPLEMENTED; /* FIXME */
1408 break;
1409
1410 case TEXTCAPS:
1411 ret = dc->GDIInfo->flTextCaps;
1412 break;
1413
1414 default:
1415 ret = 0;
1416 break;
1417 }
1418
1419 DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
1420
1421 DC_UnlockDc( hDC );
1422 return ret;
1423 }
1424
1425 DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
1426 DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
1427
1428 INT FASTCALL
1429 IntGdiGetObject(HANDLE Handle, INT Count, LPVOID Buffer)
1430 {
1431 PGDIOBJHDR GdiObject;
1432 INT Result = 0;
1433 DWORD ObjectType;
1434
1435 GdiObject = GDIOBJ_LockObj(Handle, GDI_OBJECT_TYPE_DONTCARE);
1436 if (NULL == GdiObject)
1437 {
1438 return 0;
1439 }
1440
1441 ObjectType = GDIOBJ_GetObjectType(Handle);
1442 switch (ObjectType)
1443 {
1444 #if 0
1445 case GDI_OBJECT_TYPE_PEN:
1446 Result = PEN_GetObject((PENOBJ *) GdiObject, Count, Buffer);
1447 break;
1448 case GDI_OBJECT_TYPE_BRUSH:
1449 Result = BRUSH_GetObject((BRUSHOBJ *) GdiObject, Count, Buffer);
1450 break;
1451 #endif
1452 case GDI_OBJECT_TYPE_BITMAP:
1453 Result = BITMAP_GetObject((BITMAPOBJ *) GdiObject, Count, Buffer);
1454 break;
1455 case GDI_OBJECT_TYPE_FONT:
1456 Result = FontGetObject((PTEXTOBJ) GdiObject, Count, Buffer);
1457 #if 0
1458 // Fix the LOGFONT structure for the stock fonts
1459 if (FIRST_STOCK_HANDLE <= Handle && Handle <= LAST_STOCK_HANDLE)
1460 {
1461 FixStockFontSizeW(Handle, Count, Buffer);
1462 }
1463 #endif
1464 break;
1465 #if 0
1466 case GDI_OBJECT_TYPE_PALETTE:
1467 Result = PALETTE_GetObject((PALETTEOBJ *) GdiObject, Count, Buffer);
1468 break;
1469 #endif
1470 default:
1471 DPRINT1("GDI object type 0x%08x not implemented\n", ObjectType);
1472 break;
1473 }
1474
1475 GDIOBJ_UnlockObj(Handle, GDI_OBJECT_TYPE_DONTCARE);
1476
1477 return Result;
1478 }
1479
1480 INT STDCALL
1481 NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
1482 {
1483 INT Ret;
1484 LPVOID SafeBuf;
1485 NTSTATUS Status;
1486
1487 if (count <= 0)
1488 {
1489 return 0;
1490 }
1491
1492 SafeBuf = ExAllocatePoolWithTag(NonPagedPool, count, TAG_GDIOBJ);
1493 if(!SafeBuf)
1494 {
1495 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
1496 return 0;
1497 }
1498
1499 Ret = IntGdiGetObject(handle, count, SafeBuf);
1500
1501 Status = MmCopyToCaller(buffer, SafeBuf, count);
1502 ExFreePool(SafeBuf);
1503 if(!NT_SUCCESS(Status))
1504 {
1505 SetLastNtError(Status);
1506 return 0;
1507 }
1508
1509 return Ret;
1510 }
1511
1512 DWORD STDCALL
1513 NtGdiGetObjectType(HANDLE handle)
1514 {
1515 GDIOBJHDR * ptr;
1516 INT result = 0;
1517 DWORD objectType;
1518
1519 ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1520 if (ptr == 0)
1521 return 0;
1522
1523 objectType = GDIOBJ_GetObjectType(handle);
1524 switch(objectType)
1525 {
1526 case GDI_OBJECT_TYPE_PEN:
1527 result = OBJ_PEN;
1528 break;
1529 case GDI_OBJECT_TYPE_BRUSH:
1530 result = OBJ_BRUSH;
1531 break;
1532 case GDI_OBJECT_TYPE_BITMAP:
1533 result = OBJ_BITMAP;
1534 break;
1535 case GDI_OBJECT_TYPE_FONT:
1536 result = OBJ_FONT;
1537 break;
1538 case GDI_OBJECT_TYPE_PALETTE:
1539 result = OBJ_PAL;
1540 break;
1541 case GDI_OBJECT_TYPE_REGION:
1542 result = OBJ_REGION;
1543 break;
1544 case GDI_OBJECT_TYPE_DC:
1545 result = OBJ_DC;
1546 break;
1547 case GDI_OBJECT_TYPE_METADC:
1548 result = OBJ_METADC;
1549 break;
1550 case GDI_OBJECT_TYPE_METAFILE:
1551 result = OBJ_METAFILE;
1552 break;
1553 case GDI_OBJECT_TYPE_ENHMETAFILE:
1554 result = OBJ_ENHMETAFILE;
1555 break;
1556 case GDI_OBJECT_TYPE_ENHMETADC:
1557 result = OBJ_ENHMETADC;
1558 break;
1559 case GDI_OBJECT_TYPE_EXTPEN:
1560 result = OBJ_EXTPEN;
1561 break;
1562 case GDI_OBJECT_TYPE_MEMDC:
1563 result = OBJ_MEMDC;
1564 break;
1565 default:
1566 DPRINT1("Magic 0x%08x not implemented\n", objectType);
1567 break;
1568 }
1569 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1570 return result;
1571 }
1572
1573 DC_GET_VAL( INT, NtGdiGetRelAbs, w.relAbsMode )
1574 DC_GET_VAL( INT, NtGdiGetROP2, w.ROPmode )
1575 DC_GET_VAL( INT, NtGdiGetStretchBltMode, w.stretchBltMode )
1576 DC_GET_VAL( UINT, NtGdiGetTextAlign, w.textAlign )
1577 DC_GET_VAL( COLORREF, NtGdiGetTextColor, w.textColor )
1578 DC_GET_VAL_EX( NtGdiGetViewportExtEx, IntGetViewportExtEx, vportExtX, vportExtY, SIZE )
1579 DC_GET_VAL_EX( NtGdiGetViewportOrgEx, IntGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
1580 DC_GET_VAL_EX( NtGdiGetWindowExtEx, IntGetWindowExtEx, wndExtX, wndExtY, SIZE )
1581 DC_GET_VAL_EX( NtGdiGetWindowOrgEx, IntGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
1582
1583 HDC STDCALL
1584 NtGdiResetDC(HDC hDC, CONST DEVMODEW *InitData)
1585 {
1586 UNIMPLEMENTED;
1587 }
1588
1589 BOOL STDCALL
1590 NtGdiRestoreDC(HDC hDC, INT SaveLevel)
1591 {
1592 PDC dc, dcs;
1593 BOOL success;
1594
1595 dc = DC_LockDc(hDC);
1596 if(!dc)
1597 {
1598 return FALSE;
1599 }
1600
1601 if (SaveLevel == -1)
1602 {
1603 SaveLevel = dc->saveLevel;
1604 }
1605
1606 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
1607 {
1608 return FALSE;
1609 }
1610
1611 success = TRUE;
1612 while (dc->saveLevel >= SaveLevel)
1613 {
1614 HDC hdcs = DC_GetNextDC (dc);
1615
1616 dcs = DC_LockDc (hdcs);
1617 if (dcs == NULL)
1618 {
1619 return FALSE;
1620 }
1621 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
1622 if (--dc->saveLevel < SaveLevel)
1623 {
1624 DC_UnlockDc( hDC );
1625 DC_UnlockDc( hdcs );
1626 NtGdiSetDCState(hDC, hdcs);
1627 #if 0
1628 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
1629 {
1630 /* FIXME: This might not be quite right, since we're
1631 * returning FALSE but still destroying the saved DC state */
1632 success = FALSE;
1633 }
1634 #endif
1635 dc = DC_LockDc(hDC);
1636 if(!dc)
1637 {
1638 return FALSE;
1639 }
1640 }
1641 else
1642 {
1643 DC_UnlockDc( hdcs );
1644 }
1645 NtGdiDeleteDC (hdcs);
1646 }
1647 DC_UnlockDc( hDC );
1648 return success;
1649 }
1650
1651 INT STDCALL
1652 NtGdiSaveDC(HDC hDC)
1653 {
1654 HDC hdcs;
1655 PDC dc, dcs;
1656 INT ret;
1657
1658 if (!(hdcs = NtGdiGetDCState(hDC)))
1659 {
1660 return 0;
1661 }
1662
1663 dcs = DC_LockDc (hdcs);
1664 if (dcs == NULL)
1665 {
1666 return 0;
1667 }
1668 dc = DC_LockDc (hDC);
1669 if (dc == NULL)
1670 {
1671 DC_UnlockDc(dc);
1672 return 0;
1673 }
1674
1675 #if 0
1676 /* Copy path. The reason why path saving / restoring is in SaveDC/
1677 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1678 * functions are only in Win16 (which doesn't have paths) and that
1679 * SetDCState doesn't allow us to signal an error (which can happen
1680 * when copying paths).
1681 */
1682 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1683 {
1684 NtGdiDeleteDC (hdcs);
1685 return 0;
1686 }
1687 #endif
1688
1689 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1690 DC_SetNextDC (dc, hdcs);
1691 ret = ++dc->saveLevel;
1692 DC_UnlockDc( hdcs );
1693 DC_UnlockDc( hDC );
1694
1695 return ret;
1696 }
1697
1698 HGDIOBJ
1699 STDCALL
1700 NtGdiSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1701 {
1702 HGDIOBJ objOrg = NULL; // default to failure
1703 BITMAPOBJ *pb;
1704 PDC dc;
1705 PPENOBJ pen;
1706 PBRUSHOBJ brush;
1707 PXLATEOBJ XlateObj;
1708 PPALGDI PalGDI;
1709 DWORD objectType;
1710 COLORREF *ColorMap;
1711 COLORREF MonoColorMap[2];
1712 ULONG NumColors, Index;
1713 HRGN hVisRgn;
1714 USHORT Mode;
1715
1716 if(!hDC || !hGDIObj) return NULL;
1717
1718 dc = DC_LockDc(hDC);
1719 if (NULL == dc)
1720 {
1721 SetLastWin32Error(ERROR_INVALID_HANDLE);
1722 return NULL;
1723 }
1724
1725 objectType = GDIOBJ_GetObjectType(hGDIObj);
1726
1727 switch (objectType)
1728 {
1729 case GDI_OBJECT_TYPE_PEN:
1730 objOrg = NULL;
1731 /* Convert the color of the pen to the format of the DC */
1732 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1733 if (NULL != PalGDI)
1734 {
1735 Mode = PalGDI->Mode;
1736 PALETTE_UnlockPalette(dc->w.hPalette);
1737 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1738 if (NULL != XlateObj)
1739 {
1740 pen = PENOBJ_LockPen((HPEN) hGDIObj);
1741 if (NULL != pen)
1742 {
1743 pen->iSolidColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1744 PENOBJ_UnlockPen((HPEN) hGDIObj);
1745 objOrg = (HGDIOBJ)dc->w.hPen;
1746 dc->w.hPen = hGDIObj;
1747 }
1748 else
1749 {
1750 SetLastWin32Error(ERROR_INVALID_HANDLE);
1751 }
1752 EngDeleteXlate(XlateObj);
1753 }
1754 else
1755 {
1756 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1757 }
1758 }
1759 else
1760 {
1761 SetLastWin32Error(ERROR_INVALID_HANDLE);
1762 }
1763 break;
1764
1765 case GDI_OBJECT_TYPE_BRUSH:
1766 objOrg = NULL;
1767 /* Convert the color of the brush to the format of the DC */
1768 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1769 if (NULL != PalGDI)
1770 {
1771 Mode = PalGDI->Mode;
1772 PALETTE_UnlockPalette(dc->w.hPalette);
1773 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1774 if (NULL != XlateObj)
1775 {
1776 brush = BRUSHOBJ_LockBrush((HBRUSH) hGDIObj);
1777 if (NULL != brush)
1778 {
1779 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1780 BRUSHOBJ_UnlockBrush((HBRUSH) hGDIObj);
1781 objOrg = (HGDIOBJ)dc->w.hBrush;
1782 dc->w.hBrush = (HBRUSH) hGDIObj;
1783 }
1784 else
1785 {
1786 SetLastWin32Error(ERROR_INVALID_HANDLE);
1787 }
1788 EngDeleteXlate(XlateObj);
1789 }
1790 else
1791 {
1792 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1793 }
1794 }
1795 else
1796 {
1797 SetLastWin32Error(ERROR_INVALID_HANDLE);
1798 }
1799 break;
1800
1801 case GDI_OBJECT_TYPE_FONT:
1802 objOrg = (HGDIOBJ)dc->w.hFont;
1803 dc->w.hFont = (HFONT) hGDIObj;
1804 TextIntRealizeFont(dc->w.hFont);
1805 break;
1806
1807 case GDI_OBJECT_TYPE_BITMAP:
1808 // must be memory dc to select bitmap
1809 if (!(dc->w.flags & DC_MEMORY))
1810 {
1811 DC_UnlockDc(hDC);
1812 return NULL;
1813 }
1814 pb = BITMAPOBJ_LockBitmap(hGDIObj);
1815 if (NULL == pb)
1816 {
1817 SetLastWin32Error(ERROR_INVALID_HANDLE);
1818 DC_UnlockDc(hDC);
1819 return NULL;
1820 }
1821 objOrg = (HGDIOBJ)dc->w.hBitmap;
1822
1823 /* Release the old bitmap, lock the new one and convert it to a SURF */
1824 EngDeleteSurface(dc->Surface);
1825 dc->w.hBitmap = hGDIObj;
1826 dc->Surface = BitmapToSurf(pb, dc->GDIDevice);
1827
1828 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1829 if(pb->dib)
1830 {
1831 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1832
1833 if(pb->dib->dsBmih.biBitCount <= 8)
1834 {
1835 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1836 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1837 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1838
1839 ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(COLORREF) * NumColors, TAG_DC);
1840 ASSERT(ColorMap);
1841 for (Index = 0; Index < NumColors; Index++)
1842 {
1843 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1844 pb->ColorMap[Index].rgbGreen,
1845 pb->ColorMap[Index].rgbBlue);
1846 }
1847 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1848 ExFreePool(ColorMap);
1849 }
1850 else if ( 16 == pb->dib->dsBmih.biBitCount )
1851 {
1852 dc->w.hPalette = PALETTE_AllocPalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1853 }
1854 else if(pb->dib->dsBmih.biBitCount >= 24)
1855 {
1856 dc->w.hPalette = PALETTE_AllocPalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1857 }
1858 }
1859 else
1860 {
1861 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1862 if (1 == dc->w.bitsPerPixel)
1863 {
1864 MonoColorMap[0] = RGB(0, 0, 0);
1865 MonoColorMap[1] = RGB(255, 255, 255);
1866 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, 2, MonoColorMap, 0, 0, 0);
1867 }
1868 else
1869 {
1870 dc->w.hPalette = dc->DevInfo->hpalDefault;
1871 }
1872 }
1873
1874 DC_UnlockDc ( hDC );
1875 hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->bitmap.bmWidth, pb->bitmap.bmHeight );
1876 NtGdiSelectVisRgn ( hDC, hVisRgn );
1877 NtGdiDeleteObject ( hVisRgn );
1878 BITMAPOBJ_UnlockBitmap(hGDIObj);
1879
1880 return objOrg;
1881
1882 #if UPDATEREGIONS
1883 case GDI_OBJECT_TYPE_REGION:
1884 DC_UnlockDc ( hDC );
1885 SelectClipRgn(hDC, (HRGN)hGDIObj);
1886 return NULL;
1887 #endif
1888 default:
1889 break;
1890 }
1891 DC_UnlockDc( hDC );
1892 return objOrg;
1893 }
1894
1895 WORD STDCALL
1896 NtGdiSetHookFlags(HDC hDC, WORD Flags)
1897 {
1898 WORD wRet;
1899 DC *dc = DC_LockDc(hDC);
1900
1901 if (NULL == dc)
1902 {
1903 return 0;
1904 }
1905
1906 wRet = dc->w.flags & DC_DIRTY;
1907
1908 /* "Undocumented Windows" info is slightly confusing.
1909 */
1910
1911 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
1912
1913 if (Flags & DCHF_INVALIDATEVISRGN)
1914 {
1915 dc->w.flags |= DC_DIRTY;
1916 }
1917 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
1918 {
1919 dc->w.flags &= ~DC_DIRTY;
1920 }
1921
1922 DC_UnlockDc(hDC);
1923
1924 return wRet;
1925 }
1926
1927 DC_SET_MODE( NtGdiSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1928 DC_SET_MODE( NtGdiSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1929 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1930 DC_SET_MODE( NtGdiSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1931 DC_SET_MODE( NtGdiSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1932
1933 // ---------------------------------------------------- Private Interface
1934
1935 HDC FASTCALL
1936 DC_AllocDC(PUNICODE_STRING Driver)
1937 {
1938 PDC NewDC;
1939 HDC hDC;
1940 PWSTR Buf = NULL;
1941
1942 if (Driver != NULL)
1943 {
1944 Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
1945 if(!Buf)
1946 {
1947 return NULL;
1948 }
1949 RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
1950 }
1951
1952 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GDI_OBJECT_TYPE_DC, (GDICLEANUPPROC) DC_InternalDeleteDC);
1953 if (hDC == NULL)
1954 {
1955 if(Buf)
1956 {
1957 ExFreePool(Buf);
1958 }
1959 return NULL;
1960 }
1961
1962 NewDC = DC_LockDc(hDC);
1963
1964 if (Driver != NULL)
1965 {
1966 RtlCopyMemory(&NewDC->DriverName, Driver, sizeof(UNICODE_STRING));
1967 NewDC->DriverName.Buffer = Buf;
1968 }
1969
1970 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1971 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1972 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1973 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1974 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1975 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1976 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1977 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1978 NewDC->w.vport2WorldValid = TRUE;
1979 NewDC->w.MapMode = MM_TEXT;
1980
1981 NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
1982 TextIntRealizeFont(NewDC->w.hFont);
1983
1984 DC_UnlockDc(hDC);
1985
1986 return hDC;
1987 }
1988
1989 HDC FASTCALL
1990 DC_FindOpenDC(PUNICODE_STRING Driver)
1991 {
1992 return NULL;
1993 }
1994
1995 /*!
1996 * Initialize some common fields in the Device Context structure.
1997 */
1998 VOID FASTCALL
1999 DC_InitDC(HDC DCHandle)
2000 {
2001 // NtGdiRealizeDefaultPalette(DCHandle);
2002
2003 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
2004 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
2005 //NtGdiSelectObject(DCHandle, hFont);
2006
2007 // CLIPPING_UpdateGCRegion(DCToInit);
2008
2009 }
2010
2011 VOID FASTCALL
2012 DC_FreeDC(HDC DCToFree)
2013 {
2014 if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC, GDIOBJFLAG_DEFAULT))
2015 {
2016 DPRINT("DC_FreeDC failed\n");
2017 }
2018 }
2019
2020 BOOL FASTCALL
2021 DC_InternalDeleteDC( PDC DCToDelete )
2022 {
2023
2024 RtlFreeUnicodeString(&DCToDelete->DriverName);
2025 return TRUE;
2026 }
2027
2028 HDC FASTCALL
2029 DC_GetNextDC (PDC pDC)
2030 {
2031 return pDC->hNext;
2032 }
2033
2034 VOID FASTCALL
2035 DC_SetNextDC (PDC pDC, HDC hNextDC)
2036 {
2037 pDC->hNext = hNextDC;
2038 }
2039
2040 VOID FASTCALL
2041 DC_UpdateXforms(PDC dc)
2042 {
2043 XFORM xformWnd2Vport;
2044 FLOAT scaleX, scaleY;
2045
2046 /* Construct a transformation to do the window-to-viewport conversion */
2047 scaleX = (dc->wndExtX ? (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX : 0.0);
2048 scaleY = (dc->wndExtY ? (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY : 0.0);
2049 xformWnd2Vport.eM11 = scaleX;
2050 xformWnd2Vport.eM12 = 0.0;
2051 xformWnd2Vport.eM21 = 0.0;
2052 xformWnd2Vport.eM22 = scaleY;
2053 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
2054 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
2055
2056 /* Combine with the world transformation */
2057 IntGdiCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
2058
2059 /* Create inverse of world-to-viewport transformation */
2060 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
2061 }
2062
2063 BOOL FASTCALL
2064 DC_InvertXform(const XFORM *xformSrc,
2065 XFORM *xformDest)
2066 {
2067 FLOAT determinant;
2068
2069 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
2070 if (determinant > -1e-12 && determinant < 1e-12)
2071 {
2072 return FALSE;
2073 }
2074
2075 xformDest->eM11 = xformSrc->eM22 / determinant;
2076 xformDest->eM12 = -xformSrc->eM12 / determinant;
2077 xformDest->eM21 = -xformSrc->eM21 / determinant;
2078 xformDest->eM22 = xformSrc->eM11 / determinant;
2079 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
2080 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
2081
2082 return TRUE;
2083 }
2084
2085 VOID FASTCALL
2086 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
2087 {
2088 PDC DC;
2089
2090 GDIOBJ_SetOwnership(hDC, Owner);
2091 DC = DC_LockDc(hDC);
2092 if (NULL != DC)
2093 {
2094 if (NULL != DC->w.hClipRgn)
2095 {
2096 GDIOBJ_CopyOwnership(hDC, DC->w.hClipRgn);
2097 }
2098 if (NULL != DC->w.hVisRgn)
2099 {
2100 GDIOBJ_CopyOwnership(hDC, DC->w.hVisRgn);
2101 }
2102 if (NULL != DC->w.hGCClipRgn)
2103 {
2104 GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
2105 }
2106 DC_UnlockDc(hDC);
2107 }
2108 }
2109
2110 BOOL FASTCALL
2111 IntIsPrimarSurface(PSURFGDI SurfGDI)
2112 {
2113 if (PrimarySurface.Handle == NULL)
2114 {
2115 return FALSE;
2116 }
2117 return SurfGDI == (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle) ? TRUE : FALSE;
2118 }
2119
2120 /* EOF */