HomeBlogMagic

Windows C/C++ cancel System Shutdown

Wenn ein Shutdown von Windows verhindert werden soll, kann das mit folgendem Beispiel gemacht werden:

Damit lässt sich kein vom Benutzer ausgelöster Shutdown verhindern, dazu benötigt man ShutdownBlockReasonDestroy und ShutdownBlockReasonCreate

#include <iostream>
#include <Windows.h>

bool g_bShutdown = false;

DWORD WINAPI threadFunction(void *Param)
{
  while (g_bShutdown == false)
  {
    Sleep(100);
    if (AbortSystemShutdownW(NULL))
    {
      g_bShutdown = true;
      std::cout << "Shutdown aborted\n";
      break;
    }
  }
  UNREFERENCED_PARAMETER(Param);
  return 0;
}

int main(int iArgc, char** ppcArgv)
{
  UNREFERENCED_PARAMETER(iArgc);
  UNREFERENCED_PARAMETER(ppcArgv);
  HANDLE hToken = NULL;
  bool bStart = false;
  if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  {
    TOKEN_PRIVILEGES oTokenPrivileges;
    // Get the LUID for the shutdown privilege on local ystem
    if (LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &oTokenPrivileges.Privileges[0].Luid))
    {
      // Prepare struct for setting privileges
      oTokenPrivileges.PrivilegeCount = 1;  // one privilege to set    
      oTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

      // Set required privileges
      if (AdjustTokenPrivileges(hToken, FALSE, &oTokenPrivileges, 0, (PTOKEN_PRIVILEGES) NULL, 0))
      {
        // Privileges are valid, we are able to cance shutdown
        bStart = true;
      }
      else
      {
        std::cout << "No privileges for preventing shutdown\n";
      }
    }
    else
    {
      std::cout << "Unable to get privileges\n";
    }
  }
  else
  {
    std::cout << "Unable to get process tokens\n";
  }

  if (bStart)
  {
    DWORD uiThredId;
    if (nullptr != CreateThread(0, 0, threadFunction, nullptr, 0, &uiThredId))
    {
      while (g_bShutdown == false)
      {
        std::cout << "Waiting for shutdown\n";
        Sleep(1000);
      }
    }
    else
    {
      std::cout << "Failed to start thread\n";
    }
  }
  return 0;
}

Die Applikation startet einen Thread welcher kontinuierlich mit AbortSystemShutdownW einen möglichen Shutdown verhindert. Wenn ein solcher Reboot verhindert wurde, bekommt die Haupt-Applikation durch g_bShutdown Notiz davon und kann darauf reagieren.