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