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