*/
/*
* PROJECT: ReactOS gdi32.dll
- * FILE: dll/win32/gdi32/misc/misc.c
+ * FILE: win32ss/gdi/gdi32/misc/misc.c
* PURPOSE: Miscellaneous functions
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
PGDI_SHARED_HANDLE_TABLE GdiSharedHandleTable = NULL;
HANDLE CurrentProcessId = NULL;
DWORD GDI_BatchLimit = 1;
+extern PGDIHANDLECACHE GdiHandleCache;
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GdiFlush(VOID)
+{
+ NtGdiFlush();
+ return TRUE;
+}
+
+/*
+ * @unimplemented
+ */
+INT
+WINAPI
+Escape(
+ _In_ HDC hdc,
+ _In_ INT nEscape,
+ _In_ INT cbInput,
+ _In_ LPCSTR lpvInData,
+ _Out_ LPVOID lpvOutData)
+{
+ INT retValue = SP_ERROR;
+ ULONG ulObjType;
+
+ ulObjType = GDI_HANDLE_GET_TYPE(hdc);
+
+ if (ulObjType == GDILoObjType_LO_METADC16_TYPE)
+ {
+ return METADC16_Escape(hdc, nEscape, cbInput, lpvInData, lpvOutData);
+ }
+
+ switch (nEscape)
+ {
+ case ABORTDOC:
+ /* Note: Windows checks if the handle has any user data for the ABORTDOC command
+ * ReactOS copies this behavior to be compatible with windows 2003
+ */
+ if (GdiGetDcAttr(hdc) == NULL)
+ {
+ GdiSetLastError(ERROR_INVALID_HANDLE);
+ retValue = FALSE;
+ }
+ else
+ {
+ retValue = AbortDoc(hdc);
+ }
+ break;
+
+ case DRAFTMODE:
+ case FLUSHOUTPUT:
+ case SETCOLORTABLE:
+ /* Note 1: DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE are outdated */
+ /* Note 2: Windows checks if the handle has any user data for the DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE commands
+ * ReactOS copies this behavior to be compatible with windows 2003
+ */
+ if (GdiGetDcAttr(hdc) == NULL)
+ {
+ GdiSetLastError(ERROR_INVALID_HANDLE);
+ }
+ retValue = FALSE;
+ break;
+
+ case SETABORTPROC:
+ /* Note: Windows checks if the handle has any user data for the SETABORTPROC command
+ * ReactOS copies this behavior to be compatible with windows 2003
+ */
+ if (GdiGetDcAttr(hdc) == NULL)
+ {
+ GdiSetLastError(ERROR_INVALID_HANDLE);
+ retValue = FALSE;
+ }
+ retValue = SetAbortProc(hdc, (ABORTPROC)lpvInData);
+ break;
+
+ case GETCOLORTABLE:
+ retValue = GetSystemPaletteEntries(hdc, (UINT)*lpvInData, 1, (LPPALETTEENTRY)lpvOutData);
+ if (!retValue)
+ {
+ retValue = SP_ERROR;
+ }
+ break;
+
+ case ENDDOC:
+ /* Note: Windows checks if the handle has any user data for the ENDDOC command
+ * ReactOS copies this behavior to be compatible with windows 2003
+ */
+ if (GdiGetDcAttr(hdc) == NULL)
+ {
+ GdiSetLastError(ERROR_INVALID_HANDLE);
+ retValue = FALSE;
+ }
+ retValue = EndDoc(hdc);
+ break;
+
+ case GETSCALINGFACTOR:
+ /* Note GETSCALINGFACTOR is outdated have been replace by GetDeviceCaps */
+ if (ulObjType == GDI_OBJECT_TYPE_DC)
+ {
+ if (lpvOutData)
+ {
+ PPOINT ptr = (PPOINT)lpvOutData;
+ ptr->x = 0;
+ ptr->y = 0;
+ }
+ }
+ retValue = FALSE;
+ break;
+
+ case GETEXTENDEDTEXTMETRICS:
+ retValue = GetETM(hdc, (EXTTEXTMETRIC *)lpvOutData) != 0;
+ break;
+
+ case STARTDOC:
+ {
+ DOCINFOA di;
+
+ /* Note: Windows checks if the handle has any user data for the STARTDOC command
+ * ReactOS copies this behavior to be compatible with windows 2003
+ */
+ if (GdiGetDcAttr(hdc) == NULL)
+ {
+ GdiSetLastError(ERROR_INVALID_HANDLE);
+ retValue = FALSE;
+ }
+
+ di.cbSize = sizeof(DOCINFOA);
+ di.lpszOutput = 0;
+ di.lpszDatatype = 0;
+ di.fwType = 0;
+ di.lpszDocName = lpvInData;
+
+ /* NOTE : doc for StartDocA/W at msdn http://msdn2.microsoft.com/en-us/library/ms535793(VS.85).aspx */
+ retValue = StartDocA(hdc, &di);
+
+ /* Check if StartDocA failed */
+ if (retValue < 0)
+ {
+ {
+ retValue = GetLastError();
+
+ /* Translate StartDocA error code to STARTDOC error code
+ * see msdn http://msdn2.microsoft.com/en-us/library/ms535472.aspx
+ */
+ switch(retValue)
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ retValue = SP_OUTOFMEMORY;
+ break;
+
+ case ERROR_PRINT_CANCELLED:
+ retValue = SP_USERABORT;
+ break;
+
+ case ERROR_DISK_FULL:
+ retValue = SP_OUTOFDISK;
+ break;
+
+ default:
+ retValue = SP_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ UNIMPLEMENTED;
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+
+ return retValue;
+}
+
+INT
+WINAPI
+ExtEscape(HDC hDC,
+ int nEscape,
+ int cbInput,
+ LPCSTR lpszInData,
+ int cbOutput,
+ LPSTR lpszOutData)
+{
+ return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
+}
+
+INT
+WINAPI
+NamedEscape(HDC hdc,
+ PWCHAR pDriver,
+ INT iEsc,
+ INT cjIn,
+ LPSTR pjIn,
+ INT cjOut,
+ LPSTR pjOut)
+{
+ /* FIXME metadc, metadc are done most in user mode, and we do not support it
+ * Windows 2000/XP/Vista ignore the current hdc, that are being pass and always set hdc to NULL
+ * when it calls to NtGdiExtEscape from NamedEscape
+ */
+ return NtGdiExtEscape(NULL,pDriver,wcslen(pDriver),iEsc,cjIn,pjIn,cjOut,pjOut);
+}
+
+/*
+ * @implemented
+ */
+int
+WINAPI
+DrawEscape(HDC hDC,
+ INT nEscape,
+ INT cbInput,
+ LPCSTR lpszInData)
+{
+ if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC)
+ return NtGdiDrawEscape(hDC, nEscape, cbInput, (LPSTR) lpszInData);
+
+ if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC)
+ {
+ PLDC pLDC = GdiGetLDC(hDC);
+ if ( pLDC )
+ {
+ if (pLDC->Flags & LDC_META_PRINT)
+ {
+// if (nEscape != QUERYESCSUPPORT)
+// return EMFDRV_WriteEscape(hDC, nEscape, cbInput, lpszInData, EMR_DRAWESCAPE);
+
+ return NtGdiDrawEscape(hDC, nEscape, cbInput, (LPSTR) lpszInData);
+ }
+ }
+ SetLastError(ERROR_INVALID_HANDLE);
+ }
+ return 0;
+}
+
+#define ALPHABLEND_NONE 0
+#define ALPHABLEND_BINARY 1
+#define ALPHABLEND_FULL 2
+
+typedef struct _MARGINS {
+ int cxLeftWidth;
+ int cxRightWidth;
+ int cyTopHeight;
+ int cyBottomHeight;
+} MARGINS, *PMARGINS;
+
+enum SIZINGTYPE {
+ ST_TRUESIZE = 0,
+ ST_STRETCH = 1,
+ ST_TILE = 2,
+};
+#define TransparentBlt GdiTransparentBlt
+#define AlphaBlend GdiAlphaBlend
+
+/***********************************************************************
+ * UXTHEME_StretchBlt
+ *
+ * Pseudo TransparentBlt/StretchBlt
+ */
+static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginDst, int nWidthDst, int nHeightDst,
+ HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
+ INT transparent, COLORREF transcolor)
+{
+ static const BLENDFUNCTION blendFunc =
+ {
+ AC_SRC_OVER, /* BlendOp */
+ 0, /* BlendFlag */
+ 255, /* SourceConstantAlpha */
+ AC_SRC_ALPHA /* AlphaFormat */
+ };
+
+ BOOL ret = TRUE;
+ int old_stretch_mode;
+ POINT old_brush_org;
+
+ old_stretch_mode = SetStretchBltMode(hdcDst, HALFTONE);
+ SetBrushOrgEx(hdcDst, nXOriginDst, nYOriginDst, &old_brush_org);
+
+ if (transparent == ALPHABLEND_BINARY) {
+ /* Ensure we don't pass any negative values to TransparentBlt */
+ ret = TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
+ hdcSrc, nXOriginSrc, nYOriginSrc, abs(nWidthSrc), abs(nHeightSrc),
+ transcolor);
+ } else if ((transparent == ALPHABLEND_NONE) ||
+ !AlphaBlend(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ blendFunc))
+ {
+ ret = StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ SRCCOPY);
+ }
+
+ SetBrushOrgEx(hdcDst, old_brush_org.x, old_brush_org.y, NULL);
+ SetStretchBltMode(hdcDst, old_stretch_mode);
+
+ return ret;
+}
+
+/***********************************************************************
+ * UXTHEME_Blt
+ *
+ * Simplify sending same width/height for both source and dest
+ */
+static inline BOOL UXTHEME_Blt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
+ HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
+ INT transparent, COLORREF transcolor)
+{
+ return UXTHEME_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthDest, nHeightDest,
+ transparent, transcolor);
+}
+
+/***********************************************************************
+ * UXTHEME_SizedBlt
+ *
+ * Stretches or tiles, depending on sizingtype.
+ */
+static inline BOOL UXTHEME_SizedBlt (HDC hdcDst, int nXOriginDst, int nYOriginDst,
+ int nWidthDst, int nHeightDst,
+ HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
+ int nWidthSrc, int nHeightSrc,
+ int sizingtype,
+ INT transparent, COLORREF transcolor)
+{
+ if (sizingtype == ST_TILE)
+ {
+ HDC hdcTemp;
+ BOOL result = FALSE;
+
+ if (!nWidthSrc || !nHeightSrc) return TRUE;
+
+ /* For destination width/height less than or equal to source
+ width/height, do not bother with memory bitmap optimization */
+ if (nWidthSrc >= nWidthDst && nHeightSrc >= nHeightDst)
+ {
+ int bltWidth = min (nWidthDst, nWidthSrc);
+ int bltHeight = min (nHeightDst, nHeightSrc);
+ return UXTHEME_Blt (hdcDst, nXOriginDst, nYOriginDst, bltWidth, bltHeight,
+ hdcSrc, nXOriginSrc, nYOriginSrc,
+ transparent, transcolor);
+ }
+
+ /* Create a DC with a bitmap consisting of a tiling of the source
+ bitmap, with standard GDI functions. This is faster than an
+ iteration with UXTHEME_Blt(). */
+ hdcTemp = CreateCompatibleDC(hdcSrc);
+ if (hdcTemp != 0)
+ {
+ HBITMAP bitmapTemp;
+ HBITMAP bitmapOrig;
+ int nWidthTemp, nHeightTemp;
+ int xOfs, xRemaining;
+ int yOfs, yRemaining;
+ int growSize;
+
+ /* Calculate temp dimensions of integer multiples of source dimensions */
+ nWidthTemp = ((nWidthDst + nWidthSrc - 1) / nWidthSrc) * nWidthSrc;
+ nHeightTemp = ((nHeightDst + nHeightSrc - 1) / nHeightSrc) * nHeightSrc;
+ bitmapTemp = CreateCompatibleBitmap(hdcSrc, nWidthTemp, nHeightTemp);
+ bitmapOrig = SelectObject(hdcTemp, bitmapTemp);
+
+ /* Initial copy of bitmap */
+ BitBlt(hdcTemp, 0, 0, nWidthSrc, nHeightSrc, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
+
+ /* Extend bitmap in the X direction. Growth of width is exponential */
+ xOfs = nWidthSrc;
+ xRemaining = nWidthTemp - nWidthSrc;
+ growSize = nWidthSrc;
+ while (xRemaining > 0)
+ {
+ growSize = min(growSize, xRemaining);
+ BitBlt(hdcTemp, xOfs, 0, growSize, nHeightSrc, hdcTemp, 0, 0, SRCCOPY);
+ xOfs += growSize;
+ xRemaining -= growSize;
+ growSize *= 2;
+ }
+
+ /* Extend bitmap in the Y direction. Growth of height is exponential */
+ yOfs = nHeightSrc;
+ yRemaining = nHeightTemp - nHeightSrc;
+ growSize = nHeightSrc;
+ while (yRemaining > 0)
+ {
+ growSize = min(growSize, yRemaining);
+ BitBlt(hdcTemp, 0, yOfs, nWidthTemp, growSize, hdcTemp, 0, 0, SRCCOPY);
+ yOfs += growSize;
+ yRemaining -= growSize;
+ growSize *= 2;
+ }
+
+ /* Use temporary hdc for source */
+ result = UXTHEME_Blt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcTemp, 0, 0,
+ transparent, transcolor);
+
+ SelectObject(hdcTemp, bitmapOrig);
+ DeleteObject(bitmapTemp);
+ }
+ DeleteDC(hdcTemp);
+ return result;
+ }
+ else
+ {
+ return UXTHEME_StretchBlt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+ hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+ transparent, transcolor);
+ }
+}
+
+/***********************************************************************
+ * UXTHEME_DrawImageBackground
+ *
+ * Draw an imagefile background
+ */
+static HRESULT UXTHEME_DrawImageBackground(HDC hdc, HBITMAP bmpSrc, RECT *prcSrc, INT transparent,
+ COLORREF transparentcolor, BOOL borderonly, int sizingtype, MARGINS *psm, RECT *pRect)
+{
+ HRESULT hr = S_OK;
+ HBITMAP bmpSrcResized = NULL;
+ HGDIOBJ oldSrc;
+ HDC hdcSrc, hdcOrigSrc = NULL;
+ RECT rcDst;
+ POINT dstSize;
+ POINT srcSize;
+ RECT rcSrc;
+ MARGINS sm;
+
+ rcDst = *pRect;
+ rcSrc = *prcSrc;
+ sm = *psm;
+
+ hdcSrc = CreateCompatibleDC(hdc);
+ if(!hdcSrc) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+ oldSrc = SelectObject(hdcSrc, bmpSrc);
+
+ dstSize.x = rcDst.right-rcDst.left;
+ dstSize.y = rcDst.bottom-rcDst.top;
+ srcSize.x = rcSrc.right-rcSrc.left;
+ srcSize.y = rcSrc.bottom-rcSrc.top;
+
+ if(sizingtype == ST_TRUESIZE) {
+ if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
+ hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
+ transparent, transparentcolor))
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else {
+ HDC hdcDst = NULL;
+ POINT org;
+
+ dstSize.x = abs(dstSize.x);
+ dstSize.y = abs(dstSize.y);
+
+ /* Resize source image if destination smaller than margins */
+#ifndef __REACTOS__
+ /* Revert Wine Commit 2b650fa as it breaks themed Explorer Toolbar Separators
+ FIXME: Revisit this when the bug is fixed. CORE-9636 and Wine Bug #38538 */
+ if (sm.cyTopHeight + sm.cyBottomHeight > dstSize.y || sm.cxLeftWidth + sm.cxRightWidth > dstSize.x) {
+ if (sm.cyTopHeight + sm.cyBottomHeight > dstSize.y) {
+ sm.cyTopHeight = MulDiv(sm.cyTopHeight, dstSize.y, srcSize.y);
+ sm.cyBottomHeight = dstSize.y - sm.cyTopHeight;
+ srcSize.y = dstSize.y;
+ }
+
+ if (sm.cxLeftWidth + sm.cxRightWidth > dstSize.x) {
+ sm.cxLeftWidth = MulDiv(sm.cxLeftWidth, dstSize.x, srcSize.x);
+ sm.cxRightWidth = dstSize.x - sm.cxLeftWidth;
+ srcSize.x = dstSize.x;
+ }
+
+ hdcOrigSrc = hdcSrc;
+ hdcSrc = CreateCompatibleDC(NULL);
+ bmpSrcResized = CreateBitmap(srcSize.x, srcSize.y, 1, 32, NULL);
+ SelectObject(hdcSrc, bmpSrcResized);
+
+ UXTHEME_StretchBlt(hdcSrc, 0, 0, srcSize.x, srcSize.y, hdcOrigSrc, rcSrc.left, rcSrc.top,
+ rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top, transparent, transparentcolor);
+
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = srcSize.x;
+ rcSrc.bottom = srcSize.y;
+ }
+#endif /* __REACTOS__ */
+
+ hdcDst = hdc;
+ OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
+
+ /* Upper left corner */
+ if(!UXTHEME_Blt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.left, rcSrc.top,
+ transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ /* Upper right corner */
+ if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, 0,
+ sm.cxRightWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top,
+ transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ /* Lower left corner */
+ if(!UXTHEME_Blt (hdcDst, 0, dstSize.y-sm.cyBottomHeight,
+ sm.cxLeftWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight,
+ transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ /* Lower right corner */
+ if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight,
+ sm.cxRightWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight,
+ transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+
+ if ((sizingtype == ST_STRETCH) || (sizingtype == ST_TILE)) {
+ int destCenterWidth = dstSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
+ int srcCenterWidth = srcSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
+ int destCenterHeight = dstSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
+ int srcCenterHeight = srcSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
+
+ if(destCenterWidth > 0) {
+ /* Center top */
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, 0,
+ destCenterWidth, sm.cyTopHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top,
+ srcCenterWidth, sm.cyTopHeight,
+ sizingtype, transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ /* Center bottom */
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight,
+ destCenterWidth, sm.cyBottomHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight,
+ srcCenterWidth, sm.cyBottomHeight,
+ sizingtype, transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ }
+ if(destCenterHeight > 0) {
+ /* Left center */
+ if(!UXTHEME_SizedBlt (hdcDst, 0, sm.cyTopHeight,
+ sm.cxLeftWidth, destCenterHeight,
+ hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight,
+ sm.cxLeftWidth, srcCenterHeight,
+ sizingtype,
+ transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ /* Right center */
+ if(!UXTHEME_SizedBlt (hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight,
+ sm.cxRightWidth, destCenterHeight,
+ hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight,
+ sm.cxRightWidth, srcCenterHeight,
+ sizingtype, transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ }
+ if(destCenterHeight > 0 && destCenterWidth > 0) {
+ if(!borderonly) {
+ /* Center */
+ if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, sm.cyTopHeight,
+ destCenterWidth, destCenterHeight,
+ hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight,
+ srcCenterWidth, srcCenterHeight,
+ sizingtype, transparent, transparentcolor)) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto draw_error;
+ }
+ }
+ }
+ }
+
+draw_error:
+ SetViewportOrgEx (hdcDst, org.x, org.y, NULL);
+ }
+ SelectObject(hdcSrc, oldSrc);
+ DeleteDC(hdcSrc);
+ if (bmpSrcResized) DeleteObject(bmpSrcResized);
+ if (hdcOrigSrc) DeleteDC(hdcOrigSrc);
+ *pRect = rcDst;
+ return hr;
+}
+
+/*
+ * @unimplemented
+ */
BOOL
WINAPI
-GdiAlphaBlend(
- HDC hDCDst,
- int DstX,
- int DstY,
- int DstCx,
- int DstCy,
- HDC hDCSrc,
- int SrcX,
- int SrcY,
- int SrcCx,
- int SrcCy,
- BLENDFUNCTION BlendFunction
-)
+GdiDrawStream(HDC dc, ULONG l, PGDI_DRAW_STREAM pDS)
{
- if ( hDCSrc == NULL ) return FALSE;
-
- if (GDI_HANDLE_GET_TYPE(hDCSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
-
- return NtGdiAlphaBlend(
- hDCDst,
- DstX,
- DstY,
- DstCx,
- DstCy,
- hDCSrc,
- SrcX,
- SrcY,
- SrcCx,
- SrcCy,
- BlendFunction,
- 0 );
+ if (!pDS || l != sizeof(*pDS))
+ {
+ DPRINT1("GdiDrawStream: Invalid params\n");
+ return 0;
+ }
+
+ if (pDS->signature != 0x44727753 ||
+ pDS->reserved != 0 ||
+ pDS->unknown1 != 1 ||
+ pDS->unknown2 != 9)
+ {
+ DPRINT1("GdiDrawStream: Got unknown pDS data\n");
+ return 0;
+ }
+
+ {
+ MARGINS sm = {pDS->leftSizingMargin, pDS->rightSizingMargin, pDS->topSizingMargin, pDS->bottomSizingMargin};
+ INT transparent = 0;
+ int sizingtype;
+
+ if (pDS->drawOption & DS_TRANSPARENTALPHA)
+ transparent = ALPHABLEND_FULL;
+ else if (pDS->drawOption & DS_TRANSPARENTCLR)
+ transparent = ALPHABLEND_BINARY;
+ else
+ transparent = ALPHABLEND_NONE;
+
+ if (pDS->drawOption & DS_TILE)
+ sizingtype = ST_TILE;
+ else if (pDS->drawOption & DS_TRUESIZE)
+ sizingtype = ST_TRUESIZE;
+ else
+ sizingtype = ST_STRETCH;
+
+ UXTHEME_DrawImageBackground(pDS->hDC,
+ pDS->hImage,
+ &pDS->rcSrc,
+ transparent,
+ pDS->crTransparent,
+ FALSE,
+ sizingtype,
+ &sm,
+ &pDS->rcDest);
+ }
+ return 0;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GdiValidateHandle(HGDIOBJ hobj)
+{
+ PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hobj);
+ if ( (Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 &&
+ ( (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK ) ==
+ GDI_HANDLE_GET_TYPE(hobj) )
+ {
+ HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
+ if(pid == NULL || pid == CurrentProcessId)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+
}
/*
PLDC
FASTCALL
-GdiGetLDC(HDC hDC)
+GdiGetLDC(HDC hdc)
{
- PDC_ATTR Dc_Attr;
- PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX((HGDIOBJ) hDC);
- HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
- // Don't check the mask, just the object type.
- if ( Entry->ObjectType == GDIObjType_DC_TYPE &&
- (pid == NULL || pid == CurrentProcessId) )
+ PDC_ATTR pdcattr;
+
+ /* Get the DC attribute */
+ pdcattr = GdiGetDcAttr(hdc);
+ if (pdcattr == NULL)
{
- BOOL Result = TRUE;
- if (Entry->UserData)
- {
- volatile CHAR *Current = (volatile CHAR*)Entry->UserData;
- _SEH2_TRY
- {
- *Current = *Current;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Result = FALSE;
- }
- _SEH2_END
- }
- else
- Result = FALSE;
+ return NULL;
+ }
- if (Result)
- {
- Dc_Attr = (PDC_ATTR)Entry->UserData;
- return Dc_Attr->pvLDC;
- }
+ /* Return the LDC pointer */
+ return pdcattr->pvLDC;
+}
+
+BOOL
+FASTCALL
+GdiSetLDC(HDC hdc, PVOID pvLDC)
+{
+ PDC_ATTR pdcattr;
+
+ /* Get the DC attribute */
+ pdcattr = GdiGetDcAttr(hdc);
+ if (pdcattr == NULL)
+ {
+ return FALSE;
}
- return NULL;
+
+ /* Set the LDC pointer */
+ pdcattr->pvLDC = pvLDC;
+ return TRUE;
}
+
VOID GdiSAPCallback(PLDC pldc)
{
DWORD Time, NewTime = GetTickCount();
*/
DWORD
WINAPI
-GdiGetBatchLimit()
+GdiGetBatchLimit(VOID)
{
return GDI_BatchLimit;
}
-/*
- * @unimplemented
- */
-BOOL
-WINAPI
-GdiReleaseDC(HDC hdc)
-{
- return 0;
-}
-
-INT
-WINAPI
-ExtEscape(HDC hDC,
- int nEscape,
- int cbInput,
- LPCSTR lpszInData,
- int cbOutput,
- LPSTR lpszOutData)
-{
- return NtGdiExtEscape(hDC, NULL, 0, nEscape, cbInput, (LPSTR)lpszInData, cbOutput, lpszOutData);
-}
/*
* @implemented
NtCurrentTeb()->LastErrorValue = (ULONG) dwErrCode;
}
-BOOL
-WINAPI
-GdiAddGlsBounds(HDC hdc,LPRECT prc)
-{
- //FIXME: Lookup what 0x8000 means
- return NtGdiSetBoundsRect(hdc, prc, 0x8000 | DCB_ACCUMULATE ) ? TRUE : FALSE;
-}
-
-extern PGDIHANDLECACHE GdiHandleCache;
-
HGDIOBJ
FASTCALL
hGetPEBHandle(HANDLECACHETYPE Type, COLORREF cr)
return Handle;
}
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+bMakePathNameW(LPWSTR lpBuffer,LPCWSTR lpFileName,LPWSTR *lpFilePart,DWORD unknown)
+{
+ UNIMPLEMENTED;
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return 0;
+}
+
+/*
+ * @implemented
+ */
+DEVMODEW *
+WINAPI
+GdiConvertToDevmodeW(const DEVMODEA *dmA)
+{
+ DEVMODEW *dmW;
+ WORD dmW_size, dmA_size;
+
+ dmA_size = dmA->dmSize;
+
+ /* this is the minimal dmSize that XP accepts */
+ if (dmA_size < FIELD_OFFSET(DEVMODEA, dmFields))
+ return NULL;
+
+ if (dmA_size > sizeof(DEVMODEA))
+ dmA_size = sizeof(DEVMODEA);
+
+ dmW_size = dmA_size + CCHDEVICENAME;
+ if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
+ dmW_size += CCHFORMNAME;
+
+ dmW = HeapAlloc(GetProcessHeap(), 0, dmW_size + dmA->dmDriverExtra);
+ if (!dmW) return NULL;
+
+ MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, CCHDEVICENAME,
+ dmW->dmDeviceName, CCHDEVICENAME);
+ /* copy slightly more, to avoid long computations */
+ memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, dmA_size - CCHDEVICENAME);
+
+ if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
+ {
+ MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, CCHFORMNAME,
+ dmW->dmFormName, CCHFORMNAME);
+ if (dmA_size > FIELD_OFFSET(DEVMODEA, dmLogPixels))
+ memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA_size - FIELD_OFFSET(DEVMODEA, dmLogPixels));
+ }
+
+ if (dmA->dmDriverExtra)
+ memcpy((char *)dmW + dmW_size, (const char *)dmA + dmA_size, dmA->dmDriverExtra);
+
+ dmW->dmSize = dmW_size;
+
+ return dmW;
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+GdiRealizationInfo(HDC hdc,
+ PREALIZATION_INFO pri)
+{
+ // ATM we do not support local font data and Language Pack.
+ return NtGdiGetRealizationInfo(hdc, pri, (HFONT) NULL);
+}
+
+
+/*
+ * @unimplemented
+ */
+VOID WINAPI GdiInitializeLanguagePack(DWORD InitParam)
+{
+ UNIMPLEMENTED;
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+}
+
+BOOL
+WINAPI
+GdiAddGlsBounds(HDC hdc,LPRECT prc)
+{
+ return NtGdiSetBoundsRect(hdc, prc, DCB_WINDOWMGR|DCB_ACCUMULATE ) ? TRUE : FALSE;
+}
+
+BOOL
+WINAPI
+GetBoundsRectAlt(HDC hdc,LPRECT prc,UINT flags)
+{
+ return NtGdiGetBoundsRect(hdc, prc, flags);
+}
+
+BOOL
+WINAPI
+SetBoundsRectAlt(HDC hdc,LPRECT prc,UINT flags)
+{
+ return NtGdiSetBoundsRect(hdc, prc, flags );
+}
+
+/*
+ * @unimplemented
+ */
+BOOL
+WINAPI
+GdiAddGlsRecord(HDC hdc,
+ DWORD unknown1,
+ LPCSTR unknown2,
+ LPRECT unknown3)
+{
+ UNIMPLEMENTED;
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return 0;
+}
+