fork download
  1. //------------------------------------------------------------------------
  2. // PtInRect Logger
  3. //
  4. // * User-friendly GUI that logs addresses that call PtInRect and allows
  5. // the user to filter out specific calls.
  6. // * Hopefully thread-safe
  7. // Coded by Franc[e]sco
  8. //------------------------------------------------------------------------
  9. // 04/02/2012 - rev1
  10. // [*] First Revision
  11. //------------------------------------------------------------------------
  12.  
  13. #include "GUI.h"
  14. #include "resource.h"
  15. #include "PtInRectLog.hpp"
  16. #include <CommCtrl.h>
  17. #include <algorithm>
  18. #include <list>
  19. #include <sstream>
  20.  
  21. #pragma region STRUCTS_AND_MACROS
  22. struct CALL_ITEM
  23. {
  24. LPVOID lpvAddress;
  25. int index;
  26. };
  27.  
  28. extern HWND hDialog;
  29. extern BOOL PIRLOGAPI SendDlgItemMessage(UINT uItem, UINT uMessage, WPARAM wParam, LPARAM lParam);
  30. #define PERROR(szMessage) MessageBoxW(hDialog ? hDialog : NULL, szMessage, L"PtInRectLog", 0);
  31. #define PDIE() TerminateProcess(GetCurrentProcess(), 0);
  32. BOOL IS_CHECKED(UINT uCheckBox) { return (SendDlgItemMessage(uCheckBox, BM_GETCHECK, 0, 0) == BST_CHECKED); };
  33.  
  34. DWORD wshextoi(LPWSTR lpsz)
  35. {
  36. DWORD res = 0;
  37. wstringstream ss(lpsz);
  38. ss << hex << lpsz;
  39. ss >> res;
  40. return res;
  41. }
  42. #pragma endregion
  43.  
  44. HWND hDialog = NULL;
  45. HINSTANCE hInstance = NULL;
  46. list<CALL_ITEM *> lvItems;
  47. HANDLE Mutex = NULL;
  48. extern CPtInRectLog *pLogger;
  49.  
  50. LPCWSTR LV_COLUMN_TEXT = L"Return Address";
  51. LPCWSTR APP_VERSION = L"PtInRectLog rev1 (04/02/2012)\nCoded by Franc[e]sco";
  52.  
  53. BOOL PIRLOGAPI SendMessage(UINT uMessage, WPARAM wParam, LPARAM lParam)
  54. {
  55. return SendMessage(hDialog, uMessage, wParam, lParam);
  56. }
  57.  
  58. BOOL PIRLOGAPI SendDlgItemMessage(UINT uItem, UINT uMessage, WPARAM wParam, LPARAM lParam)
  59. {
  60. return SendDlgItemMessage(hDialog, uItem, uMessage, wParam, lParam);
  61. }
  62.  
  63. VOID PIRLOGAPI OnCreate(HWND hDialog)
  64. {
  65. HFONT hFont = NULL;
  66. HICON hIcon = NULL;
  67. LVCOLUMN Column = {0};
  68.  
  69. ::hDialog = hDialog;
  70.  
  71. Column.pszText = const_cast<LPWSTR>(LV_COLUMN_TEXT);
  72. Column.mask = LVCF_TEXT;
  73. Column.fmt = LVCFMT_LEFT;
  74. Column.cx = -1;
  75. Column.cchTextMax = wcslen(LV_COLUMN_TEXT);
  76.  
  77. hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
  78. hFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
  79. OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, L"Consolas");
  80.  
  81. SendMessage(WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIcon));
  82. SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hIcon));
  83. SendDlgItemMessage(IDC_LIST1, WM_SETFONT, reinterpret_cast<WPARAM>(hFont), TRUE);
  84. SendDlgItemMessage(IDC_LIST2, WM_SETFONT, reinterpret_cast<WPARAM>(hFont), TRUE);
  85. SendDlgItemMessage(IDC_CHECK1, BM_SETCHECK, BST_CHECKED, 0);
  86. SendDlgItemMessage(IDC_CHECK2, BM_SETCHECK, BST_CHECKED, 0);
  87. SendDlgItemMessage(IDC_CHECK3, BM_SETCHECK, BST_CHECKED, 0);
  88. SendDlgItemMessage(IDC_LIST1, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  89. SendDlgItemMessage(IDC_LIST1, LVM_INSERTCOLUMN, 0, reinterpret_cast<LPARAM>(&Column));
  90. SendDlgItemMessage(IDC_LIST2, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  91. SendDlgItemMessage(IDC_LIST2, LVM_INSERTCOLUMN, 0, reinterpret_cast<LPARAM>(&Column));
  92.  
  93. CPtInRectLog::Hook();
  94. ShowWindow(hDialog, SW_SHOW);
  95. }
  96.  
  97. VOID PIRLOGAPI OnClose()
  98. {
  99. int mbResult = MessageBox(hDialog, L"Do you also want to terminate the application"
  100. L" this was injected to?", L"PtInRectLog", MB_YESNO | MB_ICONINFORMATION);
  101.  
  102. DestroyGUI();
  103.  
  104. if (mbResult == IDYES)
  105. PDIE();
  106. }
  107.  
  108. VOID PIRLOGAPI About()
  109. {
  110. MessageBox(hDialog, APP_VERSION, L"PtInRectLog", MB_OK | MB_ICONINFORMATION);
  111. }
  112.  
  113. VOID PIRLOGAPI AddToIgnoreList()
  114. {
  115. WCHAR szItemText[MAX_PATH] = {0};
  116. LVITEM lvItem = {0};
  117. LVITEM lvDeselectItem = {0};
  118. lvDeselectItem.stateMask = LVIF_STATE;
  119. lvDeselectItem.state = 0;
  120. INT iSelected;
  121.  
  122. if (SendDlgItemMessage(IDC_LIST2, LVM_GETNEXTITEM, -1, LVNI_SELECTED) < 0)
  123. return;
  124.  
  125. WaitForSingleObject(Mutex, INFINITE);
  126. do
  127. {
  128. iSelected = SendDlgItemMessage(IDC_LIST2, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
  129.  
  130. if (iSelected >= 0)
  131. {
  132. list<CALL_ITEM *>::iterator it;
  133. SendDlgItemMessage(IDC_LIST2, LVM_SETITEMSTATE, iSelected,
  134. reinterpret_cast<LPARAM>(&lvDeselectItem));
  135. SendDlgItemMessage(IDC_LIST2, LVM_DELETEITEM, iSelected, 0);
  136.  
  137. for (it = lvItems.begin(); it != lvItems.end() &&
  138. (*it)->index != iSelected; it++);
  139.  
  140. if (it != lvItems.end())
  141. pLogger->Ignore((*it)->lpvAddress);
  142. else
  143. continue;
  144.  
  145. for each(CALL_ITEM *Call in lvItems)
  146. if (Call->index > iSelected)
  147. Call->index--;
  148.  
  149. wsprintf(szItemText, L"0x%.8X", (*it)->lpvAddress);
  150. lvItem.pszText = szItemText;
  151. lvItem.mask = LVIF_TEXT;
  152. lvItem.iItem = 0x7FFFFFFF;
  153. SendDlgItemMessage(IDC_LIST1, LVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&lvItem));
  154.  
  155. delete *it;
  156. lvItems.erase(it);
  157. }
  158. }
  159. while (iSelected >= 0);
  160. ReleaseMutex(Mutex);
  161. }
  162.  
  163. VOID PIRLOGAPI RemoveFromIgnoreList()
  164. {
  165. INT iSelected;
  166. DWORD dwAddress = 0;
  167. WCHAR szItemText[MAX_PATH] = {0};
  168. LVITEM lvItem = {0};
  169.  
  170. WaitForSingleObject(Mutex, INFINITE);
  171. do
  172. {
  173. iSelected = SendDlgItemMessage(IDC_LIST1, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
  174.  
  175. if (iSelected >= 0)
  176. {
  177. lvItem.pszText = szItemText;
  178. lvItem.cchTextMax = MAX_PATH;
  179. SendDlgItemMessage(IDC_LIST1, LVM_GETITEMTEXT,
  180. iSelected, reinterpret_cast<LPARAM>(&lvItem));
  181. dwAddress = wshextoi(szItemText+2);
  182. SendDlgItemMessage(IDC_LIST1, LVM_DELETEITEM, iSelected, 0);
  183. pLogger->UnIgnore(reinterpret_cast<LPVOID>(dwAddress));
  184. }
  185. }
  186. while (iSelected >= 0);
  187. ReleaseMutex(Mutex);
  188. }
  189.  
  190. VOID PIRLOGAPI ClearLogList()
  191. {
  192. WaitForSingleObject(Mutex, INFINITE);
  193. SendDlgItemMessage(IDC_LIST2, LVM_DELETEALLITEMS, 0, 0);
  194. lvItems.clear();
  195. pLogger->ResetCallCount();
  196. ReleaseMutex(Mutex);
  197. }
  198.  
  199. VOID PIRLOGAPI DispatchCall(LPVOID lpvReturnAddress)
  200. {
  201. WCHAR szItemText[MAX_PATH] = {0};
  202. LVITEM lvItem = {0};
  203. list<CALL_ITEM *>::iterator it;
  204.  
  205. WaitForSingleObject(Mutex, INFINITE);
  206. wsprintf(szItemText, L"0x%.8X (%d)", lpvReturnAddress, pLogger->GetCallCount(lpvReturnAddress));
  207. lvItem.pszText = szItemText;
  208. lvItem.mask = LVIF_TEXT;
  209. lvItem.iItem = 0x7FFFFFFF;
  210.  
  211. for (it = lvItems.begin(); it != lvItems.end() && (*it)->lpvAddress != lpvReturnAddress; it++);
  212.  
  213. if (it != lvItems.end())
  214. SendDlgItemMessage(IDC_LIST2, LVM_SETITEMTEXT, (*it)->index, reinterpret_cast<LPARAM>(&lvItem));
  215. else
  216. {
  217. INT Index;
  218. CALL_ITEM *pCallItem = new CALL_ITEM;
  219. pCallItem->lpvAddress = lpvReturnAddress;
  220.  
  221. Index = SendDlgItemMessage(IDC_LIST2, LVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&lvItem));
  222. pCallItem->index = Index;
  223. lvItems.push_back(pCallItem);
  224. }
  225. ReleaseMutex(Mutex);
  226. Sleep(1);
  227. }
  228.  
  229. BOOL CALLBACK DlgProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
  230. {
  231. switch(Message)
  232. {
  233. #pragma region SYSTEM_MESSAGES
  234. case WM_INITDIALOG:
  235. OnCreate(hWnd);
  236. return TRUE;
  237.  
  238. case WM_CLOSE:
  239. OnClose();
  240. return TRUE;
  241.  
  242. case WM_DESTROY:
  243. PostQuitMessage(0);
  244. return TRUE;
  245. #pragma endregion
  246.  
  247. #pragma region CONTROLS
  248. case WM_COMMAND:
  249. switch(LOWORD(wParam))
  250. {
  251. #pragma region BUTTONS
  252. case IDC_BUTTON1:
  253. AddToIgnoreList();
  254. return TRUE;
  255.  
  256. case IDC_BUTTON2:
  257. RemoveFromIgnoreList();
  258. return TRUE;
  259.  
  260. case IDC_BUTTON3:
  261. ClearLogList();
  262. return TRUE;
  263. #pragma endregion
  264.  
  265. #pragma region MENU
  266. case ID_FILE_EXIT:
  267. SendMessage(WM_CLOSE, 0, 0);
  268. return TRUE;
  269.  
  270. case ID_ABOUT_EXIT:
  271. About();
  272. return TRUE;
  273. #pragma endregion
  274.  
  275. #pragma region CHECKBOXES
  276. case IDC_CHECK1:
  277. if(IS_CHECKED(IDC_CHECK1))
  278. CPtInRectLog::Hook();
  279. else
  280. CPtInRectLog::UnHook();
  281. return TRUE;
  282.  
  283. case IDC_CHECK2:
  284. pLogger->ToggleIgnoring(IS_CHECKED(IDC_CHECK2));
  285. return TRUE;
  286.  
  287. case IDC_CHECK3:
  288. pLogger->ToggleExternCalls(!IS_CHECKED(IDC_CHECK3));
  289. return TRUE;
  290. #pragma endregion
  291. }
  292. break;
  293. #pragma endregion
  294. }
  295.  
  296. return FALSE;
  297. }
  298.  
  299. VOID PIRLOGAPI CreateGUI(HINSTANCE hInstance)
  300. {
  301. Mutex = CreateMutex(NULL, FALSE, NULL);
  302. ::hInstance = hInstance;
  303. hDialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
  304. SendDlgItemMessage(IDC_LIST1, LVM_SETCOLUMNWIDTH, 0, 100);
  305. SendDlgItemMessage(IDC_LIST2, LVM_SETCOLUMNWIDTH, 0, 240);
  306. }
  307.  
  308. VOID PIRLOGAPI DestroyGUI()
  309. {
  310. for each (CALL_ITEM *pItem in lvItems)
  311. delete pItem;
  312.  
  313. lvItems.clear();
  314. CloseHandle(Mutex);
  315. DestroyWindow(hDialog);
  316. }
  317.  
  318. VOID PIRLOGAPI MessageLoop()
  319. {
  320. MSG msg;
  321. INT status;
  322.  
  323. while ((status = GetMessage(&msg, 0, 0, 0)) != 0)
  324. {
  325. if (status == -1)
  326. return;
  327. if (!IsDialogMessage(hDialog, &msg))
  328. {
  329. TranslateMessage(&msg);
  330. DispatchMessage(&msg);
  331. }
  332. }
  333. }
  334.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty