Graceful application shutdown when Windows shuts down - windows

I have an application that I'd like to shutdown gracefully when Windows shuts down (or user logs off). This used to work (in xp) but sometime in the last year it broke without anyone noticing. It's also broke (but differently) under Windows 7.
Our product has a main process (server.exe) that starts many other processes. A graceful shutdown would have server.exe asking all of the process that it starts to shut down. However, when I debug this code it seems that the other processes have already been terminated. Our main process (server.exe) is the only process that is handling the WM_QUERYENDSESSION and the WM_ENDSESSION messages. Code below (this used to work under XP but doesn't any more):
LRESULT CALLBACK master_wnd_proc
(
HWND hwnd, /* (in) handle to window */
UINT uMsg, /* (in) message identifier */
WPARAM wParam, /* (in) first message parameter */
LPARAM lParam /* (in) second message parameter */
)
{
LRESULT result; /* return value */
long msg_code;
switch (uMsg)
{
case WM_ENDSESSION:
if (wParam)
{
msg_code = PCS_WINDOWS_SHUTDOWN;
if( lParam & 0x01L )
msg_code = WINDOWS_SHUT_CLOSE;
if( lParam & 0x40000000L )
msg_code = WINDOWS_SHUT_CRIT;
if( (unsigned long)lParam & 0x80000000 )
msg_code = WINDOWS_SHUT_LOGOFF;
MsgGenerate(msg_code, MSG_SEVERE, MSG_LOG, "");
ipc_declare_shutdown( msg_code );
//We need one more message in the message queue
//to force the message loop, below, to exit.
PostQuitMessage(EXIT_SUCCESS);
/* WARNING: Don't call MsgGenerate() after this point! */
}
result = 0;
break;
case WM_QUERYENDSESSION:
/* return TRUE to say "okay to shutdown"
* If FALSE is returned, then other processes are not stopped
* and the session isn't ended.
*/
result = TRUE;
break;
/* for a Windows TIMER or for an IPC prompt, handle
* the old server code and tcall messages and
* once-per-second work. Notice that the
* once-per-second work could just be done on the WM_TIMER
* and the tcall work could just be done on the WM_APP_IPC_POSTED
* but I've merged them together here. The merge isn't
* necessary to fix a bug or anything, but rather to
* make the code more robust in the face of unexpected
* conditions.
*/
case WM_TIMER:
case WM_APP_IPC_POSTED:
/* now handle tcall messages */
(void) server();
result = FALSE;
break;
default:
result = DefWindowProc (hwnd, uMsg, wParam, lParam);
break;
}
return result;
}
It seems as though we've changed something in the last year the would require all the child processes to handle the WM_QUERYENDSESSION message (I'd really like to avoid this). I don't seem to be able to find any any information as to when processes do or don't get this message.
I've make it work under Windows 7 using the new API but would like to figure out why it's broke under XP so I can have a solution that works for both OS's.
Any help?

Things changed around Vista time, not so sure how that would affect your code. The best thing to do is to not leave it up to Windows to determine the shutdown order. Just ask it to have your server get the shutdown notification before the helper processes:
DWORD dwLevel, dwFlags;
BOOL fOkay = GetProcessShutdownParameters(&dwLevel, &dwFlags);
ASSERT(fOkay);
if (fOkay && dwLevel > 0x100) {
fOkay = SetProcessShutdownParameters(dwLevel + 1, SHUTDOWN_NORETRY);
ASSERT(fOkay);
}

Related

How does reciprocal SendMessage-ing between two applications work?

Suppose I have 2 applications, A and B. Each one of them creates one window in the main thread, and has no other threads.
When the "close" button of the window of application A is pressed, the following happens:
Application A receives a WM_CLOSE message and handles it like:
DestroyWindow(hWnd_A);
return 0;
On WM_DESTROY application A behaves like:
SendMessage(hWnd_B, WM_REGISTERED_MSG, 0, 0); //key line!!
PostQuitMessage(0);
return 0;
On WM_REGISTERED_MSG application B runs:
SendMessage(hWnd_A, WM_ANOTHER_REGISTERED_MSG, 0, 0);
return 0;
On WM_ANOTHER_REGISTERED_MSG application A runs:
OutputDebugString("Cannot print this");
return 0;
And that's it.
From MSDN, I read that when a message is sent to a window created by another thread, the calling thread is blocked, and it can only process non-queued messages.
Now, since the above code works and does not hang, I guess that the call to SendMessage from application B (point 3) sends a non-queued message to application A's window procedure, which processes it in the context of application B's main thread. Indeed, no debug output is displayed with OutputDebugString in point 4.
This is also proved by the fact that replacing SendMessage with SendMessageTimeout with the SMTO_BLOCK flag in the key line of point 2, makes the whole thing actually block. (See documentation of SendMessage)
Then, my questions are:
Actually, are non-queued messages just simple direct calls to the window procedure made by SendMessage in process B?
How does SendMessage know when to send queued or non-queued messages?
UPDATE
Still, I do not understand how does A process WM_ANOTHER_REGISTERED_MSG. What I would expect is that when that message is sent, A's thread should be waiting for its call to SendMessage to return.
Any insight?
SUGGESTION FOR THE READERS
I would suggest to read Adrian's answer as an introduction to RbMm's one, which follows the same line of thought, but goes more in detail.
the described behavior really work well.
How does SendMessage know when to send queued or non-queued
messages?
from Nonqueued Messages
Some functions that send nonqueued messages are ... SendMessage
...
so SendMessage simply always send nonqueued messages.
and from SendMessage documentation:
However, the sending thread will process incoming nonqueued messages
while waiting for its message to be processed.
this mean that window procedure can be called inside SendMessage call. and process incoming messages sent via SendMessage from another thread. how this is implemented ?
when we call SendMessage message to another thread window, it enter to kernel mode. kernel mode always remember usermode stack pointer. and we switched to kernel stack. when we return from kernel to user mode - kernel usually return back to point, from where user mode called it and to saved stack. but exist and exceptions. one of this:
NTSYSCALLAPI
NTSTATUS
NTAPI
KeUserModeCallback
(
IN ULONG RoutineIndex,
IN PVOID Argument,
IN ULONG ArgumentLength,
OUT PVOID* Result,
OUT PULONG ResultLenght
);
this is exported but undocumented api. however it all time used by win32k.sys for call window procedure. how this api worked ?
first of all it allocate additional kernel stack frame below current. than it take saved user mode stack pointer and copy some data (arguments) below it. finally we exit from kernel to user mode, but not to point, from where kernel was called but for special ( exported from ntdll.dll) function -
void
KiUserCallbackDispatcher
(
IN ULONG RoutineIndex,
IN PVOID Argument,
IN ULONG ArgumentLength
);
and stack was below stack pointer, from where we enter kernel early.
KiUserCallbackDispatcher call RtlGetCurrentPeb()->KernelCallbackTable[RoutineIndex](Argument, ArgumentLength) - usually this is some function in user32.dll. this function already call corresponded window procedure. from window procedure we can call kernel back - because KeUserModeCallback allocate additional kernel frame - we will be enter to kernel inside this frame and not damage previous. when window procedure return - again special api called
__declspec(noreturn)
NTSTATUS
NTAPI
ZwCallbackReturn
(
IN PVOID Result OPTIONAL,
IN ULONG ResultLength,
IN NTSTATUS Status
);
this api (if no error) must never return - in kernel side - the allocated kernel frame is de-allocated and we return to previous kernel stack inside KeUserModeCallback. so we finally return from point, from where KeUserModeCallback was called. then we back to user mode, exactly from point where we call kernel, on same stack.
really how is window procedure is called inside call to GetMessage ? exactly by this. call flow was:
GetMessage...
--- kernel mode ---
KeUserModeCallback...
push additional kernel stack frame
--- user mode --- (stack below point from where GetMessage enter kernel)
KiUserCallbackDispatcher
WindowProc
ZwCallbackReturn
-- kernel mode --
pop kernel stack frame
...KeUserModeCallback
--- user mode ---
...GetMessage
exactly the same was with blocking SendMessage.
so when thread_A send message_1 to thread_B via SendMessage - we enter to kernel, signal gui event_B, on which thread_B waited. and begin wait on gui event_A for current thread. if thread_B executes message retrieval code (call GetMessage or PeekMessage ) KeUserModeCallback called in thread_B. as result executed it window procedure. here it call SendMessage to send some message_2 to thread_A back. as result we set event_A on which thread_A wait and begin wait on event_B. thread_A will be awaken and call KeUserModeCallback. it Window procedure will be called with this message. when it return (assume this time we not more call SendMessage) we again signal back event_B and begin wait on event_A.
now thread_B return from SendMessage and then return from window procedure - finalize handle original message_1. will be event_A set. thread_A awaken and return from SendMessage. call flow will be next:
thread_A thread_B
----------------------------------------------------
GetMessage...
wait(event_B)
SendMessage(WM_B)...
set(event_B)
wait(event_A)
begin process WM_B...
KeUserModeCallback...
KiUserCallbackDispatcher
WindowProc(WM_B)...
SendMessage(WM_A)...
set(event_A)
wait(event_B)
begin process WM_A...
KeUserModeCallback...
KiUserCallbackDispatcher
WindowProc(WM_A)...
...WindowProc(WM_A)
ZwCallbackReturn
...KeUserModeCallback
set(event_B)
...end process WM_A
wait(event_A)
...SendMessage(WM_A)
...WindowProc(WM_B)
ZwCallbackReturn
...KeUserModeCallback
set(event_A)
...end process WM_B
wait(event_B)
...SendMessage(WM_B)
...GetMessage
also note that when we handle WM_DESTROY message - window is still valid and call process incoming messages. we can implement next demo: at first we not need 2 processes. absolute enough single process with 2 threads. and special registered message here not need. why not use say WM_APP as test message ?
thread_A from self WM_CREATE create thread_B and pass own window handle to it.
thread_B create self window, but on WM_CREATE simply return -1 (for fail create window)
thread_B from WM_DESTROY call SendMessage(hwnd_A, WM_APP, 0, hwnd_B) (pass self hwnd as lParam)
thread_A got WM_APP and call SendMessage(hwnd_B, WM_APP, 0, 0)
thread_B got WM_APP (so WindowProc was recursively called, on stack bellow WM_DESTROY
thread_B print "Cannot print this" and return self ID to thread_A
thread_A returned from call SendMessage and return self ID to thread_B
thread_B returned from call SendMessage inside WM_DESTROY
ULONG WINAPI ThreadProc(PVOID hWnd);
struct WNDCTX
{
HANDLE hThread;
HWND hWndSendTo;
};
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WNDCTX* ctx = reinterpret_cast<WNDCTX*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
switch (uMsg)
{
case WM_NULL:
DestroyWindow(hWnd);
break;
case WM_APP:
DbgPrint("%x:%p>WM_APP:(%p, %p)\n", GetCurrentThreadId(), _AddressOfReturnAddress(), wParam, lParam);
if (lParam)
{
DbgPrint("%x:%p>Send WM_APP(0)\n", GetCurrentThreadId(), _AddressOfReturnAddress());
LRESULT r = SendMessage((HWND)lParam, WM_APP, 0, 0);
DbgPrint("%x:%p>SendMessage=%p\n", GetCurrentThreadId(), _AddressOfReturnAddress(), r);
PostMessage(hWnd, WM_NULL, 0, 0);
}
else
{
DbgPrint("%x:%p>Cannot print this\n", GetCurrentThreadId(), _AddressOfReturnAddress());
}
return GetCurrentThreadId();
case WM_DESTROY:
if (HANDLE hThread = ctx->hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
if (HWND hWndSendTo = ctx->hWndSendTo)
{
DbgPrint("%x:%p>Send WM_APP(%p)\n", GetCurrentThreadId(), _AddressOfReturnAddress(), hWnd);
LRESULT r = SendMessage(hWndSendTo, WM_APP, 0, (LPARAM)hWnd);
DbgPrint("%x:%p>SendMessage=%p\n", GetCurrentThreadId(), _AddressOfReturnAddress(), r);
}
break;
case WM_NCCREATE:
SetLastError(0);
SetWindowLongPtr(hWnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams));
if (GetLastError())
{
return 0;
}
break;
case WM_CREATE:
if (ctx->hWndSendTo)
{
return -1;
}
if (ctx->hThread = CreateThread(0, 0, ThreadProc, hWnd, 0, 0))
{
break;
}
return -1;
case WM_NCDESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
static const WNDCLASS wndcls = {
0, WindowProc, 0, 0, (HINSTANCE)&__ImageBase, 0, 0, 0, 0, L"lpszClassName"
};
ULONG WINAPI ThreadProc(PVOID hWndSendTo)
{
WNDCTX ctx = { 0, (HWND)hWndSendTo };
CreateWindowExW(0, wndcls.lpszClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, &ctx);
return 0;
}
void DoDemo()
{
DbgPrint("%x>test begin\n", GetCurrentThreadId());
if (RegisterClassW(&wndcls))
{
WNDCTX ctx = { };
if (CreateWindowExW(0, wndcls.lpszClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, &ctx))
{
MSG msg;
while (0 < GetMessage(&msg, 0, 0, 0))
{
DispatchMessage(&msg);
}
}
UnregisterClassW(wndcls.lpszClassName, (HINSTANCE)&__ImageBase);
}
DbgPrint("%x>test end\n", GetCurrentThreadId());
}
i got next output:
d94>test begin
6d8:00000008884FEFD8>Send WM_APP(0000000000191BF0)
d94:00000008880FF4F8>WM_APP:(0000000000000000, 0000000000191BF0)
d94:00000008880FF4F8>Send WM_APP(0)
6d8:00000008884FEB88>WM_APP:(0000000000000000, 0000000000000000)
6d8:00000008884FEB88>Cannot print this
d94:00000008880FF4F8>SendMessage=00000000000006D8
6d8:00000008884FEFD8>SendMessage=0000000000000D94
d94>test end
most interesting look stack trace of thread_B when it recursively called on WM_APP
Still, I do not understand how does A process WM_ANOTHER_REGISTERED_MSG. What I would expect is that when that message is sent, A's thread should be waiting for its call to SendMessage to return.
The SendMessage in A is waiting for the message it sent (from A to B) to complete, but, while it's waiting, it's able to dispatch messages sent from other threads to this thread.
When SendMessage is called for a window on the same thread, we think of it like a chain of function calls that eventually leads to the target windowproc and eventually returns to the caller.
But when the message crosses thread boundaries, it's not that simple. It becomes like a client-server application. SendMessage packages up the message and signals the target thread that it has a message to process. At that point, it waits.
The target thread eventually (we hope) reaches a yield point where it checks that signal, gets the message and processes it. The target thread then signals that it's done the work.
The original thread sees the "I'm done!" signal and returns the result value. To the caller of SendMessage, it looks like it was just a function call, but it was actually choreographed to marshal the message over to the other thread and marshal the result back.
Several Windows API calls are "yield points," places that check to see if there's a message being sent to the current thread from another thread. The most well-known ones are GetMessage and PeekMessage, but certain types of waits--including the wait inside a SendMessage--are also yield points. It's this yield point that makes it possible for A to respond to the message sent back from B all while waiting for B to finish processing the first message.
Here's part of the call stack for A when it receives the WM_ANOTHER_REGISTERED_MSG back from B (step 4):
A.exe!MyWnd::OnFromB(unsigned int __formal, unsigned int __formal, long __formal, int & __formal)
A.exe!MyWnd::ProcessWindowMessage(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam, long & lResult, unsigned long dwMsgMapID)
A.exe!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<114229248,262400> >::WindowProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam)
atlthunk.dll!AtlThunk_Call(unsigned int,unsigned int,unsigned int,long)
atlthunk.dll!AtlThunk_0x00(struct HWND__ *,unsigned int,unsigned int,long)
user32.dll!__InternalCallWinProc#20()
user32.dll!UserCallWinProcCheckWow()
user32.dll!DispatchClientMessage()
user32.dll!___fnDWORD#4()
ntdll.dll!_KiUserCallbackDispatcher#12()
user32.dll!SendMessageW()
A.exe!MyWnd::OnClose(unsigned int __formal, unsigned int __formal, long __formal, int & __formal)
You can see the OnClose is still inside SendMessageW, but, nested within that, it's getting the callback message from B and routing that to A's window procedure.

Windows 10 - WinAPI - detect if power button pressed [duplicate]

I have a headless computer running a custom service that I want to enable/disable using the power button, rather than having to remotely connect every time. The computer does other things as well, so turning it off is not an option.
Is it possible to hook the system power button under Windows XP & up, such that my program would get the event before Windows initiates a powerdown/sleep event (before PBT_APMQUERYSUSPEND event get sent out)?
This is indeed possible, but it's a bit hackish and requires two completely different implementations depending on the Windows version. For both methods, you need to set your power button to put the computer to sleep in your power options.
Windows XP and below:
You need to overwrite your program's main window's WndProc function. On IDEs that don't support this natively, this can be done using SetWindowLong in user32 API. In your custom WndProc function, listen for a WM_POWERBROADCAST (0x218) message. If you receive a message with wParam of PBT_APMQUERYSUSPEND (0x0), call your wanted function and then return BROADCAST_QUERY_DENY (0x424D5144) instead of calling the base WndProc function. Example code:
//At program start
//GWL_WNDPROC = -4
oldWndProc = SetWindowLong(this.hWnd, GWL_WNDPROC, &MyWndProc)
//In MyWndProc(hWnd, wMsg, wParam, lParam)
//WM_POWERBROADCAST = 0x218
//PBT_APMQUERYSUSPEND = 0x0
//BROADCAST_QUERY_DENY = 0x424D5144
if wMsg = WM_POWERBROADCAST && wParam = PBT_APMQUERYSUSPEND (
//CALL YOUR FUNCTION HERE!
return BROADCAST_QUERY_DENY
)
return CallWindowProc(oldWndProc, hWnd, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
Windows Vista & up: (thanks to Remy Lebeau for setting me on the right track)
You need to override WndProc like for XP, but also call SetThreadExecutionState in kernel32 API to disable sleep mode and RegisterPowerSettingNotification in user32 API to listen for advanced power notifications. You will be listening, in particular, to the GUID_SYSTEM_AWAYMODE notification, which gets sent out when the system was asked to go to sleep but is unable to do so. To easily convert a string to a properly formed LPCGUID you can use UuidFromStringA in rpcrt4.dll API. Example code:
typedef struct UUID{
int d1, d2, d3, d4
} LPCGUID;
//At program start
//GWL_WNDPROC = -4
//ES_CONTINUOUS = 0x80000000
//ES_SYSTEM_REQUIRED = 0x1
//ES_AWAYMODE_REQUIRED = 0x40
//GUID_SYSTEM_AWAYMODE = "98a7f580-01f7-48aa-9c0f-44352c29e5C0"
LPCGUID uid;
oldWndProc = SetWindowLong(this.hWnd, GWL_WNDPROC, &MyWndProc)
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED)
UuidFromStringA(*(GUID_SYSTEM_AWAYMODE), uid)
ps = RegisterPowerSettingNotification(this.hWnd, uid, 0)
//In MyWndProc(hWnd, wMsg, wParam, lParam)
//WM_POWERBROADCAST = 0x218
//PBT_POWERSETTINGCHANGE = 0x8013
if wMsg = WM_POWERBROADCAST && wParam = PBT_POWERSETTINGCHANGE (
//CALL YOUR FUNCTION HERE!
//You can additionally extract data from the lParam to verify
//this is the notification you're waiting for (see below)
)
return CallWindowProc(oldWndProc, hWnd, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
UnregisterPowerSettingNotification(ps)
This method has the side effect of turning off your physical screen (not a problem on a headless machine), and also possibly locking your session. Make sure you disable prompting for password after sleeping to avoid this. There's some additional useful information on RegisterPowerSettingNotification available here which shows how to extract information from the lParam in your WndProc function in case you want additional info on the notification. Have fun ;)

Cannot find the main window handle of the just stareted Dialog APP

Here is the scenario:
I have 2 apps. One of them is my main app, and the second is a dialog based app, which is started from the first one. I'm trying to capture the main handle of the dialog based app from my main app. The problem is that I cannot find it with EnumWindows. The problem disappears if I put sleep for a second, just before start enumerating windows.
This is the code:
...
BOOL res = ::CreateProcess( NULL, _T("MyApp.exe"), NULL, NULL, FALSE, NULL, NULL, NULL, &siStartInfo, &piProcInfo );
ASSERT(res);
dwErr = WaitForInputIdle(piProcInfo.hProcess, iTimeout);
ASSERT(dwErr == 0);
//Sleep(1000); //<-- uncomment this will fix the problem
DWORD dwProcessId = piProcInfo.dwProcessId;
EnumWindows(EnumWindowsProc, (LPARAM)&dwProcessId);
....
BOOL IsMainWindow(HWND handle)
{
return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD* pParam = (DWORD*)lParam;
DWORD dwTargetProcessId = *pParam;
DWORD dwProcessId = 0;
::GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == dwTargetProcessId )
{
TCHAR buffer[MAXTEXT];
::SendMessage(hwnd, WM_GETTEXT, (WPARAM)MAXTEXT,(LPARAM)buffer);
if( IsMainWindow(hwnd))
{
g_hDlg = hwnd;
return FALSE;
}
}
return TRUE;
}
There are exactly 2 windows which belongs to my process and tracing their text shows:
GDI+ Window
Default IME
I'm not quite sure what does this mean. These might be the default captions, assigned to the windows, before their initialization.... but I call EnumWindows after WaitForInputIdle ...
Any help will be appreciated.
CreateProcess returns, when the OS has created the process object including the object representing the primary thread. This does not imply, that the process has started execution.
If you need to query another process for information that is only available after that process has run to a certain point, you will need to install some sort of synchronization. An obvious option is a named event object (see CreateEvent), that is signaled, when the second process has finished its initialization, and the dialog is up and running. The first process would then simply WaitForSingleProcess, and only continue, once the event is signaled. (A more robust solution would call WaitForMultipleObjects on both the event and the process handle, to respond to unexpected process termination.)
Another option would be to have the second process send a user-defined message (WM_APP+x) to the first process, passing its HWND along.
WaitForInputIdle sounds like a viable solution. Except, it isn't. WaitForInputIdle was introduced to meet the requirements of DDE, and merely checks, if a thread in the target process can receive messages. And that really means any thread in that process. It is not strictly tied to a GUI being up and running.
Additional information on the topic can be found here:
WaitForInputIdle should really be called WaitForProcessStartupComplete
WaitForInputIdle waits for any thread, which might not be the thread you care about

No matter what, I can't get this progress bar to update from a thread

I have a Windows app written in C (using gcc/MinGW) that works pretty well except for a few UI problems. One, I simply cannot get the progress bar to update from a thread. In fact, I probably can't get ANY UI stuff to update.
Basically, I have a spawned thread that does some processing, and from that thread I attempt to update the progress bar in the main thread. I tried this by using PostMessage() to the main hwnd, but no luck even though I can do other things like open message boxes. However, it's unclear whether the message box is getting called within the thread or on the main thread.
Here's some code:
// in header/globally accessible
HWND wnd; // main application window
HWND progress_bar; //progress bar
typedef struct { //to pass to thread
DWORD mainThreadId;
HWND mainHwnd;
char *filename;
} THREADSTUFF;
//callback function
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_CREATE:{
// create progress bar
progress_bar = CreateWindowEx(
0,
PROGRESS_CLASS,
(LPCTSTR) NULL,
WS_CHILD | WS_VISIBLE,
79,164,455,15,
hwnd,
(HMENU)20,
NULL,
NULL);
SendMessage(progress_bar, PBM_SETSTEP, 1, 0 );
SendMessage(progress_bar, PBM_SETPOS, 0, 0 );
//test to make sure it actually works
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
break;
}
case WM_COMMAND: {
if(LOWORD(wParam)==2){ //do some processing in a thread
//struct of stuff I need to pass to thread
THREADSTUFF *threadStuff;
threadStuff = (THREADSTUFF*)malloc(sizeof(*threadStuff));
threadStuff->mainThreadId = GetCurrentThreadId();
threadStuff->mainHwnd = hwnd;
threadStuff->filename = (void*)&filename;
hThread1 = CreateThread(NULL,0,convertFile (LPVOID)threadStuff,0,NULL);
}else if(LOWORD(wParam)==5){ //update progress bar
MessageBox(hwnd,"I got a message!", "Message", MB_OK | MB_ICONINFORMATION);
PostMessage(progress_bar,PBM_STEPIT,0,0);
}
break;
}
}
}
This all seems to work okay. The problem is in the thread:
DWORD WINAPI convertFile(LPVOID params){
//get passed params, this works perfectly fine
THREADSTUFF *tData = (THREADSTUFF*)params;
MessageBox(tData->mainHwnd,tData->filename,"File name",MB_OK | MB_ICONINFORMATION); //yep
PostMessage(tData->mainHwnd,WM_COMMAND,5,0); //only shows message
PostThreadMessage(tData->mainThreadId,WM_COMMAND,5,0); //does nothing
}
When I say, "only shows message," that means the MessageBox() function in the callback works, but not the PostMessage() to update the position of the progress bar.
If I use PostThreadMessage() to send a message to the main thread's message loop, I can intercept it and launch MessageBoxes so it's definitely working. However, even if I try to update the progress bar this way. it still won't update.
What am I missing?
From the MSDN documentation for PBM_STEPIT:
wParam
Must be zero.
lParam
Must be zero.
CLR_DEFAULT is defined as 0xFF000000L. What happens if you change your code to:
PostMessage(progress_bar, PBM_STEPIT, 0, 0);
I suspect the problem lies in your message loop. Anyway then, three things:
I don't think theres any reason to post a PBM_STEPIT message, just send it.
Check your message loop and make sure you arn't doing something silly like GetMessage(&msg,hwnd,... - always pass NULL for the hwnd parameter for GetMessage otherwise posted messages destined for other windows will never get dispatched.
WindowProc's are always called by windows in the correct thread. So you can SendMessage, or PostMessage, directly from the worker thread to the progress control to update it.
bonus 4th point:
MessageBox creates a window, and runs its message loop in the calling thread. In your case all the windows are created and are running in the main thread. But there is no real minus to displaying message boxes in your worker thread (other than the fact that the worker threads processing will be stopped until the Message Box is closed).

Is it possible to send WM_QUERYENDSESSION messages to a window in a different process?

I want to debug a windows C++ application I've written to see why it isn't responding to WM_QUERYENDSESSION how I expect it to. Clearly it's a little tricky to do this by just shutting the system down. Is there any utility or code which I can use to send a fake WM_QUERYENDSESSION to my application windows myself?
I've used the Win32::GuiTest Perl module to do this kind of thing in the past.
The Windows API SendMessage can be used to do this.
http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx
IS ti possible it's not responding because some other running process has responded with a zero (making the system wait on it.)
Yes of course, it possible. I faced a similar issue some months ago where some (unknown, but probably mine) app was preventing shutdown, so I wrote some quick code that used EnumWindows to enumerate all the top level windows, sent each one a WM_QUERYENDSESSION message, noted what the return value from SendMessage was and stopped the enumeration if anyone returned FALSE. Took about ten minutes in C++/MFC. This was the guts of it:
void CQes_testDlg::OnBtnTest()
{
// enumerate all the top-level windows.
m_ctrl_ListMsgs.ResetContent();
EnumWindows (EnumProc, 0);
}
BOOL CALLBACK EnumProc (HWND hTarget, LPARAM lParam)
{
CString csTitle;
CString csMsg;
CWnd * pWnd = CWnd::FromHandle (hTarget);
BOOL bRetVal = TRUE;
DWORD dwPID;
if (pWnd)
{
pWnd->GetWindowText (csTitle);
if (csTitle.GetLength() == 0)
{
GetWindowThreadProcessId (hTarget, &dwPID);
csTitle.Format ("<PID=%d>", dwPID);
}
if (pWnd->SendMessage (WM_QUERYENDSESSION, 0, ENDSESSION_LOGOFF))
{
csMsg.Format ("window 0x%X (%s) returned TRUE", hTarget, csTitle);
}
else
{
csMsg.Format ("window 0x%X (%s) returned FALSE", hTarget, csTitle);
bRetVal = FALSE;
}
mg_pThis->m_ctrl_ListMsgs.AddString (csMsg);
}
else
{
csMsg.Format ("Unable to resolve HWND 0x%X to a CWnd", hTarget);
mg_pThis->m_ctrl_ListMsgs.AddString (csMsg);
}
return bRetVal;
}
mg_pThis was just a local copy of the dialog's this pointer, so the helper callback could access it. I told you it was quick and dirty :-)
Yes. If you can get the window handle (maybe using FindWindow()), you can send/post any message to it as long as the WPARAM & LPARAM aren't pointers.

Resources