Vista的文件拖放

    技术2022-05-11  69

     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,执行这个判断,其它的情况嘛,照旧。    

    最新回复(0)