VBoxVideoWinDbg.cpp revision 67927207a2d6bb545eb655ef14cdb090b1957120
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync/* $Id$ */
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync/*
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * Copyright (C) 2010 Oracle Corporation
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync *
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * available from http://www.virtualbox.org. This file is free software;
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * you can redistribute it and/or modify it under the terms of the GNU
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * General Public License (GPL) as published by the Free Software
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync */
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#include <windows.h>
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#define KDEXT_64BIT
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#include <wdbgexts.h>
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#define VBOXVWD_VERSION_MAJOR 1
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#define VBOXVWD_VERSION_MINOR 1
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncstatic EXT_API_VERSION g_VBoxVWDVersion = {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync VBOXVWD_VERSION_MAJOR,
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync VBOXVWD_VERSION_MINOR,
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync EXT_API_VERSION_NUMBER64,
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync 0
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync};
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync/**
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync * DLL entry point.
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync */
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncBOOL WINAPI DllMain(HINSTANCE hInstance,
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync DWORD dwReason,
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync LPVOID lpReserved)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync BOOL bOk = TRUE;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync switch (dwReason)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
88acfa6629a7976c0583c1712d2b5b22a87a5121vboxsync case DLL_PROCESS_ATTACH:
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync break;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync case DLL_PROCESS_DETACH:
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync break;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync default:
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync break;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync return bOk;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync/* note: need to name it this way to make dprintf & other macros defined in wdbgexts.h work */
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncWINDBG_EXTENSION_APIS64 ExtensionApis = {0};
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncUSHORT SavedMajorVersion;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncUSHORT SavedMinorVersion;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#ifdef __cplusplus
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncextern "C"
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#endif
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncLPEXT_API_VERSION WDBGAPI ExtensionApiVersion();
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncVOID WDBGAPI CheckVersion();
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncVOID WDBGAPI WinDbgExtensionDllInit(PWINDBG_EXTENSION_APIS64 lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#ifdef __cplusplus
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync#endif
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncLPEXT_API_VERSION WDBGAPI ExtensionApiVersion()
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync return &g_VBoxVWDVersion;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncVOID WDBGAPI CheckVersion()
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync return;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncVOID WDBGAPI WinDbgExtensionDllInit(PWINDBG_EXTENSION_APIS64 lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync ExtensionApis = *lpExtensionApis;
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync SavedMajorVersion = MajorVersion;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync SavedMinorVersion = MinorVersion;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncDECLARE_API(help)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("**** VirtulBox Video Driver debugging extension ****\n"
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync " The following commands are supported: \n"
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync " !ms - save memory (video data) to clipboard \n"
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync " usage: !ms <virtual memory address> <width> <height> [bitsPerPixel (default is 32)] [pitch (default is ((width * bpp + 7) >> 3) + 3) & ~3)]\n");
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync}
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsyncDECLARE_API(ms)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync{
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64Mem;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64Width;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64Height;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64Bpp = 32;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64NumColors = 3;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64Pitch;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync ULONG64 u64DefaultPitch;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync PCSTR pExpr = args;
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync if (!pExpr) { dprintf("address not specified\n"); return; }
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync if (!GetExpressionEx(pExpr, &u64Mem, &pExpr)) { dprintf("error evaluating address\n"); return; }
002ceede8bd0a6978946f0fbf9877b6a07e94db7vboxsync if (!u64Mem) { dprintf("address value can not be NULL\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!pExpr) { dprintf("width not specified\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!GetExpressionEx(pExpr, &u64Width, &pExpr)) { dprintf("error evaluating width\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!u64Width) { dprintf("width value can not be NULL\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!pExpr) { dprintf("height not specified\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!GetExpressionEx(pExpr, &u64Height, &pExpr)) { dprintf("error evaluating height\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!u64Height) { dprintf("height value can not be NULL\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (pExpr && GetExpressionEx(pExpr, &u64NumColors, &pExpr))
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!u64NumColors) { dprintf("Num Colors value can not be NULL\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (pExpr && GetExpressionEx(pExpr, &u64Bpp, &pExpr))
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!u64Bpp) { dprintf("bpp value can not be NULL\n"); return; }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync u64DefaultPitch = (((((u64Width * u64Bpp) + 7) >> 3) + 3) & ~3ULL);
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync if (pExpr && GetExpressionEx(pExpr, &u64Pitch, &pExpr))
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync {
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync if (u64Pitch < u64DefaultPitch) { dprintf("pitch value can not be less than (%I)\n", u64DefaultPitch); return; }
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync }
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync else
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync {
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync u64Pitch = u64DefaultPitch;
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync }
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync dprintf("processing data for address(0x%p), width(%d), height(%d), bpp(%d), pitch(%d)...\n",
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync u64Mem, (UINT)u64Width, (UINT)u64Height, (UINT)u64Bpp, (UINT)u64Pitch);
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync ULONG64 cbSize = u64DefaultPitch * u64Height;
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync PVOID pvBuf = malloc(cbSize);
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync if (pvBuf)
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync {
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync ULONG uRc = 0;
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync if(u64DefaultPitch == u64Pitch)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync ULONG cbRead = 0;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("reading the entire memory buffer...\n");
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync uRc = ReadMemory(u64Mem, pvBuf, cbSize, &cbRead);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!uRc)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("Failed to read the memory buffer of size(%I)\n", cbSize);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync else if (cbRead != cbSize)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("the actual number of bytes read(%I) no equal the requested size(%I)\n", cbRead, cbSize);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync uRc = 0;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync else
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync ULONG64 u64Offset = u64Mem;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync char* pvcBuf = (char*)pvBuf;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync ULONG64 i;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("reading memory by chunks since custom pitch is specified...\n");
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync for (i = 0; i < u64Height; ++i, u64Offset+=u64Pitch, pvcBuf+=u64DefaultPitch)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync ULONG cbRead = 0;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync uRc = ReadMemory(u64Offset, pvcBuf, u64DefaultPitch, &cbRead);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (!uRc)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("Failed to read the memory buffer of size(%I), chunk(%I)\n", u64DefaultPitch, i);
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync break;
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync }
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync else if (cbRead != u64DefaultPitch)
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync {
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync dprintf("the actual number of bytes read(%I) no equal the requested size(%I), chunk(%I)\n", cbRead, u64DefaultPitch, i);
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync uRc = 0;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync break;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync }
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync }
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync if (uRc)
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync {
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync switch (u64Bpp)
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync {
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync case 32:
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync case 24:
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync case 16:
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync if (u64NumColors != 3)
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync {
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync dprintf("WARNING: unsupported number colors: (%d)\n", u64NumColors);
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync }
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync break;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync case 8:
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync {
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync if (u64NumColors == 1)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync ULONG64 cbSize32 = u64DefaultPitch * 4 * u64Height;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync PVOID pvBuf32 = malloc(cbSize32);
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (pvBuf32)
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync byte* pByteBuf32 = (byte*)pvBuf32;
0d7011109d3d6a3608cd2e3e2d4f80bf537501b9vboxsync byte* pByteBuf = (byte*)pvBuf;
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync memset(pvBuf32, 0, cbSize32);
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync for (UINT i = 0; i < u64Height; ++i)
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync {
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync for (UINT j = 0; j < u64Width; ++j)
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync {
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync pByteBuf32[0] = pByteBuf[0];
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync pByteBuf32[1] = pByteBuf[0];
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync pByteBuf32[2] = pByteBuf[0];
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync pByteBuf32 += 4;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync pByteBuf += 1;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync free(pvBuf);
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync pvBuf = pvBuf32;
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync u64DefaultPitch *= 4;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync u64Bpp *= 4;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync }
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync else
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync {
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync dprintf("WARNING: unsupported number colors: (%d)\n", u64NumColors);
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync }
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync break;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync }
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync BITMAP Bmp = {0};
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync HBITMAP hBmp;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync dprintf("read memory succeeded..\n");
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync Bmp.bmType = 0;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync Bmp.bmWidth = (LONG)u64Width;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync Bmp.bmHeight = (LONG)u64Height;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync Bmp.bmWidthBytes = (LONG)u64DefaultPitch;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync Bmp.bmPlanes = 1;
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync Bmp.bmBitsPixel = (WORD)u64Bpp;
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync Bmp.bmBits = (LPVOID)pvBuf;
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync hBmp = CreateBitmapIndirect(&Bmp);
009635ee9648f6f4405065001dc9acb6f9af7c83vboxsync if (hBmp)
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync {
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync if (OpenClipboard(GetDesktopWindow()))
5a6c4ec7956e6e9501d97a19b61c3c101bb2086bvboxsync {
4d0d9097df43f55a27ac86bdd587e8c217493e62vboxsync if (EmptyClipboard())
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync if (SetClipboardData(CF_BITMAP, hBmp))
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync {
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync dprintf("succeeded!! You can now do <ctrl>+v in your favourite image editor\n");
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync }
70d78cc23a9585983d71fec4e7df3dce0de2b713vboxsync else
{
DWORD winEr = GetLastError();
dprintf("SetClipboardData failed, err(%I)\n", winEr);
}
}
else
{
DWORD winEr = GetLastError();
dprintf("EmptyClipboard failed, err(%I)\n", winEr);
}
CloseClipboard();
}
else
{
DWORD winEr = GetLastError();
dprintf("OpenClipboard failed, err(%I)\n", winEr);
}
DeleteObject(hBmp);
}
else
{
DWORD winEr = GetLastError();
dprintf("CreateBitmapIndirect failed, err(%I)\n", winEr);
}
}
else
{
dprintf("read memory failed\n");
}
free(pvBuf);
}
else
{
dprintf("failed to allocate memory buffer of size(%I)\n", cbSize);
}
}