У меня есть приложение, которое я хотел бы корректно завершить при завершении работы Windows (или выходе пользователя из системы). Раньше это работало (в XP), но когда-то в прошлом году оно сломалось, и никто этого не заметил. Он также не работает (но по-другому) под Windows 7.
В нашем продукте есть главный процесс (server.exe), который запускает многие другие процессы. При плавном завершении работы server.exe запрашивает завершение работы всего процесса. Однако, когда я отлаживаю этот код, кажется, что другие процессы уже завершены. Наш основной процесс (server.exe) - единственный процесс, который обрабатывает сообщения WM_QUERYENDSESSION и WM_ENDSESSION.Код ниже (раньше это работало под XP, но больше не работает):
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;
}
Похоже, что мы что-то изменили за последний год, потребовалось бы, чтобы все дочерние процессы обрабатывали сообщение WM_QUERYENDSESSION (я бы действительно хотелось бы этого избежать). Кажется, я не могу найти никакой информации о том, когда процессы получают или не получают это сообщение.
Я заставил его работать под Windows 7, используя новый API, но хотел бы выяснить, почему он сломался под XP, чтобы у меня было решение, которое работает для обеих ОС.
Есть помощь?