xref: /reactos/win32ss/gdi/ntgdi/dcutil.c (revision 37b2c145)
1 #include <win32k.h>
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 BOOL FASTCALL
7 GreDPtoLP(HDC hdc, LPPOINT lpPoints, INT nCount)
8 {
9    PDC dc;
10    if (!(dc = DC_LockDc(hdc)))
11    {
12       EngSetLastError(ERROR_INVALID_HANDLE);
13       return FALSE;
14    }
15    IntDPtoLP(dc, lpPoints, nCount);
16    DC_UnlockDc(dc);
17    return TRUE;
18 }
19 
20 BOOL FASTCALL
21 GreLPtoDP(HDC hdc, LPPOINT lpPoints, INT nCount)
22 {
23    PDC dc;
24    if (!(dc = DC_LockDc(hdc)))
25    {
26       EngSetLastError(ERROR_INVALID_HANDLE);
27       return FALSE;
28    }
29    IntLPtoDP(dc, lpPoints, nCount);
30    DC_UnlockDc(dc);
31    return TRUE;
32 }
33 
34 int FASTCALL
35 GreGetBkMode(HDC hdc)
36 {
37    PDC dc;
38    LONG lBkMode;
39    if (!(dc = DC_LockDc(hdc)))
40    {
41       EngSetLastError(ERROR_INVALID_HANDLE);
42       return CLR_INVALID;
43    }
44    lBkMode = dc->pdcattr->lBkMode;
45    DC_UnlockDc(dc);
46    return lBkMode;
47 }
48 
49 COLORREF FASTCALL
50 GreGetBkColor(HDC hdc)
51 {
52    PDC dc;
53    COLORREF crBk;
54    if (!(dc = DC_LockDc(hdc)))
55    {
56       EngSetLastError(ERROR_INVALID_HANDLE);
57       return CLR_INVALID;
58    }
59    crBk = dc->pdcattr->ulBackgroundClr;
60    DC_UnlockDc(dc);
61    return crBk;
62 }
63 
64 int FASTCALL
65 GreGetMapMode(HDC hdc)
66 {
67    PDC dc;
68    INT iMapMode;
69    if (!(dc = DC_LockDc(hdc)))
70    {
71       EngSetLastError(ERROR_INVALID_HANDLE);
72       return CLR_INVALID;
73    }
74    iMapMode = dc->pdcattr->iMapMode;
75    DC_UnlockDc(dc);
76    return iMapMode;
77 }
78 
79 COLORREF FASTCALL
80 GreGetTextColor(HDC hdc)
81 {
82    PDC dc;
83    ULONG ulForegroundClr;
84    if (!(dc = DC_LockDc(hdc)))
85    {
86       EngSetLastError(ERROR_INVALID_HANDLE);
87       return CLR_INVALID;
88    }
89    ulForegroundClr = dc->pdcattr->ulForegroundClr;
90    DC_UnlockDc(dc);
91    return ulForegroundClr;
92 }
93 
94 COLORREF FASTCALL
95 IntGdiSetBkColor(HDC hDC, COLORREF color)
96 {
97     COLORREF oldColor;
98     PDC dc;
99     PDC_ATTR pdcattr;
100     HBRUSH hBrush;
101 
102     if (!(dc = DC_LockDc(hDC)))
103     {
104         EngSetLastError(ERROR_INVALID_HANDLE);
105         return CLR_INVALID;
106     }
107     pdcattr = dc->pdcattr;
108 
109     oldColor = pdcattr->ulBackgroundClr;
110     pdcattr->ulBackgroundClr = color;
111 
112     if (pdcattr->crBackgroundClr != color)
113     {
114         pdcattr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); // Clear Flag if set.
115         pdcattr->crBackgroundClr = color;
116     }
117     hBrush = pdcattr->hbrush;
118     DC_UnlockDc(dc);
119     NtGdiSelectBrush(hDC, hBrush);
120     return oldColor;
121 }
122 
123 INT FASTCALL
124 IntGdiSetBkMode(HDC hDC, INT Mode)
125 {
126     COLORREF oldMode;
127     PDC dc;
128     PDC_ATTR pdcattr;
129 
130     if (!(dc = DC_LockDc(hDC)))
131     {
132         EngSetLastError(ERROR_INVALID_HANDLE);
133         return CLR_INVALID;
134     }
135     pdcattr = dc->pdcattr;
136     oldMode = pdcattr->lBkMode;
137     pdcattr->jBkMode = Mode;
138     pdcattr->lBkMode = Mode;
139     DC_UnlockDc(dc);
140     return oldMode;
141 }
142 
143 UINT
144 FASTCALL
145 IntGdiSetTextAlign(HDC  hDC,
146                    UINT  Mode)
147 {
148     UINT prevAlign;
149     DC *dc;
150     PDC_ATTR pdcattr;
151 
152     dc = DC_LockDc(hDC);
153     if (!dc)
154     {
155         EngSetLastError(ERROR_INVALID_HANDLE);
156         return GDI_ERROR;
157     }
158     pdcattr = dc->pdcattr;
159     prevAlign = pdcattr->lTextAlign;
160     pdcattr->lTextAlign = Mode;
161     if (pdcattr->dwLayout & LAYOUT_RTL)
162     {
163         if ((Mode & TA_CENTER) != TA_CENTER) Mode ^= TA_RIGHT;
164     }
165     pdcattr->flTextAlign = Mode & TA_MASK;
166     DC_UnlockDc(dc);
167     return  prevAlign;
168 }
169 
170 COLORREF
171 FASTCALL
172 IntGdiSetTextColor(HDC hDC,
173                    COLORREF color)
174 {
175     COLORREF crOldColor;
176     PDC pdc;
177     PDC_ATTR pdcattr;
178 
179     pdc = DC_LockDc(hDC);
180     if (!pdc)
181     {
182         EngSetLastError(ERROR_INVALID_HANDLE);
183         return CLR_INVALID;
184     }
185     pdcattr = pdc->pdcattr;
186 
187     crOldColor = (COLORREF) pdcattr->ulForegroundClr;
188     pdcattr->ulForegroundClr = (ULONG)color;
189 
190     if (pdcattr->crForegroundClr != color)
191     {
192         pdcattr->ulDirty_ |= (DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL);
193         pdcattr->crForegroundClr = color;
194     }
195 
196     DC_vUpdateTextBrush(pdc);
197     DC_vUpdateLineBrush(pdc);
198     DC_vUpdateFillBrush(pdc);
199 
200     DC_UnlockDc(pdc);
201 
202     return  crOldColor;
203 }
204 
205 COLORREF FASTCALL
206 IntSetDCBrushColor(HDC hdc, COLORREF crColor)
207 {
208    COLORREF OldColor = CLR_INVALID;
209    PDC dc;
210    if (!(dc = DC_LockDc(hdc)))
211    {
212       EngSetLastError(ERROR_INVALID_HANDLE);
213       return CLR_INVALID;
214    }
215    else
216    {
217       OldColor = (COLORREF) dc->pdcattr->ulBrushClr;
218       dc->pdcattr->ulBrushClr = (ULONG) crColor;
219 
220       if ( dc->pdcattr->crBrushClr != crColor )
221       {
222          dc->pdcattr->ulDirty_ |= DIRTY_FILL;
223          dc->pdcattr->crBrushClr = crColor;
224       }
225    }
226    DC_UnlockDc(dc);
227    return OldColor;
228 }
229 
230 BOOL FASTCALL
231 GreSetBrushOrg(
232     HDC hdc,
233     INT x,
234     INT y,
235     LPPOINT pptOut)
236 {
237     PDC pdc = DC_LockDc(hdc);
238     if (pdc == NULL)
239     {
240         EngSetLastError(ERROR_INVALID_HANDLE);
241         return FALSE;
242     }
243 
244     if (pptOut != NULL)
245     {
246         *pptOut = pdc->pdcattr->ptlBrushOrigin;
247     }
248 
249     pdc->pdcattr->ptlBrushOrigin.x = x;
250     pdc->pdcattr->ptlBrushOrigin.y = y;
251 
252     DC_vSetBrushOrigin(pdc, x, y);
253 
254     DC_UnlockDc(pdc);
255     return TRUE;
256 }
257 
258 COLORREF FASTCALL
259 IntSetDCPenColor(HDC hdc, COLORREF crColor)
260 {
261    COLORREF OldColor;
262    PDC dc;
263    if (!(dc = DC_LockDc(hdc)))
264    {
265       EngSetLastError(ERROR_INVALID_PARAMETER);
266       return CLR_INVALID;
267    }
268 
269    OldColor = (COLORREF)dc->pdcattr->ulPenClr;
270    dc->pdcattr->ulPenClr = (ULONG)crColor;
271 
272    if (dc->pdcattr->crPenClr != crColor)
273    {
274       dc->pdcattr->ulDirty_ |= DIRTY_LINE;
275       dc->pdcattr->crPenClr = crColor;
276    }
277    DC_UnlockDc(dc);
278    return OldColor;
279 }
280 
281 int
282 FASTCALL
283 GreSetStretchBltMode(HDC hDC, int iStretchMode)
284 {
285     PDC pdc;
286     PDC_ATTR pdcattr;
287     INT oSMode = 0;
288 
289     pdc = DC_LockDc(hDC);
290     if (pdc)
291     {
292        pdcattr = pdc->pdcattr;
293        oSMode = pdcattr->lStretchBltMode;
294        pdcattr->lStretchBltMode = iStretchMode;
295 
296        // Wine returns an error here. We set the default.
297        if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
298 
299        pdcattr->jStretchBltMode = iStretchMode;
300        DC_UnlockDc(pdc);
301     }
302     return oSMode;
303 }
304 
305 int FASTCALL
306 GreGetGraphicsMode(HDC hdc)
307 {
308    PDC dc;
309    int GraphicsMode;
310    if (!(dc = DC_LockDc(hdc)))
311    {
312       EngSetLastError(ERROR_INVALID_HANDLE);
313       return CLR_INVALID;
314    }
315    GraphicsMode = dc->pdcattr->iGraphicsMode;
316    DC_UnlockDc(dc);
317    return GraphicsMode;
318 }
319 
320 VOID
321 FASTCALL
322 DCU_SetDcUndeletable(HDC  hDC)
323 {
324     PDC dc = DC_LockDc(hDC);
325     if (!dc)
326     {
327         EngSetLastError(ERROR_INVALID_HANDLE);
328         return;
329     }
330 
331     dc->fs |= DC_FLAG_PERMANENT;
332     DC_UnlockDc(dc);
333     return;
334 }
335 
336 #if 0
337 BOOL FASTCALL
338 IntIsPrimarySurface(SURFOBJ *SurfObj)
339 {
340     if (PrimarySurface.pSurface == NULL)
341     {
342         return FALSE;
343     }
344     return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
345 }
346 #endif
347 
348 BOOL
349 FASTCALL
350 IntSetDefaultRegion(PDC pdc)
351 {
352     PSURFACE pSurface;
353     PREGION prgn;
354     RECTL rclWnd, rclClip;
355 
356     IntGdiReleaseRaoRgn(pdc);
357 
358     rclWnd.left   = 0;
359     rclWnd.top    = 0;
360     rclWnd.right  = pdc->dclevel.sizl.cx;
361     rclWnd.bottom = pdc->dclevel.sizl.cy;
362     rclClip = rclWnd;
363 
364     //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
365     if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
366     {
367         pSurface = pdc->dclevel.pSurface;
368         if (pSurface && pSurface->flags & PDEV_SURFACE)
369         {
370             rclClip.left   += pdc->ppdev->ptlOrigion.x;
371             rclClip.top    += pdc->ppdev->ptlOrigion.y;
372             rclClip.right  += pdc->ppdev->ptlOrigion.x;
373             rclClip.bottom += pdc->ppdev->ptlOrigion.y;
374         }
375     }
376     //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
377 
378     prgn = pdc->prgnVis;
379 
380     if (prgn && prgn != prgnDefault)
381     {
382         REGION_SetRectRgn( prgn,
383                            rclClip.left,
384                            rclClip.top,
385                            rclClip.right ,
386                            rclClip.bottom );
387     }
388     else
389     {
390         prgn = IntSysCreateRectpRgn( rclClip.left,
391                                      rclClip.top,
392                                      rclClip.right ,
393                                      rclClip.bottom );
394         pdc->prgnVis = prgn;
395     }
396 
397     if (prgn)
398     {
399         pdc->ptlDCOrig.x = 0;
400         pdc->ptlDCOrig.y = 0;
401         pdc->erclWindow = rclWnd;
402         pdc->erclClip = rclClip;
403         /* Might be an InitDC or DCE... */
404         pdc->ptlFillOrigin = pdc->dcattr.ptlBrushOrigin;
405         return TRUE;
406     }
407     // No Vis use the Default System Region.
408     pdc->prgnVis = prgnDefault;
409     return FALSE;
410 }
411 
412 
413 BOOL APIENTRY
414 NtGdiCancelDC(HDC  hDC)
415 {
416     UNIMPLEMENTED;
417     return FALSE;
418 }
419 
420 
421 WORD APIENTRY
422 IntGdiSetHookFlags(HDC hDC, WORD Flags)
423 {
424     WORD wRet;
425     DC *dc = DC_LockDc(hDC);
426 
427     if (NULL == dc)
428     {
429         EngSetLastError(ERROR_INVALID_HANDLE);
430         return 0;
431     }
432 
433     wRet = dc->fs & DC_FLAG_DIRTY_RAO; // FIXME: Wrong flag!
434 
435     /* Info in "Undocumented Windows" is slightly confusing. */
436     DPRINT("DC %p, Flags %04x\n", hDC, Flags);
437 
438     if (Flags & DCHF_INVALIDATEVISRGN)
439     {
440         /* hVisRgn has to be updated */
441         dc->fs |= DC_FLAG_DIRTY_RAO;
442     }
443     else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
444     {
445         //dc->fs &= ~DC_FLAG_DIRTY_RAO;
446     }
447 
448     DC_UnlockDc(dc);
449 
450     return wRet;
451 }
452 
453 
454 BOOL
455 APIENTRY
456 NtGdiGetDCDword(
457     HDC hDC,
458     UINT u,
459     DWORD *Result)
460 {
461     BOOL Ret = TRUE;
462     PDC pdc;
463     PDC_ATTR pdcattr;
464 
465     DWORD SafeResult = 0;
466     NTSTATUS Status = STATUS_SUCCESS;
467 
468     if (!Result)
469     {
470         EngSetLastError(ERROR_INVALID_PARAMETER);
471         return FALSE;
472     }
473 
474     pdc = DC_LockDc(hDC);
475     if (!pdc)
476     {
477         EngSetLastError(ERROR_INVALID_HANDLE);
478         return FALSE;
479     }
480     pdcattr = pdc->pdcattr;
481 
482     switch (u)
483     {
484         case GdiGetJournal:
485             break;
486 
487         case GdiGetRelAbs:
488             SafeResult = pdcattr->lRelAbs;
489             break;
490 
491         case GdiGetBreakExtra:
492             SafeResult = pdcattr->lBreakExtra;
493             break;
494 
495         case GdiGerCharBreak:
496             SafeResult = pdcattr->cBreak;
497             break;
498 
499         case GdiGetArcDirection:
500             if (pdcattr->dwLayout & LAYOUT_RTL)
501                 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
502             else
503                 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
504             break;
505 
506         case GdiGetEMFRestorDc:
507             SafeResult = pdc->dclevel.lSaveDepth;
508             break;
509 
510         case GdiGetFontLanguageInfo:
511             SafeResult = IntGetFontLanguageInfo(pdc);
512             break;
513 
514         case GdiGetIsMemDc:
515             SafeResult = pdc->dctype;
516             break;
517 
518         case GdiGetMapMode:
519             SafeResult = pdcattr->iMapMode;
520             break;
521 
522         case GdiGetTextCharExtra:
523             SafeResult = pdcattr->lTextExtra;
524             break;
525 
526         default:
527             EngSetLastError(ERROR_INVALID_PARAMETER);
528             Ret = FALSE;
529             break;
530     }
531 
532     if (Ret)
533     {
534         _SEH2_TRY
535         {
536             ProbeForWrite(Result, sizeof(DWORD), 1);
537             *Result = SafeResult;
538         }
539         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
540         {
541             Status = _SEH2_GetExceptionCode();
542         }
543         _SEH2_END;
544 
545         if (!NT_SUCCESS(Status))
546         {
547             SetLastNtError(Status);
548             Ret = FALSE;
549         }
550     }
551 
552     DC_UnlockDc(pdc);
553     return Ret;
554 }
555 
556 _Success_(return != FALSE)
557 BOOL
558 APIENTRY
559 NtGdiGetAndSetDCDword(
560     _In_ HDC hdc,
561     _In_ UINT u,
562     _In_ DWORD dwIn,
563     _Out_ DWORD *pdwResult)
564 {
565     BOOL Ret = TRUE;
566     PDC pdc;
567     PDC_ATTR pdcattr;
568 
569     DWORD SafeResult = 0;
570     NTSTATUS Status = STATUS_SUCCESS;
571 
572     if (!pdwResult)
573     {
574         EngSetLastError(ERROR_INVALID_PARAMETER);
575         return FALSE;
576     }
577 
578     pdc = DC_LockDc(hdc);
579     if (!pdc)
580     {
581         EngSetLastError(ERROR_INVALID_HANDLE);
582         return FALSE;
583     }
584     pdcattr = pdc->pdcattr;
585 
586     switch (u)
587     {
588         case GdiGetSetCopyCount:
589             SafeResult = pdc->ulCopyCount;
590             pdc->ulCopyCount = dwIn;
591             break;
592 
593         case GdiGetSetTextAlign:
594             SafeResult = pdcattr->lTextAlign;
595             pdcattr->lTextAlign = dwIn;
596             // pdcattr->flTextAlign = dwIn; // Flags!
597             break;
598 
599         case GdiGetSetRelAbs:
600             SafeResult = pdcattr->lRelAbs;
601             pdcattr->lRelAbs = dwIn;
602             break;
603 
604         case GdiGetSetTextCharExtra:
605             SafeResult = pdcattr->lTextExtra;
606             pdcattr->lTextExtra = dwIn;
607             break;
608 
609         case GdiGetSetSelectFont:
610             break;
611 
612         case GdiGetSetMapperFlagsInternal:
613             if (dwIn & ~1)
614             {
615                 EngSetLastError(ERROR_INVALID_PARAMETER);
616                 Ret = FALSE;
617                 break;
618             }
619             SafeResult = pdcattr->flFontMapper;
620             pdcattr->flFontMapper = dwIn;
621             break;
622 
623         case GdiGetSetMapMode:
624             SafeResult = IntGdiSetMapMode(pdc, dwIn);
625             break;
626 
627         case GdiGetSetArcDirection:
628             if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
629             {
630                 EngSetLastError(ERROR_INVALID_PARAMETER);
631                 Ret = FALSE;
632                 break;
633             }
634             if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
635             {
636                 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
637                 if (dwIn == AD_CLOCKWISE)
638                 {
639                     pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
640                     break;
641                 }
642                 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
643             }
644             else // Left to Right
645             {
646                 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
647                              AD_COUNTERCLOCKWISE;
648                 if (dwIn == AD_COUNTERCLOCKWISE)
649                 {
650                     pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
651                     break;
652                 }
653                 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
654             }
655             break;
656 
657         default:
658             EngSetLastError(ERROR_INVALID_PARAMETER);
659             Ret = FALSE;
660             break;
661     }
662 
663     if (Ret)
664     {
665         _SEH2_TRY
666         {
667             ProbeForWrite(pdwResult, sizeof(DWORD), 1);
668             *pdwResult = SafeResult;
669         }
670         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
671         {
672             Status = _SEH2_GetExceptionCode();
673         }
674         _SEH2_END;
675 
676         if (!NT_SUCCESS(Status))
677         {
678             SetLastNtError(Status);
679             Ret = FALSE;
680         }
681     }
682 
683     DC_UnlockDc(pdc);
684     return Ret;
685 }
686 
687 VOID
688 FASTCALL
689 IntUpdateBoundsRect(PDC pdc, PRECTL pRect)
690 {
691    if (pdc->fs & DC_ACCUM_APP)
692    {
693       RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, pRect);
694    }
695    if (pdc->fs & DC_ACCUM_WMGR)
696    {
697       RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, pRect);
698    }
699 }
700 
701 DWORD
702 APIENTRY
703 NtGdiGetBoundsRect(
704     IN HDC hdc,
705     OUT LPRECT prc,
706     IN DWORD flags)
707 {
708     DWORD ret;
709     PDC pdc;
710     RECT rc;
711 
712     /* Lock the DC */
713     if (!(pdc = DC_LockDc(hdc))) return 0;
714 
715     if (!(flags & DCB_WINDOWMGR))
716     {
717        rc = pdc->erclBoundsApp;
718 
719        if (RECTL_bIsEmptyRect(&rc))
720        {
721           rc.left = rc.top = rc.right = rc.bottom = 0;
722           ret = DCB_RESET;
723        }
724        else
725        {
726           RECTL rcRgn;
727           if (pdc->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdc);
728           if(!REGION_GetRgnBox(pdc->prgnRao, &rcRgn))
729           {
730              REGION_GetRgnBox(pdc->prgnVis, &rcRgn);
731           }
732           rc.left   = max( rc.left, 0 );
733           rc.top    = max( rc.top, 0 );
734           rc.right  = min( rc.right,  rcRgn.right - rcRgn.left );
735           rc.bottom = min( rc.bottom, rcRgn.bottom - rcRgn.top );
736           DPRINT("Rao dc %p r %d b %d\n",pdc,rcRgn.right - rcRgn.left, rcRgn.bottom - rcRgn.top);
737           DPRINT("rc  l %d t %d\n",rc.left,rc.top);
738           DPRINT("    r %d b %d\n",rc.right,rc.bottom);
739           ret = DCB_SET;
740        }
741        IntDPtoLP( pdc, &rc, 2 );
742        DPRINT("rc1 l %d t %d\n",rc.left,rc.top);
743        DPRINT("    r %d b %d\n",rc.right,rc.bottom);
744     }
745     else
746     {
747        rc = pdc->erclBounds;
748        ret = DCB_SET;
749     }
750 
751     /* Copy the rect to the caller */
752     _SEH2_TRY
753     {
754         ProbeForWrite(prc, sizeof(RECT), 1);
755         *prc = rc;
756     }
757     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
758     {
759         ret = 0;
760     }
761     _SEH2_END;
762 
763     if (flags & DCB_RESET)
764     {
765         if (!(flags & DCB_WINDOWMGR))
766         {
767            pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
768            pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
769         }
770         else
771         {
772            pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
773            pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
774         }
775     }
776 
777     DC_UnlockDc(pdc);
778     return ret;
779 }
780 
781 DWORD
782 APIENTRY
783 NtGdiSetBoundsRect(
784     IN HDC hdc,
785     IN LPRECT prc,
786     IN DWORD flags)
787 {
788     DWORD ret;
789     PDC pdc;
790     RECTL rcl;
791 
792     /* Verify arguments */
793     if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
794 
795     /* Lock the DC */
796     if (!(pdc = DC_LockDc(hdc))) return 0;
797 
798     /* Get the return value */
799     ret = DCB_RESET; /* we don't have device-specific bounds */
800     ret = (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR) ? DCB_ENABLE : DCB_DISABLE) |
801           (RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? ret & DCB_SET : DCB_SET );
802     ret |= (flags & DCB_WINDOWMGR);
803 
804     if (flags & DCB_RESET)
805     {
806         if (!(flags & DCB_WINDOWMGR))
807         {
808            pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
809            pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
810         }
811         else
812         {
813            pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
814            pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
815         }
816     }
817 
818     if (flags & DCB_ACCUMULATE && prc != NULL)
819     {
820         /* Capture the rect */
821         _SEH2_TRY
822         {
823             ProbeForRead(prc, sizeof(RECT), 1);
824             rcl = *prc;
825         }
826         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
827         {
828             DC_UnlockDc(pdc);
829             _SEH2_YIELD(return 0;)
830         }
831         _SEH2_END;
832 
833         RECTL_vMakeWellOrdered(&rcl);
834 
835         if (!(flags & DCB_WINDOWMGR))
836         {
837            IntLPtoDP( pdc, (POINT *)&rcl, 2 );
838            RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
839         }
840         else
841            RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, &rcl);
842     }
843 
844     if (flags & DCB_ENABLE)
845     {
846        if (!(flags & DCB_WINDOWMGR))
847           pdc->fs |= DC_ACCUM_APP;
848        else
849           pdc->fs |= DC_ACCUM_WMGR;
850     }
851     if (flags & DCB_DISABLE)
852     {
853        if (!(flags & DCB_WINDOWMGR))
854           pdc->fs &= ~DC_ACCUM_APP;
855        else
856           pdc->fs &= ~DC_ACCUM_WMGR;
857     }
858     DC_UnlockDc(pdc);
859     return ret;
860 }
861 
862 /* Translates a COLORREF to the right color in the specified DC color space */
863 ULONG
864 TranslateCOLORREF(PDC pdc, COLORREF crColor)
865 {
866     PSURFACE psurfDC;
867     PPALETTE ppalDC;
868     ULONG index, ulColor, iBitmapFormat;
869     EXLATEOBJ exlo;
870 
871     /* Get the DC surface */
872     psurfDC = pdc->dclevel.pSurface;
873 
874     /* If no surface is selected, use the default bitmap */
875     if (!psurfDC)
876         psurfDC = psurfDefaultBitmap;
877 
878     /* Check what color type this is */
879     switch (crColor >> 24)
880     {
881         case 0x00: /* RGB color */
882             break;
883 
884         case 0x01: /* PALETTEINDEX */
885             index = crColor & 0xFFFFFF;
886             ppalDC = pdc->dclevel.ppal;
887             if (index >= ppalDC->NumColors) index = 0;
888 
889             /* Get the RGB value */
890             crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
891             break;
892 
893         case 0x02: /* PALETTERGB */
894 
895             if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
896             {
897                 /* First find the nearest index in the dc palette */
898                 ppalDC = pdc->dclevel.ppal;
899                 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
900 
901                 /* Get the RGB value */
902                 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
903             }
904             else
905             {
906                 /* Use the pure color */
907                 crColor = crColor & 0x00FFFFFF;
908             }
909             break;
910 
911         case 0x10: /* DIBINDEX */
912             /* Mask the value to match the target bpp */
913             iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
914             if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
915             else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
916             else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
917             else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
918             else index = crColor & 0xFFFFFF;
919             return index;
920 
921         default:
922             DPRINT("Unsupported color type %u passed\n", crColor >> 24);
923             crColor &= 0xFFFFFF;
924     }
925 
926     /* Initialize an XLATEOBJ from RGB to the target surface */
927     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
928 
929     /* Translate the color to the target format */
930     ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
931 
932     /* Cleanup the XLATEOBJ */
933     EXLATEOBJ_vCleanup(&exlo);
934 
935     return ulColor;
936 }
937 
938 
939