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