// Util.cpp : Implementation of CUtil #include "stdafx.h" #include "CompatUI.h" #include "Util.h" #include #include #include #include #include #include #include "Aclapi.h" extern "C" { #include "shimdb.h" } #pragma warning(disable:4786) #include #include #include #include #include #include using namespace std; ///////////////////////////////////////////////////////////////////////////// // CUtil extern "C" VOID InvalidateAppcompatCacheEntry( LPCWSTR pwszDosPath ); BOOL GetExePathFromObject( LPCTSTR lpszPath, // path to an arbitrary object CComBSTR& bstrExePath ); typedef INSTALLSTATE (WINAPI*PMsiGetComponentPath)( LPCTSTR szProduct, // product code for client product LPCTSTR szComponent, // component ID LPTSTR lpPathBuf, // returned path DWORD *pcchBuf // buffer character count ); typedef UINT (WINAPI* PMsiGetShortcutTarget)( LPCTSTR szShortcutTarget, // path to shortcut link file LPTSTR szProductCode, // fixed length buffer for product code LPTSTR szFeatureId, // fixed length buffer for feature id LPTSTR szComponentCode // fixed length buffer for component code ); BOOL IsUserAdmin( void ); BOOL GiveUsersWriteAccess( void ); BOOL IsLUAEnabled( LPCWSTR pszLayers ); wstring StrUpCase( wstring& wstr ); BOOL ShimExpandEnvironmentVars( LPCTSTR lpszCmd, CComBSTR& bstr ) { DWORD dwLength; LPTSTR lpBuffer = NULL; BOOL bExpanded = FALSE; if (_tcschr(lpszCmd, TEXT('%')) == NULL) { goto out; } dwLength = ExpandEnvironmentStrings(lpszCmd, NULL, 0); if (!dwLength) { goto out; } lpBuffer = new TCHAR[dwLength]; if (NULL == lpBuffer) { goto out; } dwLength = ExpandEnvironmentStrings(lpszCmd, lpBuffer, dwLength); if (!dwLength) { goto out; } bstr = lpBuffer; bExpanded = TRUE; out: if (!bExpanded) { bstr = lpszCmd; } if (lpBuffer) { delete[] lpBuffer; } return bExpanded; } wstring ShimUnquotePath( LPCTSTR pwszFileName ) { wstring sFileName; LPCTSTR pScan = pwszFileName; LPCTSTR pQuote; LPCTSTR pLastQuote = NULL; // skip over the leading spaces pScan += _tcsspn(pScan, TEXT(" \t")); while (*pScan) { pQuote = _tcschr(pScan, TEXT('\"')); if (NULL == pQuote) { sFileName += pScan; break; } // // we found a quote // is this the first quote we've found? if (pLastQuote == NULL) { pLastQuote = pQuote; // add the current string sFileName += wstring(pScan, (int)(pQuote-pScan)); } else { // we have a closing quote ++pLastQuote; sFileName += wstring(pLastQuote, (int)(pQuote-pLastQuote)); pLastQuote = NULL; } pScan = pQuote + 1; } return sFileName; } // // ShimGetPathFromCmdLine // BOOL ShimGetPathFromCmdLine( LPCTSTR pwszCmdLine, CComBSTR& StrPath ) { TCHAR chSave; LPTSTR pScan = (LPTSTR)pwszCmdLine; LPTSTR pAppName; TCHAR szBuffer[MAX_PATH]; DWORD dwLength; DWORD dwAttributes; BOOL bScan = FALSE; CComBSTR bstrPathName; if (*pScan == TEXT('\"')) { // seek till we find matching " pAppName = ++pScan; while (*pScan) { if (*pScan == TEXT('\"')) { break; } ++pScan; } } else { pAppName = pScan; while (*pScan) { if (_istspace(*pScan)) { bScan = TRUE; break; } ++pScan; } } while (TRUE) { chSave = *pScan; *pScan = TEXT('\0'); ShimExpandEnvironmentVars(pAppName, bstrPathName); // // check whether bstrPathName is valid (failure due to memory allocation is possible) // if (!bstrPathName) { // // overloaded operator ! for CComBSTR will check whether bstrPathName == NULL // break; } // // Check this path // dwLength = SearchPathW(NULL, bstrPathName, TEXT(".exe"), CHARCOUNT(szBuffer), szBuffer, NULL); // // restore the character // *pScan = chSave; if (dwLength && dwLength < CHARCOUNT(szBuffer)) { // // check attributes // dwAttributes = GetFileAttributesW(szBuffer); if ((dwAttributes != (DWORD)-1) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // // we are mighty done // StrPath = (LPCWSTR)szBuffer; return TRUE; } } if (!bScan || *pScan == TEXT('\0')) { break; } ++pScan; while (*pScan) { if (_istspace(*pScan)) { break; } ++pScan; } } return FALSE; } // // This class allows us to change error mode on selected apis // // class CSaveErrorMode { public: CSaveErrorMode() { m_uiErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); } ~CSaveErrorMode() { SetErrorMode(m_uiErrorMode); } protected: UINT m_uiErrorMode; }; STDMETHODIMP CUtil::IsCompatWizardDisabled(BOOL* pbDisabled) { HKEY hKey; LONG lResult; DWORD dwValue, dwSize = sizeof(dwValue); DWORD dwType; // // First, check for the whole engine being disabled. // lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, POLICY_KEY_APPCOMPAT_W, 0, KEY_READ, &hKey); if (lResult == ERROR_SUCCESS) { dwValue = 0; lResult = RegQueryValueExW(hKey, POLICY_VALUE_DISABLE_ENGINE_W, 0, &dwType, (LPBYTE)&dwValue, &dwSize); RegCloseKey (hKey); } // // The default is enabled, so if we didn't find a value, treat it like the value is 0. // if (lResult != ERROR_SUCCESS || dwValue == 0) { // // Check for the proppage being disabled. // lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, POLICY_KEY_APPCOMPAT_W, 0, KEY_READ, &hKey); if (lResult == ERROR_SUCCESS) { dwValue = 0; lResult = RegQueryValueExW(hKey, POLICY_VALUE_DISABLE_WIZARD_W, 0, &dwType, (LPBYTE) &dwValue, &dwSize); RegCloseKey (hKey); } // // The default is to be enabled, so if we didn't find a value, or the value is 0, then we're good to go. // } *pbDisabled = (lResult == ERROR_SUCCESS) && (dwValue != 0); return S_OK; } STDMETHODIMP CUtil::RemoveArgs(BSTR pVar, VARIANT* pRet) { // TODO: Add your implementation code here CComBSTR bstr; CSaveErrorMode ErrMode; if (!ShimGetPathFromCmdLine(pVar, bstr)) { bstr = pVar; } pRet->vt = VT_BSTR; pRet->bstrVal = bstr.Copy(); return S_OK; } STDMETHODIMP CUtil::GetItemKeys(BSTR pVar, VARIANT *pRet) { CComBSTR bstr = pVar; CComBSTR bstrOut; LPWSTR pwszPermKeys; DWORD cbSize; BOOL bLayers; if (!m_Safe) { return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); } bLayers = SdbGetPermLayerKeys(bstr, NULL, &cbSize, GPLK_ALL); if (bLayers) { pwszPermKeys = new WCHAR[cbSize / sizeof(WCHAR)]; if (pwszPermKeys == NULL) { return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); } bLayers = SdbGetPermLayerKeys(bstr, pwszPermKeys, &cbSize, GPLK_ALL); if (bLayers) { bstrOut = pwszPermKeys; } delete [] pwszPermKeys; } if (!bstrOut) { pRet->vt = VT_NULL; } else { pRet->vt = VT_BSTR; pRet->bstrVal = bstrOut.Copy(); } return S_OK; } STDMETHODIMP CUtil::SetItemKeys(BSTR pszPath, VARIANT* pKeys, VARIANT* pKeysMachine, BOOL *pVal) { // TODO: Add your implementation code here CComBSTR bstrKeys; CComBSTR bstrKeysMachine; BOOL bSuccess = TRUE; VARIANT varKeys; VARIANT varKeysMachine; if (!m_Safe) { return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); } InvalidateAppcompatCacheEntry(pszPath); if (pKeys->vt == VT_NULL || pKeys->vt == VT_EMPTY) { bSuccess &= SdbDeletePermLayerKeys(pszPath, FALSE); } else { VariantInit(&varKeys); if (SUCCEEDED(VariantChangeType(&varKeys, pKeys, 0, VT_BSTR))) { bstrKeys = varKeys.bstrVal; VariantClear(&varKeys); } if (bstrKeys) { bSuccess &= SdbSetPermLayerKeys(pszPath, bstrKeys, FALSE); } } if (IsUserAdmin()) { if (pKeysMachine->vt == VT_NULL || pKeysMachine->vt == VT_EMPTY) { bSuccess &= SdbDeletePermLayerKeys(pszPath, TRUE); } else { VariantInit(&varKeysMachine); if (SUCCEEDED(VariantChangeType(&varKeysMachine, pKeysMachine, 0, VT_BSTR))) { bstrKeysMachine = varKeysMachine.bstrVal; VariantClear(&varKeysMachine); } if (bstrKeysMachine) { bSuccess &= SdbSetPermLayerKeys(pszPath, bstrKeysMachine, TRUE); // // find whether we need to have LUA setting handled by granting write access to a common area // if (IsLUAEnabled(bstrKeysMachine)) { GiveUsersWriteAccess(); } } } } *pVal = bSuccess; return S_OK; } BOOL SearchGroupForSID( DWORD dwGroup, BOOL* pfIsMember ) { PSID pSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; BOOL fRes = TRUE; if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, dwGroup, 0, 0, 0, 0, 0, 0, &pSID)) { ATLTRACE(_T("[SearchGroupForSID] AllocateAndInitializeSid failed 0x%lx\n"), GetLastError()); return FALSE; } if (!CheckTokenMembership(NULL, pSID, pfIsMember)) { ATLTRACE(_T("[SearchGroupForSID] CheckTokenMembership failed 0x%x\n"), GetLastError()); fRes = FALSE; } FreeSid(pSID); return fRes; } BOOL IsUserAdmin( void ) { BOOL fIsUser, fIsAdmin, fIsPowerUser; if (!SearchGroupForSID(DOMAIN_ALIAS_RID_USERS, &fIsUser) || !SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin)) { return FALSE; } return (fIsUser && fIsAdmin); } BOOL GiveUsersWriteAccess( void ) { DWORD dwRes; EXPLICIT_ACCESS ea; PACL pOldDACL; PACL pNewDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; PSID pUsersSID = NULL; TCHAR szDir[MAX_PATH]; ExpandEnvironmentStrings(LUA_REDIR_W, szDir, MAX_PATH); if (!CreateDirectory(szDir, NULL)) { DWORD err = GetLastError(); if (GetLastError() != ERROR_ALREADY_EXISTS) { return FALSE; } } dwRes = GetNamedSecurityInfo(szDir, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD); if (ERROR_SUCCESS != dwRes) { goto Cleanup; } if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pUsersSID) ) { goto Cleanup; } // // Initialize an EXPLICIT_ACCESS structure for the new ACE. // ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = FILE_GENERIC_WRITE | FILE_GENERIC_READ | DELETE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea.Trustee.ptstrName = (LPTSTR)pUsersSID; // // Create a new ACL that merges the new ACE // into the existing DACL. // dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (ERROR_SUCCESS != dwRes) { goto Cleanup; } dwRes = SetNamedSecurityInfo(szDir, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL); if (ERROR_SUCCESS != dwRes) { goto Cleanup; } Cleanup: if (pSD) { LocalFree(pSD); } if (pUsersSID) { FreeSid(pUsersSID); } if (pNewDACL) { LocalFree(pNewDACL); } return (dwRes == ERROR_SUCCESS); } BOOL IsLUAEnabled( LPCWSTR pszLayers ) { LPCWSTR pchStart = pszLayers; LPCWSTR pch; wstring strTok; BOOL bLUAEnabled = FALSE; pchStart += wcsspn(pchStart, L"#!"); while (pchStart != NULL && *pchStart != L'\0' && !bLUAEnabled) { pchStart += wcsspn(pchStart, L" \t"); if (*pchStart == L'\0') { break; } pch = wcspbrk(pchStart, L" \t"); if (pch == NULL) { strTok = pchStart; pchStart = NULL; } else { strTok = wstring(pchStart, (size_t)(pch - pchStart)); StrUpCase(strTok); pchStart = pch; } bLUAEnabled = (strTok == L"LUA"); } return bLUAEnabled; } // this method returns true when we should present the LUA checkbox and // false when we should not STDMETHODIMP CUtil::CheckAdminPrivileges(BOOL *pVal) { *pVal = IsUserAdmin(); return S_OK; } STDMETHODIMP CUtil::RunApplication(BSTR pLayers, BSTR pszCmdLine, BOOL bEnableLog, DWORD* pResult) { LPCWSTR pszExt; BOOL bShellExecute = FALSE; BOOL bSuccess = FALSE; DWORD dwError = 0; DWORD dwBinaryType = 0; DWORD dwCreateProcessFlags = 0; CSaveErrorMode ErrMode; if (!m_Safe) { return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); } CComBSTR bstrAppName = pszCmdLine; ShimGetPathFromCmdLine(pszCmdLine, bstrAppName); CComBSTR bstrExePath; if (!bstrAppName) { dwError = ERROR_BAD_PATHNAME; goto Done; } // check if we are using .lnk file pszExt = PathFindExtension(bstrAppName); if (pszExt != NULL) { bShellExecute = !_tcsicmp(pszExt, TEXT(".lnk")); } if (!bShellExecute) { // not shell exec? check the binary if (!pszExt || (_tcsicmp(pszExt, TEXT(".cmd")) && _tcsicmp(pszExt, TEXT(".bat")))) { bShellExecute = !GetBinaryTypeW(bstrAppName, &dwBinaryType); if (!bShellExecute && (dwBinaryType == SCS_WOW_BINARY || dwBinaryType == SCS_PIF_BINARY)) { dwCreateProcessFlags |= CREATE_SEPARATE_WOW_VDM; } } } // // invalidate cache // if (::GetExePathFromObject(bstrAppName, bstrExePath)) { InvalidateAppcompatCacheEntry(bstrExePath); } SetEnvironmentVariable(TEXT("__COMPAT_LAYER"), pLayers); SetEnvironmentVariable(TEXT("SHIM_FILE_LOG"), bEnableLog ? TEXT("shim.log") : NULL); // // now we shall either ShellExecute or do a CreateProcess // if (bShellExecute) { int nLength = bstrAppName.Length() + 3; LPTSTR pszCmdLineShellExec = new TCHAR[nLength]; SHELLEXECUTEINFO ShExecInfo = { 0 }; if (pszCmdLineShellExec == NULL) { // // out of memory, just do a create process // goto HandleCreateProcess; } nLength = _sntprintf(pszCmdLineShellExec, nLength, TEXT("\"%s\""), (LPCTSTR)bstrAppName); if (nLength < 0) { delete[] pszCmdLineShellExec; goto HandleCreateProcess; } ShExecInfo.cbSize = sizeof(ShExecInfo); ShExecInfo.fMask = 0; //SEE_MASK_FLAG_NO_UI; ShExecInfo.lpVerb = L"open"; ShExecInfo.lpFile = pszCmdLineShellExec; ShExecInfo.nShow = SW_SHOW; bSuccess = ShellExecuteEx(&ShExecInfo); if (!bSuccess || (int)((INT_PTR)ShExecInfo.hInstApp) < 32) { dwError = GetLastError(); } delete[] pszCmdLineShellExec; } else { HandleCreateProcess: // get working directory TCHAR szWorkingDir[MAX_PATH]; LPTSTR pAppName = (LPTSTR)bstrAppName.m_str; int nLength; LPTSTR pszWorkingDir = NULL; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; LPTSTR pBackslash = _tcsrchr(pAppName, TEXT('\\')); if (pBackslash != NULL) { // // check for root // nLength = (int)(pBackslash - pAppName); if (nLength == 2 && pAppName[1] == TEXT(':')) { ++nLength; } _tcsncpy(szWorkingDir, pAppName, nLength); szWorkingDir[nLength] = TEXT('\0'); pszWorkingDir = szWorkingDir; } ZeroMemory(&StartupInfo, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); ZeroMemory(&ProcessInfo, sizeof(ProcessInfo)); bSuccess = CreateProcess(NULL, pszCmdLine, NULL, NULL, FALSE, 0, NULL, pszWorkingDir, &StartupInfo, &ProcessInfo); if (!bSuccess) { dwError = GetLastError(); } if (ProcessInfo.hThread) { CloseHandle(ProcessInfo.hThread); } if (ProcessInfo.hProcess) { CloseHandle(ProcessInfo.hProcess); } } Done: *pResult = dwError; SetEnvironmentVariable(TEXT("__COMPAT_LAYER"), NULL); SetEnvironmentVariable(TEXT("SHIM_FILE_LOG") , NULL); return S_OK; } BOOL GetExePathFromLink( LPMALLOC pMalloc, LPCITEMIDLIST pidlLinkFull, LPCTSTR pszLinkFile, LPTSTR pszExePath, DWORD dwBufferSize ) { IShellLink* psl = NULL; WIN32_FIND_DATA wfd; HRESULT hr; BOOL bSuccess = FALSE; TCHAR szPath[MAX_PATH]; IPersistFile* ipf = NULL; IShellLinkDataList* pdl; DWORD dwFlags = 0; BOOL bMsiLink = FALSE; HMODULE hMSI = NULL; // first do the link hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); if (!SUCCEEDED(hr)) { return FALSE; // we can't create link object } hr = psl->SetIDList(pidlLinkFull); // set the id list if (!SUCCEEDED(hr)) { goto out; } hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ipf); if (!SUCCEEDED(hr)) { goto out; } hr = ipf->Load(pszLinkFile, STGM_READ); if (!SUCCEEDED(hr)) { goto out; } // // resolve the link for now // // hr = psl->Resolve(NULL, SLR_NO_UI|SLR_NOUPDATE); // hr = psl->QueryInterface(IID_IShellLinkDataList, (LPVOID*)&pdl); if (SUCCEEDED(hr)) { hr = pdl->GetFlags(&dwFlags); bMsiLink = SUCCEEDED(hr) && (dwFlags & SLDF_HAS_DARWINID); pdl->Release(); } if (bMsiLink) { // // this is msi link, we need to crack it using msi // UINT ErrCode; TCHAR szProduct [MAX_PATH]; TCHAR szFeatureId [MAX_PATH]; TCHAR szComponentCode[MAX_PATH]; INSTALLSTATE is; hMSI = LoadLibrary(TEXT("Msi.dll")); if (NULL == hMSI) { goto out; } PMsiGetComponentPath pfnGetComponentPath = (PMsiGetComponentPath )GetProcAddress(hMSI, "MsiGetComponentPathW"); PMsiGetShortcutTarget pfnGetShortcutTarget = (PMsiGetShortcutTarget)GetProcAddress(hMSI, "MsiGetShortcutTargetW"); if (!pfnGetComponentPath || !pfnGetShortcutTarget) { goto out; } ErrCode = pfnGetShortcutTarget(pszLinkFile, szProduct, szFeatureId, szComponentCode); if (ERROR_SUCCESS != ErrCode) { goto out; } *pszExePath = TEXT('\0'); is = pfnGetComponentPath(szProduct, szComponentCode, pszExePath, &dwBufferSize); bSuccess = (INSTALLSTATE_LOCAL == is); } else { hr = psl->GetPath(pszExePath, dwBufferSize, &wfd, 0); bSuccess = SUCCEEDED(hr); } out: if (hMSI) { FreeLibrary(hMSI); } if (NULL != ipf) { ipf->Release(); } if (NULL != psl) { psl->Release(); } return bSuccess; } BOOL GetExePathFromObject( LPCTSTR lpszPath, // path to an arbitrary object CComBSTR& bstrExePath ) { IShellFolder* psh = NULL; LPMALLOC pMalloc = NULL; HRESULT hr; LPITEMIDLIST pidl = NULL; DWORD dwAttributes; CComBSTR bstr; BOOL bSuccess = FALSE; hr = SHGetMalloc(&pMalloc); if (!SUCCEEDED(hr)) { goto cleanup; } hr = SHGetDesktopFolder(&psh); if (!SUCCEEDED(hr)) { goto cleanup; } if (!ShimGetPathFromCmdLine(lpszPath, bstr)) { goto cleanup; } // // parse display name // dwAttributes = SFGAO_LINK | SFGAO_FILESYSTEM | SFGAO_VALIDATE; hr = psh->ParseDisplayName(NULL, NULL, bstr, // path to the executable file NULL, // number of chars eaten &pidl, &dwAttributes); if (!SUCCEEDED(hr)) { goto cleanup; } // // display name parsed, check whether it's a link // if (dwAttributes & SFGAO_LINK) { TCHAR szExePath[MAX_PATH]; // // it's a link, crack it // bSuccess = GetExePathFromLink(pMalloc, pidl, bstr, szExePath, CHARCOUNT(szExePath)); // after recovering the path -- get the env vars expanded if (bSuccess) { ShimExpandEnvironmentVars(szExePath, bstrExePath); } } else if (dwAttributes & SFGAO_FILESYSTEM) { // // filesystem object (a file) // bstrExePath = bstr; bSuccess = TRUE; } cleanup: if (pidl) { pMalloc->Free(pidl); } if (psh) { psh->Release(); } if (pMalloc) { pMalloc->Release(); } return bSuccess; } STDMETHODIMP CUtil::GetExePathFromObject(BSTR pszPath, VARIANT* pExePath) { CComBSTR bstrExePath; BOOL bSuccess; CSaveErrorMode ErrMode; if (!m_Safe) { return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); } bSuccess = ::GetExePathFromObject(pszPath, bstrExePath); if (bSuccess) { pExePath->vt = VT_BSTR; pExePath->bstrVal = bstrExePath.Copy(); } else { pExePath->vt = VT_NULL; } return S_OK; } STDMETHODIMP CUtil::IsSystemTarget(BSTR bstrPath, BOOL *pbSystemTarget) { CComBSTR bstrExePath; BOOL bSystemTarget = FALSE; DWORD dwAttributes; CSaveErrorMode ErrMode; /*++ // // This code was used to check system directory // ULONG uSize; int nch; TCHAR szSystemDir[MAX_PATH]; TCHAR szCommonPath[MAX_PATH]; uSize = ::GetSystemWindowsDirectory(szSystemDir, CHARCOUNT(szSystemDir)); if (uSize == 0 || uSize > CHARCOUNT(szSystemDir)) { *pbSystemTarget = FALSE; return S_OK; } --*/ if (!::GetExePathFromObject(bstrPath, bstrExePath)) { bstrExePath = bstrPath; } if (!bstrExePath) { goto Done; } /*++ // this code was used before -- it checked system directory as // well as sfc, we are only checking sfc now nch = PathCommonPrefix(szSystemDir, bstrExePath, szCommonPath); bSystemTarget = (nch == (int)uSize); if (!bSystemTarget) { bSystemTarget = SfcIsFileProtected(NULL, bstrExePath); } --*/ bSystemTarget = SfcIsFileProtected(NULL, bstrExePath); if (!bSystemTarget) { dwAttributes = GetFileAttributes(bstrExePath); bSystemTarget = (dwAttributes == (DWORD)-1 || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)); } Done: *pbSystemTarget = bSystemTarget; return S_OK; } STDMETHODIMP CUtil::IsExecutableFile(BSTR bstrPath, BOOL *pbExecutableFile) { BOOL bExecutable = FALSE; DWORD dwExeType = 0; CComBSTR bstrExePath; LPCWSTR pszExt; CSaveErrorMode ErrMode; if (!m_Safe) { return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); } if (!::GetExePathFromObject(bstrPath, bstrExePath)) { bstrExePath = bstrPath; } if (!bstrExePath) { // // this could happen on a memory allocation failure path // goto Done; } bExecutable = GetBinaryTypeW(bstrExePath, &dwExeType); if (!bExecutable) { // is this a batch file? if not -- you are out! pszExt = PathFindExtension(bstrPath); if (pszExt != NULL) { bExecutable = !_tcsicmp(pszExt, TEXT(".bat")) || !_tcsicmp(pszExt, TEXT(".cmd")); } } Done: *pbExecutableFile = bExecutable; return S_OK; } //////////////////////////////////////////////////////////////////////////////////// // // Security: Check for invocation via the hcp protocol and system as the host // // BOOL CheckHost( IUnknown* pObjectClientSite ) { HRESULT hr; CComPtr spClientSite; BSTR bstrURL = NULL; TCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH]; TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH]; URL_COMPONENTS UrlComponents = { 0 }; BOOL bHostVerified = FALSE; if (pObjectClientSite == NULL) { return FALSE; } CComQIPtr spServiceProvider(pObjectClientSite); if (spServiceProvider == NULL) { return FALSE; } CComPtr spBrowser; hr = spServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast(&spBrowser)); if (!SUCCEEDED(hr)) { return FALSE; } // // we have browser i/f -- get url now // hr = spBrowser->get_LocationURL(&bstrURL); if (!SUCCEEDED(hr) || bstrURL == NULL) { return FALSE; } // // crack the url // UrlComponents.dwStructSize = sizeof(UrlComponents); UrlComponents.lpszScheme = szScheme; UrlComponents.dwSchemeLength = CHARCOUNT(szScheme); UrlComponents.lpszHostName = szHostName; UrlComponents.dwHostNameLength = CHARCOUNT(szHostName); if (!InternetCrackUrl(bstrURL, 0, 0, &UrlComponents)) { goto cleanup; } // // now we should be good to go to check scheme and the host name // if (_tcsicmp(UrlComponents.lpszScheme, TEXT("hcp")) != 0 ) { // // bad protocol // goto cleanup; } if (_tcsicmp(UrlComponents.lpszHostName, TEXT("system")) != 0) { // // bad host // goto cleanup; } bHostVerified = TRUE; cleanup: if (bstrURL) { SysFreeString(bstrURL); } return bHostVerified; }