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