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