Vista的文件拖放

 Vista提供了较XP更严格的安全管理机制, 使一些原本在XP上运行良好的应用程序, 在Vista上表现得水土不服。其中, 文件拖放即是其中一例。你可以试一下,拖动一个文本文件到一个双击打开的NotePad中,一切正常。 但当你Run As Administrator方式加载NotePad时,你会发现,文本文件怎么也无法被拖到NotePad中了。

 
我们尝试拿一个更复杂强大的文本编辑器,比如VisualStudio2005来试,结果,我们得到另外的答案,VS2005竟然显示了一个禁止拖放的图标来拒绝你的文件拖放请求!
 
从安全的角度来看,个中一定隐藏着一些无奈的考虑。我就不猜测其中的原因了。但要做到与VS2005一样,也还是要费一些周折。首先,我们需要一个函数来确定当前的进程是否运行在Administrator等级。为此, 我google了良久,终寻到一法,可解此题。
 
 
下面的这段代码,可以分辨出当前的进程是否Run As Administrator了。其原理十分简单,如果当前是Administrator,那么申请一个SID, 必为当前组标识中的一员。
#define MAX_NAME 256
 
BOOL SearchTokenGroupsForSID (VOID)
{
       DWORD i, dwSize = 0, dwResult = 0;
       HANDLE hToken;
       PTOKEN_GROUPS pGroupInfo;
       SID_NAME_USE SidType;
       TCHAR lpName[MAX_NAME];
       TCHAR lpDomain[MAX_NAME];
       BYTE sidBuffer[100];
       PSID pSID = (PSID)&sidBuffer;
       SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
       BOOL retVal = FALSE;
      
       // Open a handle to the access token for the calling process.
      
       if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken )) {
              WinDBGPrintf( _T("OpenProcessToken Error %u/n"), GetLastError() );
              return FALSE;
       }
      
       // Call GetTokenInformation to get the buffer size.
      
       if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize)) {
              dwResult = GetLastError();
              if( dwResult != ERROR_INSUFFICIENT_BUFFER ) {
                     WinDBGPrintf( _T("GetTokenInformation Error %u/n"), dwResult );
                     return FALSE;
              }
       }
      
       // Allocate the buffer.
      
       pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc( GPTR, dwSize );
      
       // Call GetTokenInformation again to get the group information.
      
       if(! GetTokenInformation(hToken, TokenGroups, pGroupInfo,
              dwSize, &dwSize ) ) {
              WinDBGPrintf( _T("GetTokenInformation Error %u/n"), GetLastError() );
              return FALSE;
       }
      
       // Create a SID for the BUILTIN/Administrators group.
      
       if(! AllocateAndInitializeSid( &SIDAuth, 2,
              SECURITY_BUILTIN_DOMAIN_RID,
              DOMAIN_ALIAS_RID_ADMINS,
              0, 0, 0, 0, 0, 0,
              &pSID) ) {
              WinDBGPrintf( _T("AllocateAndInitializeSid Error %u/n"), GetLastError() );
              return FALSE;
       }
      
       // Loop through the group SIDs looking for the administrator SID.
      
       for(i=0; i<pGroupInfo->GroupCount; i++) {
              if ( EqualSid(pSID, pGroupInfo->Groups[i].Sid) ) {
                    
                     // Lookup the account name and print it.
                    
                     dwSize = MAX_NAME;
                     if( !LookupAccountSid( NULL, pGroupInfo->Groups[i].Sid,
                            lpName, &dwSize, lpDomain,
                            &dwSize, &SidType ) ) {
                            dwResult = GetLastError();
                            if( dwResult == ERROR_NONE_MAPPED )
                                   _tcscpy(lpName, _T("NONE_MAPPED"));
                            else {
                                   WinDBGPrintf(_T("LookupAccountSid Error %u/n"), GetLastError());
                                   return FALSE;
                            }
                     }
 
                     WinDBGPrintf( _T("Current user is a member of the %s//%s group/n"),
                lpDomain, lpName );
                    
                     // Find out whether the SID is enabled in the token.
                     if (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
                     {
                                                      //只有此时,才能断定当前进程以Administrator运行
                            WinDBGPrintf(_T("The group SID is enabled./n"));
                            retVal = TRUE;
                     }
                     else if (pGroupInfo->Groups[i].Attributes &
                            SE_GROUP_USE_FOR_DENY_ONLY)
                                                      //这个时候,只能说明User是Administrator,但并未以Adminstrator方式运行.
                            WinDBGPrintf(_T("The group SID is a deny-only SID./n"));
                     else
                            WinDBGPrintf(_T("The group SID is not enabled./n"));
              }
       }
      
       if (pSID)
              FreeSid(pSID);
       if ( pGroupInfo )
              GlobalFree( pGroupInfo );
       return retVal;
}
 
我只是对这篇代码( Searching for a SID in an Access Token in C++)作了轻微的调整,最好还是到代码的出处去了解详情吧。
 
有了这个工具,下一步就简单了:
OSVERSIONINFO osvi;
 
::memset(&osvi,0,sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
WinDBGPrintf(_T("MajorVersion: %d, MinorVersion: %d/n"), osvi.dwMajorVersion, osvi.dwMinorVersion);
if(osvi.dwMajorVersion > 5)
{
       if(SearchTokenGroupsForSID())
       {
              WinDBGPrintf(_T("I'm Adminstrator, so disable AcceptDragFile/n"));
              DragAcceptFiles(0);
       }
       else
       {
              WinDBGPrintf(_T("I'm Standard user, so enable AcceptDragFile/n"));
              DragAcceptFiles(1);
       }
}
else
{
       WinDBGPrintf(_T("Current windows version is not VISTA. /n"));
       DragAcceptFiles(1);
}
我们以前又没有这个限制,所以只对主版本号> 5的windows,执行这个判断,其它的情况嘛,照旧。
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值