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