- Fix ExtSelectClipRgn and some other clipping functions.
[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.135 2004/05/14 16:55:18 navaraf 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)AccessInternalObject((ULONG) PrimarySurface.Handle);
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)AccessInternalObject((ULONG) PrimarySurface.Handle);
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(NonPagedPool, 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 *ColorMap;
1753 COLORREF MonoColorMap[2];
1754 ULONG NumColors, Index;
1755 HRGN hVisRgn;
1756 USHORT Mode;
1757
1758 if(!hDC || !hGDIObj) return NULL;
1759
1760 dc = DC_LockDc(hDC);
1761 if (NULL == dc)
1762 {
1763 SetLastWin32Error(ERROR_INVALID_HANDLE);
1764 return NULL;
1765 }
1766
1767 objectType = GDIOBJ_GetObjectType(hGDIObj);
1768
1769 switch (objectType)
1770 {
1771 case GDI_OBJECT_TYPE_PEN:
1772 objOrg = NULL;
1773 /* Convert the color of the pen to the format of the DC */
1774 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1775 if (NULL != PalGDI)
1776 {
1777 Mode = PalGDI->Mode;
1778 PALETTE_UnlockPalette(dc->w.hPalette);
1779 XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1780 if (NULL != XlateObj)
1781 {
1782 pen = PENOBJ_LockPen((HPEN) hGDIObj);
1783 if (NULL != pen)
1784 {
1785 if (pen->flAttrs & GDIBRUSH_IS_SOLID)
1786 {
1787 pen->BrushObject.iSolidColor =
1788 XLATEOBJ_iXlate(XlateObj, pen->BrushAttr.lbColor);
1789 }
1790 else
1791 {
1792 pen->BrushObject.iSolidColor = 0xFFFFFFFF;
1793 }
1794 pen->crBack = XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor);
1795 pen->crFore = XLATEOBJ_iXlate(XlateObj, dc->w.textColor);
1796 PENOBJ_UnlockPen((HPEN) hGDIObj);
1797 objOrg = (HGDIOBJ)dc->w.hPen;
1798 dc->w.hPen = hGDIObj;
1799 }
1800 else
1801 {
1802 SetLastWin32Error(ERROR_INVALID_HANDLE);
1803 }
1804 EngDeleteXlate(XlateObj);
1805 }
1806 else
1807 {
1808 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1809 }
1810 }
1811 else
1812 {
1813 SetLastWin32Error(ERROR_INVALID_HANDLE);
1814 }
1815 break;
1816
1817 case GDI_OBJECT_TYPE_BRUSH:
1818 objOrg = NULL;
1819 /* Convert the color of the brush to the format of the DC */
1820 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1821 if (NULL != PalGDI)
1822 {
1823 Mode = PalGDI->Mode;
1824 PALETTE_UnlockPalette(dc->w.hPalette);
1825 XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1826 if (NULL != XlateObj)
1827 {
1828 brush = BRUSHOBJ_LockBrush((HBRUSH) hGDIObj);
1829 if (NULL != brush)
1830 {
1831 if (brush->flAttrs & GDIBRUSH_IS_SOLID)
1832 {
1833 brush->BrushObject.iSolidColor =
1834 XLATEOBJ_iXlate(XlateObj, brush->BrushAttr.lbColor);
1835 }
1836 else
1837 {
1838 brush->BrushObject.iSolidColor = 0xFFFFFFFF;
1839 }
1840 brush->crBack = XLATEOBJ_iXlate(XlateObj, dc->w.backgroundColor);
1841 brush->crFore = XLATEOBJ_iXlate(XlateObj, ((brush->flAttrs & GDIBRUSH_IS_HATCH) ?
1842 brush->BrushAttr.lbColor : dc->w.textColor));
1843 /* according to the documentation of SetBrushOrgEx(), the origin is assigned to the
1844 next brush selected into the DC, so we should set it here */
1845 brush->ptOrigin.x = dc->w.brushOrgX;
1846 brush->ptOrigin.y = dc->w.brushOrgY;
1847
1848 BRUSHOBJ_UnlockBrush((HBRUSH) hGDIObj);
1849 objOrg = (HGDIOBJ)dc->w.hBrush;
1850 dc->w.hBrush = (HBRUSH) hGDIObj;
1851 }
1852 else
1853 {
1854 SetLastWin32Error(ERROR_INVALID_HANDLE);
1855 }
1856 EngDeleteXlate(XlateObj);
1857 }
1858 else
1859 {
1860 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1861 }
1862 }
1863 else
1864 {
1865 SetLastWin32Error(ERROR_INVALID_HANDLE);
1866 }
1867 break;
1868
1869 case GDI_OBJECT_TYPE_FONT:
1870 objOrg = (HGDIOBJ)dc->w.hFont;
1871 dc->w.hFont = (HFONT) hGDIObj;
1872 TextIntRealizeFont(dc->w.hFont);
1873 break;
1874
1875 case GDI_OBJECT_TYPE_BITMAP:
1876 // must be memory dc to select bitmap
1877 if (!(dc->w.flags & DC_MEMORY))
1878 {
1879 DC_UnlockDc(hDC);
1880 return NULL;
1881 }
1882 pb = BITMAPOBJ_LockBitmap(hGDIObj);
1883 if (NULL == pb)
1884 {
1885 SetLastWin32Error(ERROR_INVALID_HANDLE);
1886 DC_UnlockDc(hDC);
1887 return NULL;
1888 }
1889 objOrg = (HGDIOBJ)dc->w.hBitmap;
1890
1891 /* Release the old bitmap, lock the new one and convert it to a SURF */
1892 EngDeleteSurface(dc->Surface);
1893 dc->w.hBitmap = hGDIObj;
1894 dc->Surface = (HSURF)BitmapToSurf(pb, dc->GDIDevice);
1895
1896 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1897 if(pb->dib)
1898 {
1899 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1900
1901 if(pb->dib->dsBmih.biBitCount <= 8)
1902 {
1903 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1904 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1905 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1906
1907 ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(COLORREF) * NumColors, TAG_DC);
1908 ASSERT(ColorMap);
1909 for (Index = 0; Index < NumColors; Index++)
1910 {
1911 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1912 pb->ColorMap[Index].rgbGreen,
1913 pb->ColorMap[Index].rgbBlue);
1914 }
1915 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1916 ExFreePool(ColorMap);
1917 }
1918 else if ( 16 == pb->dib->dsBmih.biBitCount )
1919 {
1920 dc->w.hPalette = PALETTE_AllocPalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1921 }
1922 else if(pb->dib->dsBmih.biBitCount >= 24)
1923 {
1924 dc->w.hPalette = PALETTE_AllocPalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1925 }
1926 }
1927 else
1928 {
1929 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1930 if (1 == dc->w.bitsPerPixel)
1931 {
1932 MonoColorMap[0] = RGB(0, 0, 0);
1933 MonoColorMap[1] = RGB(255, 255, 255);
1934 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, 2, MonoColorMap, 0, 0, 0);
1935 }
1936 else
1937 {
1938 dc->w.hPalette = dc->DevInfo->hpalDefault;
1939 }
1940 }
1941
1942 DC_UnlockDc ( hDC );
1943 hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->bitmap.bmWidth, pb->bitmap.bmHeight );
1944 NtGdiSelectVisRgn ( hDC, hVisRgn );
1945 NtGdiDeleteObject ( hVisRgn );
1946 BITMAPOBJ_UnlockBitmap(hGDIObj);
1947
1948 return objOrg;
1949
1950 case GDI_OBJECT_TYPE_REGION:
1951 DC_UnlockDc (hDC);
1952 return (HGDIOBJ) NtGdiSelectClipRgn(hDC, (HRGN) hGDIObj);
1953
1954 default:
1955 break;
1956 }
1957 DC_UnlockDc( hDC );
1958 return objOrg;
1959 }
1960
1961 WORD STDCALL
1962 NtGdiSetHookFlags(HDC hDC, WORD Flags)
1963 {
1964 WORD wRet;
1965 DC *dc = DC_LockDc(hDC);
1966
1967 if (NULL == dc)
1968 {
1969 SetLastWin32Error(ERROR_INVALID_HANDLE);
1970 return 0;
1971 }
1972
1973 wRet = dc->w.flags & DC_DIRTY;
1974
1975 /* "Undocumented Windows" info is slightly confusing.
1976 */
1977
1978 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
1979
1980 if (Flags & DCHF_INVALIDATEVISRGN)
1981 {
1982 dc->w.flags |= DC_DIRTY;
1983 }
1984 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
1985 {
1986 dc->w.flags &= ~DC_DIRTY;
1987 }
1988
1989 DC_UnlockDc(hDC);
1990
1991 return wRet;
1992 }
1993
1994 DC_SET_MODE( NtGdiSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1995 DC_SET_MODE( NtGdiSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1996 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1997 DC_SET_MODE( NtGdiSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1998 DC_SET_MODE( NtGdiSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1999
2000 // ---------------------------------------------------- Private Interface
2001
2002 HDC FASTCALL
2003 DC_AllocDC(PUNICODE_STRING Driver)
2004 {
2005 PDC NewDC;
2006 HDC hDC;
2007 PWSTR Buf = NULL;
2008
2009 if (Driver != NULL)
2010 {
2011 Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
2012 if(!Buf)
2013 {
2014 return NULL;
2015 }
2016 RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
2017 }
2018
2019 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GDI_OBJECT_TYPE_DC, (GDICLEANUPPROC) DC_InternalDeleteDC);
2020 if (hDC == NULL)
2021 {
2022 if(Buf)
2023 {
2024 ExFreePool(Buf);
2025 }
2026 return NULL;
2027 }
2028
2029 NewDC = DC_LockDc(hDC);
2030
2031 if (Driver != NULL)
2032 {
2033 RtlCopyMemory(&NewDC->DriverName, Driver, sizeof(UNICODE_STRING));
2034 NewDC->DriverName.Buffer = Buf;
2035 }
2036
2037 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
2038 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
2039 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
2040 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
2041 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
2042 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
2043 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
2044 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
2045 NewDC->w.vport2WorldValid = TRUE;
2046 NewDC->w.MapMode = MM_TEXT;
2047
2048 NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
2049 TextIntRealizeFont(NewDC->w.hFont);
2050
2051 NewDC->w.hPalette = NtGdiGetStockObject(DEFAULT_PALETTE);
2052
2053 DC_UnlockDc(hDC);
2054
2055 return hDC;
2056 }
2057
2058 HDC FASTCALL
2059 DC_FindOpenDC(PUNICODE_STRING Driver)
2060 {
2061 return NULL;
2062 }
2063
2064 /*!
2065 * Initialize some common fields in the Device Context structure.
2066 */
2067 VOID FASTCALL
2068 DC_InitDC(HDC DCHandle)
2069 {
2070 // NtGdiRealizeDefaultPalette(DCHandle);
2071
2072 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
2073 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
2074 //NtGdiSelectObject(DCHandle, hFont);
2075
2076 // CLIPPING_UpdateGCRegion(DCToInit);
2077
2078 }
2079
2080 VOID FASTCALL
2081 DC_FreeDC(HDC DCToFree)
2082 {
2083 if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC, GDIOBJFLAG_DEFAULT))
2084 {
2085 DPRINT("DC_FreeDC failed\n");
2086 }
2087 }
2088
2089 BOOL FASTCALL
2090 DC_InternalDeleteDC( PDC DCToDelete )
2091 {
2092
2093 RtlFreeUnicodeString(&DCToDelete->DriverName);
2094 return TRUE;
2095 }
2096
2097 HDC FASTCALL
2098 DC_GetNextDC (PDC pDC)
2099 {
2100 return pDC->hNext;
2101 }
2102
2103 VOID FASTCALL
2104 DC_SetNextDC (PDC pDC, HDC hNextDC)
2105 {
2106 pDC->hNext = hNextDC;
2107 }
2108
2109 VOID FASTCALL
2110 DC_UpdateXforms(PDC dc)
2111 {
2112 XFORM xformWnd2Vport;
2113 FLOAT scaleX, scaleY;
2114
2115 /* Construct a transformation to do the window-to-viewport conversion */
2116 scaleX = (dc->wndExtX ? (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX : 0.0);
2117 scaleY = (dc->wndExtY ? (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY : 0.0);
2118 xformWnd2Vport.eM11 = scaleX;
2119 xformWnd2Vport.eM12 = 0.0;
2120 xformWnd2Vport.eM21 = 0.0;
2121 xformWnd2Vport.eM22 = scaleY;
2122 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
2123 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
2124
2125 /* Combine with the world transformation */
2126 IntGdiCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
2127
2128 /* Create inverse of world-to-viewport transformation */
2129 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
2130 }
2131
2132 BOOL FASTCALL
2133 DC_InvertXform(const XFORM *xformSrc,
2134 XFORM *xformDest)
2135 {
2136 FLOAT determinant;
2137
2138 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
2139 if (determinant > -1e-12 && determinant < 1e-12)
2140 {
2141 return FALSE;
2142 }
2143
2144 xformDest->eM11 = xformSrc->eM22 / determinant;
2145 xformDest->eM12 = -xformSrc->eM12 / determinant;
2146 xformDest->eM21 = -xformSrc->eM21 / determinant;
2147 xformDest->eM22 = xformSrc->eM11 / determinant;
2148 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
2149 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
2150
2151 return TRUE;
2152 }
2153
2154 VOID FASTCALL
2155 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
2156 {
2157 PDC DC;
2158
2159 GDIOBJ_SetOwnership(hDC, Owner);
2160 DC = DC_LockDc(hDC);
2161 if (NULL != DC)
2162 {
2163 if (NULL != DC->w.hClipRgn)
2164 {
2165 GDIOBJ_CopyOwnership(hDC, DC->w.hClipRgn);
2166 }
2167 if (NULL != DC->w.hVisRgn)
2168 {
2169 GDIOBJ_CopyOwnership(hDC, DC->w.hVisRgn);
2170 }
2171 if (NULL != DC->w.hGCClipRgn)
2172 {
2173 GDIOBJ_CopyOwnership(hDC, DC->w.hGCClipRgn);
2174 }
2175 DC_UnlockDc(hDC);
2176 }
2177 }
2178
2179 BOOL FASTCALL
2180 IntIsPrimarySurface(PSURFGDI SurfGDI)
2181 {
2182 if (PrimarySurface.Handle == NULL)
2183 {
2184 return FALSE;
2185 }
2186 return SurfGDI == (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle) ? TRUE : FALSE;
2187 }
2188
2189 /*
2190 * Returns the color of the brush or pen that is currently selected into the DC.
2191 * This function is called from GetDCBrushColor() and GetDCPenColor()
2192 */
2193 COLORREF FASTCALL
2194 IntGetDCColor(HDC hDC, ULONG Object)
2195 {
2196 COLORREF Result;
2197 DC *dc;
2198 PPALGDI PalGDI;
2199 PGDIBRUSHOBJ pen;
2200 PGDIBRUSHOBJ brush;
2201 XLATEOBJ *XlateObj;
2202 HPALETTE Pal;
2203 USHORT Mode;
2204 ULONG iColor;
2205
2206 if(!(dc = DC_LockDc(hDC)))
2207 {
2208 SetLastWin32Error(ERROR_INVALID_HANDLE);
2209 return CLR_INVALID;
2210 }
2211
2212 switch(Object)
2213 {
2214 case OBJ_PEN:
2215 {
2216 if(!(pen = PENOBJ_LockPen(dc->w.hPen)))
2217 {
2218 DC_UnlockDc(hDC);
2219 return CLR_INVALID;
2220 }
2221 if(!(pen->flAttrs & GDIBRUSH_IS_SOLID))
2222 {
2223 /* FIXME - just bail here? */
2224 PENOBJ_UnlockPen(dc->w.hPen);
2225 DC_UnlockDc(hDC);
2226 return CLR_INVALID;
2227 }
2228 iColor = pen->BrushObject.iSolidColor;
2229 PENOBJ_UnlockPen(dc->w.hPen);
2230 break;
2231 }
2232 case OBJ_BRUSH:
2233 {
2234 if(!(brush = BRUSHOBJ_LockBrush(dc->w.hBrush)))
2235 {
2236 DC_UnlockDc(hDC);
2237 return CLR_INVALID;
2238 }
2239 if(!(brush->flAttrs & GDIBRUSH_IS_SOLID))
2240 {
2241 /* FIXME - just bail here? */
2242 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
2243 DC_UnlockDc(hDC);
2244 return CLR_INVALID;
2245 }
2246 iColor = brush->BrushObject.iSolidColor;
2247 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
2248 break;
2249 }
2250 default:
2251 {
2252 DC_UnlockDc(hDC);
2253 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2254 return CLR_INVALID;
2255 }
2256 }
2257
2258 /* translate the color into RGB */
2259
2260 if(dc->w.hPalette)
2261 Pal = dc->w.hPalette;
2262
2263 Result = CLR_INVALID;
2264
2265 if((PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
2266 {
2267 Mode = PalGDI->Mode;
2268 PALETTE_UnlockPalette(dc->w.hPalette);
2269 XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, Pal);
2270 if(XlateObj)
2271 {
2272 Result = XLATEOBJ_iXlate(XlateObj, iColor);
2273 EngDeleteXlate(XlateObj);
2274 }
2275 }
2276
2277 DC_UnlockDc(hDC);
2278 return Result;
2279 }
2280
2281 /*
2282 * Changes the color of the brush or pen that is currently selected into the DC.
2283 * This function is called from SetDCBrushColor() and SetDCPenColor()
2284 */
2285 COLORREF FASTCALL
2286 IntSetDCColor(HDC hDC, ULONG Object, COLORREF Color)
2287 {
2288 COLORREF Result;
2289 DC *dc;
2290 PPALGDI PalGDI;
2291 PGDIBRUSHOBJ pen;
2292 PGDIBRUSHOBJ brush;
2293 XLATEOBJ *XlateObj;
2294 HPALETTE Pal;
2295 USHORT Mode;
2296 ULONG iColor;
2297
2298 if(Color == CLR_INVALID)
2299 {
2300 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2301 return CLR_INVALID;
2302 }
2303
2304 if(!(dc = DC_LockDc(hDC)))
2305 {
2306 SetLastWin32Error(ERROR_INVALID_HANDLE);
2307 return CLR_INVALID;
2308 }
2309
2310 switch(Object)
2311 {
2312 case OBJ_PEN:
2313 {
2314 if(!(pen = PENOBJ_LockPen(dc->w.hPen)))
2315 {
2316 DC_UnlockDc(hDC);
2317 return CLR_INVALID;
2318 }
2319 if(!(pen->flAttrs & GDIBRUSH_IS_SOLID))
2320 {
2321 /* FIXME - just bail here? */
2322 PENOBJ_UnlockPen(dc->w.hPen);
2323 DC_UnlockDc(hDC);
2324 return CLR_INVALID;
2325 }
2326
2327 /* save old color index, translate it to RGB later */
2328 iColor = pen->BrushObject.iSolidColor;
2329
2330 if(!(PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
2331 {
2332 PENOBJ_UnlockPen(dc->w.hPen);
2333 DC_UnlockDc(hDC);
2334 return CLR_INVALID;
2335 }
2336 Mode = PalGDI->Mode;
2337 PALETTE_UnlockPalette(dc->w.hPalette);
2338 if(!(XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL)))
2339 {
2340 PENOBJ_UnlockPen(dc->w.hPen);
2341 DC_UnlockDc(hDC);
2342 return CLR_INVALID;
2343 }
2344 pen->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, (ULONG)Color);
2345 EngDeleteXlate(XlateObj);
2346 PENOBJ_UnlockPen(dc->w.hPen);
2347 break;
2348 }
2349 case OBJ_BRUSH:
2350 {
2351 if(!(brush = BRUSHOBJ_LockBrush(dc->w.hBrush)))
2352 {
2353 DC_UnlockDc(hDC);
2354 return CLR_INVALID;
2355 }
2356 if(!(brush->flAttrs & GDIBRUSH_IS_SOLID))
2357 {
2358 /* FIXME - just bail here? */
2359 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
2360 DC_UnlockDc(hDC);
2361 return CLR_INVALID;
2362 }
2363
2364 /* save old color index, translate it to RGB later */
2365 iColor = brush->BrushObject.iSolidColor;
2366
2367 if(!(PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
2368 {
2369 PENOBJ_UnlockPen(dc->w.hPen);
2370 DC_UnlockDc(hDC);
2371 return CLR_INVALID;
2372 }
2373 Mode = PalGDI->Mode;
2374 PALETTE_UnlockPalette(dc->w.hPalette);
2375 if(!(XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL)))
2376 {
2377 PENOBJ_UnlockPen(dc->w.hPen);
2378 DC_UnlockDc(hDC);
2379 return CLR_INVALID;
2380 }
2381 brush->BrushObject.iSolidColor = XLATEOBJ_iXlate(XlateObj, (ULONG)Color);
2382 EngDeleteXlate(XlateObj);
2383 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
2384 break;
2385 }
2386 default:
2387 {
2388 DC_UnlockDc(hDC);
2389 SetLastWin32Error(ERROR_INVALID_PARAMETER);
2390 return CLR_INVALID;
2391 }
2392 }
2393
2394 /* translate the old color into RGB */
2395
2396 if(dc->w.hPalette)
2397 Pal = dc->w.hPalette;
2398
2399 Result = CLR_INVALID;
2400
2401 if((PalGDI = PALETTE_LockPalette(dc->w.hPalette)))
2402 {
2403 Mode = PalGDI->Mode;
2404 PALETTE_UnlockPalette(dc->w.hPalette);
2405 XlateObj = (XLATEOBJ*)IntEngCreateXlate(PAL_RGB, Mode, NULL, Pal);
2406 if(XlateObj)
2407 {
2408 Result = XLATEOBJ_iXlate(XlateObj, iColor);
2409 EngDeleteXlate(XlateObj);
2410 }
2411 }
2412
2413 DC_UnlockDc(hDC);
2414 return Result;
2415 }
2416
2417 /* EOF */