-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathDIPSLib.cpp
More file actions
282 lines (189 loc) · 7.77 KB
/
Copy pathDIPSLib.cpp
File metadata and controls
282 lines (189 loc) · 7.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/******************************************************************************
Module: DIPSLib.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
#include "..\CmnHdr.h" /* See Appendix A. */
#include <WindowsX.h>
#include <CommCtrl.h>
#define DIPSLIBAPI __declspec(dllexport)
#include "DIPSLib.h"
#include "Resource.h"
///////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
// This function forces the debugger to be invoked
void ForceDebugBreak() {
__try { DebugBreak(); }
__except(UnhandledExceptionFilter(GetExceptionInformation())) { }
}
#else
#define ForceDebugBreak()
#endif
///////////////////////////////////////////////////////////////////////////////
// Forward references
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
///////////////////////////////////////////////////////////////////////////////
// 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, writable, and shared.
#pragma comment(linker, "/section:Shared,rws")
///////////////////////////////////////////////////////////////////////////////
// Nonshared variables
HINSTANCE g_hinstDll = NULL;
///////////////////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
// DLL is attaching to the address space of the current process.
g_hinstDll = hinstDll;
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) {
// 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 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.
chASSERT(g_hhook != NULL);
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_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\\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);
}
///////////////////////////////////////////////////////////////////////////////
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);
}
}
///////////////////////////////////////////////////////////////////////////////
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);
}
//////////////////////////////// End of File //////////////////////////////////