3 * Copyright (C) 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * PROJECT: ReactOS gdi32.dll
21 * FILE: win32ss/gdi/gdi32/misc/misc.c
22 * PURPOSE: Miscellaneous functions
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
33 PGDI_TABLE_ENTRY GdiHandleTable
= NULL
;
34 PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable
= NULL
;
35 HANDLE CurrentProcessId
= NULL
;
36 DWORD GDI_BatchLimit
= 1;
37 extern PGDIHANDLECACHE GdiHandleCache
;
59 _In_ LPCSTR lpvInData
,
60 _Out_ LPVOID lpvOutData
)
62 INT retValue
= SP_ERROR
;
65 ulObjType
= GDI_HANDLE_GET_TYPE(hdc
);
67 if (ulObjType
== GDILoObjType_LO_METADC16_TYPE
)
69 return METADC16_Escape(hdc
, nEscape
, cbInput
, lpvInData
, lpvOutData
);
75 /* Note: Windows checks if the handle has any user data for the ABORTDOC command
76 * ReactOS copies this behavior to be compatible with windows 2003
78 if (GdiGetDcAttr(hdc
) == NULL
)
80 GdiSetLastError(ERROR_INVALID_HANDLE
);
85 retValue
= AbortDoc(hdc
);
92 /* Note 1: DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE are outdated */
93 /* Note 2: Windows checks if the handle has any user data for the DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE commands
94 * ReactOS copies this behavior to be compatible with windows 2003
96 if (GdiGetDcAttr(hdc
) == NULL
)
98 GdiSetLastError(ERROR_INVALID_HANDLE
);
104 /* Note: Windows checks if the handle has any user data for the SETABORTPROC command
105 * ReactOS copies this behavior to be compatible with windows 2003
107 if (GdiGetDcAttr(hdc
) == NULL
)
109 GdiSetLastError(ERROR_INVALID_HANDLE
);
112 retValue
= SetAbortProc(hdc
, (ABORTPROC
)lpvInData
);
116 retValue
= GetSystemPaletteEntries(hdc
, (UINT
)*lpvInData
, 1, (LPPALETTEENTRY
)lpvOutData
);
124 /* Note: Windows checks if the handle has any user data for the ENDDOC command
125 * ReactOS copies this behavior to be compatible with windows 2003
127 if (GdiGetDcAttr(hdc
) == NULL
)
129 GdiSetLastError(ERROR_INVALID_HANDLE
);
132 retValue
= EndDoc(hdc
);
135 case GETSCALINGFACTOR
:
136 /* Note GETSCALINGFACTOR is outdated have been replace by GetDeviceCaps */
137 if (ulObjType
== GDI_OBJECT_TYPE_DC
)
141 PPOINT ptr
= (PPOINT
)lpvOutData
;
149 case GETEXTENDEDTEXTMETRICS
:
150 retValue
= GetETM(hdc
, (EXTTEXTMETRIC
*)lpvOutData
) != 0;
157 /* Note: Windows checks if the handle has any user data for the STARTDOC command
158 * ReactOS copies this behavior to be compatible with windows 2003
160 if (GdiGetDcAttr(hdc
) == NULL
)
162 GdiSetLastError(ERROR_INVALID_HANDLE
);
166 di
.cbSize
= sizeof(DOCINFOA
);
170 di
.lpszDocName
= lpvInData
;
172 /* NOTE : doc for StartDocA/W at msdn http://msdn2.microsoft.com/en-us/library/ms535793(VS.85).aspx */
173 retValue
= StartDocA(hdc
, &di
);
175 /* Check if StartDocA failed */
179 retValue
= GetLastError();
181 /* Translate StartDocA error code to STARTDOC error code
182 * see msdn http://msdn2.microsoft.com/en-us/library/ms535472.aspx
186 case ERROR_NOT_ENOUGH_MEMORY
:
187 retValue
= SP_OUTOFMEMORY
;
190 case ERROR_PRINT_CANCELLED
:
191 retValue
= SP_USERABORT
;
194 case ERROR_DISK_FULL
:
195 retValue
= SP_OUTOFDISK
;
209 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
224 return NtGdiExtEscape(hDC
, NULL
, 0, nEscape
, cbInput
, (LPSTR
)lpszInData
, cbOutput
, lpszOutData
);
237 /* FIXME metadc, metadc are done most in user mode, and we do not support it
238 * Windows 2000/XP/Vista ignore the current hdc, that are being pass and always set hdc to NULL
239 * when it calls to NtGdiExtEscape from NamedEscape
241 return NtGdiExtEscape(NULL
,pDriver
,wcslen(pDriver
),iEsc
,cjIn
,pjIn
,cjOut
,pjOut
);
254 if (GDI_HANDLE_GET_TYPE(hDC
) == GDI_OBJECT_TYPE_DC
)
255 return NtGdiDrawEscape(hDC
, nEscape
, cbInput
, (LPSTR
) lpszInData
);
257 if (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_METADC
)
259 PLDC pLDC
= GdiGetLDC(hDC
);
262 if (pLDC
->Flags
& LDC_META_PRINT
)
264 // if (nEscape != QUERYESCSUPPORT)
265 // return EMFDRV_WriteEscape(hDC, nEscape, cbInput, lpszInData, EMR_DRAWESCAPE);
267 return NtGdiDrawEscape(hDC
, nEscape
, cbInput
, (LPSTR
) lpszInData
);
270 SetLastError(ERROR_INVALID_HANDLE
);
275 #define ALPHABLEND_NONE 0
276 #define ALPHABLEND_BINARY 1
277 #define ALPHABLEND_FULL 2
279 typedef struct _MARGINS
{
284 } MARGINS
, *PMARGINS
;
286 typedef struct GDI_DRAW_STREAM_TAG
288 DWORD signature
; // must be 0x44727753;//"Swrd"
289 DWORD reserved
; // must be 0
290 HDC hDC
; // handle to the device object of windiw to draw.
291 RECT rcDest
; // desination rect of window to draw.
292 DWORD unknown1
; // must be 1.
294 DWORD unknown2
; // must be 9.
295 RECT rcClip
; // desination rect of window to draw.
296 RECT rcSrc
; // source rect of bitmap to draw.
297 DWORD drawOption
; // 0x2 is tile instead of stretch. 0x4 is transparent. 0x20 is true size
298 DWORD leftSizingMargin
;
299 DWORD rightSizingMargin
;
300 DWORD topSizingMargin
;
301 DWORD bottomSizingMargin
;
302 DWORD crTransparent
; // transparent color.
304 } GDI_DRAW_STREAM
, *PGDI_DRAW_STREAM
;
312 #define TransparentBlt GdiTransparentBlt
313 #define AlphaBlend GdiAlphaBlend
315 /***********************************************************************
318 * Pseudo TransparentBlt/StretchBlt
320 static inline BOOL
UXTHEME_StretchBlt(HDC hdcDst
, int nXOriginDst
, int nYOriginDst
, int nWidthDst
, int nHeightDst
,
321 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
, int nWidthSrc
, int nHeightSrc
,
322 INT transparent
, COLORREF transcolor
)
324 static const BLENDFUNCTION blendFunc
=
326 AC_SRC_OVER
, /* BlendOp */
328 255, /* SourceConstantAlpha */
329 AC_SRC_ALPHA
/* AlphaFormat */
333 int old_stretch_mode
;
336 old_stretch_mode
= SetStretchBltMode(hdcDst
, HALFTONE
);
337 SetBrushOrgEx(hdcDst
, nXOriginDst
, nYOriginDst
, &old_brush_org
);
339 if (transparent
== ALPHABLEND_BINARY
) {
340 /* Ensure we don't pass any negative values to TransparentBlt */
341 ret
= TransparentBlt(hdcDst
, nXOriginDst
, nYOriginDst
, abs(nWidthDst
), abs(nHeightDst
),
342 hdcSrc
, nXOriginSrc
, nYOriginSrc
, abs(nWidthSrc
), abs(nHeightSrc
),
344 } else if ((transparent
== ALPHABLEND_NONE
) ||
345 !AlphaBlend(hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
346 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
349 ret
= StretchBlt(hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
350 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
354 SetBrushOrgEx(hdcDst
, old_brush_org
.x
, old_brush_org
.y
, NULL
);
355 SetStretchBltMode(hdcDst
, old_stretch_mode
);
360 /***********************************************************************
363 * Simplify sending same width/height for both source and dest
365 static inline BOOL
UXTHEME_Blt(HDC hdcDest
, int nXOriginDest
, int nYOriginDest
, int nWidthDest
, int nHeightDest
,
366 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
,
367 INT transparent
, COLORREF transcolor
)
369 return UXTHEME_StretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
,
370 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthDest
, nHeightDest
,
371 transparent
, transcolor
);
374 /***********************************************************************
377 * Stretches or tiles, depending on sizingtype.
379 static inline BOOL
UXTHEME_SizedBlt (HDC hdcDst
, int nXOriginDst
, int nYOriginDst
,
380 int nWidthDst
, int nHeightDst
,
381 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
,
382 int nWidthSrc
, int nHeightSrc
,
384 INT transparent
, COLORREF transcolor
)
386 if (sizingtype
== ST_TILE
)
391 if (!nWidthSrc
|| !nHeightSrc
) return TRUE
;
393 /* For destination width/height less than or equal to source
394 width/height, do not bother with memory bitmap optimization */
395 if (nWidthSrc
>= nWidthDst
&& nHeightSrc
>= nHeightDst
)
397 int bltWidth
= min (nWidthDst
, nWidthSrc
);
398 int bltHeight
= min (nHeightDst
, nHeightSrc
);
400 return UXTHEME_Blt (hdcDst
, nXOriginDst
, nYOriginDst
, bltWidth
, bltHeight
,
401 hdcSrc
, nXOriginSrc
, nYOriginSrc
,
402 transparent
, transcolor
);
405 /* Create a DC with a bitmap consisting of a tiling of the source
406 bitmap, with standard GDI functions. This is faster than an
407 iteration with UXTHEME_Blt(). */
408 hdcTemp
= CreateCompatibleDC(hdcSrc
);
413 int nWidthTemp
, nHeightTemp
;
414 int xOfs
, xRemaining
;
415 int yOfs
, yRemaining
;
418 /* Calculate temp dimensions of integer multiples of source dimensions */
419 nWidthTemp
= ((nWidthDst
+ nWidthSrc
- 1) / nWidthSrc
) * nWidthSrc
;
420 nHeightTemp
= ((nHeightDst
+ nHeightSrc
- 1) / nHeightSrc
) * nHeightSrc
;
421 bitmapTemp
= CreateCompatibleBitmap(hdcSrc
, nWidthTemp
, nHeightTemp
);
422 bitmapOrig
= SelectObject(hdcTemp
, bitmapTemp
);
424 /* Initial copy of bitmap */
425 BitBlt(hdcTemp
, 0, 0, nWidthSrc
, nHeightSrc
, hdcSrc
, nXOriginSrc
, nYOriginSrc
, SRCCOPY
);
427 /* Extend bitmap in the X direction. Growth of width is exponential */
429 xRemaining
= nWidthTemp
- nWidthSrc
;
430 growSize
= nWidthSrc
;
431 while (xRemaining
> 0)
433 growSize
= min(growSize
, xRemaining
);
434 BitBlt(hdcTemp
, xOfs
, 0, growSize
, nHeightSrc
, hdcTemp
, 0, 0, SRCCOPY
);
436 xRemaining
-= growSize
;
440 /* Extend bitmap in the Y direction. Growth of height is exponential */
442 yRemaining
= nHeightTemp
- nHeightSrc
;
443 growSize
= nHeightSrc
;
444 while (yRemaining
> 0)
446 growSize
= min(growSize
, yRemaining
);
447 BitBlt(hdcTemp
, 0, yOfs
, nWidthTemp
, growSize
, hdcTemp
, 0, 0, SRCCOPY
);
449 yRemaining
-= growSize
;
453 /* Use temporary hdc for source */
454 result
= UXTHEME_Blt (hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
456 transparent
, transcolor
);
458 SelectObject(hdcTemp
, bitmapOrig
);
459 DeleteObject(bitmapTemp
);
466 return UXTHEME_StretchBlt (hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
467 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
468 transparent
, transcolor
);
472 /***********************************************************************
473 * UXTHEME_DrawImageBackground
475 * Draw an imagefile background
477 static HRESULT
UXTHEME_DrawImageBackground(HDC hdc
, HBITMAP bmpSrc
, RECT
*prcSrc
, INT transparent
,
478 COLORREF transparentcolor
, BOOL borderonly
, int sizingtype
, MARGINS
*psm
, RECT
*pRect
)
481 HBITMAP bmpSrcResized
= NULL
;
483 HDC hdcSrc
, hdcOrigSrc
= NULL
;
494 hdcSrc
= CreateCompatibleDC(hdc
);
496 hr
= HRESULT_FROM_WIN32(GetLastError());
499 oldSrc
= SelectObject(hdcSrc
, bmpSrc
);
501 dstSize
.x
= rcDst
.right
-rcDst
.left
;
502 dstSize
.y
= rcDst
.bottom
-rcDst
.top
;
503 srcSize
.x
= rcSrc
.right
-rcSrc
.left
;
504 srcSize
.y
= rcSrc
.bottom
-rcSrc
.top
;
506 if(sizingtype
== ST_TRUESIZE
) {
507 if(!UXTHEME_StretchBlt(hdc
, rcDst
.left
, rcDst
.top
, dstSize
.x
, dstSize
.y
,
508 hdcSrc
, rcSrc
.left
, rcSrc
.top
, srcSize
.x
, srcSize
.y
,
509 transparent
, transparentcolor
))
510 hr
= HRESULT_FROM_WIN32(GetLastError());
516 dstSize
.x
= abs(dstSize
.x
);
517 dstSize
.y
= abs(dstSize
.y
);
519 /* Resize source image if destination smaller than margins */
521 /* Revert Wine Commit 2b650fa as it breaks themed Explorer Toolbar Separators
522 FIXME: Revisit this when the bug is fixed. CORE-9636 and Wine Bug #38538 */
523 if (sm
.cyTopHeight
+ sm
.cyBottomHeight
> dstSize
.y
|| sm
.cxLeftWidth
+ sm
.cxRightWidth
> dstSize
.x
) {
524 if (sm
.cyTopHeight
+ sm
.cyBottomHeight
> dstSize
.y
) {
525 sm
.cyTopHeight
= MulDiv(sm
.cyTopHeight
, dstSize
.y
, srcSize
.y
);
526 sm
.cyBottomHeight
= dstSize
.y
- sm
.cyTopHeight
;
527 srcSize
.y
= dstSize
.y
;
530 if (sm
.cxLeftWidth
+ sm
.cxRightWidth
> dstSize
.x
) {
531 sm
.cxLeftWidth
= MulDiv(sm
.cxLeftWidth
, dstSize
.x
, srcSize
.x
);
532 sm
.cxRightWidth
= dstSize
.x
- sm
.cxLeftWidth
;
533 srcSize
.x
= dstSize
.x
;
537 hdcSrc
= CreateCompatibleDC(NULL
);
538 bmpSrcResized
= CreateBitmap(srcSize
.x
, srcSize
.y
, 1, 32, NULL
);
539 SelectObject(hdcSrc
, bmpSrcResized
);
541 UXTHEME_StretchBlt(hdcSrc
, 0, 0, srcSize
.x
, srcSize
.y
, hdcOrigSrc
, rcSrc
.left
, rcSrc
.top
,
542 rcSrc
.right
- rcSrc
.left
, rcSrc
.bottom
- rcSrc
.top
, transparent
, transparentcolor
);
546 rcSrc
.right
= srcSize
.x
;
547 rcSrc
.bottom
= srcSize
.y
;
549 #endif /* __REACTOS__ */
552 OffsetViewportOrgEx(hdcDst
, rcDst
.left
, rcDst
.top
, &org
);
554 /* Upper left corner */
555 if(!UXTHEME_Blt(hdcDst
, 0, 0, sm
.cxLeftWidth
, sm
.cyTopHeight
,
556 hdcSrc
, rcSrc
.left
, rcSrc
.top
,
557 transparent
, transparentcolor
)) {
558 hr
= HRESULT_FROM_WIN32(GetLastError());
561 /* Upper right corner */
562 if(!UXTHEME_Blt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, 0,
563 sm
.cxRightWidth
, sm
.cyTopHeight
,
564 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.top
,
565 transparent
, transparentcolor
)) {
566 hr
= HRESULT_FROM_WIN32(GetLastError());
569 /* Lower left corner */
570 if(!UXTHEME_Blt (hdcDst
, 0, dstSize
.y
-sm
.cyBottomHeight
,
571 sm
.cxLeftWidth
, sm
.cyBottomHeight
,
572 hdcSrc
, rcSrc
.left
, rcSrc
.bottom
-sm
.cyBottomHeight
,
573 transparent
, transparentcolor
)) {
574 hr
= HRESULT_FROM_WIN32(GetLastError());
577 /* Lower right corner */
578 if(!UXTHEME_Blt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, dstSize
.y
-sm
.cyBottomHeight
,
579 sm
.cxRightWidth
, sm
.cyBottomHeight
,
580 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.bottom
-sm
.cyBottomHeight
,
581 transparent
, transparentcolor
)) {
582 hr
= HRESULT_FROM_WIN32(GetLastError());
586 if ((sizingtype
== ST_STRETCH
) || (sizingtype
== ST_TILE
)) {
587 int destCenterWidth
= dstSize
.x
- (sm
.cxLeftWidth
+ sm
.cxRightWidth
);
588 int srcCenterWidth
= srcSize
.x
- (sm
.cxLeftWidth
+ sm
.cxRightWidth
);
589 int destCenterHeight
= dstSize
.y
- (sm
.cyTopHeight
+ sm
.cyBottomHeight
);
590 int srcCenterHeight
= srcSize
.y
- (sm
.cyTopHeight
+ sm
.cyBottomHeight
);
592 if(destCenterWidth
> 0) {
594 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, 0,
595 destCenterWidth
, sm
.cyTopHeight
,
596 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.top
,
597 srcCenterWidth
, sm
.cyTopHeight
,
598 sizingtype
, transparent
, transparentcolor
)) {
599 hr
= HRESULT_FROM_WIN32(GetLastError());
603 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, dstSize
.y
-sm
.cyBottomHeight
,
604 destCenterWidth
, sm
.cyBottomHeight
,
605 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.bottom
-sm
.cyBottomHeight
,
606 srcCenterWidth
, sm
.cyBottomHeight
,
607 sizingtype
, transparent
, transparentcolor
)) {
608 hr
= HRESULT_FROM_WIN32(GetLastError());
612 if(destCenterHeight
> 0) {
614 if(!UXTHEME_SizedBlt (hdcDst
, 0, sm
.cyTopHeight
,
615 sm
.cxLeftWidth
, destCenterHeight
,
616 hdcSrc
, rcSrc
.left
, rcSrc
.top
+sm
.cyTopHeight
,
617 sm
.cxLeftWidth
, srcCenterHeight
,
619 transparent
, transparentcolor
)) {
620 hr
= HRESULT_FROM_WIN32(GetLastError());
624 if(!UXTHEME_SizedBlt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, sm
.cyTopHeight
,
625 sm
.cxRightWidth
, destCenterHeight
,
626 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.top
+sm
.cyTopHeight
,
627 sm
.cxRightWidth
, srcCenterHeight
,
628 sizingtype
, transparent
, transparentcolor
)) {
629 hr
= HRESULT_FROM_WIN32(GetLastError());
633 if(destCenterHeight
> 0 && destCenterWidth
> 0) {
636 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, sm
.cyTopHeight
,
637 destCenterWidth
, destCenterHeight
,
638 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.top
+sm
.cyTopHeight
,
639 srcCenterWidth
, srcCenterHeight
,
640 sizingtype
, transparent
, transparentcolor
)) {
641 hr
= HRESULT_FROM_WIN32(GetLastError());
649 SetViewportOrgEx (hdcDst
, org
.x
, org
.y
, NULL
);
651 SelectObject(hdcSrc
, oldSrc
);
653 if (bmpSrcResized
) DeleteObject(bmpSrcResized
);
654 if (hdcOrigSrc
) DeleteDC(hdcOrigSrc
);
664 GdiDrawStream(HDC dc
, ULONG l
, PGDI_DRAW_STREAM pDS
)
666 if (!pDS
|| l
!= sizeof(*pDS
))
668 DPRINT1("GdiDrawStream: Invalid params\n");
672 if (pDS
->signature
!= 0x44727753 ||
673 pDS
->reserved
!= 0 ||
674 pDS
->unknown1
!= 1 ||
677 DPRINT1("GdiDrawStream: Got unknown pDS data\n");
682 MARGINS sm
= {pDS
->leftSizingMargin
, pDS
->rightSizingMargin
, pDS
->topSizingMargin
, pDS
->bottomSizingMargin
};
686 if (pDS
->drawOption
& 0x4)
687 transparent
= ALPHABLEND_FULL
;
688 else if (pDS
->drawOption
& 0x8)
689 transparent
= ALPHABLEND_BINARY
;
691 transparent
= ALPHABLEND_NONE
;
693 if (pDS
->drawOption
& 0x2)
694 sizingtype
= ST_TILE
;
695 else if (pDS
->drawOption
& 0x20)
696 sizingtype
= ST_TRUESIZE
;
698 sizingtype
= ST_STRETCH
;
700 UXTHEME_DrawImageBackground(pDS
->hDC
,
719 GdiValidateHandle(HGDIOBJ hobj
)
721 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hobj
);
722 if ( (Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != 0 &&
723 ( (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) ==
724 GDI_HANDLE_GET_TYPE(hobj
) )
726 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
727 if(pid
== NULL
|| pid
== CurrentProcessId
)
741 GdiFixUpHandle(HGDIOBJ hGdiObj
)
743 PGDI_TABLE_ENTRY Entry
;
745 if (((ULONG_PTR
)(hGdiObj
)) & GDI_HANDLE_UPPER_MASK
)
750 /* FIXME is this right ?? */
752 Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
754 /* Rebuild handle for Object */
755 return hGdiObj
= (HGDIOBJ
)(((LONG_PTR
)(hGdiObj
)) | (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
));
765 return (PVOID
)GdiHandleTable
;
768 BOOL
GdiIsHandleValid(HGDIOBJ hGdiObj
)
770 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
771 // We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
772 // DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
773 if((Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != 0 &&
774 ( (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) ==
775 GDI_HANDLE_GET_TYPE(hGdiObj
))
777 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
778 if(pid
== NULL
|| pid
== CurrentProcessId
)
786 BOOL
GdiGetHandleUserData(HGDIOBJ hGdiObj
, DWORD ObjectType
, PVOID
*UserData
)
788 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
790 /* Check if twe have the correct type */
791 if (GDI_HANDLE_GET_TYPE(hGdiObj
) != ObjectType
||
792 ((Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) != ObjectType
||
793 (Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != (ObjectType
& GDI_ENTRY_BASETYPE_MASK
))
798 /* Check if we are the owner */
799 if ((HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1) != CurrentProcessId
)
804 *UserData
= Entry
->UserData
;
814 /* Get the DC attribute */
815 pdcattr
= GdiGetDcAttr(hdc
);
821 /* Return the LDC pointer */
822 return pdcattr
->pvLDC
;
827 GdiSetLDC(HDC hdc
, PVOID pvLDC
)
831 /* Get the DC attribute */
832 pdcattr
= GdiGetDcAttr(hdc
);
838 /* Set the LDC pointer */
839 pdcattr
->pvLDC
= pvLDC
;
844 VOID
GdiSAPCallback(PLDC pldc
)
846 DWORD Time
, NewTime
= GetTickCount();
848 Time
= NewTime
- pldc
->CallBackTick
;
850 if ( Time
< SAPCALLBACKDELAY
) return;
852 pldc
->CallBackTick
= NewTime
;
854 if ( !pldc
->pAbortProc(pldc
->hDC
, 0) )
866 GdiSetBatchLimit(DWORD Limit
)
868 DWORD OldLimit
= GDI_BatchLimit
;
871 (Limit
>= GDI_BATCH_LIMIT
))
877 GDI_BatchLimit
= Limit
;
887 GdiGetBatchLimit(VOID
)
889 return GDI_BatchLimit
;
898 GdiSetLastError(DWORD dwErrCode
)
900 NtCurrentTeb()->LastErrorValue
= (ULONG
) dwErrCode
;
905 hGetPEBHandle(HANDLECACHETYPE Type
, COLORREF cr
)
907 int Number
, Offset
, MaxNum
, GdiType
;
909 HGDIOBJ Handle
= NULL
;
911 Lock
= InterlockedCompareExchangePointer( (PVOID
*)&GdiHandleCache
->ulLock
,
915 if (Lock
) return Handle
;
917 Number
= GdiHandleCache
->ulNumHandles
[Type
];
919 if (Type
== hctBrushHandle
)
922 MaxNum
= CACHE_BRUSH_ENTRIES
;
923 GdiType
= GDILoObjType_LO_BRUSH_TYPE
;
925 else if (Type
== hctPenHandle
)
927 Offset
= CACHE_BRUSH_ENTRIES
;
928 MaxNum
= CACHE_PEN_ENTRIES
;
929 GdiType
= GDILoObjType_LO_PEN_TYPE
;
931 else if (Type
== hctRegionHandle
)
933 Offset
= CACHE_BRUSH_ENTRIES
+CACHE_PEN_ENTRIES
;
934 MaxNum
= CACHE_REGION_ENTRIES
;
935 GdiType
= GDILoObjType_LO_REGION_TYPE
;
937 else // Font is not supported here.
942 if ( Number
&& Number
<= MaxNum
)
944 PBRUSH_ATTR pBrush_Attr
;
946 hPtr
= GdiHandleCache
->Handle
+ Offset
;
947 Handle
= hPtr
[Number
- 1];
949 if (GdiGetHandleUserData( Handle
, GdiType
, (PVOID
) &pBrush_Attr
))
951 if (pBrush_Attr
->AttrFlags
& ATTR_CACHED
)
953 DPRINT("Get Handle! Type %d Count %lu PEB 0x%p\n", Type
, GdiHandleCache
->ulNumHandles
[Type
], NtCurrentTeb()->ProcessEnvironmentBlock
);
954 pBrush_Attr
->AttrFlags
&= ~ATTR_CACHED
;
955 hPtr
[Number
- 1] = NULL
;
956 GdiHandleCache
->ulNumHandles
[Type
]--;
957 if ( Type
== hctBrushHandle
) // Handle only brush.
959 if ( pBrush_Attr
->lbColor
!= cr
)
961 pBrush_Attr
->lbColor
= cr
;
962 pBrush_Attr
->AttrFlags
|= ATTR_NEW_COLOR
;
972 (void)InterlockedExchangePointer((PVOID
*)&GdiHandleCache
->ulLock
, Lock
);
981 bMakePathNameW(LPWSTR lpBuffer
,LPCWSTR lpFileName
,LPWSTR
*lpFilePart
,DWORD unknown
)
984 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
993 GdiConvertToDevmodeW(const DEVMODEA
*dmA
)
996 WORD dmW_size
, dmA_size
;
998 dmA_size
= dmA
->dmSize
;
1000 /* this is the minimal dmSize that XP accepts */
1001 if (dmA_size
< FIELD_OFFSET(DEVMODEA
, dmFields
))
1004 if (dmA_size
> sizeof(DEVMODEA
))
1005 dmA_size
= sizeof(DEVMODEA
);
1007 dmW_size
= dmA_size
+ CCHDEVICENAME
;
1008 if (dmA_size
>= FIELD_OFFSET(DEVMODEA
, dmFormName
) + CCHFORMNAME
)
1009 dmW_size
+= CCHFORMNAME
;
1011 dmW
= HeapAlloc(GetProcessHeap(), 0, dmW_size
+ dmA
->dmDriverExtra
);
1012 if (!dmW
) return NULL
;
1014 MultiByteToWideChar(CP_ACP
, 0, (const char*) dmA
->dmDeviceName
, CCHDEVICENAME
,
1015 dmW
->dmDeviceName
, CCHDEVICENAME
);
1016 /* copy slightly more, to avoid long computations */
1017 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
, dmA_size
- CCHDEVICENAME
);
1019 if (dmA_size
>= FIELD_OFFSET(DEVMODEA
, dmFormName
) + CCHFORMNAME
)
1021 MultiByteToWideChar(CP_ACP
, 0, (const char*) dmA
->dmFormName
, CCHFORMNAME
,
1022 dmW
->dmFormName
, CCHFORMNAME
);
1023 if (dmA_size
> FIELD_OFFSET(DEVMODEA
, dmLogPixels
))
1024 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA_size
- FIELD_OFFSET(DEVMODEA
, dmLogPixels
));
1027 if (dmA
->dmDriverExtra
)
1028 memcpy((char *)dmW
+ dmW_size
, (const char *)dmA
+ dmA_size
, dmA
->dmDriverExtra
);
1030 dmW
->dmSize
= dmW_size
;
1040 GdiRealizationInfo(HDC hdc
,
1041 PREALIZATION_INFO pri
)
1043 // ATM we do not support local font data and Language Pack.
1044 return NtGdiGetRealizationInfo(hdc
, pri
, (HFONT
) NULL
);
1051 VOID WINAPI
GdiInitializeLanguagePack(DWORD InitParam
)
1054 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1059 GdiAddGlsBounds(HDC hdc
,LPRECT prc
)
1061 //FIXME: Lookup what 0x8000 means
1062 return NtGdiSetBoundsRect(hdc
, prc
, 0x8000 | DCB_ACCUMULATE
) ? TRUE
: FALSE
;
1070 GdiAddGlsRecord(HDC hdc
,
1076 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);