suspend_start.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include <stdio.h>
  2. #include <windows.h>
  3. // SuspendThread or ResumeThread
  4. typedef DWORD threadfunc_t(HANDLE);
  5. #if 1 // TinyCC compatibility
  6. #define TH32CS_SNAPTHREAD 0x00000004
  7. typedef struct {
  8. DWORD dwSize;
  9. DWORD cntUsage;
  10. DWORD th32ThreadID;
  11. DWORD th32OwnerProcessID;
  12. LONG tpBasePri;
  13. LONG tpDeltaPri;
  14. DWORD dwFlags;
  15. } THREADENTRY32;
  16. typedef THREADENTRY32 *LPTHREADENTRY32;
  17. HANDLE CreateToolhelp32Snapshot(DWORD, DWORD);
  18. BOOL Thread32First(HANDLE, LPTHREADENTRY32);
  19. BOOL Thread32Next(HANDLE, LPTHREADENTRY32);
  20. #endif
  21. // https://stackoverflow.com/questions/11010165/how-to-suspend-resume-a-process-in-windows
  22. BOOL ThreadAction(DWORD pid, threadfunc_t action)
  23. {
  24. BOOL found = FALSE;
  25. // Ignore Wine warnings
  26. HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  27. THREADENTRY32 entry;
  28. entry.dwSize = sizeof(THREADENTRY32);
  29. Thread32First(snapshot, &entry);
  30. do {
  31. if (entry.th32OwnerProcessID != pid)
  32. continue;
  33. found = TRUE;
  34. HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE,
  35. entry.th32ThreadID);
  36. if (action(thread) == -1)
  37. printf("Action failed. TID=%d, Error=%d\n", thread, GetLastError());
  38. CloseHandle(thread);
  39. } while (Thread32Next(snapshot, &entry));
  40. CloseHandle(snapshot);
  41. return found; // As long the thread lives
  42. }
  43. int main(int argc, char *argv[])
  44. {
  45. if (argc < 2) {
  46. puts("Usage: suspend_start.exe \"C:/path/to/app.exe\" [\"args ...\"]");
  47. return 1;
  48. }
  49. // https://docs.microsoft.com/en-us/windows/win32/procthread/creating-processes
  50. STARTUPINFO si;
  51. PROCESS_INFORMATION pi;
  52. memset(&si, 0, sizeof(si));
  53. memset(&pi, 0, sizeof(pi));
  54. BOOL success = CreateProcessA(
  55. argv[1], // Application name
  56. argc >= 3 ? argv[2] : NULL,
  57. NULL, NULL, // Security
  58. FALSE,
  59. CREATE_SUSPENDED,
  60. NULL,
  61. NULL, // Current directory. Is it needed?
  62. &si, &pi
  63. );
  64. if (!success) {
  65. puts("Failed to start app. Path not found?");
  66. return 1;
  67. }
  68. printf("Success! Handle=%p, PID=%d, TID=%d\n", pi.hProcess, pi.dwProcessId, pi.dwThreadId);
  69. for (int i = 0; TRUE; ++i) {
  70. printf("% 4d | Proc suspended. ENTER to resume\n", i);
  71. getchar();
  72. if (!ThreadAction(pi.dwProcessId, ResumeThread))
  73. break;
  74. printf("% 4d | Proc resumed. ENTER to suspend\n", i);
  75. getchar();
  76. if (!ThreadAction(pi.dwProcessId, SuspendThread))
  77. break;
  78. }
  79. puts("END. Lost process.");
  80. return 0;
  81. }