#include "precomp.h" #include #include // Private forward decalarations static LPCTSTR mapSingleDw2Psz(PCMAPDW2PSZ pMap, UINT cEntries, DWORD dw, BOOL fFailNotFound = FALSE); ULONG CoTaskMemSize(LPVOID pv) { IMalloc *p; HRESULT hr; if (pv == NULL) return 0; hr = CoGetMalloc(1, &p); if (FAILED(hr)) return 0; return (ULONG)p->GetSize(pv); } UINT CoStringFromGUID(REFGUID rguid, LPTSTR pszBuf, UINT cchBuf) { WCHAR wszGuid[128]; UINT nSize; nSize = StringFromGUID2(rguid, wszGuid, countof(wszGuid)); W2Tbuf(wszGuid, pszBuf, cchBuf); return nSize; } LPCTSTR GetHrSz(HRESULT hr) { static MAPDW2PSZ mapHr[] = { // real HRESULTs DW2PSZ_PAIR(S_OK), DW2PSZ_PAIR(S_FALSE), DW2PSZ_PAIR(E_UNEXPECTED), DW2PSZ_PAIR(E_NOTIMPL), DW2PSZ_PAIR(E_OUTOFMEMORY), DW2PSZ_PAIR(E_INVALIDARG), DW2PSZ_PAIR(E_NOINTERFACE), DW2PSZ_PAIR(E_POINTER), DW2PSZ_PAIR(E_HANDLE), DW2PSZ_PAIR(E_ABORT), DW2PSZ_PAIR(E_FAIL), DW2PSZ_PAIR(E_ACCESSDENIED), DW2PSZ_PAIR(CO_E_NOTINITIALIZED), DW2PSZ_PAIR(CO_E_ALREADYINITIALIZED), DW2PSZ_PAIR(CO_E_DLLNOTFOUND), DW2PSZ_PAIR(CO_E_APPNOTFOUND), DW2PSZ_PAIR(CO_E_ERRORINDLL), DW2PSZ_PAIR(CO_E_APPDIDNTREG), DW2PSZ_PAIR(RPC_E_CHANGED_MODE), DW2PSZ_PAIR(REGDB_E_CLASSNOTREG), DW2PSZ_PAIR(REGDB_E_READREGDB), DW2PSZ_PAIR(REGDB_E_IIDNOTREG), DW2PSZ_PAIR(CLASS_E_NOAGGREGATION), DW2PSZ_PAIR(STG_E_FILENOTFOUND), DW2PSZ_PAIR(STG_E_PATHNOTFOUND), DW2PSZ_PAIR(TRUST_E_NOSIGNATURE), DW2PSZ_PAIR(TRUST_E_FAIL), DW2PSZ_PAIR(TRUST_E_SUBJECT_NOT_TRUSTED), // win32 errors DW2PSZ_PAIR(ERROR_FILE_NOT_FOUND), DW2PSZ_PAIR(ERROR_PATH_NOT_FOUND), // wininet errors DW2PSZ_PAIR(ERROR_INTERNET_INTERNAL_ERROR) }; LPCTSTR pszResult; pszResult = mapSingleDw2Psz(mapHr, countof(mapHr), hr, TRUE); if (pszResult != NULL) return pszResult; // error from HRESULT_FROM_WIN32 if (hr < 0 && (hr & (FACILITY_WIN32 << 16)) == (FACILITY_WIN32 << 16)) hr &= 0x0000FFFF; // only LOWORD matters return mapSingleDw2Psz(mapHr, countof(mapHr), hr); } DWORD GetStringField(LPTSTR szStr, UINT uField, LPTSTR szBuf, UINT cchBufSize) { LPTSTR pszBegin = szStr; LPTSTR pszEnd; TCHAR cSeparator; UINT i = 0; DWORD dwToCopy; if(cchBufSize == 0) return 0; szBuf[0] = TEXT('\0'); if(szStr == NULL) return 0; // figure out whether we're looking for commas or periods if (StrChr(szStr, TEXT(','))) cSeparator = TEXT(','); else { if (StrChr(szStr, TEXT('.'))) cSeparator = TEXT('.'); else return 0; } while(pszBegin && *pszBegin != TEXT('\0') && i < uField) { pszBegin = StrChr(pszBegin, cSeparator); if(pszBegin && (*pszBegin != TEXT('\0'))) pszBegin++; i++; } // we reached end of string, no field if(!pszBegin || *pszBegin == TEXT('\0')) { return 0; } pszEnd = StrChr(pszBegin, cSeparator); while(pszBegin <= pszEnd && *pszBegin == TEXT(' ')) pszBegin++; while(pszEnd > pszBegin && *(pszEnd - 1) == TEXT(' ')) pszEnd--; if(pszEnd > (pszBegin + 1) && *pszBegin == TEXT('"') && *(pszEnd-1) == TEXT('"')) { pszBegin++; pszEnd--; } dwToCopy = (DWORD) (pszEnd - pszBegin + 1); if(dwToCopy > cchBufSize) dwToCopy = cchBufSize; StrCpyN(szBuf, pszBegin, dwToCopy); return dwToCopy - 1; } DWORD GetIntField(LPTSTR szStr, UINT uField, DWORD dwDefault) { TCHAR szNumBuf[16]; if (GetStringField(szStr, uField, szNumBuf, countof(szNumBuf)) == 0) return dwDefault; else return StrToInt(szNumBuf); } void ConvertVersionStrToDwords(LPTSTR pszVer, LPDWORD pdwVer, LPDWORD pdwBuild) { DWORD dwTemp1,dwTemp2; dwTemp1 = GetIntField(pszVer, 0, 0); dwTemp2 = GetIntField(pszVer, 1, 0); *pdwVer = (dwTemp1 << 16) + dwTemp2; dwTemp1 = GetIntField(pszVer, 2, 0); dwTemp2 = GetIntField(pszVer, 3, 0); *pdwBuild = (dwTemp1 << 16) + dwTemp2; } void ConvertDwordsToVersionStr(LPTSTR pszVer, DWORD dwVer, DWORD dwBuild) { WORD w1, w2, w3, w4; w1 = HIWORD(dwVer); w2 = LOWORD(dwVer); w3 = HIWORD(dwBuild); w4 = LOWORD(dwBuild); wnsprintf(pszVer, 32, TEXT("%d,%d,%d,%d"), w1, w2, w3, w4); } DWORD GetIEVersion() { TCHAR szValue[MAX_PATH]; DWORD dwInstalledVer, dwInstalledBuild, dwSize; dwInstalledVer = dwInstalledBuild = (DWORD)-1; szValue[0] = TEXT('\0'); dwSize = sizeof(szValue); SHGetValue(HKEY_LOCAL_MACHINE, RK_IE, RV_VERSION, NULL, szValue, &dwSize); if (szValue[0] != TEXT('\0')) { ConvertVersionStrToDwords(szValue, &dwInstalledVer, &dwInstalledBuild); return dwInstalledVer; } if (dwInstalledVer == (DWORD)-1) { szValue[0] = TEXT('\0'); dwSize = sizeof(szValue); SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_APPPATHS TEXT("\\iexplore.exe"), NULL, NULL, szValue, &dwSize); if (szValue[0] != TEXT('\0')) { GetVersionFromFileWrap(szValue, &dwInstalledVer, &dwInstalledBuild, TRUE); return dwInstalledVer; } } return 0; } BOOL SetFlag(LPDWORD pdwFlags, DWORD dwMask, BOOL fSet /*= TRUE*/) { if (pdwFlags == NULL) return FALSE; if (fSet) *pdwFlags |= dwMask; else *pdwFlags &= ~dwMask; return TRUE; } // taken from IE setup code BOOL IsNTAdmin() { typedef BOOL (WINAPI *LPCHECKTOKENMEMBERSHIP)(HANDLE, PSID, PBOOL); static int s_fIsAdmin = 2; HANDLE hAccessToken = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID AdministratorsGroup; BOOL bRet = FALSE; // // If we have cached a value, return the cached value. Note I never // set the cached value to false as I want to retry each time in // case a previous failure was just a temp. problem (ie net access down) // bRet = FALSE; if( s_fIsAdmin != 2 ) return (BOOL)s_fIsAdmin; if (!IsOS(OS_NT)) { s_fIsAdmin = TRUE; // If we are not running under NT return TRUE. return (BOOL)s_fIsAdmin; } if(!IsOS(OS_NT5) && !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hAccessToken ) ) return FALSE; if(AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup) ) { // if we're running on W2K use the proper check (b388901 in W2K database) which // will work for restricted tokens if (IsOS(OS_NT5)) { HINSTANCE hAdvapi32 = NULL; LPCHECKTOKENMEMBERSHIP lpfnCheckTokenMembership = NULL; hAdvapi32 = LoadLibrary(TEXT("advapi32.dll")); if (hAdvapi32 != NULL) { lpfnCheckTokenMembership = (LPCHECKTOKENMEMBERSHIP)GetProcAddress(hAdvapi32, "CheckTokenMembership"); if (lpfnCheckTokenMembership != NULL) { BOOL fMember = FALSE; if (lpfnCheckTokenMembership(hAccessToken, AdministratorsGroup, &fMember) && fMember) { s_fIsAdmin = TRUE; bRet = TRUE; } } FreeLibrary(hAdvapi32); } } else { PTOKEN_GROUPS ptgGroups; DWORD dwReqSize; UINT i; ptgGroups = NULL; // See how big of a buffer we need for the token information if(!GetTokenInformation( hAccessToken, TokenGroups, NULL, 0, &dwReqSize)) { // GetTokenInfo should the buffer size we need - Alloc a buffer if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) ptgGroups = (PTOKEN_GROUPS) CoTaskMemAlloc(dwReqSize); } // ptgGroups could be NULL for a coupla reasons here: // 1. The alloc above failed // 2. GetTokenInformation actually managed to succeed the first time (possible?) // 3. GetTokenInfo failed for a reason other than insufficient buffer // Any of these seem justification for bailing. // So, make sure it isn't null, then get the token info if((ptgGroups != NULL) && GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwReqSize, &dwReqSize)) { // Search thru all the groups this process belongs to looking for the // Administrators Group. for( i=0; i < ptgGroups->GroupCount; i++ ) { if (EqualSid(ptgGroups->Groups[i].Sid, AdministratorsGroup)) { // Yea! This guy looks like an admin s_fIsAdmin = TRUE; bRet = TRUE; break; } } } if (ptgGroups != NULL) CoTaskMemFree(ptgGroups); } FreeSid(AdministratorsGroup); } // BUGBUG: Close handle here? doc's aren't clear whether this is needed. if (hAccessToken != NULL) CloseHandle(hAccessToken); return bRet; } HRESULT GetLcid(LCID *pLcid, LPCTSTR pcszLang, LPCTSTR pcszLocaleIni) { TCHAR szLookupEntries[1024]; TCHAR szLang[8]; LPTSTR pszIndex; HRESULT hRetVal = E_FAIL; if (pLcid == NULL || pcszLang == NULL || *pcszLang == TEXT('\0') || pcszLocaleIni == NULL || *pcszLocaleIni == TEXT('\0')) return hRetVal; if (GetPrivateProfileString(IS_ACTIVESETUP, NULL, TEXT(""), szLookupEntries, countof(szLookupEntries), pcszLocaleIni)) { for (pszIndex = szLookupEntries; *pszIndex; pszIndex += StrLen(pszIndex)+1) { GetPrivateProfileString(IS_ACTIVESETUP, pszIndex, TEXT(""), szLang, countof(szLang), pcszLocaleIni); if (StrCmpI(szLang, pcszLang) == 0) { TCHAR szHexLCID[16]; StrCpy(szHexLCID, TEXT("0x")); StrCat(szHexLCID, pszIndex); if (StrToIntEx(szHexLCID, STIF_SUPPORT_HEX, (int *)pLcid)) hRetVal = S_OK; break; } } } return hRetVal; } UINT GetUnitsFromCb(UINT cbSrc, UINT cbUnit) { ASSERT(0 == cbSrc % cbUnit); return (cbSrc / cbUnit); } ///////////////////////////////////////////////////////////////////////////// // Implementation helpers routines (private) LPCTSTR mapSingleDw2Psz(PCMAPDW2PSZ pMap, UINT cEntries, DWORD dw, BOOL fFailNotFound /*= FALSE*/) { static TCHAR szUnknown[30]; ASSERT(pMap != NULL); for (UINT i = 0; i < cEntries; i++) if ((pMap + i)->dw == dw) return (pMap + i)->psz; if (fFailNotFound) return NULL; wnsprintf(szUnknown, countof(szUnknown), TEXT("(unknown) [0x%08lX]"), dw); return szUnknown; }