void UninitWatcher(void) { /* remember watcher if running */ if (!ServiceStopWatcher(0, 0)) if (db_get_b(NULL, "AutoShutdown", "RememberOnRestart", SETTING_REMEMBERONRESTART_DEFAULT)) db_set_b(NULL, "AutoShutdown", "RememberOnRestart", SDROR_RUNNING); /* Message Shutdown */ UnhookEvent(hHookEventAdded); /* Status Shutdown*/ UnhookEvent(hHookSettingChanged); /* Idle Shutdown */ UnhookEvent(hHookIdleChanged); /* Transfer Shutdown */ UnhookEvent(hHookProtoAck); mir_free(transfers); /* does NULL check */ /* Weather Shutdown */ UnhookEvent(hHookWeatherUpdated); /* does NULL check */ /* Services */ DestroyServiceFunction(hServiceStartWatcher); DestroyServiceFunction(hServiceStopWatcher); DestroyServiceFunction(hServiceIsEnabled); DestroyHookableEvent(hEventWatcherChanged); /* Misc */ UnhookEvent(hHookModulesLoaded); }
static void __stdcall MainThreadMapping(void *param) { HANDLE *phDoneEvent = (HANDLE*)param; ServiceShutdown(0, TRUE); /* ensure main thread (for cpu usage shutdown) */ ServiceStopWatcher(0, 0); if (*phDoneEvent != NULL) SetEvent(*phDoneEvent); }
static INT_PTR MenuItemCommand(WPARAM,LPARAM) { /* toggle between StopWatcher and ShowSettingsDdialog */ if (ServiceIsWatcherEnabled(0,0)) ServiceStopWatcher(0,0); else ServiceShowSettingsDialog(0,0); return 0; }
static LRESULT CALLBACK FrameWndProc(HWND hwndFrame, UINT msg, WPARAM wParam, LPARAM lParam) { CountdownFrameWndData *dat = (CountdownFrameWndData*)GetWindowLongPtr(hwndFrame, GWLP_USERDATA); switch (msg) { case WM_NCCREATE: /* init window data */ dat = (struct CountdownFrameWndData*)mir_calloc(sizeof(*dat)); SetWindowLongPtr(hwndFrame, GWLP_USERDATA, (LONG_PTR)dat); if (dat == NULL) return FALSE; /* creation failed */ dat->fTimeFlags = *(WORD*)((CREATESTRUCT*)lParam)->lpCreateParams; dat->flags = FWPDF_COUNTDOWNINVALID; break; case WM_CREATE: /* create childs */ { CREATESTRUCT *params = (CREATESTRUCT*)lParam; dat->hwndIcon = CreateWindowEx(WS_EX_NOPARENTNOTIFY, _T("Static"), NULL, WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE | SS_NOTIFY, 3, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), hwndFrame, NULL, params->hInstance, NULL); dat->hwndProgress = CreateWindowEx(WS_EX_NOPARENTNOTIFY, PROGRESS_CLASS, (dat->fTimeFlags&SDWTF_ST_TIME) ? TranslateT("Shutdown at:") : TranslateT("Time left:"), WS_CHILD | WS_VISIBLE | PBS_SMOOTH, GetSystemMetrics(SM_CXICON) + 5, 5, 90, (GetSystemMetrics(SM_CXICON) / 2) - 5, hwndFrame, NULL, params->hInstance, NULL); if (dat->hwndProgress == NULL) return -1; /* creation failed, calls WM_DESTROY */ SendMessage(dat->hwndProgress, PBM_SETSTEP, 1, 0); mir_subclassWindow(dat->hwndProgress, ProgressBarSubclassProc); dat->hwndDesc = CreateWindowEx(WS_EX_NOPARENTNOTIFY, _T("Static"), (dat->fTimeFlags&SDWTF_ST_TIME) ? TranslateT("Shutdown at:") : TranslateT("Time left:"), WS_CHILD | WS_VISIBLE | SS_LEFTNOWORDWRAP | SS_NOTIFY, GetSystemMetrics(SM_CXICON) + 5, (GetSystemMetrics(SM_CXICON) / 2), 75, (GetSystemMetrics(SM_CXICON) / 2), hwndFrame, NULL, params->hInstance, NULL); dat->hwndTime = CreateWindowEx(WS_EX_NOPARENTNOTIFY, _T("Static"), NULL, WS_CHILD | WS_VISIBLE | SS_RIGHT | SS_NOTIFY | SS_ENDELLIPSIS, (GetSystemMetrics(SM_CXICON) + 80), (GetSystemMetrics(SM_CXICON) / 2), 35, (GetSystemMetrics(SM_CXICON) / 2), hwndFrame, NULL, params->hInstance, NULL); if (dat->hwndTime == NULL) return -1; /* creation failed, calls WM_DESTROY */ // create tooltips TTTOOLINFO ti; dat->hwndToolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP | TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndFrame, NULL, params->hInstance, NULL); if (dat->hwndToolTip != NULL) { SetWindowPos(dat->hwndToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); memset(&ti, 0, sizeof(ti)); ti.cbSize = sizeof(ti); ti.hwnd = hwndFrame; ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRANSPARENT; ti.lpszText = LPSTR_TEXTCALLBACK; /* commctl 4.70+ */ ti.uId = (UINT_PTR)dat->hwndTime; /* in-place tooltip */ SendMessage(dat->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); ti.uFlags &= ~TTF_TRANSPARENT; ti.uId = (UINT_PTR)dat->hwndProgress; SendMessage(dat->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); if (dat->hwndDesc != NULL) { ti.uId = (UINT_PTR)dat->hwndDesc; SendMessage(dat->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); } if (dat->hwndIcon != NULL) { ti.uId = (UINT_PTR)dat->hwndIcon; SendMessage(dat->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti); } } /* init layout */ dat->hHookColorsChanged = HookEventMessage(ME_COLOUR_RELOAD, hwndFrame, M_REFRESH_COLORS); dat->hHookFontsChanged = HookEventMessage(ME_FONT_RELOAD, hwndFrame, M_REFRESH_FONTS); dat->hHookIconsChanged = HookEventMessage(ME_SKIN2_ICONSCHANGED, hwndFrame, M_REFRESH_ICONS); SendMessage(hwndFrame, M_REFRESH_COLORS, 0, 0); SendMessage(hwndFrame, M_REFRESH_FONTS, 0, 0); SendMessage(hwndFrame, M_REFRESH_ICONS, 0, 0); SendMessage(hwndFrame, M_SET_COUNTDOWN, 0, 0); SendMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); if (!SetTimer(hwndFrame, 1, 1000, NULL)) return -1; /* creation failed, calls WM_DESTROY */ } return 0; case WM_DESTROY: if (dat == NULL) return 0; UnhookEvent(dat->hHookColorsChanged); UnhookEvent(dat->hHookFontsChanged); UnhookEvent(dat->hHookIconsChanged); /* other childs are destroyed automatically */ if (dat->hwndToolTip != NULL) DestroyWindow(dat->hwndToolTip); break; case WM_NCDESTROY: if (dat == NULL) return 0; if (dat->hFont != NULL) DeleteObject(dat->hFont); if (dat->hbrBackground != NULL) DeleteObject(dat->hbrBackground); mir_free(dat); SetWindowLongPtr(hwndFrame, GWLP_USERDATA, 0); break; case WM_SIZE: { RECT rc; UINT defflg = SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE; SetRect(&rc, 0, 0, LOWORD(lParam), HIWORD(lParam)); /* width,height */ /* workaround: reduce flickering of frame in clist */ InvalidateRect(hwndFrame, &rc, FALSE); HDWP hdwp = BeginDeferWindowPos(3); /* progress */ LONG width = rc.right - GetSystemMetrics(SM_CXICON) - 10; LONG height = rc.bottom - (GetSystemMetrics(SM_CYICON) / 2) - 5; if (NULL != dat->hwndProgress) /* Wine fix. */ hdwp = DeferWindowPos(hdwp, dat->hwndProgress, NULL, 0, 0, width, height, SWP_NOMOVE | defflg); /* desc */ if (dat->hwndDesc != NULL) /* Wine fix. */ hdwp = DeferWindowPos(hdwp, dat->hwndDesc, NULL, GetSystemMetrics(SM_CXICON) + 5, 5 + height, 0, 0, SWP_NOSIZE | defflg); /* time */ if (NULL != dat->hwndTime) /* Wine fix. */ hdwp = DeferWindowPos(hdwp, dat->hwndTime, NULL, GetSystemMetrics(SM_CXICON) + 85, 5 + height, width - 80, (GetSystemMetrics(SM_CXICON) / 2), defflg); EndDeferWindowPos(hdwp); } PostMessage(hwndFrame, M_CHECK_CLIPPED, 0, 0); return 0; case M_REFRESH_COLORS: COLORREF clrBar; if (FontService_GetColor(_T("Automatic Shutdown"), _T("Progress Bar"), &clrBar)) clrBar = GetDefaultColor(FRAMEELEMENT_BAR); if (FontService_GetColor(_T("Automatic Shutdown"), _T("Background"), &dat->clrBackground)) dat->clrBackground = GetDefaultColor(FRAMEELEMENT_BKGRND); if (dat->hbrBackground != NULL) DeleteObject(dat->hbrBackground); dat->hbrBackground = CreateSolidBrush(dat->clrBackground); SendMessage(dat->hwndProgress, PBM_SETBARCOLOR, 0, (LPARAM)clrBar); SendMessage(dat->hwndProgress, PBM_SETBKCOLOR, 0, (LPARAM)dat->clrBackground); InvalidateRect(hwndFrame, NULL, TRUE); return 0; case M_REFRESH_ICONS: return 0; case M_REFRESH_FONTS: { LOGFONT lf; if (!FontService_GetFont(_T("Automatic Shutdown"), _T("Countdown on Frame"), &dat->clrText, &lf)) { if (dat->hFont != NULL) DeleteObject(dat->hFont); dat->hFont = CreateFontIndirect(&lf); } else { dat->clrText = GetDefaultColor(FRAMEELEMENT_TEXT); if (GetDefaultFont(&lf) != NULL) { if (dat->hFont != NULL) DeleteObject(dat->hFont); dat->hFont = CreateFontIndirect(&lf); } } } if (dat->hwndDesc != NULL) SendMessage(dat->hwndDesc, WM_SETFONT, (WPARAM)dat->hFont, FALSE); SendMessage(dat->hwndTime, WM_SETFONT, (WPARAM)dat->hFont, FALSE); InvalidateRect(hwndFrame, NULL, FALSE); return 0; case WM_SYSCOLORCHANGE: SendMessage(hwndFrame, M_REFRESH_COLORS, 0, 0); break; case WM_SETTINGCHANGE: /* colors depend on windows settings */ SendMessage(hwndFrame, M_REFRESH_COLORS, 0, 0); SendMessage(hwndFrame, M_REFRESH_FONTS, 0, 0); SendMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); RedrawWindow(hwndFrame, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE); break; case WM_TIMECHANGE: /* windows system clock changed */ SendMessage(hwndFrame, M_SET_COUNTDOWN, 0, 0); PostMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); break; case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: SetTextColor((HDC)wParam, dat->clrText); SetBkColor((HDC)wParam, dat->clrBackground); return (INT_PTR)dat->hbrBackground; case WM_ERASEBKGND: { RECT rc; if (dat->hbrBackground != NULL && GetClientRect(hwndFrame, &rc)) { FillRect((HDC)wParam, &rc, dat->hbrBackground); return TRUE; } return FALSE; } case M_SET_COUNTDOWN: if (dat->fTimeFlags&SDWTF_ST_TIME) { dat->settingLastTime = (time_t)db_get_dw(NULL, "AutoShutdown", "TimeStamp", SETTING_TIMESTAMP_DEFAULT); dat->countdown = time(NULL); if (dat->settingLastTime > dat->countdown) dat->countdown = dat->settingLastTime - dat->countdown; else dat->countdown = 0; } else if (dat->flags&FWPDF_COUNTDOWNINVALID) { dat->countdown = (time_t)db_get_dw(NULL, "AutoShutdown", "Countdown", SETTING_COUNTDOWN_DEFAULT); dat->countdown *= (time_t)db_get_dw(NULL, "AutoShutdown", "CountdownUnit", SETTING_COUNTDOWNUNIT_DEFAULT); } dat->flags &= ~FWPDF_COUNTDOWNINVALID; /* commctl 4.70+, Win95: 1-100 will work fine (wrap around) */ SendMessage(dat->hwndProgress, PBM_SETRANGE32, 0, (LPARAM)dat->countdown); return 0; case WM_TIMER: if (dat == NULL) return 0; if (dat->countdown != 0 && !(dat->flags&FWPDF_COUNTDOWNINVALID) && !(dat->flags&FWPDF_PAUSED)) { dat->countdown--; PostMessage(dat->hwndProgress, PBM_STEPIT, 0, 0); } if (IsWindowVisible(hwndFrame)) PostMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); if (dat->countdown == 0) { SendMessage(hwndFrame, M_CLOSE_COUNTDOWN, 0, 0); ServiceShutdown(0, TRUE); ServiceStopWatcher(0, 0); } return 0; case WM_SHOWWINDOW: /* the text is kept unchanged while hidden */ if ((BOOL)wParam) SendMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); break; case M_UPDATE_COUNTDOWN: if (dat->flags&FWPDF_PAUSED && !(dat->flags&FWPDF_PAUSEDSHOWN)) { SetWindowText(dat->hwndTime, TranslateT("Paused")); dat->flags |= FWPDF_PAUSEDSHOWN; } else { TCHAR szOutput[256]; if (dat->fTimeFlags&SDWTF_ST_TIME) GetFormatedDateTime(szOutput, _countof(szOutput), dat->settingLastTime, TRUE); else GetFormatedCountdown(szOutput, _countof(szOutput), dat->countdown); SetWindowText(dat->hwndTime, szOutput); PostMessage(hwndFrame, M_CHECK_CLIPPED, 0, 0); /* update tooltip text (if shown) */ if (dat->hwndToolTip != NULL && !(dat->flags&FWPDF_PAUSED)) { TTTOOLINFO ti; ti.cbSize = sizeof(ti); if (SendMessage(dat->hwndToolTip, TTM_GETCURRENTTOOL, 0, (LPARAM)&ti) && (HWND)ti.uId != dat->hwndIcon) SendMessage(dat->hwndToolTip, TTM_UPDATE, 0, 0); } else dat->flags &= ~FWPDF_PAUSEDSHOWN; } return 0; case M_CLOSE_COUNTDOWN: KillTimer(hwndFrame, 1); dat->countdown = 0; dat->flags &= ~FWPDF_PAUSED; SendMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); dat->flags |= FWPDF_COUNTDOWNINVALID; /* step up to upper range */ SendMessage(dat->hwndProgress, PBM_SETPOS, SendMessage(dat->hwndProgress, PBM_GETRANGE, FALSE, 0), 0); SetWindowLongPtr(dat->hwndProgress, GWL_STYLE, GetWindowLongPtr(dat->hwndProgress, GWL_STYLE) | PBM_SETMARQUEE); SendMessage(dat->hwndProgress, PBM_SETMARQUEE, TRUE, 10); /* marquee for rest of time */ return 0; case M_PAUSE_COUNTDOWN: if (dat->flags&FWPDF_PAUSED) { /* unpause */ dat->flags &= ~(FWPDF_PAUSED | FWPDF_PAUSEDSHOWN); SendMessage(hwndFrame, M_SET_COUNTDOWN, 0, 0); SendMessage(dat->hwndProgress, PBM_SETSTATE, PBST_NORMAL, 0); /* WinVista+ */ } else { /* pause */ dat->flags |= FWPDF_PAUSED; SendMessage(dat->hwndProgress, PBM_SETSTATE, PBST_PAUSED, 0); /* WinVista+ */ } SendMessage(hwndFrame, M_UPDATE_COUNTDOWN, 0, 0); return 0; case WM_CONTEXTMENU: { if (dat->flags & FWPDF_COUNTDOWNINVALID) return 0; POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; if (pt.x == -1 && pt.y == -1) { /* invoked by keyboard */ RECT rc; /* position in middle above rect */ if (!GetWindowRect(hwndFrame, &rc)) return 0; pt.x = rc.left + ((int)(rc.right - rc.left) / 2); pt.y = rc.top + ((int)(rc.bottom - rc.top) / 2); } HMENU hContextMenu = CreatePopupMenu(); if (hContextMenu != NULL) { AppendMenu(hContextMenu, MF_STRING, MENUITEM_PAUSECOUNTDOWN, (dat->flags&FWPDF_PAUSED) ? TranslateT("&Unpause Countdown") : TranslateT("&Pause Countdown")); SetMenuDefaultItem(hContextMenu, MENUITEM_PAUSECOUNTDOWN, FALSE); AppendMenu(hContextMenu, MF_STRING, MENUITEM_STOPCOUNTDOWN, TranslateT("&Cancel Countdown")); TrackPopupMenuEx(hContextMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_HORPOSANIMATION | TPM_VERPOSANIMATION | TPM_RIGHTBUTTON, pt.x, pt.y, hwndFrame, NULL); DestroyMenu(hContextMenu); } } return 0; case WM_LBUTTONDBLCLK: if (!(dat->flags&FWPDF_COUNTDOWNINVALID)) SendMessage(hwndFrame, M_PAUSE_COUNTDOWN, 0, 0); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case MENUITEM_STOPCOUNTDOWN: /* close only countdown window when other watcher types running */ if (dat->fTimeFlags&~(SDWTF_SPECIFICTIME | SDWTF_ST_MASK)) CloseCountdownFrame(); /* something else is running */ else ServiceStopWatcher(0, 0); /* calls CloseCountdownFrame() */ return 0; case MENUITEM_PAUSECOUNTDOWN: SendMessage(hwndFrame, M_PAUSE_COUNTDOWN, 0, 0); return 0; } break; case M_CHECK_CLIPPED: /* for in-place tooltip on dat->hwndTime */ { RECT rc; HDC hdc; SIZE size; HFONT hFontPrev = NULL; TCHAR szOutput[256]; dat->flags &= ~FWPDF_TIMEISCLIPPED; if (GetWindowText(dat->hwndTime, szOutput, _countof(szOutput))) if (GetClientRect(dat->hwndTime, &rc)) { hdc = GetDC(dat->hwndTime); if (hdc != NULL) { if (dat->hFont != NULL) hFontPrev = (HFONT)SelectObject(hdc, dat->hFont); if (GetTextExtentPoint32(hdc, szOutput, (int)mir_tstrlen(szOutput), &size)) if (size.cx >= (rc.right - rc.left)) dat->flags &= FWPDF_TIMEISCLIPPED; if (dat->hFont != NULL) SelectObject(hdc, hFontPrev); ReleaseDC(dat->hwndTime, hdc); } } return 0; } case WM_NOTIFY: if (((NMHDR*)lParam)->hwndFrom == dat->hwndToolTip) switch (((NMHDR*)lParam)->code) { case TTN_SHOW: /* 'in-place' tooltip on dat->hwndTime */ if (dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam == dat->hwndTime) { RECT rc; if (GetWindowRect(dat->hwndTime, &rc)) { SetWindowLongPtr(dat->hwndToolTip, GWL_STYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_STYLE) | TTS_NOANIMATE); SetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE) | WS_EX_TRANSPARENT); SendMessage(dat->hwndToolTip, TTM_ADJUSTRECT, TRUE, (LPARAM)&rc); SetWindowPos(dat->hwndToolTip, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); return TRUE; /* self-defined position */ } } SetWindowLongPtr(dat->hwndToolTip, GWL_STYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_STYLE) & (~TTS_NOANIMATE)); SetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE, GetWindowLongPtr(dat->hwndToolTip, GWL_EXSTYLE) & (~WS_EX_TRANSPARENT)); return 0; case TTN_POP: /* workaround #5: frame does not get redrawn after * in-place tooltip hidden on dat->hwndTime */ RedrawWindow(hwndCountdownFrame, NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE); return 0; case TTN_NEEDTEXT: { NMTTDISPINFO *ttdi = (NMTTDISPINFO*)lParam; if (dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam == dat->hwndTime) { if (GetWindowText(dat->hwndTime, ttdi->szText, _countof(ttdi->szText))) ttdi->lpszText = ttdi->szText; } else if ((HWND)wParam == dat->hwndIcon) ttdi->lpszText = TranslateT("Automatic Shutdown"); else { TCHAR szTime[_countof(ttdi->szText)]; if (dat->fTimeFlags&SDWTF_ST_TIME) GetFormatedDateTime(szTime, _countof(szTime), dat->settingLastTime, FALSE); else GetFormatedCountdown(szTime, _countof(szTime), dat->countdown); mir_sntprintf(ttdi->szText, _T("%s %s"), (dat->fTimeFlags&SDWTF_ST_TIME) ? TranslateT("Shutdown at:") : TranslateT("Time left:"), szTime); ttdi->lpszText = ttdi->szText; } return 0; } } break; } return DefWindowProc(hwndFrame, msg, wParam, lParam); }