VC++判断当前程序对文件或文件夹是否有写权限(附源码)

        在某些场景下,需要判断当前程序对某文件或文件夹是否写权限。比如没有管理员权限,是不能向系统敏感路径(比如C:\Windows\System32、C:\Program Files等)创建文件或者改写这些路径中的文件。

       我们可以通过以下代码判断对目标文件或者文件夹是否有写权限:

// 将要检测的权限GENERIC_XXXXXX传递给dwGenericAccessMask,可检测对
// 文件或者文件夹的权限
BOOL CanAccessFile( CUIString strPath, DWORD dwGenericAccessMask )  
{  
	CUIString strLog;
	strLog.Format( _T("[CanAccessFile]strPath: %s, dwGenericAccessMask: %d"), strPath, dwGenericAccessMask );
	WriteUpdateLog( strLog );

	DWORD dwSize = 0;  
	PSECURITY_DESCRIPTOR psd = NULL;  
	SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION | 
		GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;

	WriteUpdateLog( _T("[CanAccessFile]GetFileSecurity - NULL") );

	// 获取文件权限信息结构体大小  
	BOOL bRet = GetFileSecurity( strPath, si, psd, 0, &dwSize );  
	if ( bRet || GetLastError() != ERROR_INSUFFICIENT_BUFFER )  
	{  
		strLog.Format( _T("[CanAccessFile]GetFileSecurity - NULL failed, GetLastError: %d"), GetLastError() );
		WriteUpdateLog( strLog );
		return FALSE;  
	}  


	char* pBuf = new char[dwSize];
	ZeroMemory( pBuf, dwSize );
	psd = (PSECURITY_DESCRIPTOR)pBuf;  

	strLog.Format( _T("[CanAccessFile]GetFileSecurity - dwSize: %d"), dwSize );
	WriteUpdateLog( strLog );

	// 获取文件权限信息结构体大小  
	bRet = GetFileSecurity( strPath, si, psd, dwSize, &dwSize );  
	if ( !bRet )  
	{  
		strLog.Format( _T("[CanAccessFile]GetFileSecurity - dwSize failed, GetLastError: %d"), GetLastError() );
		WriteUpdateLog( strLog );
		delete []pBuf;
		return FALSE;  
	}  

	WriteUpdateLog( _T("[CanAccessFile]OpenProcessToken") );

	HANDLE hToken = NULL;  
	if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) )  
	{  
		strLog.Format( _T("[CanAccessFile]OpenProcessToken failed, GetLastError: %d"), GetLastError() );
		WriteUpdateLog( strLog );
		delete []pBuf;
		return FALSE;  
	}  

	WriteUpdateLog( _T("[CanAccessFile]DuplicateToken") );

	// 模拟令牌  
	HANDLE hImpersonatedToken = NULL;  
	if( !DuplicateToken( hToken, SecurityImpersonation, &hImpersonatedToken ) )  
	{  
		strLog.Format( _T("[CanAccessFile]DuplicateToken failed, GetLastError: %d"), GetLastError() );
		WriteUpdateLog( strLog );

		delete []pBuf;
		CloseHandle( hToken );
		return FALSE;  
	}  

	WriteUpdateLog( _T("[CanAccessFile]MapGenericMask") );
  
	// 在检测是否有某个权限时,将GENERIC_WRITE等值传给本函数的第二个参数dwGenericAccessMask
	// GENERIC_WRITE等参数在调用CreateFile创建文件时会使用到,下面调用MapGenericMask将
	// GENERIC_WRITE等转换成FILE_GENERIC_WRITE等
	// 将GENERIC_XXXXXX转换成FILE_GENERIC_XXXXXX
	GENERIC_MAPPING genMap;
	genMap.GenericRead = FILE_GENERIC_READ;  
	genMap.GenericWrite = FILE_GENERIC_WRITE;  
	genMap.GenericExecute = FILE_GENERIC_EXECUTE;  
	genMap.GenericAll = FILE_ALL_ACCESS;  
	MapGenericMask( &dwGenericAccessMask, &genMap );  

	WriteUpdateLog( _T("[CanAccessFile]AccessCheck") );

	// 调用AccessCheck来检测是否有指定的权限
	PRIVILEGE_SET privileges = { 0 };  
	DWORD dwGrantedAccess = 0;  
	DWORD privLength = sizeof(privileges);  
	BOOL bGrantedAccess = FALSE;  
	if( AccessCheck( psd, hImpersonatedToken, dwGenericAccessMask, 
		&genMap, &privileges, &privLength, &dwGrantedAccess, &bGrantedAccess ) )  
	{    
		strLog.Format( _T("[CanAccessFile]AccessCheck succeed, dwGenericAccessMask: %d, dwGrantedAccess: %d, bGrantedAccess: %d, "), 
			dwGenericAccessMask, dwGrantedAccess, bGrantedAccess );
		WriteUpdateLog( strLog );

		if ( bGrantedAccess )
		{
			if ( dwGenericAccessMask == dwGrantedAccess )
			{
				bGrantedAccess = TRUE;
			}
			else
			{
				bGrantedAccess = FALSE;
			}
		}
		else
		{
			bGrantedAccess = FALSE;
		}
	}
	else
	{
		strLog.Format( _T("[CanAccessFile]AccessCheck failed, GetLastError: %d"), GetLastError() );
		WriteUpdateLog( strLog );

		bGrantedAccess = FALSE;
	}

	strLog.Format( _T("[CanAccessFile]bGrantedAccess: %d"), bGrantedAccess );
	WriteUpdateLog( strLog );

	delete []pBuf;
	CloseHandle( hImpersonatedToken );
	CloseHandle( hToken );
	return bGrantedAccess;  
}

        比如我们判断当前程序对C:\Windows\System32路径是否有写权限,可以这样来调回上面封装的函数:

BOOL bCanWrite = CanAccessFile( _T("C:\\Windows\\System32"), GENERIC_WRITE );

第二个参数传入GENERIC_WRITE即可。

你可能感兴趣的:(VC++常用功能代码封装,文件,文件夹,写权限)