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
;
292 #define TransparentBlt GdiTransparentBlt
293 #define AlphaBlend GdiAlphaBlend
295 /***********************************************************************
298 * Pseudo TransparentBlt/StretchBlt
300 static inline BOOL
UXTHEME_StretchBlt(HDC hdcDst
, int nXOriginDst
, int nYOriginDst
, int nWidthDst
, int nHeightDst
,
301 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
, int nWidthSrc
, int nHeightSrc
,
302 INT transparent
, COLORREF transcolor
)
304 static const BLENDFUNCTION blendFunc
=
306 AC_SRC_OVER
, /* BlendOp */
308 255, /* SourceConstantAlpha */
309 AC_SRC_ALPHA
/* AlphaFormat */
313 int old_stretch_mode
;
316 old_stretch_mode
= SetStretchBltMode(hdcDst
, HALFTONE
);
317 SetBrushOrgEx(hdcDst
, nXOriginDst
, nYOriginDst
, &old_brush_org
);
319 if (transparent
== ALPHABLEND_BINARY
) {
320 /* Ensure we don't pass any negative values to TransparentBlt */
321 ret
= TransparentBlt(hdcDst
, nXOriginDst
, nYOriginDst
, abs(nWidthDst
), abs(nHeightDst
),
322 hdcSrc
, nXOriginSrc
, nYOriginSrc
, abs(nWidthSrc
), abs(nHeightSrc
),
324 } else if ((transparent
== ALPHABLEND_NONE
) ||
325 !AlphaBlend(hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
326 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
329 ret
= StretchBlt(hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
330 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
334 SetBrushOrgEx(hdcDst
, old_brush_org
.x
, old_brush_org
.y
, NULL
);
335 SetStretchBltMode(hdcDst
, old_stretch_mode
);
340 /***********************************************************************
343 * Simplify sending same width/height for both source and dest
345 static inline BOOL
UXTHEME_Blt(HDC hdcDest
, int nXOriginDest
, int nYOriginDest
, int nWidthDest
, int nHeightDest
,
346 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
,
347 INT transparent
, COLORREF transcolor
)
349 return UXTHEME_StretchBlt(hdcDest
, nXOriginDest
, nYOriginDest
, nWidthDest
, nHeightDest
,
350 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthDest
, nHeightDest
,
351 transparent
, transcolor
);
354 /***********************************************************************
357 * Stretches or tiles, depending on sizingtype.
359 static inline BOOL
UXTHEME_SizedBlt (HDC hdcDst
, int nXOriginDst
, int nYOriginDst
,
360 int nWidthDst
, int nHeightDst
,
361 HDC hdcSrc
, int nXOriginSrc
, int nYOriginSrc
,
362 int nWidthSrc
, int nHeightSrc
,
364 INT transparent
, COLORREF transcolor
)
366 if (sizingtype
== ST_TILE
)
371 if (!nWidthSrc
|| !nHeightSrc
) return TRUE
;
373 /* For destination width/height less than or equal to source
374 width/height, do not bother with memory bitmap optimization */
375 if (nWidthSrc
>= nWidthDst
&& nHeightSrc
>= nHeightDst
)
377 int bltWidth
= min (nWidthDst
, nWidthSrc
);
378 int bltHeight
= min (nHeightDst
, nHeightSrc
);
380 return UXTHEME_Blt (hdcDst
, nXOriginDst
, nYOriginDst
, bltWidth
, bltHeight
,
381 hdcSrc
, nXOriginSrc
, nYOriginSrc
,
382 transparent
, transcolor
);
385 /* Create a DC with a bitmap consisting of a tiling of the source
386 bitmap, with standard GDI functions. This is faster than an
387 iteration with UXTHEME_Blt(). */
388 hdcTemp
= CreateCompatibleDC(hdcSrc
);
393 int nWidthTemp
, nHeightTemp
;
394 int xOfs
, xRemaining
;
395 int yOfs
, yRemaining
;
398 /* Calculate temp dimensions of integer multiples of source dimensions */
399 nWidthTemp
= ((nWidthDst
+ nWidthSrc
- 1) / nWidthSrc
) * nWidthSrc
;
400 nHeightTemp
= ((nHeightDst
+ nHeightSrc
- 1) / nHeightSrc
) * nHeightSrc
;
401 bitmapTemp
= CreateCompatibleBitmap(hdcSrc
, nWidthTemp
, nHeightTemp
);
402 bitmapOrig
= SelectObject(hdcTemp
, bitmapTemp
);
404 /* Initial copy of bitmap */
405 BitBlt(hdcTemp
, 0, 0, nWidthSrc
, nHeightSrc
, hdcSrc
, nXOriginSrc
, nYOriginSrc
, SRCCOPY
);
407 /* Extend bitmap in the X direction. Growth of width is exponential */
409 xRemaining
= nWidthTemp
- nWidthSrc
;
410 growSize
= nWidthSrc
;
411 while (xRemaining
> 0)
413 growSize
= min(growSize
, xRemaining
);
414 BitBlt(hdcTemp
, xOfs
, 0, growSize
, nHeightSrc
, hdcTemp
, 0, 0, SRCCOPY
);
416 xRemaining
-= growSize
;
420 /* Extend bitmap in the Y direction. Growth of height is exponential */
422 yRemaining
= nHeightTemp
- nHeightSrc
;
423 growSize
= nHeightSrc
;
424 while (yRemaining
> 0)
426 growSize
= min(growSize
, yRemaining
);
427 BitBlt(hdcTemp
, 0, yOfs
, nWidthTemp
, growSize
, hdcTemp
, 0, 0, SRCCOPY
);
429 yRemaining
-= growSize
;
433 /* Use temporary hdc for source */
434 result
= UXTHEME_Blt (hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
436 transparent
, transcolor
);
438 SelectObject(hdcTemp
, bitmapOrig
);
439 DeleteObject(bitmapTemp
);
446 return UXTHEME_StretchBlt (hdcDst
, nXOriginDst
, nYOriginDst
, nWidthDst
, nHeightDst
,
447 hdcSrc
, nXOriginSrc
, nYOriginSrc
, nWidthSrc
, nHeightSrc
,
448 transparent
, transcolor
);
452 /***********************************************************************
453 * UXTHEME_DrawImageBackground
455 * Draw an imagefile background
457 static HRESULT
UXTHEME_DrawImageBackground(HDC hdc
, HBITMAP bmpSrc
, RECT
*prcSrc
, INT transparent
,
458 COLORREF transparentcolor
, BOOL borderonly
, int sizingtype
, MARGINS
*psm
, RECT
*pRect
)
461 HBITMAP bmpSrcResized
= NULL
;
463 HDC hdcSrc
, hdcOrigSrc
= NULL
;
474 hdcSrc
= CreateCompatibleDC(hdc
);
476 hr
= HRESULT_FROM_WIN32(GetLastError());
479 oldSrc
= SelectObject(hdcSrc
, bmpSrc
);
481 dstSize
.x
= rcDst
.right
-rcDst
.left
;
482 dstSize
.y
= rcDst
.bottom
-rcDst
.top
;
483 srcSize
.x
= rcSrc
.right
-rcSrc
.left
;
484 srcSize
.y
= rcSrc
.bottom
-rcSrc
.top
;
486 if(sizingtype
== ST_TRUESIZE
) {
487 if(!UXTHEME_StretchBlt(hdc
, rcDst
.left
, rcDst
.top
, dstSize
.x
, dstSize
.y
,
488 hdcSrc
, rcSrc
.left
, rcSrc
.top
, srcSize
.x
, srcSize
.y
,
489 transparent
, transparentcolor
))
490 hr
= HRESULT_FROM_WIN32(GetLastError());
496 dstSize
.x
= abs(dstSize
.x
);
497 dstSize
.y
= abs(dstSize
.y
);
499 /* Resize source image if destination smaller than margins */
501 /* Revert Wine Commit 2b650fa as it breaks themed Explorer Toolbar Separators
502 FIXME: Revisit this when the bug is fixed. CORE-9636 and Wine Bug #38538 */
503 if (sm
.cyTopHeight
+ sm
.cyBottomHeight
> dstSize
.y
|| sm
.cxLeftWidth
+ sm
.cxRightWidth
> dstSize
.x
) {
504 if (sm
.cyTopHeight
+ sm
.cyBottomHeight
> dstSize
.y
) {
505 sm
.cyTopHeight
= MulDiv(sm
.cyTopHeight
, dstSize
.y
, srcSize
.y
);
506 sm
.cyBottomHeight
= dstSize
.y
- sm
.cyTopHeight
;
507 srcSize
.y
= dstSize
.y
;
510 if (sm
.cxLeftWidth
+ sm
.cxRightWidth
> dstSize
.x
) {
511 sm
.cxLeftWidth
= MulDiv(sm
.cxLeftWidth
, dstSize
.x
, srcSize
.x
);
512 sm
.cxRightWidth
= dstSize
.x
- sm
.cxLeftWidth
;
513 srcSize
.x
= dstSize
.x
;
517 hdcSrc
= CreateCompatibleDC(NULL
);
518 bmpSrcResized
= CreateBitmap(srcSize
.x
, srcSize
.y
, 1, 32, NULL
);
519 SelectObject(hdcSrc
, bmpSrcResized
);
521 UXTHEME_StretchBlt(hdcSrc
, 0, 0, srcSize
.x
, srcSize
.y
, hdcOrigSrc
, rcSrc
.left
, rcSrc
.top
,
522 rcSrc
.right
- rcSrc
.left
, rcSrc
.bottom
- rcSrc
.top
, transparent
, transparentcolor
);
526 rcSrc
.right
= srcSize
.x
;
527 rcSrc
.bottom
= srcSize
.y
;
529 #endif /* __REACTOS__ */
532 OffsetViewportOrgEx(hdcDst
, rcDst
.left
, rcDst
.top
, &org
);
534 /* Upper left corner */
535 if(!UXTHEME_Blt(hdcDst
, 0, 0, sm
.cxLeftWidth
, sm
.cyTopHeight
,
536 hdcSrc
, rcSrc
.left
, rcSrc
.top
,
537 transparent
, transparentcolor
)) {
538 hr
= HRESULT_FROM_WIN32(GetLastError());
541 /* Upper right corner */
542 if(!UXTHEME_Blt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, 0,
543 sm
.cxRightWidth
, sm
.cyTopHeight
,
544 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.top
,
545 transparent
, transparentcolor
)) {
546 hr
= HRESULT_FROM_WIN32(GetLastError());
549 /* Lower left corner */
550 if(!UXTHEME_Blt (hdcDst
, 0, dstSize
.y
-sm
.cyBottomHeight
,
551 sm
.cxLeftWidth
, sm
.cyBottomHeight
,
552 hdcSrc
, rcSrc
.left
, rcSrc
.bottom
-sm
.cyBottomHeight
,
553 transparent
, transparentcolor
)) {
554 hr
= HRESULT_FROM_WIN32(GetLastError());
557 /* Lower right corner */
558 if(!UXTHEME_Blt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, dstSize
.y
-sm
.cyBottomHeight
,
559 sm
.cxRightWidth
, sm
.cyBottomHeight
,
560 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.bottom
-sm
.cyBottomHeight
,
561 transparent
, transparentcolor
)) {
562 hr
= HRESULT_FROM_WIN32(GetLastError());
566 if ((sizingtype
== ST_STRETCH
) || (sizingtype
== ST_TILE
)) {
567 int destCenterWidth
= dstSize
.x
- (sm
.cxLeftWidth
+ sm
.cxRightWidth
);
568 int srcCenterWidth
= srcSize
.x
- (sm
.cxLeftWidth
+ sm
.cxRightWidth
);
569 int destCenterHeight
= dstSize
.y
- (sm
.cyTopHeight
+ sm
.cyBottomHeight
);
570 int srcCenterHeight
= srcSize
.y
- (sm
.cyTopHeight
+ sm
.cyBottomHeight
);
572 if(destCenterWidth
> 0) {
574 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, 0,
575 destCenterWidth
, sm
.cyTopHeight
,
576 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.top
,
577 srcCenterWidth
, sm
.cyTopHeight
,
578 sizingtype
, transparent
, transparentcolor
)) {
579 hr
= HRESULT_FROM_WIN32(GetLastError());
583 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, dstSize
.y
-sm
.cyBottomHeight
,
584 destCenterWidth
, sm
.cyBottomHeight
,
585 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.bottom
-sm
.cyBottomHeight
,
586 srcCenterWidth
, sm
.cyBottomHeight
,
587 sizingtype
, transparent
, transparentcolor
)) {
588 hr
= HRESULT_FROM_WIN32(GetLastError());
592 if(destCenterHeight
> 0) {
594 if(!UXTHEME_SizedBlt (hdcDst
, 0, sm
.cyTopHeight
,
595 sm
.cxLeftWidth
, destCenterHeight
,
596 hdcSrc
, rcSrc
.left
, rcSrc
.top
+sm
.cyTopHeight
,
597 sm
.cxLeftWidth
, srcCenterHeight
,
599 transparent
, transparentcolor
)) {
600 hr
= HRESULT_FROM_WIN32(GetLastError());
604 if(!UXTHEME_SizedBlt (hdcDst
, dstSize
.x
-sm
.cxRightWidth
, sm
.cyTopHeight
,
605 sm
.cxRightWidth
, destCenterHeight
,
606 hdcSrc
, rcSrc
.right
-sm
.cxRightWidth
, rcSrc
.top
+sm
.cyTopHeight
,
607 sm
.cxRightWidth
, srcCenterHeight
,
608 sizingtype
, transparent
, transparentcolor
)) {
609 hr
= HRESULT_FROM_WIN32(GetLastError());
613 if(destCenterHeight
> 0 && destCenterWidth
> 0) {
616 if(!UXTHEME_SizedBlt (hdcDst
, sm
.cxLeftWidth
, sm
.cyTopHeight
,
617 destCenterWidth
, destCenterHeight
,
618 hdcSrc
, rcSrc
.left
+sm
.cxLeftWidth
, rcSrc
.top
+sm
.cyTopHeight
,
619 srcCenterWidth
, srcCenterHeight
,
620 sizingtype
, transparent
, transparentcolor
)) {
621 hr
= HRESULT_FROM_WIN32(GetLastError());
629 SetViewportOrgEx (hdcDst
, org
.x
, org
.y
, NULL
);
631 SelectObject(hdcSrc
, oldSrc
);
633 if (bmpSrcResized
) DeleteObject(bmpSrcResized
);
634 if (hdcOrigSrc
) DeleteDC(hdcOrigSrc
);
644 GdiDrawStream(HDC dc
, ULONG l
, PGDI_DRAW_STREAM pDS
)
646 if (!pDS
|| l
!= sizeof(*pDS
))
648 DPRINT1("GdiDrawStream: Invalid params\n");
652 if (pDS
->signature
!= 0x44727753 ||
653 pDS
->reserved
!= 0 ||
654 pDS
->unknown1
!= 1 ||
657 DPRINT1("GdiDrawStream: Got unknown pDS data\n");
662 MARGINS sm
= {pDS
->leftSizingMargin
, pDS
->rightSizingMargin
, pDS
->topSizingMargin
, pDS
->bottomSizingMargin
};
666 if (pDS
->drawOption
& DS_TRANSPARENTALPHA
)
667 transparent
= ALPHABLEND_FULL
;
668 else if (pDS
->drawOption
& DS_TRANSPARENTCLR
)
669 transparent
= ALPHABLEND_BINARY
;
671 transparent
= ALPHABLEND_NONE
;
673 if (pDS
->drawOption
& DS_TILE
)
674 sizingtype
= ST_TILE
;
675 else if (pDS
->drawOption
& DS_TRUESIZE
)
676 sizingtype
= ST_TRUESIZE
;
678 sizingtype
= ST_STRETCH
;
680 UXTHEME_DrawImageBackground(pDS
->hDC
,
699 GdiValidateHandle(HGDIOBJ hobj
)
701 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hobj
);
702 if ( (Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != 0 &&
703 ( (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) ==
704 GDI_HANDLE_GET_TYPE(hobj
) )
706 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
707 if(pid
== NULL
|| pid
== CurrentProcessId
)
721 GdiFixUpHandle(HGDIOBJ hGdiObj
)
723 PGDI_TABLE_ENTRY Entry
;
725 if (((ULONG_PTR
)(hGdiObj
)) & GDI_HANDLE_UPPER_MASK
)
730 /* FIXME is this right ?? */
732 Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
734 /* Rebuild handle for Object */
735 return hGdiObj
= (HGDIOBJ
)(((LONG_PTR
)(hGdiObj
)) | (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
));
745 return (PVOID
)GdiHandleTable
;
748 BOOL
GdiIsHandleValid(HGDIOBJ hGdiObj
)
750 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
751 // We are only looking for TYPE not the rest here, and why is FullUnique filled up with CRAP!?
752 // DPRINT1("FullUnique -> %x\n", Entry->FullUnique);
753 if((Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != 0 &&
754 ( (Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) ==
755 GDI_HANDLE_GET_TYPE(hGdiObj
))
757 HANDLE pid
= (HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1);
758 if(pid
== NULL
|| pid
== CurrentProcessId
)
766 BOOL
GdiGetHandleUserData(HGDIOBJ hGdiObj
, DWORD ObjectType
, PVOID
*UserData
)
768 PGDI_TABLE_ENTRY Entry
= GdiHandleTable
+ GDI_HANDLE_GET_INDEX(hGdiObj
);
770 /* Check if twe have the correct type */
771 if (GDI_HANDLE_GET_TYPE(hGdiObj
) != ObjectType
||
772 ((Entry
->Type
<< GDI_ENTRY_UPPER_SHIFT
) & GDI_HANDLE_TYPE_MASK
) != ObjectType
||
773 (Entry
->Type
& GDI_ENTRY_BASETYPE_MASK
) != (ObjectType
& GDI_ENTRY_BASETYPE_MASK
))
778 /* Check if we are the owner */
779 if ((HANDLE
)((ULONG_PTR
)Entry
->ProcessId
& ~0x1) != CurrentProcessId
)
784 *UserData
= Entry
->UserData
;
794 /* Get the DC attribute */
795 pdcattr
= GdiGetDcAttr(hdc
);
801 /* Return the LDC pointer */
802 return pdcattr
->pvLDC
;
807 GdiSetLDC(HDC hdc
, PVOID pvLDC
)
811 /* Get the DC attribute */
812 pdcattr
= GdiGetDcAttr(hdc
);
818 /* Set the LDC pointer */
819 pdcattr
->pvLDC
= pvLDC
;
824 VOID
GdiSAPCallback(PLDC pldc
)
826 DWORD Time
, NewTime
= GetTickCount();
828 Time
= NewTime
- pldc
->CallBackTick
;
830 if ( Time
< SAPCALLBACKDELAY
) return;
832 pldc
->CallBackTick
= NewTime
;
834 if ( !pldc
->pAbortProc(pldc
->hDC
, 0) )
846 GdiSetBatchLimit(DWORD Limit
)
848 DWORD OldLimit
= GDI_BatchLimit
;
851 (Limit
>= GDI_BATCH_LIMIT
))
857 GDI_BatchLimit
= Limit
;
867 GdiGetBatchLimit(VOID
)
869 return GDI_BatchLimit
;
878 GdiSetLastError(DWORD dwErrCode
)
880 NtCurrentTeb()->LastErrorValue
= (ULONG
) dwErrCode
;
885 hGetPEBHandle(HANDLECACHETYPE Type
, COLORREF cr
)
887 int Number
, Offset
, MaxNum
, GdiType
;
889 HGDIOBJ Handle
= NULL
;
891 Lock
= InterlockedCompareExchangePointer( (PVOID
*)&GdiHandleCache
->ulLock
,
895 if (Lock
) return Handle
;
897 Number
= GdiHandleCache
->ulNumHandles
[Type
];
899 if (Type
== hctBrushHandle
)
902 MaxNum
= CACHE_BRUSH_ENTRIES
;
903 GdiType
= GDILoObjType_LO_BRUSH_TYPE
;
905 else if (Type
== hctPenHandle
)
907 Offset
= CACHE_BRUSH_ENTRIES
;
908 MaxNum
= CACHE_PEN_ENTRIES
;
909 GdiType
= GDILoObjType_LO_PEN_TYPE
;
911 else if (Type
== hctRegionHandle
)
913 Offset
= CACHE_BRUSH_ENTRIES
+CACHE_PEN_ENTRIES
;
914 MaxNum
= CACHE_REGION_ENTRIES
;
915 GdiType
= GDILoObjType_LO_REGION_TYPE
;
917 else // Font is not supported here.
922 if ( Number
&& Number
<= MaxNum
)
924 PBRUSH_ATTR pBrush_Attr
;
926 hPtr
= GdiHandleCache
->Handle
+ Offset
;
927 Handle
= hPtr
[Number
- 1];
929 if (GdiGetHandleUserData( Handle
, GdiType
, (PVOID
) &pBrush_Attr
))
931 if (pBrush_Attr
->AttrFlags
& ATTR_CACHED
)
933 DPRINT("Get Handle! Type %d Count %lu PEB 0x%p\n", Type
, GdiHandleCache
->ulNumHandles
[Type
], NtCurrentTeb()->ProcessEnvironmentBlock
);
934 pBrush_Attr
->AttrFlags
&= ~ATTR_CACHED
;
935 hPtr
[Number
- 1] = NULL
;
936 GdiHandleCache
->ulNumHandles
[Type
]--;
937 if ( Type
== hctBrushHandle
) // Handle only brush.
939 if ( pBrush_Attr
->lbColor
!= cr
)
941 pBrush_Attr
->lbColor
= cr
;
942 pBrush_Attr
->AttrFlags
|= ATTR_NEW_COLOR
;
952 (void)InterlockedExchangePointer((PVOID
*)&GdiHandleCache
->ulLock
, Lock
);
961 bMakePathNameW(LPWSTR lpBuffer
,LPCWSTR lpFileName
,LPWSTR
*lpFilePart
,DWORD unknown
)
964 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
973 GdiConvertToDevmodeW(const DEVMODEA
*dmA
)
976 WORD dmW_size
, dmA_size
;
978 dmA_size
= dmA
->dmSize
;
980 /* this is the minimal dmSize that XP accepts */
981 if (dmA_size
< FIELD_OFFSET(DEVMODEA
, dmFields
))
984 if (dmA_size
> sizeof(DEVMODEA
))
985 dmA_size
= sizeof(DEVMODEA
);
987 dmW_size
= dmA_size
+ CCHDEVICENAME
;
988 if (dmA_size
>= FIELD_OFFSET(DEVMODEA
, dmFormName
) + CCHFORMNAME
)
989 dmW_size
+= CCHFORMNAME
;
991 dmW
= HeapAlloc(GetProcessHeap(), 0, dmW_size
+ dmA
->dmDriverExtra
);
992 if (!dmW
) return NULL
;
994 MultiByteToWideChar(CP_ACP
, 0, (const char*) dmA
->dmDeviceName
, CCHDEVICENAME
,
995 dmW
->dmDeviceName
, CCHDEVICENAME
);
996 /* copy slightly more, to avoid long computations */
997 memcpy(&dmW
->dmSpecVersion
, &dmA
->dmSpecVersion
, dmA_size
- CCHDEVICENAME
);
999 if (dmA_size
>= FIELD_OFFSET(DEVMODEA
, dmFormName
) + CCHFORMNAME
)
1001 MultiByteToWideChar(CP_ACP
, 0, (const char*) dmA
->dmFormName
, CCHFORMNAME
,
1002 dmW
->dmFormName
, CCHFORMNAME
);
1003 if (dmA_size
> FIELD_OFFSET(DEVMODEA
, dmLogPixels
))
1004 memcpy(&dmW
->dmLogPixels
, &dmA
->dmLogPixels
, dmA_size
- FIELD_OFFSET(DEVMODEA
, dmLogPixels
));
1007 if (dmA
->dmDriverExtra
)
1008 memcpy((char *)dmW
+ dmW_size
, (const char *)dmA
+ dmA_size
, dmA
->dmDriverExtra
);
1010 dmW
->dmSize
= dmW_size
;
1020 GdiRealizationInfo(HDC hdc
,
1021 PREALIZATION_INFO pri
)
1023 // ATM we do not support local font data and Language Pack.
1024 return NtGdiGetRealizationInfo(hdc
, pri
, (HFONT
) NULL
);
1031 VOID WINAPI
GdiInitializeLanguagePack(DWORD InitParam
)
1034 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1039 GdiAddGlsBounds(HDC hdc
,LPRECT prc
)
1041 return NtGdiSetBoundsRect(hdc
, prc
, DCB_WINDOWMGR
|DCB_ACCUMULATE
) ? TRUE
: FALSE
;
1046 GetBoundsRectAlt(HDC hdc
,LPRECT prc
,UINT flags
)
1048 return NtGdiGetBoundsRect(hdc
, prc
, flags
);
1053 SetBoundsRectAlt(HDC hdc
,LPRECT prc
,UINT flags
)
1055 return NtGdiSetBoundsRect(hdc
, prc
, flags
);
1063 GdiAddGlsRecord(HDC hdc
,
1069 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);