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