Windows: PeekMessage loop anomaly - c++

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?

Related

Windows C++ -- Using DeviceIoControl to return a product string

I am trying to return the "product string" for a HID using DeviceIoControl in Windows. Here is my code:
for (int i = 0; i < nDevices; i++)
{
wchar_t* productString = new wchar_t[POINTER_DEVICE_PRODUCT_STRING_MAX];
HANDLE potentialUsbDevice = CreateFile(devInfoDataBuffer[i]->DevicePath, GENERIC_READ,
NULL,
NULL,
OPEN_EXISTING,
0,
NULL);
if (potentialUsbDevice != INVALID_HANDLE_VALUE) {
DeviceIoControl(potentialUsbDevice, IOCTL_HID_GET_PRODUCT_STRING, 0, 0, productString, 0, 0, 0);
wprintf(L"%s", productString);
}
delete[] productString;
CloseHandle(potentialUsbDevice);
}
Unfortunately, I am not getting anything human-readable. Is there something wrong with my function call or is it an issue of formatting?
Thank you for your help and consideration on this topic.
You need to pass the size of the output buffer (in bytes) to DeviceIoControl. You also need to pass lpBytesReturned as non-NULL:
DWORD bytes_returned;
DeviceIoControl (potentialUsbDevice, IOCTL_HID_GET_PRODUCT_STRING, 0, 0,
productString, POINTER_DEVICE_PRODUCT_STRING_MAX * sizeof (wchar_t),
&bytes_returned, 0);
Also, check for errors (not shown in my code for brevity) and call CloseHandle inside your if statement.

Handle firefox error message “Cannot load XPCOM” using C++

I'm trying to open Mozilla Firefox using CreateProcess(). However, If Firefox is auto updating while I try to open it, I get the following error message:
Cannot load XPCOM
And I need to restart the application.
Here is the code I'm using:
path = MozillaExePath.c_str();
STARTUPINFO info = { sizeof(STARTUPINFO), NULL, NULL, "FireFox", 0,0,800, 600, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL };
PROCESS_INFORMATION processInfo;
if (CreateProcess(path, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
WaitForSingleObject(processInfo.hProcess, 3000);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
else
{
WriteLogFile("May be error with mozilla firefox...\n");
exit(1);
}
So, how can I handle that error message using C++?
Here is a different way to do this that is working for me:
#include <shellapi.h>
[...]
if (ShellExecute(NULL, TEXT("open"), TEXT("firefox.exe"), NULL, NULL, 0) <= HINSTANCE(32))
{
WriteLogFile("Could not open Mozilla Firefox...\n");
}
Reference:
https://learn.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea

Waitforsingleobject works when trying to open Notepad++ but returns immediately with Firefox

I have the following code that opens an application using CreateProcess and waits for it for a few seconds and then closes it if its not been closed. The same code works OK on notepad++ for example, but not when I try to open Firefox.exe
BOOL CALLBACK SendWMCloseMsg(HWND hwnd, LPARAM lParam)
{
//never gets called when opening Firefox.exe
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == lParam)
SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 30000, NULL);
return TRUE;
}
int main()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
WCHAR szFilename[] = L"C:\\Program Files\\Mozilla Firefox\\firefox.exe";
if (CreateProcess(NULL,
szFilename,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&si,
&pi))
{
CloseHandle(pi.hThread);
WaitForInputIdle(pi.hProcess, INFINITE);
auto a = WaitForSingleObject(pi.hProcess, 30000);
if (a == WAIT_TIMEOUT)
{
EnumWindows(&SendWMCloseMsg, pi.dwProcessId);
if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_TIMEOUT)
{
//never gets here.
TerminateProcess(pi.hProcess, 0);
}
}
//a vlaue is 0 and it never gets in the if statement.
CloseHandle(pi.hProcess);
}
return 0;
}
SendWMCloseMsg does not get called and when I remove the if statement and call EnumWindows(&SendWMCloseMsg, pi.dwProcessId);, it still does not find the correct processId.
What Am I doing wrong with this code and how to address this issue?
I'm using Windows 10, 64bit and VS2015
The answer is that the process you started with CreateProcess created a bunch of other processes - and then quit.
Your WaitForSingleObject completes successfully, and your program ends.

WINAPI - Close mutex without being the owner

I'm trying to close a mutex in another application.
I'm using the WinAPI ("windows.h").
Here's my code to close this mutex:
DWORD pid = 0;
hMyWnd = FindWindow(NULL, "TheFamousWindowName");
GetWindowThreadProcessId(hMyWnd, &pid);
HANDLE hProc = OpenProcess(PROCESS_DUP_HANDLE, 0, pid);
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, false, "TheEvilMutex"); // hMutex isn't null
WaitForSingleObject(hMutex, 10000); // Wait 10 seconds, nothing happens
if (!DuplicateHandle(hProc, hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE)) {
// Arrive always here because of error 288
// And the mutex is still there, not closed
}
ReleaseMutex(hMutex);
CloseHandle(hMutex);
The problem is when I call
DuplicateHandle(hProc, hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE)
I got the error 288 with
GetLastError()
labeled as "Attempt to release mutex not owned by caller" and the mutex isn't closed
Now, I know that I'm not the owner, but I can't see a solution to close this mutex.
I've seen some programs doing it like Process Explorer or Process Hacker. I've looked into the code of this last on GitHub but didn't find anything about how it close a mutex without being the owner.
I've also checked this thread
how does procexp close a mutex held by another process? but I can't get it working.
Thanks for reading me.
Hoping someone could help me.
EDIT :
Thanks to #RbMm, replacing
DuplicateHandle(hProc, hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE)
with
DuplicateHandle((HANDLE)-1, hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE)
solved error 288, but the mutex isn't closed with this.
in call DuplicateHandle(hProc, hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE) hMutex must be handle that is valid in the context of the hProc. but hMutex is handle in current process, not in hProc. so in this line of code you try close arbitrary handle in context of hProc, but not your hMutex. and result of this will be arbitrary. may be you close some handle. may be this handle not exist at all, or handle is protected from close.
And the mutex is still there, not closed
of course it not closed and can not be closed. for close it you need call
DuplicateHandle(NtCurrentProcess(), hMutex, NULL, 0, 0, false, DUPLICATE_CLOSE_SOURCE);
because of error 288
i absolute sure that DuplicateHandle never return this error. ERROR_NOT_OWNER you got from ReleaseMutex(hMutex);
for close mutex in another process - need use handle value of this mutex in target process, not in self process. this code is done work:
void CloseRemote(ULONG dwProcessId, PCWSTR Name)
{
// create any file
HANDLE hFile = OpenMutex(MAXIMUM_ALLOWED, FALSE, Name);
if (hFile != INVALID_HANDLE_VALUE)
{
if (HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId))
{
NTSTATUS status;
ULONG cb = 0x80000;
union {
PSYSTEM_HANDLE_INFORMATION_EX pshi;
PVOID pv;
};
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (pv = LocalAlloc(0, cb))
{
if (0 <= (status = ZwQuerySystemInformation(SystemExtendedHandleInformation, pv, cb, &cb)))
{
if (ULONG_PTR NumberOfHandles = pshi->NumberOfHandles)
{
ULONG_PTR UniqueProcessId = GetCurrentProcessId();
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles = pshi->Handles;
do
{
// search for created file
if (Handles->UniqueProcessId == UniqueProcessId && Handles->HandleValue == (ULONG_PTR)hFile)
{
// we got it !
PVOID Object = Handles->Object;
NumberOfHandles = pshi->NumberOfHandles, Handles = pshi->Handles;
do
{
if (Object == Handles->Object && Handles->UniqueProcessId == dwProcessId)
{
DuplicateHandle(hProcess, (HANDLE)Handles->HandleValue, 0, 0, 0, 0, DUPLICATE_CLOSE_SOURCE);
}
} while (Handles++, --NumberOfHandles);
break;
}
} while (Handles++, --NumberOfHandles);
}
}
LocalFree(pv);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
CloseHandle(hProcess);
}
CloseHandle(hFile);
}
}

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);
}