AccessCheck() and MoveFileEx() doesn't work with network mapped driver
Hi
We have a NAS installed locally and mapped a folder as local driver letter, such W .
Here uses credential from NAS to establish the mapping from NAS folder to local driver letter, not from Windows Active Directory. And user account is local. Any operation from Explorer works as usual.
By using AccessChk tools, it prints the SID starts with S-1-5-21, it means SECURITY_NT_NON_UNIQUE
Accesschk v6.12 - Reports effective permissions for securable objects
Copyright (C) 2006-2017 Mark Russinovich
Sysinternals - www.sysinternals.comW:\temp
RW S-1-5-21-825604914-2373088077-4039564966-1203
RW S-1-5-21-825604914-2373088077-4039564966-3052
RW S-1-5-21-825604914-2373088077-4039564966-3048
Print current user's SID
USER INFORMATION
User Name SID
========= =============================================
3fasd6sf\user S-1-5-21-3089250728-987539432-1982516474-1001
Now we have a program needs to check if current process has permission to read/write/execute a file under an existed folder such as W:\temp, by API AccessCheck and MoveFileEx always return 5 = ACCESS_DENIED. Here is simple program to re-produce.
bool CanAccessFolder( LPCTSTR folderName, DWORD genericAccessRights )
{
bool bRet = false;
DWORD length = 0;
if (!::GetFileSecurity( folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION, NULL, NULL, &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;
}
int main(int argc, char *argv[])
{
bool can = CanAccessFolder(argv[1], FILE_GENERIC_WRITE);
if (can) {
printf("OK");
} else {
printf("BAD");
}
return 0;
}
Any idea on this ? Thanks a lot !