Suspending and Resuming a Process

[Previous] [Next]

The concept of suspending or resuming a process doesn't exist for Windows since processes are never scheduled CPU time. However, I have been asked numerous times how to suspend all of the threads in a process. Windows does allow one process to suspend all the threads in another process, but the process doing the suspending must be a debugger. Specifically, the process must call functions such as WaitForDebugEvent and ContinueDebugEvent.

Windows doesn't offer any other way to suspend all threads in a process because of race conditions. For example, while the threads are suspended, a new thread might be created. Somehow the system must suspend any new threads during this window of time. Microsoft has integrated this functionality into the debugging mechanism of the system.

While you cannot create an absolutely perfect SuspendProcess function, you can create an implementation of this function that works well in many situations. Here is my implementation of a SuspendProcess function:

 VOID SuspendProcess(DWORD dwProcessID, BOOL fSuspend) { // Get the list of threads in the system. HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, dwProcessID); if (hSnapshot != INVALID_HANDLE_VALUE) { // Walk the list of threads. THREADENTRY32 te = { sizeof(te) }; BOOL fOk = Thread32First(hSnapshot, &te); for (; fOk; fOk = Thread32Next(hSnapshot, &te)) { // Is this thread in the desired process? if (te.th32OwnerProcessID == dwProcessID) { // Attempt to convert the thread ID into a handle. HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID); if (hThread != NULL) { // Suspend or resume the thread. if (fSuspend) SuspendThread(hThread); else ResumeThread(hThread); } CloseHandle(hThread); } } CloseHandle(hSnapshot); } } 

My SuspendProcess function uses the ToolHelp functions (discussed in Chapter 4) to enumerate the list of threads in the system. As I locate threads that are part of the specified process, I call OpenThread:

 HANDLE OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadID); 

This new Windows 2000 function locates the thread kernel object with the matching thread ID, increments the kernel object's usage count, and returns a handle to the object. With this handle, I call SuspendThread (or ResumeThread). Because OpenThread is new in Windows 2000, my SuspendProcess function will not work on Windows 95 or Windows 98, or on Windows NT 4.0 or earlier.

You probably understand why SuspendProcess does not work 100 percent of the time: while enumerating the set of threads, new threads can be created and destroyed. So after I call CreateToolhelp32Snapshot, a new thread might appear in the target process, which my function will not suspend. Later, when you call SuspendProcess to resume the threads, it will resume a thread that it never suspended. Even worse, while enumerating the thread IDs, an existing thread might be destroyed and a new thread might be created, and both of these threads might have the same ID. This would cause the function to suspend some arbitrary thread (probably in a process other than the target process).

Of course, these situations are unlikely, and if you have intimate knowledge of how the target process operates, these issues might not be problems at all. I offer you this function to use at your own risk.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net