PDEBUG.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:39k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. #include "pwalk.h"
  11. #include <memory.h>
  12. /* module globals */
  13. LPVOID   PMAAddress;
  14. LPVOID   PMABuffer;
  15. DWORD   PMASize;
  16. extern   char   szCurPath[MAX_PATH];
  17. /* local debug functions */
  18. BOOL   WINAPI DebugEventThread (DBGPROCESS *);
  19. BOOL   WINAPI CreateDebugEvents (LPHANDLE);
  20. void   WINAPI AddThreadNode (DBGPROCESS *, DWORD, HANDLE, int, LPTHREAD_START_ROUTINE, HANDLE);
  21. int    WINAPI HandleBreakPoint(DBGPROCESS *, DWORD);
  22. void   WINAPI RemoveThreadNode (DBGPROCESS *, DWORD);
  23. void   WINAPI AddDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *);
  24. void   WINAPI RemoveDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *);
  25. void   WINAPI SuspendDebuggeeProcess (DBGPROCESS *);
  26. void   WINAPI ResumeDebuggeeProcess (DBGPROCESS *);
  27. void   WINAPI NameObjects (HANDLE, LPVOID, LPVMOBJECT, int, char *, char *);
  28. BOOL   WINAPI VMCompare (LPVMOBJECT, LPVMOBJECT);
  29. BOOL   WINAPI InterruptThread_HookProcess (DBGPROCESS *, LPPROCESS_STATE);
  30. void   WINAPI ResetInterruptedThread (DBGPROCESS *, LPPROCESS_STATE);
  31. void   WINAPI RecordException (DBGPROCESS *, DEBUG_EVENT *);
  32. HANDLE WINAPI FindThreadHandle (DBGPROCESS *, DWORD);
  33. /* start debug thread, and return event active handle */
  34. DBGPROCESS* WINAPI StartChildProcess (
  35.     HWND hWnd,
  36.     char *lpszModule,
  37.     LPHANDLE lpDbgEvents)
  38. {
  39.     DWORD   TID;
  40.     HANDLE   hDebugHeap;
  41.     DBGPROCESS   *lpDbgProcess;
  42.     int    i;
  43.     /* create unique debug events using debuggee process ID */
  44.     if (!CreateDebugEvents (lpDbgEvents))
  45. return NULL;
  46.     /* create serialized heap of dynamic size */
  47.     if (!(hDebugHeap = HeapCreate (0, sizeof (DBGPROCESS) + sizeof (DBGTHREAD), 0)))
  48. {
  49. /* close all event handles */
  50. for (i=0; i<nDEBUGEVENTS; i++)
  51.     CloseHandle (lpDbgEvents[i]);
  52. return NULL;
  53. }
  54.     /* allocate and initialize debug heap structure */
  55.     lpDbgProcess = (DBGPROCESS *)HeapAlloc (hDebugHeap, 0, sizeof (DBGPROCESS));
  56.     lpDbgProcess->hDbgHeap = hDebugHeap;
  57.     strcpy (lpDbgProcess->szModule, lpszModule);
  58.     lpDbgProcess->hWnd = hWnd;
  59.     lpDbgProcess->lpThreads = NULL;
  60.     lpDbgProcess->lpSection = NULL;
  61.     lpDbgProcess->lpERs = NULL;
  62.     /* create debug thread */
  63.     if (!(CreateThread ((LPSECURITY_ATTRIBUTES)NULL,
  64. 4096,
  65. (LPTHREAD_START_ROUTINE)DebugEventThread,
  66. (LPVOID)lpDbgProcess,
  67. 0,
  68. &TID)))
  69. return NULL;
  70.     /* wait 15 seconds for debugger to complete initialization, else error */
  71.     if (WAIT_TIMEOUT == WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], 15000))
  72. {
  73. HeapDestroy (lpDbgProcess->hDbgHeap);
  74. /* close all event handles */
  75. for (i=0; i<nDEBUGEVENTS; i++)
  76.     CloseHandle (lpDbgEvents[i]);
  77. return NULL;
  78. }
  79.     /* reset acknowledge event */
  80.     ResetEvent (lpDbgEvents[ACKNOWLEDGE]);
  81.     /* successfull thread and event start */
  82.     return lpDbgProcess;
  83. }
  84. /* function notifies debug thread to terminate, frees handles, and destroys heap */
  85. void   WINAPI CloseChildProcess (
  86.     DBGPROCESS *lpDbgProcess,
  87.     LPHANDLE   lpDbgEvents)
  88. {
  89.     int   i;
  90.     DBGTHREAD  *pNode = lpDbgProcess->lpThreads;
  91.     /* set close event for debug thread and wait for acknowledge */
  92.     SetEvent (lpDbgEvents[CLOSEDEBUGGER]);
  93.     WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], INFINITE);
  94.     /* close all event handles */
  95.     for (i=0; i<nDEBUGEVENTS; i++)
  96. CloseHandle (lpDbgEvents[i]);
  97.     /* close all thread handles in the list */
  98.     while (pNode != NULL)
  99. {
  100. RemoveThreadNode (lpDbgProcess, pNode->dwThreadID);
  101. pNode = lpDbgProcess->lpThreads;
  102. }
  103.     /* destroy the debug heap */
  104.     HeapDestroy (lpDbgProcess->hDbgHeap);
  105. }
  106. /* local function creates debug event objects for thread synchronization */
  107. BOOL WINAPI CreateDebugEvents (
  108.     LPHANDLE lpDbgEvents)
  109. {
  110.     char    szEvent[MAX_PATH];
  111.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACTIVE, szEvent, sizeof (szEvent));
  112.     if (!(lpDbgEvents[DEBUGACTIVE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  113.   TRUE,
  114.   TRUE,
  115.   szEvent)))
  116. return FALSE;
  117.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTCLOSE, szEvent, sizeof (szEvent));
  118.     if (!(lpDbgEvents[CLOSEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  119.    TRUE,
  120.    FALSE,
  121.    szEvent)))
  122. {
  123. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  124. return FALSE;
  125. }
  126.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTOP, szEvent, sizeof (szEvent));
  127.     if (!(lpDbgEvents[SUSPENDDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  128.       TRUE,
  129.       FALSE,
  130.       szEvent)))
  131. {
  132. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  133. CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
  134. return FALSE;
  135. }
  136.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTART, szEvent, sizeof (szEvent));
  137.     if (!(lpDbgEvents[RESUMEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  138.      TRUE,
  139.      FALSE,
  140.      szEvent)))
  141. {
  142. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  143. CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
  144. CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
  145. return FALSE;
  146. }
  147.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTREAD, szEvent, sizeof (szEvent));
  148.     if (!(lpDbgEvents[READMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  149.  TRUE,
  150.  FALSE,
  151.  szEvent)))
  152. {
  153. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  154. CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
  155. CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
  156. CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
  157. return FALSE;
  158. }
  159.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTWRITE, szEvent, sizeof (szEvent));
  160.     if (!(lpDbgEvents[WRITEMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  161.   TRUE,
  162.   FALSE,
  163.   szEvent)))
  164. {
  165. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  166. CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
  167. CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
  168. CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
  169. CloseHandle (lpDbgEvents[READMEMORY]);
  170. return FALSE;
  171. }
  172.     LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACK, szEvent, sizeof (szEvent));
  173.     if (!(lpDbgEvents[ACKNOWLEDGE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
  174.   TRUE,
  175.   FALSE,
  176.   szEvent)))
  177. {
  178. CloseHandle (lpDbgEvents[DEBUGACTIVE]);
  179. CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
  180. CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
  181. CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
  182. CloseHandle (lpDbgEvents[READMEMORY]);
  183. CloseHandle (lpDbgEvents[WRITEMEMORY]);
  184. return FALSE;
  185. }
  186.     /* success */
  187.     return TRUE;
  188. }
  189. /* main daddyo thread that is the debugger residing over a debuggee */
  190. BOOL WINAPI DebugEventThread (
  191.     DBGPROCESS   *lpDbgProcess)
  192. {
  193.     DEBUG_EVENT     de;
  194.     HANDLE    hDbgEvent[nDEBUGEVENTS];
  195.     STARTUPINFO     si;
  196.     PROCESS_INFORMATION    pi;
  197.     HANDLE    hChildProcess;
  198.     BOOL    bHooked, bUnHooked;
  199. //    PROCESS_STATE    ProcessState;
  200.     bHooked = FALSE;
  201.     bUnHooked = FALSE;
  202.     /* initialize process startup information */
  203.     si.cb        = sizeof (si);
  204.     si.lpReserved      = NULL;
  205.     si.lpDesktop       = NULL;
  206.     si.lpTitle        = NULL;
  207.     si.dwX        = 0;
  208.     si.dwY        = 0;
  209.     si.dwXSize        = 0;
  210.     si.dwYSize        = 0;
  211.     si.dwXCountChars   = 0;
  212.     si.dwYCountChars   = 0;
  213.     si.dwFillAttribute = 0;
  214.     si.dwFlags        = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
  215.     si.wShowWindow     = SW_SHOWNORMAL;
  216.     si.cbReserved2     = 0;
  217.     si.lpReserved2     = NULL;
  218.     /* create debug process on module name */
  219.     if (!CreateProcess (lpDbgProcess->szModule,
  220. NULL,
  221. (LPSECURITY_ATTRIBUTES)NULL,
  222. (LPSECURITY_ATTRIBUTES)NULL,
  223. FALSE,
  224. DEBUG_PROCESS,
  225. NULL,
  226. NULL,
  227. (LPSTARTUPINFO)&si,
  228. (LPPROCESS_INFORMATION)&pi))
  229. {
  230. ReportError (IDS_ERRCREATEPROCESS);
  231. return FALSE;
  232. }
  233.     /* open process for all access */
  234.     if ((hChildProcess = OpenProcess (PROCESS_ALL_ACCESS,
  235.       FALSE,
  236.       pi.dwProcessId)) == NULL)
  237. {
  238. ReportError (IDS_ERROPENPROCESS);
  239. TerminateProcess (pi.hProcess, 0);
  240. return FALSE;
  241. }
  242.     /* store process info */
  243.     lpDbgProcess->hProcess = hChildProcess;
  244.     lpDbgProcess->dwPriority = GetPriorityClass (pi.hProcess);
  245.     lpDbgProcess->dwProcessID = pi.dwProcessId;
  246.     lpDbgProcess->bActive = TRUE;
  247.     /* close process and thread handles in pi structure */
  248.     CloseHandle (pi.hThread);
  249.     CloseHandle (pi.hProcess);
  250.     /* open debug events */
  251.     CreateDebugEvents (hDbgEvent);
  252.     /* signale completion of task */
  253.     SetEvent (hDbgEvent[ACKNOWLEDGE]);
  254.     /* start debug event loop */
  255.     while (TRUE)
  256. {
  257. int    nIndex;
  258. /* wait for debugger active */
  259. switch (nIndex = WaitForMultipleObjects (nDEBUGEVENTS, hDbgEvent, FALSE, INFINITE))
  260.     {
  261.     case CLOSEDEBUGGER:
  262. {
  263. int    i;
  264. /* terminate debuggee process */
  265. TerminateProcess (lpDbgProcess->hProcess, 0);
  266. CloseHandle (lpDbgProcess->hProcess);
  267. /* signal completion of task */
  268. SetEvent (hDbgEvent[ACKNOWLEDGE]);
  269. /* close all debug events */
  270. for (i=0; i<nDEBUGEVENTS; i++)
  271.     CloseHandle (hDbgEvent[i]);
  272. /* exit debugger now */
  273. return TRUE;
  274. }
  275. break;
  276.     case SUSPENDDEBUGGER:
  277. SuspendDebuggeeProcess (lpDbgProcess);
  278. ResetEvent (hDbgEvent[DEBUGACTIVE]);
  279. ResetEvent (hDbgEvent[SUSPENDDEBUGGER]);
  280. break;
  281.     case RESUMEDEBUGGER:
  282. ResumeDebuggeeProcess (lpDbgProcess);
  283. SetEvent (hDbgEvent[DEBUGACTIVE]);
  284. ResetEvent (hDbgEvent[RESUMEDEBUGGER]);
  285. break;
  286.     case READMEMORY:
  287. {
  288. MEMORY_BASIC_INFORMATION    mbi;
  289. DWORD     Protect = 0;
  290. /* reset event so we don't do repeat */
  291. ResetEvent (hDbgEvent [READMEMORY]);
  292. /* if not committed memory abort */
  293. if (!VirtualQueryEx (lpDbgProcess->hProcess,
  294.      PMAAddress,
  295.      &mbi,
  296.      sizeof (MEMORY_BASIC_INFORMATION)) ||
  297.     mbi.State != MEM_COMMIT)
  298.     {
  299.     PMASize = 0;
  300.     SetEvent (hDbgEvent [ACKNOWLEDGE]);
  301.     break;
  302.     }
  303. /* if guarded memory, change protection temporarily */
  304. if (!(mbi.Protect & PAGE_READONLY) &&
  305.     !(mbi.Protect & PAGE_READWRITE))
  306.     VirtualProtectEx (lpDbgProcess->hProcess,
  307.       PMAAddress,
  308.       PMASize,
  309.       PAGE_READONLY,
  310.       &Protect);
  311. if (!ReadProcessMemory (lpDbgProcess->hProcess,
  312. PMAAddress,
  313. PMABuffer,
  314. PMASize,
  315. NULL))
  316.     {
  317.     if (mbi.AllocationProtect != PAGE_READONLY &&
  318. mbi.AllocationProtect != PAGE_READWRITE)
  319. NotifyUser (NULL, IDS_ERROR, 0, "BaseProtect NOACCESS", 0);
  320.     else
  321. {
  322. ReportError (IDS_ERRREADPROCESSMEMORY);
  323. PMASize = 0;
  324. }
  325.     }
  326. /* reset protection if changed */
  327. if (Protect)
  328.     VirtualProtectEx (lpDbgProcess->hProcess,
  329.       PMAAddress,
  330.       PMASize,
  331.       Protect,
  332.       &Protect);
  333. /* acknowledge success */
  334. SetEvent (hDbgEvent [ACKNOWLEDGE]);
  335. }
  336. break;
  337.     case WRITEMEMORY:
  338. if (!WriteProcessMemory (lpDbgProcess->hProcess,
  339.  PMAAddress,
  340.  PMABuffer,
  341.  PMASize,
  342.  NULL))
  343.     {
  344.     ReportError (IDS_ERRWRITEPROCESSMEMORY);
  345.     PMASize = 0;
  346.     }
  347. ResetEvent (hDbgEvent [WRITEMEMORY]);
  348. SetEvent (hDbgEvent [ACKNOWLEDGE]);
  349. break;
  350.     case DEBUGACTIVE:
  351. /* if debug active */
  352. if ((WaitForDebugEvent (&de, (DWORD)100)))
  353.     {
  354.     if (de.dwProcessId == lpDbgProcess->dwProcessID)
  355. {
  356. switch (de.dwDebugEventCode)
  357.     {
  358.     case EXIT_PROCESS_DEBUG_EVENT:
  359. SetStatusText (lpDbgProcess->hWnd, IDS_EXITPROCESS, 0);
  360. /* uninitialize probe dll */
  361. ResetProbe ();
  362. /* process is going away so notify main window */
  363. SendNotifyMessage (lpDbgProcess->hWnd,
  364.    WM_COMMAND,
  365.    IDM_PROCESSUNLOAD,
  366.    0);
  367. break;
  368.     case LOAD_DLL_DEBUG_EVENT:
  369. SetStatusText (lpDbgProcess->hWnd, IDS_LOADDLL, 0);
  370. AddDllNode (lpDbgProcess,
  371.     (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll));
  372. break;
  373.     case UNLOAD_DLL_DEBUG_EVENT:
  374. SetStatusText (lpDbgProcess->hWnd, IDS_UNLOADDLL, 0);
  375. RemoveDllNode (lpDbgProcess,
  376.        (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll));
  377. break;
  378.     case CREATE_PROCESS_DEBUG_EVENT:
  379. SetStatusText (lpDbgProcess->hWnd, IDS_CREATEPROCESS, 0);
  380. /* add first thread to linked list of dbg structures */
  381. AddThreadNode (lpDbgProcess,
  382. de.dwThreadId,
  383. de.u.CreateProcessInfo.hThread,
  384. GetThreadPriority (de.u.CreateProcessInfo.hThread),
  385. de.u.CreateProcessInfo.lpStartAddress,
  386. de.u.CreateProcessInfo.hFile);
  387. lpDbgProcess->hFile = de.u.CreateProcessInfo.hFile;
  388. lpDbgProcess->lpImage = de.u.CreateProcessInfo.lpBaseOfImage;
  389. lpDbgProcess->dwDbgInfoOffset = de.u.CreateProcessInfo.dwDebugInfoFileOffset;
  390. lpDbgProcess->nDbgInfoSize = de.u.CreateProcessInfo.nDebugInfoSize;
  391. break;
  392.     case CREATE_THREAD_DEBUG_EVENT:
  393. SetStatusText (lpDbgProcess->hWnd, IDS_CREATETHREAD, 0);
  394. /* add thread to linked list of dbg structures */
  395. AddThreadNode (lpDbgProcess,
  396.  de.dwThreadId,
  397.  de.u.CreateThread.hThread,
  398.  GetThreadPriority (de.u.CreateThread.hThread),
  399.  de.u.CreateThread.lpStartAddress,
  400.  NULL);
  401. break;
  402.     case EXIT_THREAD_DEBUG_EVENT:
  403. SetStatusText (lpDbgProcess->hWnd, IDS_EXITTHREAD, 0);
  404. /* remove thread record */
  405. RemoveThreadNode (lpDbgProcess,
  406.     de.dwThreadId);
  407. break;
  408.     case EXCEPTION_DEBUG_EVENT:
  409. switch (de.u.Exception.ExceptionRecord.ExceptionCode)
  410.     {
  411.     case EXCEPTION_BREAKPOINT:
  412. HandleBreakPoint(lpDbgProcess, de.dwThreadId);
  413. SetStatusText (lpDbgProcess->hWnd,
  414.        IDS_BREAKPOINTEXCEPTION,
  415.        RGB (0, 0xff, 0));
  416. /* post message to get ball rolling in main thread */
  417. PostMessage (lpDbgProcess->hWnd,
  418.  WM_COMMAND,
  419.  IDM_PROCESSREWALK,
  420.  0);
  421. break;
  422.     case EXCEPTION_ACCESS_VIOLATION:
  423. /* record exception information */
  424. SetStatusText (lpDbgProcess->hWnd,
  425.        IDS_ACCESSVIOLATIONEXCEPTION,
  426.        RGB (0xff, 0, 0));
  427. RecordException (lpDbgProcess, &de);
  428. break;
  429.     default:
  430. SetStatusText (lpDbgProcess->hWnd,
  431.        IDS_UNHANDLEDEXCEPTION,
  432.        RGB (0xff, 0, 0));
  433. RecordException (lpDbgProcess, &de);
  434. break;
  435.     }
  436. break;
  437.     case RIP_EVENT:
  438. SetStatusText (lpDbgProcess->hWnd,
  439.        IDS_RIPEVENT,
  440.        RGB (0, 0xff, 0));
  441. break;
  442.     case OUTPUT_DEBUG_STRING_EVENT:
  443. SetStatusText (lpDbgProcess->hWnd,
  444.        IDS_OUTPUTDEBUGSTRING,
  445.        RGB (0, 0xff, 0));
  446. break;
  447.     default:
  448. break;
  449.     }
  450. }
  451.             if(de.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)
  452.         ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
  453.             else
  454.         ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
  455.     }
  456. break;
  457.     }
  458. }
  459.     return TRUE;
  460. }
  461. void WINAPI SuspendDebuggeeProcess (
  462.     DBGPROCESS   *lppr)
  463. {
  464.     DBGTHREAD  *lpth = (DBGTHREAD *)lppr->lpThreads;
  465.     while (lpth)
  466. {
  467. SuspendThread (lpth->hThread);
  468. lpth = (DBGTHREAD *)lpth->Next;
  469. }
  470.     /* inform user via status bar */
  471.     SetStatusText (lppr->hWnd, IDS_PROCESSSUSPENDED, RGB (0xff, 0, 0));
  472.     lppr->bActive = FALSE;
  473. }
  474. void WINAPI ResumeDebuggeeProcess (
  475.     DBGPROCESS   *lppr)
  476. {
  477.     DBGTHREAD  *lpth = (DBGTHREAD *)lppr->lpThreads;
  478.     while (lpth)
  479. {
  480. ResumeThread (lpth->hThread);
  481. lpth = (DBGTHREAD *)lpth->Next;
  482. }
  483.     /* inform user via status bar */
  484.     SetStatusText (lppr->hWnd, IDS_PROCESSRESUMED, RGB (0, 0xff, 0));
  485.     lppr->bActive = TRUE;
  486. }
  487. void WINAPI AddThreadNode (
  488.     DBGPROCESS       *lppr,
  489.     DWORD       dwThreadID,
  490.     HANDLE       hThread,
  491.     int        nPriority,
  492.     LPTHREAD_START_ROUTINE    lpStart,
  493.     HANDLE       hFile)
  494. {
  495.     DBGTHREAD  *lpth;
  496.     DBGTHREAD  *pNode = lppr->lpThreads;
  497.     /* allocate thread node off heap */
  498.     lpth = (DBGTHREAD *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGTHREAD));
  499.     /* initialize thread data */
  500.     lpth->lpStartAddress = lpStart;
  501.     lpth->nPriority = nPriority;
  502.     lpth->dwThreadID = dwThreadID;
  503.     lpth->hThread = hThread;
  504.     lpth->Next = NULL;
  505.     /* retieve section names for executable module if file handle passed */
  506.     if (hFile)
  507. {
  508. RetrieveModuleName (lppr->szModule, hFile);
  509. lppr->lpSection = NULL;
  510. RetrieveSectionNames (lppr->hDbgHeap, hFile, &(lppr->lpSection));
  511. }
  512.     /* set linked list pointers */
  513.     while (pNode && pNode->Next)
  514. pNode = (DBGTHREAD *)pNode->Next;
  515.     if (!pNode)
  516. lppr->lpThreads = lpth;
  517.     else
  518. (DBGTHREAD *)pNode->Next = lpth;
  519. }
  520. void WINAPI RemoveThreadNode (
  521.     DBGPROCESS   *lppr,
  522.     DWORD   dwThreadID)
  523. {
  524.     DBGTHREAD  *pNode = lppr->lpThreads;
  525.     DBGTHREAD  *lpth;
  526.     while (pNode->Next &&
  527.    ((DBGTHREAD *)(pNode->Next))->dwThreadID != dwThreadID)
  528. pNode = (DBGTHREAD *)pNode->Next;
  529.     if (pNode->Next)
  530. {
  531. lpth = (DBGTHREAD *)pNode->Next;
  532. pNode->Next = ((DBGTHREAD *)(pNode->Next))->Next;
  533. CloseHandle (lpth->hThread);
  534. HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth);
  535. }
  536.     else if (pNode->dwThreadID == dwThreadID)
  537. {
  538. lpth = pNode;
  539. lppr->lpThreads = NULL;
  540. CloseHandle (lpth->hThread);
  541. HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth);
  542. }
  543. }
  544. /* find a thread's handle based on thread ID */
  545. HANDLE WINAPI FindThreadHandle (
  546.     DBGPROCESS   *lppr,
  547.     DWORD   dwThreadId)
  548. {
  549.     DBGTHREAD  *pNode = lppr->lpThreads;
  550.     while (pNode != NULL)
  551. if (pNode->dwThreadID == dwThreadId)
  552.     return (pNode->hThread);
  553.     return NULL;
  554. }
  555. void WINAPI AddDllNode (
  556.     DBGPROCESS    *lppr,
  557.     LOAD_DLL_DEBUG_INFO    *lpdbgDll)
  558. {
  559.     DBGDLL    *lpdll;
  560.     DBGDLL    *pNode = lppr->lpDlls;
  561.     /* allocate Dll node off heap */
  562.     if ((lpdll = (DBGDLL *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGDLL))) == NULL)
  563. ReportError (IDS_ERRHEAPALLOC);
  564.     /* initialize Dll structure */
  565.     lpdll->hFile = lpdbgDll->hFile;
  566.     lpdll->lpBaseOfDll = lpdbgDll->lpBaseOfDll;
  567.     lpdll->dwDebugInfoFileOffset = lpdbgDll->dwDebugInfoFileOffset;
  568.     lpdll->nDebugInfoSize = lpdbgDll->nDebugInfoSize;
  569.     lpdll->fUnicode = lpdbgDll->fUnicode;
  570.     lpdll->Next = NULL;
  571.     lpdll->lpSection = NULL;
  572. RetrieveModuleName (lpdll->szImageName, lpdbgDll->hFile);
  573.     /* get section names for DLL */
  574.     RetrieveSectionNames (lppr->hDbgHeap, lpdbgDll->hFile, &(lpdll->lpSection));
  575.     /* set linked list pointers */
  576.     while (pNode && pNode->Next)
  577. pNode = (DBGDLL *)pNode->Next;
  578.     if (!pNode)
  579. lppr->lpDlls = lpdll;
  580.     else
  581. (DBGDLL *)pNode->Next = lpdll;
  582. }
  583. void WINAPI RemoveDllNode (
  584.     DBGPROCESS    *lppr,
  585.     LOAD_DLL_DEBUG_INFO    *lpdbgDll)
  586. {
  587.     DBGDLL   *pNode = lppr->lpDlls;
  588.     DBGDLL   *lpdll;
  589.     SECTIONINFO    *pSection, *pNext;
  590.     while (pNode->Next &&
  591.    ((DBGDLL *)(pNode->Next))->lpBaseOfDll != lpdbgDll->lpBaseOfDll)
  592. pNode = (DBGDLL *)pNode->Next;
  593.     if (pNode->Next)
  594. {
  595. lpdll = (DBGDLL *)pNode->Next;
  596. pNode->Next = ((DBGDLL *)(pNode->Next))->Next;
  597. pSection = pNext = lpdll->lpSection;
  598. while (pNext)
  599.     {
  600.     pNext = (SECTIONINFO *)pSection->Next;
  601.     HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection);
  602.     pSection = pNext;
  603.     }
  604. HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll);
  605. }
  606.     else if (pNode->lpBaseOfDll == lpdbgDll->lpBaseOfDll)
  607. {
  608. lpdll = pNode;
  609. lppr->lpDlls = NULL;
  610. pSection = pNext = lpdll->lpSection;
  611. while (pNext)
  612.     {
  613.     pNext = (SECTIONINFO *)pSection->Next;
  614.     HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection);
  615.     pSection = pNext;
  616.     }
  617. HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll);
  618. }
  619. }
  620. void WINAPI RecordException (
  621.     DBGPROCESS    *lppr,
  622.     DEBUG_EVENT    *de)
  623. {
  624.     DBGEXCEPTREC    *lper;
  625.     DBGEXCEPTREC    *per = lppr->lpERs;
  626.     HANDLE     hThread;
  627.     int      i;
  628.     /* allocate Dll node off heap */
  629.     if ((lper = (DBGEXCEPTREC *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGEXCEPTREC))) == NULL)
  630. ReportError (IDS_ERRHEAPALLOC);
  631.     /* initialize exception record structure */
  632.     lper->dwThreadId = de->dwThreadId;
  633.     lper->dwFirstChance = de->u.Exception.dwFirstChance;
  634.     lper->ExceptRecord.ExceptionCode = de->u.Exception.ExceptionRecord.ExceptionCode;
  635.     lper->ExceptRecord.ExceptionFlags = de->u.Exception.ExceptionRecord.ExceptionFlags;
  636.     lper->ExceptRecord.ExceptionRecord = NULL;
  637.     lper->ExceptRecord.ExceptionAddress = de->u.Exception.ExceptionRecord.ExceptionAddress;
  638.     lper->ExceptRecord.NumberParameters = de->u.Exception.ExceptionRecord.NumberParameters;
  639.     for (i=0; i<EXCEPTION_MAXIMUM_PARAMETERS; i++)
  640. lper->ExceptRecord.ExceptionInformation[i] =
  641.    de->u.Exception.ExceptionRecord.ExceptionInformation[i];
  642.     /* get exception thread handle */
  643.     hThread = FindThreadHandle (lppr, de->dwThreadId);
  644.     lper->Context.ContextFlags = CONTEXT_CONTROL;
  645.     GetThreadContext (hThread, &(lper->Context));
  646.     /* set linked list pointers */
  647.     while (per && per->Next)
  648. per = (DBGEXCEPTREC *)per->Next;
  649.     if (!per)
  650. lppr->lpERs = lper;
  651.     else
  652. (DBGEXCEPTREC *)per->Next = lper;
  653. }
  654. /*
  655.  * MIPS/ALPHA/PPC must increment the FIR/Iar on a breakpoint
  656.  * in order to fetch the next instruction
  657.  */
  658. int WINAPI HandleBreakPoint(
  659.     DBGPROCESS       *lppr,
  660.     DWORD       dwThreadID
  661.     )
  662. {
  663.     CONTEXT   ThreadContext;
  664.     DBGTHREAD *pNode = lppr->lpThreads;
  665.     HANDLE    hThread;
  666.     while (pNode && pNode->dwThreadID != dwThreadID)
  667. pNode = (DBGTHREAD *)pNode->Next;
  668.     if(!pNode)
  669. return(0);
  670.     else
  671. {
  672.         hThread = (HANDLE) pNode->hThread;
  673.         ThreadContext.ContextFlags = CONTEXT_CONTROL;
  674.         if (!GetThreadContext (hThread, &ThreadContext))
  675.     {
  676.     ReportError (IDS_ERRGETTHREADCONTEXT);
  677.             return(0);
  678.     }
  679. #ifdef _PPC_
  680.         ThreadContext.Iar += 4;
  681. #elif !defined _X86_
  682.         ThreadContext.Fir += 4;
  683. #endif
  684.         if (!SetThreadContext (hThread, &ThreadContext))
  685.     {
  686.     ReportError (IDS_ERRSETTHREADCONTEXT);
  687.     return (0);
  688.     }
  689. return (1);
  690. }
  691. }
  692. int   WINAPI WhereIsStack (
  693.     HANDLE   hThreadContext)
  694. {
  695.     CONTEXT ThreadContext;
  696.     ThreadContext.ContextFlags = CONTEXT_CONTROL;
  697.     if (!GetThreadContext (hThreadContext, &ThreadContext))
  698. ReportError (IDS_ERRGETTHREADCONTEXT);
  699. #ifdef _X86_
  700.     return ThreadContext.Esp;
  701. #elif defined (_PPC_)
  702.     return (int) ThreadContext.Gpr1;
  703. #else /* _MIPS_ */
  704.     return (int) ThreadContext.IntSp;
  705. #endif
  706. }
  707. /* function walks memory regions of process */
  708. int    WINAPI WalkProcess (
  709.     HANDLE    hChildProcess,
  710.     LPVOID    *lpWalk,
  711.     LPINT     *lpObjects)
  712. {
  713.     LPVMOBJECT   lpList;
  714.     LPVOID   lpMem = 0;
  715.     LPVOID   lpStack = 0;
  716.     int    nCnt, i;
  717.     SYSTEM_INFO   si;
  718.     /* if pointer exists, reset to no commit */
  719.     if (*lpWalk)
  720. {
  721. if (!VirtualFree (*lpWalk, 0, MEM_DECOMMIT))
  722.     ReportError (IDS_ERRVIRTUALFREE);
  723. }
  724.     /* else perform initial reserve */
  725.     else
  726. if ((*lpWalk = VirtualAlloc (NULL,
  727.      TOTALVMRESERVE,
  728.      MEM_RESERVE,
  729.      PAGE_NOACCESS)) == NULL)
  730.     ReportError (IDS_ERRVIRTUALALLOC);
  731.     /* initialize list pointer to beginning of walker list */
  732.     lpList = (LPVMOBJECT)*lpWalk;
  733.     /* Get maximum address range from system info */
  734.     GetSystemInfo(&si);
  735.     /* walk process addresses */
  736.     while (lpMem < si.lpMaximumApplicationAddress)
  737. {
  738. try  /* virtual memory exception handler automatically commits mem */
  739.     {
  740.     /* touch memory in VMOBJECT structure that exists after mbi field to trigger
  741.        access violation for a new page of memory.  Do this here since VirtualQueryEx
  742.        does not seem to generate exceptions, rather it just fails calls */
  743.     *lpList->szObjType = 0;
  744.     *lpList->szModule = 0;
  745.     *lpList->szSection = 0;
  746.     lpList->bNew = 0;
  747.     VirtualQueryEx (hChildProcess,
  748.     lpMem,
  749.     &(lpList->mbi),
  750.     sizeof (MEMORY_BASIC_INFORMATION));
  751.     /* increment lpMem to next region of memory */
  752.     lpMem = (LPVOID)((DWORD)lpList->mbi.BaseAddress +
  753.      (DWORD)lpList->mbi.RegionSize);
  754.     lpList++;
  755.     }
  756. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
  757.     {
  758.     /* commit next page of walker list memory */
  759.     if (((int)lpList + 4096) < (int)*lpWalk + TOTALVMRESERVE)
  760. VirtualAlloc ((LPVOID)((int)lpList + sizeof (VMOBJECT)),
  761.       4096,
  762.       MEM_COMMIT,
  763.       PAGE_READWRITE);
  764.     else
  765. {
  766. NotifyUser (NULL,
  767.     IDS_ERROR,
  768.     IDS_NOTENOUGHMEM,
  769.     " reserved for Objects",
  770.     MB_OK);
  771. return 0;
  772. }
  773.     }
  774. }
  775.     /* allocate objects index array */
  776.     if (*lpObjects)
  777. LocalFree (*lpObjects);
  778.     nCnt = (((int)(LPVOID)lpList)-(int)*lpWalk)/sizeof (VMOBJECT);
  779.     *lpObjects = LocalAlloc (LPTR, nCnt * sizeof (int));
  780.     for (i=0; i<nCnt; i++)
  781. (*lpObjects)[i] = i;
  782.     /* return number of item in list */
  783.     return (nCnt);
  784. }
  785. void WINAPI AnalyzeProcess (
  786.     DBGPROCESS   *lpDbgProcess,
  787.     LPVMOBJECT   lpVMObject,
  788.     int    nObjects)
  789. {
  790.     DBGTHREAD *pTh = lpDbgProcess->lpThreads;
  791.     DBGDLL *pDll = lpDbgProcess->lpDlls;
  792.     int  nStack;
  793.     int  nThreadCnt = 0;
  794.     char szNum[10];
  795.     char szObjDesc[MAX_PATH];
  796.     SECTIONINFO   *pSection;
  797.     int  i;
  798.     MEMORY_BASIC_INFORMATION mbi;
  799.     LPPROBE lpProbe;
  800.     /* name default heap in process if available */
  801.     if (lpProbe = RetrieveProbeData ())
  802. {
  803. VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)lpProbe->hDefHeap, &mbi, sizeof (mbi));
  804. /* ignore invalid regions with a base region of 0 */
  805. if (mbi.AllocationBase)
  806.     {
  807.     /* find all objects with same base region */
  808.     for (i=0; i<nObjects; i++)
  809. {
  810. if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
  811.     {
  812.     strcpy (lpVMObject[i].szObjType, "heap");
  813.     strcpy (lpVMObject[i].szModule, "process default");
  814.     }
  815. }
  816.     }
  817. }
  818.     /* name stack object for each thread in process */
  819.     while (pTh != NULL)
  820. {
  821. /* get stack location for thread */
  822. nStack = WhereIsStack (pTh->hThread);
  823. strcpy (szObjDesc, "Thread ");
  824. strcat (szObjDesc, itoa (nThreadCnt, szNum, 10));
  825. /* locate base region */
  826. VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)nStack, &mbi, sizeof (mbi));
  827. /* ignore invalid regions with a base region of 0 */
  828. if (mbi.AllocationBase)
  829.     {
  830.     /* find all objects with same base region */
  831.     for (i=0; i<nObjects; i++)
  832. {
  833. if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
  834.     {
  835.     strcpy (lpVMObject[i].szObjType, "stack");
  836.     strcpy (lpVMObject[i].szModule, szObjDesc);
  837.     }
  838. }
  839.     }
  840. /* locate and identify the guard page in each stack.
  841.    The guard page is a single page of committed memory at the lower end of
  842.    committed memory and immediately adjacent to the stack's reserved memory.
  843.    If there is no more reserved stack space left, the guard page will be the
  844.    last page of committed memory.  A stack cannot exist without a guard page.
  845.    There will be at most three regions of memory in the stack: the actual stack
  846.    space is committed, the guard page is committed and the remaining address
  847.    space is marked reserved. */
  848. /* locate lowest region of stack, since objects array is not sorted until after
  849.    this function, it is always in ascending address order :) */
  850. i=0;
  851. while (i<nObjects &&
  852.        (int)lpVMObject[i].mbi.BaseAddress < nStack &&
  853.        lpVMObject[i].mbi.AllocationBase != mbi.AllocationBase)
  854.     i++;
  855. if (i<nObjects &&
  856.     lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
  857.     {
  858.     if (lpVMObject[i].mbi.State == MEM_RESERVE)
  859. i++;
  860.     /* identify guard page in section field */
  861.     strcpy (lpVMObject[i].szSection, "guard");
  862.     }
  863. /* increment thread count */
  864. nThreadCnt++;
  865. /* increment list pointer */
  866. pTh = (DBGTHREAD *)pTh->Next;
  867. }
  868.     /* name DLL objects in process */
  869.     while (pDll != NULL)
  870. {
  871. /* locate dll base region */
  872. VirtualQueryEx (lpDbgProcess->hProcess, pDll->lpBaseOfDll, &mbi, sizeof (mbi));
  873. /* ignore invalid regions with a base region of 0 */
  874. if (mbi.AllocationBase)
  875.     {
  876.     /* find all objects with same base region */
  877.     for (i=0; i<nObjects; i++)
  878. {
  879. if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
  880.     {
  881.     strcpy (lpVMObject[i].szObjType, "dll");
  882.     strcpy (lpVMObject[i].szModule, pDll->szImageName);
  883.     }
  884. }
  885.     }
  886. /* name dll sections */
  887. pSection = (SECTIONINFO *)pDll->lpSection;
  888. while (pSection != NULL)
  889.     {
  890.     i = 0;
  891.     while (i++<nObjects)
  892. {
  893. if (lpVMObject[i].mbi.BaseAddress ==
  894. ((char *)pDll->lpBaseOfDll + pSection->uVirtualAddress))
  895.     {
  896.     strcpy (lpVMObject[i].szSection, pSection->szSection);
  897.     break;
  898.     }
  899. }
  900.     pSection = (SECTIONINFO *)pSection->Next;
  901.     }
  902. /* increment list pointer */
  903. pDll = (DBGDLL *)pDll->Next;
  904. }
  905.     /* locate exe base region */
  906.     VirtualQueryEx (lpDbgProcess->hProcess, lpDbgProcess->lpImage, &mbi, sizeof (mbi));
  907.     /* ignore invalid regions with a base region of 0 */
  908.     if (mbi.AllocationBase)
  909. {
  910. /* find all objects with same base region */
  911. for (i=0; i<nObjects; i++)
  912.     {
  913.     if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
  914. {
  915. strcpy (lpVMObject[i].szObjType, "exe");
  916. strcpy (lpVMObject[i].szModule, lpDbgProcess->szModule);
  917. }
  918.     }
  919. }
  920.     /* name exe sections */
  921.     pSection = lpDbgProcess->lpSection;
  922.     while (pSection != NULL)
  923. {
  924. i = 0;
  925. while (i++<nObjects)
  926.     {
  927.     if (lpVMObject[i].mbi.BaseAddress ==
  928.     ((char *)lpDbgProcess->lpImage + pSection->uVirtualAddress))
  929. {
  930. strcpy (lpVMObject[i].szSection, pSection->szSection);
  931. break;
  932. }
  933.     }
  934. pSection = (SECTIONINFO *)pSection->Next;
  935. }
  936. }
  937. /* find all occurrances of objects having same base region */
  938. void WINAPI NameObjects (
  939.     HANDLE   hProcess,
  940.     LPVOID   lpAddress,
  941.     LPVMOBJECT   lpVMObj,
  942.     int    nObjects,
  943.     char   *lpszObjType,
  944.     char   *lpszModule)
  945. {
  946.     int  i;
  947.     MEMORY_BASIC_INFORMATION mbi;
  948.     /* locate base region */
  949.     VirtualQueryEx (hProcess, lpAddress, &mbi, sizeof (mbi));
  950.     /* ignore invalid regions with a base region of 0 */
  951.     if (!mbi.AllocationBase)
  952. return;
  953.     /* find all objects with same base region */
  954.     for (i=0; i<nObjects; i++)
  955. {
  956. if (lpVMObj[i].mbi.AllocationBase == mbi.AllocationBase)
  957.     {
  958.     strcpy (lpVMObj[i].szObjType, lpszObjType);
  959.     strcpy (lpVMObj[i].szModule, lpszModule);
  960.     }
  961. }
  962. }
  963. void WINAPI IdentifyNewObjects (
  964.     LPVMOBJECT   lpVMObjectOld,
  965.     int    nObjectsOld,
  966.     LPVMOBJECT   lpVMObject,
  967.     int    nObjects)
  968. {
  969.     int    i, j;
  970.     for (i=0; i<nObjects; i++)
  971. {
  972. for (j=0; j<nObjectsOld; j++)
  973.     {
  974.     if (VMCompare (lpVMObject+i, lpVMObjectOld+j))
  975. goto NEXT;
  976.     }
  977. /* if not found must be a new item */
  978. lpVMObject[i].bNew = TRUE;
  979. NEXT:;
  980. }
  981. }
  982. BOOL WINAPI VMCompare (
  983.     LPVMOBJECT   lpVM1,
  984.     LPVMOBJECT   lpVM2)
  985. {
  986.     /* compare memory info */
  987.     if (lpVM1->mbi.AllocationBase      != lpVM2->mbi.AllocationBase   ||
  988. lpVM1->mbi.BaseAddress        != lpVM2->mbi.BaseAddress   ||
  989. lpVM1->mbi.RegionSize        != lpVM2->mbi.RegionSize    ||
  990. lpVM1->mbi.Protect        != lpVM2->mbi.Protect   ||
  991. lpVM1->mbi.AllocationProtect   != lpVM2->mbi.AllocationProtect   ||
  992. lpVM1->mbi.State        != lpVM2->mbi.State   ||
  993. lpVM1->mbi.Type         != lpVM2->mbi.Type      )
  994. return FALSE;
  995.     /* compare character information */
  996.     if (memcmp ((LPVOID)lpVM1->szObjType, (LPVOID)lpVM2->szObjType, 12) ||
  997. memcmp ((LPVOID)lpVM1->szSection,
  998. (LPVOID)lpVM2->szSection,
  999. IMAGE_SIZEOF_SHORT_NAME) ||
  1000. memcmp ((LPVOID)lpVM1->szModule, (LPVOID)lpVM2->szModule, MAX_PATH))
  1001. return FALSE;
  1002.     /* if still here, must be a match */
  1003.     return TRUE;
  1004. }
  1005. /* test to see if all memory objects in range are committed */
  1006. BOOL   WINAPI CommittedMemoryRange (
  1007.     int    i,
  1008.     int    j,
  1009.     LPVMOBJECT   lpvm,
  1010.     int    *Objects)
  1011. {
  1012.     int    k;
  1013.     /* test each memory object in range */
  1014.     for (k = min(i, j); k <= max (i, j); k++)
  1015. /* report any non committed memory regions */
  1016. if (lpvm[Objects[k]].mbi.State != MEM_COMMIT)
  1017.     return FALSE;
  1018.     /* report all committed range */
  1019.     return TRUE;
  1020. }
  1021. /* signal debugger thread to access process memory */
  1022. BOOL WINAPI AccessProcessMemory (
  1023.     HANDLE    hMemoryEvent,
  1024.     HANDLE    hAckEvent,
  1025.     LPVOID    lpAddress,
  1026.     LPVOID    lpBuffer,
  1027.     DWORD     *dwSize)
  1028. {
  1029.     DWORD    dwResult;
  1030.     /* copy data to module globals */
  1031.     PMAAddress = lpAddress;
  1032.     PMABuffer = lpBuffer;
  1033.     PMASize = *dwSize;
  1034.     /* signal debugger thread to read memory from process */
  1035.     SetEvent (hMemoryEvent);
  1036.     /* wait on debugger thread to signal completion of memory task */
  1037.     dwResult = WaitForSingleObject (hAckEvent, 100000);
  1038.     ResetEvent (hAckEvent);
  1039.     /* reset size accessed to verify operation */
  1040.     *dwSize = PMASize;
  1041.     return (dwResult == WAIT_OBJECT_0 &&
  1042.     PMASize != 0);
  1043. }
  1044. BOOL WINAPI InterruptThread_HookProcess (
  1045.     DBGPROCESS        *lpDbgProcess,
  1046.     LPPROCESS_STATE    lpState)
  1047. {
  1048.     DBGDLL *pDlls = lpDbgProcess->lpDlls;
  1049.     int  nBytes, nLen, i;
  1050.     MEMORY_BASIC_INFORMATION mbi;
  1051.     LPVOID lpLoadLibrary = NULL;
  1052.     char szKernel[] = "KERNEL32.DLL";
  1053.     char szFunction[] = "LoadLibraryA";
  1054.     BYTE pCode[PAGESIZE];
  1055.     BYTE pStack[PAGESIZE];
  1056.     HANDLE hDll;
  1057.     /* initialize stack and code pages */
  1058.     for (i=0; i<PAGESIZE; i++)
  1059. {
  1060. pStack[i] = 0;
  1061. pCode[i] = 0;
  1062. }
  1063.     /* find kernel32 Dll */
  1064.     while (pDlls != NULL)
  1065. {
  1066. if (!stricmp (pDlls->szImageName, szKernel))
  1067.     break;
  1068. pDlls = (DBGDLL *)pDlls->Next;
  1069. }
  1070.     /* if DLL not loaded abort */
  1071.     if (pDlls == NULL)
  1072. return FALSE;
  1073.     /* load the dll in this process, find the function offset in this
  1074.        process and normalize to the offset in the child process */
  1075.     hDll = LoadLibrary (szKernel);
  1076.     lpLoadLibrary = GetProcAddress (hDll, szFunction);
  1077.     VirtualQuery (lpLoadLibrary, &mbi, sizeof (mbi));
  1078.     (int)lpLoadLibrary += ((int)pDlls->lpBaseOfDll - (int)mbi.AllocationBase);
  1079.     FreeLibrary (hDll);
  1080.     /* get thread context information and save for replacement */
  1081.     lpState->Context.ContextFlags = CONTEXT_FULL;
  1082.     if (!GetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context)))
  1083. return FALSE;
  1084. #ifdef _X86_
  1085.     lpState->Eip = (LPVOID)lpState->Context.Eip;
  1086.     lpState->Esp = (LPVOID)lpState->Context.Esp;
  1087. #elif defined(_PPC_)
  1088.     lpState->Eip = (LPVOID)lpState->Context.Iar;
  1089.     lpState->Esp = (LPVOID)lpState->Context.Gpr1;
  1090. #else /* MIPS */
  1091.     lpState->Eip = (LPVOID)lpState->Context.Fir;
  1092.     lpState->Esp = (LPVOID)lpState->Context.IntSp;
  1093. #endif
  1094.     /* locate first writeable code page in exe module */
  1095.     lpState->pCodePage = lpDbgProcess->lpImage;
  1096.     VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi));
  1097.     while (!(mbi.Protect & PAGE_READWRITE) &&
  1098.    mbi.AllocationBase == lpDbgProcess->lpImage)
  1099. {
  1100. (int)lpState->pCodePage = (int)mbi.BaseAddress + mbi.RegionSize;
  1101. VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi));
  1102. }
  1103.     if (mbi.AllocationBase != lpDbgProcess->lpImage)
  1104. return FALSE;
  1105.     /* save code page for reset process */
  1106.     ReadProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
  1107.     /* write DLL path to code page */
  1108.     strcpy ((char *)pCode, szCurPath);
  1109.     strcat ((char *)pCode, "\probe.dll");
  1110.     nLen = strlen ((char *)pCode) + 1;
  1111.     /* find current stack page and save  */
  1112. #ifdef _X86_
  1113.     lpState->pStackPage = (LPVOID)((((int)lpState->Context.Esp)/PAGESIZE) * PAGESIZE);
  1114. #elif defined(_PPC_)
  1115.     lpState->pStackPage = (LPVOID)((((int)lpState->Context.Gpr1)/PAGESIZE) * PAGESIZE);
  1116. #else /* MIPS */
  1117.     lpState->pStackPage = (LPVOID)((((int)lpState->Context.IntSp)/PAGESIZE) * PAGESIZE);
  1118. #endif
  1119.     ReadProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
  1120.     /* push address of DLL string on stack */
  1121.     *((int *)(pStack+4092)) = (int)lpState->pCodePage;
  1122.     /* push return address on stack */
  1123.     *((int *)(pStack+4088)) = (int)lpState->pCodePage+nLen;
  1124.     /* return to Int 3 breakpoint instruction */
  1125.     pCode[nLen] = 0xCC;
  1126.     /* write new code and stack pages */
  1127.     WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, pCode, PAGESIZE, &nBytes);
  1128.     WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, pStack, PAGESIZE, &nBytes);
  1129.     /* update Eip to execute at actual LoadLibrary function */
  1130.     /* adjust stack pointer to point to return address */
  1131. #ifdef _X86_
  1132.     lpState->Context.Eip = (UINT)lpLoadLibrary;
  1133.     lpState->Context.Esp = (UINT)lpState->pStackPage+4088;
  1134. #elif defined(_PPC_)
  1135.     lpState->Context.Iar = (UINT)lpLoadLibrary;
  1136.     lpState->Context.Gpr1 = (UINT)lpState->pStackPage+4088;
  1137. #else /* _MIPS_ */
  1138.     lpState->Context.Fir = (UINT)lpLoadLibrary;
  1139.     lpState->Context.IntSp = (UINT)lpState->pStackPage+4088;
  1140. #endif
  1141.     if (!SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context)))
  1142. {
  1143. ReportError (IDS_ERRSETTHREADCONTEXT);
  1144. /* replace code and stack pages */
  1145. WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
  1146. WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
  1147. return FALSE;
  1148. }
  1149.     return TRUE;
  1150. }
  1151. void WINAPI ResetInterruptedThread (
  1152.     DBGPROCESS        *lpDbgProcess,
  1153.     LPPROCESS_STATE    lpState)
  1154. {
  1155.     int    nBytes;
  1156.     /* return thread context information */
  1157. #ifdef _X86_
  1158.     lpState->Context.Eip = (UINT)lpState->Eip;
  1159.     lpState->Context.Esp = (UINT)lpState->Esp;
  1160. #elif defined(_PPC_)
  1161.     lpState->Context.Iar = (UINT)lpState->Eip;
  1162.     lpState->Context.Gpr1 = (UINT)lpState->Esp;
  1163. #else /* MIPS */
  1164.     lpState->Context.Fir = (UINT)lpState->Eip;
  1165.     lpState->Context.IntSp = (UINT)lpState->Esp;
  1166. #endif
  1167.     SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context));
  1168.     /* return code and stack information */
  1169.     WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
  1170.     WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
  1171. }