逻辑扩展文件失败

时间:2014-03-10 08:47:09

标签: c++ windows file-io

尝试使用SetFileVaildData()在逻辑上扩展 Windows 8.1 文件时,以下代码失败。

返回的Windows错误代码和消息是:

  

ERROR_PRIVILEGE_NOT_HELD    1314(0x522)客户端不持有所需的权限。

我将代码作为管理员运行,并且我已声明该进程确实具有使用SE_MANAGE_VOLUME_NAMEOpenProcessToken()的{​​{1}}权限。< / p>

GetTokenInformation()

结果:

// 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;
}

1 个答案:

答案 0 :(得分:1)

需要启用权限才能使用它们。以下是我的一个启用SE_INCREASE_QUOTE_NAMESE_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;
}