WinAPI 确定文件是否可访问/私有的方法

发布于 2024-12-10 10:03:22 字数 763 浏览 0 评论 0原文

在 win32 c++ 中;有没有办法确定文件夹/文件是否可访问?如果您尝试访问 C:/Windows 目录中的某个文件夹,您就会知道如何操作。您将看到一个弹出窗口,显示“此文件夹无法访问”。

也许有一个文件属性常量表明该文件是私有的?也许类似 FILE_ATTRIBUTE_PRIVATE 之类的东西?

WIN32_FIND_DATA dirData;

while (FindNextFile( dir, &dirData ) != 0 )
{
    // I made the following constant up
    if ( !(fileData.dwFileAttributes & FILE_ATTRIBUTE_PRIVATE) )
    {
        // file is accessible so store filepath
        files.push_back( fileData.cFileName );
    }
    else // file is not accessible so dont store
}

或者是通过以下方式了解的唯一方法:

dir = FindFirstFileEx( (LPCTSTR)directory.c_str(), FindExInfoStandard, &dirData, FindExSearchNameMatch, NULL, 0 );

if ( dir == ??? ) { the file is inaccessible } [/code]

In win32 c++; is there a way to determine if a folder/file is accessible? You know how if you try to access a certain folder in the C:/Windows directory & you will get a popup saying "This folder is not accessible".

Maybe there is a file attribute constant that signifies that the file is private? Maybe something like FILE_ATTRIBUTE_PRIVATE?

WIN32_FIND_DATA dirData;

while (FindNextFile( dir, &dirData ) != 0 )
{
    // I made the following constant up
    if ( !(fileData.dwFileAttributes & FILE_ATTRIBUTE_PRIVATE) )
    {
        // file is accessible so store filepath
        files.push_back( fileData.cFileName );
    }
    else // file is not accessible so dont store
}

Or is the only way to know by going:

dir = FindFirstFileEx( (LPCTSTR)directory.c_str(), FindExInfoStandard, &dirData, FindExSearchNameMatch, NULL, 0 );

if ( dir == ??? ) { the file is inaccessible } [/code]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

已下线请稍等 2024-12-17 10:03:22

最好的办法就是尝试访问它。

您可以计算访问控制列表为特定用户帐户授予的访问权限,但这相当复杂,并且在执行访问检查后权限可能会发生变化。因此,只需打开文件并处理访问被拒绝错误即可。

Best thing to do is just try to access it.

You can calculate the access granted by the access control list for a particular user account, but this is quite complicated, and the permission could change after you do the access check. So just open the file and handle access denied errors.

挽清梦 2024-12-17 10:03:22

它不会是文件本身的标志,因为不同的帐户可能有权访问不同的文件/目录。相反,Windows 使用 ACL(访问控制列表),这是确定谁有权访问什么的数据结构。

Windows 中的 ACL 几乎可以与句柄引用的任何内容一起使用(文件、目录、进程、互斥体、命名管道...)。您可以通过转到文件属性并查看“安全”选项卡来查看文件 ACL。

因此,在您的应用程序中,您并不是真的想检查标志,而是将文件的 ACL 与应用程序运行时的用户帐户进行比较。查看 AccessCheck Win32 函数。我认为这正是您正在寻找的。

就我个人而言,我从未使用过该函数,但如果您正在寻找 Win32 解决方案并且需要函数调用,那么这可能是您最好的选择。然而,正如其他人指出的那样,它可能太复杂了。我一直使用 _access (或 _waccess),它是 CRT 的一部分,非常易于使用,并且您不会因为获取文件句柄而只是为了关闭它而对性能造成影响(取决于您的循环的紧密程度,这些调用实际上可以加起来)。

It wouldn't be a flag on the file itself because different accounts may have access to different files/directories. Instead, windows uses ACL's (access control lists), which are data structures that determine who has access to what.

ACLs in windows can be used with just about anything that is referred to by a handle (files, directories, processes, mutexes, named pipes...). You can view file ACLs by going to properties of a file and view "Security" tab.

So in your app you don't really want to check for a flag, but to compare file's ACL against the user account under which your app is running. Check out AccessCheck Win32 function. I think it's exactly what you are looking for.

Personally, I've never used that function, but if you are looking for Win32 solution and you want a function call, that's probably your best bet. However, as others have pointed out, it might be too complicated. I've always used _access (or _waccess) which is part of CRT, uber easy to use, and you don't take a performance hit of acquiring a file handle only to close it (depending on how tight your loop is, those calls can actually add up).

や莫失莫忘 2024-12-17 10:03:22
int _access( 
   const char *path, 
   int mode 
);

易于使用:

http://msdn.microsoft .com/en-us/library/1w06ktdy%28v=vs.80%29.aspx

int _access( 
   const char *path, 
   int mode 
);

Simple to use:

http://msdn.microsoft.com/en-us/library/1w06ktdy%28v=vs.80%29.aspx

高冷爸爸 2024-12-17 10:03:22

是的,亚伦·鲍尔曼,你是老板!天啊天啊!我可以用一些有用的脏话来表达我现在的喜悦。

https://blog.aaronballman.com/2011/08 /how-to-check-access-rights/ 是检查 win32 中 fpath 的访问权限示例的链接。以及 AccessCheck win32 函数背后的解释。下面是代码。

bool canAccessPath( LPCTSTR folderName, DWORD genericAccessRights )
{
    bool bRet = 0;
    DWORD length = 0;

    if (!::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &length ) &&
            ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
    {
        PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >( ::malloc( length ) );

        if (security && ::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, security, length, &length ))
        {
            HANDLE hToken = NULL;

            if (::OpenProcessToken( ::GetCurrentProcess(), TOKEN_IMPERSONATE|TOKEN_QUERY|TOKEN_DUPLICATE|STANDARD_RIGHTS_READ, &hToken ))
            {
                HANDLE hImpersonatedToken = NULL;

                if (::DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken ))
                {
                    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                    PRIVILEGE_SET privileges = { 0 };
                    DWORD grantedAccess = 0, privilegesLength = sizeof( privileges );
                    BOOL result = FALSE;

                    mapping.GenericRead = FILE_GENERIC_READ;
                    mapping.GenericWrite = FILE_GENERIC_WRITE;
                    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                    mapping.GenericAll = FILE_ALL_ACCESS;

                    ::MapGenericMask( &genericAccessRights, &mapping );

                    if (::AccessCheck( security, hImpersonatedToken, genericAccessRights,
                            &mapping, &privileges, &privilegesLength, &grantedAccess, &result ))
                    {
                     bRet = result == TRUE;
                    }

                    ::CloseHandle( hImpersonatedToken );
                }

                ::CloseHandle( hToken );
            }

            ::free( security );
        }
    }

    return bRet;
}

不要害羞地进入他的网站并查看他的作品。我相信他还有更多有趣的东西。

Yes Aaron Ballman you are a boss! Oh man oh man! Which I could use some useful expletives to expressives my joy right now.

https://blog.aaronballman.com/2011/08/how-to-check-access-rights/ is a link to the example of checking accesss rights in win32 on a fpath. And the explanation behind the poorly documented AccessCheck win32 function. Below is the code.

bool canAccessPath( LPCTSTR folderName, DWORD genericAccessRights )
{
    bool bRet = 0;
    DWORD length = 0;

    if (!::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, NULL, 0, &length ) &&
            ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
    {
        PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >( ::malloc( length ) );

        if (security && ::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, security, length, &length ))
        {
            HANDLE hToken = NULL;

            if (::OpenProcessToken( ::GetCurrentProcess(), TOKEN_IMPERSONATE|TOKEN_QUERY|TOKEN_DUPLICATE|STANDARD_RIGHTS_READ, &hToken ))
            {
                HANDLE hImpersonatedToken = NULL;

                if (::DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken ))
                {
                    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                    PRIVILEGE_SET privileges = { 0 };
                    DWORD grantedAccess = 0, privilegesLength = sizeof( privileges );
                    BOOL result = FALSE;

                    mapping.GenericRead = FILE_GENERIC_READ;
                    mapping.GenericWrite = FILE_GENERIC_WRITE;
                    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                    mapping.GenericAll = FILE_ALL_ACCESS;

                    ::MapGenericMask( &genericAccessRights, &mapping );

                    if (::AccessCheck( security, hImpersonatedToken, genericAccessRights,
                            &mapping, &privileges, &privilegesLength, &grantedAccess, &result ))
                    {
                     bRet = result == TRUE;
                    }

                    ::CloseHandle( hImpersonatedToken );
                }

                ::CloseHandle( hToken );
            }

            ::free( security );
        }
    }

    return bRet;
}

Don't be shy to pop into his website and check out his work. I am sure he has more interesting stuff.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文