You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
424 lines
12 KiB
424 lines
12 KiB
#include "precomp.h"
|
|
#include <wininet.h>
|
|
#include <regstr.h>
|
|
|
|
// 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;
|
|
}
|
|
|