Message id's in the main application loop - c++

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).

Related

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

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.

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

Windows: PeekMessage loop anomaly

Here's a code snippet from a project I am currently working on:
MSG msg;
bool msgAvail = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
while(msgAvail)
{
TranslateMessage(&msg);
...
...
msgAvail = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
}
While analyzing a customer crash dump, I found that the call to TranslateMessage() has the parameter as NULL. I am confused as to how could &msg become NULL in the above scenario. Could someone explain what could be happening in the above code due to which the address of msg is becoming NULL?

Peekmessage (creating window loop)

Igot this error and I don't know why, I just follow correctly what he do, and he doesn't get this error. Here is the code.
//Main application loop
MSG msg = {0};
while(WM_QUIT != msg.message())
{
if(PeekMessage(&msg, NULL, NULL, NULL, PM_Remove))
{
//Translate message
TranslateMessage(&msg);
//Dispatch message
DispatchMessage(&msg);
}
}
And here are the error:
error C2064: term does not evaluate to a function taking 0 arguments
fatal error C1903: unable to recover from previous error(s); stopping compilation
And when I clicked it, they all pointing to the while loop.
The message member of the MSG structure is a field, not a method. You should access it instead of calling it:
while (WM_QUIT != msg.message) {
// ...
}
There are other issues in your code snippet. First, C++ is a case-sensitive language, so the last argument to PeekMessage() should be PM_REMOVE instead of PM_Remove.
In addition, PeekMessage() does not block if the message queue is empty, so your code will end up consuming 100% of the CPU core it runs on. You can use GetMessage() instead, which blocks if no message is available and would allow you to remove the explicit test for WM_QUIT:
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

The PeekMessage function in C++ and named pipes

Regarding:
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
If hWnd is NULL, PeekMessage retrieves
messages for any window that belongs
to the current thread, and any
messages on the current thread's
message queue whose hwnd value is NULL
(see the MSG structure). Therefore if
hWnd is NULL, both window messages and
thread messages are processed.
Are messages received via a named pipe included in window messages and thread messages?
Definitely not. Named pipes do not send window messages.
The thread messages in this context are special and have nothing to do with named pipes.
Use MsgWaitForMultipleObjects instead.
CODE SAMPLE:
void MessageLoop(HANDLE hNamedPipe)
{
do {
DWORD res = MsgWaitForMultipleObjects(1, &hNamedPipe, INFINITE, QS_ALLEVENTS, MWMO_INPUTAVAILABLE);
if (res == WAIT_OBJECT_0) {
/* Handle named pipe -- at this point ReadFile will not block */
} else if (res == WAIT_OBJECT_0 + 1) {
MSG msg;
if (!GetMessage(&msg, NULL, 0, 0))
break; /* WM_QUIT */
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (1);
}
No, Windows messages and named pipes are completely unrelated. You would need to use the MsgWaitForMultipleObjectsEx function to wait for either an incoming message or a message on the named pipe.
Note that MsgWaitForMultipleObjectsEx doesn't actually retrieve the message; check its return value to see if there's a Windows message or data on the named pipe, then use GetMessage or ReadFile as appropriate.