xref: /reactos/win32ss/gdi/gdi32/objects/dc.c (revision a9bdd62d)
1 #include <precomp.h>
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 HDC
7 FASTCALL
IntCreateDICW(LPCWSTR lpwszDriver,LPCWSTR lpwszDevice,LPCWSTR lpwszOutput,PDEVMODEW lpInitData,ULONG iType)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
CreateCompatibleDC(_In_ HDC hdc)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
CreateDCA(LPCSTR lpszDriver,LPCSTR lpszDevice,LPCSTR lpszOutput,CONST DEVMODEA * lpdvmInit)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
CreateDCW(LPCWSTR lpwszDriver,LPCWSTR lpwszDevice,LPCWSTR lpwszOutput,CONST DEVMODEW * lpInitData)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
CreateICW(LPCWSTR lpszDriver,LPCWSTR lpszDevice,LPCWSTR lpszOutput,CONST DEVMODEW * lpdvmInit)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
CreateICA(LPCSTR lpszDriver,LPCSTR lpszDevice,LPCSTR lpszOutput,CONST DEVMODEA * lpdvmInit)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
DeleteDC(HDC hdc)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
SaveDC(IN HDC hdc)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
RestoreDC(IN HDC hdc,IN INT iLevel)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
CancelDC(HDC hDC)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
GetArcDirection(_In_ HDC hdc)358 GetArcDirection(
359     _In_ HDC hdc)
360 {
361     return GetDCDWord( hdc, GdiGetArcDirection, 0);
362 }
363 
364 
365 INT
366 WINAPI
SetArcDirection(_In_ HDC hdc,_In_ INT nDirection)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
GdiReleaseDC(HDC hdc)379 GdiReleaseDC(HDC hdc)
380 {
381     return 0;
382 }
383 
384 
385 /*
386  * @implemented
387  */
388 BOOL
389 WINAPI
GdiCleanCacheDC(HDC hdc)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
GdiConvertAndCheckDC(HDC hdc)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
GetCurrentObject(_In_ HDC hdc,_In_ UINT uObjectType)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
EnumObjects(HDC hdc,int nObjectType,GOBJENUMPROC lpObjectFunc,LPARAM lParam)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
GetDeviceCaps(_In_ HDC hdc,_In_ int nIndex)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
GetRelAbs(_In_ HDC hdc,_In_ DWORD dwIgnore)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
SetRelAbs(HDC hdc,INT Mode)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
GetAndSetDCDWord(_In_ HDC hdc,_In_ UINT u,_In_ DWORD dwIn,_In_ ULONG ulMFId,_In_ USHORT usMF16Id,_In_ DWORD dwError)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
GetDCDWord(_In_ HDC hdc,_In_ UINT u,_In_ DWORD dwError)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
GetAspectRatioFilterEx(HDC hdc,LPSIZE lpAspectRatio)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
GetBoundsRect(HDC hdc,LPRECT lprcBounds,UINT flags)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
SetBoundsRect(HDC hdc,CONST RECT * prc,UINT flags)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
GetClipBox(HDC hdc,LPRECT lprc)851 GetClipBox(HDC hdc,
852            LPRECT lprc)
853 {
854     return NtGdiGetAppClipBox(hdc, lprc);
855 }
856 
857 
858 /*
859  * @implemented
860  */
861 COLORREF
862 WINAPI
GetDCBrushColor(_In_ HDC hdc)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
GetDCPenColor(_In_ HDC hdc)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
SetDCBrushColor(_In_ HDC hdc,_In_ COLORREF crColor)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
SetDCPenColor(_In_ HDC hdc,_In_ COLORREF crColor)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
GetBkColor(_In_ HDC hdc)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
SetBkColor(_In_ HDC hdc,_In_ COLORREF crColor)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
GetBkMode(HDC hdc)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
SetBkMode(_In_ HDC hdc,_In_ int iBkMode)1056 SetBkMode(
1057     _In_ HDC hdc,
1058     _In_ int iBkMode)
1059 {
1060     PDC_ATTR pdcattr;
1061     INT iOldMode;
1062 
1063     /* Avoid bad mode setting */
1064     if ((iBkMode != TRANSPARENT) && (iBkMode != OPAQUE))
1065     {
1066         DPRINT1("SetBkMode: Incorrect value\n");
1067         return 0;
1068     }
1069 
1070     HANDLE_METADC(INT, SetBkMode, 0, hdc, iBkMode);
1071 
1072     /* Get the DC attribute */
1073     pdcattr = GdiGetDcAttr(hdc);
1074     if (pdcattr == NULL)
1075     {
1076         SetLastError(ERROR_INVALID_PARAMETER);
1077         return 0;
1078     }
1079 
1080     iOldMode = pdcattr->lBkMode;
1081     pdcattr->jBkMode = iBkMode; // Processed
1082     pdcattr->lBkMode = iBkMode; // Raw
1083 
1084     return iOldMode;
1085 }
1086 
1087 /*
1088  * @implemented
1089  *
1090  */
1091 int
1092 WINAPI
GetROP2(_In_ HDC hdc)1093 GetROP2(
1094     _In_ HDC hdc)
1095 {
1096     PDC_ATTR pdcattr;
1097 
1098     /* Get the DC attribute */
1099     pdcattr = GdiGetDcAttr(hdc);
1100     if (pdcattr == NULL)
1101     {
1102         /* Do not set LastError here! */
1103         return 0;
1104     }
1105 
1106     return pdcattr->jROP2;
1107 }
1108 
1109 /*
1110  * @implemented
1111  */
1112 int
1113 WINAPI
SetROP2(_In_ HDC hdc,_In_ int rop2)1114 SetROP2(
1115     _In_ HDC hdc,
1116     _In_ int rop2)
1117 {
1118     PDC_ATTR pdcattr;
1119     INT rop2Old;
1120 
1121     HANDLE_METADC(INT, SetROP2, 0, hdc, rop2);
1122 
1123     /* Get the DC attribute */
1124     pdcattr = GdiGetDcAttr(hdc);
1125     if (pdcattr == NULL)
1126     {
1127         SetLastError(ERROR_INVALID_PARAMETER);
1128         return 0;
1129     }
1130 
1131     if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1132     {
1133         if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
1134         {
1135             NtGdiFlush();
1136             pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
1137         }
1138     }
1139 
1140     rop2Old = pdcattr->jROP2;
1141     pdcattr->jROP2 = (BYTE)rop2;
1142 
1143     return rop2Old;
1144 }
1145 
1146 
1147 /*
1148  * @implemented
1149  *
1150  */
1151 int
1152 WINAPI
GetPolyFillMode(HDC hdc)1153 GetPolyFillMode(HDC hdc)
1154 {
1155     PDC_ATTR pdcattr;
1156 
1157     /* Get DC attribute */
1158     pdcattr = GdiGetDcAttr(hdc);
1159     if (pdcattr == NULL)
1160     {
1161         /* Don't set LastError here! */
1162         return 0;
1163     }
1164 
1165     /* Return current fill mode */
1166     return pdcattr->lFillMode;
1167 }
1168 
1169 /*
1170  * @unimplemented
1171  */
1172 int
1173 WINAPI
SetPolyFillMode(_In_ HDC hdc,_In_ int iPolyFillMode)1174 SetPolyFillMode(
1175     _In_ HDC hdc,
1176     _In_ int iPolyFillMode)
1177 {
1178     INT iOldPolyFillMode;
1179     PDC_ATTR pdcattr;
1180 
1181     HANDLE_METADC(INT, SetPolyFillMode, 0, hdc, iPolyFillMode);
1182 
1183     /* Get the DC attribute */
1184     pdcattr = GdiGetDcAttr(hdc);
1185     if (pdcattr == NULL)
1186     {
1187         SetLastError(ERROR_INVALID_PARAMETER);
1188         return 0;
1189     }
1190 
1191     if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1192     {
1193         if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
1194         {
1195             NtGdiFlush(); // Sync up pdcattr from Kernel space.
1196             pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
1197         }
1198     }
1199 
1200     iOldPolyFillMode = pdcattr->lFillMode;
1201     pdcattr->lFillMode = iPolyFillMode;
1202 
1203     return iOldPolyFillMode;
1204 }
1205 
1206 /*
1207  * @implemented
1208  *
1209  */
1210 int
1211 WINAPI
GetGraphicsMode(HDC hdc)1212 GetGraphicsMode(HDC hdc)
1213 {
1214     PDC_ATTR pdcattr;
1215 
1216     /* Get the DC attribute */
1217     pdcattr = GdiGetDcAttr(hdc);
1218     if (pdcattr == NULL)
1219     {
1220         /* Don't set LastError here! */
1221         return 0;
1222     }
1223 
1224     /* Return current graphics mode */
1225     return pdcattr->iGraphicsMode;
1226 }
1227 
1228 /*
1229  * @unimplemented
1230  */
1231 int
1232 WINAPI
SetGraphicsMode(_In_ HDC hdc,_In_ int iMode)1233 SetGraphicsMode(
1234     _In_ HDC hdc,
1235     _In_ int iMode)
1236 {
1237     INT iOldMode;
1238     PDC_ATTR pdcattr;
1239 
1240     /* Check parameters */
1241     if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
1242     {
1243         SetLastError(ERROR_INVALID_PARAMETER);
1244         return 0;
1245     }
1246 
1247     /* Get the DC attribute */
1248     pdcattr = GdiGetDcAttr(hdc);
1249     if (pdcattr == NULL)
1250     {
1251         SetLastError(ERROR_INVALID_PARAMETER);
1252         return 0;
1253     }
1254 
1255     /* Check for trivial case */
1256     if (iMode == pdcattr->iGraphicsMode)
1257         return iMode;
1258 
1259     if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1260     {
1261         if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
1262         {
1263             NtGdiFlush(); // Sync up pdcattr from Kernel space.
1264             pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
1265         }
1266     }
1267 
1268     /* One would think that setting the graphics mode to GM_COMPATIBLE
1269      * would also reset the world transformation matrix to the unity
1270      * matrix. However, in Windows, this is not the case. This doesn't
1271      * make a lot of sense to me, but that's the way it is.
1272      */
1273     iOldMode = pdcattr->iGraphicsMode;
1274     pdcattr->iGraphicsMode = iMode;
1275 
1276     return iOldMode;
1277 }
1278 
1279 /*
1280  * @implemented
1281  */
1282 HDC
1283 WINAPI
ResetDCW(_In_ HDC hdc,_In_ CONST DEVMODEW * lpInitData)1284 ResetDCW(
1285     _In_ HDC hdc,
1286     _In_ CONST DEVMODEW *lpInitData)
1287 {
1288     NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
1289     return hdc;
1290 }
1291 
1292 
1293 /*
1294  * @implemented
1295  */
1296 HDC
1297 WINAPI
ResetDCA(_In_ HDC hdc,_In_ CONST DEVMODEA * lpInitData)1298 ResetDCA(
1299     _In_ HDC hdc,
1300     _In_ CONST DEVMODEA *lpInitData)
1301 {
1302     LPDEVMODEW InitDataW;
1303 
1304     InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
1305 
1306     NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
1307     HEAP_free(InitDataW);
1308     return hdc;
1309 }
1310 
1311 
1312 /* FIXME: include correct header */
1313 HPALETTE WINAPI NtUserSelectPalette(HDC  hDC,
1314                                     HPALETTE  hpal,
1315                                     BOOL  ForceBackground);
1316 
1317 HPALETTE
1318 WINAPI
SelectPalette(HDC hdc,HPALETTE hpal,BOOL bForceBackground)1319 SelectPalette(
1320     HDC hdc,
1321     HPALETTE hpal,
1322     BOOL bForceBackground)
1323 {
1324     if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE)
1325     {
1326         if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
1327         {
1328            return (HPALETTE)((ULONG_PTR)METADC_SelectPalette(hdc, hpal));
1329         }
1330         else
1331         {
1332            PLDC pLDC = GdiGetLDC(hdc);
1333            if ( !pLDC )
1334            {
1335               SetLastError(ERROR_INVALID_HANDLE);
1336               return NULL;
1337            }
1338            if ( pLDC->iType == LDC_EMFLDC && !(EMFDC_SelectPalette(pLDC, hpal)) )
1339            {
1340               return NULL;
1341            }
1342         }
1343     }
1344     return NtUserSelectPalette(hdc, hpal, bForceBackground);
1345 }
1346 
1347 /*
1348  * @implemented
1349  *
1350  */
1351 int
1352 WINAPI
GetStretchBltMode(HDC hdc)1353 GetStretchBltMode(HDC hdc)
1354 {
1355     PDC_ATTR pdcattr;
1356 
1357     /* Get the DC attribute */
1358     pdcattr = GdiGetDcAttr(hdc);
1359     if (pdcattr == NULL)
1360     {
1361         /* Don't set LastError here! */
1362         return 0;
1363     }
1364 
1365     return pdcattr->lStretchBltMode;
1366 }
1367 
1368 /*
1369  * @implemented
1370  */
1371 int
1372 WINAPI
SetStretchBltMode(_In_ HDC hdc,_In_ int iStretchMode)1373 SetStretchBltMode(
1374     _In_ HDC hdc,
1375     _In_ int iStretchMode)
1376 {
1377     INT iOldMode;
1378     PDC_ATTR pdcattr;
1379 
1380     HANDLE_METADC(INT, SetStretchBltMode, 0, hdc, iStretchMode);
1381 
1382     /* Get the DC attribute */
1383     pdcattr = GdiGetDcAttr(hdc);
1384     if (pdcattr == NULL)
1385     {
1386         SetLastError(ERROR_INVALID_PARAMETER);
1387         return 0;
1388     }
1389 
1390     iOldMode = pdcattr->lStretchBltMode;
1391     pdcattr->lStretchBltMode = iStretchMode;
1392 
1393     // Wine returns an error here. We set the default.
1394     if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
1395 
1396     pdcattr->jStretchBltMode = iStretchMode;
1397 
1398     return iOldMode;
1399 }
1400 
1401 /*
1402  * @implemented
1403  */
1404 HFONT
1405 WINAPI
GetHFONT(HDC hdc)1406 GetHFONT(HDC hdc)
1407 {
1408     PDC_ATTR pdcattr;
1409 
1410     /* Get the DC attribute */
1411     pdcattr = GdiGetDcAttr(hdc);
1412     if (pdcattr == NULL)
1413     {
1414         /* Don't set LastError here! */
1415         return NULL;
1416     }
1417 
1418     /* Return the current font */
1419     return pdcattr->hlfntNew;
1420 }
1421 
1422 
1423 
1424 HBITMAP
1425 WINAPI
GdiSelectBitmap(_In_ HDC hdc,_In_ HBITMAP hbmp)1426 GdiSelectBitmap(
1427     _In_ HDC hdc,
1428     _In_ HBITMAP hbmp)
1429 {
1430     return NtGdiSelectBitmap(hdc, hbmp);
1431 }
1432 
1433 HBRUSH
1434 WINAPI
GdiSelectBrush(_In_ HDC hdc,_In_ HBRUSH hbr)1435 GdiSelectBrush(
1436     _In_ HDC hdc,
1437     _In_ HBRUSH hbr)
1438 {
1439     PDC_ATTR pdcattr;
1440     HBRUSH hbrOld;
1441 
1442     HANDLE_METADC(HBRUSH, SelectObject, NULL, hdc, hbr);
1443 
1444     /* Get the DC attribute */
1445     pdcattr = GdiGetDcAttr(hdc);
1446     if (pdcattr == NULL)
1447     {
1448         SetLastError(ERROR_INVALID_PARAMETER);
1449         return NULL;
1450     }
1451 
1452     /* Get the current brush. If it matches the new brush, we're done */
1453     hbrOld = pdcattr->hbrush;
1454     if (hbrOld == hbr)
1455         return hbrOld;
1456 
1457     /* Set the new brush and update dirty flags */
1458     pdcattr->hbrush = hbr;
1459     pdcattr->ulDirty_ |= DC_BRUSH_DIRTY;
1460     return hbrOld;
1461 }
1462 
1463 HPEN
1464 WINAPI
GdiSelectPen(_In_ HDC hdc,_In_ HPEN hpen)1465 GdiSelectPen(
1466     _In_ HDC hdc,
1467     _In_ HPEN hpen)
1468 {
1469     PDC_ATTR pdcattr;
1470     HPEN hpenOld;
1471 
1472     HANDLE_METADC(HPEN, SelectObject, NULL, hdc, hpen);
1473 
1474     /* Get the DC attribute */
1475     pdcattr = GdiGetDcAttr(hdc);
1476     if (pdcattr == NULL)
1477     {
1478         SetLastError(ERROR_INVALID_HANDLE);
1479         return NULL;
1480     }
1481 
1482     /* Get the current pen. If it matches the new pen, we're done */
1483     hpenOld = pdcattr->hpen;
1484     if (hpenOld == hpen)
1485         return hpenOld;
1486 
1487     /* Set the new pen and update dirty flags */
1488     pdcattr->ulDirty_ |= DC_PEN_DIRTY;
1489     pdcattr->hpen = hpen;
1490     return hpenOld;
1491 }
1492 
1493 HFONT
1494 WINAPI
GdiSelectFont(_In_ HDC hdc,_In_ HFONT hfont)1495 GdiSelectFont(
1496     _In_ HDC hdc,
1497     _In_ HFONT hfont)
1498 {
1499     PDC_ATTR pdcattr;
1500     HFONT hfontOld;
1501 
1502     HANDLE_METADC(HFONT, SelectObject, NULL, hdc, hfont);
1503 
1504     /* Get the DC attribute */
1505     pdcattr = GdiGetDcAttr(hdc);
1506     if (pdcattr == NULL)
1507     {
1508         SetLastError(ERROR_INVALID_PARAMETER);
1509         return NULL;
1510     }
1511 
1512     /* Get the current font. If it matches the new font, we're done */
1513     hfontOld = pdcattr->hlfntNew;
1514     if (hfontOld == hfont)
1515         return hfontOld;
1516 
1517     /* Set the new font and update dirty flags */
1518     pdcattr->hlfntNew = hfont;
1519     pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
1520     pdcattr->ulDirty_ |= DIRTY_CHARSET;
1521 
1522     /* If the DC does not have a DIB section selected, try a batch command */
1523     if (!(pdcattr->ulDirty_ & DC_DIBSECTION))
1524     {
1525         PGDIBSOBJECT pgO;
1526 
1527         pgO = GdiAllocBatchCommand(hdc, GdiBCSelObj);
1528         if (pgO)
1529         {
1530             pgO->hgdiobj = hfont;
1531             return hfontOld;
1532         }
1533     }
1534 
1535     /* We could not use the batch command, call win32k */
1536     return NtGdiSelectFont(hdc, hfont);
1537 }
1538 
1539 
1540 /*
1541  * @implemented
1542  *
1543  */
1544 HGDIOBJ
1545 WINAPI
SelectObject(_In_ HDC hdc,_In_ HGDIOBJ hobj)1546 SelectObject(
1547     _In_ HDC hdc,
1548     _In_ HGDIOBJ hobj)
1549 {
1550     /* Fix up 16 bit handles */
1551     hobj = GdiFixUpHandle(hobj);
1552     if (!GdiValidateHandle(hobj))
1553     {
1554         return NULL;
1555     }
1556 
1557     /* Call the appropriate select function */
1558     switch (GDI_HANDLE_GET_TYPE(hobj))
1559     {
1560         case GDILoObjType_LO_REGION_TYPE:
1561             return (HGDIOBJ)UlongToHandle(ExtSelectClipRgn(hdc, hobj, RGN_COPY));
1562 
1563         case GDILoObjType_LO_BITMAP_TYPE:
1564         case GDILoObjType_LO_DIBSECTION_TYPE:
1565             return GdiSelectBitmap(hdc, hobj);
1566 
1567         case GDILoObjType_LO_BRUSH_TYPE:
1568             return GdiSelectBrush(hdc, hobj);
1569 
1570         case GDILoObjType_LO_PEN_TYPE:
1571         case GDILoObjType_LO_EXTPEN_TYPE:
1572             return GdiSelectPen(hdc, hobj);
1573 
1574         case GDILoObjType_LO_FONT_TYPE:
1575             return GdiSelectFont(hdc, hobj);
1576 
1577         case GDILoObjType_LO_ICMLCS_TYPE:
1578             return SetColorSpace(hdc, hobj);
1579 
1580         case GDILoObjType_LO_PALETTE_TYPE:
1581             SetLastError(ERROR_INVALID_FUNCTION);
1582 
1583         default:
1584             return NULL;
1585     }
1586 
1587     return NULL;
1588 }
1589