首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 實作 Windows 2000/XP 系統休眠功能:權限提升與 API 呼叫全解析

     編輯:VC 教學

前言:休眠看似簡單,權限卻是關鍵

在 Windows 98 時代,呼叫 SetSystemPowerState() 即可讓系統進入休眠,但自 Windows 2000/XP 起,作業系統引入嚴格的使用者權限模型,若未擁有 SE_SHUTDOWN_NAME 特權,該 API 會直接失敗。本文示範如何在 VC++ 中透過調整程序權杖權限,安全地實現系統休眠。

核心步驟:取得關機特權

  1. 開啟程序權杖:OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)
  2. 查詢特權 LUID:LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luid)
  3. 構建 TOKEN_PRIVILEGES 結構:設定 PrivilegeCount = 1,Attributes = SE_PRIVILEGE_ENABLED
  4. 調整權杖特權:AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)

完整實作代碼

#define RTN_ERROR 13

void PERR(LPCTSTR szAPI, DWORD dwLastError) {
    LPTSTR MessageBuffer = nullptr;
    DWORD dwBufferLength = FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, dwLastError, LANG_NEUTRAL,
        reinterpret_cast(&MessageBuffer), 0, NULL);
    if (dwBufferLength) {
        fprintf(stderr, _T("%s error! (rc=%lu) "), szAPI, dwLastError);
        DWORD dwBytesWritten;
        WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer, dwBufferLength, &dwBytesWritten, NULL);
        LocalFree(MessageBuffer);
    }
}

INT SetPower() {
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;
    LPCTSTR MachineName = NULL;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
        PERR(_T("OpenProcessToken"), GetLastError());
        return RTN_ERROR;
    }

    if (!LookupPrivilegeValue(MachineName, SE_SHUTDOWN_NAME, &luid)) {
        PERR(_T("LookupPrivilegeValue"), GetLastError());
        CloseHandle(hToken);
        return RTN_ERROR;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
        PERR(_T("AdjustTokenPrivileges"), GetLastError());
        CloseHandle(hToken);
        return RTN_ERROR;
    }

    CloseHandle(hToken);

    // 觸發休眠:FALSE=休眠(非強制), TRUE=關閉電源前不強制應用程式關閉
    if (!SetSystemPowerState(FALSE, TRUE)) {
        PERR(_T("SetSystemPowerState"), GetLastError());
        return RTN_ERROR;
    }
    return 0;
}

必要條件與注意事項

  • 系統必須在「電源選項」中啟用「休眠」支援,否則 SetSystemPowerState 會失敗。
  • 程式需以管理員權限執行,或使用者帳號需具備「關閉系統」使用者權限(本地安全性原則 → 使用者權限指派)。
  • 錯誤處理函式 PERR 使用 FormatMessage 取得系統錯誤描述,方便除錯。

延伸應用

同樣的權限提升模式適用於 ExitWindowsEx(登出/重開機/關機)、InitiateSystemShutdown 等需要 SE_SHUTDOWN_NAME 特權的 API。掌握此模式,即可在 NT 核心系統上安全執行電源管理操作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved