#pragma once #include // 提升权限 inline int DebugPrivilege() { HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return -1; // 动态分配空间,包含 3 个 LUID TOKEN_PRIVILEGES* tp = (TOKEN_PRIVILEGES*)malloc(sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES)); if (!tp) { SAFE_CLOSE_HANDLE(hToken); return 1; } tp->PrivilegeCount = 3; if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp->Privileges[0].Luid)) { free(tp); SAFE_CLOSE_HANDLE(hToken); return 2; } tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, &tp->Privileges[1].Luid)) { free(tp); SAFE_CLOSE_HANDLE(hToken); return 3; } tp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &tp->Privileges[2].Luid)) { free(tp); SAFE_CLOSE_HANDLE(hToken); return 4; } tp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, tp, sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES), NULL, NULL); free(tp); SAFE_CLOSE_HANDLE(hToken); return 0; } typedef void (*StartupLogFunc)(const char* file, int line, const char* format, ...); /** * @brief 设置本身开机自启动 * @param[in] *sPath 注册表的路径 * @param[in] *sNmae 注册表项名称 * @return 返回注册结果 * @details Win7 64位机器上测试结果表明,注册项在:\n * HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run * @note 首次运行需要以管理员权限运行,才能向注册表写入开机启动项 */ inline BOOL SetSelfStart(const char* sPath, const char* sNmae, StartupLogFunc Log) { #define _Mprintf(format, ...) if (Log) Log(__FILE__, __LINE__, format, __VA_ARGS__) int n = DebugPrivilege(); if (n != 0) { _Mprintf("提升权限失败,错误码:%d\n", n); return FALSE; } // 写入的注册表路径 #define REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run" // 在注册表中写入启动信息 HKEY hKey = NULL; LONG lRet = RegOpenKeyExA(HKEY_CURRENT_USER, REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey); // 判断是否成功 if (lRet != ERROR_SUCCESS) { _Mprintf("打开注册表失败,错误码:%d\n", lRet); return FALSE; } lRet = RegSetValueExA(hKey, sNmae, 0, REG_SZ, (const BYTE*)sPath, strlen(sPath) + 1); if (lRet != ERROR_SUCCESS) { _Mprintf("写入注册表失败,错误码:%d\n", lRet); } else { _Mprintf("写入注册表成功:%s -> %s\n", sNmae, sPath); } // 关闭注册表 RegCloseKey(hKey); #undef _Mprintf // 判断是否成功 return lRet == ERROR_SUCCESS; } inline bool markForDeleteOnReboot(const char* file) { return MoveFileExA(file, NULL, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_WRITE_THROUGH) != FALSE; } inline BOOL self_del(int timeoutSecond=3) { char file[MAX_PATH] = { 0 }, szCmd[MAX_PATH * 2] = { 0 }; if (GetModuleFileName(NULL, file, MAX_PATH) == 0) return FALSE; markForDeleteOnReboot(file); sprintf(szCmd, "cmd.exe /C timeout /t %d /nobreak > Nul & Del /f /q \"%s\"", timeoutSecond, file); STARTUPINFO si = { 0 }; PROCESS_INFORMATION pi = { 0 }; si.cb = sizeof(si); if (CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { SAFE_CLOSE_HANDLE(pi.hThread); SAFE_CLOSE_HANDLE(pi.hProcess); return TRUE; } return FALSE; }