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