dll部分:
/////xxx.h
#ifndef HOOK_API
#define HOOK_API __declspec(dllimport)
#endif
HOOK_API BOOL WINAPI SetDIPSHook(DWORD dwThreadId);
/////xxx.cpp
#define HOOK_API __declspec(dllexport)
#include "hook.h"
#include <Windows.h>
#include "resource.h"
#include <fstream>
using namespace std;
#pragma data_seg("shared")
HHOOK g_hhook = NULL;
DWORD g_dwThreadIdDIPS = 0;
#pragma data_seg()
#pragma comment(linker, "/section:shared,rws")
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HINSTANCE g_hinstDll = NULL;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
// DLL is attaching to the address space of the current process.
g_hinstDll = hModule;
break;
case DLL_THREAD_ATTACH:
// A new thread is being created in the current process.
break;
case DLL_THREAD_DETACH:
// A thread is exiting cleanly.
break;
case DLL_PROCESS_DETACH:
// The calling process is detaching the DLL from its address space.
break;
}
return TRUE;
}
BOOL WINAPI SetDIPSHook(DWORD dwThreadId)
{
BOOL fOk = FALSE;
if (dwThreadId != 0) {
// Save our thread ID in a shared variable so that our GetMsgProc
// function can post a message back to to thread when the server
// window has been created.
g_dwThreadIdDIPS = GetCurrentThreadId();
// Install the hook on the specified thread
g_hhook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hinstDll,
dwThreadId);
fOk = (g_hhook != NULL);
if (fOk) {
// The hook was installed successfully; force a benign message to
// the thread's queue so that the hook function gets called.
fOk = PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
}
} else {
// Make sure that a hook has been installed.
fOk = UnhookWindowsHookEx(g_hhook);
g_hhook = NULL;
}
return(fOk);
}
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
static BOOL fFirstTime = TRUE;
if (fFirstTime) {
// The DLL just got injected.
fFirstTime = FALSE;
// Uncomment the line below to invoke the debugger
// on the process that just got the injected DLL.
// ForceDebugBreak();
// Create the DTIS Server window to handle the client request.
CreateDialog(g_hinstDll, MAKEINTRESOURCE(IDD_DIALOG1), NULL, Dlg_Proc);
// Tell the DIPS application that the server is up
// and ready to handle requests.
PostThreadMessage(g_dwThreadIdDIPS, WM_NULL, 0, 0);
}
return(CallNextHookEx(g_hhook, nCode, wParam, lParam));
}
///////////////////////////////////////////////////////////////////////////////
void Dlg_OnClose(HWND hwnd) {
DestroyWindow(hwnd);
}
///////////////////////////////////////////////////////////////////////////////
static const TCHAR g_szRegSubKey[] =
TEXT("Software//Richter//Desktop Item Position Saver");
///////////////////////////////////////////////////////////////////////////////
void SaveListViewItemPositions(HWND hwndLV) {
/*
int nMaxItems = ListView_GetItemCount(hwndLV);
// When saving new positions, delete the old position
// information that is currently in the registry.
LONG l = RegDeleteKey(HKEY_CURRENT_USER, g_szRegSubKey);
// Create the registry key to hold the info
HKEY hkey;
l = RegCreateKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, NULL);
chASSERT(l == ERROR_SUCCESS);
for (int nItem = 0; nItem < nMaxItems; nItem++) {
// Get the name and position of a ListView item.
TCHAR szName[MAX_PATH];
ListView_GetItemText(hwndLV, nItem, 0, szName, chDIMOF(szName));
POINT pt;
ListView_GetItemPosition(hwndLV, nItem, &pt);
// Save the name and position in the registry.
l = RegSetValueEx(hkey, szName, 0, REG_BINARY, (PBYTE) &pt, sizeof(pt));
chASSERT(l == ERROR_SUCCESS);
}
RegCloseKey(hkey);
*/
ofstream fout("e:/1.txt");
fout<<"save";
fout.close();
}
///////////////////////////////////////////////////////////////////////////////
void RestoreListViewItemPositions(HWND hwndLV) {
/*
HKEY hkey;
LONG l = RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegSubKey,
0, KEY_QUERY_VALUE, &hkey);
if (l == ERROR_SUCCESS) {
// If the ListView has AutoArrange on, temporarily turn it off.
DWORD dwStyle = GetWindowStyle(hwndLV);
if (dwStyle & LVS_AUTOARRANGE)
SetWindowLong(hwndLV, GWL_STYLE, dwStyle & ~LVS_AUTOARRANGE);
l = NO_ERROR;
for (int nIndex = 0; l != ERROR_NO_MORE_ITEMS; nIndex++) {
TCHAR szName[MAX_PATH];
DWORD cbValueName = chDIMOF(szName);
POINT pt;
DWORD cbData = sizeof(pt), nItem;
// Read a value name and position from the registry.
DWORD dwType;
l = RegEnumValue(hkey, nIndex, szName, &cbValueName,
NULL, &dwType, (PBYTE) &pt, &cbData);
if (l == ERROR_NO_MORE_ITEMS)
continue;
if ((dwType == REG_BINARY) && (cbData == sizeof(pt))) {
// The value is something that we recognize; try to find
// an item in the ListView control that matches the name.
LV_FINDINFO lvfi;
lvfi.flags = LVFI_STRING;
lvfi.psz = szName;
nItem = ListView_FindItem(hwndLV, -1, &lvfi);
if (nItem != -1) {
// We found a match; change the item's position.
ListView_SetItemPosition(hwndLV, nItem, pt.x, pt.y);
}
}
}
// Turn AutoArrange back on if it was originally on.
SetWindowLong(hwndLV, GWL_STYLE, dwStyle);
RegCloseKey(hkey);
}
*/
ofstream fout("e:/1.txt");
fout<<"load";
fout.close();
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_APP:
// Uncomment the line below to invoke the debugger
// on the process that just got the injected DLL.
// ForceDebugBreak();
if (lParam==1)
SaveListViewItemPositions((HWND) wParam);
else
RestoreListViewItemPositions((HWND) wParam);
break;
}
return(FALSE);
}
exe测试部分:
HWND hwndLV = ::GetFirstChild(::GetFirstChild(::FindWindow("ProgMan",NULL)));
if(hwndLV==NULL)
AfxMessageBox("zfq");
SetDIPSHook(GetWindowThreadProcessId(hwndLV, NULL));
// Wait for the DIPS server window to be created.
MSG msg;
GetMessage(&msg, NULL, 0, 0);
// Find the handle of the hidden dialog box window.
hwndDIPS = ::FindWindow(NULL, "HookServer");
// Tell the DIPS window which ListView window to manipulate
// and whether the items should be saved or restored.
::SendMessage(hwndDIPS, WM_APP, (WPARAM) hwndLV, 0);
// Tell the DIPS window to destroy itself. Use SendMessage
// instead of PostMessage so that we know the window is
// destroyed before the hook is removed.
::SendMessage(hwndDIPS, WM_CLOSE, 0, 0);
// Unhook the DLL, removing the DIPS dialog box procedure
// from the Explorer's address space.
SetDIPSHook(0);