INT_PTR ServiceShutdown(WPARAM wParam, LPARAM lParam) { /* passing 0 as wParam is only to be used internally, undocumented */ if (!wParam) wParam = db_get_b(NULL, "AutoShutdown", "ShutdownType", SETTING_SHUTDOWNTYPE_DEFAULT); if (!IsShutdownTypeEnabled((BYTE)wParam)) return 1; /* does shutdownType range check */ if ((BOOL)lParam && hwndShutdownDlg != NULL) return 2; /* ask others if allowed */ if (NotifyEventHooks(hEventOkToShutdown, wParam, lParam)) { OutputDebugStringA("automatic shutdown denied by event hook\n"); /* all ascii */ return 3; } /* tell others */ NotifyEventHooks(hEventShutdown, wParam, lParam); /* show dialog */ if (lParam && db_get_b(NULL, "AutoShutdown", "ShowConfirmDlg", SETTING_SHOWCONFIRMDLG_DEFAULT)) if (CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SHUTDOWNNOW), NULL, ShutdownDlgProc, (BYTE)wParam) != NULL) return 0; /* show error */ DWORD dwErrCode = ShutdownNow((BYTE)wParam); if (dwErrCode != ERROR_SUCCESS) { char *pszErr = GetWinErrorDescription(dwErrCode); ShowInfoMessage(NIIF_ERROR, Translate("Automatic Shutdown Error"), Translate("Inititiating the shutdown process failed!\nReason: %s"), (pszErr != NULL) ? pszErr : Translate("Unknown")); if (pszErr != NULL) LocalFree(pszErr); return 4; } return 0; }
std::string I_ConsoleInput (void) { // denis - todo - implement this properly!!! static char text[1024] = {0}; static char buffer[1024] = {0}; unsigned int len = strlen(buffer); if (ShutdownNow()) return "quit"; while(kbhit() && len < sizeof(text)) { char ch = (char)getch(); // input the character if(ch == '\b' && len) { buffer[--len] = 0; // john - backspace hack fwrite(&ch, 1, 1, stdout); ch = ' '; fwrite(&ch, 1, 1, stdout); ch = '\b'; } else buffer[len++] = ch; buffer[len] = 0; // recalculate length len = strlen(buffer); // echo character back to user fwrite(&ch, 1, 1, stdout); fflush(stdout); } if(len && buffer[len - 1] == '\n' || buffer[len - 1] == '\r') { // echo newline back to user char ch = '\n'; fwrite(&ch, 1, 1, stdout); fflush(stdout); strcpy(text, buffer); text[len-1] = 0; // rip off the /n and terminate buffer[0] = 0; len = 0; return text; } return ""; }
static INT_PTR CALLBACK ShutdownDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { BYTE shutdownType = (BYTE)GetWindowLongPtr(hwndDlg, DWLP_USER); WORD countdown = (WORD)GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: hwndShutdownDlg = hwndDlg; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); TranslateDialogDefault(hwndDlg); if (lParam == SDSDT_SHUTDOWN || lParam == SDSDT_REBOOT || lParam == SDSDT_LOGOFF) ShowWindow(GetDlgItem(hwndDlg, IDC_TEXT_UNSAVEDWARNING), SW_SHOW); SendDlgItemMessage(hwndDlg, IDC_ICON_HEADER, STM_SETIMAGE, IMAGE_ICON, (LPARAM)IcoLib_GetIcon("AutoShutdown_Header")); { HFONT hBoldFont; LOGFONT lf; if (GetObject((HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_HEADER, WM_GETFONT, 0, 0), sizeof(lf), &lf)) { lf.lfWeight = FW_BOLD; hBoldFont = CreateFontIndirect(&lf); } else hBoldFont = NULL; SendDlgItemMessage(hwndDlg, IDC_TEXT_HEADER, WM_SETFONT, (WPARAM)hBoldFont, FALSE); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, (LONG_PTR)hBoldFont); } { countdown = db_get_w(NULL, "AutoShutdown", "ConfirmDlgCountdown", SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT); if (countdown < 3) countdown = SETTING_CONFIRMDLGCOUNTDOWN_DEFAULT; SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, countdown); SendMessage(hwndDlg, M_UPDATE_COUNTDOWN, 0, countdown); } SkinPlaySound("AutoShutdown_Countdown"); if (!SetTimer(hwndDlg, 1, 1000, NULL)) PostMessage(hwndDlg, M_START_SHUTDOWN, 0, 0); Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, "AutoShutdown", "ConfirmDlg_"); /* disallow foreground window changes (WinMe/2000+) */ SetForegroundWindow(hwndDlg); LockSetForegroundWindow(LSFW_LOCK); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDCANCEL), TRUE); return FALSE; /* focus set on cancel */ case WM_DESTROY: { hwndShutdownDlg = NULL; ShowWindow(hwndDlg, SW_HIDE); /* reallow foreground window changes (WinMe/2000+) */ LockSetForegroundWindow(LSFW_UNLOCK); Utils_SaveWindowPosition(hwndDlg, NULL, "AutoShutdown", "ConfirmDlg_"); HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_TEXT_HEADER, WM_GETFONT, 0, 0); SendDlgItemMessage(hwndDlg, IDC_TEXT_HEADER, WM_SETFONT, 0, FALSE); /* no return value */ if (hFont != NULL) DeleteObject(hFont); } return TRUE; case M_START_SHUTDOWN: if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BUTTON_SHUTDOWNNOW))) { EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_SHUTDOWNNOW), FALSE); ShowWindow(hwndDlg, SW_HIDE); /* get rid of the dialog immediately */ DWORD dwErrCode = ShutdownNow(shutdownType); if (dwErrCode != ERROR_SUCCESS) { char *pszErr = GetWinErrorDescription(dwErrCode); ShowInfoMessage(NIIF_ERROR, Translate("Automatic Shutdown Error"), Translate("The shutdown process failed!\nReason: %s"), (pszErr != NULL) ? pszErr : Translate("Unknown")); if (pszErr != NULL) LocalFree(pszErr); } DestroyWindow(hwndDlg); } return TRUE; case WM_TIMER: if (countdown) { --countdown; SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, countdown); if (countdown == 27 || countdown == 24 || countdown == 21 || countdown == 19 || countdown == 17 || countdown == 15 || countdown == 13 || countdown == 11 || countdown <= 10) SkinPlaySound("AutoShutdown_Countdown"); } else KillTimer(hwndDlg, wParam); /* countdown finished */ PostMessage(hwndDlg, M_UPDATE_COUNTDOWN, 0, countdown); return TRUE; case M_UPDATE_COUNTDOWN: /* lParam=(WORD)countdown */ { TCHAR szText[256]; mir_sntprintf(szText, TranslateTS(desc[shutdownType - 1]), lParam); SetDlgItemText(hwndDlg, IDC_TEXT_HEADER, szText); /* countdown finished */ if (!lParam) PostMessage(hwndDlg, M_START_SHUTDOWN, 0, 0); } return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BUTTON_SHUTDOWNNOW: KillTimer(hwndDlg, 1); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT_HEADER), GWLP_USERDATA, 0); SendMessage(hwndDlg, M_UPDATE_COUNTDOWN, 0, (LONG)0); PostMessage(hwndDlg, M_START_SHUTDOWN, 0, 0); return TRUE; case IDCANCEL: /* WM_CLOSE */ if (countdown) { KillTimer(hwndDlg, 1); DestroyWindow(hwndDlg); } return TRUE; } break; } return FALSE; }
static DWORD ShutdownNow(BYTE shutdownType) { DWORD dwErrCode = ERROR_SUCCESS; switch (shutdownType) { case SDSDT_CLOSEMIRANDA: if (!Miranda_Terminated()) { /* waiting for short until ready (but not too long...) */ DWORD dwLastTickCount = GetTickCount(); while (!CallService(MS_SYSTEM_OKTOEXIT, 0, 0)) { /* infinite loop protection (max 5 sec) */ if (GetTickCount() - dwLastTickCount >= 5000) { /* wraparound works */ OutputDebugStringA("Timeout (5 sec)\n"); /* tell others, all ascii */ break; } SleepEx(1000, TRUE); if (Miranda_Terminated()) break; /* someone else did it */ OutputDebugStringA("Not ready to exit. Waiting...\n"); /* tell others, all ascii */ } /* shutdown service must be called from main thread anyway */ if (!DestroyWindow(pcli->hwndContactList)) dwErrCode = GetLastError(); } break; case SDSDT_SETMIRANDAOFFLINE: /* set global status mode to offline (is remembered by Miranda on exit) */ CallService(MS_CLIST_SETSTATUSMODE, (WPARAM)ID_STATUS_OFFLINE, 0); break; case SDSDT_STANDBY: case SDSDT_HIBERNATE: WinNT_SetPrivilege(SE_SHUTDOWN_NAME, TRUE); if (!SetSystemPowerState(shutdownType == SDSDT_STANDBY, TRUE)) dwErrCode = GetLastError(); WinNT_SetPrivilege(SE_SHUTDOWN_NAME, FALSE); break; case SDSDT_LOCKWORKSTATION: if (!IsWorkstationLocked()) dwErrCode = GetLastError(); break; case SDSDT_CLOSERASCONNECTIONS: ShutdownNow(SDSDT_SETMIRANDAOFFLINE); /* set Miranda offline */ /* hang up all ras connections */ { DWORD dwRetries; RASCONNSTATUS rcs; DWORD dw, dwLastTickCount; DWORD dwConnSize = sizeof(RASCONN); DWORD dwConnItems = 0; RASCONN *paConn = (RASCONN*)mir_alloc(dwConnSize); dwErrCode = ERROR_NOT_ENOUGH_MEMORY; if (paConn != NULL) { for (dwRetries = 5; dwRetries != 0; dwRetries--) { /* prevent infinite loop (rare) */ memset(paConn, 0, dwConnSize); paConn[0].dwSize = sizeof(RASCONN); dwErrCode = RasEnumConnections(paConn, &dwConnSize, &dwConnItems); if (dwErrCode != ERROR_BUFFER_TOO_SMALL) break; RASCONN *paConnBuf = (RASCONN*)mir_realloc(paConn, dwConnSize); if (paConnBuf == NULL) { mir_free(paConn); paConn = NULL; dwErrCode = ERROR_NOT_ENOUGH_MEMORY; break; } paConn = paConnBuf; } if (dwErrCode == ERROR_SUCCESS || dwErrCode == ERROR_BUFFER_TOO_SMALL) { for (dw = 0; dw < dwConnItems; ++dw) { if (dwErrCode) { if (RasHangUp(paConn[dw].hrasconn)) paConn[dw].hrasconn = NULL; /* do not wait for on error */ } else { dwErrCode = RasHangUp(paConn[dw].hrasconn); if (!dwErrCode) paConn[dw].hrasconn = NULL; /* do not wait for on error */ } } /* RAS does not allow to quit directly after HangUp (see docs) */ dwLastTickCount = GetTickCount(); memset(&rcs, 0, sizeof(RASCONNSTATUS)); rcs.dwSize = sizeof(RASCONNSTATUS); for (dw = 0; dw < dwConnItems; ++dw) { if (paConn[dw].hrasconn != NULL) { while (RasGetConnectStatus(paConn[dw].hrasconn, &rcs) != ERROR_INVALID_HANDLE) { Sleep(0); /* give rest of time silce to other threads with equal priority */ /* infinite loop protection (3000ms defined in docs) */ dwRetries = GetTickCount(); if (dwRetries - dwLastTickCount > 3000) break; /* wraparound works */ } } } } mir_free(paConn); /* does NULL check */ } } /* set Miranda to offline again, to remain offline with reconnection plugins */ ShutdownNow(SDSDT_SETMIRANDAOFFLINE); break; case SDSDT_REBOOT: case SDSDT_SHUTDOWN: if (GetSystemMetrics(SM_SHUTTINGDOWN)) { /* Win2000+, 0 on error */ dwErrCode = ERROR_SHUTDOWN_IN_PROGRESS; break; } /* WinNT4/2000/XP */ { WinNT_SetPrivilege(SE_SHUTDOWN_NAME, TRUE); /* does not send out WM_ENDSESSION messages, so we do it manually to * give the applications the chance to save their data */ WinNT_SetPrivilege(SE_TCB_NAME, TRUE); /* for BSM_ALLDESKTOPS */ BroadcastEndSession(BSM_APPLICATIONS | BSM_ALLDESKTOPS, ENDSESSION_CLOSEAPP); /* app should close itself */ WinNT_SetPrivilege(SE_TCB_NAME, FALSE); if (!InitiateSystemShutdownEx(NULL, TranslateT("AutoShutdown"), 0, TRUE, shutdownType == SDSDT_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) dwErrCode = GetLastError(); /* cleanly close Miranda */ if (!dwErrCode) ShutdownNow(SDSDT_CLOSEMIRANDA); break; } /* fall through for Win9x */ case SDSDT_LOGOFF: { UINT flags; switch (shutdownType) { case SDSDT_LOGOFF: flags = EWX_LOGOFF; break; case SDSDT_REBOOT: flags = EWX_REBOOT; break; default: flags = EWX_SHUTDOWN | EWX_POWEROFF; } if (shutdownType == SDSDT_LOGOFF && !IsWorkstationLocked()) flags |= EWX_FORCEIFHUNG; /* only considered for WM_ENDSESSION messages */ else flags |= EWX_FORCE; /* must be used when workstation locked */ if (flags & EWX_FORCE) { /* EWX_FORCE does not send out WM_ENDSESSION messages, so we do it * manually to give the applications the chance to save their data */ BroadcastEndSession(BSM_APPLICATIONS, (shutdownType == SDSDT_LOGOFF) ? ENDSESSION_LOGOFF : 0); /* Windows Me/98/95 (msdn): Because of the design of the shell, * calling ExitWindowsEx with EWX_FORCE fails to completely log off * the user (the system terminates the applications and displays the * Enter Windows Password dialog box, however, the user's desktop remains.) * To log off the user forcibly, terminate the Explorer process before calling * ExitWindowsEx with EWX_LOGOFF and EWX_FORCE. */ } if (!ExitWindowsEx(flags, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) dwErrCode = GetLastError(); /* cleanly close Miranda */ if (!dwErrCode) ShutdownNow(SDSDT_CLOSEMIRANDA); } break; } return dwErrCode; }