[GDI32]
[reactos.git] / reactos / win32ss / gdi / gdi32 / objects / dc.c
1 #include <precomp.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 HDC
7 FASTCALL
8 IntCreateDICW(
9 LPCWSTR lpwszDriver,
10 LPCWSTR lpwszDevice,
11 LPCWSTR lpwszOutput,
12 PDEVMODEW lpInitData,
13 ULONG iType)
14 {
15 UNICODE_STRING Device, Output;
16 HDC hdc = NULL;
17 BOOL Display = FALSE, Default = FALSE;
18 ULONG UMdhpdev = 0;
19
20 HANDLE hspool = NULL;
21
22 if ( !ghSpooler && !LoadTheSpoolerDrv())
23 {
24 DPRINT1("WinSpooler.Drv Did not load!\n");
25 }
26 else
27 {
28 DPRINT("WinSpooler.Drv Loaded! hMod -> 0x%p\n", ghSpooler);
29 }
30
31 if ((!lpwszDevice) && (!lpwszDriver))
32 {
33 Default = TRUE; // Ask Win32k to set Default device.
34 Display = TRUE; // Most likely to be DISPLAY.
35 }
36 else
37 {
38 if ((lpwszDevice) && (wcslen(lpwszDevice) != 0)) // First
39 {
40 if (!_wcsnicmp(lpwszDevice, L"\\\\.\\DISPLAY",11)) Display = TRUE;
41 RtlInitUnicodeString(&Device, lpwszDevice);
42 }
43 else
44 {
45 if (lpwszDriver) // Second
46 {
47 if ((!_wcsnicmp(lpwszDriver, L"DISPLAY",7)) ||
48 (!_wcsnicmp(lpwszDriver, L"\\\\.\\DISPLAY",11))) Display = TRUE;
49 RtlInitUnicodeString(&Device, lpwszDriver);
50 }
51 }
52 }
53
54 if (lpwszOutput) RtlInitUnicodeString(&Output, lpwszOutput);
55
56 if (!Display)
57 {
58 //Handle Print device or something else.
59 DPRINT1("Not a DISPLAY device! %wZ\n", &Device);
60 }
61
62 hdc = NtGdiOpenDCW((Default ? NULL : &Device),
63 (PDEVMODEW) lpInitData,
64 (lpwszOutput ? &Output : NULL),
65 iType, // DCW 0 and ICW 1.
66 Display,
67 hspool,
68 (PVOID) NULL, // NULL for now.
69 (PVOID) &UMdhpdev );
70 #if 0
71 // Handle something other than a normal dc object.
72 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
73 {
74 PDC_ATTR Dc_Attr;
75 PLDC pLDC;
76
77 GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID*)&Dc_Attr);
78
79 pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC));
80
81 Dc_Attr->pvLDC = pLDC;
82 pLDC->hDC = hdc;
83 pLDC->iType = LDC_LDC; // 1 (init) local DC, 2 EMF LDC
84 DbgPrint("DC_ATTR Allocated -> 0x%x\n",Dc_Attr);
85 }
86 #endif
87 return hdc;
88 }
89
90
91 /*
92 * @implemented
93 */
94 HDC
95 WINAPI
96 CreateCompatibleDC(
97 _In_ HDC hdc)
98 {
99 HDC hdcNew;
100 // PDC_ATTR pdcattr;
101
102 hdcNew = NtGdiCreateCompatibleDC(hdc);
103 #if 0
104 if ( hdc && hdcNew)
105 {
106 if (GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID*)&pdcattr))
107 {
108 if (pdcattr->pvLIcm) IcmCompatibleDC(hdcNew, hdc, pdcattr);
109 }
110 }
111 #endif
112
113 return hdcNew;
114 }
115
116 /*
117 * @implemented
118 */
119 HDC
120 WINAPI
121 CreateDCA (
122 LPCSTR lpszDriver,
123 LPCSTR lpszDevice,
124 LPCSTR lpszOutput,
125 CONST DEVMODEA * lpdvmInit)
126 {
127 ANSI_STRING DriverA, DeviceA, OutputA;
128 UNICODE_STRING DriverU, DeviceU, OutputU;
129 LPDEVMODEW dvmInitW = NULL;
130 HDC hdc;
131
132 /*
133 * If needed, convert to Unicode
134 * any string parameter.
135 */
136
137 if (lpszDriver != NULL)
138 {
139 RtlInitAnsiString(&DriverA, (LPSTR)lpszDriver);
140 RtlAnsiStringToUnicodeString(&DriverU, &DriverA, TRUE);
141 }
142 else
143 {
144 DriverU.Buffer = NULL;
145 }
146
147 if (lpszDevice != NULL)
148 {
149 RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice);
150 RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE);
151 }
152 else
153 {
154 DeviceU.Buffer = NULL;
155 }
156
157 if (lpszOutput != NULL)
158 {
159 RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput);
160 RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE);
161 }
162 else
163 {
164 OutputU.Buffer = NULL;
165 }
166
167 if (lpdvmInit != NULL)
168 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
169
170 hdc = IntCreateDICW(DriverU.Buffer,
171 DeviceU.Buffer,
172 OutputU.Buffer,
173 lpdvmInit ? dvmInitW : NULL,
174 0);
175 HEAP_free(dvmInitW);
176
177 /* Free Unicode parameters. */
178 RtlFreeUnicodeString(&DriverU);
179 RtlFreeUnicodeString(&DeviceU);
180 RtlFreeUnicodeString(&OutputU);
181
182 /* Return the DC handle. */
183 return hdc;
184 }
185
186
187 /*
188 * @implemented
189 */
190 HDC
191 WINAPI
192 CreateDCW (
193 LPCWSTR lpwszDriver,
194 LPCWSTR lpwszDevice,
195 LPCWSTR lpwszOutput,
196 CONST DEVMODEW *lpInitData)
197 {
198 return IntCreateDICW(lpwszDriver,
199 lpwszDevice,
200 lpwszOutput,
201 (PDEVMODEW)lpInitData,
202 0);
203 }
204
205
206 /*
207 * @implemented
208 */
209 HDC
210 WINAPI
211 CreateICW(
212 LPCWSTR lpszDriver,
213 LPCWSTR lpszDevice,
214 LPCWSTR lpszOutput,
215 CONST DEVMODEW *lpdvmInit)
216 {
217 return IntCreateDICW(lpszDriver,
218 lpszDevice,
219 lpszOutput,
220 (PDEVMODEW)lpdvmInit,
221 1);
222 }
223
224
225 /*
226 * @implemented
227 */
228 HDC
229 WINAPI
230 CreateICA(
231 LPCSTR lpszDriver,
232 LPCSTR lpszDevice,
233 LPCSTR lpszOutput,
234 CONST DEVMODEA *lpdvmInit)
235 {
236 NTSTATUS Status;
237 LPWSTR lpszDriverW, lpszDeviceW, lpszOutputW;
238 LPDEVMODEW dvmInitW = NULL;
239 HDC hdc = 0;
240
241 Status = HEAP_strdupA2W(&lpszDriverW, lpszDriver);
242 if (!NT_SUCCESS(Status))
243 SetLastError(RtlNtStatusToDosError(Status));
244 else
245 {
246 Status = HEAP_strdupA2W(&lpszDeviceW, lpszDevice);
247 if (!NT_SUCCESS(Status))
248 SetLastError(RtlNtStatusToDosError(Status));
249 else
250 {
251 Status = HEAP_strdupA2W(&lpszOutputW, lpszOutput);
252 if (!NT_SUCCESS(Status))
253 SetLastError(RtlNtStatusToDosError(Status));
254 else
255 {
256 if (lpdvmInit)
257 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
258
259 hdc = IntCreateDICW(lpszDriverW,
260 lpszDeviceW,
261 lpszOutputW,
262 lpdvmInit ? dvmInitW : NULL,
263 1 );
264 HEAP_free(dvmInitW);
265 HEAP_free(lpszOutputW);
266 }
267 HEAP_free(lpszDeviceW);
268 }
269 HEAP_free(lpszDriverW);
270 }
271
272 return hdc;
273 }
274
275
276 /*
277 * @implemented
278 */
279 BOOL
280 WINAPI
281 DeleteDC(HDC hdc)
282 {
283 BOOL bResult = TRUE;
284 PLDC pLDC = NULL;
285 HANDLE hPrinter = NULL;
286 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
287
288 pLDC = GdiGetLDC(hdc);
289
290 if (hType != GDILoObjType_LO_DC_TYPE)
291 {
292
293 if ( !pLDC || hType == GDILoObjType_LO_METADC16_TYPE)
294 {
295 SetLastError(ERROR_INVALID_HANDLE);
296 return FALSE;
297 }
298 if (pLDC->Flags & LDC_INIT_DOCUMENT) AbortDoc(hdc);
299 if (pLDC->hPrinter)
300 {
301 DocumentEventEx(NULL, pLDC->hPrinter, hdc, DOCUMENTEVENT_DELETEDC, 0, NULL, 0, NULL);
302 hPrinter = pLDC->hPrinter;
303 pLDC->hPrinter = NULL;
304 }
305 }
306
307 bResult = NtGdiDeleteObjectApp(hdc);
308
309 if (bResult && pLDC)
310 {
311 DPRINT1("Delete the Local DC structure\n");
312 LocalFree( pLDC );
313 }
314
315 if (hPrinter)
316 fpClosePrinter(hPrinter);
317
318 return bResult;
319 }
320
321
322 /*
323 * @unimplemented
324 */
325 INT
326 WINAPI
327 SaveDC(IN HDC hdc)
328 {
329 /* FIXME Sharememory */
330 return NtGdiSaveDC(hdc);
331 }
332
333
334 /*
335 * @unimplemented
336 */
337 BOOL
338 WINAPI
339 RestoreDC(IN HDC hdc,
340 IN INT iLevel)
341 {
342 /* FIXME Sharememory */
343 return NtGdiRestoreDC(hdc, iLevel);
344 }
345
346
347 /*
348 * @implemented
349 */
350 BOOL
351 WINAPI
352 CancelDC(HDC hDC)
353 {
354 PDC_ATTR pDc_Attr;
355
356 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC &&
357 GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
358 {
359 PLDC pLDC = GdiGetLDC(hDC);
360 if ( !pLDC )
361 {
362 SetLastError(ERROR_INVALID_HANDLE);
363 return FALSE;
364 }
365 /* If a document has started set it to die. */
366 if (pLDC->Flags & LDC_INIT_DOCUMENT) pLDC->Flags |= LDC_KILL_DOCUMENT;
367
368 return NtGdiCancelDC(hDC);
369 }
370
371 if (GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr))
372 {
373 pDc_Attr->ulDirty_ &= ~DC_PLAYMETAFILE;
374 return TRUE;
375 }
376
377 return FALSE;
378 }
379
380 INT
381 WINAPI
382 GetArcDirection(
383 _In_ HDC hdc)
384 {
385 return GetDCDWord( hdc, GdiGetArcDirection, 0);
386 }
387
388
389 INT
390 WINAPI
391 SetArcDirection(
392 _In_ HDC hdc,
393 _In_ INT nDirection)
394 {
395 return GetAndSetDCDWord(hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0);
396 }
397
398 /*
399 * @unimplemented
400 */
401 BOOL
402 WINAPI
403 GdiReleaseDC(HDC hdc)
404 {
405 return 0;
406 }
407
408
409 /*
410 * @implemented
411 */
412 BOOL
413 WINAPI
414 GdiCleanCacheDC(HDC hdc)
415 {
416 if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_DC_TYPE)
417 return TRUE;
418 SetLastError(ERROR_INVALID_HANDLE);
419 return FALSE;
420 }
421
422 /*
423 * @implemented
424 */
425 HDC
426 WINAPI
427 GdiConvertAndCheckDC(HDC hdc)
428 {
429 PLDC pldc;
430 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
431 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
432 return hdc;
433 pldc = GdiGetLDC(hdc);
434 if (pldc)
435 {
436 if (pldc->Flags & LDC_SAPCALLBACK) GdiSAPCallback(pldc);
437 if (pldc->Flags & LDC_KILL_DOCUMENT) return NULL;
438 if (pldc->Flags & LDC_STARTPAGE) StartPage(hdc);
439 return hdc;
440 }
441 SetLastError(ERROR_INVALID_HANDLE);
442 return NULL;
443 }
444
445
446 /*
447 * @implemented
448 *
449 */
450 HGDIOBJ
451 WINAPI
452 GetCurrentObject(
453 _In_ HDC hdc,
454 _In_ UINT uObjectType)
455 {
456 PDC_ATTR pdcattr = NULL;
457
458 /* Check if this is a user mode object */
459 if ((uObjectType == OBJ_PEN) ||
460 (uObjectType == OBJ_EXTPEN) ||
461 (uObjectType == OBJ_BRUSH) ||
462 (uObjectType == OBJ_COLORSPACE))
463 {
464 /* Get the DC attribute */
465 pdcattr = GdiGetDcAttr(hdc);
466 if (pdcattr == NULL)
467 {
468 return NULL;
469 }
470 }
471
472 /* Check what object was requested */
473 switch (uObjectType)
474 {
475 case OBJ_EXTPEN:
476 case OBJ_PEN:
477 return pdcattr->hpen;
478
479 case OBJ_BRUSH:
480 return pdcattr->hbrush;
481
482 case OBJ_COLORSPACE:
483 return pdcattr->hColorSpace;
484
485 case OBJ_PAL:
486 uObjectType = GDI_OBJECT_TYPE_PALETTE;
487 break;
488
489 case OBJ_FONT:
490 uObjectType = GDI_OBJECT_TYPE_FONT;
491 break;
492
493 case OBJ_BITMAP:
494 uObjectType = GDI_OBJECT_TYPE_BITMAP;
495 break;
496
497 /* All others are invalid */
498 default:
499 SetLastError(ERROR_INVALID_PARAMETER);
500 return NULL;
501 }
502
503 /* Pass the request to win32k */
504 return NtGdiGetDCObject(hdc, uObjectType);
505 }
506
507
508 /*
509 * @implemented
510 */
511 int
512 WINAPI
513 EnumObjects(HDC hdc,
514 int nObjectType,
515 GOBJENUMPROC lpObjectFunc,
516 LPARAM lParam)
517 {
518 ULONG ObjectsCount;
519 ULONG Size;
520 PVOID Buffer = NULL;
521 DWORD_PTR EndOfBuffer;
522 int Result = 0;
523
524 switch (nObjectType)
525 {
526 case OBJ_BRUSH:
527 Size = sizeof(LOGBRUSH);
528 break;
529
530 case OBJ_PEN:
531 Size = sizeof(LOGPEN);
532 break;
533
534 default:
535 SetLastError(ERROR_INVALID_PARAMETER);
536 return 0;
537 }
538
539 ObjectsCount = NtGdiEnumObjects(hdc, nObjectType, 0, NULL);
540 if (!ObjectsCount) return 0;
541
542 Buffer = HeapAlloc(GetProcessHeap(), 0, ObjectsCount * Size);
543 if (!Buffer)
544 {
545 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
546 return 0;
547 }
548
549 if (!NtGdiEnumObjects(hdc, nObjectType, ObjectsCount * Size, Buffer))
550 {
551 HeapFree(GetProcessHeap(), 0, Buffer);
552 return 0;
553 }
554
555 EndOfBuffer = (DWORD_PTR)Buffer + (ObjectsCount * Size);
556 while ((DWORD_PTR)Buffer < EndOfBuffer)
557 {
558 Result = lpObjectFunc(Buffer, lParam);
559 if (!Result) break;
560 Buffer = (PVOID)((DWORD_PTR)Buffer + Size);
561 }
562
563 HeapFree(GetProcessHeap(), 0, Buffer);
564 return Result;
565 }
566
567
568 /*
569 * @implemented
570 *
571 */
572 int
573 WINAPI
574 GetDeviceCaps(
575 _In_ HDC hdc,
576 _In_ int nIndex)
577 {
578 PDC_ATTR pdcattr;
579 PLDC pLDC;
580 PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities.
581 DPRINT("Device CAPS1\n");
582
583 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
584 {
585 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
586 {
587 if (nIndex == TECHNOLOGY) return DT_METAFILE;
588 return 0;
589 }
590 else
591 {
592 pLDC = GdiGetLDC(hdc);
593 if ( !pLDC )
594 {
595 SetLastError(ERROR_INVALID_HANDLE);
596 return 0;
597 }
598 if (!(pLDC->Flags & LDC_DEVCAPS))
599 {
600 if (!NtGdiGetDeviceCapsAll(hdc, &pLDC->DevCaps))
601 SetLastError(ERROR_INVALID_PARAMETER);
602 pLDC->Flags |= LDC_DEVCAPS;
603 }
604 pDevCaps = &pLDC->DevCaps;
605 }
606 }
607 else
608 {
609 /* Get the DC attribute */
610 pdcattr = GdiGetDcAttr(hdc);
611 if (pdcattr == NULL)
612 {
613 SetLastError(ERROR_INVALID_PARAMETER);
614 return 0;
615 }
616
617 if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY) )
618 return NtGdiGetDeviceCaps(hdc, nIndex);
619 }
620 DPRINT("Device CAPS2\n");
621
622 switch (nIndex)
623 {
624 case DRIVERVERSION:
625 return pDevCaps->ulVersion;
626
627 case TECHNOLOGY:
628 return pDevCaps->ulTechnology;
629
630 case HORZSIZE:
631 return pDevCaps->ulHorzSize;
632
633 case VERTSIZE:
634 return pDevCaps->ulVertSize;
635
636 case HORZRES:
637 return pDevCaps->ulHorzRes;
638
639 case VERTRES:
640 return pDevCaps->ulVertRes;
641
642 case LOGPIXELSX:
643 return pDevCaps->ulLogPixelsX;
644
645 case LOGPIXELSY:
646 return pDevCaps->ulLogPixelsY;
647
648 case BITSPIXEL:
649 return pDevCaps->ulBitsPixel;
650
651 case PLANES:
652 return pDevCaps->ulPlanes;
653
654 case NUMBRUSHES:
655 return -1;
656
657 case NUMPENS:
658 return pDevCaps->ulNumPens;
659
660 case NUMFONTS:
661 return pDevCaps->ulNumFonts;
662
663 case NUMCOLORS:
664 return pDevCaps->ulNumColors;
665
666 case ASPECTX:
667 return pDevCaps->ulAspectX;
668
669 case ASPECTY:
670 return pDevCaps->ulAspectY;
671
672 case ASPECTXY:
673 return pDevCaps->ulAspectXY;
674
675 case CLIPCAPS:
676 return CP_RECTANGLE;
677
678 case SIZEPALETTE:
679 return pDevCaps->ulSizePalette;
680
681 case NUMRESERVED:
682 return 20;
683
684 case COLORRES:
685 return pDevCaps->ulColorRes;
686
687 case DESKTOPVERTRES:
688 return pDevCaps->ulVertRes;
689
690 case DESKTOPHORZRES:
691 return pDevCaps->ulHorzRes;
692
693 case BLTALIGNMENT:
694 return pDevCaps->ulBltAlignment;
695
696 case SHADEBLENDCAPS:
697 return pDevCaps->ulShadeBlend;
698
699 case COLORMGMTCAPS:
700 return pDevCaps->ulColorMgmtCaps;
701
702 case PHYSICALWIDTH:
703 return pDevCaps->ulPhysicalWidth;
704
705 case PHYSICALHEIGHT:
706 return pDevCaps->ulPhysicalHeight;
707
708 case PHYSICALOFFSETX:
709 return pDevCaps->ulPhysicalOffsetX;
710
711 case PHYSICALOFFSETY:
712 return pDevCaps->ulPhysicalOffsetY;
713
714 case VREFRESH:
715 return pDevCaps->ulVRefresh;
716
717 case RASTERCAPS:
718 return pDevCaps->ulRasterCaps;
719
720 case CURVECAPS:
721 return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
722 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
723
724 case LINECAPS:
725 return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
726 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
727
728 case POLYGONALCAPS:
729 return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
730 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
731
732 case TEXTCAPS:
733 return pDevCaps->ulTextCaps;
734
735 case PDEVICESIZE:
736 case SCALINGFACTORX:
737 case SCALINGFACTORY:
738 default:
739 return 0;
740 }
741 return 0;
742 }
743
744 /*
745 * @implemented
746 */
747 DWORD
748 WINAPI
749 GetRelAbs(
750 _In_ HDC hdc,
751 _In_ DWORD dwIgnore)
752 {
753 return GetDCDWord(hdc, GdiGetRelAbs, 0);
754 }
755
756
757 /*
758 * @implemented
759 */
760 INT
761 WINAPI
762 SetRelAbs(
763 HDC hdc,
764 INT Mode)
765 {
766 return GetAndSetDCDWord(hdc, GdiGetSetRelAbs, Mode, 0, 0, 0);
767 }
768
769
770 /*
771 * @implemented
772 */
773 DWORD
774 WINAPI
775 GetAndSetDCDWord(
776 _In_ HDC hdc,
777 _In_ UINT u,
778 _In_ DWORD dwIn,
779 _In_ ULONG ulMFId,
780 _In_ USHORT usMF16Id,
781 _In_ DWORD dwError)
782 {
783 DWORD dwResult;
784 BOOL Ret = TRUE;
785
786 /* Handle something other than a normal dc object. */
787 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
788 {
789 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
790 return 0; //call MFDRV
791 else
792 {
793 PLDC pLDC = GdiGetLDC(hdc);
794 if ( !pLDC )
795 {
796 SetLastError(ERROR_INVALID_HANDLE);
797 return 0;
798 }
799 if (pLDC->iType == LDC_EMFLDC)
800 {
801 Ret = TRUE; //call EMFDRV
802 if (Ret)
803 return u;
804 return 0;
805 }
806 }
807 }
808
809 if (!NtGdiGetAndSetDCDword(hdc, u, dwIn, &dwResult))
810 {
811 SetLastError(ERROR_INVALID_HANDLE);
812 return 0;
813 }
814
815 return dwResult;
816 }
817
818
819 /*
820 * @implemented
821 */
822 DWORD
823 WINAPI
824 GetDCDWord(
825 _In_ HDC hdc,
826 _In_ UINT u,
827 _In_ DWORD dwError)
828 {
829 DWORD dwResult;
830
831 if (!NtGdiGetDCDword(hdc, u, &dwResult))
832 {
833 return dwError;
834 }
835
836 return dwResult;
837 }
838
839
840 /*
841 * @implemented
842 */
843 BOOL
844 WINAPI
845 GetAspectRatioFilterEx(
846 HDC hdc,
847 LPSIZE lpAspectRatio)
848 {
849 return NtGdiGetDCPoint(hdc, GdiGetAspectRatioFilter, (PPOINTL)lpAspectRatio );
850 }
851
852
853 /*
854 * @implemented
855 */
856 UINT
857 WINAPI
858 GetBoundsRect(
859 HDC hdc,
860 LPRECT lprcBounds,
861 UINT flags
862 )
863 {
864 return NtGdiGetBoundsRect(hdc,lprcBounds,flags & DCB_RESET);
865 }
866
867
868 /*
869 * @implemented
870 */
871 UINT
872 WINAPI
873 SetBoundsRect(HDC hdc,
874 CONST RECT *prc,
875 UINT flags)
876 {
877 /* FIXME add check for validate the flags */
878 return NtGdiSetBoundsRect(hdc, (LPRECT)prc, flags);
879 }
880
881
882 /*
883 * @implemented
884 *
885 */
886 int
887 WINAPI
888 GetClipBox(HDC hdc,
889 LPRECT lprc)
890 {
891 return NtGdiGetAppClipBox(hdc, lprc);
892 }
893
894
895 /*
896 * @implemented
897 */
898 COLORREF
899 WINAPI
900 GetDCBrushColor(
901 _In_ HDC hdc)
902 {
903 PDC_ATTR pdcattr;
904
905 /* Get the DC attribute */
906 pdcattr = GdiGetDcAttr(hdc);
907 if (pdcattr == NULL)
908 {
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return CLR_INVALID;
911 }
912
913 return pdcattr->ulBrushClr;
914 }
915
916 /*
917 * @implemented
918 */
919 COLORREF
920 WINAPI
921 GetDCPenColor(
922 _In_ HDC hdc)
923 {
924 PDC_ATTR pdcattr;
925
926 /* Get the DC attribute */
927 pdcattr = GdiGetDcAttr(hdc);
928 if (pdcattr == NULL)
929 {
930 SetLastError(ERROR_INVALID_PARAMETER);
931 return CLR_INVALID;
932 }
933
934 return pdcattr->ulPenClr;
935 }
936
937 /*
938 * @implemented
939 */
940 COLORREF
941 WINAPI
942 SetDCBrushColor(
943 _In_ HDC hdc,
944 _In_ COLORREF crColor)
945 {
946 PDC_ATTR pdcattr;
947 COLORREF crOldColor;
948
949 /* Get the DC attribute */
950 pdcattr = GdiGetDcAttr(hdc);
951 if (pdcattr == NULL)
952 {
953 SetLastError(ERROR_INVALID_PARAMETER);
954 return CLR_INVALID;
955 }
956
957 /* Get old color and store the new */
958 crOldColor = pdcattr->ulBrushClr;
959 pdcattr->ulBrushClr = crColor;
960
961 if (pdcattr->crBrushClr != crColor)
962 {
963 pdcattr->ulDirty_ |= DIRTY_FILL;
964 pdcattr->crBrushClr = crColor;
965 }
966
967 return crOldColor;
968 }
969
970 /*
971 * @implemented
972 */
973 COLORREF
974 WINAPI
975 SetDCPenColor(
976 _In_ HDC hdc,
977 _In_ COLORREF crColor)
978 {
979 PDC_ATTR pdcattr;
980 COLORREF crOldColor;
981
982 /* Get the DC attribute */
983 pdcattr = GdiGetDcAttr(hdc);
984 if (pdcattr == NULL)
985 {
986 SetLastError(ERROR_INVALID_PARAMETER);
987 return CLR_INVALID;
988 }
989
990 /* Get old color and store the new */
991 crOldColor = pdcattr->ulPenClr;
992 pdcattr->ulPenClr = (ULONG)crColor;
993
994 if (pdcattr->crPenClr != crColor)
995 {
996 pdcattr->ulDirty_ |= DIRTY_LINE;
997 pdcattr->crPenClr = crColor;
998 }
999
1000 return crOldColor;
1001 }
1002
1003 /*
1004 * @implemented
1005 *
1006 */
1007 COLORREF
1008 WINAPI
1009 GetBkColor(
1010 _In_ HDC hdc)
1011 {
1012 PDC_ATTR pdcattr;
1013
1014 /* Get the DC attribute */
1015 pdcattr = GdiGetDcAttr(hdc);
1016 if (pdcattr == NULL)
1017 {
1018 /* Don't set LastError here! */
1019 return CLR_INVALID;
1020 }
1021
1022 return pdcattr->ulBackgroundClr;
1023 }
1024
1025 /*
1026 * @implemented
1027 */
1028 COLORREF
1029 WINAPI
1030 SetBkColor(
1031 _In_ HDC hdc,
1032 _In_ COLORREF crColor)
1033 {
1034 PDC_ATTR pdcattr;
1035 COLORREF crOldColor;
1036
1037 /* Get the DC attribute */
1038 pdcattr = GdiGetDcAttr(hdc);
1039 if (pdcattr == NULL)
1040 {
1041 SetLastError(ERROR_INVALID_PARAMETER);
1042 return CLR_INVALID;
1043 }
1044
1045 #if 0
1046 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1047 {
1048 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1049 return MFDRV_SetBkColor(hdc, crColor );
1050 else
1051 {
1052 PLDC pLDC = pdcattr->pvLDC;
1053 if ( !pLDC )
1054 {
1055 SetLastError(ERROR_INVALID_HANDLE);
1056 return FALSE;
1057 }
1058 if (pLDC->iType == LDC_EMFLDC)
1059 {
1060 return EMFDRV_SetBkColor(hdc, crColor );
1061 }
1062 }
1063 }
1064 #endif
1065
1066 /* Get old color and store the new */
1067 crOldColor = pdcattr->ulBackgroundClr;
1068 pdcattr->ulBackgroundClr = crColor;
1069
1070 if (pdcattr->crBackgroundClr != crColor)
1071 {
1072 pdcattr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
1073 pdcattr->crBackgroundClr = crColor;
1074 }
1075
1076 return crOldColor;
1077 }
1078
1079 /*
1080 * @implemented
1081 *
1082 */
1083 int
1084 WINAPI
1085 GetBkMode(HDC hdc)
1086 {
1087 PDC_ATTR pdcattr;
1088
1089 /* Get the DC attribute */
1090 pdcattr = GdiGetDcAttr(hdc);
1091 if (pdcattr == NULL)
1092 {
1093 /* Don't set LastError here! */
1094 return 0;
1095 }
1096
1097 return pdcattr->lBkMode;
1098 }
1099
1100 /*
1101 * @implemented
1102 *
1103 */
1104 int
1105 WINAPI
1106 SetBkMode(
1107 _In_ HDC hdc,
1108 _In_ int iBkMode)
1109 {
1110 PDC_ATTR pdcattr;
1111 INT iOldMode;
1112
1113 /* Get the DC attribute */
1114 pdcattr = GdiGetDcAttr(hdc);
1115 if (pdcattr == NULL)
1116 {
1117 SetLastError(ERROR_INVALID_PARAMETER);
1118 return 0;
1119 }
1120
1121 #if 0
1122 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1123 {
1124 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1125 return MFDRV_SetBkMode( hdc, iBkMode )
1126 else
1127 {
1128 PLDC pLDC = pdcattr->pvLDC;
1129 if ( !pLDC )
1130 {
1131 SetLastError(ERROR_INVALID_HANDLE);
1132 return FALSE;
1133 }
1134 if (pLDC->iType == LDC_EMFLDC)
1135 {
1136 return EMFDRV_SetBkMode(hdc, iBkMode)
1137 }
1138 }
1139 }
1140 #endif
1141
1142 iOldMode = pdcattr->lBkMode;
1143 pdcattr->jBkMode = iBkMode; // Processed
1144 pdcattr->lBkMode = iBkMode; // Raw
1145
1146 return iOldMode;
1147 }
1148
1149 /*
1150 * @implemented
1151 *
1152 */
1153 int
1154 WINAPI
1155 GetPolyFillMode(HDC hdc)
1156 {
1157 PDC_ATTR pdcattr;
1158
1159 /* Get DC attribute */
1160 pdcattr = GdiGetDcAttr(hdc);
1161 if (pdcattr == NULL)
1162 {
1163 /* Don't set LastError here! */
1164 return 0;
1165 }
1166
1167 /* Return current fill mode */
1168 return pdcattr->lFillMode;
1169 }
1170
1171 /*
1172 * @unimplemented
1173 */
1174 int
1175 WINAPI
1176 SetPolyFillMode(
1177 _In_ HDC hdc,
1178 _In_ int iPolyFillMode)
1179 {
1180 INT iOldPolyFillMode;
1181 PDC_ATTR pdcattr;
1182
1183 #if 0
1184 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1185 {
1186 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1187 return MFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1188 else
1189 {
1190 PLDC pLDC = GdiGetLDC(hdc);
1191 if ( !pLDC )
1192 {
1193 SetLastError(ERROR_INVALID_HANDLE);
1194 return FALSE;
1195 }
1196 if (pLDC->iType == LDC_EMFLDC)
1197 {
1198 return EMFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1199 }
1200 }
1201 }
1202 #endif
1203
1204 /* Get the DC attribute */
1205 pdcattr = GdiGetDcAttr(hdc);
1206 if (pdcattr == NULL)
1207 {
1208 SetLastError(ERROR_INVALID_PARAMETER);
1209 return 0;
1210 }
1211
1212 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1213 {
1214 if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
1215 {
1216 NtGdiFlush(); // Sync up pdcattr from Kernel space.
1217 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1218 }
1219 }
1220
1221 iOldPolyFillMode = pdcattr->lFillMode;
1222 pdcattr->lFillMode = iPolyFillMode;
1223
1224 return iOldPolyFillMode;
1225 }
1226
1227 /*
1228 * @implemented
1229 *
1230 */
1231 int
1232 WINAPI
1233 GetGraphicsMode(HDC hdc)
1234 {
1235 PDC_ATTR pdcattr;
1236
1237 /* Get the DC attribute */
1238 pdcattr = GdiGetDcAttr(hdc);
1239 if (pdcattr == NULL)
1240 {
1241 /* Don't set LastError here! */
1242 return 0;
1243 }
1244
1245 /* Return current graphics mode */
1246 return pdcattr->iGraphicsMode;
1247 }
1248
1249 /*
1250 * @unimplemented
1251 */
1252 int
1253 WINAPI
1254 SetGraphicsMode(
1255 _In_ HDC hdc,
1256 _In_ int iMode)
1257 {
1258 INT iOldMode;
1259 PDC_ATTR pdcattr;
1260
1261 /* Check parameters */
1262 if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
1263 {
1264 SetLastError(ERROR_INVALID_PARAMETER);
1265 return 0;
1266 }
1267
1268 /* Get the DC attribute */
1269 pdcattr = GdiGetDcAttr(hdc);
1270 if (pdcattr == NULL)
1271 {
1272 SetLastError(ERROR_INVALID_PARAMETER);
1273 return 0;
1274 }
1275
1276 /* Check for trivial case */
1277 if (iMode == pdcattr->iGraphicsMode)
1278 return iMode;
1279
1280 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1281 {
1282 if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
1283 {
1284 NtGdiFlush(); // Sync up pdcattr from Kernel space.
1285 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1286 }
1287 }
1288
1289 /* One would think that setting the graphics mode to GM_COMPATIBLE
1290 * would also reset the world transformation matrix to the unity
1291 * matrix. However, in Windows, this is not the case. This doesn't
1292 * make a lot of sense to me, but that's the way it is.
1293 */
1294 iOldMode = pdcattr->iGraphicsMode;
1295 pdcattr->iGraphicsMode = iMode;
1296
1297 return iOldMode;
1298 }
1299
1300 /*
1301 * @implemented
1302 */
1303 HDC
1304 WINAPI
1305 ResetDCW(
1306 _In_ HDC hdc,
1307 _In_ CONST DEVMODEW *lpInitData)
1308 {
1309 NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
1310 return hdc;
1311 }
1312
1313
1314 /*
1315 * @implemented
1316 */
1317 HDC
1318 WINAPI
1319 ResetDCA(
1320 _In_ HDC hdc,
1321 _In_ CONST DEVMODEA *lpInitData)
1322 {
1323 LPDEVMODEW InitDataW;
1324
1325 InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
1326
1327 NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
1328 HEAP_free(InitDataW);
1329 return hdc;
1330 }
1331
1332
1333 /* FIXME: include correct header */
1334 HPALETTE WINAPI NtUserSelectPalette(HDC hDC,
1335 HPALETTE hpal,
1336 BOOL ForceBackground);
1337
1338 HPALETTE
1339 WINAPI
1340 SelectPalette(
1341 HDC hdc,
1342 HPALETTE hpal,
1343 BOOL bForceBackground)
1344 {
1345 #if 0
1346 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1347 {
1348 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1349 return MFDRV_SelectPalette(hdc, hpal, bForceBackground);
1350 else
1351 {
1352 PLDC pLDC = GdiGetLDC(hdc);
1353 if ( !pLDC )
1354 {
1355 SetLastError(ERROR_INVALID_HANDLE);
1356 return NULL;
1357 }
1358 if (pLDC->iType == LDC_EMFLDC)
1359 {
1360 if return EMFDRV_SelectPalette(hdc, hpal, bForceBackground);
1361 }
1362 }
1363 }
1364 #endif
1365 return NtUserSelectPalette(hdc, hpal, bForceBackground);
1366 }
1367
1368 /*
1369 * @implemented
1370 *
1371 */
1372 int
1373 WINAPI
1374 GetStretchBltMode(HDC hdc)
1375 {
1376 PDC_ATTR pdcattr;
1377
1378 /* Get the DC attribute */
1379 pdcattr = GdiGetDcAttr(hdc);
1380 if (pdcattr == NULL)
1381 {
1382 /* Don't set LastError here! */
1383 return 0;
1384 }
1385
1386 return pdcattr->lStretchBltMode;
1387 }
1388
1389 /*
1390 * @implemented
1391 */
1392 int
1393 WINAPI
1394 SetStretchBltMode(
1395 _In_ HDC hdc,
1396 _In_ int iStretchMode)
1397 {
1398 INT iOldMode;
1399 PDC_ATTR pdcattr;
1400 #if 0
1401 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1402 {
1403 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1404 return MFDRV_SetStretchBltMode( hdc, iStretchMode);
1405 else
1406 {
1407 PLDC pLDC = GdiGetLDC(hdc);
1408 if ( !pLDC )
1409 {
1410 SetLastError(ERROR_INVALID_HANDLE);
1411 return 0;
1412 }
1413 if (pLDC->iType == LDC_EMFLDC)
1414 {
1415 return EMFDRV_SetStretchBltMode( hdc, iStretchMode);
1416 }
1417 }
1418 }
1419 #endif
1420 /* Get the DC attribute */
1421 pdcattr = GdiGetDcAttr(hdc);
1422 if (pdcattr == NULL)
1423 {
1424 SetLastError(ERROR_INVALID_PARAMETER);
1425 return 0;
1426 }
1427
1428 iOldMode = pdcattr->lStretchBltMode;
1429 pdcattr->lStretchBltMode = iStretchMode;
1430
1431 // Wine returns an error here. We set the default.
1432 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
1433
1434 pdcattr->jStretchBltMode = iStretchMode;
1435
1436 return iOldMode;
1437 }
1438
1439 /*
1440 * @implemented
1441 */
1442 HFONT
1443 WINAPI
1444 GetHFONT(HDC hdc)
1445 {
1446 PDC_ATTR pdcattr;
1447
1448 /* Get the DC attribute */
1449 pdcattr = GdiGetDcAttr(hdc);
1450 if (pdcattr == NULL)
1451 {
1452 /* Don't set LastError here! */
1453 return NULL;
1454 }
1455
1456 /* Return the current font */
1457 return pdcattr->hlfntNew;
1458 }
1459
1460
1461
1462 HBITMAP
1463 WINAPI
1464 GdiSelectBitmap(
1465 _In_ HDC hdc,
1466 _In_ HBITMAP hbmp)
1467 {
1468 return NtGdiSelectBitmap(hdc, hbmp);
1469 }
1470
1471 HBRUSH
1472 WINAPI
1473 GdiSelectBrush(
1474 _In_ HDC hdc,
1475 _In_ HBRUSH hbr)
1476 {
1477 PDC_ATTR pdcattr;
1478 HBRUSH hbrOld;
1479
1480 /* Get the DC attribute */
1481 pdcattr = GdiGetDcAttr(hdc);
1482 if (pdcattr == NULL)
1483 {
1484 SetLastError(ERROR_INVALID_PARAMETER);
1485 return NULL;
1486 }
1487
1488 /* Get the current brush. If it matches the new brush, we're done */
1489 hbrOld = pdcattr->hbrush;
1490 if (hbrOld == hbr)
1491 return hbrOld;
1492
1493 /* Set the new brush and update dirty flags */
1494 pdcattr->hbrush = hbr;
1495 pdcattr->ulDirty_ |= DC_BRUSH_DIRTY;
1496 return hbrOld;
1497 }
1498
1499 HPEN
1500 WINAPI
1501 GdiSelectPen(
1502 _In_ HDC hdc,
1503 _In_ HPEN hpen)
1504 {
1505 PDC_ATTR pdcattr;
1506 HPEN hpenOld;
1507
1508 /* Get the DC attribute */
1509 pdcattr = GdiGetDcAttr(hdc);
1510 if (pdcattr == NULL)
1511 {
1512 SetLastError(ERROR_INVALID_PARAMETER);
1513 return NULL;
1514 }
1515
1516 /* Get the current pen. If it matches the new pen, we're done */
1517 hpenOld = pdcattr->hpen;
1518 if (hpenOld == hpen)
1519 return hpenOld;
1520
1521 /* Set the new pen and update dirty flags */
1522 pdcattr->ulDirty_ |= DC_PEN_DIRTY;
1523 pdcattr->hpen = hpen;
1524 return hpenOld;
1525 }
1526
1527 HFONT
1528 WINAPI
1529 GdiSelectFont(
1530 _In_ HDC hdc,
1531 _In_ HFONT hfont)
1532 {
1533 PDC_ATTR pdcattr;
1534 HFONT hfontOld;
1535
1536 /* Get the DC attribute */
1537 pdcattr = GdiGetDcAttr(hdc);
1538 if (pdcattr == NULL)
1539 {
1540 SetLastError(ERROR_INVALID_PARAMETER);
1541 return NULL;
1542 }
1543
1544 /* Get the current font. If it matches the new font, we're done */
1545 hfontOld = pdcattr->hlfntNew;
1546 if (hfontOld == hfont)
1547 return hfontOld;
1548
1549 /* Set the new font and update dirty flags */
1550 pdcattr->hlfntNew = hfont;
1551 pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
1552 pdcattr->ulDirty_ |= DIRTY_CHARSET;
1553
1554 /* If the DC does not have a DIB section selected, try a batch command */
1555 if (!(pdcattr->ulDirty_ & DC_DIBSECTION))
1556 {
1557 PGDIBSOBJECT pgO;
1558
1559 pgO = GdiAllocBatchCommand(hdc, GdiBCSelObj);
1560 if (pgO)
1561 {
1562 pgO->hgdiobj = hfont;
1563 return hfontOld;
1564 }
1565 }
1566
1567 /* We could not use the batch command, call win32k */
1568 return NtGdiSelectFont(hdc, hfont);
1569 }
1570
1571
1572 /*
1573 * @implemented
1574 *
1575 */
1576 HGDIOBJ
1577 WINAPI
1578 SelectObject(
1579 _In_ HDC hdc,
1580 _In_ HGDIOBJ hobj)
1581 {
1582 /* Fix up 16 bit handles */
1583 hobj = GdiFixUpHandle(hobj);
1584 if (!GdiIsHandleValid(hobj))
1585 {
1586 return NULL;
1587 }
1588
1589 /* Call the appropriate select function */
1590 switch (GDI_HANDLE_GET_TYPE(hobj))
1591 {
1592 case GDILoObjType_LO_REGION_TYPE:
1593 return (HGDIOBJ)ExtSelectClipRgn(hdc, hobj, RGN_COPY);
1594
1595 case GDILoObjType_LO_BITMAP_TYPE:
1596 case GDILoObjType_LO_DIBSECTION_TYPE:
1597 return GdiSelectBitmap(hdc, hobj);
1598
1599 case GDILoObjType_LO_BRUSH_TYPE:
1600 return GdiSelectBrush(hdc, hobj);
1601
1602 case GDILoObjType_LO_PEN_TYPE:
1603 case GDILoObjType_LO_EXTPEN_TYPE:
1604 return GdiSelectPen(hdc, hobj);
1605
1606 case GDILoObjType_LO_FONT_TYPE:
1607 return GdiSelectFont(hdc, hobj);
1608
1609 case GDILoObjType_LO_ICMLCS_TYPE:
1610 return SetColorSpace(hdc, hobj);
1611
1612 case GDILoObjType_LO_PALETTE_TYPE:
1613 SetLastError(ERROR_INVALID_FUNCTION);
1614
1615 default:
1616 return NULL;
1617 }
1618
1619 return NULL;
1620 }
1621