Получение дескриптора основного потока процесса

Я создал дополнительный поток в небольшом тестовом приложении и хочу приостановить основной поток из этого дополнительного потока. Дополнительный поток создается через CreateRemoteThread из внешнего процесса.

Так как SuspendThread нуждается в HANDLE для потока, который должен быть приостановлен, я хочу знать, как получить этот HANDLE из кода, запущенного в моем дополнительном потоке.

Ответ 1

DWORD GetMainThreadId () {
    const std::tr1::shared_ptr<void> hThreadSnapshot(
        CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0), CloseHandle);
    if (hThreadSnapshot.get() == INVALID_HANDLE_VALUE) {
        throw std::runtime_error("GetMainThreadId failed");
    }
    THREADENTRY32 tEntry;
    tEntry.dwSize = sizeof(THREADENTRY32);
    DWORD result = 0;
    DWORD currentPID = GetCurrentProcessId();
    for (BOOL success = Thread32First(hThreadSnapshot.get(), &tEntry);
        !result && success && GetLastError() != ERROR_NO_MORE_FILES;
        success = Thread32Next(hThreadSnapshot.get(), &tEntry))
    {
        if (tEntry.th32OwnerProcessID == currentPID) {
            result = tEntry.th32ThreadID;
        }
    }
    return result;
}

Ответ 2

Я не думаю, что есть что-то, что отличает основной поток от других потоков после начала процесса. Однако вы можете перечислить все потоки процесса и использовать GetThreadTimes найти поток с самым ранним временем создания. Вызовите OpenThread, чтобы получить HANDLE из идентификатора потока.

Ответ 3

Получить идентификатор потока с помощью этой функции:

/* CAUTION: ONLY x86 TESTED
 * get the thread id of the main thread of a target process
 *
 * params:
 *     DWORD dwPid  process id of the target process
 *
 * return:
 *     Success      thread id
 *     Error        NULL
 */
DWORD GetMainThreadId(DWORD dwPid)
{
    LPVOID lpTid;

    _asm
    {
        mov eax, fs:[18h]
        add eax, 36
        mov [lpTid], eax
    }

    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid);
    if(hProcess == NULL)
        return NULL;

    DWORD dwTid;
    if(ReadProcessMemory(hProcess, lpTid, &dwTid, sizeof(dwTid), NULL) == FALSE)
    {
        CloseHandle(hProcess);
        return NULL;
    }

    CloseHandle(hProcess);

    return dwTid;
}

Просто откройте поток, чтобы получить дескриптор:

/*
 * get a handle to the main thread of a target process
 * if successfull, the returned handle must be closed with CloseHandle()
 *
 * params:
 *     DWORD dwPid              process id of the target process
 *     DWORD dwDesiredAccess    desired access rights to the thread
 *
 * return:
 *     Success      thread handle with desired access rights
 *     Error        NULL
 */
HANDLE GetMainThreadHandle(DWORD dwPid, DWORD dwDesiredAccess)
{
    DWORD dwTid = GetMainThreadId(dwPid);
    if(dwTid == FALSE)
        return NULL;

    return OpenThread(dwDesiredAccess, FALSE, dwTid);
}

Ответ 4

Почему бы вам просто не создать глобальную программу (используйте extern, если вам нужно)

HANDLE mainThread ;
DWORD mainThreadId ;

В первой строке main (перед созданием любых потоков) выполните

mainThread = GetCurrentThread() ;
mainThreadId = GetCurrentThreadId() ;

Вы можете использовать любую форму IPC для обмена либо идентификатором, либо РУЧКОЙ с удаленным процессом (еще не подтвердили, что совместное использование HANDLE будет работа, но он должен!)

Ответ 5

Несколько полезных функций API этого типа находятся под (конечно!) Tool Help. CreateToolhelp32Snapshot() API сделает снимок текущих потоков для определенного процесса.

// Take a snapshot of all running threads  
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
if( hThreadSnap == INVALID_HANDLE_VALUE ) 
  return( FALSE );

Полный пример кода здесь.

Возвращенная структура не отличает основной поток от других. Я не знаю механизма для этого; в то время как в некоторых версиях среды выполнения C будет все ExitProcess() в конце основного потока, во всех последних версиях процесс продолжает работать до тех пор, пока последний поток не выйдет.

Рекомендация Interjay использовать GetThreadTimes может быть лучшим выбором. Если вы можете CreateProcess() целевой процесс, член hThread PROCESS_INFORMATION содержит tid для основного потока. Приветствуйте любые идеи от других.