LV2Clip.cpp
/******************************************************************************
Module name: LV2Clip.cpp
Written by: Jeffrey Richter
Purpose: Utilty to copy ListView control strings to the clipboard.
******************************************************************************/
#define STRICT
#define UNICODE
#define _UNICODE
#include <Windows.h>
#include <WindowsX.h>
#include <commctrl.h>
#include <tchar.h>
#include <stdio.h>
#include "Resource.h"
///////////////////////////////////////////////////////////////////////////////
// For message box captions
TCHAR g_szAppName[] = __TEXT("ListView to Clipboard");
///////////////////////////////////////////////////////////////////////////////
// Returns HWND of ListView control under a screen coordinate
HWND LV2Clip_GetLVFromPoint(HWND hwnd, int x, int y) {
POINT pt = { x, y };
// Convert the (x, y) from client to screen coordinates
ClientToScreen(hwnd, &pt);
// Get the top-level window that is under the mouse cursor
HWND hwndLV = WindowFromPoint(pt);
// Convert (x, y) from screen to parent window's client coordinates
ScreenToClient(hwndLV, &pt);
// Determine which child window (if any) is under the mouse cursor
hwndLV = ChildWindowFromPoint(hwndLV, pt);
if (hwndLV != NULL) {
// Check to see if the child window is a ListView control
TCHAR sz[100];
GetClassName(hwndLV, sz, 100);
if (lstrcmpi(sz, WC_LISTVIEW) != 0)
hwndLV = NULL; // Not a ListView control
}
// Update the finder tool's status to indicate whether the cursor
// is over a ListView control or not.
SetDlgItemText(hwnd, IDC_FINDERSTATUS,
(hwndLV != NULL) ?
__TEXT("The Finder is over a ListView control") :
__TEXT("The Finder is NOT over a ListView control"));
return(hwndLV); // Returns NULL if not a ListView control
}
///////////////////////////////////////////////////////////////////////////////
void LV2Clip_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags) {
// If we didn't have capture set, we have nothing to do.
if (GetCapture() == hwnd) {
// Update the Finder Tool's status
LV2Clip_GetLVFromPoint(hwnd, x, y);
}
}
///////////////////////////////////////////////////////////////////////////////
void LV2Clip_OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags) {
// If we didn't have capture set, we have nothing to do.
if (GetCapture() != hwnd) return;
ReleaseCapture();
// Restore the Finder Tool icon
Static_SetIcon(GetDlgItem(hwnd, IDC_FINDERTOOL),
LoadIcon(GetWindowInstance(hwnd), MAKEINTRESOURCE(IDI_DOCKEDFINDER)));
// Get the HWND of the ListView under the mouse cursor
HWND hwndLV = LV2Clip_GetLVFromPoint(hwnd, x, y);
// If the window under the cursor isn't a ListView, we have nothing to do.
if (hwndLV == NULL) return;
// Get the count of items in the ListView control
int nCount = ListView_GetItemCount(hwndLV);
// Open a handle to the remote process's kernel object
DWORD dwProcessId;
GetWindowThreadProcessId(hwndLV, &dwProcessId);
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
FALSE, dwProcessId);
if (hProcess == NULL) {
MessageBox(hwnd, __TEXT("Could not communicate with process"),
g_szAppName, MB_OK | MB_ICONWARNING);
return;
}
// Prepare a buffer to hold the ListView's data.
// Note: Hardcoded maximum of 10240 chars for clipboard data.
// Note: Clipboard only accepts data that is in a block allocated with
// GlobalAlloc using the GMEM_MOVEABLE and GMEM_DDESHARE flags.
HGLOBAL hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
sizeof(TCHAR) * 10240);
LPTSTR pClipData = (LPTSTR) GlobalLock(hClipData);
pClipData[0] = 0;
// Allocate memory in the remote process's address space
LV_ITEM* plvi = (LV_ITEM*) VirtualAllocEx(hProcess,
NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Get each ListView item's text data
for (int nIndex = 0; nIndex < nCount; nIndex++) {
// Initialize a local LV_ITEM structure
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iItem = nIndex;
lvi.iSubItem = 0;
// NOTE: The text data immediately follows the LV_ITEM structure
// in the memory block allocated in the remote process.
lvi.pszText = (LPTSTR) (plvi + 1);
lvi.cchTextMax = 100;
// Write the local LV_ITEM structure to the remote memory block
WriteProcessMemory(hProcess, plvi, &lvi, sizeof(lvi), NULL);
// Tell the ListView control to fill the remote LV_ITEM structure
ListView_GetItem(hwndLV, plvi);
// If this is not the first item, add a carriage-return/linefeed
if (nIndex > 0) lstrcat(pClipData, __TEXT("\r\n"));
// Read the remote text string into the end of our clipboard buffer
ReadProcessMemory(hProcess, plvi + 1,
&pClipData[lstrlen(pClipData)], 1024, NULL);
}
// Free the memory in the remote process's address space
VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);
// Cleanup and put our results on the clipboard
CloseHandle(hProcess);
OpenClipboard(hwnd);
EmptyClipboard();
#ifdef UNICODE
BOOL fOk = (SetClipboardData(CF_UNICODETEXT, hClipData) == hClipData);
#else
BOOL fOk = (SetClipboardData(CF_TEXT, hClipData) == hClipData);
#endif
CloseClipboard();
if (!fOk) {
GlobalFree(hClipData);
MessageBox(hwnd, __TEXT("Error putting text on the clipboard"),
g_szAppName, MB_OK | MB_ICONINFORMATION);
}
}
///////////////////////////////////////////////////////////////////////////////
void LV2Clip_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
switch (id) {
case IDCANCEL:
EndDialog(hwnd, 0);
break;
case IDC_FINDERTOOL:
switch (codeNotify) {
case STN_CLICKED:
SetCapture(hwnd);
Static_SetIcon(hwndCtl, LoadIcon(GetWindowInstance(hwnd),
MAKEINTRESOURCE(IDI_FLOATINGFINDER)));
SetCursor(LoadCursor(GetWindowInstance(hwnd),
MAKEINTRESOURCE(IDC_FINDER)));
break;
}
break;
}
}
///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI LV2Clip_WndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
HANDLE_MSG(hwnd, WM_COMMAND, LV2Clip_OnCommand);
HANDLE_MSG(hwnd, WM_MOUSEMOVE, LV2Clip_OnMouseMove);
HANDLE_MSG(hwnd, WM_LBUTTONUP, LV2Clip_OnLButtonUp);
}
return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hinstExe,
HINSTANCE hinstExePrev, LPSTR pszCmdLine, int nCmdLine) {
return(DialogBox(hinstExe, MAKEINTRESOURCE(IDD_LV2CLIP),
NULL, LV2Clip_WndProc));
}
///////////////////////////////// End of File /////////////////////////////////
Figure 2 MyApp Exception
int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE hinstExePrev,
LPSTR pszCmdLine, int nCmdShow) {
HRSRC hrsrc = FindResource(hinstExe, MAKEINTRESOURCE(IDB_SOMEBITMAP),
RT_BITMAP);
HGLOBAL hglbl = LoadResource(hinstExe, hrsrc);
PBYTE pb = (PBYTE) GlobalLock(hglbl);
BYTE b = *pb; // This does not generate an access violation
*pb = 5; // This does generate an access violation
return(0);
}