先上源代码
DIPSLib.DLL编译篇
这个是公共头文件CmnHdr.h
#pragma once
//#define _WIN32_WINNT _WIN32_WINNT_LONGHORN
//#define WINVER _WIN32_WINNT_LONGHORN
#ifndef UNICODE
#define UNICODE
#endif // UNICODE
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE
#endif // !_UNICODE
#endif // UNICODE
#pragma warning(push,3)
#include<Windows.h>
#pragma warning(pop)
#pragma warning(push,4)
#include<CommCtrl.h>
#include<process.h>
#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCESS
#pragma message("You are not using the latest Platform SDK header /library")
#pragma message("files. This may prevent the project form building correctly.")
#endif // !FILE_SKIP_COMPLETION_PORT_ON_SUCESS
#define chSTR2(x) #x
#define chSTR(x) chSTR2(x)
#define chMSG(desc) message(__FILE__ "(" chSTR(__LINE__) "):" #desc)
inline void chMB(PCSTR szMsg)
{
char szTitle[MAX_PATH];
GetModuleFileNameA(NULL, szTitle, _countof(szTitle));
MessageBoxA(GetActiveWindow(), szMsg, szTitle, MB_OK);
}
inline void chFAIL(PSTR szMsg)
{
chMB(szMsg);
DebugBreak();
}
inline void chASSERTFAIL(LPCSTR file, int line, PCSTR expr)
{
char sz[2 * MAX_PATH];
wsprintfA(sz, "File %s , Linr %d : %s", file, line, expr);
chFAIL(sz);
}
#ifdef _DEBUG
#define chASSERT(x) if(!(x)) chASSERTFAIL(__FILE__,__LINE__,#x)
#else
#define chASSERT(x)
#endif // _DEBUG
#ifdef _DEBUG
#define chVERIFY(x) chASSERT(x)
#else
#define chVERIFY(x) (x)
#endif // _DEBUG
inline void chSETDLGICONS(HWND hWnd, int idi)
{
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)
LoadIcon((HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)
LoadIcon((HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
MAKEINTRESOURCE(idi)));
}
#define chHANDLE_DLGMSG(hWnd,message,fn) \
case(message): return (SetDlgMsgResult(hWnd,message,HANDLE_##message((hWnd),(wParam),(lParam),(fn))))
创建个dialog资源用mfc 改名字Wintellect DIPS 改id IDD_DIPS
下面附上DIPSLib代码 .H文件
#pragma once
#if !defined(DIPSLIBAPI)
#define DIPSLIBAPI __declspec(dllimport)
#endif
DIPSLIBAPI BOOL __stdcall SetDIPSHook(DWORD dwThreadId);
.cpp文件
#include"CmnHdr.h"
#include<WindowsX.h>
#include<CommCtrl.h>
#define DIPSLIBAPI __declspec(dllexport)
#include"DIPSLib.h"
#include"resource.h"
#ifdef _DEBUG
void ForceDebugBreak()
{
__try {
DebugBreak();
}
__except (UnhandledExceptionFilter(GetExceptionInformation()))
{
}
}
#else
#define ForceDebugBreak()
#endif // _DEBUG
//Instruct the compiler to put the g_hHook data variable in its own
//data section called shared. we then instruct the linker that we want to
//share the data in this section with all instances of this application
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
DWORD g_dwThreadIdDIPS = 0;
#pragma data_seg()
//Instruct the linker to make the shared section
//readable writeable and shared
#pragma comment(linker,"/section:Shared,rws")
//Nonshared variables
HINSTANCE g_hInstDll = NULL;
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID fImpLoad)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_hInstDll = hInstance;
break;
case DLL_THREAD_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_DETACH:
break;
default:
break;
}
return TRUE;
}
BOOL WINAPI SetDIPSHook(DWORD dwThreadId)
{
BOOL bok = FALSE;
if (dwThreadId != 0)
{
//make sure that the hook is not already installed
chASSERT(g_hHook == NULL);
//Save our thread ID in a shared variable so that our GetMsgProc
//function can post a message back to the thread when the server window
//has been created
g_dwThreadIdDIPS = GetCurrentThreadId();
//install the hook on the spacified thread
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, dwThreadId);
bok = (g_hHook != NULL);
if (bok)
{
//The Hook was installed sucessfully; force a benign message to
//the thread's queue so that the hook funtion gets called
bok = PostThreadMessage(dwThreadId, WM_NULL, 0, 0);
}
else
{
}
}
else
{
//make sure that a hook has been installed
chASSERT(g_hHook != NULL);
bok = UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
return bok;
}
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static BOOL bFirstTime = TRUE;
if (bFirstTime)
{
//the dll just got injected
bFirstTime = FALSE;
chMB("wo jinlaile wokaixin");
//create the dips server window to handle the client request
CreateDialog(g_hInstDll, MAKEINTRESOURCE(IDD_DIPS), 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\\Wintellect\\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 positon of a ListView item.
TCHAR szName[MAX_PATH];
ListView_GetItemText(hWndLV, nItem, 0, szName, _countof(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);
}
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 temporarity turn it of
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 = _countof(szName);
POINT pt;
DWORD cbData = sizeof(pt);
DWORD 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 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 auto arrange back on if it was originally on
SetWindowLong(hWndLV, GWL_STYLE, dwStyle);
RegCloseKey(hkey);
}
}
INT_PTR WINAPI Dlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hWnd, WM_CLOSE, Dlg_OnClose);
case WM_APP:
// Uncomment the line below to invoke the debugger
// on the process that just got the injected DLL.
//ForceDebugBreak();
if (lParam)
SaveListViewItemPositions((HWND)wParam);
else
RestoreListViewItemPositions((HWND)wParam);
break;
}
return FALSE;
}
注意你hook的是explorer 你得确定它的窗口位置用spy++来获取,不再是原先作者提示的一个窗口的唯一子窗口了
第二explorer程序是系统程序如果你是64位系统恭喜你你的整个环境都得换成64位来编译了
命令预处理得加入WIN32(64);_DEBUG;_WINDOWS;_USRDLL;
下面贴exe代码 .cpp
//#include"..\CommonFiles\CmnHdr.h"
#include<WindowsX.h>
#include<Windows.h>
#include<tchar.h>
#include"resource.h"
#pragma comment(lib,"E:\\VS2017WSpce\\Proxxxxxx\\x64\\Debug\\DIPSLib.lib")
#include"../DIPSLib/DIPSLib.h"
#include"CmnHdr.h"
BOOL Dlg_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam)
{
chSETDLGICONS(hWnd, IDI_DIPS);
return TRUE;
}
void Dlg_OnCommand(HWND hWnd, int id, HWND hWndCt1, UINT codeNotify)
{
switch (id)
{
case IDC_SAVE:
case IDC_RESTORE:
case IDCANCEL:
EndDialog(hWnd, id);
break;
default:
break;
}
}
BOOL WINAPI Dlg_Proc2(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
//case(WM_INITDIALOG): return (SetDlgMsgResult(hWnd, message, HANDLE_##message((hWnd), (wParam), (lParam), (Dlg_OnInitDialog))))
//case(WM_COMMAND): return (SetDlgMsgResult(hWnd, message, HANDLE_##message((hWnd), (wParam), (lParam), (Dlg_OnInitDialog))))
chHANDLE_DLGMSG(hWnd, WM_INITDIALOG,Dlg_OnInitDialog);
chHANDLE_DLGMSG(hWnd, WM_COMMAND, Dlg_OnCommand);
}
return FALSE;
}
int WINAPI _tWinMain(HINSTANCE hInstExe, HINSTANCE, PTSTR pszCmdLine, int)
{
//Conver Command-Line character to uppercase
CharUpperBuff(pszCmdLine, 1);
TCHAR cWhatToDo = pszCmdLine[0];
if ((cWhatToDo != TEXT('S')) && (cWhatToDo != TEXT('R')))
{
//An incalid command-line argument;prompt the user
cWhatToDo = 0;
}
if (cWhatToDo == 0)
{
//NO Command-line argument was used to tell us what to
//do; show usage dialog box and prompt the user
switch (DialogBox(hInstExe,MAKEINTRESOURCE(IDD_DIPS),NULL,(DLGPROC)Dlg_Proc2))
{
case IDC_SAVE:
cWhatToDo = TEXT('S');
break;
case IDC_RESTORE:
cWhatToDo = TEXT('R');
break;
default:
break;
}
}
if (cWhatToDo == 0)
{
//The user doesn't want to do anything
return (0);
}
//The Desktop ListView window is the grandchild of the ProMan window.
HWND hWndLV2 = FindWindow(TEXT("Progman"), NULL);
HWND hwnd3 = GetFirstChild(hWndLV2);
HWND hwnd4 = GetNextSibling(hwnd3);
HWND hWndLV = GetFirstChild(hwnd4);
//HWND hWndLV = GetFirstChild(GetFirstChild(
// FindWindow(TEXT("Progman"), NULL)));
chASSERT(IsWindow(hWndLV));
//Set hook that injects out DLL into the Exporer's address space. After
//setting the hook, the DIPS hidden modeless dialog box is created. we
//send messages to this window to tell it what we want it to do.
DWORD threadId = GetWindowThreadProcessId(hWndLV, NULL);
chVERIFY(SetDIPSHook(threadId));
//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.
HWND hWndDIPS = FindWindow(NULL, TEXT("Wintellect DIPS"));
//make sure that the window was created.
chASSERT(IsWindow(hWndDIPS));
//Tell the DIPS window which ListView window to manipulate
//and wherther the item should be saved or restored
BOOL bSave = (cWhatToDo == TEXT('S'));
SendMessage(hWndDIPS, WM_APP, (WPARAM)hWndLV, bSave);
//Tell the DIPS window to destory itself .Use sendMessage
//instead of PostMessage so that we know the window is
//destoryed befor the hook is removed.
SendMessage(hWndDIPS, WM_CLOSE, 0, 0);
//Make sure that the window was destoryed.
chASSERT(!IsWindow(hWndDIPS));
//Unhook the DLL, removing the DIPS dialog box provedure
//form the Exporer's address space.
SetDIPSHook(0);
return 0;
}
这个不要.h
需要包含那个dll的头文件,生成的dll lib 都得移动到工程下面来,附加依赖也得把lib加上去
编译平台得移植,Unicode编码一致,字符集得一致,多线程调试得一致
然后你就可以愉快的踩坑了