Просмотр исходного кода

Add shutdown/suspend/reboot to Windows, part of #283

LongChair 8 лет назад
Родитель
Сommit
42614973b6

+ 2 - 1
CMakeModules/Win32Configuration.cmake

@@ -7,4 +7,5 @@ find_library(IMMLIB imm32)
 find_library(VERLIB version)
 find_library(DWMLIB dwmapi)
 find_library(AVRTLIB avrt)
-set(OS_LIBS ${WINMM} ${IMMLIB} ${VERLIB} ${DWMLIB} ${AVRTLIB})
+find_library(POWRPROFLIB PowrProf)
+set(OS_LIBS ${WINMM} ${IMMLIB} ${VERLIB} ${DWMLIB} ${AVRTLIB} ${POWRPROFLIB})

+ 34 - 0
src/power/PowerComponentWin.cpp

@@ -1,6 +1,14 @@
 #include <windows.h>
 
 #include "PowerComponentWin.h"
+#include "powrprof.h"
+#include "utils/Utils.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+PowerComponentWin::PowerComponentWin() :  PowerComponent(nullptr), m_hasPrivileges(false)
+{
+  m_hasPrivileges = WinUtils::getPowerManagementPrivileges();
+}
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 void PowerComponentWin::doDisableScreensaver()
@@ -13,3 +21,29 @@ void PowerComponentWin::doEnableScreensaver()
 {
   SetThreadExecutionState(ES_CONTINUOUS);
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+bool PowerComponentWin::Suspend()
+{
+  return SetSuspendState(false, true, false) == TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+bool PowerComponentWin::Reboot()
+{
+  return InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART,
+                           SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+bool PowerComponentWin::PowerOff()
+{
+  DWORD shutdownFlags = SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_POWEROFF;
+
+  if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8)
+    shutdownFlags |= SHUTDOWN_HYBRID;
+
+  return InitiateShutdownW(NULL, NULL, 0, shutdownFlags,
+                           SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED) == ERROR_SUCCESS;
+
+}

+ 14 - 1
src/power/PowerComponentWin.h

@@ -3,12 +3,25 @@
 
 #include "PowerComponent.h"
 
+
 class PowerComponentWin : public PowerComponent
 {
 public:
-  PowerComponentWin() : PowerComponent(0) { }
+  PowerComponentWin();
   virtual void doDisableScreensaver();
   virtual void doEnableScreensaver();
+
+  virtual bool canPowerOff() override { return m_hasPrivileges; }
+  virtual bool canReboot() override { return m_hasPrivileges; }
+  virtual bool canSuspend() override { return true; }
+
+  virtual bool PowerOff() override;
+  virtual bool Reboot() override;
+  virtual bool Suspend() override;
+
+private:
+  bool m_hasPrivileges;
+
 };
 
 #endif // POWERCOMPONENTWIN_H

+ 4 - 0
src/utils/CMakeLists.txt

@@ -11,3 +11,7 @@ if(APPLE)
   add_sources(HelperLaunchd.cpp HelperLaunchd.cpp)
   add_subdirectory(osx)
 endif(APPLE)
+
+if(WIN32)
+  add_subdirectory(win)
+endif()

+ 2 - 0
src/utils/Utils.h

@@ -10,6 +10,8 @@
 
 #ifdef Q_OS_MAC
   #include "osx/OSXUtils.h"
+#elif defined(Q_OS_WIN)
+  #include "win/WinUtils.h"
 #endif
 
 #define DEFINE_SINGLETON(cls) \

+ 2 - 0
src/utils/win/CMakeLists.txt

@@ -0,0 +1,2 @@
+set(WINUTILS_SRC WinUtils.h WinUtils.cpp)
+add_sources(${WINUTILS_SRC})

+ 30 - 0
src/utils/win/WinUtils.cpp

@@ -0,0 +1,30 @@
+#include "WinUtils.h"
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+bool WinUtils::getPowerManagementPrivileges()
+{
+  HANDLE hToken = nullptr;
+  // Get a token for this process.
+  if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+  {
+    // Get the LUID for the shutdown privilege.
+    TOKEN_PRIVILEGES tkp = {};
+    if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
+    {
+      tkp.PrivilegeCount = 1;  // one privilege to set
+      tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+      // Get the shutdown privilege for this process.
+      if (AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
+      {
+        CloseHandle(hToken);
+        return true;
+      }
+    }
+  }
+
+  if (hToken)
+    CloseHandle(hToken);
+  return false;
+}

+ 10 - 0
src/utils/win/WinUtils.h

@@ -0,0 +1,10 @@
+#ifndef WINUTILS_H
+#define WINUTILS_H
+
+
+namespace WinUtils
+{
+  bool getPowerManagementPrivileges();
+}
+
+#endif // WINUTILS_H