99 */
1010
1111#include "msgina.h"
12- #include <powrprof.h>
1312#include <wingdi.h>
1413#include <windowsx.h>
1514#include <commctrl.h>
15+ #include <ndk/pofuncs.h>
1616
1717/* Macros for fancy shutdown dialog */
1818#define FONT_POINT_SIZE 13
@@ -587,7 +587,7 @@ CreateToolTipForButtons(
587587 CW_USEDEFAULT , CW_USEDEFAULT ,
588588 hDlg , NULL , hInst , NULL );
589589
590- /* Associate the tooltip with the tool. */
590+ /* Associate the tooltip with the tool */
591591 LoadStringW (hInst , detailID , szBuffer , _countof (szBuffer ));
592592 tool .lpszText = szBuffer ;
593593 SendMessageW (hwndTip , TTM_ADDTOOLW , 0 , (LPARAM )& tool );
@@ -811,6 +811,8 @@ GetAllowedShutdownOptions(
811811{
812812 DWORD Options = 0 ;
813813 DWORD dwPolicyValue ;
814+ SYSTEM_POWER_CAPABILITIES PowerCaps ;
815+ NTSTATUS Status ;
814816
815817 dwPolicyValue = 0 ;
816818 GetPolicyDWORDValue (hKeyCurrentUser ,
@@ -832,17 +834,27 @@ GetAllowedShutdownOptions(
832834 if (!TestTokenPrivilege (hUserToken , SE_SHUTDOWN_PRIVILEGE ))
833835 return Options ; // The user doesn't have them, bail out.
834836
837+ /* We can always shutdown and restart */
835838 Options |= WLX_SHUTDOWN_STATE_POWER_OFF | WLX_SHUTDOWN_STATE_REBOOT ;
836839
837- // NOTE: "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power" value "Shutdown"
838- // for "advanced" sleep options. See the 3rd parameter of:
839- // https://learn.microsoft.com/en-us/windows/win32/api/powrprof/nf-powrprof-setsuspendstate
840+ /* Determine whether extra power options are available */
841+ Status = NtPowerInformation (SystemPowerCapabilities , NULL , 0 , & PowerCaps , sizeof (PowerCaps ));
842+ if (!NT_SUCCESS (Status ))
843+ {
844+ ERR ("NtPowerInformation(SystemPowerCapabilities) failed (Status 0x%08lx)\n" , Status );
845+ }
846+ else
847+ {
848+ if (IS_PWR_SUSPEND_ALLOWED (& PowerCaps ))
849+ Options |= WLX_SHUTDOWN_STATE_SLEEP ;
840850
841- if (IsPwrSuspendAllowed ())
842- Options |= WLX_SHUTDOWN_STATE_SLEEP ;
851+ // TODO: "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power" value "Shutdown"
852+ // for sleep options. In particular, if set it tells that wakeup events can be disabled.
853+ // This will enable WLX_SHUTDOWN_STATE_SLEEP2 support.
843854
844- if (IsPwrHibernateAllowed ())
845- Options |= WLX_SHUTDOWN_STATE_HIBERNATE ;
855+ if (IS_PWR_HIBERNATE_ALLOWED (& PowerCaps ))
856+ Options |= WLX_SHUTDOWN_STATE_HIBERNATE ;
857+ }
846858
847859 // TODO: Consider Windows 8+ support for:
848860 // "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power" value "HiberbootEnabled"
@@ -918,6 +930,8 @@ ShutdownOnFriendlyInit(
918930 PGINA_CONTEXT pgContext = pContext -> pgContext ;
919931 HDC hdc ;
920932 LONG lfHeight ;
933+ BOOLEAN bCanSuspend = !!(pContext -> ShutdownOptions & (WLX_SHUTDOWN_STATE_SLEEP | WLX_SHUTDOWN_STATE_SLEEP2 ));
934+ BOOLEAN bCanHibernate = !!(pContext -> ShutdownOptions & WLX_SHUTDOWN_STATE_HIBERNATE );
921935
922936 /* Create font for the IDC_TURN_OFF_STATIC static control */
923937 hdc = GetDC (hDlg );
@@ -936,10 +950,10 @@ ShutdownOnFriendlyInit(
936950 pContext -> bIsSleepButtonReplaced = FALSE;
937951 pContext -> bTimer = FALSE;
938952
939- EnableWindow (GetDlgItem (hDlg , IDC_BUTTON_HIBERNATE ), FALSE );
940- EnableWindow (GetDlgItem (hDlg , IDC_BUTTON_SLEEP ), IsPwrSuspendAllowed () );
953+ EnableWindow (GetDlgItem (hDlg , IDC_BUTTON_HIBERNATE ), bCanHibernate );
954+ EnableWindow (GetDlgItem (hDlg , IDC_BUTTON_SLEEP ), bCanSuspend );
941955
942- /* Gather old button func */
956+ /* Gather old button function */
943957 pContext -> OldButtonProc = (WNDPROC )GetWindowLongPtrW (GetDlgItem (hDlg , IDC_BUTTON_HIBERNATE ), GWLP_WNDPROC );
944958
945959 /* Set bIsButtonHot to false, create tooltips for each buttons, make buttons to remember pContext and subclass the buttons */
@@ -952,10 +966,10 @@ ShutdownOnFriendlyInit(
952966 CreateToolTipForButtons (IDC_BUTTON_SHUTDOWN + i ,
953967 IDS_SHUTDOWN_SHUTDOWN_DESC + i ,
954968 hDlg , IDS_SHUTDOWN_SHUTDOWN + i ,
955- pContext -> pgContext -> hDllInstance );
969+ pgContext -> hDllInstance );
956970 }
957971
958- if (pContext -> ShutdownDialogId == IDD_SHUTDOWN_FANCY && IsPwrSuspendAllowed () )
972+ if (( pContext -> ShutdownDialogId == IDD_SHUTDOWN_FANCY ) && bCanSuspend )
959973 {
960974 pContext -> iTimer = SetTimer (hDlg , 0 , 50 , NULL );
961975 pContext -> bTimer = TRUE;
@@ -1126,18 +1140,49 @@ ShutdownDialogProc(
11261140 case WM_COMMAND :
11271141 switch (LOWORD (wParam ))
11281142 {
1129- case IDC_BUTTON_SHUTDOWN :
1130- ExitWindowsEx (EWX_SHUTDOWN , SHTDN_REASON_MAJOR_OTHER );
1131- break ;
1132-
1133- case IDC_BUTTON_REBOOT :
1134- ExitWindowsEx (EWX_REBOOT , SHTDN_REASON_MAJOR_OTHER );
1135- break ;
1143+ /* Check for fancy shutdown dialog buttons */
1144+ case IDC_BUTTON_SHUTDOWN : case IDC_BUTTON_REBOOT :
1145+ case IDC_BUTTON_SLEEP : case IDC_BUTTON_HIBERNATE :
1146+ {
1147+ DWORD Button = LOWORD (wParam );
1148+ PGINA_CONTEXT pgContext = pContext -> pgContext ;
1149+ pgContext -> nShutdownAction = 0 ;
1150+ if (Button == IDC_BUTTON_SHUTDOWN )
1151+ {
1152+ if (pContext -> ShutdownOptions & WLX_SHUTDOWN_STATE_POWER_OFF )
1153+ pgContext -> nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF ;
1154+ }
1155+ else if (Button == IDC_BUTTON_REBOOT )
1156+ {
1157+ if (pContext -> ShutdownOptions & WLX_SHUTDOWN_STATE_REBOOT )
1158+ pgContext -> nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT ;
1159+ }
1160+ else if (Button == IDC_BUTTON_SLEEP )
1161+ {
1162+ if (pContext -> ShutdownOptions & (WLX_SHUTDOWN_STATE_SLEEP | WLX_SHUTDOWN_STATE_SLEEP2 ))
1163+ {
1164+ /* Choose "Sleep with wakeup events disabled" if
1165+ * available, otherwise use the regular sleep mode */
1166+ if (pContext -> ShutdownOptions & WLX_SHUTDOWN_STATE_SLEEP2 )
1167+ pgContext -> nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_SLEEP2 ;
1168+ else
1169+ pgContext -> nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_SLEEP ;
1170+ }
1171+ }
1172+ else if (Button == IDC_BUTTON_HIBERNATE )
1173+ {
1174+ if (pContext -> ShutdownOptions & WLX_SHUTDOWN_STATE_HIBERNATE )
1175+ pgContext -> nShutdownAction = WLX_SAS_ACTION_SHUTDOWN_HIBERNATE ;
1176+ }
1177+ if (pgContext -> nShutdownAction == 0 )
1178+ break ;
11361179
1137- case IDC_BUTTON_SLEEP :
1138- SetSuspendState (TRUE, TRUE, TRUE );
1180+ pContext -> bCloseDlg = TRUE;
1181+ EndDialog ( hDlg , IDOK );
11391182 break ;
1183+ }
11401184
1185+ /* Classic shutdown dialog buttons */
11411186 case IDOK :
11421187 ShutdownOnOk (hDlg , pContext -> pgContext );
11431188
0 commit comments