From f4b7593953d6df6004cf6fa65e5ec256ed13c9da Mon Sep 17 00:00:00 2001 From: aubymori Date: Thu, 10 Oct 2024 23:37:27 -0500 Subject: [PATCH] Add hibernate, add /lang arg --- ClassicShutdown/ClassicShutdown.cpp | 52 ++++-- ClassicShutdown/ClassicShutdown.h | 4 +- ClassicShutdown/ClassicShutdown.vcxproj.user | 17 +- ClassicShutdown/ExitWindowsDlg.cpp | 29 ++- ClassicShutdown/FriendlyDlg.cpp | 181 ++++++++++++------- ClassicShutdown/LogoffDlg.cpp | 2 - ClassicShutdown/mui.c | 31 ++-- ClassicShutdown/mui.h | 3 +- ClassicShutdown/resource.h | 7 +- en-US/en-US.rc | 7 +- ja-JP/ja-JP.rc | 7 +- 11 files changed, 214 insertions(+), 126 deletions(-) diff --git a/ClassicShutdown/ClassicShutdown.cpp b/ClassicShutdown/ClassicShutdown.cpp index 5078f96..5f2d550 100644 --- a/ClassicShutdown/ClassicShutdown.cpp +++ b/ClassicShutdown/ClassicShutdown.cpp @@ -16,6 +16,7 @@ HWND g_hDesktopWnd, g_hDlg; HBITMAP g_hbDesktop; HINSTANCE g_hAppInstance, g_hMuiInstance, g_hShell32; BOOL g_bLogoff; +BOOL g_bHibernationAvailable; SHUTDOWNSTYLE g_ssStyle; BrandingLoadImage_t BrandingLoadImage = nullptr; @@ -63,8 +64,11 @@ void HandleShutdown(HWND hWnd, DWORD dwCode) case SHTDN_STANDBY: SetSuspendState(FALSE, TRUE, FALSE); break; - case SHTDN_LOCK: - LockWorkStation(); + case SHTDN_HIBER: + SetSuspendState(TRUE, FALSE, FALSE); + break; + case SHTDN_DISCONNECT: + WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, FALSE); break; default: { @@ -154,15 +158,14 @@ int WINAPI wWinMain( ShowWindow(hFader, SW_HIDE); } - /* Set up HINSTANCEs */ - g_hAppInstance = hInstance; - g_hMuiInstance = GetMUIModule(g_hAppInstance); - if (!g_hMuiInstance) - { - ERRORANDQUIT( - L"Failed to load language resources.\n\nMost likely, you did not copy over files properly." - ); - } + /* Check if hibernation is available */ + SYSTEM_POWER_CAPABILITIES spc = { 0 }; + CallNtPowerInformation( + SystemPowerCapabilities, + NULL, NULL, + &spc, sizeof(spc) + ); + g_bHibernationAvailable = spc.HiberFilePresent; CDimmedWindow *pDimmedWindow = NULL; @@ -194,6 +197,7 @@ int WINAPI wWinMain( LPWSTR *argv = CommandLineToArgvW( lpCmdLine, &argc ); + WCHAR szLocale[LOCALE_NAME_MAX_LENGTH] = { 0 }; for (int i = 0; i < argc; i++) { if (!_wcsicmp(argv[i], L"/logoff")) @@ -240,6 +244,32 @@ int WINAPI wWinMain( g_ssStyle = SS_CLASSIC; } } + else if (!_wcsicmp(argv[i], L"/lang")) + { + if (i + 1 != argc) + { + wcscpy_s(szLocale, LOCALE_NAME_MAX_LENGTH, argv[i + 1]); + } + else + { + MessageBoxW( + NULL, + L"No value defined for /lang parameter, defaulting to system locale.", + L"ClassicShutdown", + MB_ICONWARNING + ); + } + } + } + + /* Set up HINSTANCEs */ + g_hAppInstance = hInstance; + g_hMuiInstance = GetMUIModule(g_hAppInstance, szLocale); + if (!g_hMuiInstance) + { + ERRORANDQUIT( + L"Failed to load language resources.\n\nMost likely, you did not copy over files properly." + ); } if (IsXP(g_ssStyle)) diff --git a/ClassicShutdown/ClassicShutdown.h b/ClassicShutdown/ClassicShutdown.h index 6edeac8..8727e0e 100644 --- a/ClassicShutdown/ClassicShutdown.h +++ b/ClassicShutdown/ClassicShutdown.h @@ -8,6 +8,7 @@ extern HWND g_hDesktopWnd, g_hDlg; extern HBITMAP g_hbDesktop; extern HINSTANCE g_hAppInstance, g_hMuiInstance, g_hShell32; extern BOOL g_bLogoff; +extern BOOL g_bHibernationAvailable; extern LPDWORD g_dwRes; typedef HANDLE (WINAPI *BrandingLoadImage_t)( @@ -44,6 +45,7 @@ return 1; #define SHTDN_SHUTDOWN 2 #define SHTDN_RESTART 3 #define SHTDN_STANDBY 4 -#define SHTDN_LOCK 5 +#define SHTDN_HIBER 5 +#define SHTDN_DISCONNECT 6 #endif \ No newline at end of file diff --git a/ClassicShutdown/ClassicShutdown.vcxproj.user b/ClassicShutdown/ClassicShutdown.vcxproj.user index 88a5509..77e3816 100644 --- a/ClassicShutdown/ClassicShutdown.vcxproj.user +++ b/ClassicShutdown/ClassicShutdown.vcxproj.user @@ -1,4 +1,19 @@  - + + /style xp + WindowsLocalDebugger + + + /style xp + WindowsLocalDebugger + + + /style xp + WindowsLocalDebugger + + + /style xp + WindowsLocalDebugger + \ No newline at end of file diff --git a/ClassicShutdown/ExitWindowsDlg.cpp b/ClassicShutdown/ExitWindowsDlg.cpp index 4a20d82..d09dc3b 100644 --- a/ClassicShutdown/ExitWindowsDlg.cpp +++ b/ClassicShutdown/ExitWindowsDlg.cpp @@ -6,7 +6,7 @@ #ifndef _ExitWindowsDlg_ #define _ExitWindowsDlg_ -HBITMAP g_hbBrand; +HBITMAP s_hbBrand; void MoveChildren(HWND hWnd, int dx, int dy) { @@ -68,15 +68,7 @@ INT_PTR CALLBACK ExitWindowsDlgProc( { case WM_INITDIALOG: { - HINSTANCE hBasebrd = LoadLibraryW(L"C:\\Windows\\Branding\\Basebrd\\basebrd.dll"); - if (!hBasebrd) - { - MessageBoxW(NULL, L"Failed to load basebrd.dll!", L"ClassicShutdown", MB_ICONERROR); - HandleShutdown(hWnd, SHTDN_NONE); - return FALSE; - } - - g_hbBrand = GetBrandingBitmap(); + s_hbBrand = GetBrandingBitmap(); HICON hShutDown = LoadIconW( g_hShell32, @@ -92,7 +84,7 @@ INT_PTR CALLBACK ExitWindowsDlgProc( /* Resize window to account for branding banner */ BITMAP bmBrand; - GetObjectW(g_hbBrand, sizeof(BITMAP), &bmBrand); + GetObjectW(s_hbBrand, sizeof(BITMAP), &bmBrand); RECT rcClient; GetClientRect(hWnd, &rcClient); @@ -139,7 +131,7 @@ INT_PTR CALLBACK ExitWindowsDlgProc( } HWND hComboBox = GetDlgItem(hWnd, IDD_EXITWINDOWS_COMBOBOX); - WCHAR szLogoffFormat[64], szLogoff[300], szShutdown[64], szRestart[64], szStandby[64], szLock[64], szUsername[UNLEN + 1]; + WCHAR szLogoffFormat[64], szLogoff[300], szShutdown[64], szRestart[64], szStandby[64], szHiber[64], szUsername[UNLEN + 1]; LoadStringW(g_hMuiInstance, IDS_LOGOFF, szLogoffFormat, 64); @@ -151,13 +143,14 @@ INT_PTR CALLBACK ExitWindowsDlgProc( LoadStringW(g_hMuiInstance, IDS_SHUTDOWN, szShutdown, 64); LoadStringW(g_hMuiInstance, IDS_RESTART, szRestart, 64); LoadStringW(g_hMuiInstance, IDS_STANDBY, szStandby, 64); - LoadStringW(g_hMuiInstance, IDS_LOCK, szLock, 64); + LoadStringW(g_hMuiInstance, IDS_HIBER, szHiber, 64); SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szLogoff); SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szShutdown); SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szRestart); SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szStandby); - SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szLock); + if (g_bHibernationAvailable) + SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)szHiber); SendMessageW(hComboBox, CB_SETCURSEL, 1, 0); WCHAR szShutdownDesc[256]; @@ -191,10 +184,10 @@ INT_PTR CALLBACK ExitWindowsDlgProc( HDC hDC = BeginPaint(hWnd, &ps); HDC hDCMem = CreateCompatibleDC(hDC); - HBITMAP hbmOld = (HBITMAP)SelectObject(hDCMem, g_hbBrand); + HBITMAP hbmOld = (HBITMAP)SelectObject(hDCMem, s_hbBrand); BITMAP bmBrand; - GetObjectW(g_hbBrand, sizeof(BITMAP), &bmBrand); + GetObjectW(s_hbBrand, sizeof(BITMAP), &bmBrand); BitBlt( hDC, @@ -237,8 +230,8 @@ INT_PTR CALLBACK ExitWindowsDlgProc( case SHTDN_STANDBY: uStringId = IDS_STANDBY_DESC; break; - case SHTDN_LOCK: - uStringId = IDS_LOCK_DESC; + case SHTDN_HIBER: + uStringId = IDS_HIBER_DESC; break; } diff --git a/ClassicShutdown/FriendlyDlg.cpp b/ClassicShutdown/FriendlyDlg.cpp index cc19573..b84b5e6 100644 --- a/ClassicShutdown/FriendlyDlg.cpp +++ b/ClassicShutdown/FriendlyDlg.cpp @@ -3,21 +3,22 @@ #include -RECT rcBkgnd, rcFlag, rcBtns; -HBITMAP hbmBkgnd, hbmFlag, hbmBtns; -HFONT hfntTitle, hfntBtn; -UINT uFocusId, uHoverId; -HWND hTooltip; +#define TIMER_HIBERNATE 0x1 -LPDWORD g_dwRes; +static RECT s_rcBkgnd, s_rcFlag, s_rcBtns; +static HBITMAP s_hbmBkgnd, s_hbmFlag, s_hbmBtns; +static HFONT s_hfntTitle, s_hfntBtn; +static UINT s_uFocusId, s_uHoverId; +static HWND s_hTooltip = NULL; +static BOOL s_bShiftDown = FALSE; -const UINT uExitIds[] = { +const UINT c_uExitIds[] = { IDC_BUTTON_STANDBY, IDC_BUTTON_TURNOFF, IDC_BUTTON_RESTART }; -const UINT uLogoffIds[] = { +const UINT c_uLogoffIds[] = { IDC_BUTTON_SWITCHUSER, IDC_BUTTON_LOGOFF }; @@ -122,7 +123,7 @@ LRESULT CALLBACK BtnSubclassProc( case BM_SETSTYLE: if (wParam == BS_DEFPUSHBUTTON) { - uFocusId = uIdCtl; + s_uFocusId = uIdCtl; } if (uIdCtl != IDCANCEL) @@ -135,10 +136,10 @@ LRESULT CALLBACK BtnSubclassProc( switch (uMsg) { case DM_GETDEFID: - lRes = (DC_HASDEFID << 16) | (WORD)uFocusId; + lRes = (DC_HASDEFID << 16) | (WORD)s_uFocusId; break; case WM_GETDLGCODE: - if (uIdCtl == uFocusId) + if (uIdCtl == s_uFocusId) { lRes = DLGC_DEFPUSHBUTTON; } @@ -149,10 +150,10 @@ LRESULT CALLBACK BtnSubclassProc( break; case WM_MOUSEMOVE: SetCursor(LoadCursorW(NULL, IDC_HAND)); - if (uIdCtl != uHoverId) + if (uIdCtl != s_uHoverId) { TRACKMOUSEEVENT tme; - uHoverId = uIdCtl; + s_uHoverId = uIdCtl; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_HOVER | TME_LEAVE; tme.hwndTrack = hWnd; @@ -170,7 +171,10 @@ LRESULT CALLBACK BtnSubclassProc( iTxtId = IDS_TURNOFF_TOOLTIP_TEXT_TURNOFF; break; case IDC_BUTTON_STANDBY: - iTxtId = IDS_TURNOFF_TOOLTIP_TEXT_STANDBY; + if (g_bHibernationAvailable) + iTxtId = s_bShiftDown ? IDS_TURNOFF_TOOLTIP_TEXT_HIBERNATE : IDS_TURNOFF_TOOLTIP_TEXT_STANDBY_HIBERNATE; + else + iTxtId = IDS_TURNOFF_TOOLTIP_TEXT_STANDBY; break; case IDC_BUTTON_RESTART: iTxtId = IDS_TURNOFF_TOOLTIP_TEXT_RESTART; @@ -186,7 +190,7 @@ LRESULT CALLBACK BtnSubclassProc( break; } - hTooltip = CreateWindowExW( + s_hTooltip = CreateWindowExW( 0, TOOLTIPS_CLASS, NULL, @@ -201,28 +205,28 @@ LRESULT CALLBACK BtnSubclassProc( NULL ); - if (hTooltip) + if (s_hTooltip) { - SetWindowPos(hTooltip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - SendMessageW(hTooltip, CCM_SETVERSION, COMCTL32_VERSION, 0); + SetWindowPos(s_hTooltip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + SendMessageW(s_hTooltip, CCM_SETVERSION, COMCTL32_VERSION, 0); TOOLINFOW ti = { 0 }; - WCHAR szText[256]; + WCHAR szText[256] = { 0 }; LoadStringW( g_hMuiInstance, iTxtId, szText + 2, - 252 + 254 ); szText[0] = L'\r'; szText[1] = L'\n'; ti.cbSize = sizeof(TOOLINFOW); ti.uFlags = TTF_TRANSPARENT | TTF_TRACK; - ti.uId = PtrToUint(hTooltip); + ti.uId = PtrToUint(s_hTooltip); ti.lpszText = szText; - SendMessageW(hTooltip, TTM_ADDTOOLW, 0, (LPARAM)&ti); - SendMessageW(hTooltip, TTM_SETMAXTIPWIDTH, 0, 300); + SendMessageW(s_hTooltip, TTM_ADDTOOLW, 0, (LPARAM)&ti); + SendMessageW(s_hTooltip, TTM_SETMAXTIPWIDTH, 0, 300); RECT rc; LONG lPosX, lPosY; @@ -230,39 +234,39 @@ LRESULT CALLBACK BtnSubclassProc( GetWindowRect(hWnd, &rc); lPosX = (rc.left + rc.right) / 2; lPosY = rc.bottom; - SendMessageW(hTooltip, TTM_TRACKPOSITION, 0, MAKELONG(lPosX, lPosY)); + SendMessageW(s_hTooltip, TTM_TRACKPOSITION, 0, MAKELONG(lPosX, lPosY)); LPWSTR szCaption; int iCapLen; + HWND hTextWnd = hWnd; + if (uIdCtl == IDC_BUTTON_STANDBY && s_bShiftDown) + hTextWnd = GetDlgItem(GetParent(hWnd), IDC_BUTTON_HIBERNATE); - iCapLen = GetWindowTextLengthW(hWnd); - szCaption = (LPWSTR)malloc(sizeof(WCHAR) * iCapLen + 1); + iCapLen = GetWindowTextLengthW(hTextWnd); + szCaption = new WCHAR[iCapLen + 1]; if (szCaption) - { - GetWindowTextW(hWnd, szCaption, iCapLen + 1); + { + GetWindowTextW(hTextWnd, szCaption, iCapLen + 1); FilterMetaCharacters(szCaption); - SendMessageW(hTooltip, TTM_SETTITLE, 0, (LPARAM)szCaption); + SendMessageW(s_hTooltip, TTM_SETTITLE, 0, (LPARAM)szCaption); } - SendMessageW(hTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti); + SendMessageW(s_hTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti); if (szCaption) - { - free(szCaption); - } + delete[] szCaption; } break; } case WM_MOUSELEAVE: - DestroyWindow(hTooltip); - uHoverId = 0; + DestroyWindow(s_hTooltip); + s_uHoverId = 0; case WM_KILLFOCUS: if (uMsg == WM_KILLFOCUS) - uFocusId = 0; + s_uFocusId = 0; InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); break; - } } @@ -282,35 +286,35 @@ INT_PTR CALLBACK FriendlyDlgProc( { BITMAP bm; - hbmBkgnd = (HBITMAP)LoadImageW( + s_hbmBkgnd = (HBITMAP)LoadImageW( g_hAppInstance, MAKEINTRESOURCEW(IDB_BACKGROUND), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION ); - GetObject(hbmBkgnd, sizeof(BITMAP), &bm); - SetRect(&rcBkgnd, 0, 0, bm.bmWidth, bm.bmHeight); + GetObject(s_hbmBkgnd, sizeof(BITMAP), &bm); + SetRect(&s_rcBkgnd, 0, 0, bm.bmWidth, bm.bmHeight); - hbmFlag = (HBITMAP)LoadImageW( + s_hbmFlag = (HBITMAP)LoadImageW( g_hAppInstance, MAKEINTRESOURCEW(IDB_FLAG), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION ); - GetObject(hbmFlag, sizeof(BITMAP), &bm); - SetRect(&rcFlag, 0, 0, bm.bmWidth, bm.bmHeight); + GetObject(s_hbmFlag, sizeof(BITMAP), &bm); + SetRect(&s_rcFlag, 0, 0, bm.bmWidth, bm.bmHeight); - hbmBtns = (HBITMAP)LoadImageW( + s_hbmBtns = (HBITMAP)LoadImageW( g_hAppInstance, g_bLogoff ? MAKEINTRESOURCEW(IDB_LOGOFF_BUTTONS) : MAKEINTRESOURCEW(IDB_BUTTONS), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION ); - GetObject(hbmBtns, sizeof(BITMAP), &bm); - SetRect(&rcBtns, 0, 0, bm.bmWidth, bm.bmHeight); + GetObject(s_hbmBtns, sizeof(BITMAP), &bm); + SetRect(&s_rcBtns, 0, 0, bm.bmWidth, bm.bmHeight); HDC hDCScreen = GetDC(NULL); LOGFONTW lf = { 0 }; @@ -334,12 +338,10 @@ INT_PTR CALLBACK FriendlyDlgProc( { lf.lfWeight = FW_MEDIUM; lf.lfQuality = DEFAULT_QUALITY; - hfntTitle = CreateFontIndirectW(&lf); + s_hfntTitle = CreateFontIndirectW(&lf); } } - //ZeroMemory(&lf, sizeof(LOGFONTW)); - /* Button font */ if (LoadStringA( g_hMuiInstance, @@ -358,14 +360,14 @@ INT_PTR CALLBACK FriendlyDlgProc( { lf.lfWeight = FW_BOLD; lf.lfQuality = DEFAULT_QUALITY; - hfntBtn = CreateFontIndirectW(&lf); + s_hfntBtn = CreateFontIndirectW(&lf); } } ReleaseDC(NULL, hDCScreen); - const UINT *lpItemIds = g_bLogoff ? uLogoffIds : uExitIds; - int len = g_bLogoff ? ARRAYSIZE(uLogoffIds) : ARRAYSIZE(uExitIds); + const UINT *lpItemIds = g_bLogoff ? c_uLogoffIds : c_uExitIds; + int len = g_bLogoff ? ARRAYSIZE(c_uLogoffIds) : ARRAYSIZE(c_uExitIds); for (int i = 0; i < len; i++) { @@ -379,11 +381,57 @@ INT_PTR CALLBACK FriendlyDlgProc( PositionDlg(hWnd); - uFocusId = g_bLogoff ? IDC_BUTTON_SWITCHUSER : IDC_BUTTON_STANDBY; - SetFocus(GetDlgItem(hWnd, uFocusId)); - SendMessageW(hWnd, DM_SETDEFID, uFocusId, 0); + s_uFocusId = g_bLogoff ? IDC_BUTTON_SWITCHUSER : IDC_BUTTON_STANDBY; + SetFocus(GetDlgItem(hWnd, s_uFocusId)); + SendMessageW(hWnd, DM_SETDEFID, s_uFocusId, 0); + + if (!g_bLogoff && g_bHibernationAvailable) + { + OutputDebugStringW(L"Setting timer\r\n"); + SetTimer(hWnd, TIMER_HIBERNATE, 50, NULL); + } break; } + case WM_TIMER: + { + BOOL bNewShiftDown = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (bNewShiftDown != s_bShiftDown) + { + s_bShiftDown = bNewShiftDown; + + RECT rc; + HWND hWndText = GetDlgItem(hWnd, IDC_TEXT_STANDBY); + GetClientRect(hWndText, &rc); + MapWindowPoints(hWndText, hWnd, (POINT *)&rc, 2); + InvalidateRect(hWnd, &rc, TRUE); + + if (s_uHoverId == IDC_BUTTON_STANDBY) + { + // Destroy current tooltip + if (s_hTooltip && IsWindow(s_hTooltip)) + { + DestroyWindow(s_hTooltip); + s_hTooltip = NULL; + + // Show tooltip for new action + // Windows XP relies on WM_MOUSEHOVER being automatically sent after the original + // For whatever reason this doesn't happen, so we just send it ourself + // + // Separate thread because we need to wait for a time before doing it and locking up + // the thread here results in the text below the button disappearing + CreateThread(NULL, NULL, [](LPVOID lpParam) -> DWORD { + HWND hWnd = (HWND)lpParam; + Sleep(400); + if (s_uHoverId == IDC_BUTTON_STANDBY) + SendDlgItemMessageW(hWnd, IDC_BUTTON_STANDBY, WM_MOUSEHOVER, 0, 0); + ExitThread(0); + return 0; + }, hWnd, NULL, NULL); + } + } + } + return 0; + } case WM_CLOSE: HandleShutdown(hWnd, SHTDN_NONE); break; @@ -398,13 +446,16 @@ INT_PTR CALLBACK FriendlyDlgProc( HandleShutdown(hWnd, SHTDN_SHUTDOWN); break; case IDC_BUTTON_STANDBY: - HandleShutdown(hWnd, SHTDN_STANDBY); + HandleShutdown( + hWnd, + (g_bHibernationAvailable && s_bShiftDown) ? SHTDN_HIBER : SHTDN_STANDBY + ); break; case IDC_BUTTON_RESTART: HandleShutdown(hWnd, SHTDN_RESTART); break; case IDC_BUTTON_SWITCHUSER: - HandleShutdown(hWnd, SHTDN_LOCK); + HandleShutdown(hWnd, SHTDN_DISCONNECT); break; case IDC_BUTTON_LOGOFF: HandleShutdown(hWnd, SHTDN_LOGOFF); @@ -421,7 +472,7 @@ INT_PTR CALLBACK FriendlyDlgProc( RECT rc; GetClientRect(hWnd, &rc); - PaintBitmap(hDC, &rc, hbmBkgnd, &rcBkgnd); + PaintBitmap(hDC, &rc, s_hbmBkgnd, &s_rcBkgnd); EndPaint(hWnd, &ps); } @@ -429,7 +480,7 @@ INT_PTR CALLBACK FriendlyDlgProc( { RECT rc; GetClientRect(hWnd, &rc); - PaintBitmap((HDC)wParam, &rc, hbmBkgnd, &rcBkgnd); + PaintBitmap((HDC)wParam, &rc, s_hbmBkgnd, &s_rcBkgnd); } case WM_PRINTCLIENT: if ((lParam & (PRF_ERASEBKGND | PRF_CLIENT)) != 0) @@ -460,7 +511,7 @@ INT_PTR CALLBACK FriendlyDlgProc( SIZE sz; WCHAR szText[256]; - HFONT hfOld = (HFONT)SelectObject(pDIS->hDC, hfntTitle); + HFONT hfOld = (HFONT)SelectObject(pDIS->hDC, s_hfntTitle); COLORREF crOld = SetTextColor(pDIS->hDC, RGB(255, 255, 255)); int iBkOld = SetBkMode(pDIS->hDC, TRANSPARENT); @@ -496,7 +547,7 @@ INT_PTR CALLBACK FriendlyDlgProc( switch (wParam) { case IDC_TEXT_STANDBY: - uBtnId = IDC_BUTTON_STANDBY; + uBtnId = (g_bHibernationAvailable && s_bShiftDown) ? IDC_BUTTON_HIBERNATE : IDC_BUTTON_STANDBY; break; case IDC_TEXT_TURNOFF: uBtnId = IDC_BUTTON_TURNOFF; @@ -513,7 +564,7 @@ INT_PTR CALLBACK FriendlyDlgProc( } - HFONT hfOld = (HFONT)SelectObject(pDIS->hDC, hfntBtn); + HFONT hfOld = (HFONT)SelectObject(pDIS->hDC, s_hfntBtn); COLORREF crOld = SetTextColor(pDIS->hDC, RGB(255, 255, 255)); int iBkOld = SetBkMode(pDIS->hDC, TRANSPARENT); @@ -581,7 +632,7 @@ INT_PTR CALLBACK FriendlyDlgProc( { iVOffset++; } - else if (uHoverId == wParam || uFocusId == wParam || (pDIS->itemState & ODS_FOCUS)) + else if (s_uHoverId == wParam || s_uFocusId == wParam || (pDIS->itemState & ODS_FOCUS)) { iVOffset += 2; } @@ -597,12 +648,12 @@ INT_PTR CALLBACK FriendlyDlgProc( ); PaintBitmap( - pDIS->hDC, &pDIS->rcItem, hbmBtns, &rc + pDIS->hDC, &pDIS->rcItem, s_hbmBtns, &rc ); break; } case IDC_TITLE_FLAG: - PaintBitmap(pDIS->hDC, &pDIS->rcItem, hbmFlag, &rcFlag); + PaintBitmap(pDIS->hDC, &pDIS->rcItem, s_hbmFlag, &s_rcFlag); break; } } diff --git a/ClassicShutdown/LogoffDlg.cpp b/ClassicShutdown/LogoffDlg.cpp index bf451de..71a32d8 100644 --- a/ClassicShutdown/LogoffDlg.cpp +++ b/ClassicShutdown/LogoffDlg.cpp @@ -89,6 +89,4 @@ INT_PTR CALLBACK LogoffDlgProc( default: return FALSE; } - - return TRUE; } \ No newline at end of file diff --git a/ClassicShutdown/mui.c b/ClassicShutdown/mui.c index bb43b34..3cc7bb8 100644 --- a/ClassicShutdown/mui.c +++ b/ClassicShutdown/mui.c @@ -1,6 +1,6 @@ #include "mui.h" -HMODULE GetMUIModule(HMODULE hMod) +HMODULE GetMUIModule(HMODULE hMod, LPCWSTR lpLocale) { HMODULE hMui; WCHAR szPath[MAX_PATH]; @@ -16,12 +16,17 @@ HMODULE GetMUIModule(HMODULE hMod) } WCHAR szLocale[LOCALE_NAME_MAX_LENGTH]; - if (!GetUserDefaultLocaleName( - szLocale, - LOCALE_NAME_MAX_LENGTH - )) + if (!lpLocale || !lpLocale[0]) { - return NULL; + if (!GetUserDefaultLocaleName( + szLocale, + LOCALE_NAME_MAX_LENGTH + )) + return NULL; + } + else + { + wcscpy_s(szLocale, LOCALE_NAME_MAX_LENGTH, lpLocale); } WCHAR *pBackslash = wcsrchr(szPath, L'\\'); @@ -56,19 +61,5 @@ HMODULE GetMUIModule(HMODULE hMod) return hMui; } - return NULL; -} - -HMODULE LoadMUIModule(LPWSTR lpLibFileName) -{ - HMODULE hTemp = LoadLibraryW(lpLibFileName); - - if (hTemp) - { - HMODULE hRet = GetMUIModule(hTemp); - FreeLibrary(hTemp); - return hRet; - } - return NULL; } \ No newline at end of file diff --git a/ClassicShutdown/mui.h b/ClassicShutdown/mui.h index e590f79..e313f7a 100644 --- a/ClassicShutdown/mui.h +++ b/ClassicShutdown/mui.h @@ -19,8 +19,7 @@ extern "C" #endif #define FALLBACK_LOCALE L"en-US" - HMODULE GetMUIModule(HMODULE hMod); - HMODULE LoadMUIModule(LPWSTR lpLibFileName); + HMODULE GetMUIModule(HMODULE hMod, LPCWSTR lpLocale); #ifdef __cplusplus } #endif diff --git a/ClassicShutdown/resource.h b/ClassicShutdown/resource.h index 62c2ece..6255d66 100644 --- a/ClassicShutdown/resource.h +++ b/ClassicShutdown/resource.h @@ -16,8 +16,8 @@ #define IDS_RESTART_DESC 305 #define IDS_STANDBY 306 #define IDS_STANDBY_DESC 307 -#define IDS_LOCK 308 -#define IDS_LOCK_DESC 309 +#define IDS_HIBER 308 +#define IDS_HIBER_DESC 309 /* XP Classic Log Off button (replaces Yes) */ #define IDS_LOGOFF_BTN 310 @@ -34,6 +34,7 @@ #define IDC_BUTTON_TURNOFF 20103 #define IDC_BUTTON_STANDBY 20104 #define IDC_BUTTON_RESTART 20105 +#define IDC_BUTTON_HIBERNATE 20106 #define IDC_TEXT_TURNOFF 20107 #define IDC_TEXT_STANDBY 20108 #define IDC_TEXT_RESTART 20109 @@ -50,7 +51,9 @@ #define IDS_TURNOFF_BUTTON_FACESIZE 20128 #define IDS_TURNOFF_TOOLTIP_TEXT_TURNOFF 20129 #define IDS_TURNOFF_TOOLTIP_TEXT_STANDBY 20130 +#define IDS_TURNOFF_TOOLTIP_TEXT_STANDBY_HIBERNATE 20131 #define IDS_TURNOFF_TOOLTIP_TEXT_RESTART 20132 +#define IDS_TURNOFF_TOOLTIP_TEXT_HIBERNATE 20133 #define IDS_SWITCHUSER_TOOLTIP_TEXT_SWITCHUSER 0x380d #define IDS_SWITCHUSER_TOOLTIP_TEXT_LOGOFF 0x380e diff --git a/en-US/en-US.rc b/en-US/en-US.rc index ac9c8ab..bc5dafa 100644 --- a/en-US/en-US.rc +++ b/en-US/en-US.rc @@ -40,8 +40,8 @@ STRINGTABLE IDS_RESTART_DESC "Ends your session, shuts down Windows, and starts Windows again." IDS_STANDBY "Stand by" IDS_STANDBY_DESC "Maintains your session, keeping the computer running on low power with data still in memory." - IDS_LOCK "Lock" - IDS_LOCK_DESC "Maintains your session, requiring you to log in to access your desktop again." + IDS_HIBER "Hibernate" + IDS_HIBER_DESC "Saves your session to disk so that you can safely turn off power. Your session is restored the next time you start Windows." IDS_LOGOFF_BTN "&Log Off" IDS_CANCEL_BTN "Cancel" } @@ -57,6 +57,7 @@ FONT 8, "MS Shell Dlg" CONTROL "&Stand By", IDC_BUTTON_STANDBY, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 36, 49, 22, 20 CONTROL "T&urn Off", IDC_BUTTON_TURNOFF, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 93, 49, 22, 20 CONTROL "&Restart", IDC_BUTTON_RESTART, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 150, 49, 22, 20 + CONTROL "&Hibernate", IDC_BUTTON_HIBERNATE, BUTTON, BS_PUSHBUTTON | BS_NOTIFY | WS_CHILD | WS_VISIBLE, 30093, 30049, 22, 20 CONTROL "", IDC_TEXT_STANDBY, "Static", SS_OWNERDRAW | WS_DISABLED, 22, 73, 50, 8 CONTROL "", IDC_TEXT_TURNOFF, "Static", SS_OWNERDRAW | WS_DISABLED, 79, 73, 50, 8 CONTROL "", IDC_TEXT_RESTART, "Static", SS_OWNERDRAW | WS_DISABLED, 136, 73, 50, 8 @@ -85,6 +86,8 @@ STRINGTABLE DISCARDABLE IDS_TURNOFF_BUTTON_FACESIZE "8" IDS_TURNOFF_TOOLTIP_TEXT_TURNOFF "Shuts down Windows so that you can safely turn off the computer." IDS_TURNOFF_TOOLTIP_TEXT_STANDBY "Puts your computer in a low-power state so that you can quickly resume your Windows session." + IDS_TURNOFF_TOOLTIP_TEXT_STANDBY_HIBERNATE "Puts your computer in a low-power state so that you can quickly resume your Windows session.\r\n\r\nTo hibernate instead, hold down the Shift key." + IDS_TURNOFF_TOOLTIP_TEXT_HIBERNATE "Saves your current desktop state to your hard disk so that you can resume where you left off, then shuts down your computer." IDS_TURNOFF_TOOLTIP_TEXT_RESTART "Shuts down Windows and then starts Windows again." IDS_SWITCHUSER_TOOLTIP_TEXT_SWITCHUSER "Lets another user log on while your programs and files remain open.\r\n\r\n(You can also switch users by pressing the Windows logo key + L.)" IDS_SWITCHUSER_TOOLTIP_TEXT_LOGOFF "Closes your programs and ends your Windows session." diff --git a/ja-JP/ja-JP.rc b/ja-JP/ja-JP.rc index 2a8443a..d4d7f4f 100644 --- a/ja-JP/ja-JP.rc +++ b/ja-JP/ja-JP.rc @@ -40,8 +40,8 @@ STRINGTABLE IDS_RESTART_DESC "セッションを終了し、Windows をシャットダウンして再起動します。" IDS_STANDBY "スタンバイ" IDS_STANDBY_DESC "データがメモリにある状態で、コンピュータを低電力で実行したままセッションを維持します。" - IDS_LOCK "ロックする" - IDS_LOCK_DESC "セッションを維持し、デスクトップに再アクセスするにはログインが必要です。" + IDS_HIBER "休止状態" + IDS_HIBER_DESC "セッションをディスクに保存して、電源を安全に切れるようにします。セッションは次回 Windows を再起動すると復元されます。" IDS_LOGOFF_BTN "ログオフ(&L)" IDS_CANCEL_BTN "キャンセル" } @@ -57,6 +57,7 @@ FONT 8, "MS Shell Dlg" CONTROL "スタンバイ(&S)", IDC_BUTTON_STANDBY, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 36, 49, 22, 20 CONTROL "電源を切る(&U)", IDC_BUTTON_TURNOFF, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 93, 49, 22, 20 CONTROL "再起動(&R)", IDC_BUTTON_RESTART, "Button", BS_OWNERDRAW | BS_NOTIFY | WS_TABSTOP, 150, 49, 22, 20 + CONTROL "休止状態(&H)", IDC_BUTTON_HIBERNATE, BUTTON, BS_PUSHBUTTON | BS_NOTIFY | WS_CHILD | WS_VISIBLE, 30093, 30049, 22, 20 CONTROL "", IDC_TEXT_STANDBY, "Static", SS_OWNERDRAW | WS_DISABLED, 20, 73, 54, 8 CONTROL "", IDC_TEXT_TURNOFF, "Static", SS_OWNERDRAW | WS_DISABLED, 77, 73, 54, 8 CONTROL "", IDC_TEXT_RESTART, "Static", SS_OWNERDRAW | WS_DISABLED, 134, 73, 54, 8 @@ -85,6 +86,8 @@ STRINGTABLE DISCARDABLE IDS_TURNOFF_BUTTON_FACESIZE "8" IDS_TURNOFF_TOOLTIP_TEXT_TURNOFF "安全にコンピュータの電源を切るために Windows をシャットダウンします。" IDS_TURNOFF_TOOLTIP_TEXT_STANDBY "コンピュータを低電力の状態にし、 Windows セッションをすばやく再開できるようにします。" + IDS_TURNOFF_TOOLTIP_TEXT_STANDBY_HIBERNATE "コンピュータを低電力の状態にし、Windows セッションをすばやく再開できるようにします。\r\n\r\n休止状態にするには、Shift キーを押してください。" + IDS_TURNOFF_TOOLTIP_TEXT_HIBERNATE "現在のデスクトップの状態をハード ディスクに保存し、コンピュータをシャットダウンします。次回起動したときには、現在の状態が再現されます。" IDS_TURNOFF_TOOLTIP_TEXT_RESTART "Windows をシャットダウンして再起動します。" IDS_SWITCHUSER_TOOLTIP_TEXT_SWITCHUSER "プログラムやファイルが開いたままで、ほかのユーザーがログオンできます。\r\n\r\n(Windows ロゴキーと "L" を同時に押すとユーザーを切り替えることができます。)" IDS_SWITCHUSER_TOOLTIP_TEXT_LOGOFF "プログラムを閉じて Windows セッションを終了します。"