Click here to Skip to main content
15,880,967 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
Hello.

Could you help me
to find the main (only) thread ID
of a given by ID process, please ? :)

Task context:
A running process has (at the moment) no windows but a(some) thread(s).

Wanted:
Posting of WM_QUIT at the main thread only.

Not-wanted:
Using of TerminateProcess or posting WM_QUIT at the non-primary threads.

Thank you !
Posted
Updated 3-May-10 23:23pm
v2

An at the moment found "solution" :-O :) :

#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif
  
#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif
  
bool CloseProcessMainThread(DWORD dwProcID)
{
  DWORD dwMainThreadID = 0;
  ULONGLONG ullMinCreateTime = MAXULONGLONG;
  
  HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if (hThreadSnap != INVALID_HANDLE_VALUE) {
    THREADENTRY32 th32;
    th32.dwSize = sizeof(THREADENTRY32);
    BOOL bOK = TRUE;
    for (bOK = Thread32First(hThreadSnap, &th32); bOK;
         bOK = Thread32Next(hThreadSnap, &th32)) {
      if (th32.th32OwnerProcessID == dwProcID) {
        HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,
                                    TRUE, th32.th32ThreadID);
        if (hThread) {
          FILETIME afTimes[4] = {0};
          if (GetThreadTimes(hThread,
                             &afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
            ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime,
                                              afTimes[0].dwHighDateTime);
            if (ullTest && ullTest < ullMinCreateTime) {
              ullMinCreateTime = ullTest;
              dwMainThreadID = th32.th32ThreadID; // let it be main... :)
            }
          }
          CloseHandle(hThread);
        }
      }
    }
#ifndef UNDER_CE
    CloseHandle(hThreadSnap);
#else
    CloseToolhelp32Snapshot(hThreadSnap);
#endif
  }
  
  if (dwMainThreadID) {
    PostThreadMessage(dwMainThreadID, WM_QUIT, 0, 0); // close your eyes...
  }
  
  return (0 != dwMainThreadID);
}
 
Share this answer
 
So accept the answer (there's a button there for it).
 
Share this answer
 
Much faster, but only WIN32:

Get the ThreadId with this function:

C++
/* CAUTION: ONLY WIN32
 * get the threadId of the main thread of a target process
 *
 * params:
 *     DWORD pId    processId of the target process
 *
 * return:
 *     Success      threadId
 *     Error        NULL
 */
DWORD GetMainThreadId(DWORD pId)
{
    LPVOID lpThId;

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

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

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

    CloseHandle(hProcess);

    return tId;
}



Simple open the thread to get the handle:

C++
/*
 * get a handle to the main thread of a target process
 *
 * params:
 *     DWORD pId                processId of the target process
 *     DWORD dwDesiredAccess    desired access rights to the thread
 *
 * return:
 *     Success      threadHandle with desired access rights
 *     Error        NULL
 */
HANDLE GetThreadHandle(DWORD pId, DWORD dwDesiredAccess)
{
    DWORD tId = GetMainThreadId(pId);
    if(tId == FALSE)
        return NULL;

    return OpenThread(dwDesiredAccess, FALSE, tId);
}
 
Share this answer
 
Comments
Member 13542004 19-Dec-17 7:53am    
hi, first of all I like your solution a lot! but I'm still trying to understand some of it. according to this https://en.wikipedia.org/wiki/Win32_Thread_Information_Block FS:[0x24] is the location of the thread id, so why adding 36?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900