mirror of
https://github.com/reactos/reactos.git
synced 2025-05-20 17:45:06 +00:00

Fix the ShowLastWin32Error helpers: - don't display the last error string if it's ERROR_SUCCESS (since the code usually expects to display the last error message in case of errors); - *always* call FormatMessage with the FORMAT_MESSAGE_IGNORE_INSERTS flag enabled. Indeed if it happens that the message string associated to an error ID contains insert parameter placeholders, and since we don't give here FormatMessage any argument array, the call would result into a crash without this flag. svn path=/trunk/; revision=72897
299 lines
7.7 KiB
C
299 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;
|
|
}
|