LogOffNicely : logoff from windows in as nice a way as possible

Download logoffnicely.zip

Synopsis:

logoffnicely.cpp
logoffnicely.rc
resource.h


logoffnicely.cpp

Synopsis
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

#include <stdio.h>
#include "resource.h"

const long cPauseTimeout = 45000; //milliseconds
const long cUserTimeout = 15; //seconds
enum DialogState {cNotSet, cCancel, cOk, cTimeout};

class BePolite
  {
  public:
    explicit BePolite(HINSTANCE h)
      : mAppInstance(h)
      {
      }
    bool IsUserCancelled()
      {
      return mDialogState == cCancel;
      }
    void AskUser(void)
      {
      mDialogState = cNotSet;
      RunMsgLoop(::CreateDialog(mAppInstance, MAKEINTRESOURCE(IDD_DLG), ::GetDesktopWindow(), DialogProc));
      }
  private:
    void RunMsgLoop(HWND dlghwnd)
      {
      MSG  Msg;
      while (GetMessage(&Msg, NULL, 0, 0))
        {
        if (IsDialogMessage(dlghwnd, &Msg))
          continue;

        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
        }
      }
    static  BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
      {
      static DialogProcHandler h;
      h.DlgHwnd = hwndDlg;
      switch(uMsg)
        {
        case WM_INITDIALOG: h.OnInitDialog(); return 1;
        case WM_TIMER: h.OnTimer(); return 1;
        case WM_DESTROY: h.OnDestroy(); return 0;
        case WM_COMMAND: 
          switch(LOWORD(wParam))
            {
            case IDOK: h.OnOk(); return 1;
            case IDCANCEL: h.OnCancel(); return 1;
            default: return 0;
            }
        default:  return 0;
        }
      }

    //-----------------------
    class DialogProcHandler
      {
      public:
        HWND DlgHwnd;
        int mTime;

        void OnInitDialog()
          {
          mTime = cUserTimeout;
          SetTimeoutText();
          StartOneSecondTimer();
          ::ShowWindow(DlgHwnd, SW_SHOW); 
          }
        void OnDestroy()
          {
          ::PostQuitMessage(mDialogState);
          }
        void OnTimer()
          {
          if (mTime <= 0)
            {
            SetState(cTimeout);
            EndDialog();
            }
          else
            {
            mTime--;
            SetTimeoutText();
            }
          }
        void OnOk()
          {
          SetState(cOk);
          EndDialog();
          }
        void OnCancel()
          {
          SetState(cCancel);
          EndDialog();
          }
      private:
        void EndDialog()
          {
          KillTimer(DlgHwnd, TimerId);
          DestroyWindow(DlgHwnd);
          }
        void SetState(BePolite::DialogState newstate)
          {
          if (mDialogState == cNotSet)
            mDialogState = newstate;
          }
        void StartOneSecondTimer()
          {
          SetTimer(DlgHwnd, TimerId, 1000, NULL); 
          }
        void SetTimeoutText()
          {
          char buf[20];
          sprintf(buf, "%d", mTime);
          ::SetWindowText(GetDlgItem(DlgHwnd, IDC_TIMEOUTTEXT), buf);
          }
      } ;

  private:
    static const int TimerId = 99;
    static DialogState mDialogState;

    HINSTANCE mAppInstance;
  } ;
DialogState BePolite::mDialogState = cNotSet;

class Terminator
  {
  public:
    void Die()
      {
      SendCloseToAllWindows();
      SendQuitToAllWindows();
      AttemptLogoff();
      ForceLogoff();
      }
  private:
    void Snooze()
      {
      Sleep(cPauseTimeout);
      }
    void SendCloseToAllWindows()
      {
      SendToAllWindows(WM_CLOSE);
      Snooze();
      }
    void SendQuitToAllWindows()
      {
      SendToAllWindows(WM_QUIT);
      Snooze();
      }
    void SendToAllWindows(UINT msg)
      {
      PostMessage(HWND_BROADCAST, msg, 0, 0);
      }

    void AttemptLogoff()
      {
      //log off nicely
      ExitWindowsEx(EWX_LOGOFF, 0);
      Snooze();
      }
    void ForceLogoff()
      {
      // Force all processes to die
      ExitWindowsEx(EWX_FORCE, 0);
      Snooze();
      }
  } ;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int )
  {
  BePolite politely(hInstance);
  politely.AskUser();
  if (politely.IsUserCancelled())
    return 1;

  // User hit OK or a cPauseTimeout happened
  Terminator t;
  t.Die();

  return 0;
  }

logoffnicely.rc

Synopsis
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DLG DIALOGEX 0, 0, 187, 99
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Logging Off!"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,24,78,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,102,78,50,14
    LTEXT           "Press Cancel to stop logging off! Press OK to continue logging off.",
                    IDC_STATIC,33,18,114,34,WS_BORDER
    LTEXT           "You have",IDC_STATIC,33,58,32,8
    LTEXT           "seconds to decide.",IDC_STATIC,97,58,61,8
    CTEXT           "0",IDC_TIMEOUTTEXT,69,58,24,11,SS_CENTERIMAGE | 
                    SS_SUNKEN
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO 
BEGIN
    IDD_DLG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 180
        TOPMARGIN, 7
        BOTTOMMARGIN, 92
    END
END
#endif    // APSTUDIO_INVOKED

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED


resource.h

Synopsis
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by LogOffNicely.rc
//
#define IDD_DLG                         102
#define IDC_TIMEOUTTEXT                 1000

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001-2010