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