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

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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++判断当前程序对文件或文件夹是否有写权限(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本的测试语句--文件测试

VC++检测防火墙是否开启判断程序是否加入防火墙白名单(附源码)

VC++判断目标文件是否被独占(附源码)

shell流程控制语句

VC++ Windows7及以上系统中管理员权限与UAC虚拟化详解(附源码)

Linux基本权限和特殊权限管理