ReactOS  0.4.12-dev-57-g7050ac4
winutils.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Clipboard Viewer
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Display helper functions.
5  * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke
6  * Copyright 2015-2018 Hermes Belusca-Maito
7  */
8 
9 #include "precomp.h"
10 
12 {
13  DWORD dwError;
14  LPWSTR lpMsgBuf = NULL;
15 
16  dwError = GetLastError();
17  if (dwError == ERROR_SUCCESS)
18  return;
19 
23  NULL,
24  dwError,
26  (LPWSTR)&lpMsgBuf,
27  0, NULL))
28  {
29  return;
30  }
31 
32  MessageBoxW(hwndParent, lpMsgBuf, NULL, MB_OK | MB_ICONERROR);
33  LocalFree(lpMsgBuf);
34 }
35 
37 {
38  if (IsIconic(hWnd))
39  {
40  ShowWindow(hWnd, SW_RESTORE);
41  SetForegroundWindow(hWnd);
42  }
43  else
44  {
45  SetForegroundWindow(hWnd);
46  }
47 }
48 
49 int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT uCaption, UINT uType)
50 {
51  MSGBOXPARAMSW mb;
52 
53  ZeroMemory(&mb, sizeof(mb));
54  mb.cbSize = sizeof(mb);
55  mb.hwndOwner = hWnd;
56  mb.hInstance = hInstance;
57  mb.lpszText = MAKEINTRESOURCEW(uText);
58  mb.lpszCaption = MAKEINTRESOURCEW(uCaption);
59  mb.dwStyle = uType;
61 
62  return MessageBoxIndirectW(&mb);
63 }
64 
66 {
68  int nCount;
69 
70  nCount = LoadStringW(hInstance, uID, (LPWSTR)&lpBuffer, 0);
71  if (nCount)
72  DrawTextW(hDC, lpBuffer, nCount, lpRect, uFormat);
73 }
74 
76 {
77  POINT ptOrg;
78  HGLOBAL hGlobal;
79  PVOID lpText, ptr;
80  SIZE_T lineSize;
81  INT FirstLine, LastLine;
82 
83  hGlobal = GetClipboardData(uFormat);
84  if (!hGlobal)
85  return;
86 
87  lpText = GlobalLock(hGlobal);
88  if (!lpText)
89  return;
90 
91  /* Find the first and last line indices to display (Note that CurrentX/Y are in pixels!) */
92  FirstLine = max(0, (state.CurrentY + ps.rcPaint.top) / Globals.CharHeight);
93  // LastLine = min(LINES - 1, (state.CurrentY + ps.rcPaint.bottom) / Globals.CharHeight);
94  // NOTE: Can be less or greater than the actual number of lines in the text.
95  LastLine = (state.CurrentY + ps.rcPaint.bottom) / Globals.CharHeight;
96 
97  /* Find the first text line to display */
98  while (FirstLine > 0)
99  {
100  if (uFormat == CF_UNICODETEXT)
101  {
102  if (*(LPCWSTR)lpText == UNICODE_NULL)
103  break;
104  GetLineExtentW(lpText, (LPCWSTR*)&ptr);
105  }
106  else
107  {
108  if (*(LPCSTR)lpText == ANSI_NULL)
109  break;
110  GetLineExtentA(lpText, (LPCSTR*)&ptr);
111  }
112 
113  --FirstLine;
114  --LastLine;
115 
116  lpText = ptr;
117  }
118 
119  ptOrg.x = ps.rcPaint.left;
120  ptOrg.y = /* FirstLine */ max(0, (state.CurrentY + ps.rcPaint.top) / Globals.CharHeight)
121  * Globals.CharHeight - state.CurrentY;
122 
123  /* Display each line from the current one up to the last one */
124  ++LastLine;
125  while (LastLine >= 0)
126  {
127  if (uFormat == CF_UNICODETEXT)
128  {
129  if (*(LPCWSTR)lpText == UNICODE_NULL)
130  break;
131  lineSize = GetLineExtentW(lpText, (LPCWSTR*)&ptr);
132  TabbedTextOutW(ps.hdc, /*ptOrg.x*/0 - state.CurrentX, ptOrg.y,
133  lpText, lineSize, 0, NULL,
134  /*ptOrg.x*/0 - state.CurrentX);
135  }
136  else
137  {
138  if (*(LPCSTR)lpText == ANSI_NULL)
139  break;
140  lineSize = GetLineExtentA(lpText, (LPCSTR*)&ptr);
141  TabbedTextOutA(ps.hdc, /*ptOrg.x*/0 - state.CurrentX, ptOrg.y,
142  lpText, lineSize, 0, NULL,
143  /*ptOrg.x*/0 - state.CurrentX);
144  }
145 
146  --LastLine;
147 
148  ptOrg.y += Globals.CharHeight;
149  lpText = ptr;
150  }
151 
152  GlobalUnlock(hGlobal);
153 }
154 
156 {
157  HDC hdcMem;
159  BITMAP bmp;
160  LONG bmWidth, bmHeight;
161 
162  hdcMem = CreateCompatibleDC(ps.hdc);
163  if (!hdcMem)
164  return;
165 
166  hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
167  GetObjectW(hBitmap, sizeof(bmp), &bmp);
168 
169  SelectObject(hdcMem, hBitmap);
170 
171  bmWidth = min(ps.rcPaint.right - ps.rcPaint.left, bmp.bmWidth - ps.rcPaint.left - state.CurrentX);
172  bmHeight = min(ps.rcPaint.bottom - ps.rcPaint.top , bmp.bmHeight - ps.rcPaint.top - state.CurrentY);
173 
174  BitBlt(ps.hdc,
175  ps.rcPaint.left,
176  ps.rcPaint.top,
177  bmWidth,
178  bmHeight,
179  hdcMem,
180  ps.rcPaint.left + state.CurrentX,
181  ps.rcPaint.top + state.CurrentY,
182  dwRop);
183 
184  DeleteDC(hdcMem);
185 }
186 
188 {
189  HGLOBAL hGlobal;
190  LPBITMAPINFOHEADER lpInfoHeader;
191  LPBYTE lpBits;
192  LONG bmWidth, bmHeight;
193  DWORD dwPalSize = 0;
194 
195  hGlobal = GetClipboardData(uFormat);
196  if (!hGlobal)
197  return;
198 
199  lpInfoHeader = GlobalLock(hGlobal);
200  if (!lpInfoHeader)
201  return;
202 
203  if (lpInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
204  {
205  LPBITMAPCOREHEADER lpCoreHeader = (LPBITMAPCOREHEADER)lpInfoHeader;
206 
207  dwPalSize = 0;
208 
209  if (lpCoreHeader->bcBitCount <= 8)
210  {
211  dwPalSize = (1 << lpCoreHeader->bcBitCount);
212 
213  if (fuColorUse == DIB_RGB_COLORS)
214  dwPalSize *= sizeof(RGBTRIPLE);
215  else
216  dwPalSize *= sizeof(WORD);
217  }
218 
219  bmWidth = lpCoreHeader->bcWidth;
220  bmHeight = lpCoreHeader->bcHeight;
221  }
222  else if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) ||
223  (lpInfoHeader->biSize == sizeof(BITMAPV4HEADER)) ||
224  (lpInfoHeader->biSize == sizeof(BITMAPV5HEADER)))
225  {
226  dwPalSize = lpInfoHeader->biClrUsed;
227 
228  if ((dwPalSize == 0) && (lpInfoHeader->biBitCount <= 8))
229  dwPalSize = (1 << lpInfoHeader->biBitCount);
230 
231  if (fuColorUse == DIB_RGB_COLORS)
232  dwPalSize *= sizeof(RGBQUAD);
233  else
234  dwPalSize *= sizeof(WORD);
235 
236  if (/*(lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) &&*/
237  (lpInfoHeader->biCompression == BI_BITFIELDS))
238  {
239  dwPalSize += 3 * sizeof(DWORD);
240  }
241 
242  /*
243  * This is a (disabled) hack for Windows, when uFormat == CF_DIB
244  * it needs yet another extra 3 DWORDs, in addition to the
245  * ones already taken into account in via the compression.
246  * This problem doesn't happen when uFormat == CF_DIBV5
247  * (in that case, when compression is taken into account,
248  * everything is nice).
249  *
250  * NOTE 1: This fix is only for us, because when one pastes DIBs
251  * directly in apps, the bitmap offset problem is still present.
252  *
253  * NOTE 2: The problem can be seen with Windows' clipbrd.exe if
254  * one copies a CF_DIB image in the clipboard. By default Windows'
255  * clipbrd.exe works with CF_DIBV5 and CF_BITMAP, so the problem
256  * is unseen, and the clipboard doesn't have to convert to CF_DIB.
257  *
258  * FIXME: investigate!!
259  * ANSWER: this is a Windows bug; part of the answer is there:
260  * https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/ac7ab3b5-8609-4478-b86a-976dab44c271/bug-clipboard-format-conversions-cfdib-cfdibv5-cfdib
261  * May be related:
262  * https://blog.talosintelligence.com/2015/10/dangerous-clipboard.html
263  */
264 #if 0
265  if ((lpInfoHeader->biSize == sizeof(BITMAPINFOHEADER)) &&
266  (lpInfoHeader->biCompression == BI_BITFIELDS))
267  {
268  dwPalSize += 3 * sizeof(DWORD);
269  }
270 #endif
271 
272  bmWidth = lpInfoHeader->biWidth;
273  /* NOTE: biHeight < 0 for bottom-up DIBs, or > 0 for top-down DIBs */
274  bmHeight = lpInfoHeader->biHeight;
275  }
276  else
277  {
278  /* Invalid format */
279  GlobalUnlock(hGlobal);
280  return;
281  }
282 
283  lpBits = (LPBYTE)lpInfoHeader + lpInfoHeader->biSize + dwPalSize;
284 
285  /*
286  * The seventh parameter (YSrc) of SetDIBitsToDevice always designates
287  * the Y-coordinate of the "lower-left corner" of the image, be the DIB
288  * in bottom-up or top-down mode.
289  */
291  -state.CurrentX, // ps.rcPaint.left,
292  -state.CurrentY, // ps.rcPaint.top,
293  bmWidth,
294  bmHeight,
295  0, // ps.rcPaint.left + state.CurrentX,
296  0, // -(ps.rcPaint.top + state.CurrentY),
297  0, // uStartScan,
298  bmHeight,
299  lpBits,
300  (LPBITMAPINFO)lpInfoHeader,
301  fuColorUse);
302 
303  GlobalUnlock(hGlobal);
304 }
305 
306 void PlayMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
307 {
308  LPMETAFILEPICT mp;
309  HGLOBAL hGlobal;
310 
312  if (!hGlobal)
313  return;
314 
315  mp = (LPMETAFILEPICT)GlobalLock(hGlobal);
316  if (!mp)
317  return;
318 
319  SetMapMode(hdc, mp->mm);
320  SetViewportExtEx(hdc, lpRect->right, lpRect->bottom, NULL);
321  SetViewportOrgEx(hdc, lpRect->left, lpRect->top, NULL);
322  PlayMetaFile(hdc, mp->hMF);
323  GlobalUnlock(hGlobal);
324 }
325 
327 {
328  HENHMETAFILE hEmf;
329 
331  PlayEnhMetaFile(hdc, hEmf, lpRect);
332 }
333 
335 {
336  BOOL Success;
337  HPALETTE hPalette, hOldPalette;
338 
340  return FALSE;
341 
342  hPalette = GetClipboardData(CF_PALETTE);
343  if (!hPalette)
344  return FALSE;
345 
346  hOldPalette = SelectPalette(hdc, hPalette, FALSE);
347  if (!hOldPalette)
348  return FALSE;
349 
350  Success = (RealizePalette(hdc) != GDI_ERROR);
351 
352  SelectPalette(hdc, hOldPalette, FALSE);
353 
354  return Success;
355 }
#define HDC
Definition: msvc.h:22
HMETAFILE hMF
Definition: wingdi.h:2585
#define max(a, b)
Definition: svc.c:63
BOOL WINAPI SetViewportOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:648
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
#define HBITMAP
Definition: msvc.h:28
long y
Definition: polytest.cpp:48
#define ERROR_SUCCESS
Definition: deptool.c:10
#define CF_ENHMETAFILE
Definition: constants.h:409
DWORD dwLanguageId
Definition: winuser.h:3287
long x
Definition: polytest.cpp:48
#define DWORD
Definition: msvc.h:34
#define LANG_NEUTRAL
Definition: nls.h:22
#define SUBLANG_DEFAULT
Definition: nls.h:168
HWND hWnd
Definition: settings.c:17
LONG top
Definition: windef.h:297
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
void BitBltFromClipboard(PAINTSTRUCT ps, SCROLLSTATE state, DWORD dwRop)
Definition: winutils.c:155
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
LPCWSTR lpszText
Definition: winuser.h:3281
void DrawTextFromResource(HINSTANCE hInstance, UINT uID, HDC hDC, LPRECT lpRect, UINT uFormat)
Definition: winutils.c:65
LONG left
Definition: windef.h:296
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
#define CF_METAFILEPICT
Definition: constants.h:398
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
#define SW_RESTORE
Definition: winuser.h:773
LONG right
Definition: windef.h:298
BOOL WINAPI IsIconic(_In_ HWND)
SIZE_T GetLineExtentA(IN LPCSTR lpText, OUT LPCSTR *lpNextLine)
Definition: cliputils.c:224
static VOID NTAPI BitBlt(IN ULONG Left, IN ULONG Top, IN ULONG Width, IN ULONG Height, IN PUCHAR Buffer, IN ULONG BitsPerPixel, IN ULONG Delta)
Definition: vga.c:416
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:56
#define BI_BITFIELDS
Definition: mmreg.h:507
void ShowLastWin32Error(HWND hwndParent)
Definition: winutils.c:11
CLIPBOARD_GLOBALS Globals
Definition: clipbrd.c:13
while(1)
Definition: macro.lex.yy.c:743
void PlayEnhMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
Definition: winutils.c:326
HINSTANCE hInstance
Definition: charmap.c:20
BOOL RealizeClipboardPalette(HDC hdc)
Definition: winutils.c:334
unsigned char * LPBYTE
Definition: typedefs.h:52
#define UNICODE_NULL
#define ANSI_NULL
long LONG
Definition: pedump.c:60
int WINAPI SetMapMode(_In_ HDC, _In_ int)
LONG WINAPI TabbedTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(chCount) LPCWSTR lpString, _In_ int chCount, _In_ int nTabPositions, _In_reads_opt_(nTabPositions) CONST INT *lpnTabStopPositions, _In_ int nTabOrigin)
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:163
DWORD biCompression
Definition: amvideo.idl:35
static PVOID ptr
Definition: dispmode.c:27
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
HDC hdc
Definition: msvc.h:53
#define CF_UNICODETEXT
Definition: constants.h:408
#define CF_BITMAP
Definition: constants.h:397
void PlayMetaFileFromClipboard(HDC hdc, const RECT *lpRect)
Definition: winutils.c:306
HPALETTE WINAPI SelectPalette(_In_ HDC, _In_ HPALETTE, _In_ BOOL)
smooth NULL
Definition: ftsmooth.c:416
LPCWSTR lpszCaption
Definition: winuser.h:3282
static HWND hwndParent
Definition: cryptui.c:300
struct tagRGBTRIPLE RGBTRIPLE
LONG WINAPI TabbedTextOutA(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(chCount) LPCSTR lpString, _In_ int chCount, _In_ int nTabPositions, _In_reads_opt_(nTabPositions) CONST INT *lpnTabStopPositions, _In_ int nTabOrigin)
const char * LPCSTR
Definition: xmlstorage.h:183
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
int MessageBoxRes(HWND hWnd, HINSTANCE hInstance, UINT uText, UINT uCaption, UINT uType)
Definition: winutils.c:49
struct tagRGBQUAD RGBQUAD
unsigned int BOOL
Definition: ntddk_ex.h:94
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
BOOL WINAPI PlayEnhMetaFile(_In_ HDC, _In_ HENHMETAFILE, _In_ LPCRECT)
struct tagBITMAPCOREHEADER * LPBITMAPCOREHEADER
HWND hwndOwner
Definition: winuser.h:3279
unsigned int UINT
Definition: ndis.h:50
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
BITMAP bmp
Definition: alphablend.c:62
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define MB_ICONERROR
Definition: winuser.h:781
static int state
Definition: maze.c:121
#define CF_PALETTE
Definition: constants.h:404
HINSTANCE hInstance
Definition: winuser.h:3280
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:401
static HDC hDC
Definition: 3dtext.c:33
ULONG_PTR SIZE_T
Definition: typedefs.h:78
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
int WINAPI SetDIBitsToDevice(_In_ HDC, _In_ int, _In_ int, _In_ DWORD, _In_ DWORD, _In_ int, _In_ int, _In_ UINT, _In_ UINT, _In_ CONST VOID *, _In_ CONST BITMAPINFO *, _In_ UINT)
BOOL WINAPI DeleteDC(_In_ HDC)
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
Definition: bl.h:1331
#define min(a, b)
Definition: monoChain.cc:55
SIZE_T GetLineExtentW(IN LPCWSTR lpText, OUT LPCWSTR *lpNextLine)
Definition: cliputils.c:199
void SetDIBitsToDeviceFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state, UINT fuColorUse)
Definition: winutils.c:187
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define MB_OK
Definition: winuser.h:784
HANDLE WINAPI GetClipboardData(_In_ UINT)
void BringWindowToFront(HWND hWnd)
Definition: winutils.c:36
int WINAPI MessageBoxIndirectW(_In_ CONST MSGBOXPARAMSW *)
#define MAKELANGID(p, s)
Definition: nls.h:15
BOOL WINAPI SetForegroundWindow(_In_ HWND)
LONG bottom
Definition: windef.h:299
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
BOOL WINAPI SetViewportExtEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPSIZE)
Definition: coord.c:462
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define DIB_RGB_COLORS
Definition: wingdi.h:365
#define GDI_ERROR
Definition: wingdi.h:1290
DWORD dwStyle
Definition: winuser.h:3283
void DrawTextFromClipboard(UINT uFormat, PAINTSTRUCT ps, SCROLLSTATE state)
Definition: winutils.c:75
static HBITMAP hBitmap
Definition: timezone.c:34
struct tagMETAFILEPICT * LPMETAFILEPICT
UINT WINAPI RealizePalette(_In_ HDC)
Definition: palette.c:138
BOOL WINAPI PlayMetaFile(_In_ HDC, _In_ HMETAFILE)
HDC hdcMem
Definition: welcome.c:104
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:17