APISpy32.cpp
上传用户:tzh4061
上传日期:2007-01-08
资源大小:309k
文件大小:27k
源码类别:

钩子与API截获

开发平台:

Visual C++

  1. // ----------------------------------- //
  2. //            APISpy32 v2.0            //
  3. //     Copyright 1999 Yariv Kaplan     //
  4. //          WWW.INTERNALS.COM          //
  5. // ----------------------------------- //
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #include <commctrl.h>
  9. #include "resource.h"
  10. #include "..dlllogapi.h"
  11. #include "htmlhelp.h"
  12. #include "apispy9x.h"
  13. #include "apispynt.h"
  14. #include "general.h"
  15. #include "errors.h"
  16. #include "apispy32.h"
  17. // Event handles
  18. HANDLE hOverflowEvent = NULL;
  19. HANDLE hLogEvent = NULL;
  20. HANDLE hInjectThreadExitEvent = NULL;
  21. HANDLE hLogThreadExitEvent = NULL;
  22. // Thread handles
  23. HANDLE hLogThread = NULL;
  24. HANDLE hInjectDLLThread = NULL;
  25. // Mutex handles
  26. HANDLE hListViewMutex = NULL;
  27. HANDLE hLogMutex = NULL;
  28. // Flags
  29. bool IsNT = false;
  30. bool WindowOnTop = false;
  31. bool AutoScroll = true;
  32. bool CaptureEvents = true;
  33. DWORD dwListViewRow = 0;
  34. HANDLE hMailslot = NULL;
  35. HWND hWndMain;
  36. HWND hWndToolbar;
  37. HWND hWndListView;
  38. HINSTANCE hInst;
  39. DWORD dwHelpCookie;
  40. bool DeletingListView = false;
  41. // Exported functions 
  42. GETLOGPARAMETERS_PROC pGetLogParameters;
  43. SETCAPTUREEVENTSFLAG_PROC pSetCaptureEventsFlag;
  44. ADVANCETONEXTLOGENTRY_PROC pAdvanceToNextLogEntry;
  45. // Toolbar buttons
  46. TBBUTTON tbButtons[] = {
  47. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
  48. { 0, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  49. { 2, IDM_CAPTURE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  50. { 4, IDM_AUTOSCROLL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  51. { 5, IDM_CLEAR, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  52. };
  53. TBBUTTON tbButtonsOld[] = {
  54. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
  55. { 0, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  56. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
  57. { 2, IDM_CAPTURE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  58. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
  59. { 4, IDM_AUTOSCROLL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0},
  60. { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0},
  61. { 5, IDM_CLEAR, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}
  62. };  
  63. // Forward declarations
  64. LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  65. bool ShutdownAPISpy32();
  66. void ErrorHandler(PSTR pszErrorMsg, bool FatalFlag)
  67. {
  68.   char szErrorMsg[256];
  69.   if (FatalFlag)
  70.   {
  71.     strcpy(szErrorMsg, pszErrorMsg);
  72.     strcat(szErrorMsg, ERRORMSG);
  73.     MessageBox(hWndMain, szErrorMsg, "APISpy32", MB_OK | MB_ICONERROR);
  74.     ShutdownAPISpy32();
  75.     ExitProcess(0);
  76.   }
  77.   else
  78.     MessageBox(hWndMain, pszErrorMsg, "APISpy32", MB_OK | MB_ICONWARNING);
  79. }
  80. void InitApplication(HINSTANCE hInstance)
  81. {
  82.   WNDCLASS wc;
  83.   ATOM WndClassAtom;
  84.   wc.style = 0;
  85.   wc.lpfnWndProc = (WNDPROC)MainWndProc;
  86.   wc.cbClsExtra = 0;
  87.   wc.cbWndExtra = 0;
  88.   wc.hInstance = hInstance;
  89.   wc.hIcon = LoadIcon(hInstance, "ICON");
  90.   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  91.   wc.hbrBackground = (HBRUSH)(COLOR_INACTIVEBORDER + 1);
  92.   wc.lpszMenuName = "LISTMENU";
  93.   wc.lpszClassName = "APISpy32Class";
  94.   WndClassAtom = RegisterClass(&wc);
  95.   if (WndClassAtom == 0)
  96.     ErrorHandler(ERROR_REGISTERCLASS, true);
  97. }
  98. bool GetWindowsVersion()
  99. {
  100.   OSVERSIONINFO VersionInfo;
  101.   BOOL Result;
  102.   VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  103.   Result = GetVersionEx(&VersionInfo);
  104.   if (Result == FALSE)
  105.     return false;
  106.   if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  107.     IsNT = true;
  108.   return true;
  109. }
  110. void ReadSettings()
  111. {
  112.   HKEY hKey;
  113.   DWORD dwParamSize;
  114.   Settings.dwLeft = CW_USEDEFAULT;
  115.   Settings.dwTop = CW_USEDEFAULT;
  116.   Settings.dwWidth = CW_USEDEFAULT;
  117.   Settings.dwHeight = CW_USEDEFAULT;
  118.   Settings.WindowOnTop = false;
  119.   Settings.Maximized = false;
  120.   Settings.dwLVColumnWidth[0] = COLUMN_WIDTH1;
  121.   Settings.dwLVColumnWidth[1] = COLUMN_WIDTH2;
  122.   Settings.dwLVColumnWidth[2] = COLUMN_WIDTH3;
  123.   Settings.dwLVColumnWidth[3] = COLUMN_WIDTH4;
  124.   RegCreateKey(HKEY_CURRENT_USER, APISPY32_REG_KEY, &hKey);
  125.   dwParamSize = sizeof(Settings);
  126.   RegQueryValueEx(hKey, "Settings", NULL, NULL, (LPBYTE)&Settings, &dwParamSize);
  127.   RegCloseKey(hKey);
  128.   WindowOnTop = Settings.WindowOnTop;  
  129. }
  130. bool WriteSettings(HWND hWnd)
  131. {
  132.   HKEY hKey;
  133.   RECT Rect;
  134.   LONG Result;
  135.   DWORD dwIndex;
  136.   Result = GetWindowRect(hWnd, &Rect);
  137.   if (Result == 0)
  138.     return false;
  139.   if (!IsIconic(hWnd))
  140.   {
  141.     Settings.dwLeft = Rect.left;
  142.     Settings.dwTop = Rect.top;
  143.     Settings.dwWidth = Rect.right - Rect.left;
  144.     Settings.dwHeight = Rect.bottom - Rect.top;
  145.   }
  146.   Settings.WindowOnTop = WindowOnTop;
  147.   Settings.Maximized = IsZoomed(hWnd);
  148.   for (dwIndex = 0; dwIndex < NUMCOLUMNS; dwIndex++)
  149.     Settings.dwLVColumnWidth[dwIndex] = ListView_GetColumnWidth(hWndListView, dwIndex);
  150.   Result = RegOpenKey(HKEY_CURRENT_USER, "Software\Internals\APISpy32", &hKey);
  151.   if (Result != ERROR_SUCCESS)
  152.     return false;
  153.   Result = RegSetValueEx(hKey, "Settings", 0, REG_BINARY, (LPBYTE)&Settings, sizeof(Settings));
  154.   if (Result != ERROR_SUCCESS)
  155.     return false;
  156.   Result = RegCloseKey(hKey);
  157.   if (Result != ERROR_SUCCESS)
  158.     return false;
  159.   return true;
  160. }
  161. HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
  162. {
  163.   ReadSettings();
  164.   hInst = hInstance;
  165.   hWndMain = CreateWindow("APISpy32Class", "APISpy32 - http://www.internals.com", WS_OVERLAPPEDWINDOW, Settings.dwLeft, Settings.dwTop, Settings.dwWidth, Settings.dwHeight, NULL, NULL, hInstance, NULL);
  166.   if (hWndMain == NULL)
  167.     return NULL;
  168.   ShowWindow(hWndMain, nCmdShow);
  169.   UpdateWindow(hWndMain);
  170.   if (Settings.Maximized)
  171.     ShowWindow(hWndMain, SW_SHOWMAXIMIZED);
  172.   if (WindowOnTop)
  173.   {
  174.     SetWindowPos(hWndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  175.     CheckMenuItem(GetMenu(hWndMain), IDM_ONTOP, MF_BYCOMMAND | (WindowOnTop ? MF_CHECKED:MF_UNCHECKED));
  176.   }
  177.   return hWndMain;
  178. }
  179. HWND CreateListView(HWND hWndParent)
  180. {
  181.   RECT Rect;
  182.   BOOL Result;
  183.   LV_COLUMN LVColumn;
  184.   DWORD dwIndex;
  185.   struct tagListViewColumn
  186.   {
  187.     PSTR pszText;
  188.     DWORD dwWidth;
  189.   }ListViewColumn[] =
  190.   
  191.   {
  192.     {"Process",      COLUMN_WIDTH1},
  193.     {"API",          COLUMN_WIDTH2},
  194.     {"Return Value", COLUMN_WIDTH3},
  195.     {"Origin",       COLUMN_WIDTH4}
  196.   };
  197.   
  198.   InitCommonControls();
  199.   for (dwIndex = 0; dwIndex < NUMCOLUMNS; dwIndex++)
  200.     ListViewColumn[dwIndex].dwWidth = Settings.dwLVColumnWidth[dwIndex];
  201.   Result = GetClientRect(hWndParent, &Rect);
  202.   if (Result == FALSE)
  203.     return NULL;
  204.   hWndListView = CreateWindowEx(0L, WC_LISTVIEW, "", WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL, 0, TOOLBARHEIGHT, Rect.right - Rect.left, Rect.bottom - Rect.top - TOOLBARHEIGHT, hWndParent, (HMENU)ID_LIST, hInst, NULL);
  205.   if (hWndListView == NULL)
  206.     return NULL;
  207.   LVColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  208.   LVColumn.fmt = LVCFMT_LEFT;
  209.   for (dwIndex = 0; dwIndex < sizeof(ListViewColumn) / sizeof(ListViewColumn[0]); dwIndex++)
  210.   {
  211.     LVColumn.iSubItem = dwIndex;
  212.     LVColumn.cx = ListViewColumn[dwIndex].dwWidth;
  213.     LVColumn.pszText = ListViewColumn[dwIndex].pszText;
  214.     
  215.     if (ListView_InsertColumn(hWndListView, dwIndex, &LVColumn) == -1)
  216.       return NULL;
  217.   }
  218.   SendMessage(hWndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  219.   return hWndListView;
  220. }
  221. DWORD GetDLLVersion(PSTR pszDLLName)
  222. {
  223.   HRESULT hResult;
  224.   DWORD dwVersion;
  225.   HINSTANCE hInstDll;
  226.   DLLVERSIONINFO DllVersionInfo;
  227.   DLLGETVERSIONPROC pDllGetVersion;
  228.   hInstDll = LoadLibrary(pszDLLName);
  229.   if (hInstDll == NULL)
  230.     return 0;
  231.   pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hInstDll, "DllGetVersion");
  232.   if (pDllGetVersion)
  233.   {
  234.     ZeroMemory(&DllVersionInfo, sizeof(DllVersionInfo));
  235.     DllVersionInfo.cbSize = sizeof(DllVersionInfo);
  236.     hResult = (*pDllGetVersion)(&DllVersionInfo);
  237.     if (SUCCEEDED(hResult))
  238.       dwVersion = PACKVERSION(DllVersionInfo.dwMajorVersion, DllVersionInfo.dwMinorVersion);
  239.   }
  240.   FreeLibrary(hInstDll);
  241.   return dwVersion;
  242. }
  243. DWORD SplitItems(PSTR pszItems, char *pItems[])
  244. {
  245.   DWORD dwItemCount = 0;
  246.   pszItems = strtok(pszItems, ";");
  247.   while (pszItems)
  248.   {
  249.     pItems[dwItemCount] = pszItems;
  250.     dwItemCount++;
  251.     pszItems = strtok(NULL, ";");
  252.   }
  253.   return dwItemCount;
  254. }
  255. void ListView_Append(PSTR pszItems)
  256. {
  257.   char *pItems[NUMCOLUMNS];
  258.   DWORD dwItemCount;
  259.   LVITEM LVItem;
  260.   DWORD dwIndex;
  261.   dwItemCount = SplitItems(pszItems, pItems);
  262.   LVItem.mask = LVIF_TEXT;
  263.   LVItem.iItem = dwListViewRow;
  264.   LVItem.iSubItem = 0;
  265.   LVItem.pszText = pItems[0];
  266.   LVItem.cchTextMax = strlen(pItems[0] + 1);
  267.   ListView_InsertItem(hWndListView, &LVItem);
  268.   if (AutoScroll)
  269.     ListView_EnsureVisible(hWndListView, ListView_GetItemCount(hWndListView) - 1, FALSE);
  270.   if (dwItemCount > 1)
  271.     for (dwIndex = 0; dwIndex < dwItemCount - 1; dwIndex++)
  272.       ListView_SetItemText(hWndListView, dwListViewRow, dwIndex + 1, pItems[dwIndex + 1]);
  273.   dwListViewRow++;
  274. }
  275. LRESULT CALLBACK AboutBoxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  276. {
  277.   switch (uMsg)
  278.   {
  279.     case WM_INITDIALOG:
  280.       return TRUE;
  281.     break;
  282.     case WM_COMMAND:
  283.       if (LOWORD(wParam) == IDOK)
  284.       {
  285.         EndDialog(hWnd, TRUE);
  286.         return TRUE;
  287.       }
  288.     break;
  289.     case WM_CLOSE:
  290.       EndDialog(hWnd, TRUE);
  291.       return TRUE;
  292.     break;
  293.   }
  294.   return FALSE;
  295. }
  296. bool OutputLogBuffer()
  297. {
  298.   bool Result;
  299.   char szItems[1024];
  300.   DWORD dwIndex;
  301.   DWORD dwNumLogEntries;
  302.   DWORD dwReadLogIndex;
  303.   tagLogEntry *pLogEntry;
  304.   char szReturnValue[20];
  305.   char szOriginAddress[20];
  306.   Result = pGetLogParameters(&dwNumLogEntries, &dwReadLogIndex, &pLogEntry);
  307.   if (Result == false)
  308.     return false;
  309.   if (dwNumLogEntries)
  310.   {
  311.     WaitForSingleObject(hListViewMutex, INFINITE);
  312.     SendMessage(hWndListView, WM_SETREDRAW, FALSE, 0);
  313.   }
  314.   
  315.   for (dwIndex = 0; dwIndex < dwNumLogEntries; dwIndex++)
  316.   {
  317.     Result = GetProcessName9x(pLogEntry[dwReadLogIndex].dwProcessId, szItems);
  318.     if (Result == false)
  319.       strcpy(szItems, "?");
  320.     strcat(szItems, ";");
  321.     strcat(szItems, pLogEntry[dwReadLogIndex].szAPIName);
  322.     wsprintf(szReturnValue, "%#.8x", pLogEntry[dwReadLogIndex].dwReturnValue);
  323.     wsprintf(szOriginAddress, "%#.8x", pLogEntry[dwReadLogIndex].pvOriginAddress);
  324.     strcat(szItems, ";");
  325.     strcat(szItems, szReturnValue);
  326.     strcat(szItems, ";");
  327.     strcat(szItems, szOriginAddress);
  328.           
  329.     ListView_Append(szItems);
  330.     pAdvanceToNextLogEntry();
  331.   }
  332.   if (dwNumLogEntries)
  333.   {
  334.     SendMessage(hWndListView, WM_SETREDRAW, TRUE, 0);
  335.     InvalidateRect(hWndListView, NULL, FALSE);
  336.     ReleaseMutex(hListViewMutex);
  337.   }
  338.   
  339.   return true;
  340. }
  341. DWORD WINAPI LogThread9x(PVOID pvParameter)
  342. {
  343.   DWORD Result;
  344.   HANDLE hEventArray[2];
  345.   hEventArray[0] = hOverflowEvent;
  346.   hEventArray[1] = hLogThreadExitEvent;
  347.   while (1)
  348.   {
  349.     Result = WaitForMultipleObjects(2, &hEventArray[0], FALSE, 100);
  350.     switch (Result)
  351.     {
  352.       case WAIT_OBJECT_0:
  353.         // Buffer overflow
  354.         OutputLogBuffer();
  355.         ResetEvent(hOverflowEvent);
  356.         SetEvent(hLogEvent);
  357.       case WAIT_OBJECT_0 + 1:
  358.         // Exit event
  359.         ResetEvent(hLogThreadExitEvent);
  360.         return TRUE;
  361.       break;
  362.       case WAIT_TIMEOUT:
  363.         OutputLogBuffer();
  364.       break;
  365.       case WAIT_FAILED:
  366.         return FALSE;
  367.       break;
  368.     }
  369.   }
  370.   return TRUE;
  371. }
  372. DWORD WINAPI LogThreadNT(PVOID pvParameter)
  373. {
  374.   DWORD Result;
  375.   DWORD dwIndex;
  376.   DWORD dwBytesRead;
  377.   char szItems[1024];
  378.   char szReturnValue[20];
  379.   char szOriginAddress[20];
  380.   tagLogEntry LogEntry;
  381.   DWORD dwMessageSize;
  382.   DWORD dwMessageCount;
  383.   while (1)
  384.   {
  385.     Result = WaitForSingleObject(hLogThreadExitEvent, 100);
  386.     switch (Result)
  387.     {
  388.       case WAIT_OBJECT_0:
  389.         // Exit event
  390.         ResetEvent(hLogThreadExitEvent);
  391.       
  392.         return TRUE;
  393.       break;
  394.       case WAIT_TIMEOUT:
  395.         Result = GetMailslotInfo(hMailslot, 0, &dwMessageSize, &dwMessageCount, NULL);
  396.         if (Result && dwMessageCount)
  397.         {
  398.           WaitForSingleObject(hListViewMutex, INFINITE);
  399.           for (dwIndex = 0; dwIndex < dwMessageCount; dwIndex++)
  400.           {
  401.             Result = ReadFile(hMailslot, &LogEntry, sizeof(tagLogEntry), &dwBytesRead, NULL);
  402.             if (Result)
  403.             {
  404.               Result = GetProcessNameNT(LogEntry.dwProcessId, szItems);
  405.   
  406.               if (Result == false)
  407.                 strcpy(szItems, "?");
  408.               strcat(szItems, ";");
  409.               strcat(szItems, LogEntry.szAPIName);
  410.               wsprintf(szReturnValue, "%#.8x", LogEntry.dwReturnValue);
  411.               wsprintf(szOriginAddress, "%#.8x", LogEntry.pvOriginAddress);
  412.               strcat(szItems, ";");
  413.               strcat(szItems, szReturnValue);
  414.               strcat(szItems, ";");
  415.               strcat(szItems, szOriginAddress);
  416.           
  417.               ListView_Append(szItems);
  418.             }
  419.           }
  420.           ReleaseMutex(hListViewMutex);
  421.         }
  422.       break;
  423.       case WAIT_FAILED:
  424.         return FALSE;
  425.       break;
  426.     }
  427.   }
  428.   return TRUE;
  429. }
  430. DWORD WINAPI InjectDLLThread(PVOID pvParameter)
  431. {
  432.   DWORD Result;
  433.   while (1)
  434.   {
  435.     Result = WaitForSingleObject(hInjectThreadExitEvent, DLL_INJECTION_TIMEOUT);
  436.     switch (Result)
  437.     {
  438.       case WAIT_OBJECT_0:
  439.         ResetEvent(hInjectThreadExitEvent);
  440.         return TRUE;
  441.       break;
  442.       case WAIT_TIMEOUT:
  443.         InjectDLL(LOAD_DLL);
  444.       break;
  445.       case WAIT_FAILED:
  446.         return FALSE;
  447.       break;
  448.     }
  449.   }
  450.   return TRUE;
  451. }
  452. DWORD WINAPI ClearListViewThread(PVOID pvParameter)
  453. {
  454.   DWORD dwIndex;
  455.   WaitForSingleObject(hListViewMutex, INFINITE);
  456.   pSetCaptureEventsFlag(false);
  457.   if (IsNT == false)
  458.   {
  459.     SendMessage(hWndListView, WM_SETREDRAW, FALSE, 0);
  460.     DeletingListView = true;
  461.     for (dwIndex = 0; dwIndex < dwListViewRow; dwIndex++)
  462.       ListView_DeleteItem(hWndListView, 0);
  463.     DeletingListView = false;
  464.     SendMessage(hWndListView, WM_SETREDRAW, TRUE, 0);
  465.     InvalidateRect(hWndListView, NULL, FALSE);
  466.   }
  467.   else
  468.     ListView_DeleteAllItems(hWndListView);
  469.   dwListViewRow = 0;
  470.   pSetCaptureEventsFlag(CaptureEvents);
  471.   ReleaseMutex(hListViewMutex);
  472.   return TRUE;
  473. }
  474. void InitAPISpy32()
  475. {
  476.   SETAPISPY32PROCESSID_PROC pSetAPISpy32ProcessId;
  477.   HINSTANCE hInstDLL;
  478.   DWORD dwLogThreadId;
  479.   DWORD dwInjectDLLThreadId;
  480.   bool Result;
  481.   if (IsNT)
  482.   {
  483.     Result = ObtainSeDebugPrivilege();
  484.     if (Result == false)
  485.       ErrorHandler(WARNING_DEBUGPRIVILEGE, false);
  486.     hMailslot = CreateMailslot("\\.\mailslot\APISpy32_Mailslot", 0, MAILSLOT_WAIT_FOREVER, 0);
  487.     if (hMailslot == INVALID_HANDLE_VALUE)
  488.       ErrorHandler(ERROR_MAILSLOT, true);
  489.     hInstDLL = LoadLibrary(APISPY32DLL_NT);
  490.     if (hInstDLL == NULL)
  491.       ErrorHandler(ERROR_APISPY32DLL_NT, true);
  492.   }
  493.   else
  494.   {
  495.     hInstDLL = LoadLibrary(APISPY32DLL_9X);
  496.     if (hInstDLL == NULL)
  497.       ErrorHandler(ERROR_APISPY32DLL_9X, true);
  498.   }
  499.   if (IsNT)
  500.   {
  501.     Result = InitPSAPI();
  502.     if (Result == false)
  503.       ErrorHandler(ERROR_PSAPI, true);
  504.   }
  505.   else
  506.   {
  507.     Result = InitToolhelp32();
  508.     if (Result == false)
  509.       ErrorHandler(ERROR_TOOLHELP32, true);
  510.   }
  511.   hLogMutex = CreateMutex(NULL, FALSE, "APISpy32_LogMutex");
  512.   if (hLogMutex == NULL)
  513.     ErrorHandler(ERROR_LOGMUTEX, true);
  514.   hOverflowEvent = CreateEvent(NULL, TRUE, FALSE, "APISpy32_OverflowEvent");
  515.   if (hOverflowEvent == NULL)
  516.     ErrorHandler(ERROR_OVERFLOWEVENT, true);
  517.   hLogEvent = CreateEvent(NULL, TRUE, FALSE, "APISpy32_LogEvent");
  518.   if (hLogEvent == NULL)
  519.     ErrorHandler(ERROR_LOGEVENT, true);
  520.   hLogThreadExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  521.   if (hLogThreadExitEvent == NULL)
  522.     ErrorHandler(ERROR_LOGTHREADEXITEVENT, true);
  523.   hInjectThreadExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  524.   if (hInjectThreadExitEvent == NULL)
  525.     ErrorHandler(ERROR_INJECTTHREADEXITEVENT, true);
  526.   hListViewMutex = CreateMutex(NULL, FALSE, NULL);
  527.   if (hListViewMutex == NULL)
  528.     ErrorHandler(ERROR_LISTVIEWMUTEX, true);
  529.   if (!IsNT)
  530.   {
  531.     pGetLogParameters = (GETLOGPARAMETERS_PROC)GetProcAddress(hInstDLL, "GetLogParameters");
  532.     if (pGetLogParameters == NULL)
  533.       ErrorHandler(ERROR_GETLOGPARAMETERS, true);
  534.     pAdvanceToNextLogEntry = (ADVANCETONEXTLOGENTRY_PROC)GetProcAddress(hInstDLL, "AdvanceToNextLogEntry");
  535.     if (pAdvanceToNextLogEntry == NULL)
  536.       ErrorHandler(ERROR_ADVANCETONEXTLOGENTRY, true);
  537.   }
  538.   pSetCaptureEventsFlag = (SETCAPTUREEVENTSFLAG_PROC)GetProcAddress(hInstDLL, "SetCaptureEventsFlag");
  539.   if (pSetCaptureEventsFlag == NULL)
  540.     ErrorHandler(ERROR_SETCAPTUREEVENTSFLAG, true);
  541.   pSetAPISpy32ProcessId = (SETAPISPY32PROCESSID_PROC)GetProcAddress(hInstDLL, "SetAPISpy32ProcessId");
  542.   if (pSetAPISpy32ProcessId == NULL)
  543.     ErrorHandler(ERROR_SETAPISPY32PROCESSID, true);
  544.   pSetAPISpy32ProcessId(GetCurrentProcessId());
  545.   if (IsNT)
  546.   {
  547.     hInjectDLLThread = CreateThread(NULL, 0, InjectDLLThread, 0, 0, &dwInjectDLLThreadId);
  548.     if (hInjectDLLThread == NULL)
  549.       ErrorHandler(ERROR_INJECTDLLTHREAD, true);
  550.     hLogThread = CreateThread(NULL, 0, LogThreadNT, 0, 0, &dwLogThreadId);
  551.   }
  552.   else
  553.     hLogThread = CreateThread(NULL, 0, LogThread9x, 0, 0, &dwLogThreadId);
  554.   if (hLogThread == NULL)
  555.     ErrorHandler(ERROR_LOGTHREAD, true);
  556.   // Start capturing events
  557.   pSetCaptureEventsFlag(true);
  558. }
  559. bool ShutdownAPISpy32()
  560. {
  561.   if (pSetCaptureEventsFlag)
  562.     pSetCaptureEventsFlag(false);
  563.   if (dwHelpCookie)
  564.   {
  565.     HtmlHelp(NULL, NULL, HH_CLOSE_ALL, 0);
  566.     HtmlHelp(NULL, NULL, HH_UNINITIALIZE, dwHelpCookie);
  567.   }
  568.   if (IsNT)
  569.   {
  570.     // Wait until the injection thread resumes
  571.     SetEvent(hInjectThreadExitEvent);
  572.     WaitForSingleObject(hInjectDLLThread, THREAD_EXIT_TIMEOUT);
  573.   }
  574.   // Wait until the logging thread resumes
  575.   SetEvent(hLogThreadExitEvent);
  576.   WaitForSingleObject(hLogThread, THREAD_EXIT_TIMEOUT);
  577.   // Remove the interception DLL from all address spaces
  578.   if (IsNT)
  579.     InjectDLL(FREE_DLL);
  580.   // Close handles of event objects
  581.   if (hOverflowEvent)
  582.     CloseHandle(hOverflowEvent);
  583.   if (hLogEvent)
  584.     CloseHandle(hLogEvent);
  585.   if (hInjectThreadExitEvent)
  586.     CloseHandle(hInjectThreadExitEvent);
  587.   if (hLogThreadExitEvent)
  588.     CloseHandle(hLogThreadExitEvent);
  589.   // Close handles of mutex objects
  590.   if (hListViewMutex)
  591.     CloseHandle(hListViewMutex);
  592.   if (hLogMutex)
  593.     CloseHandle(hLogMutex);
  594.   
  595.   // Close handles of threads
  596.   if (hLogThread)
  597.     CloseHandle(hLogThread);
  598.   if (hInjectDLLThread)
  599.     CloseHandle(hInjectDLLThread);
  600.   // Close handle of mailslot
  601.   if (IsNT && hMailslot)
  602.     CloseHandle(hMailslot);
  603.   return true;
  604. }
  605. DWORD WINAPI SaveLogFileThread(PVOID SaveAs)
  606. {
  607.   OPENFILENAME OpenFileName;
  608.   BOOL Result;
  609.   DWORD dwRow;
  610.   DWORD dwColumn;
  611.   FILE *hLogFile;
  612.   char szItemText[256] = "";
  613.   char szListViewText[1024];
  614.   static bool LogFileChosen = false;
  615.   static char szLogFileName[MAX_PATH];
  616.   if (SaveAs || !LogFileChosen)
  617.   {
  618.     OpenFileName.lStructSize       =  sizeof(OPENFILENAME);
  619.     OpenFileName.hwndOwner         =  hWndMain;
  620.     OpenFileName.hInstance         =  (HINSTANCE)hInst;
  621.     OpenFileName.lpstrFilter       =  "Log Files (*.log)*.logAll Files (*.*)*.*";
  622.     OpenFileName.lpstrCustomFilter =  (LPTSTR)NULL;
  623.     OpenFileName.nMaxCustFilter    =  0L;
  624.     OpenFileName.nFilterIndex      =  1L;
  625.     OpenFileName.lpstrFile         =  szLogFileName;
  626.     OpenFileName.nMaxFile          =  256;
  627.     OpenFileName.lpstrFileTitle    =  NULL;
  628.     OpenFileName.nMaxFileTitle     =  0;
  629.     OpenFileName.lpstrInitialDir   =  NULL;
  630.     OpenFileName.lpstrTitle        =  "Save File Info...";
  631.     OpenFileName.nFileOffset       =  0;
  632.     OpenFileName.nFileExtension    =  0;
  633.     OpenFileName.lpstrDefExt       =  "*.log";
  634.     OpenFileName.lpfnHook          =  NULL;
  635.     OpenFileName.Flags             =  OFN_LONGNAMES | OFN_HIDEREADONLY;
  636.     Result = GetSaveFileName(&OpenFileName);
  637.     if (Result == FALSE)
  638.       return FALSE;
  639.   }
  640.   hLogFile = fopen(szLogFileName, "w");
  641.   if (hLogFile == NULL)
  642.   {
  643.     ErrorHandler(WARNING_OPENLOGFILE, false);
  644.     return FALSE;
  645.   }
  646.   WaitForSingleObject(hListViewMutex, INFINITE);
  647.   for (dwRow = 0; dwRow < dwListViewRow; dwRow++)
  648.   {
  649.     strcpy(szListViewText, "");
  650.     for (dwColumn = 0; dwColumn < NUMCOLUMNS; dwColumn++)
  651.     {
  652.       ListView_GetItemText(hWndListView, dwRow, dwColumn, szItemText, sizeof(szItemText)); 
  653.       strcat(szListViewText, szItemText);
  654.       strcat(szListViewText, "t");
  655.     }
  656.     fprintf(hLogFile, "%sn", szListViewText);
  657.   }
  658.   fclose(hLogFile);
  659.   ReleaseMutex(hListViewMutex);
  660.   LogFileChosen = true;
  661.   return TRUE;
  662. }
  663. LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  664. {
  665.   LPTOOLTIPTEXT pToolTipText;
  666.   char szToolTipText[128];
  667.   PAINTSTRUCT PaintStruct;
  668.   DWORD dwClearListViewThreadId;
  669.   HANDLE hClearListViewThread;
  670.   DWORD dwSaveLogFileThreadId;
  671.   HANDLE hSaveLogFileThread;
  672.   DWORD DllVersion;
  673.   DWORD Result;
  674.   HDC hDC;
  675.   switch (uMsg)
  676.   {
  677.     case WM_CREATE:
  678.       DllVersion = GetDLLVersion("comctl32.dll");
  679.       if (DllVersion >= PACKVERSION(4, 71))
  680.         hWndToolbar = CreateToolbarEx(hWnd, TOOLBAR_FLAT | WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, ID_TOOLBAR, 10, hInst, IDB_TOOLBAR, (LPCTBBUTTON)&tbButtons, NUM_TOOLBAR_BUTTONS, 16, 16, 16, 15, sizeof(TBBUTTON));
  681.       else
  682.         hWndToolbar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, ID_TOOLBAR, 10, hInst, IDB_TOOLBAR, (LPCTBBUTTON)&tbButtonsOld, NUM_OLD_TOOLBAR_BUTTONS, 16, 16, 16, 15, sizeof(TBBUTTON));
  683.       
  684.       if (hWndToolbar == NULL)
  685.         ErrorHandler(WARNING_TOOLBAR, false);
  686.       hWndListView = CreateListView(hWnd);
  687.       if (hWndListView == NULL)
  688.         ErrorHandler(ERROR_LISTVIEW, true);
  689.       HtmlHelp(NULL, NULL, HH_INITIALIZE, (DWORD)&dwHelpCookie);
  690.  
  691.       // Initialize the API interception engine
  692.       InitAPISpy32();
  693.     break;
  694.     case WM_NOTIFY:
  695.       if (((LPNMHDR)lParam)->code == TTN_NEEDTEXT)
  696.       {
  697.         pToolTipText = (LPTOOLTIPTEXT)lParam;
  698.         LoadString(hInst, pToolTipText->hdr.idFrom, szToolTipText, sizeof(szToolTipText));
  699.         pToolTipText->lpszText = szToolTipText;
  700.       }
  701.       
  702.     break;
  703.     case WM_SIZE:
  704.       MoveWindow(hWndToolbar, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  705.       MoveWindow(hWndListView, 0, TOOLBARHEIGHT, LOWORD(lParam), HIWORD(lParam) - TOOLBARHEIGHT, TRUE);
  706.     break;
  707.     case WM_CLOSE:
  708.       ShutdownAPISpy32();
  709.       WriteSettings(hWnd);
  710.       return DefWindowProc(hWnd, uMsg, wParam, lParam);
  711.     break;
  712.     case WM_SETFOCUS:
  713.       SetFocus(hWndListView);
  714.     break;
  715.     case WM_PAINT:
  716.       if (IsNT == false && DeletingListView)
  717.       {
  718.         hDC = BeginPaint(hWnd, &PaintStruct);
  719.         EndPaint(hWnd, &PaintStruct);
  720.         return TRUE;
  721.       }
  722.       return DefWindowProc(hWnd, uMsg, wParam, lParam);
  723.     
  724.     break;
  725.     case WM_DESTROY:
  726.       PostQuitMessage(0);
  727.     break;
  728.     case WM_COMMAND:
  729.       switch (LOWORD(wParam))
  730.       {
  731.         case IDM_CLEAR:
  732.           hClearListViewThread = CreateThread(NULL, 0, ClearListViewThread, NULL, 0, &dwClearListViewThreadId);
  733.           
  734.           if (hClearListViewThread)
  735.             CloseHandle(hClearListViewThread);
  736.         break;
  737.         case IDM_HELP:
  738.           if (dwHelpCookie)
  739.             HtmlHelp(hWnd, "APISpy32.chm", HH_DISPLAY_TOPIC, NULL);
  740.           else
  741.           {
  742.             Result = (DWORD)ShellExecute(hWnd, "open", "APISpy32.htm", NULL, NULL, SW_SHOWNORMAL);
  743.             if (Result <= 32)
  744.               ErrorHandler(WARNING_SHELLEXECUTE, false);
  745.           }
  746.         break;
  747.         case IDM_AUTOSCROLL:
  748.           AutoScroll = !AutoScroll;
  749.           CheckMenuItem(GetMenu(hWnd), IDM_AUTOSCROLL, MF_BYCOMMAND | (AutoScroll ? MF_CHECKED:MF_UNCHECKED));
  750.           SendMessage(hWndToolbar, TB_CHANGEBITMAP, IDM_AUTOSCROLL, (AutoScroll ? 4:3));
  751.           InvalidateRect(hWndToolbar, NULL, TRUE);
  752.           
  753.         break;
  754.         case IDM_ONTOP:
  755.           WindowOnTop = !WindowOnTop;
  756.           if (WindowOnTop)
  757.             SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  758.           else
  759.             SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  760.           CheckMenuItem(GetMenu(hWnd), IDM_ONTOP, MF_BYCOMMAND | (WindowOnTop ? MF_CHECKED:MF_UNCHECKED));
  761.         break;
  762.         case IDM_CAPTURE:
  763.           CaptureEvents = !CaptureEvents;
  764.           CheckMenuItem(GetMenu(hWnd), IDM_CAPTURE, MF_BYCOMMAND | (CaptureEvents ? MF_CHECKED:MF_UNCHECKED));
  765.           SendMessage(hWndToolbar, TB_CHANGEBITMAP, IDM_CAPTURE, (CaptureEvents ? 2:1));
  766.           InvalidateRect(hWndToolbar, NULL, TRUE);
  767.           // Notify the DLL about the change
  768.           pSetCaptureEventsFlag(CaptureEvents);
  769.         break;
  770.         case IDM_SAVE:
  771.           hSaveLogFileThread = CreateThread(NULL, 0, SaveLogFileThread, FALSE, 0, &dwSaveLogFileThreadId);
  772.           if (hSaveLogFileThread)
  773.             CloseHandle(hSaveLogFileThread);
  774.           
  775.         break;
  776.         case IDM_SAVEAS:
  777.           hSaveLogFileThread = CreateThread(NULL, 0, SaveLogFileThread, (PVOID)TRUE, 0, &dwSaveLogFileThreadId);
  778.           if (hSaveLogFileThread)
  779.             CloseHandle(hSaveLogFileThread);
  780.         break;
  781.         case IDM_ABOUT:
  782.           DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)AboutBoxWndProc);
  783.         break;
  784.         case IDM_EXIT:
  785.           SendMessage(hWnd, WM_CLOSE, 0, 0);
  786.         break;
  787.         default:
  788.           return DefWindowProc(hWnd, uMsg, wParam, lParam);
  789.         break;
  790.       }
  791.     break;
  792.     default:
  793.       return DefWindowProc(hWnd, uMsg, wParam, lParam);
  794.   }
  795.   return FALSE;
  796. }
  797. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  798. {
  799.   bool Result;
  800.   HWND hWnd;
  801.   HWND hWndPrevInst;
  802.   HACCEL hAccel;
  803.   MSG msg;
  804.   // Is this a second instance ?
  805.   hWndPrevInst = FindWindow("APISpy32Class", "APISpy32 - http://www.internals.com");
  806.   // If so, activate the previous one and terminate
  807.   if (hWndPrevInst)
  808.   {
  809.     OpenIcon(hWndPrevInst);
  810.     SetForegroundWindow(hWndPrevInst);
  811.     return 0;
  812.   }
  813.   Result = GetWindowsVersion();
  814.   if (Result == false)
  815.     ErrorHandler(ERROR_GETWINDOWSVERSION, true);
  816.   InitApplication(hInstance);
  817.   hWnd = InitInstance(hInstance, nCmdShow); 
  818.   if (hWnd == NULL)
  819.     ErrorHandler(ERROR_INITINSTANCE, true);
  820.   hAccel = LoadAccelerators(hInstance, "ACCELERATORS");
  821.   if (hAccel == NULL)
  822.     ErrorHandler(WARNING_ACCELERATORS, false);
  823.   while (GetMessage(&msg, NULL, 0, 0))
  824.   {
  825.     if (!TranslateAccelerator(hWnd, hAccel, &msg))
  826.     {
  827.       TranslateMessage(&msg);
  828.       DispatchMessage(&msg);
  829.     }
  830.   }
  831.   return msg.wParam;
  832. }