mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
74150633f1
Converting a CmdlineArg straight to a Filename allows us to make the filename out of the wide-character version of the string on Windows. So now filenames specified on the command line should generally be able to handle pathnames containing Unicode characters not in the system code page. This change also involves making some char pointers _into_ Filename structs where they weren't previously: for example, the 'openssh_config_file' variable in Windows Pageant's WinMain().
127 lines
3.7 KiB
C
127 lines
3.7 KiB
C
#include "putty.h"
|
|
|
|
#if HAVE_DWMAPI_H
|
|
|
|
#include <dwmapi.h>
|
|
|
|
char *save_screenshot(HWND hwnd, Filename *outfile)
|
|
{
|
|
HDC dcWindow = NULL, dcSave = NULL;
|
|
HBITMAP bmSave = NULL;
|
|
uint8_t *buffer = NULL;
|
|
char *err = NULL;
|
|
|
|
static HMODULE dwmapi_module;
|
|
DECL_WINDOWS_FUNCTION(static, HRESULT, DwmGetWindowAttribute,
|
|
(HWND, DWORD, PVOID, DWORD));
|
|
|
|
if (!dwmapi_module) {
|
|
dwmapi_module = load_system32_dll("dwmapi.dll");
|
|
GET_WINDOWS_FUNCTION(dwmapi_module, DwmGetWindowAttribute);
|
|
}
|
|
|
|
dcWindow = GetDC(NULL);
|
|
if (!dcWindow) {
|
|
err = dupprintf("GetDC(window): %s", win_strerror(GetLastError()));
|
|
goto out;
|
|
}
|
|
|
|
int x, y, w, h;
|
|
RECT wr;
|
|
|
|
/* Use DwmGetWindowAttribute in place of GetWindowRect to exclude
|
|
* drop shadow, otherwise we get a load of unwanted desktop
|
|
* background under the shadow */
|
|
if (p_DwmGetWindowAttribute &&
|
|
0 <= p_DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS,
|
|
&wr, sizeof(wr))) {
|
|
x = wr.left;
|
|
y = wr.top;
|
|
w = wr.right - wr.left;
|
|
h = wr.bottom - wr.top;
|
|
} else {
|
|
BITMAP bmhdr;
|
|
memset(&bmhdr, 0, sizeof(bmhdr));
|
|
GetObject(GetCurrentObject(dcWindow, OBJ_BITMAP),
|
|
sizeof(bmhdr), &bmhdr);
|
|
x = y = 0;
|
|
w = bmhdr.bmWidth;
|
|
h = bmhdr.bmHeight;
|
|
}
|
|
|
|
dcSave = CreateCompatibleDC(dcWindow);
|
|
if (!dcSave) {
|
|
err = dupprintf("CreateCompatibleDC(desktop window dc): %s",
|
|
win_strerror(GetLastError()));
|
|
goto out;
|
|
}
|
|
|
|
bmSave = CreateCompatibleBitmap(dcWindow, w, h);
|
|
if (!bmSave) {
|
|
err = dupprintf("CreateCompatibleBitmap: %s",
|
|
win_strerror(GetLastError()));
|
|
goto out;
|
|
}
|
|
|
|
if (!SelectObject(dcSave, bmSave)) {
|
|
err = dupprintf("SelectObject: %s", win_strerror(GetLastError()));
|
|
goto out;
|
|
}
|
|
|
|
if (!BitBlt(dcSave, 0, 0, w, h, dcWindow, x, y, SRCCOPY)) {
|
|
err = dupprintf("BitBlt: %s", win_strerror(GetLastError()));
|
|
goto out;
|
|
}
|
|
|
|
BITMAPINFO bmInfo;
|
|
memset(&bmInfo, 0, sizeof(bmInfo));
|
|
bmInfo.bmiHeader.biSize = sizeof(bmInfo.bmiHeader);
|
|
bmInfo.bmiHeader.biWidth = w;
|
|
bmInfo.bmiHeader.biHeight = h;
|
|
bmInfo.bmiHeader.biPlanes = 1;
|
|
bmInfo.bmiHeader.biBitCount = 32;
|
|
bmInfo.bmiHeader.biCompression = BI_RGB;
|
|
|
|
size_t bmPixels = (size_t)w*h, bmBytes = bmPixels * 4;
|
|
buffer = snewn(bmBytes, uint8_t);
|
|
|
|
if (!GetDIBits(dcWindow, bmSave, 0, h, buffer, &bmInfo, DIB_RGB_COLORS))
|
|
err = dupprintf("GetDIBits (get data): %s",
|
|
win_strerror(GetLastError()));
|
|
|
|
FILE *fp = f_open(outfile, "wb", false);
|
|
if (!fp) {
|
|
err = dupprintf("'%s': unable to open file", filename_to_str(outfile));
|
|
goto out;
|
|
}
|
|
|
|
BITMAPFILEHEADER bmFileHdr;
|
|
bmFileHdr.bfType = 'B' | ('M' << 8);
|
|
bmFileHdr.bfSize = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader) + bmBytes;
|
|
bmFileHdr.bfOffBits = sizeof(bmFileHdr) + sizeof(bmInfo.bmiHeader);
|
|
fwrite((void *)&bmFileHdr, 1, sizeof(bmFileHdr), fp);
|
|
fwrite((void *)&bmInfo.bmiHeader, 1, sizeof(bmInfo.bmiHeader), fp);
|
|
fwrite((void *)buffer, 1, bmBytes, fp);
|
|
fclose(fp);
|
|
|
|
out:
|
|
if (dcWindow)
|
|
ReleaseDC(NULL, dcWindow);
|
|
if (bmSave)
|
|
DeleteObject(bmSave);
|
|
if (dcSave)
|
|
DeleteObject(dcSave);
|
|
sfree(buffer);
|
|
return err;
|
|
}
|
|
|
|
#else /* HAVE_DWMAPI_H */
|
|
|
|
/* Without <dwmapi.h> we can't get the right window rectangle */
|
|
char *save_screenshot(HWND hwnd, Filename *outfile)
|
|
{
|
|
return dupstr("Demo screenshots not compiled in to this build");
|
|
}
|
|
|
|
#endif /* HAVE_DWMAPI_H */
|