reactos/base/applications/clipbrd/winutils.c

300 lines
7.7 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Clipboard Viewer
* FILE: base/applications/clipbrd/winutils.c
* PURPOSE: Miscellaneous helper functions.
* PROGRAMMERS: Ricardo Hanke
*/
#include "precomp.h"
void ShowLastWin32Error(HWND hwndParent)
{
DWORD dwError;
LPWSTR lpMsgBuf = NULL;
dwError = GetLastError();
if (dwError == ERROR_SUCCESS)
return;
if (!FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
LANG_USER_DEFAULT,
(LPWSTR)&lpMsgBuf,
0, NULL))
{
return;
}
MessageBoxW(hwndParent, lpMsgBuf, NULL, MB_OK | MB_ICONERROR);
LocalFree(lpMsgBuf);
}
void BringWindowToFront(HWND hWnd)
{
if (IsIconic(hWnd))
{
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
}
else
{
SetForegroundWindow(hWnd);
}
}
int DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT uFormat)
{
LPWSTR lpBuffer;
int nCount;
nCount = LoadStringW(hInstance, uID, (LPWSTR)&lpBuffer, 0);
if (nCount)
{
return DrawTextW(hDC, lpBuffer, nCount, lpRect, uFormat);
}
else
{
return 0;
}
}
int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT uCaption, UINT uType)
{
MSGBOXPARAMSW mb;
ZeroMemory(&mb, sizeof(mb));
mb.cbSize = sizeof(mb);
mb.hwndOwner = hWnd;
mb.hInstance = hInstance;
mb.lpszText = MAKEINTRESOURCEW(uText);
mb.lpszCaption = MAKEINTRESOURCEW(uCaption);
mb.dwStyle = uType;
mb.dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
return MessageBoxIndirectW(&mb);
}
void DrawTextFromClipboard(HDC hDC, LPRECT lpRect, UINT uFormat)
{
HGLOBAL hGlobal;
LPWSTR lpchText;
hGlobal = GetClipboardData(CF_UNICODETEXT);
if (!hGlobal)
return;
lpchText = GlobalLock(hGlobal);
if (!lpchText)
return;
DrawTextW(hDC, lpchText, -1, lpRect, uFormat);
GlobalUnlock(hGlobal);
}
void BitBltFromClipboard(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, int nXSrc, int nYSrc, DWORD dwRop)
{
HDC hdcMem;
HBITMAP hbm;
hdcMem = CreateCompatibleDC(hdcDest);
if (hdcMem)
{
hbm = (HBITMAP)GetClipboardData(CF_BITMAP);
SelectObject(hdcMem, hbm);
BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcMem, nXSrc, nYSrc, dwRop);
DeleteDC(hdcMem);
}
}
void SetDIBitsToDeviceFromClipboard(UINT uFormat, HDC hdc, int XDest, int YDest, int XSrc, int YSrc, UINT uStartScan, UINT fuColorUse)
{
LPBITMAPINFOHEADER lpInfoHeader;
LPBYTE lpBits;
LONG bmWidth, bmHeight;
DWORD dwPalSize = 0;
HGLOBAL hGlobal;
hGlobal = GetClipboardData(uFormat);
if (!hGlobal)
return;
lpInfoHeader = GlobalLock(hGlobal);
if (!lpInfoHeader)
return;
if (lpInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
{
LPBITMAPCOREHEADER lpCoreHeader = (LPBITMAPCOREHEADER)lpInfoHeader;
dwPalSize = 0;
if (lpCoreHeader->bcBitCount <= 8)
{
dwPalSize = (1 << lpCoreHeader->bcBitCount);
if (fuColorUse == DIB_RGB_COLORS)
dwPalSize *= sizeof(RGBTRIPLE);
else
dwPalSize *= sizeof(WORD);
}
bmWidth = lpCoreHeader->bcWidth;
bmHeight = lpCoreHeader->bcHeight;
}
else if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) ||
(lpInfoHeader->biSize == sizeof(BITMAPV4HEADER)) ||
(lpInfoHeader->biSize == sizeof(BITMAPV5HEADER)))
{
dwPalSize = lpInfoHeader->biClrUsed;
if ((dwPalSize == 0) && (lpInfoHeader->biBitCount <= 8))
dwPalSize = (1 << lpInfoHeader->biBitCount);
if (fuColorUse == DIB_RGB_COLORS)
dwPalSize *= sizeof(RGBQUAD);
else
dwPalSize *= sizeof(WORD);
if (/*(lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) &&*/
(lpInfoHeader->biCompression == BI_BITFIELDS))
{
dwPalSize += 3 * sizeof(DWORD);
}
/*
* This is a (disabled) hack for Windows, when uFormat == CF_DIB
* it needs yet another extra 3 DWORDs, in addition to the
* ones already taken into account in via the compression.
* This problem doesn't happen when uFormat == CF_DIBV5
* (in that case, when compression is taken into account,
* everything is nice).
*
* NOTE 1: This fix is only for us, because when one pastes DIBs
* directly in apps, the bitmap offset problem is still present.
*
* NOTE 2: The problem can be seen with Windows' clipbrd.exe if
* one copies a CF_DIB image in the clipboard. By default Windows'
* clipbrd.exe works with CF_DIBV5 and CF_BITMAP, so the problem
* is unseen, and the clipboard doesn't have to convert to CF_DIB.
*
* FIXME: investigate!!
* ANSWER: this is a Windows bug; part of the answer is there:
* http://go4answers.webhost4life.com/Help/bug-clipboard-format-conversions-28724.aspx
* May be related:
* http://blog.talosintel.com/2015/10/dangerous-clipboard.html
*/
#if 0
if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) &&
(lpInfoHeader->biCompression == BI_BITFIELDS))
{
dwPalSize += 3 * sizeof(DWORD);
}
#endif
bmWidth = lpInfoHeader->biWidth;
bmHeight = lpInfoHeader->biHeight;
}
else
{
/* Invalid format */
GlobalUnlock(hGlobal);
return;
}
lpBits = (LPBYTE)lpInfoHeader + lpInfoHeader->biSize + dwPalSize;
SetDIBitsToDevice(hdc,
XDest, YDest,
bmWidth, bmHeight,
XSrc, YSrc,
uStartScan,
bmHeight,
lpBits,
(LPBITMAPINFO)lpInfoHeader,
fuColorUse);
GlobalUnlock(hGlobal);
}
void PlayMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
{
LPMETAFILEPICT mp;
HGLOBAL hGlobal;
hGlobal = GetClipboardData(CF_METAFILEPICT);
if (!hGlobal)
return;
mp = (LPMETAFILEPICT)GlobalLock(hGlobal);
if (!mp)
return;
SetMapMode(hdc, mp->mm);
SetViewportExtEx(hdc, lpRect->right, lpRect->bottom, NULL);
SetViewportOrgEx(hdc, lpRect->left, lpRect->top, NULL);
PlayMetaFile(hdc, mp->hMF);
GlobalUnlock(hGlobal);
}
void PlayEnhMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
{
HENHMETAFILE hEmf;
hEmf = GetClipboardData(CF_ENHMETAFILE);
PlayEnhMetaFile(hdc, hEmf, lpRect);
}
UINT RealizeClipboardPalette(HWND hWnd)
{
HPALETTE hPalette;
HPALETTE hOldPalette;
UINT uResult;
HDC hDevContext;
if (!OpenClipboard(Globals.hMainWnd))
{
return GDI_ERROR;
}
if (!IsClipboardFormatAvailable(CF_PALETTE))
{
CloseClipboard();
return GDI_ERROR;
}
hPalette = GetClipboardData(CF_PALETTE);
if (!hPalette)
{
CloseClipboard();
return GDI_ERROR;
}
hDevContext = GetDC(hWnd);
if (!hDevContext)
{
CloseClipboard();
return GDI_ERROR;
}
hOldPalette = SelectPalette(hDevContext, hPalette, FALSE);
if (!hOldPalette)
{
ReleaseDC(hWnd, hDevContext);
CloseClipboard();
return GDI_ERROR;
}
uResult = RealizePalette(hDevContext);
SelectPalette(hDevContext, hOldPalette, FALSE);
ReleaseDC(hWnd, hDevContext);
CloseClipboard();
return uResult;
}