2014年3月29日星期六

获取文件的所有者(用户)

/*
一个文件的所有者,大概也就是创建者,这是一个简单的问题,你想过吗?
一般人不会关注,只有安全的人才去关注,并有所获,深入深入再深入.
本文修改自MSDN的:Finding the Owner of a File Object in C++.
再次说明,改编自VS2008的MSDN,非网络上的MSDN的代码.

made by correy
made at 2014.03.29
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/

#include "aclapi.h" //这个在VC及SDK和WDK都有.


bool get_owner_of_file(IN wchar_t * filename, OUT wchar_t * owner)
{
    if (!filename || !owner) {
        return false;
    }

    HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        _tprintf(TEXT("CreateFile error = %d\n"), GetLastError());
        return false;
    }
   
    PSID pSidOwner = (PSID)GlobalAlloc(GMEM_FIXED, sizeof(PSID));// Allocate memory for the SID structure.
    if (!pSidOwner) {//这两个内存申请,微软竟然不判断失败的情况.
        return false;
    }
    PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GMEM_FIXED, sizeof(PSECURITY_DESCRIPTOR));// Allocate memory for the security descriptor structure.
    if (!pSD) {//经测试.这个变量不用申请,没有用.
        GlobalFree(pSidOwner);
        return false;
    }

    // Get the owner SID of the file.
    DWORD dwRtnCode = GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD);//除了签三个参数,剩余的都是OUT类型.
    if (dwRtnCode != ERROR_SUCCESS) {
        _tprintf(TEXT("GetSecurityInfo error = %d\n"), GetLastError());
        GlobalFree(pSidOwner);
        GlobalFree(pSD);
        return false;
    }

    // First call to LookupAccountSid to get the buffer sizes.
    DWORD dwAcctName = 1, dwDomainName = 1;
    SID_NAME_USE eUse = SidTypeUnknown;
    BOOL bRtnBool = LookupAccountSid(NULL, pSidOwner, 0, (LPDWORD)&dwAcctName, 0, (LPDWORD)&dwDomainName, &eUse); //返回两个值的大小.      
    LPTSTR AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName);// Reallocate memory for the buffers.  
    if (AcctName == NULL) {// Check GetLastError for GlobalAlloc error condition.
        _tprintf(TEXT("GlobalAlloc error = %d\n"), GetLastError());
        GlobalFree(pSidOwner);
        GlobalFree(pSD);
        return false;
    }
    LPTSTR DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName); //其实这个也不是我们想要的.但必须得有,不然下面的函数运行失败.
    if (DomainName == NULL) {// Check GetLastError for GlobalAlloc error condition.
        _tprintf(TEXT("GlobalAlloc error = %d\n"), GetLastError());
        GlobalFree(pSidOwner);
        GlobalFree(pSD);
        GlobalFree(AcctName);
        return false;
    }
   
    bRtnBool = LookupAccountSid(// Second call to LookupAccountSid to get the account name.
        NULL,                   // name of local or remote computer
        pSidOwner,              // security identifier
        AcctName,               // account name buffer
        (LPDWORD)&dwAcctName,   // size of account name buffer
        DomainName,             // domain name.这个域名也会返回
        (LPDWORD)&dwDomainName, // size of domain name buffer.
        &eUse);                 // SID type.这个也会返回.  
    if (bRtnBool == FALSE) {// Check GetLastError for LookupAccountSid error condition.
        if (GetLastError() == ERROR_NONE_MAPPED) {
            _tprintf(TEXT("Account owner not found for specified SID.\n"));
        } else {
            _tprintf(TEXT("Error in LookupAccountSid.\n"));
        }
    } else if (bRtnBool == TRUE) {      
        _tprintf(TEXT("Account owner = %s\n"), AcctName);// Print the account name.
        lstrcpy(owner, AcctName);
    }

    GlobalFree(pSidOwner);
    GlobalFree(pSD);
    //GlobalFree(AcctName);//释放出错.
    //GlobalFree(DomainName);//释放出错.

    return !!bRtnBool;
}


int main(int argc, char **argv)
{  
    wchar_t owner_user[MAX_PATH] = {0};
    bool b = get_owner_of_file(L"f:\\test.exe", owner_user);
    if (b) {
        _tprintf(TEXT("Account owner = %s\n"), owner_user);
    } else {
        _tprintf(TEXT("Account owner not found\n"));
    }

    return 0;
}

没有评论:

发表评论