当试图用SetFileVaildData()逻辑扩展我的Windows 8.1文件时,下面的代码失败。
返回的Windows错误代码和消息是:
ERROR_PRIVILEGE_NOT_HELD 1314(0x522)所需的特权不由客户端持有。
我以pipe理员身份运行代码,并且我声称该过程确实具有使用OpenProcessToken()
和GetTokenInformation()
的SE_MANAGE_VOLUME_NAME
特权。
// SetFileValidData_test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <Windows.h> bool ProcessHasSeManageVolumePrivilege(); int _tmain(int argc, _TCHAR* argv[]) { // Set access methods DWORD accessMethods = GENERIC_READ | GENERIC_WRITE; // Set share modes DWORD shareModes = 0; // Set security attributes LPSECURITY_ATTRIBUTES secAttr = NULL; // Set creation disposition DWORD creationDispositions = CREATE_ALWAYS; // Set file flags DWORD fileFlags = 0; // Set template HANDLE templateFile = NULL; if (!ProcessHasSeManageVolumePrivilege()) { // Missing privilege to continue std::cerr << "Process is missing the required SE_MANAGE_VOLUME_NAME (\"SeManageVolumePrivilege\") privilege." << std::endl; return -1; } // Create the file HANDLE filehandle = CreateFile( L"testfile.tmp", accessMethods, shareModes, secAttr, creationDispositions, fileFlags, templateFile); if (filehandle == INVALID_HANDLE_VALUE) { // Error std::cerr << "CreateFile() failed with error #" << GetLastError() << "." << std::endl; return -1; } // Extend the file to 1 MB if (!SetFileValidData(filehandle, 1024*1024)) { // Error std::cerr << "SetFileValidData() failed with error #" << GetLastError() << "." << std::endl; return -1; } std::cout << "File was logically extended successfully!" << std::endl << "Press a key to quit..." << std::endl; getchar(); return 0; } bool ProcessHasSeManageVolumePrivilege() { HANDLE token; void* tpv; TOKEN_PRIVILEGES* tp; DWORD rl; bool hasPrivilege = false; std::cout << "Asserting process has the \"SeManageVolumePrivilege\" privilege:" << std::endl; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)) { std::cerr << "OpenProcessToken() failed with error #" << GetLastError() << "." << std::endl; return false; } if (!GetTokenInformation(token, TokenPrivileges, NULL, 0, &rl)) { DWORD dw = GetLastError(); if (dw != ERROR_INSUFFICIENT_BUFFER) { std::cerr << "GetTokenInformation() failed with error #" << GetLastError() << "." << std::endl; return false; } } tpv = malloc(rl + 10); if (!tpv) throw std::bad_alloc(); ZeroMemory(tpv, rl + 10); if (!GetTokenInformation(token, TokenPrivileges, tpv, rl, &rl)) { std::cerr << "GetTokenInformation() failed with error #" << GetLastError() << "." << std::endl; return false; } tp = (TOKEN_PRIVILEGES*)tpv; for (DWORD i = 0; i < tp->PrivilegeCount; i++) { const int nLen = 100; TCHAR bufname[nLen]; DWORD bufsize = nLen; try { LookupPrivilegeName(NULL, &tp->Privileges[i].Luid, bufname, &bufsize); bufname[nLen - 1] = '\0'; std::wcout << "\t" << bufname; if (wcscmp(L"SeManageVolumePrivilege", bufname) == 0) { std::cout << " ... YES! Found it!" << std::endl; hasPrivilege = true; break; } else std::cout << " ... no" << std::endl; } catch (...) { // Clean up before re-throwing exception free(tpv); CloseHandle(token); throw; } } free(tpv); CloseHandle(token); token = NULL; return hasPrivilege; }
结果:
C:\dev\SetFileValidData_test\Debug> SetFileValidData_test.exe Asserting process has the "SeManageVolumePrivilege" privilege: SeIncreaseQuotaPrivilege ... no SeSecurityPrivilege ... no SeTakeOwnershipPrivilege ... no SeLoadDriverPrivilege ... no SeSystemProfilePrivilege ... no SeSystemtimePrivilege ... no SeProfileSingleProcessPrivilege ... no SeIncreaseBasePriorityPrivilege ... no SeCreatePagefilePrivilege ... no SeBackupPrivilege ... no SeRestorePrivilege ... no SeShutdownPrivilege ... no SeDebugPrivilege ... no SeSystemEnvironmentPrivilege ... no SeChangeNotifyPrivilege ... no SeRemoteShutdownPrivilege ... no SeUndockPrivilege ... no SeManageVolumePrivilege ... YES! Found it! SetFileValidData() failed with error #1314. C:\dev\SetFileValidData_test\Debug>
权限需要启用,然后才能使用它们。 以下是一些启用SE_INCREASE_QUOTE_NAME
和SE_ASSIGNPRIMARYTOKEN_NAME
项目的代码,可以轻松修改它以启用其他权限。
BOOL enable_privs(void) { HANDLE token; struct { DWORD count; LUID_AND_ATTRIBUTES privilege[2]; } token_privileges; token_privileges.count = 2; token_privileges.privilege[0].Attributes = SE_PRIVILEGE_ENABLED; token_privileges.privilege[1].Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(0, SE_INCREASE_QUOTA_NAME, &token_privileges.privilege[0].Luid)) return FALSE; if (!LookupPrivilegeValue(0, SE_ASSIGNPRIMARYTOKEN_NAME, &token_privileges.privilege[1].Luid)) return FALSE; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) return FALSE; if (!AdjustTokenPrivileges(token, 0, (PTOKEN_PRIVILEGES)&token_privileges, 0, 0, 0)) return FALSE; if (GetLastError() != ERROR_SUCCESS) return FALSE; return TRUE; }