Изящное завершение работы приложения при завершении работы Windows

У меня есть приложение, которое я хотел бы корректно завершить при завершении работы 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, чтобы у меня было решение, которое работает для обеих ОС.

Есть помощь?

5
задан Brian Erickson 6 January 2012 в 15:51
поделиться