Windows2000/private/inet/urlmon/zones/zoneutil.cxx
2020-09-30 17:12:32 +02:00

973 lines
27 KiB
C++

// File: util.cxx
// Contents: Utility classes.
// Classes: CRefCount, CRegKey
// Functions://
// History:
#include "zonepch.h"
#include "advpub.h"
#ifdef UNIX
#include <platform.h>
#endif /* UNIX */
#include "shfolder.h"
// Misc utility functions and declarations.
#define DRIVE_UNINIT 0xFFFF // Indicates that we haven't called GetDriveType yet.
DWORD rgdwDriveTypeCache[26]; // one for each drive letter.
BOOL g_bInit = FALSE;
BOOL g_bUseHKLMOnly = FALSE;
static LPWSTR s_pwzCacheDir;
static HRESULT GetCacheDirectory( );
static CHAR *s_szMarkPrefix = "<!-- saved from url=(%04d)";
static CHAR *s_szMarkSuffix = " -->\r\n";
CSharedMem g_SharedMem;
BOOL IsZonesInitialized( )
{
return g_bInit;
}
BOOL ZonesInit( )
{
if (!g_bInit)
{
DWORD dwType;
DWORD dwSize = sizeof(DWORD);
DWORD dwDefault = FALSE ; // If no entry found default is use HKCU.
g_bInit = TRUE;
// Call the shlwapi wrapper function that directly reads in a value for us.
// Note that if the call fails we have the right value in g_bHKLMOnly already.
SHRegGetUSValue(SZPOLICIES, SZHKLMONLY, &dwType, &g_bUseHKLMOnly, &dwSize, TRUE, &dwDefault, sizeof(dwDefault));
InitializeCriticalSection(&CUrlZoneManager::s_csect);
CUrlZoneManager::s_bcsectInit = TRUE;
CSecurityManager::GlobalInit();
// Initialize the drive type cache.
for ( int i = 0 ; i < ARRAYSIZE(rgdwDriveTypeCache) ; i++ )
rgdwDriveTypeCache[i] = DRIVE_UNINIT;
GetCacheDirectory(); // Return value ignored.
}
return TRUE;
}
VOID ZonesUnInit ( )
{
CUrlZoneManager::Cleanup( );
CSecurityManager::GlobalCleanup( );
g_SharedMem.Release();
// Free any memory allocated for the cache directory.
delete [] s_pwzCacheDir;
}
// IEAK calls this function so force us to re-read the global settings for
// HKLM vs HKCU.
STDAPI ZonesReInit(DWORD /* dwReserved */)
{
DWORD dwType;
DWORD dwDefault = g_bUseHKLMOnly;
DWORD dwSize = sizeof(DWORD);
DWORD dwError = SHRegGetUSValue(SZPOLICIES, SZHKLMONLY, &dwType, &g_bUseHKLMOnly, &dwSize, TRUE, &dwDefault, sizeof(dwDefault));
return HRESULT_FROM_WIN32(dwError);
}
// SHDOCVW calls this during Thicket save to get the comment to flag the
// saved file as
STDAPI GetMarkOfTheWeb(LPCSTR pszURL, LPCSTR pszFile, DWORD dwFlags, LPSTR *ppszMark)
{
HRESULT hr = S_OK;
int cchURL = lstrlenA(pszURL);
// Note - the code assumes that lstrlen(IDS_MARK_PREFIX)
// equals wsprintf(IDS_MARK_PREFIX, lstrlen(url)
*ppszMark = (LPSTR)LocalAlloc( LMEM_FIXED, (lstrlenA(s_szMarkPrefix) + cchURL + lstrlenA(s_szMarkSuffix) + 1) * sizeof(CHAR) );
if ( *ppszMark )
{
wsprintfA( *ppszMark, s_szMarkPrefix, cchURL );
lstrcatA( *ppszMark, pszURL );
lstrcatA( *ppszMark, s_szMarkSuffix );
}
else
hr = E_OUTOFMEMORY;
return hr;
}
// The security manager calls this to sniff a file: URL for the Mark of the Web
BOOL FileBearsMarkOfTheWeb(LPCTSTR pszFile, LPWSTR *ppszURLMark)
{
BOOL fMarked = FALSE;
HANDLE hFile;
CHAR szMarkPrefix[MARK_PREFIX_SIZE];
CHAR szMarkSuffix[MARK_SUFFIX_SIZE];
WCHAR wzMarkPrefix[MARK_PREFIX_SIZE];
WCHAR wzMarkSuffix[MARK_SUFFIX_SIZE];
BOOL fIsInUnicode = FALSE;
DWORD cchReadBufLen = 0;
DWORD cchURL;
CHAR *szMarkHead = NULL;
WCHAR *wzMarkHead = NULL;
CHAR *szMarkSuf = NULL;
WCHAR *wzMarkSuf = NULL;
CHAR *pszURLMark = NULL;
DWORD cchReadLen = 0;
char *pszTmp = NULL;
char *szReadBuf = NULL;
int iIteration = 1;
lstrcpyA(szMarkPrefix, s_szMarkPrefix);
lstrcpyA(szMarkSuffix, s_szMarkSuffix);
hFile = CreateFile( pszFile, GENERIC_READ, FILE_SHARE_READ , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile != INVALID_HANDLE_VALUE )
{
DWORD cchPrefix = lstrlenA(szMarkPrefix);
DWORD dwRead;
CHAR szHeader[UNICODE_HEADER_SIZE];
DWORD cchHeader = UNICODE_HEADER_SIZE;
if (ReadFile(hFile, szHeader, cchHeader, &dwRead, NULL) && cchHeader == dwRead)
{
if ((BYTE)szHeader[0] == (BYTE)0xFF && (BYTE)szHeader[1] == (BYTE)0xFE)
{
fIsInUnicode = TRUE;
}
else
{
fIsInUnicode = FALSE;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
TransAssert(GetLastError() == NO_ERROR);
}
}
else
{
// Unable to sniff for header
goto Exit;
}
// File pointer is not at "real" beginning of file, regardless of
// whether we are reading a UNICODE or ANSI file.
szReadBuf = NULL;
cchReadBufLen = 0;
iIteration = 1;
// Anchor NULL to make szMarkPrefix: <!-- saved from url=
szMarkPrefix[cchPrefix-6] = '\0';
if (fIsInUnicode)
{
if (!MultiByteToWideChar(CP_ACP, 0, szMarkPrefix, -1, wzMarkPrefix, MARK_PREFIX_SIZE))
{
goto Exit;
}
if (!MultiByteToWideChar(CP_ACP, 0, szMarkSuffix, -1, wzMarkSuffix, MARK_PREFIX_SIZE))
{
goto Exit;
}
}
for (;;)
{
cchReadBufLen = INTERNET_MAX_URL_LENGTH + EXTRA_BUFFER_SIZE * iIteration + 1;
if (fIsInUnicode)
{
cchReadBufLen *= 2;
}
szReadBuf = new char[cchReadBufLen];
if (!szReadBuf)
{
goto Exit;
}
cchReadLen = (fIsInUnicode) ? (cchReadBufLen - 2) : (cchReadBufLen - 1);
if (ReadFile(hFile, szReadBuf, cchReadLen, &dwRead, NULL))
{
// look for mark of the web
if (fIsInUnicode)
{
szReadBuf[dwRead] = L'\0';
wzMarkHead = StrStrW((WCHAR *)szReadBuf, wzMarkPrefix);
if (wzMarkHead)
{
// Look for mark of the web suffix. If we don't
// have it, that means that we didn't have enough
// space for the buffer, and we need to try again
// with more space.
wzMarkSuf = StrStrW(wzMarkHead, wzMarkSuffix);
if (wzMarkSuf)
{
// Found suffix. We're done.
break;
}
else
{
if (dwRead < cchReadLen)
{
// We've already read everything, and
// we didn't find the suffix!
goto Exit;
}
// Didn't find suffix because buffer was too
// small. Try it again
delete [] szReadBuf;
szReadBuf = NULL;
iIteration++;
SetFilePointer(hFile, 2, 0, FILE_BEGIN);
TransAssert(GetLastError() == NO_ERROR);
continue;
}
}
else
{
// Can't find the mark head! Must find it on
// first iteration, or we give up.
goto Exit;
}
}
else
{
// We are dealing with ANSI
szReadBuf[dwRead] = '\0';
szMarkHead = StrStrA(szReadBuf, szMarkPrefix);
if (szMarkHead)
{
// Look for mark of the web suffix. If we don't
// have it, that means that we didn't have enough
// space for the buffer, and we need to try again
// with more space.
szMarkSuf = StrStrA(szMarkHead, szMarkSuffix);
if (szMarkSuf)
{
// Found suffix. We're done.
break;
}
else
{
if (dwRead < cchReadLen)
{
// We've already read everything, and
// we didn't find the suffix!
goto Exit;
}
// Didn't find suffix because buffer was too
// small. Try it again
delete [] szReadBuf;
szReadBuf = NULL;
iIteration++;
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
TransAssert(GetLastError() == NO_ERROR);
continue;
}
}
else
{
// Can't find the mark head! Must find it on
// first iteration, or we give up.
goto Exit;
}
}
}
else
{
// Read failure!
TransAssert(0);
}
}
// now wzMarkHead or szMarkHead points to beginning of the mark
// of the web, and wzMarkSuf or szMarkSuf point to the mark suffix
if (fIsInUnicode)
{
DWORD cchURL = 0;
LPWSTR wzPtr = StrStrW(wzMarkHead, L"=(");
TransAssert(wzPtr);
wzPtr += 2; // skip to beginning of length
wzPtr[4] = L'\0'; // anchor NULL
cchURL = StrToIntW(wzPtr);
if (cchURL > INTERNET_MAX_URL_LENGTH)
{
cchURL = INTERNET_MAX_URL_LENGTH;
}
*ppszURLMark = (WCHAR*)LocalAlloc(LMEM_FIXED, (cchURL+1) * sizeof(WCHAR));
if (!*ppszURLMark)
{
goto Exit;
}
// StrCpyN length includes NULL terminator
StrCpyNW(*ppszURLMark, wzPtr + 5, cchURL + 1);
}
else
{
DWORD cchURL = 0;
LPSTR szPtr = StrStrA(szMarkHead, "=(");
TransAssert(szPtr);
szPtr += 2; // skip to beginning of length
szPtr[4] = '\0'; // anchor NULL
cchURL = StrToIntA(szPtr);
if (cchURL > INTERNET_MAX_URL_LENGTH)
{
cchURL = INTERNET_MAX_URL_LENGTH;
}
pszTmp = new char[cchURL + 1];
if (!pszTmp)
{
goto Exit;
}
*ppszURLMark = (WCHAR*)LocalAlloc(LMEM_FIXED, (cchURL+1) * sizeof(WCHAR));
if (!*ppszURLMark)
{
goto Exit;
}
// StrCpyN length includes NULL terminator
StrCpyNA(pszTmp, szPtr + 5, cchURL + 1);
MultiByteToWideChar(CP_ACP, 0, pszTmp, -1, *ppszURLMark, cchURL);
(*ppszURLMark)[cchURL] = '\0';
}
if (szReadBuf)
{
delete [] szReadBuf;
szReadBuf = NULL;
}
}
else
{
// CreateFile failure
goto Exit;
}
fMarked = TRUE;
Exit:
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
}
if (szReadBuf)
{
delete [] szReadBuf;
}
if (pszURLMark)
{
delete [] pszURLMark;
}
if (pszTmp) {
delete [] pszTmp;
}
return fMarked;
}
HRESULT GetCacheDirectory( )
{
HRESULT hr = E_FAIL;
HMODULE hMod;
OSVERSIONINFOA osvi;
BOOL bNT5OrGreater = FALSE;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if (GetVersionExA(&osvi))
{
bNT5OrGreater = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 5);
}
// On NT5 or greater, the functionality is available in shell32.dll. We don't need to go through
// shfolder.dll in this case.
hMod = LoadLibrary(bNT5OrGreater ? TEXT("shell32.dll") : TEXT("shfolder.dll"));
if (hMod == NULL)
return HRESULT_FROM_WIN32(GetLastError());
PFNSHGETFOLDERPATH pfnGetFolderPath;
#ifdef UNICODE
pfnGetFolderPath = (PFNSHGETFOLDERPATHW)GetProcAddress(hMod, "SHGetFolderPathW");
#else
pfnGetFolderPath = (PFNSHGETFOLDERPATHA)GetProcAddress(hMod, "SHGetFolderPathA");
#endif
if (pfnGetFolderPath == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
TCHAR rgchCachePath[MAX_PATH];
hr = pfnGetFolderPath(NULL, CSIDL_INTERNET_CACHE, NULL, 0, rgchCachePath);
if (rgchCachePath[0] == TEXT('\0'))
hr = E_FAIL;
if (SUCCEEDED(hr))
{
if (s_pwzCacheDir != NULL)
{
delete [] s_pwzCacheDir;
s_pwzCacheDir = NULL;
}
// Allocate memory for the new location.
s_pwzCacheDir = new TCHAR[lstrlen(rgchCachePath) + 1];
if (s_pwzCacheDir != NULL)
{
StrCpy(s_pwzCacheDir, rgchCachePath);
hr = S_OK;
}
else
hr = E_OUTOFMEMORY;
}
}
FreeLibrary(hMod);
return hr;
}
#if NOTUSED // Keep this code around in the unlikely event that we resurrect the Unix port.
// This function gets the location of the cache directory.
HRESULT GetCacheDirectory( )
{
DWORD dwType;
// First figure out if we are using per-user cache or per-machine cache.
// This decides which registry key to look at for the cache value.
BOOL fPerUserCache = TRUE;
#ifndef UNIX
OSVERSIONINFOA osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
fPerUserCache = TRUE;
}
else
{
DWORD dwUserProfile = 0;
DWORD dwSize = sizeof(dwUserProfile);
// Determine if user profiles are enabled.
if ((ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, SZLOGON, SZUSERPROFILES, &dwType, &dwUserProfile, &dwSize))
&& (dwUserProfile != 0 ))
{
fPerUserCache = TRUE;
// Look for the exceptional case where User Profiles are enabled but the cache is still
// global.
dwSize = sizeof(dwUserProfile);
if ((ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, SZCACHE, SZUSERPROFILES, &dwType, &dwUserProfile, &dwSize))
&& (dwUserProfile == 0))
{
fPerUserCache = FALSE;
}
}
else
{
fPerUserCache = FALSE;
}
}
#endif /* !UNIX */
HRESULT hr = S_OK;
#ifdef UNIX
WCHAR wszIE5Dir[] = L"ie5/";
DWORD cchPath = MAX_PATH + sizeof(wszIE5Dir)/sizeof(WCHAR);
#else
DWORD cchPath = MAX_PATH;
#endif /* !UNIX */
s_pwzCacheDir = new WCHAR[cchPath];
DWORD dwError = NOERROR;
// First figure out if we are using per-user cache or per-machine cache.
// This decides which registry key to look at for the cache value.
if (s_pwzCacheDir != NULL)
{
LPCWSTR pwzKey = fPerUserCache ? SZSHELLFOLDER : SZCACHECONTENT;
LPCWSTR pwzValue = fPerUserCache ? SZTIFS : SZCACHEPATH ;
HKEY hKey = fPerUserCache ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
dwError = SHGetValueW(hKey, pwzKey, pwzValue, &dwType, s_pwzCacheDir, &cchPath);
}
else
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
}
if (dwError != NOERROR)
{
delete [] s_pwzCacheDir;
s_pwzCacheDir = NULL;
hr = HRESULT_FROM_WIN32(dwError);
}
else
{
TransAssert(s_pwzCacheDir != NULL);
PathRemoveBackslashW(s_pwzCacheDir);
#ifdef UNIX
{
int ccPath, index;
int lenIE5Dir = lstrlen(wszIE5Dir);
ccPath = lstrlen(s_pwzCacheDir);
index = ccPath - 1;
while(index >= 0 && s_pwzCacheDir[index] != FILENAME_SEPARATOR_W)
index--;
index++;
memmove(&s_pwzCacheDir[index+lenIE5Dir],&s_pwzCacheDir[index],(ccPath-index+1)*sizeof(TCHAR));
memcpy(&s_pwzCacheDir[index], wszIE5Dir, lenIE5Dir*sizeof(TCHAR));
}
#endif /* UNIX */
hr = S_OK;
}
return hr;
}
#endif // NOTUSED
BOOL IsFileInCacheDir(LPCWSTR pwzFile)
{
BOOL bReturn = FALSE;
if (s_pwzCacheDir != NULL)
{
bReturn = PathIsPrefixW(s_pwzCacheDir, pwzFile);
}
return bReturn;
}
// This function takes a DWORD and returns a wide char string
// in hex. There is no leading 0x and the leading 0's are stripped off
// This is to avoid pulling in the general wsprintfW into wininet which is
// pretty big. You have to pass in enough memory to write the resulting string
// into ( i.e >= 9 chars)
BOOL DwToWchar(DWORD dw, LPWSTR pwz, int radix)
{
char sz[9];
LPSTR psz = sz;
LPSTR pszTemp = (LPSTR)pwz;
char rgFormatHex[] = "%lX";
char rgFormatDecimal[] = "%ld";
char *pszFormat;
if (radix == 16)
pszFormat = rgFormatHex;
else if (radix == 10)
pszFormat = rgFormatDecimal;
else
{
TransAssert(FALSE);
return FALSE;
}
if (wsprintfA(sz, pszFormat, dw) == 0)
{
return FALSE;
}
#ifndef unix
// Everything in the string sz is ANSI.
while (*psz != 0)
{
*pszTemp++ = *psz++;
*pszTemp++ = '\0';
}
// Put the trailing NULL to the wide-char string.
*pszTemp++ = '\0';
*pszTemp++ = '\0';
#else
while(*psz != 0)
*pwz++ = (WCHAR)(DWORD)*psz++;
*pwz++ = 0;
#endif /* unix */
return TRUE;
}
// Drive type caching function.
DWORD GetDriveTypeFromCacheA(LPCSTR lpsz)
{
// NOTE: The retail version doesn't do any paramater validation to determine if this path is
// a valid one. So something like CTHISISGARBAGE will return the drive type for C:.
// This is just meant to be used inside the security manager so we can bypass these
// checks.
TransAssert(lstrlenA(lpsz) >= 3); // c:\ for example
TransAssert(lpsz[1] == ':' && lpsz[2] == '\\');
#ifndef unix
CHAR ch = (CHAR)CharLowerA((LPSTR)lpsz[0]);
#else
CHAR *pch = CharLowerA((LPSTR)lpsz);
CHAR ch = *pch;
#endif /* unix */
#ifndef UNIX
if (ch >= 'a' && ch <= 'z')
{
// First check the cache to see if the entry already exists.
int index = ch - 'a';
if (rgdwDriveTypeCache[index] == DRIVE_UNINIT)
{
rgdwDriveTypeCache[index] = GetDriveTypeA(lpsz);
}
TransAssert(rgdwDriveTypeCache[index] != DRIVE_UNINIT);
return rgdwDriveTypeCache[index];
}
#else
if (ch == '/')
{
// IEUNIX - On unix we have only one drive "/" which is of type fixed
// This was causing a wrong zone to be calculated for unix paths.
return DRIVE_FIXED;
}
#endif
else
{
return DRIVE_UNKNOWN;
}
}
// CRegKey
LONG CRegKey::Close()
{
LONG lRes = ERROR_SUCCESS;
if (m_hKey != NULL)
{
lRes = SHRegCloseUSKey(m_hKey);
m_hKey = NULL;
}
return lRes;
}
LONG CRegKey::Create(HUSKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired)
{
HUSKEY hKey = NULL;
// BUGBUG : Is this the correct flag to call this function with?
DWORD dwFlags = m_bHKLMOnly ? SHREGSET_FORCE_HKLM : SHREGSET_FORCE_HKCU;
LONG lRes = SHRegCreateUSKey(lpszKeyName, samDesired, hKeyParent, &hKey, dwFlags);
if (lRes == ERROR_SUCCESS)
{
lRes = Close();
m_hKey = hKey;
}
return lRes;
}
LONG CRegKey::Open(HUSKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired)
{
HUSKEY hKey = NULL;
LONG lRes = SHRegOpenUSKey(lpszKeyName, samDesired, hKeyParent, &hKey, m_bHKLMOnly);
if (lRes == ERROR_SUCCESS)
{
lRes = Close();
TransAssert(lRes == ERROR_SUCCESS);
m_hKey = hKey;
}
return lRes;
}
LONG CRegKey::QueryValue(DWORD* pdwValue, LPCTSTR lpszValueName)
{
DWORD dwType = NULL;
DWORD dwCount = sizeof(DWORD);
LONG lRes = SHRegQueryUSValue(m_hKey, lpszValueName, &dwType,
pdwValue, &dwCount, m_bHKLMOnly, NULL, 0);
TransAssert((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD));
TransAssert((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD)));
return lRes;
}
LONG CRegKey::QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, DWORD* pdwCount)
{
TransAssert(pdwCount != NULL);
DWORD dwType = 0;
LONG lRes = SHRegQueryUSValue(m_hKey, lpszValueName, &dwType,
szValue, pdwCount, m_bHKLMOnly, NULL, 0);
TransAssert((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) ||
(dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ));
return lRes;
}
LONG CRegKey::QueryBinaryValue(LPBYTE pb, LPCTSTR lpszValueName, DWORD* pdwCount)
{
TransAssert(pdwCount != NULL);
DWORD dwType = NULL;
LONG lRes = SHRegQueryUSValue(m_hKey, lpszValueName, &dwType,
pb, pdwCount, m_bHKLMOnly, NULL, 0);
TransAssert((lRes!=ERROR_SUCCESS) || (dwType == REG_BINARY));
return lRes;
}
LONG WINAPI CRegKey::SetValue(HUSKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName, BOOL bHKLMOnly)
{
TransAssert(lpszValue != NULL);
CRegKey key(bHKLMOnly);
LONG lRes = key.Create(hKeyParent, lpszKeyName, KEY_WRITE);
if (lRes == ERROR_SUCCESS)
lRes = key.SetValue(lpszValue, lpszValueName);
return lRes;
}
LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName)
{
TransAssert(lpszValue != NULL);
CRegKey key(m_bHKLMOnly);
LONG lRes = key.Create(m_hKey, lpszKeyName, KEY_WRITE);
if (lRes == ERROR_SUCCESS)
lRes = key.SetValue(lpszValue, lpszValueName);
return lRes;
}
// Autoregistration entry points
HRESULT CallRegInstall(LPSTR szSection)
{
HRESULT hr = E_FAIL;
HINSTANCE hinstAdvPack = LoadLibraryA("ADVPACK.DLL");
if (hinstAdvPack)
{
REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, achREGINSTALL);
if (pfnri)
{
hr = pfnri(g_hInst, szSection, NULL);
}
FreeLibrary(hinstAdvPack);
}
return hr;
}
STDAPI
ZonesDllInstall
(
IN BOOL bInstall, // Install or Uninstall
IN LPCWSTR pwStr
)
{
TransAssert(pwStr != NULL);
HRESULT hr = S_OK;
BOOL bUseHKLM = TRUE;
if (pwStr && (0 == StrCmpIW(pwStr, L"HKCU")))
{
bUseHKLM = FALSE;
}
if ( bInstall )
{
// Backup IE3 user agent string.
CallRegInstall("BackupUserAgent");
CallRegInstall("BackupConnectionSettings");
CallRegInstall(bUseHKLM ? "Backup.HKLM" : "Backup.HKCU");
hr = CallRegInstall(bUseHKLM ? "Reg.HKLM" : "Reg.HKCU");
if (!bUseHKLM)
{
// Bug # 19514: To appease the press, we need to change the default for scripting unsafe activex
// controls to "disable" instead of "prompt". But at install time we can't blindly overwrite
// the existing value. We have to check if the users Intranet/Internet zones are at medium
// security from the previous install. To avoid instantiating the zone manager at registration
// time we also hardcode the registry values here.
#define SZINTRANET SZZONES TEXT("1")
#define SZINTERNET SZZONES TEXT("3")
TransAssert(URLZONE_INTRANET == 1);
TransAssert(URLZONE_INTERNET == 3);
DWORD dwCurrentLevel ;
CRegKey regKeyIntranet(FALSE);
if ((regKeyIntranet.Open(NULL, SZINTRANET, KEY_READ) == ERROR_SUCCESS) &&
(regKeyIntranet.QueryValue(&dwCurrentLevel, SZCURRLEVEL) == NOERROR) &&
(dwCurrentLevel == URLTEMPLATE_MEDIUM)
)
{
CallRegInstall("Intranet.HackActiveX");
}
CRegKey regKeyInternet(FALSE);
if ((regKeyInternet.Open(NULL, SZINTERNET, KEY_READ) == ERROR_SUCCESS) &&
(regKeyInternet.QueryValue(&dwCurrentLevel, SZCURRLEVEL) == NOERROR) &&
(dwCurrentLevel == URLTEMPLATE_MEDIUM)
)
{
CallRegInstall("Internet.HackActiveX");
}
}
}
else
{
// Restore IE3 user agent string.
CallRegInstall("RestoreUserAgent");
CallRegInstall("RestoreConnectionSettings");
hr = CallRegInstall(bUseHKLM ? "Unreg.HKLM" : "UnReg.HKCU");
if (bUseHKLM)
hr = CallRegInstall("Restore.HKLM");
}
return hr;
}
// CSharedMem member functions.
BOOL CSharedMem::Init(LPCSTR pszNamePrefix, DWORD dwSize)
{
// Note that this function is in ANSI, because we don't have Unicode wrappers
// for the file-mapping functions on Win9x and these need to work on Win9x.
// Create the name for the file mapping object.
// We want this name to be unique per logged in user.
// We will choose a name of the form ZonesSM_"UserName" for systems prior to NT5
// BUGBUG: On Terminal server should we use Global\ in the name. If a user is logged on in multiple
// sessions this seems desirable, but not sure if registry changes get reflected in the other
// session anyway.
DWORD cchPrefix = lstrlenA(pszNamePrefix);
LPSTR pszHandleName = (LPSTR) _alloca(cchPrefix + MAX_PATH);
if (pszHandleName == NULL)
return FALSE;
memcpy(pszHandleName, pszNamePrefix, cchPrefix);
// Move pointer to after the fixed part of the string.
LPSTR psz = pszHandleName + cchPrefix;
// Technically the max username possible is UNLEN which is less than MAX_PATH.
// We use MAX_PATH to not pull in another random header into the build.
DWORD dwMaxNameSize = MAX_PATH;
if (GetUserNameA(psz, &dwMaxNameSize))
{
// If succeeded, rgchHandleName now contains the exact same thing.
}
else
{
TransAssert(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
// if it fails, we will assume no logged on user and just use a global shared memory
// section of the base name
}
m_dwSize = dwSize ;
// First try to see if the shared memory section already exists.
m_hFileMapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, m_dwSize, pszHandleName) ;
if (m_hFileMapping != NULL)
{
m_lpVoidShared = MapViewOfFile(m_hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
}
return (m_hFileMapping != NULL && m_lpVoidShared != NULL);
}
VOID CSharedMem::Release()
{
if (m_lpVoidShared != NULL)
{
UnmapViewOfFile(m_lpVoidShared);
m_lpVoidShared = NULL;
}
if (m_hFileMapping != NULL)
{
CloseHandle(m_hFileMapping);
m_hFileMapping = NULL;
}
m_dwSize = 0;
}
// This function will return NULL if either we couldn not initialize the shared memory
// for some reason or the offset specified is not in range. The offset should be specified
// in number of bytes.
LPVOID CSharedMem::GetPtr(DWORD dwOffset)
{
if (m_lpVoidShared == NULL)
return NULL;
if (dwOffset >= m_dwSize)
return NULL;
return (BYTE *)m_lpVoidShared + dwOffset;
}