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