c++ how do i get the current console conhost process - c++

i have searched on so many websites after "how i get the conhost process", and nothing is really what i'm looking for.
i have searched on.
superuser/stackoverflow when-is-conhost-exe-actually-necessary
stackoverflow how-can-a-win32-process-get-the-pid-of-its-parent
stackoverflow c-how-to-fetch-parent-process-id
stackoverflow c-how-to-determine-if-a-windows-process-is-running
stackoverflow get-full-running-process-list-visual-c
stackoverflow ms-c-get-pid-of-current-process
stackoverflow get-list-of-dlls-loaded-in-current-process-with-their-reference-counts
codeproject Get-Parent-Process-PID
cplusplus Getting list of running processes
msdn.microsoft GetModuleFileNameEx
msdn.microsoft GetModuleFileName
msdn.microsoft GetCurrentProcessId
msdn.microsoft GetProcessId
msdn.microsoft GetModuleHandle
msdn.microsoft GetConsoleWindow
msdn.microsoft Tool Help
msdn.microsoft CreateToolhelp32Snapshot
msdn.microsoft NextModule32
msdn.microsoft DebugActiveProcess
msdn.microsoft Enumerating All Modules For a Process
and i can't find anything about "how to get the conhost process".
i have some code that works for the current "cmd.exe / program.exe" and that gives me the "PID, NAME, PATH, READ/WRITE ADDRESS".
i can get the parent process but that is not conhost.exe.
code "need to link library 'psapi' first":
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
#include <tlhelp32.h>
int PrintModules(DWORD processID) {
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
printf( "\nProcess ID: %u\n", processID);
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if(NULL == hProcess) return 1;
if(EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
for(i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
TCHAR szModName[MAX_PATH];
if(GetModuleFileNameEx(hProcess, hMods[i], szModName,sizeof(szModName) / sizeof(TCHAR))) {
_tprintf( TEXT(" %s (0x%08X)\n"), szModName, hMods[i]);
}
}
}
CloseHandle(hProcess);
return 0;
}
int main(void) {
DWORD cpid = GetCurrentProcessId();
PrintModules(cpid);
int ppid = -1;
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(h, &pe)) {
do {
if(pe.th32ProcessID == cpid) {
printf("PID: %i; PPID: %i\n", cpid, pe.th32ParentProcessID);
ppid = pe.th32ParentProcessID;
}
} while(Process32Next(h, &pe));
}
PrintModules(ppid);
CloseHandle(h);
std::cin.get();
return 0;
}
and i can't figure out a way to get the current conhost process.
when you open a program that uses the console, a conhost.exe process is created.
and my question is how do i get that conhost.exe process...
Thanks! :)

In case you still need it (after reading the comments), here's a piece of code that gets the conhost.exe processes. Please note that I only wrote it for demonstrative purposes (to check whether [MSDN]: Tool Help Functions can be used for this scenario), so don't mind its structure or other coding NO-NOs.
code.c:
#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
int main(int argc, char **argv) {
DWORD pid = 0, i = 0, cPid = 0;
PROCESSENTRY32 pe32;
BOOL res = FALSE;
HANDLE snap = INVALID_HANDLE_VALUE, proc = INVALID_HANDLE_VALUE;
char c = 0;
if (argc > 1) {
pid = atoi(argv[1]);
} else {
pid = GetCurrentProcessId();
}
printf("PID: %d\n", pid);
snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
if (snap == INVALID_HANDLE_VALUE) {
printf("CreateToolhelp32Snapshot failed: %d\n", GetLastError());
return -1;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
res = Process32First(snap, &pe32);
if (res == FALSE) {
printf("Process32First failed: %d\n", GetLastError());
CloseHandle(snap);
return -2;
}
do {
if (_tcscmp(pe32.szExeFile, TEXT("conhost.exe")) == 0) {
_tprintf(TEXT(" Idx: %02d PID: %5d PPID: %5d Name: %s\n"), i++, pe32.th32ProcessID, pe32.th32ParentProcessID, pe32.szExeFile);
if (pe32.th32ParentProcessID == pid) {
cPid = pe32.th32ProcessID;
}
}
} while ((res = Process32Next(snap, &pe32)));
CloseHandle(snap);
if ((proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, cPid)) == INVALID_HANDLE_VALUE) {
printf("OpenProcess failed: %d\n", GetLastError());
return -3;
}
printf("Conhost handle: 0x%08X\n", proc);
CloseHandle(proc);
printf("Press a key to exit...\n");
c = getch();
return 0;
}
Output (as a VStudio 2010, Console App (Debug - x86) on Win 10):
e:\Work\Dev\StackOverflow\q035102238>ver
Microsoft Windows [Version 10.0.17134.48]
e:\Work\Dev\StackOverflow\q035102238>"Debug\q035102238.exe"
PID: 22388
Idx: 00 PID: 19892 PPID: 20164 Name: conhost.exe
Idx: 01 PID: 21128 PPID: 21120 Name: conhost.exe
Idx: 02 PID: 1144 PPID: 20572 Name: conhost.exe
Idx: 03 PID: 8184 PPID: 19572 Name: conhost.exe
Idx: 04 PID: 10976 PPID: 20608 Name: conhost.exe
Idx: 05 PID: 21284 PPID: 8792 Name: conhost.exe
Idx: 06 PID: 8172 PPID: 20444 Name: conhost.exe
Idx: 07 PID: 4396 PPID: 19484 Name: conhost.exe
Idx: 08 PID: 12484 PPID: 2580 Name: conhost.exe
Idx: 09 PID: 18636 PPID: 11552 Name: conhost.exe
Idx: 10 PID: 21456 PPID: 21016 Name: conhost.exe
Idx: 11 PID: 960 PPID: 3528 Name: conhost.exe
Idx: 12 PID: 20616 PPID: 18404 Name: conhost.exe
Idx: 13 PID: 21548 PPID: 21528 Name: conhost.exe
Idx: 14 PID: 20192 PPID: 8316 Name: conhost.exe
Idx: 15 PID: 2496 PPID: 9284 Name: conhost.exe
Idx: 16 PID: 5820 PPID: 23140 Name: conhost.exe
Idx: 17 PID: 6032 PPID: 26512 Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...
So, it is possible to enumerate all running conhost.exe processes, and also get PROCESS_ALL_ACCESS to the one associated with my current application (I have to mention here that my Win user has full administrative privileges).
#EDIT0:
As #BladeMight noticed, on Win 7 all conhost.exe processes are children of crss.exe (as it can be also seen in ProcExp)
Output:
c:\Work\Dev\StackOverflow\q035102238>ver
Microsoft Windows [Version 6.1.7601]
c:\Work\Dev\StackOverflow\q035102238>q035102238.exe
PID: 1548
Idx: 00 PID: 4960 PPID: 3472 Name: conhost.exe
Idx: 01 PID: 5024 PPID: 3472 Name: conhost.exe
Idx: 02 PID: 5076 PPID: 3472 Name: conhost.exe
Idx: 03 PID: 2676 PPID: 3472 Name: conhost.exe
Idx: 04 PID: 1888 PPID: 3472 Name: conhost.exe
Connhost handle: 0x00000000
Press a key to exit...

One method that comes to mind is to obtain the start time of the CMD.EXE process. Then iterate through all of the CONHOST processes looking for the same (or very close) start time.
As a proof of concept download and install Process Explorer. Find your CMD.EXE process in ProcExp, then look at Properties, Image tab. Note the start time. Then look through each CONHOST process looking for one that starts at the same time.
Note that ProcExp displays 1 second resolution, but whatever underlying API ProcExp uses probably has better resolution.
You may need to google some to get an idea what API(s) ProcExp uses to gather the process start time. Additionally there are a variety of tools you can use to see what APIs an executable (ProcExp in this case) import. You may be able to deduce from the API names that ProcExp imports which one(s) would provide a process' start time.

Some unbelievably convoluted answers here. Use process explorer to get the pid of the console application and then do the following in kd -kl
lkd> !process 0n16592 0
Searching for Process with Cid == 40d0
Cid handle table at fffff8a001db8000 with 4368 entries in use
PROCESS fffffa8042eb9590
.
.
.
lkd> .process /P fffffa8042eb9590
Implicit process is now fffffa80`42eb9590
lkd> !peb
PEB at 000007fffffd3000
.
.
.
ProcessParameters: 0000000000202880
.
.
.
lkd> dt nt!_RTL_USER_PROCESS_PARAMETERS 0000000000202880
.
.
.
+0x010 ConsoleHandle : 0x00000000`00003d98 Void
+0x018 ConsoleFlags : 0
+0x020 StandardInput : 0x00000000`00000003 Void
+0x028 StandardOutput : 0x00000000`00000007 Void
+0x030 StandardError : 0x00000000`0000000b Void
.
.
.
.
lkd> ? 0x3d98
Evaluate expression: 15768 = 00000000`00003d98
This is the pid of the conhost process that it is attached to. In C++, you'd have to get the current PEB, take a look at how that is done programmatically here, study the structure of the PEB and ParameterBlock and then you'll know how to get the parameter block and at what offset it is in the parameter block. You can use the type definition for _PEB and _RTL_USER_PROCESS_PARAMETERS in winternl.h or the one here, or write your own using the ntkrnlmp.pdb symbols.

Related

Message id's in the main application loop

I've written a simple Win32 App in Visual Studio 2019 on Win 10. In the main message loop inside the WinMain function i have:
while (Msg.message != WM_QUIT) {
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
swprintf_s(msgbuf, _T("In the PeekMessage loop cnt: %d, msg: %d\n"), loop_cnt++, Msg.message);
OutputDebugString(msgbuf);
}
...
}
I get following output:
In the PeekMessage loop cnt: 0, msg: 799
In the PeekMessage loop cnt: 1, msg: 49300
In the PeekMessage loop cnt: 2, msg: 96
In the PeekMessage loop cnt: 3, msg: 96
In the PeekMessage loop cnt: 4, msg: 275
In the PeekMessage loop cnt: 5, msg: 275
...
The odd is that the messages id's returned to the output like 799 or 49300 doesn't exist in the WinUser.h! So my question is what that messages are and where it comes from?
799 is WM_DWMNCRENDERINGCHANGED.
49300 is a registered message (i.e. its value is in the range 0xC000-0xFFFF).

When a child process is created with fork, the parent ID is not as the same as the parent ID [duplicate]

This question already has answers here:
Why getppid() from the child return 1
(2 answers)
Closed 6 years ago.
In order to explain the question I'm asking let's consider this code,
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t child, parent;
parent = getpid();
printf("Main parent pid: %d\n",parent );
if((child = fork()) < 0) {
printf("Error\n");
} else if(child == 0 ) {
printf("A Child process is created, pid: %d, ppid: %d \n",
getpid(), getppid());
} else if(child > 0) {
printf("Parent says: Child pid: %d, getpid: %d, getppid: %d\n",
child, getpid(), getppid());
}
return 0;
}
When I execute this code on terminal I get such an output
Main pid: 711
Parent says: Child pid: 712, getpid: 711, getppid: 598
A Child process is created, pid: 712, ppid: 1
As far as I understand, when I'm creating a new process by forking from a already created process, the parent of this new process must the process that I have forked.Hovewer, as you can see from the output, the parent process ID of the child is 1, i.e the init process, so why is that so ? Is my understand wrong, or there is some other things that I'm not seeing ?
Note: I'm working on Mac OSX.
The problem is that the parent process (711) has died and the child process inherited by the init process (1) before it gets to report. If you have the parent wait for the child to die before exiting itself, you'll see the result you expect.
To demonstrate:
#include <sys/wait.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
pid_t child, parent;
parent = getpid();
printf("Main parent pid: %d\n", (int)parent);
if ((child = fork()) < 0)
{
printf("Error\n");
}
else if (child == 0)
{
printf("A Child process is created, pid: %d, ppid: %d\n",
(int)getpid(), (int)getppid());
}
else if (child > 0)
{
printf("Parent says: Child pid: %d, getpid: %d, getppid: %d\n",
(int)child, (int)getpid(), (int)getppid());
#ifndef DO_NOT_WAIT_FOR_CHILD
int status;
int corpse = wait(&status);
printf("Child %d exited with status 0x%.4X\n", corpse, status);
#endif
}
return 0;
}
When compiled without -DDO_NOT_WAIT_FOR_CHILD, I got the sample output:
Main parent pid: 77646
Parent says: Child pid: 77647, getpid: 77646, getppid: 46383
A Child process is created, pid: 77647, ppid: 77646
Child 77647 exited with status 0x0000
When compiled with -DDO_NOT_WAIT_FOR_CHILD, I got the sample output:
Main parent pid: 77662
Parent says: Child pid: 77663, getpid: 77662, getppid: 46383
A Child process is created, pid: 77663, ppid: 1

Strange Parent ID

I am using two forks in my code:
int main()
{
cout<<"Main Process ID is: "<<getpid()<<endl;
int processID;
processID = fork();
cout<<"Part 1"<<endl;
cout<<"PID is: "<<getpid()<<" Child PID: "<<processID<<" Parent PID: "<<getppid()<<endl;
processID = fork();
cout<<"Part 2"<<endl;
cout<<"PID is: "<<getpid()<<" Child PID: "<<processID<<" Parent PID: "<<getppid()<<endl;
return 0;
}
But there are some strange "Parent ID" for "children". Why? (Please refer to screenshot below)
Thanks a lot in advance.
In your case the parent executed first, hence got eventually terminated. In this case child become orphan and hence it's parent id got replaced with the id of other process in same group or the child got re-parented.Hence, the parent id is different(strange).

How would I check for child process changing state but not terminating?

I'm using waitpid to get status code returned by the child when it changes state. I'm using:
if (WIFEXITED(code)){
if (WEXITSTATUS(code)==0){
//worked correctly
}
else{
//failed, throw error
}
}
else{
..
}
In the bottom part, I want to check for whether the child changed state without terminating and wait for it to terminate using a loop. How can I do so?
Assuming you don't ptrace the child process, you have to wait for it with the WUNTRACED and WCONTINUED flags:
waitpid(pid, &code, WUNTRACED | WCONTINUED);
If you do ptrace it, WUNTRACED is unnecessary, but since ptrace is a different kettle of fish altogether, I'll not go into it in detail.
Then, you can check what happened like so:
if (WIFEXITED(code)) {
// process ended normally with exit status WEXITSTATUS(code)
} else if(WIFSIGNALLED(code)) {
// process was terminated by signal WTERMSIG(code)
} else if(WIFSTOPPED(code)) {
// child was stopped by signal WSTOPSIG(code)
} else if(WIFCONTINUED(code)) {
// child was continued
}
To get a feeling for the way this works, you can play around with this piece of code:
#include <stddef.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
if(pid == -1) {
fputs("fork failed\n", stderr);
} else if(pid == 0) {
int i;
for(i = 0; i < 100; ++i) {
usleep(1000000);
puts("child");
}
} else {
int status;
printf("%d\n", pid);
do {
waitpid(pid, &status, WUNTRACED | WCONTINUED);
printf("exited: %d status: %d\n"
"signalled: %d signal: %d\n"
"stopped: %d signal: %d\n"
"continued: %d\n",
WIFEXITED(status),
WEXITSTATUS(status),
WIFSIGNALED(status),
WTERMSIG(status),
WIFSTOPPED(status),
WSTOPSIG(status),
WIFCONTINUED(status));
} while(!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 0;
}
This will fork, the parent process will print the process ID of the child process, and when you send the child process signals, the parent will print the status properties it gets from waitpid (not all of them will make sense, naturally; if the process is stopped, WTERMSIG does not return anything meaningful). Here's my example output from a session in which I sent the child process SIGSTOP, SIGCONT, and SIGTERM:
38167
child
child
child
child
exited: 0 status: 19
signalled: 0 signal: 127
stopped: 1 signal: 19
continued: 0
exited: 0 status: 255
signalled: 0 signal: 127
stopped: 0 signal: 255
continued: 1
child
child
child
exited: 0 status: 0
signalled: 1 signal: 15
stopped: 0 signal: 0
continued: 0

Listing Windows Processes and Modules

So I've been messing around with Windows API lately, and I've encountered an issue that I need a little assistance with. Actually, to be precise, there are two issues.
I will first show the code and then explain the difficulties that I am experiencing:
#pragma once
#pragma comment(lib, "Psapi.lib")
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
void ProcessError(DWORD error);
int main() {
FILE* file = fopen("C:\\Users\\Administrator\\Desktop\\processes.txt", "w");
DWORD count, i, modulesCount;
WCHAR buffer[128] = {0};
HMODULE modules[128] = {0};
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(PROCESSENTRY32);
count = 0;
if(snapshot != INVALID_HANDLE_VALUE) {
if(!Process32First(snapshot, &pEntry)) {
ProcessError(GetLastError());
CloseHandle(snapshot);
ExitProcess(EXIT_FAILURE);
}
do {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pEntry.th32ProcessID);
GetModuleFileNameEx(hProc, NULL, (LPWSTR)memset(buffer, 0, 128), 128);
fwprintf(file, L"-------------------------------------------------------\n");
fwprintf(file, L"%s\t pid: %d\n", pEntry.szExeFile, pEntry.th32ProcessID);
fwprintf(file, L"%s\n", buffer);
if(hProc != INVALID_HANDLE_VALUE) {
if(EnumProcessModules(hProc, (HMODULE*)memset(modules, 0, 128), 128, &modulesCount)) {
modulesCount = modulesCount <= 128 ? modulesCount : 128;
for(i = 0; i < modulesCount; ++i) {
GetModuleFileName(modules[i], (LPWSTR)memset(buffer, 0, 128), 128);
if(wcslen(buffer) > 0) {
fwprintf(file, L"\t\t0x%X Module: %s\n", modules[i], buffer);
}
}
}
else {
ProcessError(GetLastError());
}
CloseHandle(hProc);
}
else {
ProcessError(GetLastError());
}
count++;
} while(Process32Next(snapshot, &pEntry));
fwprintf(file, L"Process count: %d\n", count);
}
else {
ProcessError(GetLastError());
CloseHandle(snapshot);
ExitProcess(EXIT_FAILURE);
}
fclose(file);
CloseHandle(snapshot);
ExitProcess(EXIT_SUCCESS);
}
void ProcessError(DWORD error) {
printf("Error in thread 0x%X, code: 0x%X\n", GetThreadId(GetCurrentThread()), error);
}
So, the first issue has to do with the following:
if(EnumProcessModules(hProc, (HMODULE*)memset(modules, 0, 128), 128, &modulesCount))
Sometimes I get an INVALID_HANDLE error, and I don't really know why. The Process handle is not invalid, nor is any other parameter passed to the function. If somebody could explain to me or at least point me in some direction (which is more preferred solution, since I am more interested to learn :D) it would do me good.
Second is that for some reason, when I enumerate process' modules and GetModuleFileName() it also includes the location of the current process.
I would get the following when I write to the file:
TuneUpUtilitiesApp32.exe pid: 2744
D:\Program Files\TuneUp Utilities 2012\TuneUpUtilitiesApp32.exe
0x76F60000 Module: C:\Windows\SYSTEM32\ntdll.dll
0x75FE0000 Module: C:\Windows\system32\kernel32.dll
0x75370000 Module: C:\Windows\system32\KERNELBASE.dll
0x761A0000 Module: C:\Windows\system32\USER32.dll
0x770D0000 Module: C:\Windows\system32\GDI32.dll
0x77130000 Module: C:\Windows\system32\LPK.dll
0x76EC0000 Module: C:\Windows\system32\USP10.dll
0x75F20000 Module: C:\Windows\system32\msvcrt.dll
0x755D0000 Module: C:\Windows\system32\ADVAPI32.dll
0x75590000 Module: C:\Windows\SYSTEM32\sechost.dll
0x757D0000 Module: C:\Windows\system32\RPCRT4.dll
0x77120000 Module: C:\Windows\system32\PSAPI.DLL
0x755B0000 Module: C:\Windows\system32\IMM32.DLL
0x75670000 Module: C:\Windows\system32\MSCTF.dll
0x10000000 Module: C:\Windows\system32\guard32.dll
0x750D0000 Module: C:\Windows\system32\VERSION.dll
0x750C0000 Module: C:\Windows\system32\fltlib.dll
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
It literally does that for every process that I can extract modules from. Any help would be much appreciated!
You are not using the returned "modulesCount" correctly. It is not the number of modules, it is the size of the array in bytes. You'll need to divide by sizeof(HMODULE) to get the number of modules.
The second problem is that you hope that the pEntry.th32ProcessID is still valid when you start iterating the process entries. That's idle hope, a process can terminate while you are iterating. You don't check for this, you don't verify if OpenProcess() returns a valid handle. It may also fail because you don't have enough permissions to access the process.
Focus on what CreateToolhelp32Snapshot() can do, it also supports Module32First/Next(). It will be more reliable because of the function's ability to create a snapshot.