Windows2003-3790/inetcore/setup/active/ie4uinit/ie4uinit.cpp
2020-09-30 16:53:55 +02:00

1896 lines
67 KiB
C++

#include "priv.h"
#include "advpub.h"
#include "sdsutils.h"
#include "utils.h"
#include "convert.h"
#include "regstr.h"
const TCHAR c_szAppName[] = TEXT("ie4uinit");
const TCHAR c_szProfRecKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ProfileReconciliation");
const TCHAR c_szHomeDirValue[] = TEXT("ProfileDirectory");
const TCHAR c_szExplorerKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders");
const TCHAR c_szIExploreMain[] = TEXT( "Software\\microsoft\\Internet Explorer\\Main" );
const TCHAR c_szIExplorerSearchUrl[] = TEXT( "Software\\microsoft\\Internet Explorer\\SearchUrl" );
const TCHAR c_szIExplorer[] = TEXT( "Software\\microsoft\\Internet Explorer" );
const TCHAR c_szCentralFile[] = TEXT("CentralFile");
const TCHAR c_szLocalFile[] = TEXT("LocalFile");
const TCHAR c_szName[] = TEXT("Name");
const TCHAR c_szRegKey[] = TEXT("RegKey");
const TCHAR c_szRegValue[] = TEXT("RegValue");
const TCHAR c_szMustBeRelative[] = TEXT("MustBeRelative");
const TCHAR c_szDefault[] = TEXT("Default");
const TCHAR c_szDefaultDir[] = TEXT("DefaultDir");
const TCHAR c_szIExploreLnk[] = TEXT("Internet Explorer.lnk" );
const TCHAR c_szIExploreBackLnk[] = TEXT("Internet Explorer Lnk.bak" );
const TCHAR c_szIExploreBackLnkIni[] = TEXT("IELnkbak.ini" );
const TCHAR c_szIESetupPath[] = TEXT( "software\\microsoft\\IE Setup\\setup" );
const TCHAR c_szIE4Path[] = TEXT( "software\\microsoft\\IE4" );
const TCHAR c_szAdvINFSetup[] = TEXT( "software\\microsoft\\Advanced INF Setup" );
const TCHAR c_szIEModRollback[] = TEXT( "IE CompList" );
const TCHAR c_szRegBackup[] = TEXT( "RegBackup" );
const TCHAR c_szInstallMode[] = TEXT("InstallMode");
const TCHAR c_szStarDotStar[] = "*.*";
const TCHAR c_szSearchUrl[] = TEXT("CleanSearchUrl");
const TCHAR c_szPrevStubINF[] = TEXT("ie4uinit.inf");
const TCHAR c_szStubINFFile[] = TEXT("ieuinit.inf");
const TCHAR c_szActInstalledIEGUID[] = TEXT( "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11cf-8B85-00AA005B4383}");
const TCHAR c_szActInstalledIEGUIDRestore[] = TEXT( "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11cf-8B85-00AA005B4383}.Restore");
const TCHAR c_szMyDocsDLL[] = TEXT("\\mydocs.dll");
const TCHAR c_szIE4Setup[]= TEXT("Software\\Microsoft\\IE Setup\\Setup");
const TCHAR c_szPreIEVer[]= TEXT("PreviousIESysFile");
const TCHAR c_szPreShellVer[]= TEXT("PreviousShellFile");
typedef VOID (*LPFNMYDOCSINIT)(VOID);
// used only at install stub time
BOOL IsPrevIE4();
BOOL IsPrevIE4WebShell();
UINT CheckIEVersion();
void RemoveOldMouseException();
void ProcessMouseException();
// used at uninstall stub time
UINT CheckUninstIEVersion();
//
//====== DllGetVersion =======================================================
//
typedef struct _DllVersionInfo
{
DWORD cbSize;
DWORD dwMajorVersion; // Major version
DWORD dwMinorVersion; // Minor version
DWORD dwBuildNumber; // Build number
DWORD dwPlatformID; // DLLVER_PLATFORM_*
} DLLVERSIONINFO;
// Platform IDs for DLLVERSIONINFO
//#define DLLVER_PLATFORM_WINDOWS 0x00000001 // Windows 95
//#define DLLVER_PLATFORM_NT 0x00000002 // Windows NT
//
// The caller should always GetProcAddress("DllGetVersion"), not
// implicitly link to it.
//
typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
//
//====== DllGetVersion =from shlwapi.h==========================================
//
HINSTANCE g_hinst;
BOOL g_fRunningOnNT = FALSE;
BOOL g_fRunningOnNT5 = FALSE;
BOOL g_fRunningOnWinXP = FALSE;
BOOL g_fRunningOnWin95 = FALSE;
// shlwapi.dll api
typedef void (* PFNSHFLUSHSFCACHEWRAP)();
PFNSHFLUSHSFCACHEWRAP pfnSHFlushSFCacheWrap = NULL;
// old shell32.dll api
typedef void (* PFNSHFLUSHSFCACHE)();
PFNSHFLUSHSFCACHE pfnSHFlushSFCache = NULL;
struct FolderDescriptor;
typedef void (* PFNINITFOLDER)(FolderDescriptor *pFolder, LPTSTR pszBaseName, LPTSTR pszUserDirectory);
void InitFolderFromDefault(FolderDescriptor *pFolder, LPTSTR pszBaseName, LPTSTR pszUserDirectory);
void InitFolderMyDocs(FolderDescriptor *pFolder, LPTSTR pszBaseName, LPTSTR pszUserDirectory);
struct FolderDescriptor {
UINT idsDirName; /* Resource ID for directory name */
LPCTSTR pszRegKey; /* Name of reg key under which to set path */
LPCTSTR pszRegValue; /* Name of reg value to set path in */
LPCTSTR pszStaticName; /* Static name for ProfileReconciliation subkey */
LPCTSTR pszFiles; /* Spec for which files should roam */
PFNINITFOLDER InitFolder; /* Function to init contents */
DWORD dwAttribs; /* Desired directory attributes */
BOOL fIntShellOnly : 1; /* TRUE if should not do this in browser only mode */
BOOL fMustBePerUser : 1; /* TRUE if should always be forced per-user on all platforms */
BOOL fDefaultInRoot : 1; /* TRUE if default location is root of drive, not windows dir */
BOOL fWriteToUSF : 1; /* TRUE if we should write to User Shell Folders to work around Win95 bug */
} aFolders[] = {
{ IDS_CSIDL_DESKTOP_L, c_szExplorerKey, TEXT("Desktop"), TEXT("Desktop"), c_szStarDotStar, InitFolderFromDefault, FILE_ATTRIBUTE_DIRECTORY, TRUE, FALSE, FALSE, FALSE } ,
{ IDS_CSIDL_RECENT_L, c_szExplorerKey, TEXT("Recent"), TEXT("Recent"), c_szStarDotStar, InitFolderFromDefault, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY, TRUE, FALSE, FALSE, FALSE } ,
{ IDS_CSIDL_NETHOOD_L, c_szExplorerKey, TEXT("NetHood"), TEXT("NetHood"), c_szStarDotStar, InitFolderFromDefault, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY, TRUE, FALSE, FALSE, FALSE } ,
{ IDS_CSIDL_PERSONAL_L, c_szExplorerKey, TEXT("Personal"), TEXT("Personal"), c_szStarDotStar, InitFolderMyDocs, FILE_ATTRIBUTE_DIRECTORY, TRUE, FALSE, TRUE, FALSE } ,
{ IDS_CSIDL_FAVORITES_L, c_szExplorerKey, TEXT("Favorites"), TEXT("Favorites"), c_szStarDotStar, InitFolderFromDefault, FILE_ATTRIBUTE_DIRECTORY, FALSE, FALSE, FALSE, TRUE },
{ IDS_CSIDL_APPDATA_L, c_szExplorerKey, TEXT("AppData"), TEXT("AppData"), c_szStarDotStar, InitFolderFromDefault, FILE_ATTRIBUTE_DIRECTORY, FALSE, TRUE, FALSE, FALSE },
{ IDS_CSIDL_CACHE_L, c_szExplorerKey, TEXT("Cache"), TEXT("Cache"), TEXT(""), NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY, FALSE, FALSE, FALSE, FALSE },
{ IDS_CSIDL_COOKIES_L, c_szExplorerKey, TEXT("Cookies"), TEXT("Cookies"), c_szStarDotStar, NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY, FALSE, TRUE, FALSE, FALSE },
{ IDS_CSIDL_HISTORY_L, c_szExplorerKey, TEXT("History"), TEXT("History"), c_szStarDotStar, NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY, FALSE, TRUE, FALSE, FALSE },
};
// Verion number 4.71
#define IE_4_MS_VERSION 0x00040047
// Build number 1712.0 (IE4.0 RTW)
#define IE_4_LS_VERSION 0x06B00000
// IE5 Major version
#define IE_5_MS_VERSION 0x00050000
// IE5.5 Major version
#define IE_55_MS_VERSION 0x00050032
// IE6 (Whistler) Major version
#define IE_6_MS_VERSION 0x00060000
// check IE version return code
#define LESSIE4 0
#define IE4 1
#define IE5 2
#define IE55 3
#define IE6 4 // Whistler
BOOL CheckWebViewShell(UINT *puiShell32)
{
HINSTANCE hInstShell32;
DLLGETVERSIONPROC fpGetDllVersion;
char szShell32[MAX_PATH];
BOOL bRet = FALSE;
GetSystemDirectory(szShell32, sizeof(szShell32));
AddPath(szShell32,"Shell32.dll");
hInstShell32 = LoadLibrary(szShell32);
if ( hInstShell32 )
{
DLLVERSIONINFO dllinfo;
fpGetDllVersion = (DLLGETVERSIONPROC)GetProcAddress(hInstShell32, "DllGetVersion");
bRet = (fpGetDllVersion != NULL);
if (puiShell32 && fpGetDllVersion)
{
dllinfo.cbSize = sizeof(DLLVERSIONINFO);
if ( fpGetDllVersion(&dllinfo) == NOERROR )
*puiShell32 = dllinfo.dwMajorVersion;
else
*puiShell32 = 0; // error case, should never be here
}
FreeLibrary(hInstShell32);
}
return bRet;
}
// this code need to be updated whenever the new major version is released!!
UINT CheckIEVersion()
{
char szIE[MAX_PATH] = { 0 };
DWORD dwMSVer, dwLSVer;
GetSystemDirectory(szIE, sizeof(szIE));
AddPath(szIE, "shdocvw.dll");
GetVersionFromFile(szIE, &dwMSVer, &dwLSVer, TRUE);
if (dwMSVer < IE_4_MS_VERSION)
{
return LESSIE4;
}
if ((dwMSVer >= IE_4_MS_VERSION) && (dwMSVer < IE_5_MS_VERSION))
{
return IE4;
}
if ((dwMSVer >= IE_5_MS_VERSION) && (dwMSVer < IE_55_MS_VERSION))
{
return IE5;
}
if ((dwMSVer >= IE_55_MS_VERSION) && (dwMSVer < IE_6_MS_VERSION))
{
return IE55;
}
if (dwMSVer == IE_6_MS_VERSION)
{
return IE6;
}
#ifdef DEBUG
OutputDebugStringA("CheckIEVersion - unknown shdocvw.dll version# ! Need to add new IE_XX_MS_VERSION id\n");
DebugBreak();
#endif
return IE6;
}
void InitFolderFromDefault(FolderDescriptor *pFolder, LPTSTR pszBaseName, LPTSTR pszUserDirectory)
{
SHFILEOPSTRUCT fos;
TCHAR szFrom[MAX_PATH];
lstrcpy(szFrom, pszBaseName);
/* Before we build the complete source filespec, check to see if the
* directory exists. In the case of lesser-used folders such as
* "Application Data", the default may not have ever been created.
* In that case, we have no contents to copy.
*/
DWORD dwAttr = GetFileAttributes(szFrom);
if (dwAttr == 0xffffffff || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
return;
AddPath(szFrom,"");
lstrcat(szFrom, pFolder->pszFiles);
szFrom[lstrlen(szFrom)+1] = '\0'; /* double null terminate from string */
pszUserDirectory[lstrlen(pszUserDirectory)+1] = '\0'; /* and to string */
fos.hwnd = NULL;
fos.wFunc = FO_COPY;
fos.pFrom = szFrom;
fos.pTo = pszUserDirectory;
fos.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI;
fos.fAnyOperationsAborted = FALSE;
fos.hNameMappings = NULL;
fos.lpszProgressTitle = NULL;
SHFileOperation(&fos);
}
void InitFolderMyDocs(FolderDescriptor *pFolder, LPTSTR pszBaseName, LPTSTR pszUserDirectory)
{
HRESULT hres = E_FAIL;
TCHAR szFrom[MAX_PATH];
TCHAR szPathDest[MAX_PATH];
BOOL fCopyLnk;
lstrcpy(szFrom, pszBaseName);
/* Before we build the complete source filespec, check to see if the
* directory exists. In the case of lesser-used folders such as
* "Application Data", the default may not have ever been created.
* In that case, we have no contents to copy.
*/
DWORD dwAttr = GetFileAttributes(szFrom);
if (dwAttr == 0xffffffff || !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
return;
IShellLink *psl;
if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (void **)&psl)))
return;
if (SHGetNewLinkInfo(szFrom,
pszUserDirectory, szPathDest, &fCopyLnk,
SHGNLI_PREFIXNAME)) {
if (fCopyLnk) {
if (GetFileAttributes(szPathDest) == 0xffffffff &&
CopyFile(szFrom, szPathDest, TRUE)) {
hres = S_OK;
SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, szPathDest, NULL);
SHChangeNotify(SHCNE_FREESPACE, SHCNF_PATH, szPathDest, NULL);
} else {
// DebugMsg(TF_ERROR, TEXT("****copy failed (%d)"),GetLastError());
}
} else {
IPersistFile *ppf;
psl->SetPath(szFrom);
//
// make sure the working directory is set to the same
// directory as the app (or document).
//
// dont do this for non-FS pidls (ie control panel)
//
// what about a UNC directory? we go ahead and set
// it, wont work for a WIn16 app.
//
if (!PathIsDirectory(szFrom)) {
PathRemoveFileSpec(szFrom);
psl->SetWorkingDirectory(szFrom);
}
/* We only did the SHGetNewLinkInfo for the fCopyLnk flag;
* load a resource string to get a more descriptive name
* for the shortcut.
*/
LPTSTR pszPathEnd = PathFindFileName(szPathDest);
LoadString(g_hinst, IDS_MYDOCS_SHORTCUT, pszPathEnd, ARRAYSIZE(szPathDest) - (int)(pszPathEnd - szPathDest));
if (GetFileAttributes(szPathDest) == 0xffffffff) {
hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
if (SUCCEEDED(hres)) {
#ifdef UNICODE
hres = ppf->Save(szPathDest, TRUE);
#else
WCHAR wszPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, szPathDest, -1, wszPath, ARRAYSIZE(wszPath));
hres = ppf->Save(wszPath, TRUE);
#endif
ppf->Release();
}
}
}
}
psl->Release();
}
HRESULT SetupFolder(HKEY hkeyProfRec, LPTSTR pszHomeDir, LPTSTR pszHomeDirEnd,
int cchHomeDir, FolderDescriptor *pFolder, BOOL fDefaultProfile,
HKEY hkeyFolderPolicies)
{
DWORD dwType, cbData;
BOOL fMakeFolderPerUser;
BOOL fGotFromPolicy = FALSE;
/* Figure out whether to make this folder be per-user or not. On NT we
* make everything per-user. Some folders (notably Application Data)
* are also always per-user. The default for everything else is to not
* make it per-user here unless a policy is set to force it. If we do
* not want to make it per-user here, we'll just leave it the way it is;
* of course, the folder could have already been made per-user by some
* other means.
*
* "Make per-user" means set a profile-relative path if we're not operating
* on the default profile, plus adding a ProfileReconciliation key on win95
* (any profile, including default).
*/
if (hkeyFolderPolicies != NULL) {
DWORD dwFlag;
cbData = sizeof(dwFlag);
if (RegQueryValueEx(hkeyFolderPolicies, pFolder->pszStaticName, NULL,
&dwType, (LPBYTE)&dwFlag, &cbData) == ERROR_SUCCESS &&
(dwType == REG_DWORD || (dwType == REG_BINARY && cbData == sizeof(dwFlag)))) {
fMakeFolderPerUser = dwFlag;
fGotFromPolicy = TRUE;
}
}
if (!fGotFromPolicy)
fMakeFolderPerUser = (g_fRunningOnNT || pFolder->fMustBePerUser);
TCHAR szUserHomeDir[MAX_PATH];
*pszHomeDirEnd = '\0'; /* strip off dir name from last time through */
lstrcpy(szUserHomeDir, pszHomeDir);
PathRemoveBackslash(szUserHomeDir);
/* Get the localized name for the directory, as it should appear in
* the file system.
*/
int cchDir = LoadString(g_hinst, pFolder->idsDirName, pszHomeDirEnd, cchHomeDir);
if (!cchDir)
return HRESULT_FROM_WIN32(GetLastError());
cchDir++; /* count null character */
/* Create the reg key where a pointer to the new directory is supposed to
* be stored, and write the path there.
*/
HKEY hkeyFolder;
LONG err = RegCreateKeyEx(HKEY_CURRENT_USER, pFolder->pszRegKey,0, NULL, REG_OPTION_NON_VOLATILE,
KEY_READ|KEY_WRITE, NULL, &hkeyFolder, NULL);
if (err != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(err);
/* Build the default location for this directory (usually just under the
* Windows directory, except for My Documents). We'll use this as the
* location to create if nothing is in the registry, and also to compare
* the registry-set location to see if we should move it or leave it
* alone.
*/
TCHAR szDefaultDir[MAX_PATH];
GetWindowsDirectory(szDefaultDir, ARRAYSIZE(szDefaultDir));
if (pFolder->fDefaultInRoot) {
LPTSTR pszRoot;
if (PathIsUNC(szDefaultDir)) {
pszRoot = ANSIStrChr(szDefaultDir, (WORD)'\\');
if (pszRoot != NULL)
pszRoot = ANSIStrChr(pszRoot+1, (WORD)'\\');
if (pszRoot != NULL)
*(pszRoot+1) = '\0';
}
else {
pszRoot = CharNext(szDefaultDir);
if (*pszRoot == ':')
pszRoot++;
if (*pszRoot == '\\')
pszRoot++;
*pszRoot = '\0';
}
}
else {
AddPath(szDefaultDir, "");
}
lstrcat(szDefaultDir, pszHomeDirEnd);
/* Get the path that was recorded for this folder before we ran. We will
* use it as the default for migrating contents, unless it's not there or
* it's already set to the new directory. In either of those cases we use
* the localized name, relative to the Windows directory.
*/
TCHAR szOldDir[MAX_PATH];
BOOL fDefaultLocation = FALSE;
cbData = sizeof(szOldDir);
szOldDir[0] = '\0';
err = SDSQueryValueExA(hkeyFolder, pFolder->pszRegValue, 0, &dwType,
(LPBYTE)szOldDir, &cbData);
BOOL fGotPathFromRegistry = (err == ERROR_SUCCESS);
if (!fGotPathFromRegistry) {
lstrcpy(szOldDir, szDefaultDir);
if (!pFolder->fDefaultInRoot)
fDefaultLocation = TRUE;
}
else {
/* Previous path is present in the registry. If it's a net path,
* it's probably been set by system policies and we want to leave
* it the way it is.
*/
BOOL fIsNet = FALSE;
if (PathIsUNC(szOldDir))
fIsNet = TRUE;
else {
int nDriveNumber = PathGetDriveNumber(szOldDir);
if (nDriveNumber != -1) {
TCHAR szRootPath[4] = TEXT("X:\\");
szRootPath[0] = nDriveNumber + TEXT('A');
if (::GetDriveType(szRootPath) == DRIVE_REMOTE)
fIsNet = TRUE;
}
}
if (fIsNet) {
RegCloseKey(hkeyFolder);
return S_OK;
}
}
LPSTR pszDirToCreate;
BOOL fInit = TRUE;
if (fDefaultProfile || !fMakeFolderPerUser) {
/* On the default profile, the directory path we want is the one we
* read from the registry (or the default windir-based path we built).
* Also, most folders we want to keep as the user has them already
* configured. In either case, we do not initialize the contents
* because there's no place to initialize them from in the first case,
* and we want the contents undisturbed in the second case.
*/
pszDirToCreate = szOldDir;
fInit = FALSE;
}
else {
/* We want to give this user a profile-relative path for this folder.
* However, if they already have an explicit non-default path set for
* this folder, we don't bother initializing it since they already have
* it set up someplace where they want it.
*/
if (fGotPathFromRegistry &&
::GetFileAttributes(szOldDir) != 0xffffffff &&
lstrcmpi(szOldDir, szDefaultDir)) {
pszDirToCreate = szOldDir;
fInit = FALSE;
}
else {
pszDirToCreate = pszHomeDir;
}
}
/* Only write the path out to the registry if we didn't originally get it
* from the registry.
*/
if (!fGotPathFromRegistry) {
/* If we're writing to the User Shell Folders key, only write non-
* default paths there.
*/
/* There are some applications (German Corel Office 7) which
* depend on the entry being in User Shell Folders for some shell
* folders. This dependency is due to the fact that the entry use
* to be created always by down level browsers (IE30).
*
* We do not do this generically because no value under
* USF is supposed to mean "use the one in the Windows
* directory", whereas an absolute path means "use that
* path"; if there's a path under USF, it will be used
* literally, which is a problem if the folder is set up
* to use the shared folder location but roams to a machine
* with Windows installed in a different directory.
*/
if ((pFolder->pszRegKey != c_szExplorerKey) ||
pszDirToCreate != szOldDir ||
!fDefaultLocation ||
pFolder->fWriteToUSF) {
if (g_fRunningOnNT) {
TCHAR szRegPath[MAX_PATH];
lstrcpy(szRegPath, TEXT("%USERPROFILE%\\"));
lstrcat(szRegPath, pszHomeDirEnd);
RegSetValueEx( hkeyFolder, pFolder->pszRegValue, 0, REG_EXPAND_SZ,
(LPBYTE)szRegPath, (lstrlen(szRegPath)+1) * sizeof(TCHAR));
}
else {
if (!pFolder->fWriteToUSF || g_fRunningOnWin95)
{
RegSetValueEx(hkeyFolder, pFolder->pszRegValue, 0, REG_SZ,
(LPBYTE)pszDirToCreate, (lstrlen(pszDirToCreate)+1) * sizeof(TCHAR));
}
else
{
// 98/12/30 #238093 (IE#50598 / Office#188177) vtan: There exists a
// case where HKCU\..\Explorer\User Shell Folders\Favorites does NOT
// exist on Win98 (unknown cause). This case simulates a Windows95
// bug which the fWriteToUSF flag is designed to get around. In the
// German Win9x this replaces the Favorites folder in User Shell
// Folders key with the english name and this is propogated below to
// Shell Folders which destroys the localization.
// In this case we want to write the value of the key in Shell Folders
// (if that points to a valid directory) to the User Shell Folders key
// and just let the code below write the same value back to the Shell
// Folders key. A little bit of wasted effort.
HKEY hkeySF;
if (RegCreateKeyEx(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hkeySF,
NULL) == ERROR_SUCCESS)
{
DWORD dwRegDataType, dwRegDataSize;
TCHAR szRegValue[MAX_PATH];
dwRegDataSize = sizeof(szRegValue);
if (RegQueryValueEx(hkeySF,
pFolder->pszRegValue,
0,
&dwRegDataType,
reinterpret_cast<LPBYTE>(szRegValue),
&dwRegDataSize) == ERROR_SUCCESS)
{
if (GetFileAttributes(szRegValue) != 0xFFFFFFFF)
{
lstrcpy(pszDirToCreate, szRegValue);
RegSetValueEx(hkeyFolder,
pFolder->pszRegValue,
0,
REG_SZ,
(LPBYTE)pszDirToCreate,
(lstrlen(pszDirToCreate)+1) * sizeof(TCHAR));
}
}
RegCloseKey(hkeySF);
}
}
}
}
/* The User Shell Folders key has a near-twin: Shell Folders, which
* (a) should always contain the path to a folder, even if the folder
* is in its default location, and (b) should contain the expanded
* path on NT.
*/
if (pFolder->pszRegKey == c_szExplorerKey) {
HKEY hkeySF;
if (RegCreateKeyEx(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_READ|KEY_WRITE, NULL, &hkeySF, NULL) == ERROR_SUCCESS) {
RegSetValueEx(hkeySF, pFolder->pszRegValue, 0, REG_SZ,
(LPBYTE)pszDirToCreate, (lstrlen(pszDirToCreate)+1) * sizeof(TCHAR));
RegCloseKey(hkeySF);
}
}
/* Initialize default contents of the folder.
*/
if (fInit && pFolder->InitFolder != NULL)
pFolder->InitFolder(pFolder, szOldDir, pszHomeDir);
}
/* Always try to create the directory we want, if it doesn't already
* exist.
*/
if (::GetFileAttributes(pszDirToCreate) == 0xffffffff) {
CreateDirectory(pszDirToCreate, NULL);
if (pFolder->dwAttribs != FILE_ATTRIBUTE_DIRECTORY)
SetFileAttributes(pszDirToCreate, pFolder->dwAttribs);
}
RegCloseKey(hkeyFolder);
/*
* If it's the My Documents folder, there is some per-user initialization
* to do regardless of whether we set the values or they already existed.
*/
if (pFolder->InitFolder == InitFolderMyDocs)
{
TCHAR szMyDocs[ MAX_PATH ];
if (GetSystemDirectory( szMyDocs, ARRAYSIZE(szMyDocs) ))
{
HINSTANCE hMyDocs;
lstrcat( szMyDocs, c_szMyDocsDLL );
hMyDocs = LoadLibrary( szMyDocs );
if (hMyDocs)
{
LPFNMYDOCSINIT pMyDocsInit =
(LPFNMYDOCSINIT)GetProcAddress( hMyDocs, "PerUserInit" );
if (pMyDocsInit)
{
pMyDocsInit();
}
FreeLibrary( hMyDocs );
}
}
}
/* Now, for Windows 95 systems, create a ProfileReconciliation subkey
* which will make this folder roam. Only if we want to make this folder
* per-user, of course.
*/
if (fMakeFolderPerUser && !g_fRunningOnNT) {
TCHAR szDefaultPath[MAX_PATH];
lstrcpy(szDefaultPath, TEXT("*windir\\"));
lstrcat(szDefaultPath, pszHomeDirEnd);
HKEY hSubKey;
LONG err = RegCreateKeyEx(hkeyProfRec, pFolder->pszStaticName, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hSubKey, NULL);
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szCentralFile, 0, REG_SZ, (LPBYTE)pszHomeDirEnd,
cchDir);
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szLocalFile, 0, REG_SZ, (LPBYTE)pszHomeDirEnd,
cchDir);
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szName, 0, REG_SZ, (LPBYTE)pFolder->pszFiles,
lstrlen(pFolder->pszFiles) + 1);
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szDefaultDir, 0, REG_SZ, (LPBYTE)szDefaultPath,
lstrlen(szDefaultPath) + 1);
DWORD dwOne = 1;
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szMustBeRelative, 0, REG_DWORD, (LPBYTE)&dwOne,
sizeof(dwOne));
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szDefault, 0, REG_DWORD, (LPBYTE)&dwOne,
sizeof(dwOne));
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szRegKey, 0, REG_SZ, (LPBYTE)pFolder->pszRegKey,
lstrlen(pFolder->pszRegKey) + 1);
if (err == ERROR_SUCCESS)
err = RegSetValueEx(hSubKey, c_szRegValue, 0, REG_SZ, (LPBYTE)pFolder->pszRegValue,
lstrlen(pFolder->pszRegValue) + 1);
RegCloseKey(hSubKey);
if (err != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(err);
}
return S_OK;
}
BOOL GetModulePath( LPTSTR szPath, UINT cbPath )
{
PSTR pszTmp;
if (GetModuleFileName(g_hinst, szPath, cbPath ) == 0)
{
szPath[0] = '\0';
return FALSE;
}
else
{
pszTmp = ANSIStrRChr( szPath, '\\' );
if ( pszTmp )
*pszTmp = '\0';
}
return TRUE ;
}
int DoMsgBoxParam(HWND hwnd, UINT TextString, UINT TitleString, UINT style, PTSTR param )
{
TCHAR szTitle[MAX_PATH];
TCHAR szMsg[2*MAX_PATH];
if (!LoadString(g_hinst, TextString, szMsg, sizeof(szMsg)))
szMsg[0] = '\0';
if ( param )
{
TCHAR szBuf[2*MAX_PATH];
wsprintf( szBuf, szMsg, param );
lstrcpy( szMsg, szBuf );
}
if (!LoadString(g_hinst, TitleString, szTitle, sizeof(szTitle)))
szTitle[0] = '\0';
return MessageBox(hwnd, szMsg, szTitle, style);
}
void InstINFFile( LPCTSTR pcszInf, LPTSTR pszSec, BOOL bInstall, BOOL bSaveRollback, DWORD dwFlag )
{
TCHAR szPath[MAX_PATH];
CABINFO cabInfo;
if ( GetModulePath( szPath, sizeof(szPath) ) )
{
if ( bSaveRollback )
{
ZeroMemory( &cabInfo, sizeof(CABINFO) );
// install IE4Uinit.INF
lstrcpy( cabInfo.szSrcPath, szPath );
AddPath( szPath, pcszInf );
if ( FileExists( szPath ) )
{
cabInfo.pszInf = szPath;
cabInfo.pszSection = pszSec;
cabInfo.dwFlags = (bInstall ? ALINF_BKINSTALL : ALINF_ROLLBACK);
cabInfo.dwFlags |= ALINF_QUIET;
ExecuteCab( NULL, &cabInfo, NULL );
}
else if (!(dwFlag & RSC_FLAG_QUIET))
{
DoMsgBoxParam( NULL, IDS_ERR_NOFOUNDINF, IDS_APPNAME, MB_OK|MB_ICONINFORMATION, szPath );
}
}
else
{
char szInfFile[MAX_PATH];
lstrcpy( szInfFile, szPath);
AddPath( szInfFile, pcszInf);
RunSetupCommand(NULL, szInfFile, pszSec, szPath,
NULL, NULL, dwFlag, NULL);
}
}
}
void DoRollback()
{
HKEY hLMkey;
HKEY hSubkey1, hSubkey2;
TCHAR szBuf[MAX_PATH];
DWORD dwSize;
DWORD dwIndex = 0;
int ilen;
// rollback all the components listed in c_szIEModRollback key
//
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szAdvINFSetup, 0, KEY_READ , &hLMkey) == ERROR_SUCCESS )
{
if ( RegOpenKeyEx(hLMkey, c_szIEModRollback, 0, KEY_READ , &hSubkey1) == ERROR_SUCCESS )
{
lstrcpy( szBuf, c_szAdvINFSetup );
AddPath( szBuf, "" );
ilen = lstrlen(szBuf);
dwSize = ARRAYSIZE(szBuf) - ilen;
while ( RegEnumValue( hSubkey1, dwIndex, &szBuf[ilen], &dwSize,
NULL, NULL, NULL, NULL ) == ERROR_SUCCESS )
{
if ( RegOpenKeyEx(hLMkey, &szBuf[ilen], 0, KEY_READ | KEY_WRITE, &hSubkey2) == ERROR_SUCCESS )
{
RegSetValueEx( hSubkey2, TEXT("BackupRegistry"), 0, REG_SZ, (LPBYTE)TEXT("n"), (lstrlen(TEXT("n"))+1)*sizeof(TCHAR) );
RegCloseKey( hSubkey2 );
}
AddPath( szBuf, c_szRegBackup );
///////////////////////////////////////////////////////////////////////////
// ShabbirS - 8/17/98
// Bug# 26774 : Found that this restoring of backup reg data undoes our
// dll registering done during the RunOnceEx phase.
///////////////////////////////////////////////////////////////////////////
// restore HKLM if there
//if ( RegOpenKeyEx(hLMkey, &szBuf[ilen], 0, KEY_READ | KEY_WRITE, &hSubkey2) == ERROR_SUCCESS )
//{
// RegRestoreAll( NULL, NULL, hSubkey2 );
// RegCloseKey( hSubkey2 );
//}
// restore HKCU if there
if ( RegOpenKeyEx( HKEY_CURRENT_USER, szBuf, 0, KEY_READ | KEY_WRITE, &hSubkey2) == ERROR_SUCCESS )
{
RegRestoreAll( NULL, NULL, hSubkey2 );
RegCloseKey( hSubkey2 );
}
dwIndex++;
dwSize = ARRAYSIZE( szBuf ) - ilen;
}
RegCloseKey( hSubkey1 );
}
RegCloseKey( hLMkey );
}
}
#define NT_MEMORYLIMIT 0x03f00000
#define WIN9X_MEMORYLIMIT 0x01f00000
void DoINFWork( BOOL bInstall, LPCTSTR pcszInfFile, LPTSTR pszInfSec, DWORD dwFlag )
{
HKEY hkey;
TCHAR szBuf[MAX_PATH] = { 0 };
DWORD dwSize;
DWORD dwRedist = 0;
BOOL bRedistMode = FALSE;
// check the InstallMode and determin if make the desktop icon and StartMenu item.
if ( bInstall && (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szIESetupPath, 0, KEY_READ, &hkey) == ERROR_SUCCESS) )
{
dwSize = sizeof(dwRedist);
// If we can read the Installmode and bit 0 is set, assume redist (Remove short cuts)
if ( (RegQueryValueEx( hkey, c_szInstallMode, 0, NULL, (LPBYTE)&dwRedist, &dwSize) == ERROR_SUCCESS) &&
(dwRedist & 1) )
{
bRedistMode = TRUE;
}
RegCloseKey( hkey );
}
// if not installed over SP4 level crypto, then backup/restore the crypto keys.
// NOTE that bInstall is passed in the 4th argument, so during install bSaveRollback is TRUE. During
// uninstall, the reg backup data should be restored when the DefaultInstall section is processed, so
// set bSaveRollback to FALSE
if (!FSP4LevelCryptoInstalled())
InstINFFile( pcszInfFile, bInstall ? "BackupCryptoKeys" : "DelCryptoKeys", bInstall, bInstall, dwFlag );
else
{
// BUGBUG: if bInstall is FALSE, need to delete the reg backup data for the crypto keys
}
// install the WinXP specific section
if(g_fRunningOnWinXP && !pszInfSec ) {
InstINFFile( pcszInfFile, TEXT("DefaultInstall.WinXP"), bInstall, TRUE, dwFlag);
}
else {
// install the current shortcut and HKCU settings by stub INF
InstINFFile( pcszInfFile, pszInfSec, bInstall, TRUE, dwFlag );
}
// Even though IE5.0 does not install channelband, if the channelband exists on IE4.0, it should works in
// IE5.0. Therefore if there is channelbar link exists(PrevIE Version is IE4.0 browser only), IE5 will update
// the channelbar link to the current browser. Otherwise, do nothing.
if (bInstall && IsPrevIE4() && !IsPrevIE4WebShell())
{
InstINFFile( pcszInfFile, TEXT("Shell.UserStub.Uninstall"), bInstall, FALSE, RSC_FLAG_INF | RSC_FLAG_QUIET );
}
if ( bRedistMode )
{
LPTSTR lpszSection;
if ( g_fRunningOnNT )
lpszSection = TEXT("RedistIE.NT");
else
lpszSection = TEXT("RedistIE.Win");
InstINFFile( pcszInfFile, lpszSection, bInstall, TRUE, dwFlag );
}
// On uninstall, check what the current browser version and determin if we need to cleanup the
// Channel and quick launch folders
if ( !bInstall && ( CheckIEVersion() == LESSIE4))
{
LPTSTR lpszSection;
if ( g_fRunningOnNT )
lpszSection = TEXT("CleanFolders.NT");
else
lpszSection = TEXT("CleanFolders.Win");
InstINFFile( pcszInfFile, lpszSection, bInstall, FALSE, RSC_FLAG_INF | RSC_FLAG_QUIET | RSC_FLAG_NGCONV );
}
// Enable sounds if user has a big enough machine
// NT - 64MB, Win9x - 32MB
if(bInstall)
{
LPTSTR lpszSection = NULL;
MEMORYSTATUS ms;
ms.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);
if ( g_fRunningOnNT)
{
if(ms.dwTotalPhys >= NT_MEMORYLIMIT)
{
lpszSection = TEXT("SoundInstall.NT");
}
}
else
{
if(ms.dwTotalPhys >= WIN9X_MEMORYLIMIT)
{
lpszSection = TEXT("SoundInstall");
}
}
if(lpszSection)
InstINFFile( pcszInfFile, lpszSection, bInstall, TRUE, RSC_FLAG_INF | RSC_FLAG_QUIET | RSC_FLAG_NGCONV );
}
if (bInstall)
{
// in fact this is only true for IE5 install inf, but IE4 inf is called ok too since there is no
// such section in IE4 stub inf.
if (CheckWebViewShell(NULL)) {
LPSTR lpszSection = NULL;
if(g_fRunningOnWinXP)
lpszSection = TEXT("IE5onIE4Shell.WinXP");
else
lpszSection = TEXT("IE5onIE4Shell");
InstINFFile( pcszInfFile, lpszSection, bInstall, FALSE, RSC_FLAG_INF | RSC_FLAG_QUIET );
}
}
// check if the user's home page is bogus one
if ( bInstall && (RegOpenKeyEx( HKEY_CURRENT_USER, c_szIExploreMain, 0, KEY_READ, &hkey ) == ERROR_SUCCESS) )
{
DWORD dwSize;
dwSize = sizeof(szBuf);
if ( RegQueryValueEx( hkey, TEXT("Start Page"), NULL, NULL, (LPBYTE)szBuf, &dwSize ) == ERROR_SUCCESS )
{
if ( (g_fRunningOnNT && ANSIStrStrI(szBuf, "Plus!") && ANSIStrStrI(szBuf, "File:")) ||
(!lstrcmpi(szBuf, TEXT("http://home.microsoft.com"))) ||
(!lstrcmpi(szBuf, TEXT("http://home.microsoft.com/"))) )
{
InstINFFile( pcszInfFile, TEXT("OverrideHomePage.NT"), bInstall, TRUE, dwFlag );
}
}
RegCloseKey( hkey );
}
if ( !bRedistMode )
{
typedef void (*PFSetFirstHomepage)();
PFSetFirstHomepage pfSetFirstHomepage;
HMODULE hMod = LoadLibrary("iesetup.dll");
if (hMod)
{
pfSetFirstHomepage = (PFSetFirstHomepage)GetProcAddress(hMod, "SetFirstHomepage");
if (pfSetFirstHomepage)
{
pfSetFirstHomepage();
}
FreeLibrary(hMod);
}
}
// DoRollback if needed
if ( !bInstall )
{
DoRollback();
}
}
/*----------------------------------------------------------
Purpose: Detect if it is run on Russian LangID
*/
//DWORD dwLangList[] = { 0x0419, 0xFFFF };
#define RUSSIANLANG 0x0419
BOOL IsBrokenLang()
{
char szTmp[MAX_PATH] = { 0 };
DWORD dwLangKernel32;
DWORD dwTmp;
BOOL bBadLang = FALSE;
GetSystemDirectory(szTmp, sizeof(szTmp));
AddPath(szTmp,"kernel32.dll" );
GetVersionFromFile(szTmp, &dwLangKernel32, &dwTmp, FALSE);
if ( dwLangKernel32 == RUSSIANLANG )
{
bBadLang = TRUE;
}
return bBadLang;
}
BOOL IsPrevStubRun()
{
HKEY hLMKey, hCUKey;
BOOL bRet = FALSE;
char szStubVer[50], szPreIEVer[50];
DWORD dwSize;
WORD wStubVer[4]={0}, wPreIEVer[4]={0};
// check if the pre-version iestub is run
if ( RegOpenKeyEx( HKEY_CURRENT_USER, c_szActInstalledIEGUID, 0, KEY_READ, &hCUKey ) == ERROR_SUCCESS )
{
dwSize = sizeof(szStubVer);
if ( RegQueryValueEx( hCUKey, TEXT("Version"), NULL, NULL, (LPBYTE)szStubVer, &dwSize ) == ERROR_SUCCESS )
{
ConvertVersionString( szStubVer, wStubVer, ',' );
}
RegCloseKey(hCUKey);
}
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szIESetupPath, 0, KEY_READ, &hLMKey ) == ERROR_SUCCESS )
{
dwSize = sizeof(szPreIEVer);
if ( RegQueryValueEx( hLMKey, TEXT("PreviousIESysFile"), NULL, NULL, (LPBYTE)szPreIEVer, &dwSize ) == ERROR_SUCCESS )
{
ConvertVersionString( szPreIEVer, wPreIEVer, '.' );
if ( (MAKELONG(wPreIEVer[1],wPreIEVer[0])<IE_4_MS_VERSION) ||
(wStubVer[0] > wPreIEVer[0]) ||
((wStubVer[0] == wPreIEVer[0]) && (wStubVer[1] >= wPreIEVer[1])) )
{
bRet = TRUE;
}
}
else //should never be here. OW
bRet = TRUE; //not forcing rerun the prev-stub
RegCloseKey(hLMKey);
}
else //should never be here. OW
bRet = TRUE; //not forcing rerun the prev-stub
return bRet;
}
/*----------------------------------------------------------
Purpose: Stripping off the trailing spaces for the registry data in the list
*/
typedef struct _REGDATACHECK
{
HKEY hRootKey;
LPSTR lpszSubKey;
LPSTR lpszValueName;
} REGDATACHECK;
REGDATACHECK chkList[] = {
{ HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "AppData" },
{ HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "Start Menu" },
{ HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "AppData" },
{ HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Start Menu" },
{ HKEY_USERS, ".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "AppData" },
{ HKEY_USERS, ".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", "Start Menu" },
{ HKEY_USERS, ".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "AppData" },
{ HKEY_USERS, ".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Start Menu" },
};
void FixRegData()
{
int iList, i;
LPSTR pszTmp;
char szBuf[MAX_PATH];
DWORD dwSize, dwType;
HKEY hKey;
iList = ARRAYSIZE( chkList );
for ( i = 0; i < iList; i++ )
{
if ( RegOpenKeyEx(chkList[i].hRootKey, chkList[i].lpszSubKey, 0, KEY_READ|KEY_WRITE,
&hKey) == ERROR_SUCCESS )
{
dwSize = sizeof(szBuf);
if ( RegQueryValueEx(hKey, chkList[i].lpszValueName, 0, &dwType, (LPBYTE)szBuf,
&dwSize) == ERROR_SUCCESS )
{
// strip off the trailing blanks
pszTmp = szBuf;
pszTmp += lstrlen(szBuf) - 1;
while ( (pszTmp >= szBuf) && (*pszTmp == ' ') )
{
*pszTmp = '\0';
pszTmp--;
}
RegSetValueEx( hKey, chkList[i].lpszValueName, 0, dwType, (LPBYTE)szBuf, lstrlen(szBuf)+1 );
}
RegCloseKey( hKey );
}
}
}
void FixSearchUrl()
{
HKEY hkey, hIEKey;
TCHAR szBuf[MAX_PATH];
DWORD dwSize;
// if HKCU, software\microsoft\internet explorer\SearchUrl, "default" value is ""
// Delete the "" default value.
//
if ( RegOpenKeyEx(HKEY_CURRENT_USER, c_szIExplorerSearchUrl, 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS )
{
dwSize = 0;
if ( RegQueryValueEx( hkey, TEXT(""), 0, NULL, (LPBYTE)szBuf, &dwSize ) != ERROR_SUCCESS )
{
dwSize = sizeof(szBuf);
if ( (RegQueryValueEx( hkey, TEXT(""), 0, NULL, (LPBYTE)szBuf, &dwSize ) == ERROR_SUCCESS) &&
(szBuf[0] == TEXT('\0')) )
{
// found "" empty string as default value, check if we have cleaned up before.
// If not, clean it now, otherwise do nothing.
if ( RegCreateKeyEx( HKEY_CURRENT_USER, c_szIE4Path,0, NULL, REG_OPTION_NON_VOLATILE,
KEY_READ|KEY_WRITE, NULL, &hIEKey, NULL) == ERROR_SUCCESS )
{
dwSize = sizeof(szBuf);
if ( (RegQueryValueEx( hIEKey, c_szSearchUrl, 0, NULL, (LPBYTE)szBuf, &dwSize ) != ERROR_SUCCESS) ||
(*CharUpper(szBuf) != TEXT('Y')) )
{
RegDeleteValue( hkey, TEXT("") );
lstrcpy( szBuf, TEXT("Y") );
RegSetValueEx( hIEKey, c_szSearchUrl, 0, REG_SZ, (LPBYTE)szBuf, (lstrlen(szBuf)+1)*sizeof(TCHAR) );
}
RegCloseKey( hIEKey );
}
}
}
RegCloseKey( hkey );
}
}
/*----------------------------------------------------------
* Helper function to check if the Channels folder exists in
* the current user profile.
*----------------------------------------------------------
*/
// "Channels" resid from CdfView. (Need to use this, b'cos could be localized
#define CHANNEL_FOLDER_RESID 0x1200
// SHGetSpecialFolderPath function from Shell32.dll
typedef BOOL (WINAPI *SH_GSFP_PROC) (HWND, LPTSTR, int, BOOL);
BOOL DoesChannelFolderExist()
{
char szChannelName[MAX_PATH];
char szSysPath[MAX_PATH] = { 0 };
char szChannelPath[MAX_PATH];
BOOL bRet = FALSE;
BOOL bGetRC = TRUE;
HMODULE hShell32 = NULL;
SH_GSFP_PROC fpSH_GSFP = NULL;
DWORD dwAttr = 0;
GetSystemDirectory( szSysPath,sizeof(szSysPath));
lstrcpy(szChannelPath, szSysPath);
AddPath( szChannelPath, "shell32.dll" );
hShell32 = LoadLibrary(szChannelPath);
// This stubs runs on IE4 or IE5 systems. Hence shell32 is garunteed
// to have the SHGetSpecialFolderPath API.
if (hShell32)
{
fpSH_GSFP = (SH_GSFP_PROC)GetProcAddress(hShell32,"SHGetSpecialFolderPathA");
*szChannelPath = '\0';
if (fpSH_GSFP && fpSH_GSFP(NULL, szChannelPath, CSIDL_FAVORITES, FALSE))
{
HKEY hKey;
DWORD cbSize = sizeof(szChannelName);
// Get the potentially localized name of the Channel folder from the
// registry if it is there. Otherwise use "Channels"
// Then tack this on the favorites path.
//
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey,"ChannelFolderName", NULL, NULL, (LPBYTE)szChannelName,&cbSize) == ERROR_SUCCESS)
{
bGetRC = FALSE;
}
RegCloseKey(hKey);
}
if (bGetRC)
{
HMODULE hLib;
// Get the default name for Channels folder from the
// CdfView.dll
AddPath(szSysPath,"cdfview.dll");
hLib = LoadLibraryEx(szSysPath,NULL,LOAD_LIBRARY_AS_DATAFILE);
if (hLib)
{
if (LoadString(hLib, CHANNEL_FOLDER_RESID,szChannelName,sizeof(szChannelName)) == 0)
{
// Fail to read the resource, default to English
lstrcpy(szChannelName,"Channels");
}
FreeLibrary(hLib);
}
}
AddPath(szChannelPath, szChannelName);
// Check if the folder exists...
dwAttr = GetFileAttributes(szChannelPath);
if ((dwAttr != 0xffffffff) && (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
bRet = TRUE;
}
FreeLibrary(hShell32);
}
return bRet;
}
HRESULT IEAccessHideExplorerIcon()
{
const TCHAR *szKeyComponent = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{871C5380-42A0-1069-A2EA-08002B30309D}");
const TCHAR *szShellFolder = TEXT("ShellFolder");
const TCHAR *szAttribute = TEXT("Attributes");
DWORD dwValue, dwSize, dwDisposition;
HKEY hKeyComponent, hKeyShellFolder;
HRESULT hResult = ERROR_SUCCESS;
hResult = RegCreateKeyEx(HKEY_CURRENT_USER, szKeyComponent, NULL, NULL, REG_OPTION_NON_VOLATILE,
KEY_CREATE_SUB_KEY, NULL, &hKeyComponent, &dwDisposition);
if (hResult != ERROR_SUCCESS)
return hResult;
hResult = RegCreateKeyEx(hKeyComponent, szShellFolder, NULL, NULL, REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hKeyShellFolder, &dwDisposition);
RegCloseKey(hKeyComponent);
if (hResult == ERROR_SUCCESS)
{
dwSize = sizeof(dwValue);
hResult = RegQueryValueEx( hKeyShellFolder, szAttribute, NULL, NULL, (LPBYTE)&dwValue, &dwSize);
if (hResult != ERROR_SUCCESS)
dwValue = 0;
dwValue |= SFGAO_NONENUMERATED;
hResult = RegSetValueEx(hKeyShellFolder, szAttribute, NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
RegCloseKey(hKeyShellFolder);
}
return hResult;
}
#define REGVAL_SHOW_CHANNELBAND "Show_ChannelBand"
#define REGVAL_SOURCE "Source"
#define REGVAL_FLAGS "Flags"
#define REG_IE_MAIN "Software\\Microsoft\\Internet Explorer\\Main"
#define REG_DESKTOP_COMP "Software\\Microsoft\\Internet Explorer\\Desktop\\Components"
#define GUID_CHNLBAND "131A6951-7F78-11D0-A979-00C04FD705A2"
#define FLAG_ENABLE_CHNLBAND 0x00002000
/*----------------------------------------------------------
Purpose: Worker function to do the work
*/
void DoWork( BOOL bInstall )
{
TCHAR szHomeDir[MAX_PATH] = { 0 };
HKEY hkeyProfRec = NULL;
HKEY hkeyFolderPolicies;
BOOL fIntShellMode = FALSE;
HMODULE hmodShell = NULL;
// HINSTANCE hlib;
TCHAR szPath[MAX_PATH] = { 0 };
DWORD dwMV, dwLV;
BOOL fUseShell32 = FALSE;
if ( bInstall )
{
if (g_fRunningOnNT) {
ExpandEnvironmentStrings("%USERPROFILE%", szHomeDir, ARRAYSIZE(szHomeDir));
}
else {
szHomeDir[0] = '\0';
LONG err = RegCreateKeyEx(HKEY_CURRENT_USER, c_szProfRecKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
NULL, &hkeyProfRec, NULL);
if (err == ERROR_SUCCESS) {
DWORD dwType;
DWORD cbData = sizeof(szHomeDir);
RegQueryValueEx(hkeyProfRec, c_szHomeDirValue, 0, &dwType,
(LPBYTE)szHomeDir, &cbData);
}
}
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Per User Folders",
0, KEY_QUERY_VALUE, &hkeyFolderPolicies) != ERROR_SUCCESS)
hkeyFolderPolicies = NULL;
/* Dynamically link to the SHFlushSFCache API in SHELL32.DLL. Its ordinal
* is 526. This API tells the shell to reinitialize the shell folder cache
* in all processes.
*/
// due to the buggy in the old shell32 of this api function. We are advised to use the new wrap
// which is in shlwapi.dll. Its ordinal is 419.
fIntShellMode = FALSE;
GetSystemDirectory( szPath,sizeof( szPath ) );
AddPath( szPath, "shlwapi.dll" );
GetVersionFromFile( szPath, &dwMV, &dwLV, TRUE );
// if major version >= 5.0
//
if ( (dwMV >= 0x00050000))
{
hmodShell = ::LoadLibrary(szPath);
}
else
{
hmodShell = ::LoadLibrary("shell32.dll");
fUseShell32 = TRUE;
}
if (hmodShell != NULL)
{
if ( !fUseShell32 )
{
::pfnSHFlushSFCacheWrap = (PFNSHFLUSHSFCACHEWRAP)::GetProcAddress(hmodShell, (LPCTSTR)419);
if (::pfnSHFlushSFCacheWrap != NULL)
{
fIntShellMode = TRUE;
}
}
else
{
::pfnSHFlushSFCache = (PFNSHFLUSHSFCACHE)::GetProcAddress(hmodShell, (LPCTSTR)526);
if (::pfnSHFlushSFCache != NULL)
{
fIntShellMode = TRUE;
}
}
}
BOOL fDefaultProfile;
LPTSTR pchHomeDirEnd = szHomeDir;
int cchHomeDir = 0;
if (szHomeDir[0] != '\0') {
fDefaultProfile = FALSE;
}
else {
GetWindowsDirectory(szHomeDir, ARRAYSIZE(szHomeDir));
fDefaultProfile = TRUE;
}
AddPath(szHomeDir,"");
pchHomeDirEnd = szHomeDir + lstrlen(szHomeDir);
cchHomeDir = ARRAYSIZE(szHomeDir) - (int)(pchHomeDirEnd - szHomeDir);
for (UINT i=0; i<ARRAYSIZE(aFolders); i++) {
if (aFolders[i].fIntShellOnly && !fIntShellMode)
continue;
if (FAILED(SetupFolder(hkeyProfRec, szHomeDir, pchHomeDirEnd,
cchHomeDir, &aFolders[i], fDefaultProfile,
hkeyFolderPolicies)))
break;
}
if (hkeyProfRec != NULL)
RegCloseKey(hkeyProfRec);
if (hkeyFolderPolicies != NULL)
RegCloseKey(hkeyFolderPolicies);
// import NS stuff if there
ImportNetscapeProxySettings( IMPTPROXY_CALLAFTIE4 );
ImportBookmarks(g_hinst);
if ( !fUseShell32 )
{
if (::pfnSHFlushSFCacheWrap != NULL)
{
(*::pfnSHFlushSFCacheWrap)();
}
}
else
{
if (::pfnSHFlushSFCache != NULL)
{
(*::pfnSHFlushSFCache)();
}
}
if (hmodShell != NULL) {
::FreeLibrary(hmodShell);
}
}
/* BUGBUG - add code to populate the default IE4 favorites, channels, and
* shortcuts here
*/
// #75346: Upgrade from Win9x to NT5, new users have no Channels folder
// and the ChannelBand pops-up with Fav. entries in it. This hack will
// ensure that the Ch.Band does not pop-up when the new user logs in for
// the first time.
if (bInstall && g_fRunningOnNT5)
{
if (!DoesChannelFolderExist())
{
HKEY hKey;
char szNo[] = "No";
// Turn off the Show_ChannelBand for this user.
if (RegOpenKeyEx(HKEY_CURRENT_USER,REG_IE_MAIN, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS)
{
RegSetValueEx(hKey, REGVAL_SHOW_CHANNELBAND,0, REG_SZ,(LPBYTE)szNo,sizeof(szNo));
RegCloseKey(hKey);
}
// Also turn off the Desktop\Components(ChannelBand)
// Open HKCU\S\M\InternetExplorer\Desktop\Coomponents and enum for
// the ChannelBand GUID. Disable the show flag.
if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKTOP_COMP, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS)
{
HKEY hSubKey = NULL;
char szSubKey[MAX_PATH];
char szSourceID[130];
DWORD dwSize = sizeof(szSubKey);
for (int i = 0;
RegEnumKeyEx(hKey,i, szSubKey, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
i++, dwSize = sizeof(szSubKey))
{
// Open this subkey and checks its SourceID.
if (RegOpenKeyEx(hKey,szSubKey,0, KEY_READ|KEY_WRITE, &hSubKey) == ERROR_SUCCESS)
{
dwSize = sizeof(szSourceID);
if ((RegQueryValueEx(hSubKey, REGVAL_SOURCE, NULL, NULL, (LPBYTE)szSourceID,&dwSize) == ERROR_SUCCESS)
&& (lstrcmpi(szSourceID, GUID_CHNLBAND) == 0))
{
// Read the current Flags setting.
DWORD dwFlags = 0;
dwSize = sizeof(dwFlags);
RegQueryValueEx(hSubKey,REGVAL_FLAGS, NULL, NULL, (LPBYTE)&dwFlags, &dwSize);
dwFlags &= ~(FLAG_ENABLE_CHNLBAND);
dwSize = sizeof(dwFlags);
RegSetValueEx(hSubKey, REGVAL_FLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, dwSize);
// close the key since we have a match and are therefore going to break out
RegCloseKey(hSubKey);
break;
}
RegCloseKey(hSubKey);
}
} // end of RegEnum loop
RegCloseKey(hKey);
}
}
}
// before we do the INF work, we have to run the following function which is
// hack way to fix Russian NT 4.0 localization problem. This only apply to Russian NT box.
if (g_fRunningOnNT && IsBrokenLang() )
{
FixRegData();
}
// On win95, due to the RegSave/Restore problem on default valuename, and valuename is space,
// we will do a specific fix for SearchUrl subkey. The generic registry operation fix will in advpack.dll.
if ( (!g_fRunningOnNT) && bInstall )
{
FixSearchUrl();
}
// because this stub code is left after uninstall IE5 to do both IE4 and IE5 work, we need the smartness to
// know when to run IE4 inf and when only needed to run IE5 inf
// BUGBUG: this portion of code is very version specific and need to be updated whenever the new Major
// version is shipped. Bud pain!! Most likely, in IE6 time we need to stub EXE to get around the problem!!
if (bInstall)
{
UINT uIEVer = CheckIEVersion();
// install stub case:
if (uIEVer == IE4)
{
DoINFWork(bInstall, c_szPrevStubINF, NULL, 0); // NULL means DefaultInstall section
}
else if (uIEVer >= IE5)
{
if (!IsPrevStubRun() )
{
// Simulate a pre-installation of IE4. So run IE4 browser stub
// first, then followed by the IE4 Shell stub (if required).
DoINFWork( bInstall, c_szPrevStubINF, NULL, RSC_FLAG_INF | RSC_FLAG_QUIET );
if (IsPrevIE4WebShell())
{
DoINFWork( bInstall, c_szPrevStubINF, g_fRunningOnNT ? TEXT("Shell.UserStubNT") : TEXT("Shell.UserStub"), RSC_FLAG_INF | RSC_FLAG_QUIET);
}
}
DoINFWork( bInstall, c_szStubINFFile, NULL, 0 );
ProcessMouseException();
}
}
else
{
// uninstall stub case: use HKCU value to make sure which version it is uninstalling
UINT uUninstIEVer = CheckUninstIEVersion();
if (uUninstIEVer == IE4)
{
DoINFWork(bInstall, c_szPrevStubINF, NULL, 0);
}
else if (uUninstIEVer == IE5)
{
DoINFWork(bInstall, c_szStubINFFile, NULL, 0);
}
else if (uUninstIEVer == IE55 || uUninstIEVer == IE6)
{
DoINFWork(bInstall, c_szStubINFFile, NULL, 0);
}
}
if (bInstall && g_fRunningOnWinXP)
IEAccessHideExplorerIcon();
}
INT WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine, INT nCmdShow )
{
BOOL bInstall;
if ( !lpszCmdLine || !*lpszCmdLine )
bInstall = TRUE;
else
bInstall = FALSE;
DoWork( bInstall );
TCHAR szCmdLine[MAX_PATH];
GetSystemDirectory(szCmdLine, ARRAYSIZE(szCmdLine));
AddPath(szCmdLine, TEXT("shmgrate.exe"));
ShellExecute(NULL, NULL, szCmdLine, TEXT("OCInstallUserConfigIE"), NULL, SW_SHOWDEFAULT);
return 0;
}
// stolen from the CRT, used to shrink our code
int
_stdcall
ModuleEntry(void)
{
STARTUPINFO si;
LPSTR pszCmdLine = GetCommandLine();
g_hinst = GetModuleHandle(NULL);
#ifdef DEBUG
CcshellGetDebugFlags();
if (IsFlagSet(g_dwBreakFlags, BF_ONOPEN))
DebugBreak();
#endif
if (FAILED(OleInitialize(NULL)))
return 0;
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
{
g_fRunningOnNT = TRUE;
if (osvi.dwMajorVersion >= 5) {
g_fRunningOnNT5 = TRUE;
if (osvi.dwMinorVersion >= 1)
g_fRunningOnWinXP = TRUE;
}
}
else if ((VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId) && (0 == osvi.dwMinorVersion))
{
g_fRunningOnWin95 = TRUE;
}
// turn off critical error stuff
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
if ( *pszCmdLine == '\"' ) {
/*
* Scan, and skip over, subsequent characters until
* another double-quote or a null is encountered.
*/
while ( *++pszCmdLine && (*pszCmdLine != '\"') );
/*
* If we stopped on a double-quote (usual case), skip
* over it.
*/
if ( *pszCmdLine == '\"' )
pszCmdLine++;
}
else {
while (*pszCmdLine > ' ')
pszCmdLine++;
}
/*
* Skip past any white space preceeding the second token.
*/
while (*pszCmdLine && (*pszCmdLine <= ' ')) {
pszCmdLine++;
}
si.dwFlags = 0;
GetStartupInfoA(&si);
WinMain(GetModuleHandle(NULL), NULL, pszCmdLine,
si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
OleUninitialize();
ExitProcess(0);
return 0; // We never come here
}
UINT CheckUninstIEVersion()
{
HKEY hKey;
DWORD dwSize;
TCHAR szPreIEVer[50];
WORD wPreIEVer[4];
UINT uRet = LESSIE4;
if ( RegOpenKeyEx( HKEY_CURRENT_USER, c_szActInstalledIEGUIDRestore, 0, KEY_READ, &hKey) != ERROR_SUCCESS )
{
if ( RegOpenKeyEx( HKEY_CURRENT_USER, c_szActInstalledIEGUID, 0, KEY_READ, &hKey) != ERROR_SUCCESS )
{
return uRet;
}
}
dwSize = sizeof( szPreIEVer );
if ( RegQueryValueEx(hKey, TEXT("Version"), NULL, NULL, (LPBYTE)szPreIEVer, &dwSize) == ERROR_SUCCESS )
{
ConvertVersionString( szPreIEVer, wPreIEVer, ',' );
if ((wPreIEVer[0] == 0x0004) && (wPreIEVer[1]>=0x0047))
uRet = IE4;
else if (wPreIEVer[0] == 0x0005)
{
if (wPreIEVer[1] >= 0x0032)
uRet = IE55;
else
uRet = IE5;
}
else if (wPreIEVer[0] == 0x0006)
uRet = IE6;
}
RegCloseKey(hKey);
return uRet;
}
BOOL IsPrevIE4()
{
HKEY hKey;
DWORD dwSize;
TCHAR szPreIEVer[50];
WORD wPreIEVer[4];
BOOL bRet = FALSE;
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szIE4Setup, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
{
dwSize = sizeof( szPreIEVer );
if ( RegQueryValueEx(hKey, c_szPreIEVer, NULL, NULL, (LPBYTE)szPreIEVer, &dwSize) == ERROR_SUCCESS )
{
ConvertVersionString( szPreIEVer, wPreIEVer, '.' );
if ( (wPreIEVer[0] == 0x0004) && (wPreIEVer[1]>=0x0047) )
{
bRet = TRUE;
}
}
RegCloseKey(hKey);
}
return bRet;
}
BOOL IsPrevIE4WebShell()
{
HKEY hKey;
DWORD dwSize;
TCHAR szPreShellVer[50];
WORD wPreShellVer[4];
BOOL bRet = FALSE;
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szIE4Setup, 0, KEY_READ, &hKey) == ERROR_SUCCESS )
{
dwSize = sizeof( szPreShellVer );
if ( RegQueryValueEx(hKey, c_szPreShellVer, NULL, NULL, (LPBYTE)szPreShellVer, &dwSize) == ERROR_SUCCESS )
{
ConvertVersionString( szPreShellVer, wPreShellVer, '.' );
if ((wPreShellVer[0] == 0x0004) && (wPreShellVer[1]>=0x0047) )
{
bRet = TRUE;
}
}
RegCloseKey(hKey);
}
return bRet;
}
const TCHAR c_szMouseExceptions[] = TEXT("Control Panel\\Microsoft Input Devices\\Mouse\\Exceptions");
// This gets written to the registry
const TCHAR c_szFilename[] = TEXT("FileName");
const TCHAR c_szInternetExplorer[] = TEXT("Internet Explorer");
const TCHAR c_szDescription[] = TEXT("Description");
const TCHAR c_szVersion[] = TEXT("Version");
const TCHAR c_szIE[] = TEXT("IEXPLORE.EXE");
#define IE_VERSION 0x50000
void ProcessMouseException()
{
HKEY hKey;
HKEY hSubKey;
DWORD dwIndex = 1001; // start with 1001.
TCHAR szSubKey[16];
BOOL bCannotUse = TRUE;
TCHAR szData[MAX_PATH];
RemoveOldMouseException();
if (RegCreateKeyEx(HKEY_CURRENT_USER, c_szMouseExceptions, 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
while (bCannotUse)
{
wsprintf(szSubKey, "%d", dwIndex);
if (RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
{
RegCloseKey(hSubKey);
dwIndex++;
}
else
bCannotUse = FALSE;
}
if (RegCreateKeyEx(hKey, szSubKey, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS)
{
if (!LoadString(g_hinst, IDS_IE_APPNAME, szData, sizeof(szData)))
lstrcpy(szData, c_szInternetExplorer);
RegSetValueEx(hSubKey, c_szDescription, 0, REG_SZ, (LPBYTE)szData, (lstrlen(szData)+1) * sizeof(TCHAR));
RegSetValueEx(hSubKey, c_szFilename, 0, REG_SZ, (LPBYTE)c_szIE, (lstrlen(c_szIE)+1) * sizeof(TCHAR));
dwIndex = IE_VERSION;
RegSetValueEx(hSubKey, c_szVersion, 0, REG_DWORD, (LPBYTE)&dwIndex , sizeof(DWORD));
RegCloseKey(hSubKey);
}
RegCloseKey(hKey);
}
}
void RemoveOldMouseException()
{
HKEY hKey;
HKEY hSubKey;
DWORD dwIndex = 0;
BOOL bFound = FALSE;
LONG lRet = ERROR_SUCCESS;
TCHAR szSubKey[MAX_PATH];
DWORD dwSize;
TCHAR szData[MAX_PATH];
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szMouseExceptions, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS)
{
while (!bFound && (lRet == ERROR_SUCCESS))
{
dwSize = sizeof(szSubKey);
lRet = RegEnumKeyEx(hKey, dwIndex, szSubKey, &dwSize, NULL, NULL, NULL, NULL);
if (lRet == ERROR_SUCCESS)
{
if (RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
{
dwSize = sizeof(szData);
if (RegQueryValueEx(hSubKey, c_szFilename,NULL, NULL, (LPBYTE)szData, &dwSize) == ERROR_SUCCESS)
{
bFound = (lstrcmpi(szData, c_szIE) == 0);
}
RegCloseKey(hSubKey);
}
if (bFound)
{
RegDeleteKey(hKey, szSubKey);
}
else
dwIndex++;
}
}
RegCloseKey(hKey);
}
}