windows-nt/Source/XPSP1/NT/shell/shdocvw/htregmng.cpp
2020-09-26 16:20:57 +08:00

3109 lines
105 KiB
C++

/*
* Registry Management
*
* HTREGMNG.C
*
* Copyright (c) 1995 Microsoft Corporation
*
*/
#include "priv.h"
#include "htregmng.h"
#include "resource.h"
#include "regapix.h"
#include <filetype.h>
#include <advpub.h>
#include <mluisupp.h>
// This file contains the auto-registration code, which smartly performs
// the install/uninstall of registry keys and values. While an inf file
// is sufficient most of the time, IE needs to be smart about what
// sort of values to set, based upon certain conditions. An inf file
// does not offer this depth of support. Additionally, IE requires
// code to be run when it detects that it is not the default browser,
// so it can make it the default browser. Any settings that determine
// this should be placed here, rather than the inf file.
//
// This code is table driven. The idea is simple. You have a RegSet
// which is the "Registry Set". The Registry Set indicates the
// root key and contains a list of RegEntries. Each RegEntry
// specifies a command, flags, key and value names, and optional data
// that provides the essential info to set/change/delete a registry
// value or key.
//
//
// NOTE: NOTE: NOTE: NOTE: NOTE: NOTE: NOTE:
//-------------------------------------------
// Any new Icon check that uses HTReg_UrlIconProc that gets added
// to any of the Assoc arrays and is REQUIRED for Default Browser check to
// succeed has to be added to the c_rlAssoc_FixIcon[] array also.
//
// Make the tables more compact
#define HKCR HKEY_CLASSES_ROOT
#define HKLM HKEY_LOCAL_MACHINE
#define HKCU HKEY_CURRENT_USER
#define IDEFICON_STD 0
#define IDEFICON_NEWS 1
#define IDEFICON_MAIL 2
#ifndef UNIX
#define IEXPLORE_APP "IExplore"
#define IEXPLORE_EXE "iexplore.exe"
#define EXPLORER_EXE "explorer.exe"
#define RUNDLL_CMD_FMT "rundll32.exe %s"
#else
#define IEXPLORE_APP "iexplorer"
#define IEXPLORE_EXE "iexplorer"
#define EXPLORER_EXE "explorer"
#define RUNDLL_CMD_FMT "rundll32 %s"
#endif
BOOL InstallRegSet(const RegSet *prs, BOOL bDontIntrude);
#ifndef UNIX
const CHAR c_szIexploreKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE";
#else
const CHAR c_szIexploreKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORER";
#endif
#ifdef DEBUG
/*----------------------------------------------------------
Purpose: Return a string path composed of hkey\pszKey\pszValueName.
Returns:
Cond: --
*/
LPTSTR
Dbg_RegStr(
IN const RegEntry * pre,
IN LPTSTR pszBuf)
{
TCHAR szRoot[5];
TCHAR szTempKey[MAXIMUM_SUB_KEY_LENGTH];
TCHAR szTempValue[MAXIMUM_VALUE_NAME_LENGTH];
ASSERT(pre);
ASSERT(pszBuf);
if (HKEY_CLASSES_ROOT == pre->hkeyRoot)
{
StrCpyN(szRoot, TEXT("HKCR"), ARRAYSIZE(szRoot));
}
else if (HKEY_CURRENT_USER == pre->hkeyRoot)
{
StrCpyN(szRoot, TEXT("HKCU"), ARRAYSIZE(szRoot));
}
else if (HKEY_LOCAL_MACHINE == pre->hkeyRoot)
{
StrCpyN(szRoot, TEXT("HKLM"), ARRAYSIZE(szRoot));
}
else
{
StrCpyN(szRoot, TEXT("????"), ARRAYSIZE(szRoot));
ASSERT(0);
}
AnsiToTChar(pre->pszKey, szTempKey, ARRAYSIZE(szTempKey));
szTempValue[0] = TEXT('\0');
if (pre->pszValName)
AnsiToTChar(pre->pszValName, szTempValue, ARRAYSIZE(szTempValue));
ASSERT(lstrlen(pszBuf) < MAX_PATH);
wnsprintf(pszBuf, MAX_PATH, TEXT("%s\\%hs\\%hs"), szRoot, szTempKey, szTempValue);
return pszBuf;
}
#else
#define Dbg_RegStr(x, y) 0
#endif // DEBUG
/*----------------------------------------------------------
Purpose: Queries the registry for the location of the path
of Internet Explorer and returns it in pszBuf.
Returns: TRUE on success
FALSE if path cannot be determined
Cond: --
*/
BOOL
GetIEPath2(
OUT LPSTR pszBuf,
IN DWORD cchBuf,
IN BOOL bInsertQuotes)
{
BOOL bRet = FALSE;
HKEY hkey;
*pszBuf = '\0';
// Get the path of Internet Explorer
if (NO_ERROR != RegOpenKeyA(HKEY_LOCAL_MACHINE, c_szIexploreKey, &hkey))
{
#ifndef UNIX
TraceMsg(TF_ERROR, "InstallRegSet(): RegOpenKey( %s ) Failed", c_szIexploreKey) ;
#endif
}
else
{
DWORD cbBrowser;
DWORD dwType;
if (bInsertQuotes)
StrCatBuffA(pszBuf, "\"", cchBuf);
cbBrowser = CbFromCchA(cchBuf - lstrlenA(" -nohome") - 4);
if (NO_ERROR != SHQueryValueExA(hkey, "", NULL, &dwType,
(LPBYTE)&pszBuf[bInsertQuotes?1:0], &cbBrowser))
{
TraceMsg(TF_ERROR, "InstallRegSet(): RegQueryValueEx() for Iexplore path failed");
}
else
{
bRet = TRUE;
}
if (bInsertQuotes)
StrCatBuffA(pszBuf, "\"", cchBuf);
RegCloseKey(hkey);
}
return bRet;
}
BOOL
GetIEPath(
OUT LPSTR pszBuf,
IN DWORD cchBuf)
{
return GetIEPath2(pszBuf, cchBuf, TRUE);
}
/*----------------------------------------------------------
Purpose: Queries the registry for the location of the path
of the shell's Explorer and returns it in pszBuf.
Returns: TRUE on success
FALSE if path cannot be determined
Cond: --
*/
BOOL
GetExplorerPath(
OUT LPSTR pszBuf,
IN DWORD cchBuf, DWORD dwType)
{
BOOL bRet;
// Get the path of the Explorer
if (dwType == REG_EXPAND_SZ)
{
StrCpyNA (pszBuf, "%SystemRoot%", cchBuf);
bRet = TRUE;
}
else
bRet = (0 < GetWindowsDirectoryA(pszBuf, cchBuf));
if (bRet)
{
StrCatBuffA(pszBuf, "\\Explorer.exe", cchBuf);
}
return bRet;
}
// Callback messages
#define RSCB_QUERY 1
#define RSCB_INSTALL 2
typedef BOOL (CALLBACK* RSPECPROC)(UINT nMsg, const RegEntry * pre, LPVOID pvData, DWORD dwData);
// Win9x to NT5 migration generated file.
#define MIGICONS "migicons.exe"
/*----------------------------------------------------------
Purpose: This callback sets the default icon to point to a
given index in url.dll.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_UrlIconProc(
IN UINT nMsg,
IN const RegEntry * pre,
IN LPVOID pvData, OPTIONAL
IN DWORD dwData)
{
BOOL bRet = TRUE;
CHAR sz[MAX_PATH + 20]; // Need a bit extra
LPCSTR pszPath = (LPCSTR) pvData;
int cch;
DWORD dwType; //local type.
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
if (!g_fRunningOnNT) {
ASSERT(REG_EXPAND_SZ == pre->dwType);
dwType = REG_SZ;
} else
dwType = (DWORD)pre->dwType;
if (dwType == REG_EXPAND_SZ)
StrCpyNA (sz, "%SystemRoot%\\system32", ARRAYSIZE(sz));
else
GetSystemDirectoryA(sz, SIZECHARS(sz));
cch = lstrlenA(sz);
// We still have to use url.dll as the source of the internet shortcut
// icons because the icons need to still be valid on uninstall.
wnsprintfA(&sz[cch], ARRAYSIZE(sz) - cch, "\\url.dll,%d", (int)pre->DUMMYUNION_MEMBER(lParam));
switch (nMsg)
{
case RSCB_QUERY:
if (0 != StrCmpNIA(sz, pszPath, dwData / SIZEOF(CHAR)) &&
0 != StrCmpIA(PathFindFileNameA(sz), PathFindFileNameA(pszPath)))
{
// Failed the Url.Dll test. Check if this is NT5. In that case
// maybe the icons are in migicons.exe (Win9x to NT5 upgrade).
if (g_bRunOnNT5 && StrStrIA(pszPath,MIGICONS)!= NULL)
{ // NT5 and 'migicons.exe' => upgrade. Set global to fix this.
g_bNT5Upgrade = TRUE;
}
else
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s is %hs, expecting %hs", Dbg_RegStr(pre, szDbg), pszPath, sz);
bRet = FALSE;
}
}
break;
case RSCB_INSTALL:
if (NO_ERROR != SHSetValueA(pre->hkeyRoot, pre->pszKey,
pre->pszValName, dwType,
sz, CbFromCchA(lstrlenA(sz) + 1)))
{
TraceMsg(TF_ERROR, "InstallRegSet(): SHSetValue(%s) Failed", Dbg_RegStr(pre, szDbg));
bRet = FALSE;
}
else
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Setting %s", Dbg_RegStr(pre, szDbg)); )
}
break;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: This callback sets the default icon to point to a
given index in iexplore.exe
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_IEIconProc(
IN UINT nMsg,
IN const RegEntry * pre,
IN LPVOID pvData, OPTIONAL
IN DWORD dwData)
{
BOOL bRet = TRUE;
CHAR sz[MAX_PATH + 20]; // Need a bit extra
LPCSTR pszPath = (LPCSTR) pvData;
int cch;
DWORD dwType; //local type.
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
if (!g_fRunningOnNT) {
// Sanity check that we don't coerce to REG_SZ wrongfully.
// If you hit this assert, it means the table entry has the
// wrong type in it.
ASSERT(REG_EXPAND_SZ == pre->dwType || REG_SZ == pre->dwType);
dwType = REG_SZ;
} else
dwType = (DWORD)pre->dwType;
if (!GetIEPath2(sz, SIZECHARS(sz), FALSE))
return FALSE;
cch = lstrlenA(sz);
wnsprintfA(&sz[cch], ARRAYSIZE(sz) - cch, ",%d", (int)pre->DUMMYUNION_MEMBER(lParam));
switch (nMsg)
{
case RSCB_QUERY:
if (0 != StrCmpNIA(sz, pszPath, dwData / SIZEOF(CHAR)) &&
0 != StrCmpA(PathFindFileNameA(sz), PathFindFileNameA(pszPath)))
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s is %hs, expecting %hs", Dbg_RegStr(pre, szDbg), pszPath, sz);
bRet = FALSE;
}
break;
case RSCB_INSTALL:
if (NO_ERROR != SHSetValueA(pre->hkeyRoot, pre->pszKey,
pre->pszValName, dwType,
sz, CbFromCchA(lstrlenA(sz) + 1)))
{
TraceMsg(TF_ERROR, "InstallRegSet(): SHSetValue(%s) Failed", Dbg_RegStr(pre, szDbg));
bRet = FALSE;
}
else
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Setting %s", Dbg_RegStr(pre, szDbg)); )
}
break;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: This callback sets the IExplore path.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_IEPathProc(
IN UINT nMsg,
IN const RegEntry * pre,
IN LPVOID pvData, OPTIONAL
IN DWORD dwData)
{
BOOL bRet = TRUE;
CHAR sz[MAX_PATH + 20]; // Need a bit extra
CHAR szOther[MAX_PATH + 20]; // Need a bit extra
LPCSTR pszPath = (LPCSTR) pvData;
int cch;
DWORD dwType;
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
ASSERT(REG_EXPAND_SZ == pre->dwType || REG_SZ == pre->dwType);
if (!g_fRunningOnNT)
{
// Expand string is not supported on Win95
dwType = REG_SZ;
}
else
{
dwType = pre->dwType;
}
if (GetIEPath(sz, SIZECHARS(sz))) {
// sz contains the path as listed in AppPaths\IExplore.
// NOTE NOTE: GetIEPath() uses the default value which has no
// terminating ';'. Hence this check is not needed. Anyway, do it and
// then convert to other form.
cch = lstrlenA(sz) - 1;
if (*sz && sz[cch] == ';')
sz[cch] = '\0';
// Convert this to LFN or SFN as the case may be.
GetPathOtherFormA(sz, szOther, ARRAYSIZE(szOther));
if (pre->DUMMYUNION_MEMBER(lParam))
{
StrCatBuffA(sz, (LPSTR)pre->DUMMYUNION_MEMBER(lParam), ARRAYSIZE(sz));
StrCatBuffA(szOther, (LPSTR)pre->DUMMYUNION_MEMBER(lParam), ARRAYSIZE(szOther));
}
switch (nMsg)
{
case RSCB_QUERY:
if ((0 != StrCmpNIA(pszPath, sz, dwData / SIZEOF(CHAR)))
&& (0 != StrCmpNIA(pszPath, szOther, dwData / SIZEOF(CHAR))))
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s string is \"%hs\", expecting \"%hs\"", Dbg_RegStr(pre, szDbg), pszPath, sz);
bRet = FALSE;
}
break;
case RSCB_INSTALL:
if (NO_ERROR != SHSetValueA(pre->hkeyRoot, pre->pszKey,
pre->pszValName, dwType,
sz, CbFromCchA(lstrlenA(sz) + 1)))
{
TraceMsg(TF_ERROR, "InstallRegSet(): SHSetValue(%hs) Failed", pre->pszValName);
bRet = FALSE;
}
else
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Setting %s", Dbg_RegStr(pre, szDbg)); )
}
break;
}
}
return bRet;
}
/*----------------------------------------------------------
Purpose: This callback checks for the existence of the string
value "Exchange" at HKLM\Software\Microsoft. If it
exists, the value is copied into the default value
of HKLM\Software\Clients\Mail\Exchange\shell\open\command.
This is for Athena. It only happens when setup is run,
not when the browser checks to see if it is the default.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_ExchangeProc(
IN UINT nMsg,
IN const RegEntry * pre,
IN LPVOID pvData,
IN DWORD dwData)
{
TCHAR sz[MAX_PATH+2]; // +2 because we may need to wrap the path in quotes.
DWORD cbSize;
switch (nMsg)
{
case RSCB_QUERY:
// We shouldn't be called for this one
ASSERT(0);
break;
case RSCB_INSTALL:
// Does the Exchange value exist at "HKLM\Software\Microsoft"?
cbSize = sizeof(sz);
if (NO_ERROR == SHGetValue(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft"), TEXT("Exchange"), NULL, sz, &cbSize))
{
// Yes; copy it to HKLM\Software\Clients\Mail\Exchange\shell\open\command
TCHAR szT[MAX_PATH+2];
// Wrap the path in quotes. Don't wrap any args though!
StrCpyN(szT, sz, ARRAYSIZE(szT));
PathProcessCommand(szT, sz, ARRAYSIZE(szT), PPCF_ADDQUOTES|PPCF_ADDARGUMENTS);
// Set the size again
cbSize = CbFromCch(lstrlen(sz)+1);
SHSetValue(HKEY_LOCAL_MACHINE,
TEXT("Software\\Clients\\Mail\\Exchange\\shell\\open\\command"),
TEXT(""), REG_SZ, sz, cbSize);
TraceMsg(TF_REGCHECK, "Copying \"%s\" to HKLM\\Software\\Clients\\Mail\\Exchange", sz);
// Set any other settings in this condition too?
if (pre->DUMMYUNION_MEMBER(lParam))
InstallRegSet((const RegSet *)pre->DUMMYUNION_MEMBER(lParam), TRUE);
// In OSR2 installs, the mailto handler will get out of
// sync with the actual default mail client. (Athena installs
// itself as the default mail client, but exchange remains
// the mailto: handler.) In this case, if exchange is the
// mailto: handler, change the default mail client to be
// exchange.
// Is Exchange the mailto handler?
cbSize = SIZEOF(sz);
if (NO_ERROR == SHGetValue(HKEY_CLASSES_ROOT, TEXT("mailto\\shell\\open\\command"),
TEXT(""), NULL, sz, &cbSize) &&
StrStrI(sz, TEXT("url.dll,MailToProtocolHandler")))
{
// Yes; make it be the default mail client too
SHSetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Clients\\Mail"),
TEXT(""), REG_SZ, TEXT("Exchange"), sizeof(TEXT("Exchange")));
TraceMsg(TF_REGCHECK, "Setting Exchange to be the default mail client.");
}
}
break;
}
return TRUE;
}
/*----------------------------------------------------------
Purpose: Uninstall certain keys, as specified by pre->pszKey.
We do not uninstall a key if the class\shell\open\command
does not have iexplore.exe.
If someone else registered themselves to add more
verbs under class\shell (other than open) or class\shellex,
then we remove everything but their keys.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_UninstallProc(
IN UINT nMsg,
IN const RegEntry * pre,
IN LPVOID pvData,
IN DWORD dwData)
{
TCHAR szKey[MAX_PATH];
TCHAR sz[MAX_PATH + 20]; // add some padding for arguments
DWORD cbSize;
switch (nMsg)
{
case RSCB_QUERY:
// We shouldn't be called for this one
ASSERT(0);
break;
case RSCB_INSTALL:
ASSERT(pre->pszKey);
// Does the shell\open\command value have a microsoft browser?
wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("%hs\\shell\\open\\command"), pre->pszKey);
cbSize = sizeof(sz);
if (NO_ERROR == SHGetValue(pre->hkeyRoot, szKey, TEXT(""),
NULL, sz, &cbSize) &&
(StrStrI(sz, TEXT(IEXPLORE_EXE)) || StrStrI(sz, TEXT(EXPLORER_EXE))))
{
// Yes; proceed to prune this key of all of our values
TraceMsg(TF_REGCHECK, "Pruning HKCR\\%hs", pre->pszKey);
ASSERT(pre->DUMMYUNION_MEMBER(lParam));
InstallRegSet((const RegSet *)pre->DUMMYUNION_MEMBER(lParam), FALSE);
}
break;
}
return TRUE;
}
// NOTE: these are ANSI strings by design.
const DWORD c_dwEditFlags2 = FTA_Show;
const CHAR c_szTelnetHandler[] = "url.dll,TelnetProtocolHandler %l";
const CHAR c_szMailToHandler[] = "url.dll,MailToProtocolHandler %l";
const CHAR c_szNewsHandler[] = "url.dll,NewsProtocolHandler %l";
const CHAR c_szFileHandler[] = "url.dll,FileProtocolHandler %l";
const CHAR c_szOpenURL[] = "url.dll,OpenURL %l";
const CHAR c_szOpenURLNash[] = "shdocvw.dll,OpenURL %l";
const CHAR c_szURL[] = "url.dll";
const CHAR c_szShdocvw[] = "shdocvw.dll";
const CHAR c_szCheckAssnSwitch[] = "Software\\Microsoft\\Internet Explorer\\Main";
const CHAR c_szDDE_Default[] = "\"%1\",,-1,0,,,,";
const CHAR c_szDDE_FileDefault[] = "\"file://%1\",,-1,,,,,";
// Note (scotth): a lot of the strings below have substrings that
// are repeated over and over and over again. Should add some
// smarter RC_ values that will concatenate the common strings
// together to save data space.
const CHAR c_szHTTP[] = "http";
const CHAR c_szHTTPDefIcon[] = "http\\DefaultIcon";
const CHAR c_szHTTPOpenCmd[] = "http\\shell\\open\\command";
const CHAR c_szHTTPDdeexec[] = "http\\shell\\open\\ddeexec";
const CHAR c_szHTTPDdeTopic[] = "http\\shell\\open\\ddeexec\\Topic";
const CHAR c_szHTTPDdeApp[] = "http\\shell\\open\\ddeexec\\Application";
const CHAR c_szHTTPS[] = "https";
const CHAR c_szHTTPSDefIcon[] = "https\\DefaultIcon";
const CHAR c_szHTTPSOpenCmd[] = "https\\shell\\open\\command";
const CHAR c_szHTTPSDdeexec[] = "https\\shell\\open\\ddeexec";
const CHAR c_szHTTPSDdeTopic[] = "https\\shell\\open\\ddeexec\\Topic";
const CHAR c_szHTTPSDdeApp[] = "https\\shell\\open\\ddeexec\\Application";
const CHAR c_szFTP[] = "ftp";
const CHAR c_szFTPDefIcon[] = "ftp\\DefaultIcon";
const CHAR c_szFTPOpenCmd[] = "ftp\\shell\\open\\command";
const CHAR c_szFTPDdeexec[] = "ftp\\shell\\open\\ddeexec";
const CHAR c_szFTPDdeTopic[] = "ftp\\shell\\open\\ddeexec\\Topic";
const CHAR c_szFTPDdeApp[] = "ftp\\shell\\open\\ddeexec\\Application";
const CHAR c_szFTPDdeifExec[] = "ftp\\shell\\open\\ddeexec\\ifExec";
const CHAR c_szGOPHER[] = "gopher";
const CHAR c_szGOPHERDefIcon[] = "gopher\\DefaultIcon";
const CHAR c_szGOPHEROpenCmd[] = "gopher\\shell\\open\\command";
const CHAR c_szGOPHERDdeexec[] = "gopher\\shell\\open\\ddeexec";
const CHAR c_szGOPHERDdeTopic[] = "gopher\\shell\\open\\ddeexec\\Topic";
const CHAR c_szGOPHERDdeApp[] = "gopher\\shell\\open\\ddeexec\\Application";
const CHAR c_szMailTo[] = "mailto";
const CHAR c_szMailToDefIcon[] = "mailto\\DefaultIcon";
const CHAR c_szMailToOpenCmd[] = "mailto\\shell\\open\\command";
const CHAR c_szTelnet[] = "telnet";
const CHAR c_szTelnetDefIcon[] = "telnet\\DefaultIcon";
const CHAR c_szTelnetOpenCmd[] = "telnet\\shell\\open\\command";
const CHAR c_szRLogin[] = "rlogin";
const CHAR c_szRLoginDefIcon[] = "rlogin\\DefaultIcon";
const CHAR c_szRLoginOpenCmd[] = "rlogin\\shell\\open\\command";
const CHAR c_szTN3270[] = "tn3270";
const CHAR c_szTN3270DefIcon[] = "tn3270\\DefaultIcon";
const CHAR c_szTN3270OpenCmd[] = "tn3270\\shell\\open\\command";
const CHAR c_szNews[] = "news";
const CHAR c_szNewsDefIcon[] = "news\\DefaultIcon";
const CHAR c_szNewsOpenCmd[] = "news\\shell\\open\\command";
const CHAR c_szFile[] = "file";
const CHAR c_szFileDefIcon[] = "file\\DefaultIcon";
const CHAR c_szFileOpenCmd[] = "file\\shell\\open\\command";
const CHAR c_szHTMDefIcon[] = "htmlfile\\DefaultIcon";
const CHAR c_szHTMShell[] = "htmlfile\\shell";
const CHAR c_szHTMOpen[] = "htmlfile\\shell\\open";
const CHAR c_szHTMOpenCmd[] = "htmlfile\\shell\\open\\command";
const CHAR c_szHTMOpenDdeexec[] = "htmlfile\\shell\\open\\ddeexec";
const CHAR c_szHTMOpenDdeTopic[] = "htmlfile\\shell\\open\\ddeexec\\Topic";
const CHAR c_szHTMOpenDdeApp[] = "htmlfile\\shell\\open\\ddeexec\\Application";
const CHAR c_szMHTMDefIcon[] = "mhtmlfile\\DefaultIcon";
const CHAR c_szMHTMShell[] = "mhtmlfile\\shell";
const CHAR c_szMHTMOpen[] = "mhtmlfile\\shell\\open";
const CHAR c_szMHTMOpenCmd[] = "mhtmlfile\\shell\\open\\command";
const CHAR c_szMHTMOpenDdeexec[] = "mhtmlfile\\shell\\open\\ddeexec";
const CHAR c_szMHTMOpenDdeTopic[] = "mhtmlfile\\shell\\open\\ddeexec\\Topic";
const CHAR c_szMHTMOpenDdeApp[] = "mhtmlfile\\shell\\open\\ddeexec\\Application";
const CHAR c_szOpenNew[] = "opennew";
const CHAR c_szHTMOpenNew[] = "htmlfile\\shell\\opennew";
const CHAR c_szHTMOpenNewCmd[] = "htmlfile\\shell\\opennew\\command";
const CHAR c_szHTMOpenNewDdeexec[] = "htmlfile\\shell\\opennew\\ddeexec";
const CHAR c_szHTMOpenNewDdeIfExec[] = "htmlfile\\shell\\opennew\\ddeexec\\IfExec";
const CHAR c_szHTMOpenNewDdeTopic[] = "htmlfile\\shell\\opennew\\ddeexec\\Topic";
const CHAR c_szHTMOpenNewDdeApp[] = "htmlfile\\shell\\opennew\\ddeexec\\Application";
const CHAR c_szMHTMOpenNew[] = "mhtmlfile\\shell\\opennew";
const CHAR c_szMHTMOpenNewCmd[] = "mhtmlfile\\shell\\opennew\\command";
const CHAR c_szMHTMOpenNewDdeexec[] = "mhtmlfile\\shell\\opennew\\ddeexec";
const CHAR c_szMHTMOpenNewDdeIfExec[] = "mhtmlfile\\shell\\opennew\\ddeexec\\IfExec";
const CHAR c_szMHTMOpenNewDdeTopic[] = "mhtmlfile\\shell\\opennew\\ddeexec\\Topic";
const CHAR c_szMHTMOpenNewDdeApp[] = "mhtmlfile\\shell\\opennew\\ddeexec\\Application";
const CHAR c_szIntShcut[] = "InternetShortcut";
const CHAR c_szIntShcutDefIcon[] = "InternetShortcut\\DefaultIcon";
const CHAR c_szIntShcutCLSID[] = "InternetShortcut\\CLSID";
const CHAR c_szIntShcutOpen[] = "InternetShortcut\\shell\\open";
const CHAR c_szIntShcutOpenCmd[] = "InternetShortcut\\shell\\open\\command";
const CHAR c_szIntShcutIconHandler[] = "InternetShortcut\\shellex\\IconHandler";
const CHAR c_szIntShcutPrshtHandler[]= "InternetShortcut\\shellex\\PropertySheetHandlers\\{FBF23B40-E3F0-101B-8488-00AA003E56F8}";
const CHAR c_szIntShcutPropHandler[] = "InternetShortcut\\shellex\\PropertyHandler";
const CHAR c_szIntShcutCMHandler[] = "InternetShortcut\\shellex\\ContextMenuHandlers\\{FBF23B40-E3F0-101B-8488-00AA003E56F8}";
const CHAR c_szCLSIDCmdFile[] = "{57651662-CE3E-11D0-8D77-00C04FC99D61}";
const CHAR c_szCLSIDIntshcut[] = "{FBF23B40-E3F0-101B-8488-00AA003E56F8}";
const CHAR c_szCLSIDURLExecHook[] = "{AEB6717E-7E19-11d0-97EE-00C04FD91972}";
const CHAR c_szIntshcutInproc[] = "CLSID\\{FBF23B40-E3F0-101B-8488-00AA003E56F8}\\InProcServer32";
const CHAR c_szIEFrameAuto[] = "CLSID\\{0002DF01-0000-0000-C000-000000000046}\\LocalServer32";
const CHAR c_szIENameSpaceOpen[] = "CLSID\\{FBF23B42-E3F0-101B-8488-00AA003E56F8}\\shell\\open\\command";
const CHAR c_szCLSIDURLRoot[] = "CLSID\\{3DC7A020-0ACD-11CF-A9BB-00AA004AE837}";
const CHAR c_szIntshcutMayChange[] = "CLSID\\{FBF23B40-E3F0-101B-8488-00AA003E56F8}\\shellex\\MayChangeDefaultMenu";
//
// General associations shared across browser-only and full-shell
//
const RegEntry c_rlAssoc[] = {
// HTTP
{ RC_ADD, REF_NOTNEEDED, HKCR, c_szHTTP, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_HTTPNAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTP, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTP, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED
|REF_DONTINTRUDE, HKCR, c_szHTTPDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
// HTTPS
{ RC_ADD, REF_NOTNEEDED, HKCR, c_szHTTPS, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_HTTPSNAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPS, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPS, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED|REF_DONTINTRUDE, HKCR, c_szHTTPSDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
// FTP
{ RC_ADD, REF_NOTNEEDED, HKCR, c_szFTP, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_FTPNAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTP, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTP, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED|REF_DONTINTRUDE, HKCR, c_szFTPDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
// Gopher
{ RC_ADD, REF_NOTNEEDED, HKCR, c_szGOPHER, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_GOPHERNAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHER, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHER, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED|REF_DONTINTRUDE, HKCR, c_szGOPHERDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
// Telnet
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_TELNETNAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szTelnetDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKCR, c_szTelnetOpenCmd, "", REG_SZ, sizeof(c_szTelnetHandler), c_szTelnetHandler },
// RLogin
{ RC_ADD, REF_IFEMPTY, HKCR, c_szRLogin, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_RLOGINNAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szRLogin, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szRLogin, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szRLoginDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKCR, c_szRLoginOpenCmd, "", REG_SZ, sizeof(c_szTelnetHandler), c_szTelnetHandler },
// TN3270
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTN3270, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_TN3270NAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTN3270, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTN3270, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szTN3270DefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKCR, c_szTN3270OpenCmd, "", REG_SZ, sizeof(c_szTelnetHandler), c_szTelnetHandler },
// Mailto protocol
{ RC_ADD, REF_IFEMPTY, HKCR, c_szMailTo, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_MAILTONAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szMailTo, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szMailTo, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szMailToDefIcon, "", REG_EXPAND_SZ, IDEFICON_MAIL, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKCR, c_szMailToOpenCmd, "", REG_SZ, sizeof(c_szMailToHandler), c_szMailToHandler },
// News protocol
{ RC_ADD, REF_IFEMPTY, HKCR, c_szNews, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_NEWSNAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szNews, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szNews, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szNewsDefIcon, "", REG_EXPAND_SZ, IDEFICON_NEWS, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKCR, c_szNewsOpenCmd, "", REG_SZ, sizeof(c_szNewsHandler), c_szNewsHandler },
// Internet shortcut
{ RC_ADD, REF_NORMAL, HKCR, ".url", "", REG_SZ, sizeof(c_szIntShcut), c_szIntShcut },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcut, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_INTSHNAME) },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szIntShcut, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcut, "IsShortcut", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcut, "NeverShowExt", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutCLSID, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szIntShcutDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutIconHandler, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutPrshtHandler, "", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{FBF23B40-E3F0-101B-8488-00AA003E56F8}", "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_INTSHNAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "", REG_SZ, sizeof(c_szShdocvw), c_szShdocvw },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "ThreadingModel", REG_SZ, sizeof("Apartment"), "Apartment" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "LoadWithoutCOM", REG_SZ, 1, ""},
// HTM file type
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szHTMDefIcon, "", REG_SZ, (LPARAM)1, HTReg_IEIconProc },
// MHTML file type
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szMHTMDefIcon, "", REG_SZ, (LPARAM)22, HTReg_IEIconProc },
};
const RegSet c_rsAssoc = {
ARRAYSIZE(c_rlAssoc),
c_rlAssoc
};
//
// .htm, .html associations for full-shell and browser-only installs
//
// This is run when the browser is opened, and considered a requirement
// to make IE be the default browser.
#ifdef UNIX
const RegEntry c_rlAssocHTM[] = {
#else
const RegList c_rlAssocHTM = {
#endif
// .html
{ RC_ADD, REF_DONTINTRUDE, HKCR, ".htm", "", REG_SZ, sizeof("htmlfile"), "htmlfile" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, ".htm", "Content Type", REG_SZ, sizeof("text/html"), "text/html" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, ".html", "", REG_SZ, sizeof("htmlfile"), "htmlfile" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, ".html", "Content Type", REG_SZ, sizeof("text/html"), "text/html" },
};
const RegSet c_rsAssocHTM = {
ARRAYSIZE(c_rlAssocHTM),
c_rlAssocHTM
};
// This is the minimum set that is queried every time a shell window opens.
// WARNING: this should be small to reduce the time it takes to open a folder.
// This is needed just to insure webview works.
//
const RegEntry c_rlAssocHTM_WV[] = {
// .html
{ RC_ADD, REF_IFEMPTY, HKCR, ".htm", "", REG_SZ, sizeof("htmlfile"), "htmlfile" },
{ RC_ADD, REF_IFEMPTY, HKCR, ".htm", "Content Type", REG_SZ, sizeof("text/html"), "text/html" },
{ RC_ADD, REF_IFEMPTY, HKCR, ".html", "", REG_SZ, sizeof("htmlfile"), "htmlfile" },
{ RC_ADD, REF_IFEMPTY, HKCR, ".html", "Content Type", REG_SZ, sizeof("text/html"), "text/html" },
};
const RegSet c_rsAssocHTM_WV = {
ARRAYSIZE(c_rlAssocHTM_WV),
c_rlAssocHTM_WV
};
//
// Browser-only specific association settings
//
const RegEntry c_rlAssoc_Alone[] = {
// HTTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// HTTPS
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPSOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// FTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szFTPOpenCmd, "", REG_SZ, (LPARAM)" %1", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeifExec, "", REG_SZ, sizeof("*"), "*" },
// Gopher
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szGOPHEROpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// File protocol
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFile, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_FILENAME) },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFile, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFile, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szFileDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFileOpenCmd, "", REG_SZ, sizeof(c_szFileHandler), c_szFileHandler },
// .htm
//
// APPCOMPAT:
// HTMOpenCmd needs to be REG_SZ because Office97 reads it out using RegQueryValue.
// WebFerret requires the string to be of type REG_SZ.
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTMOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMOpenDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMOpenDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMOpenDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// .mht, .mhtml
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szMHTMOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// Internet shortcut
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutCMHandler, "", REG_SZ, 1, "" },
// Other stuff
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szIntShcutOpenCmd, "", REG_SZ, sizeof(c_szOpenURLNash), c_szOpenURLNash },
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szIEFrameAuto, "", REG_SZ, 0, HTReg_IEPathProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szIENameSpaceOpen, "", REG_SZ, 0, HTReg_IEPathProc },
};
const RegSet c_rsAssoc_Alone = {
ARRAYSIZE(c_rlAssoc_Alone),
c_rlAssoc_Alone
};
// The reg entries for the browser only case for http, https, and ftp are duplicated here
const RegEntry c_rlAssoc_Quick[] = {
// HTTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// HTTPS
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPSOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// FTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szFTPOpenCmd, "", REG_SZ, (LPARAM)" %1", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeifExec, "", REG_SZ, sizeof("*"), "*" },
};
const RegSet c_rsAssoc_Quick = {
ARRAYSIZE(c_rlAssoc_Quick),
c_rlAssoc_Quick
};
//
// Full-shell specific association settings
//
const RegEntry c_rlAssoc_Full[] = {
// HTTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// HTTPS
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTTPSOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// FTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szFTPOpenCmd, "", REG_SZ, (LPARAM)" %1", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeifExec, "", REG_SZ, sizeof("*"), "*" },
// Gopher
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szGOPHEROpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// .htm
//
// APPCOMPAT:
// HTMOpenCmd needs to be REG_SZ because Office97 reads it out using RegQueryValue.
// WebFerret requires the string to be of type REG_SZ.
// Visual Source Safe reads the Ddeexec string, puts a file in the %1 (NOT %l!),
// and performs a dde transaction, so we are pretty much stuck with the "file:%1,,-1,,,,," string now.
//
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMShell, "", REG_SZ, sizeof(c_szOpenNew), c_szOpenNew },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpen, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_OPENSAME)},
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTMOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMShell, "", REG_SZ, sizeof(c_szOpenNew), c_szOpenNew },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNew, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_OPEN)},
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTMOpenNewCmd, "", REG_SZ, (LPARAM)" %1", HTReg_IEPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNewDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default},
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNewDdeIfExec, "", REG_SZ, sizeof("*"), "*"},
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNewDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNewDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMOpenNewDdeTopic, "", REG_SZ, sizeof("WWW_OpenURLNewWindow"), "WWW_OpenURLNewWindow" },
// .mht, .mhtml
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpen, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_OPENSAME)},
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szMHTMOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szMHTMOpenDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNew, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_OPEN)},
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szMHTMOpenNewCmd, "", REG_SZ, (LPARAM)" %1", HTReg_IEPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeIfExec, "", REG_SZ, sizeof("*"), "*"},
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeApp, "", REG_SZ, sizeof(IEXPLORE_APP), IEXPLORE_APP },
{ RC_ADD, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeTopic, "", REG_SZ, sizeof("WWW_OpenURLNewWindow"), "WWW_OpenURLNewWindow" },
// Internet shortcut
{ RC_ADD, REF_NORMAL, HKCR, c_szCLSIDURLRoot, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_THEINTERNET) },
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szIntShcutOpenCmd, "", REG_SZ, sizeof(c_szOpenURLNash), c_szOpenURLNash },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutOpen, "CLSID", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutOpen, "LegacyDisable", REG_SZ, 1, ""},
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutCMHandler, "", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutMayChange, "", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutPropHandler, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
// add ourselves to the applications key
{ RC_CALLBACK, REF_NORMAL, HKCR, "Applications\\iexplore.exe\\shell\\open\\command", "", REG_SZ, (LPARAM)" ""%1""", HTReg_IEPathProc},
// Other stuff
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szIEFrameAuto, "", REG_SZ, 0, HTReg_IEPathProc },
};
const RegSet c_rsAssoc_Full = {
ARRAYSIZE(c_rlAssoc_Full),
c_rlAssoc_Full
};
//
// On upgrading from Win9x to NT5, the icons are shifted to newly created
// file called "migicons.exe". This breaks our Assoc checks. Hence this is
// a list of all HTReg_UrlIconProc checks from the various Assoc arrays that
// MUST BELONG TO US FOR US TO BE DEFAULT BROWSER (REF_NOTNEEDED and
// REF_IFEMPTY ==> not used for check purposes).
// This list is used to fix the icons.
//
// NOTE: NOTE: NOTE: NOTE: NOTE: NOTE: NOTE:
// Any new Icon check that uses HTReg_UrlIconProc that gets added
// to any of the Assoc arrays and is REQUIRED for Default Browser check to
// succeed has to be added here also.
//
const RegEntry c_rlAssoc_FixIcon[] = {
// Icon checks from c_rlAssoc that are essential for us to be Default
// Browser
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szIntShcutDefIcon, "", REG_EXPAND_SZ, IDEFICON_STD, HTReg_UrlIconProc }
};
const RegSet c_rsAssoc_FixIcon = {
ARRAYSIZE(c_rlAssoc_FixIcon),
c_rlAssoc_FixIcon
};
//
// General browser-only settings
//
const CHAR c_szCLSIDMIME[] = "{FBF23B41-E3F0-101B-8488-00AA003E56F8}";
const CHAR c_szIEOnDesktop[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{FBF23B42-E3F0-101B-8488-00AA003E56F8}";
const CHAR c_szShellExecHook[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellExecuteHooks";
const CHAR c_szFileTypesHook[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileTypesPropertySheetHook";
const RegEntry c_rlGeneral_Alone[] = {
{ RC_ADD, REF_NORMAL, HKLM, c_szIEOnDesktop, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_THEINTERNET) },
{ RC_ADD, REF_NORMAL, HKLM, c_szFileTypesHook, "", REG_SZ, sizeof(c_szCLSIDMIME), c_szCLSIDMIME },
// URL Exec Hook (CLSID_URLExecHook) (this replaces the old overloaded intshcut CLSID)
{ RC_DEL, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDIntshcut, REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDURLExecHook, REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}", "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_URLEXECHOOK) },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}\\InProcServer32", "", REG_SZ, sizeof("url.dll"), "url.dll" },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}\\InProcServer32", "ThreadingModel", REG_SZ, sizeof("Apartment"), "Apartment" },
};
const RegSet c_rsGeneral_Alone = {
ARRAYSIZE(c_rlGeneral_Alone),
c_rlGeneral_Alone
};
//
// General full-shell only settings
//
const RegEntry c_rlGeneral_Full[] = {
{ RC_DEL, REF_NORMAL, HKLM, c_szIEOnDesktop, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NUKE, HKLM, c_szFileTypesHook, "", REG_SZ, sizeof(c_szCLSIDMIME), c_szCLSIDMIME },
// URL Exec Hook (this replaces the old overloaded intshcut CLSID)
{ RC_DEL, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDIntshcut, REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDURLExecHook, REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}", "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_URLEXECHOOK) },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}\\InProcServer32", "", REG_SZ, sizeof("shell32.dll"), "shell32.dll" },
{ RC_ADD, REF_NORMAL, HKCR, "CLSID\\{AEB6717E-7E19-11d0-97EE-00C04FD91972}\\InProcServer32", "ThreadingModel", REG_SZ, sizeof("Apartment"), "Apartment" },
};
const RegSet c_rsGeneral_Full = {
ARRAYSIZE(c_rlGeneral_Full),
c_rlGeneral_Full
};
// XP start menu
// Note: the IE start menu reg entries are created in ie.inx, this table is only needed
// to restore IE as default browser in the start menu (as a result of the user prompts)
const RegEntry c_rlStartMenu_XP[] = {
// make IE the default internet browser for this machine's Start Menu
{ RC_ADD, REF_NORMAL, HKLM, "Software\\Clients\\StartMenuInternet", "", REG_SZ, 0, "IEXPLORE.EXE" },
};
const RegSet c_rsStartMenu_XP = {
ARRAYSIZE(c_rlStartMenu_XP),
c_rlStartMenu_XP
};
const RegEntry c_rlStartMenu_XP_CU[] = {
// make IE the default internet browser for this user's Start Menu
{ RC_ADD, REF_NORMAL, HKCU, "Software\\Clients\\StartMenuInternet", "", REG_SZ, 0, "IEXPLORE.EXE" },
};
const RegSet c_rsStartMenu_XP_CU = {
ARRAYSIZE(c_rlStartMenu_XP_CU),
c_rlStartMenu_XP_CU
};
/*
* S P E C I A L D Y N A M I C S E T T I N G S
*
*/
#define SZ_EXMAILTO "Software\\Clients\\Mail\\Exchange\\Protocols\\Mailto"
const RegEntry c_rlExchange[] = {
{ RC_ADD, REF_NORMAL, HKLM, "Software\\Clients\\Mail\\Exchange", "", REG_SZ, 0, MAKEINTRESOURCE(IDS_EXCHANGE) },
{ RC_ADD, REF_IFEMPTY, HKLM, SZ_EXMAILTO, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_MAILTONAME) },
{ RC_ADD, REF_IFEMPTY, HKLM, SZ_EXMAILTO, "EditFlags", REG_DWORD, sizeof(c_dwEditFlags2), &c_dwEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKLM, SZ_EXMAILTO, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKLM, SZ_EXMAILTO "\\DefaultIcon", "", REG_EXPAND_SZ, IDEFICON_MAIL, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKLM, SZ_EXMAILTO "\\Shell\\Open\\Command", "", REG_SZ, sizeof(c_szMailToHandler), c_szMailToHandler },
};
const RegSet c_rsExchange = {
ARRAYSIZE(c_rlExchange),
c_rlExchange
};
#ifdef UNIX
const RegEntry c_rlAthena[] = {
#else
const RegList c_rlAthena = {
#endif
{ RC_CALLBACK, REF_NORMAL, HKLM, "", "", REG_SZ, (LPARAM)&c_rsExchange, HTReg_ExchangeProc },
};
const RegSet c_rsAthena = {
ARRAYSIZE(c_rlAthena),
c_rlAthena
};
/*
* U N I N S T A L L S E T T I N G S
*
*/
// Protocol-specific uninstall (for both full-shell and browser-only)
const RegEntry c_rlUnHTTP[] = {
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTP, "URL Protocol", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szHTTPOpenCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, c_szHTTP, "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnHTTP = {
ARRAYSIZE(c_rlUnHTTP),
c_rlUnHTTP
};
#ifdef UNIX
const RegEntry c_rlUnHTTPS[] = {
#else
const RegList c_rlUnHTTPS = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPS, "URL Protocol", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szHTTPSOpenCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, c_szHTTPS, "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnHTTPS = {
ARRAYSIZE(c_rlUnHTTPS),
c_rlUnHTTPS
};
#ifdef UNIX
const RegEntry c_rlUnFTP[] = {
#else
const RegList c_rlUnFTP = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szFTP, "URL Protocol", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szFTPOpenCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, c_szFTP, "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnFTP = {
ARRAYSIZE(c_rlUnFTP),
c_rlUnFTP
};
#ifdef UNIX
const RegEntry c_rlUnGopher[] = {
#else
const RegList c_rlUnGopher = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHER, "URL Protocol", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szGOPHEROpenCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, c_szGOPHER, "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnGopher = {
ARRAYSIZE(c_rlUnGopher),
c_rlUnGopher
};
#ifdef UNIX
const RegEntry c_rlUnHTM[] = {
#else
const RegList c_rlUnHTM = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szHTMOpenCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, "htmlfile", "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMDefIcon, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_EDITFLAGS, HKCR, "mhtmlfile", "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnHTM = {
ARRAYSIZE(c_rlUnHTM),
c_rlUnHTM
};
// Protocol-specific uninstall for full-shell
#ifdef UNIX
const RegEntry c_rlUnHTTP_Full[] = {
#else
const RegList c_rlUnHTTP_Full = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDdeexec, "NoActivateHandler", REG_SZ, 0, NULL }
};
const RegSet c_rsUnHTTP_Full = {
ARRAYSIZE(c_rlUnHTTP_Full),
c_rlUnHTTP_Full
};
#ifdef UNIX
const RegEntry c_rlUnHTTPS_Full[] = {
#else
const RegList c_rlUnHTTPS_Full = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDdeexec, "NoActivateHandler", REG_SZ, 0, NULL }
};
const RegSet c_rsUnHTTPS_Full = {
ARRAYSIZE(c_rlUnHTTPS_Full),
c_rlUnHTTPS_Full
};
#ifdef UNIX
const RegEntry c_rlUnFTP_Full[] = {
#else
const RegList c_rlUnFTP_Full = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet c_rsUnFTP_Full = {
ARRAYSIZE(c_rlUnFTP_Full),
c_rlUnFTP_Full
};
#ifdef UNIX
const RegEntry c_rlUnGopher_Full[] = {
#else
const RegList c_rlUnGopher_Full = {
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet c_rsUnGopher_Full = {
ARRAYSIZE(c_rlUnGopher_Full),
c_rlUnGopher_Full
};
#ifdef UNIX
const RegEntry c_rlUnHTM_Full[] = {
#else
const RegList c_rlUnHTM_Full = {
// remove the default context menu items
#endif
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMShell, NULL, REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMShell, NULL, REG_SZ, 0, NULL },
// remove the default values
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenNew, NULL, REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMOpenNew, NULL, REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenNewDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenNewDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenNewDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMOpenNewDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szHTMOpenNewCmd, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szMHTMOpenNewDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szMHTMOpenNewCmd, "", REG_SZ, 0, NULL },
};
const RegSet c_rsUnHTM_Full = {
ARRAYSIZE(c_rlUnHTM_Full),
c_rlUnHTM_Full
};
//
// Browser-only uninstall
//
#ifdef UNIX
const RegEntry c_rlUninstall_Alone[] = {
#else
const RegList c_rlUninstall_Alone = {
#endif
{ RC_DEL, REF_NORMAL, HKLM, c_szIEOnDesktop, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_THEINTERNET) },
{ RC_DEL, REF_PRUNE, HKCR, c_szIENameSpaceOpen, "", REG_SZ, 0, NULL },
// InternetShortcut
{ RC_DEL, REF_NORMAL, HKCR, c_szIntShcutOpen, "CLSID", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
{ RC_DEL, REF_PRUNE, HKCR, c_szIntShcutCMHandler, "", REG_SZ, 1, "" },
{ RC_DEL, REF_PRUNE, HKCR, c_szIntshcutMayChange, "", REG_SZ, 1, "" },
{ RC_DEL, REF_PRUNE, HKCR, c_szIntShcutPropHandler, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
// Change the inprocserver after removing "MayChangeDefaultMenu" above.
// Do this so url.dll doesn't repatch the registry.
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "", REG_SZ, sizeof(c_szURL), c_szURL },
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szIntShcutOpenCmd, "", REG_SZ, sizeof(c_szOpenURL), c_szOpenURL },
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_BROWSERONLY, (LPARAM)&c_rsUnHTTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_BROWSERONLY, (LPARAM)&c_rsUnHTTPS, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_BROWSERONLY, (LPARAM)&c_rsUnFTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_BROWSERONLY, (LPARAM)&c_rsUnGopher, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_BROWSERONLY, (LPARAM)&c_rsUnHTM, HTReg_UninstallProc },
};
const RegSet c_rsUninstall_Alone = {
ARRAYSIZE(c_rlUninstall_Alone),
c_rlUninstall_Alone
};
//
// Full-shell uninstall
//
#ifdef UNIX
const RegEntry c_rlUninstall_Full[] = {
#else
const RegList c_rlUninstall_Full = {
#endif
// InternetShortcut
{ RC_DEL, REF_NORMAL, HKCR, c_szIntShcutOpen, "CLSID", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
{ RC_DEL, REF_NORMAL, HKCR, c_szIntShcutOpen, "LegacyDisable", REG_SZ, 1, ""},
{ RC_DEL, REF_PRUNE, HKCR, c_szIntShcutCMHandler, "", REG_SZ, 1, "" },
{ RC_DEL, REF_PRUNE, HKCR, c_szIntshcutMayChange, "", REG_SZ, 1, "" },
{ RC_DEL, REF_PRUNE, HKCR, c_szIntShcutPropHandler, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
// Change the inprocserver after removing "MayChangeDefaultMenu" above.
// Do this so url.dll doesn't repatch the registry.
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "", REG_SZ, sizeof(c_szURL), c_szURL },
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szIntShcutOpenCmd, "", REG_SZ, sizeof(c_szOpenURL), c_szOpenURL },
// Protocol associations
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTTP_Full, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTTPS_Full, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTTPS, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnFTP_Full, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnFTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnGopher_Full, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnGopher, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTM_Full, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_INTEGRATED, (LPARAM)&c_rsUnHTM, HTReg_UninstallProc },
};
const RegSet c_rsUninstall_Full = {
ARRAYSIZE(c_rlUninstall_Full),
c_rlUninstall_Full
};
/*
* D E F A U L T S E T O F R E G S E T S
*
*/
// Common association settings for both browser-only and full-shell
// This is the required set of entries to make IE be the default
// browser. Only used if the user hasn't turned this off.
const RegSet * const g_rgprsDefault[] = {
&c_rsAssoc,
&c_rsAssocHTM,
};
// Browser-only specific associations
const RegSet * const g_rgprsDefault_Alone[] = {
&c_rsAssoc_Alone,
};
// Browser-only specific associations for a quick check
const RegSet * const g_rgprsDefault_Quick[] = {
&c_rsAssoc_Quick,
};
// Full-shell specific associations
const RegSet * const g_rgprsDefault_Full[] = {
&c_rsAssoc_Full,
};
// This is the set of icon entries that need to be fixed in case of a
// Win9x to NT5 upgrade.
const RegSet * const g_rgprsDefault_FixIcon[] = {
&c_rsAssoc_FixIcon,
};
//
// Other registry settings
//
const RegSet * const g_rgprsIE30Only[] =
{
&c_rsGeneral_Alone,
&c_rsAthena,
};
const RegSet * const g_rgprsNashOnly[] =
{
&c_rsGeneral_Full,
&c_rsAthena,
};
const RegSet * const g_rgprsUninstallIE30[] =
{
&c_rsUninstall_Alone,
};
const RegSet * const g_rgprsUninstallNash[] =
{
&c_rsUninstall_Full,
};
/*----------------------------------------------------------
Purpose: Determine if a particular RegSet is installed
Returns:
Cond: --
*/
BOOL
IsRegSetInstalled(
IN const RegSet * prs)
{
BOOL bRet = FALSE;
UINT i;
HKEY hkey = NULL;
const RegEntry * pre;
CHAR szBuffer[1024]; // Registry Data Holder
CHAR szT[MAX_PATH + 20]; // Need a bit extra for pszIExpAppendage
DWORD dwType;
DWORD dwSize;
DWORD dwSizeExpect;
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
// Check each registry entry. Stop when we encounter the first
// entry which doesn't match (no need to waste time looking at
// other entries).
//
// In the debug build, we enumerate the whole list, so we can
// see all the differences at once.
//
#ifdef DEBUG
#define BAIL_OUT bRet = TRUE; continue
#else
#define BAIL_OUT goto Bail
#endif
for (i = 0; i < prs->cre; i++)
{
pre = &(prs->pre[i]);
// Is this regentry not needed, or can it be set by some third
// party?
if (IsFlagSet(pre->dwFlags, REF_NOTNEEDED))
{
// Yes; skip to next
continue;
}
// Does the key exist?
if (NO_ERROR != RegOpenKeyA(pre->hkeyRoot, pre->pszKey, &hkey))
{
// No; should it?
if (RC_DEL == pre->regcmd)
{
// No; skip to next
continue;
}
else
{
// Yes
DEBUG_CODE( TraceMsg(TF_REGCHECK, "%s doesn't exist and should", Dbg_RegStr(pre, szDbg)); )
BAIL_OUT;
}
}
// Yes; should it?
else if (RC_DEL == pre->regcmd && !*pre->pszValName)
{
// No
DEBUG_CODE( TraceMsg(TF_REGCHECK, "%s exists and shouldn't", Dbg_RegStr(pre, szDbg)); )
RegCloseKey(hkey);
BAIL_OUT;
}
// Does the value exist?
dwSize = SIZEOF(szBuffer);
if (NO_ERROR != RegQueryValueExA(hkey, pre->pszValName, NULL,
&dwType, (BYTE *)szBuffer, &dwSize))
{
// No; should it?
if (RC_DEL != pre->regcmd)
{
// Yes
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: RegQueryValueEx( %hs, %hs ) Failed", pre->pszKey, pre->pszValName);
RegCloseKey(hkey);
BAIL_OUT;
}
}
// Yes; should it?
else if (RC_DEL == pre->regcmd)
{
// No
ASSERT(pre->pszValName && *pre->pszValName);
DEBUG_CODE( TraceMsg(TF_REGCHECK, "%s exists and shouldn't",
Dbg_RegStr(pre, szDbg)); )
RegCloseKey(hkey);
BAIL_OUT;
}
RegCloseKey(hkey);
// Is this a value that cannot be stomped (ie, a 3rd party might have
// set its value, and that's okay with us)?
if (IsFlagSet(pre->dwFlags, REF_IFEMPTY))
{
// Yes; the existence of the value is good enough for us,
// skip to next
continue;
}
switch (pre->regcmd)
{
case RC_ADD:
case RC_RUNDLL:
if (dwType == REG_SZ)
{
LPCVOID pvValue;
// Is this a resource string?
if (0 == HIWORD64(pre->pvValue))
{
// Yes; load it
dwSizeExpect = LoadStringA(g_hinst, PtrToUlong(pre->pvValue), szT, SIZECHARS(szT));
// Add null and convert to bytes
dwSizeExpect = CbFromCchA(dwSizeExpect + 1);
pvValue = szT;
}
else
{
// No
ASSERT(pre->pvValue);
if (RC_RUNDLL == pre->regcmd)
{
wnsprintfA(szT, ARRAYSIZE(szT), RUNDLL_CMD_FMT, (LPSTR)pre->pvValue);
pvValue = szT;
// Add null and convert to bytes
dwSizeExpect = CbFromCchA(lstrlenA(szT) + 1);
}
else
{
pvValue = pre->pvValue;
if (0 == pre->DUMMYUNION_MEMBER(dwSize))
dwSizeExpect = (DWORD)CbFromCchA(lstrlenA((LPCSTR)pvValue) + 1);
else
dwSizeExpect = (DWORD)pre->DUMMYUNION_MEMBER(dwSize);
}
}
if (dwSize != dwSizeExpect)
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s string size is %d, expecting %d", Dbg_RegStr(pre, szDbg), dwSize, dwSizeExpect);
BAIL_OUT;
}
// Compare case-insensitive (otherwise we'd just use
// memcmp below)
if (0 != StrCmpNIA((LPSTR)pvValue, szBuffer, dwSize / SIZEOF(CHAR)))
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s string is \"%hs\", expecting \"%hs\"", Dbg_RegStr(pre, szDbg), szBuffer, pvValue);
BAIL_OUT;
}
}
else
{
// Non-string case
if (dwSize != pre->DUMMYUNION_MEMBER(dwSize))
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s size is %d, expecting %d", Dbg_RegStr(pre, szDbg), dwSize, pre->DUMMYUNION_MEMBER(dwSize));
BAIL_OUT;
}
if (0 != memcmp(pre->pvValue, (BYTE *)szBuffer, dwSize))
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s value is different, expecting %#08x", Dbg_RegStr(pre, szDbg), *(LPDWORD)pre->pvValue);
BAIL_OUT;
}
}
break;
case RC_CALLBACK:
{
RSPECPROC pfn = (RSPECPROC)pre->pvValue;
ASSERT(IS_VALID_CODE_PTR(pfn, RSPECPROC));
// If the callback returns false, it means we're not the
// default browser.
if ( !pfn(RSCB_QUERY, pre, szBuffer, dwSize) )
BAIL_OUT;
break;
}
case RC_DEL:
// Work is done before the switch statement. Do nothing here.
break;
default:
ASSERT(0);
TraceMsg(TF_ERROR, "IsRegSetInstalled: Unhandled Special Type");
break;
}
}
#ifdef DEBUG
// In the debug build, leaving the above loop with bRet == TRUE means
// something doesn't match, so we need to flip the boolean value.
bRet ^= TRUE;
#else
bRet = TRUE;
Bail:
#endif
return bRet;
}
/*----------------------------------------------------------
Purpose: Returns TRUE if the key is empty of all subkeys and
all (non-default) values.
If dwFlags has REF_EDITFLAGS set, then this function
ignores the EditFlags value.
Returns: see above
Cond: --
*/
BOOL
IsKeyPsuedoEmpty(
IN HKEY hkey,
IN LPCSTR pszSubKey,
IN DWORD dwFlags) // REF_ flags
{
BOOL bRet = FALSE;
DWORD dwRet;
HKEY hkeyNew;
dwRet = RegOpenKeyExA(hkey, pszSubKey, 0, KEY_READ, &hkeyNew);
if (NO_ERROR == dwRet)
{
DWORD ckeys;
DWORD cvalues;
// Are the any subkeys?
if (NO_ERROR == RegQueryInfoKey(hkeyNew, NULL, NULL, NULL, &ckeys,
NULL, NULL, &cvalues, NULL, NULL,
NULL, NULL) &&
0 == ckeys)
{
// No; how about non-default values?
DWORD dwRetDef = SHGetValueA(hkey, pszSubKey, "", NULL, NULL, NULL);
bRet = (0 == cvalues || (1 == cvalues && NO_ERROR == dwRetDef));
// Should we ignore edit flags?
if (!bRet && IsFlagSet(dwFlags, REF_EDITFLAGS))
{
// Yes
DWORD dwRetEdit = SHGetValueA(hkey, pszSubKey, "EditFlags", NULL, NULL, NULL);
bRet = ((1 == cvalues && NO_ERROR == dwRetEdit) ||
(2 == cvalues && NO_ERROR == dwRetEdit &&
NO_ERROR == dwRetDef));
}
}
RegCloseKey(hkeyNew);
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Prune the key of our keys and values. Walk back up
the tree and delete empty keys below us.
Returns:
Cond: --
*/
void
PruneKey(
IN HKEY hkeyRoot,
IN LPCSTR pszKey)
{
CHAR szPath[MAX_PATH];
ASSERT(hkeyRoot);
ASSERT(pszKey);
StrCpyNA(szPath, pszKey, ARRAYSIZE(szPath));
while (PathRemoveFileSpecA(szPath) && *szPath)
{
SHDeleteOrphanKeyA(hkeyRoot, szPath);
}
}
/*----------------------------------------------------------
Purpose: Install a regset (set of registry entries).
If bDontIntrude is TRUE , then behave such that any
REF_DONTINTRUDE entry is not forcefully installed (i.e., it
will only get installed if the key doesn't already
have a value in it).
Returns:
Cond: --
*/
BOOL
InstallRegSet(
IN const RegSet *prs,
IN BOOL bDontIntrude)
{
BOOL bRet = TRUE;
UINT i;
HKEY hkey;
const RegEntry * pre;
CHAR szBuffer[MAX_PATH + 20]; // Need additional space for pszIExpAppendage
DWORD dwSize;
LPCVOID pvValue;
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
/*
* Install each registry entry
*/
for (i = 0; i < prs->cre; i++)
{
pre = &(prs->pre[i]);
// Stomp on this value?
if (bDontIntrude && IsFlagSet(pre->dwFlags, REF_DONTINTRUDE))
continue;
if (IsFlagSet(pre->dwFlags, REF_IFEMPTY))
{
// No
if (NO_ERROR == RegOpenKeyA(pre->hkeyRoot, pre->pszKey, &hkey))
{
BOOL bSkip;
// Are we checking the default value?
if (0 == *pre->pszValName)
{
// Yes; check the size, because default values
// always exist with at least a null terminator.
dwSize = 0;
RegQueryValueExA(hkey, pre->pszValName, NULL, NULL, NULL, &dwSize);
bSkip = (1 < dwSize);
}
else
{
// No
bSkip = (NO_ERROR == RegQueryValueExA(hkey, pre->pszValName,
NULL, NULL, NULL, NULL));
}
RegCloseKey(hkey);
// Does it exist?
if (bSkip)
{
// Yes; skip it
DEBUG_CODE( TraceMsg(TF_REGCHECK, "%s already exists, skipping",
Dbg_RegStr(pre, szDbg)); )
continue;
}
}
}
switch (pre->regcmd)
{
case RC_ADD:
case RC_RUNDLL:
if (NO_ERROR != RegCreateKeyA(pre->hkeyRoot, pre->pszKey, &hkey))
{
TraceMsg(TF_ERROR, "InstallRegSet(): RegCreateKey(%hs) Failed", pre->pszKey);
bRet = FALSE;
}
else
{
// Is the value a resource string?
if (REG_SZ == pre->dwType && 0 == HIWORD64(pre->pvValue))
{
UINT idRes = PtrToUlong(pre->pvValue);
// Yes; load it
dwSize = LoadStringA(g_hinst, idRes, szBuffer, SIZECHARS(szBuffer));
// Add null and convert to bytes
dwSize = CbFromCchA(dwSize + 1);
pvValue = szBuffer;
}
else
{
// No
if (RC_RUNDLL == pre->regcmd)
{
ASSERT(pre->pvValue);
ASSERT(REG_SZ == pre->dwType);
wnsprintfA(szBuffer, ARRAYSIZE(szBuffer), RUNDLL_CMD_FMT, (LPSTR)pre->pvValue);
pvValue = szBuffer;
dwSize = CbFromCchA(lstrlenA(szBuffer) + 1);
}
else
{
// Normal case
pvValue = pre->pvValue;
if (0 == pre->DUMMYUNION_MEMBER(dwSize) && REG_SZ == pre->dwType)
dwSize = CbFromCchA(lstrlenA((LPCSTR)pvValue) + 1);
else
dwSize = pre->DUMMYUNION_MEMBER(dwSize);
}
}
ASSERT(0 < dwSize);
if (NO_ERROR != RegSetValueExA(hkey, pre->pszValName, 0, pre->dwType, (BYTE*)pvValue, dwSize))
{
TraceMsg(TF_ERROR, "InstallRegSet(): RegSetValueEx(%hs) Failed", pre->pszValName );
bRet = FALSE;
}
else
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Setting %s", Dbg_RegStr(pre, szDbg)); )
}
RegCloseKey(hkey);
}
break;
case RC_CALLBACK:
{
RSPECPROC pfn = (RSPECPROC)pre->pvValue;
ASSERT(IS_VALID_CODE_PTR(pfn, RSPECPROC));
pfn(RSCB_INSTALL, pre, NULL, 0);
break;
}
case RC_DEL:
// Delete the default value, a named value, or the key?
if (pre->pszValName == NULL)
{
// Default value
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Deleting default value %s", Dbg_RegStr(pre, szDbg)); )
SHDeleteValueA(pre->hkeyRoot, pre->pszKey, pre->pszValName);
}
else if (*pre->pszValName)
{
// Named value
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Deleting value %s", Dbg_RegStr(pre, szDbg)); )
SHDeleteValueA(pre->hkeyRoot, pre->pszKey, pre->pszValName);
}
else
{
// Key
if (IsFlagSet(pre->dwFlags, REF_NUKE))
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Deleting key %s", Dbg_RegStr(pre, szDbg)); )
SHDeleteKeyA(pre->hkeyRoot, pre->pszKey);
}
// If there are keys or values (other than the
// default value) that are set, then we don't want
// to delete either the default value or the
// key.
else if (IsKeyPsuedoEmpty(pre->hkeyRoot, pre->pszKey, pre->dwFlags))
{
// Delete the default value so SHDeleteOrphanKey
// will work
SHDeleteValueA(pre->hkeyRoot, pre->pszKey, "");
// Delete the EditFlags value? (Without the EditFlags,
// the user will not be able to specify associations
// for this class in the FileTypes dialog, b/c that
// dialog requires this value. So the rule is, this
// function will delete the EditFlags if there is
// nothing else in the key.)
if (IsFlagSet(pre->dwFlags, REF_EDITFLAGS))
{
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Deleting %s\\EditFlags", Dbg_RegStr(pre, szDbg)); )
SHDeleteValueA(pre->hkeyRoot, pre->pszKey, "EditFlags");
}
DEBUG_CODE( TraceMsg(TF_REGCHECK, "Deleting empty key %s", Dbg_RegStr(pre, szDbg)); )
SHDeleteOrphanKeyA(pre->hkeyRoot, pre->pszKey);
// Should we prune? (This mean we'll walk back up
// the tree and try deleting empty keys that lead
// to this key.)
if (IsFlagSet(pre->dwFlags, REF_PRUNE))
PruneKey(pre->hkeyRoot, pre->pszKey);
}
}
break;
default:
ASSERT(0);
TraceMsg(TF_ERROR, "InstallRegSet(): Unhandled Special Case");
break;
}
}
return bRet;
}
/****************************************************************************
FUNCTION: CenterWindow (HWND, HWND)
PURPOSE: Center one window over another
COMMENTS:
Dialog boxes take on the screen position that they were designed at,
which is not always appropriate. Centering the dialog over a particular
window usually results in a better position.
****************************************************************************/
BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
{
RECT rChild, rParent;
int wChild, hChild, wParent, hParent;
int wScreen, hScreen, xNew, yNew;
HDC hdc;
// Get the Height and Width of the child window
GetWindowRect (hwndChild, &rChild);
wChild = rChild.right - rChild.left;
hChild = rChild.bottom - rChild.top;
// Get the Height and Width of the parent window
GetWindowRect (hwndParent, &rParent);
wParent = rParent.right - rParent.left;
hParent = rParent.bottom - rParent.top;
// Get the display limits
hdc = GetDC (hwndChild);
if (hdc)
{
wScreen = GetDeviceCaps (hdc, HORZRES);
hScreen = GetDeviceCaps (hdc, VERTRES);
ReleaseDC (hwndChild, hdc);
}
else
{
wScreen = 0;
hScreen = 0;
}
// Calculate new X position, then adjust for screen
xNew = rParent.left + ((wParent - wChild) /2);
if (xNew < 0) {
xNew = 0;
} else if ((xNew+wChild) > wScreen) {
xNew = wScreen - wChild;
}
// Calculate new Y position, then adjust for screen
yNew = rParent.top + ((hParent - hChild) /2);
if (yNew < 0) {
yNew = 0;
} else if ((yNew+hChild) > hScreen) {
yNew = hScreen - hChild;
}
// Set it, and return
return SetWindowPos (hwndChild, NULL,
xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
/*----------------------------------------------------------
Purpose: Dialog proc
*/
BOOL_PTR
CALLBACK
AssociationDialogProc(HWND hdlg, UINT uMsg, WPARAM wparam, LPARAM lparam)
{
BOOL bMsgHandled = FALSE;
/* uMsg may be any value. */
/* wparam may be any value. */
/* lparam may be any value. */
switch (uMsg){
case WM_INITDIALOG:
CenterWindow( hdlg, GetDesktopWindow());
if (g_bRunOnNT5)
{
// Initialize Checkbox
// uncheck by default for the first time we show this dialog,
// user's action is required. we still persist user's last choice.
if (FALSE == SHRegGetBoolUSValue(REGSTR_PATH_MAIN, TEXT("ShowedCheckBrowser"),
FALSE, FALSE))
{
Button_SetCheck(GetDlgItem(hdlg, IDC_ASSOC_CHECK), FALSE);
// mark we have showed this dialog once.
LPTSTR sz = TEXT("Yes");
SHRegSetUSValue(REGSTR_PATH_MAIN, TEXT("ShowedCheckBrowser"), REG_SZ,
(LPBYTE)sz, CbFromCch(lstrlen(sz)+1), SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
}
else
{
Button_SetCheck(GetDlgItem(hdlg, IDC_ASSOC_CHECK), IsCheckAssociationsOn());
}
}
else
Button_SetCheck(GetDlgItem(hdlg, IDC_ASSOC_CHECK), IsCheckAssociationsOn());
bMsgHandled = TRUE;
break;
//
// MSN mucks with the registry in a way that causes IE to ask if it's the
// default browser. Then after they launch IE they maximize the active
// window. Since the default browsre dialog is active, it gets maximized.
// Handeling the WM_GETMINMAXINFO prevents this dialog from maximizing.
//
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
if (lpmmi)
{
RECT rc;
if (GetWindowRect(hdlg, &rc))
{
lpmmi->ptMaxSize.x = rc.right - rc.left;
lpmmi->ptMaxSize.y = rc.bottom - rc.top;
lpmmi->ptMaxPosition.x = rc.left;
lpmmi->ptMaxPosition.y = rc.top;
bMsgHandled = TRUE;
}
}
}
break;
case WM_COMMAND:
switch (LOWORD(wparam)) {
case IDYES:
case IDNO:
SetCheckAssociations( Button_GetCheck(GetDlgItem(hdlg, IDC_ASSOC_CHECK)) );
EndDialog( hdlg, LOWORD(wparam));
break;
}
default:
break;
}
return(bMsgHandled);
}
/*----------------------------------------------------------
Purpose: Asks the user whether to make IE be the default browser
*/
BOOL
AskUserShouldFixReg()
{
return IDYES == SHFusionDialogBoxParam(MLGetHinst(),
MAKEINTRESOURCE(IDD_ASSOC),
NULL,
AssociationDialogProc,
NULL);
}
HRESULT InstallFTPAssociations(void)
{
IFtpInstaller * pfi;
HRESULT hr = CoCreateInstance(CLSID_FtpInstaller, NULL, CLSCTX_INPROC_SERVER, IID_IFtpInstaller, (void **) &pfi);
if (SUCCEEDED(hr))
{
hr = pfi->MakeIEDefautlFTPClient();
pfi->Release();
}
else
{
// This may fail to create if FTP wasn't installed, which is
// a valid install case.
hr = S_OK;
}
return hr;
}
/*----------------------------------------------------------
Purpose: Install file and protocol association settings in
registry.
*/
HRESULT
InstallRegAssoc(
UINT nInstall, // One of PLATFORM_*
BOOL bDontIntrude) // TRUE: be non-intrusive
{
int i;
// Install associations common across both IE and Nashville
for (i = 0; i < ARRAYSIZE(g_rgprsDefault); i++)
InstallRegSet(g_rgprsDefault[i], bDontIntrude);
if (PLATFORM_UNKNOWN == nInstall)
{
nInstall = WhichPlatform();
}
switch (nInstall)
{
case PLATFORM_BROWSERONLY:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Alone); i++)
InstallRegSet(g_rgprsDefault_Alone[i], bDontIntrude);
break;
case PLATFORM_INTEGRATED:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Full); i++)
InstallRegSet(g_rgprsDefault_Full[i], bDontIntrude);
break;
default:
ASSERT(0);
break;
}
InstallFTPAssociations();
// Notify shell that the associations have changed.
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
return NOERROR;
}
/*----------------------------------------------------------
Purpose: Settings that can only be set after user confirmation.
*/
void
InstallAfterConfirmation(
BOOL bDontIntrude) // TRUE: be non-intrusive
{
// on XP, add IE to show up in the start menu as the Internet app
if (IsOS(OS_WHISTLERORGREATER))
{
// Try to set ourselves as the system default Start Menu web browser
if (InstallRegSet(&c_rsStartMenu_XP, bDontIntrude))
{
// If that succeeds, then clear the per-user setting and let
// the user float with the system default. This is necessary
// to allow downlevel browsers like Netscape to come in and
// take over the default browser and steal the user away from us.
// (We're so nice and accomodating. I bet they won't extend
// us the same courtesy!)
SHDeleteValue(HKEY_CURRENT_USER, TEXT("Software\\Clients\\StartMenuInternet"), NULL);
}
else
{
// We don't have permission to set the global browser, so set ourselves
// as the browser for this user.
InstallRegSet(&c_rsStartMenu_XP_CU, bDontIntrude);
}
SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)TEXT("Software\\Clients\\StartMenuInternet"));
}
}
/*----------------------------------------------------------
Purpose: Set the CheckAssocation setting in the registry
*/
void
SetCheckAssociations(
BOOL fCheck)
{
HKEY hk;
if (RegOpenKeyExA(HKEY_CURRENT_USER, c_szCheckAssnSwitch, 0, KEY_WRITE, &hk) == ERROR_SUCCESS) {
LPTSTR szStr;
DWORD dwSize;
if (fCheck)
szStr = TEXT("Yes");
else
szStr = TEXT("No");
dwSize = CbFromCch( lstrlen( szStr ) + 1 );
RegSetValueEx( hk, TEXT("Check_Associations"), 0, REG_SZ, (LPBYTE) szStr, dwSize );
RegCloseKey( hk );
}
}
/*----------------------------------------------------------
Purpose: Determines if the user has turned off the "check for
default browser" in the registry.
*/
BOOL IsCheckAssociationsOn()
{
BOOL rval = TRUE;
CHAR szBuf[20];
DWORD dwSize = sizeof(szBuf);
DWORD dwValType;
if (NO_ERROR == SHGetValueA(HKEY_CURRENT_USER, c_szCheckAssnSwitch,
"Check_Associations", &dwValType,
szBuf, &dwSize))
{
if ((dwValType == REG_SZ) && (dwSize < sizeof(szBuf))) {
if (StrCmpIA( szBuf, "No") == 0)
rval = FALSE;
}
}
return( rval );
}
/***********************************************************************
These routines are used to repair damage done to Internet Explorer's
settings by "Netscape Navigator" and "Netscape TuneUp For IE"
***********************************************************************/
//
// Prototype for advpack functions
//
HRESULT RunSetupCommand(HWND hWnd, LPCSTR szCmdName, LPCSTR szInfSection, LPCSTR szDir, LPCSTR lpszTitle, HANDLE *phEXE, DWORD dwFlags, LPVOID pvReserved);
//
// This flag tells us whether it's ok to used the
// cached BOOL for IsResetWebSettingsRequired.
//
BOOL g_fAlreadyCheckedForClobber = FALSE;
HRESULT RunSetupCommandW(HWND hWnd, LPCWSTR szCmdName, LPCWSTR szInfSection, LPCWSTR szDir, LPCWSTR lpszTitle, HANDLE *phEXE, DWORD dwFlags, LPVOID pvReserved)
{
CHAR szCmdNameA[MAX_PATH];
CHAR szInfSectionA[MAX_PATH];
CHAR szDirA[MAX_PATH];
SHUnicodeToAnsi(szCmdName,szCmdNameA,ARRAYSIZE(szCmdNameA));
SHUnicodeToAnsi(szInfSection,szInfSectionA,ARRAYSIZE(szInfSectionA));
SHUnicodeToAnsi(szDir,szDirA,ARRAYSIZE(szDirA));
ASSERT(NULL == pvReserved);
ASSERT(NULL == lpszTitle);
return RunSetupCommand(hWnd, szCmdNameA, szInfSectionA, szDirA, NULL, phEXE, dwFlags, NULL);
}
//
// Path to the inf file
//
#define IERESTORE_FILENAME TEXT("iereset.inf")
#define INF_PATH TEXT("inf")
//
// Names of the sections in our inf file
//
#define INFSECTION_HOMEPAGE TEXT("RestoreHomePage")
#define INFSECTION_SETTINGS TEXT("RestoreBrowserSettings")
#define IE_VERIFY_REGKEY TEXT("Software\\Microsoft\\Internet Explorer\\Main")
#define IE_VERIFY_REGVALUE TEXT("Default_Page_URL")
#define INFSECTION_VERIFY TEXT("Strings")
#define IE_VERIFY_INFKEY TEXT("START_PAGE_URL")
void GetIEResetInfFileName(LPWSTR pszBuffer)
{
TCHAR szWindowsDir[MAX_PATH];
if (NULL == pszBuffer)
return;
GetWindowsDirectory(szWindowsDir,ARRAYSIZE(szWindowsDir));
wnsprintfW(
pszBuffer,
MAX_PATH,
TEXT("%s\\%s\\%s"),
szWindowsDir,INF_PATH,IERESTORE_FILENAME);
return;
}
/*
* CheckIESettings
*
* This function will try to determine whether or not IE's settings
* have been clobbered by another browser.
*
* Returns S_OK if IE settings are intact.
* Returns S_FALSE if someone has mucked with the IE settings
* Returns E_FAIL on error
*
*/
HRESULT CheckWebSettings(void)
{
TCHAR szInfPath[MAX_PATH];
TCHAR szDataFromInf[MAX_PATH];
TCHAR szDataFromReg[MAX_PATH];
LONG retval;
HKEY hkey;
DWORD dwType;
DWORD dwSize = sizeof(szDataFromReg);
//
// Get the path to the inf file
//
GetIEResetInfFileName(szInfPath);
//
// Read the string from the inf file
//
retval = SHGetIniString(
INFSECTION_VERIFY,
IE_VERIFY_INFKEY,
szDataFromInf,
ARRAYSIZE(szDataFromInf),
szInfPath);
if (retval <= 0)
return E_FAIL;
//
// Open the corresponding key in the registry
//
retval = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
IE_VERIFY_REGKEY,
NULL,
KEY_READ,
&hkey);
if (retval != ERROR_SUCCESS)
return E_FAIL;
//
// Read the data from the registry
//
retval = RegQueryValueEx(
hkey,
IE_VERIFY_REGVALUE,
NULL,
&dwType,
(LPBYTE)szDataFromReg,
&dwSize);
if (retval != ERROR_SUCCESS)
{
RegCloseKey(hkey);
return E_FAIL;
}
ASSERT(dwType == REG_SZ);
RegCloseKey(hkey);
//
// Return S_OK if they match, S_FALSE if they don't
//
return StrCmp(szDataFromReg,szDataFromInf) ? S_FALSE : S_OK;
}
extern "C" BOOL IsResetWebSettingsRequired(void)
{
static BOOL fRequired;
if (!g_fAlreadyCheckedForClobber)
{
fRequired = (S_FALSE == CheckWebSettings());
g_fAlreadyCheckedForClobber = TRUE;
}
return fRequired;
}
HRESULT ResetWebSettingsHelper(BOOL fRestoreHomePage)
{
HRESULT hr;
TCHAR szTempPath[MAX_PATH];
TCHAR szInfPath[MAX_PATH];
GetTempPath(ARRAYSIZE(szTempPath),szTempPath);
GetIEResetInfFileName(szInfPath);
g_fAlreadyCheckedForClobber = FALSE;
//
// Run the main part of the inf file
//
hr = RunSetupCommandW(
NULL,
szInfPath,
INFSECTION_SETTINGS,
szTempPath,
NULL,
NULL,
RSC_FLAG_INF|RSC_FLAG_QUIET,
NULL);
//
// Also, reset their homepage if requested to do so
//
if (SUCCEEDED(hr) && fRestoreHomePage)
hr = RunSetupCommandW(
NULL,
szInfPath,
INFSECTION_HOMEPAGE,
szTempPath,
NULL,
NULL,
RSC_FLAG_INF|RSC_FLAG_QUIET,
NULL);
return hr;
}
//
// Dialog Procedure for the "reset web settings" dialog
//
// Return values are:
//
// -1 Something went wrong
// 0 The user changes his/her mind
// 1 We reset everything except the homepage
// 2 We reset everything including the homepage
//
BOOL_PTR CALLBACK ResetWebSettingsDlgProc(HWND hdlg, UINT uMsg, WPARAM wparam, LPARAM lparam)
{
switch (uMsg)
{
case WM_INITDIALOG:
CenterWindow(hdlg, GetDesktopWindow());
CheckDlgButton(hdlg,IDC_RESET_WEB_SETTINGS_HOMEPAGE,BST_CHECKED);
return TRUE;
case WM_COMMAND:
switch(LOWORD(wparam))
{
case IDYES:
{
HRESULT hr;
BOOL fResetHomePage = (BST_CHECKED == IsDlgButtonChecked(hdlg,IDC_RESET_WEB_SETTINGS_HOMEPAGE));
//
// Restore the settings to their IE defaults
//
hr = ResetWebSettingsHelper(fResetHomePage);
if (!IsIEDefaultBrowser())
{
InstallRegAssoc(WhichPlatform(), FALSE);
InstallAfterConfirmation(FALSE);
}
if (FAILED(hr))
EndDialog(hdlg, -1);
else if (fResetHomePage)
EndDialog(hdlg, 2);
else
EndDialog(hdlg, 1);
}
return TRUE;
case IDCANCEL:
case IDNO:
EndDialog(hdlg, 0);
return TRUE;
default:
return FALSE;
}
default:
return FALSE;
}
}
HRESULT ResetWebSettings(HWND hwnd, BOOL *pfChangedHomePage)
{
HRESULT hr;
if (pfChangedHomePage)
*pfChangedHomePage = FALSE;
switch (DialogBoxParam(
MLGetHinst(),
MAKEINTRESOURCE(IDD_RESET_WEB_SETTINGS),
hwnd,
ResetWebSettingsDlgProc,
NULL))
{
case -1:
hr = E_FAIL;
break;
case 0:
hr = S_FALSE;
break;
case 1:
hr = S_OK;
break;
case 2:
if (pfChangedHomePage)
*pfChangedHomePage = TRUE;
hr = S_OK;
break;
default:
ASSERT(0);
hr = E_FAIL;
break;
}
if (FAILED(hr))
{
MLShellMessageBox(
hwnd,
MAKEINTRESOURCE(IDS_RESET_WEB_SETTINGS_FAILURE),
MAKEINTRESOURCE(IDS_RESET_WEB_SETTINGS_TITLE),
MB_OK | MB_ICONEXCLAMATION);
}
else if (hr == S_OK)
{
MLShellMessageBox(
hwnd,
MAKEINTRESOURCE(IDS_RESET_WEB_SETTINGS_SUCCESS),
MAKEINTRESOURCE(IDS_RESET_WEB_SETTINGS_TITLE),
MB_OK | MB_ICONINFORMATION);
}
return hr;
}
void EnsureWebViewRegSettings()
{
// We do the following mini-check regardless of the user's settings,
// and for every window we open
if (!IsRegSetInstalled(&c_rsAssocHTM_WV))
InstallRegSet(&c_rsAssocHTM_WV, FALSE);
}
void FixIcons()
{
int i;
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_FixIcon); i++)
{
// 2nd param FALSE ==> always intrude.
InstallRegSet(g_rgprsDefault_FixIcon[i], FALSE);
}
}
/*----------------------------------------------------------
Purpose: Function that determines if we are the default browser.
If not the default browser, this function will
ask the user to if they want to become the default
browser and make those changes.
*/
void
DetectAndFixAssociations()
{
TraceMsg(TF_REGCHECK, "Performing expensive registry query for default browser!");
// We will become the Default browser if:
// 1. The User has "Check Associations" On,
// 2. We don't own the associations, and
// 3. The user said Yes when we displayed the dialog.
if (IsCheckAssociationsOn() &&
!IsIEDefaultBrowser() &&
AskUserShouldFixReg())
{
InstallRegAssoc(WhichPlatform(), FALSE);
InstallAfterConfirmation(FALSE);
}
}
/*
A really quick - non - through check to see if IE is likely the
default browser
*/
BOOL IsIEDefaultBrowserQuick(void)
{
int i;
BOOL bAssociated = TRUE;
TraceMsg(TF_REGCHECK, "Performing expensive registry query for default browser!");
// Check the settings common to all platforms
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Quick); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault_Quick[i]))
bAssociated = FALSE;
}
return bAssociated;
}
/*----------------------------------------------------------
Purpose: Function that determines if we are the default browser.
*/
BOOL
IsIEDefaultBrowser(void)
{
int i;
BOOL bAssociated = TRUE;
UINT nInstall = WhichPlatform();
TraceMsg(TF_REGCHECK, "Performing expensive registry query for default browser!");
// Check the settings common to all platforms
for (i = 0; i < ARRAYSIZE(g_rgprsDefault); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault[i]))
bAssociated = FALSE;
}
if (bAssociated)
{
// Check specific to IE or Nashville
switch (nInstall)
{
case PLATFORM_BROWSERONLY:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Alone); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault_Alone[i]))
{
bAssociated = FALSE;
break;
}
}
break;
case PLATFORM_INTEGRATED:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Full); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault_Full[i]))
{
bAssociated = FALSE;
break;
}
}
break;
default:
ASSERT(0);
break;
}
}
// If IE is the default browser and this was an NT5Upgrade scenario,
// fix the Icons references.
if (g_bNT5Upgrade && bAssociated)
{
FixIcons();
}
return bAssociated;
}
/*----------------------------------------------------------
Purpose: Checks if we're installing over IE. This function
looks at the associated shell\open\command handler
for the http protocol.
Returns: TRUE if we're installing over IE
*/
BOOL
AreWeInstallingOverIE(void)
{
BOOL bRet = FALSE;
CHAR sz[MAX_PATH + 20]; // add some padding for arguments
DWORD cbData = SIZEOF(sz);
if (NO_ERROR == SHGetValueA(HKEY_CLASSES_ROOT, c_szHTTPOpenCmd, "",
NULL, sz, &cbData) &&
StrStrIA(sz, IEXPLORE_EXE) || StrStrIA(sz, EXPLORER_EXE))
{
TraceMsg(TF_REGCHECK, "Installing over IEXPLORE.EXE");
bRet = TRUE;
}
return bRet;
}
#if 0
BOOL ShouldIEBeDefaultBrowser(void)
{
BOOL bRet = TRUE; // default to TRUE (eg take over the association)
CHAR sz[MAX_PATH] = "";
DWORD cchData = ARRAYSIZE(sz);
if (SUCCEEDED(AssocQueryStringA(0, ASSOCSTR_COMMAND, ".htm", NULL, sz, &cchData)))
{
if (sz[0] && !StrStrIA(sz, IEXPLORE_EXE))
{
TraceMsg(TF_REGCHECK, "%s is the default browser (NOT iexplore.exe)", sz);
bRet = FALSE;
}
else
{
// if sz[0] is NULL, (probably broken reg) - Let IE be the Default Browser.
// or IE may be the Default browser setting.
TraceMsg(TF_REGCHECK, "IEXPLORE.EXE is assumed to be the default browser");
}
}
else
{
//May be a Broken Registry - Default to IE.
TraceMsg(TF_REGCHECK, "IEXPLORE.EXE is assumed to be the default browser due to broken Association");
}
return bRet;
}
#else
BOOL ShouldIEBeDefaultBrowser(void)
{
BOOL bRet = TRUE; // default to TRUE (eg take over the association)
CHAR sz[MAX_PATH + 20]; // add some padding for arguments
DWORD cbData = ARRAYSIZE(sz);
sz[0] = '\0';
if (NO_ERROR == SHGetValueA(HKEY_CLASSES_ROOT, ".htm", "", NULL, sz, &cbData))
{
if (!sz[0])
{
// null key so return TRUE
return bRet;
}
else if (!StrCmpIA(sz, "htmlfile"))
{
// Maybe, make sure further
sz[0] = '\0';
cbData = ARRAYSIZE(sz);
if (NO_ERROR == SHGetValueA(HKEY_CLASSES_ROOT, c_szHTMOpenCmd, "",
NULL, sz, &cbData))
{
if (!sz[0] || // if sz[0] is NULL, we will take it over (probably broken reg)
StrStrIA(sz, IEXPLORE_EXE))
{
// Default browser was IE, so we return TRUE
TraceMsg(TF_REGCHECK, "IEXPLORE.EXE is the default browser");
}
else
{
TraceMsg(TF_REGCHECK, "%s is the default browser (NOT iexplore.exe)", sz);
bRet = FALSE;
}
}
}
else
{
// the progid does not point to "htmlfile", so IE cant be the default browser
TraceMsg(TF_REGCHECK, "%s is the .htm progid (NOT htmlfile)", sz);
bRet = FALSE;
}
}
// .htm progid key does not exist, so we return TRUE
return bRet;
}
#endif
#define SZ_REGKEY_FTPSHELLOPEN TEXT("ftp\\shell\\open")
#define SZ_REGKEY_COMMAND TEXT("command")
#define SZ_REGKEY_DDEEXEC TEXT("ddeexec\\ifExec")
#define SZ_IEXPLORE_FTP_NEW TEXT("iexplore.exe\" %1")
#define SZ_IEXPLORE_FTP_OLD TEXT("iexplore.exe\" -nohome")
HRESULT UpgradeSettings(void)
{
HRESULT hr = S_OK;
HKEY hKey;
LONG lRet = RegOpenKey(HKEY_CLASSES_ROOT, SZ_REGKEY_FTPSHELLOPEN, &hKey);
hr = HRESULT_FROM_WIN32(lRet);
if (hKey)
{
TCHAR szData[MAX_PATH];
LONG cbSize = sizeof(szData);
lRet = RegQueryValue(hKey, SZ_REGKEY_COMMAND, szData, &cbSize);
hr = HRESULT_FROM_WIN32(lRet);
if (SUCCEEDED(hr))
{
DWORD cchStart = (lstrlen(szData) - ARRAYSIZE(SZ_IEXPLORE_FTP_OLD) + 1);
// Do we own it?
if (0 == StrCmp(SZ_IEXPLORE_FTP_OLD, &szData[cchStart]))
{
// Yes, so we can upgrade it.
// Buffer Overflow isn't a problem because I know SZ_IEXPLORE_FTP_NEW is smaller
// than SZ_IEXPLORE_FTP_OLD.
StrCpyN(&szData[cchStart], SZ_IEXPLORE_FTP_NEW, ARRAYSIZE(szData));
// Yes, so let's upgrade.
lRet = RegSetValue(hKey, SZ_REGKEY_COMMAND, REG_SZ, szData, lstrlen(szData));
hr = HRESULT_FROM_WIN32(lRet);
if (SUCCEEDED(hr))
{
lRet = RegSetValue(hKey, SZ_REGKEY_DDEEXEC, REG_SZ, TEXT(""), ARRAYSIZE(TEXT("")));
hr = HRESULT_FROM_WIN32(lRet);
}
}
}
RegCloseKey(hKey);
}
return hr;
}
/*----------------------------------------------------------
Purpose: Install registry info based upon which shell we're running
*/
HRESULT InstallIEAssociations(DWORD dwFlags) // IEA_* flags
{
int i;
UINT nInstall = WhichPlatform();
BOOL bDontIntrude = TRUE;
// If IE was the default browser before (or the registry is messed up)
// or setup is forcing us to register then we want to force IE to be
// the default browser
if (ShouldIEBeDefaultBrowser() || IsFlagSet(dwFlags, IEA_FORCEIE))
bDontIntrude = FALSE;
// Install file and protocol associations
InstallRegAssoc(nInstall, bDontIntrude);
// Install other registry settings
switch (nInstall)
{
case PLATFORM_BROWSERONLY:
for (i = 0; i < ARRAYSIZE(g_rgprsIE30Only); i++)
{
InstallRegSet(g_rgprsIE30Only[i], bDontIntrude);
}
break;
case PLATFORM_INTEGRATED:
for (i = 0; i < ARRAYSIZE(g_rgprsNashOnly); i++)
{
InstallRegSet(g_rgprsNashOnly[i], bDontIntrude);
}
break;
default:
ASSERT(0);
break;
}
InstallFTPAssociations();
return NOERROR;
}
HRESULT UninstallPlatformRegItems(BOOL bIntegrated)
{
int i;
UINT uPlatform = bIntegrated ? PLATFORM_INTEGRATED : PLATFORM_BROWSERONLY;
switch (uPlatform)
{
case PLATFORM_BROWSERONLY:
for (i = 0; i < ARRAYSIZE(g_rgprsUninstallIE30); i++)
{
InstallRegSet(g_rgprsUninstallIE30[i], FALSE);
}
break;
case PLATFORM_INTEGRATED:
for (i = 0; i < ARRAYSIZE(g_rgprsUninstallNash); i++)
{
InstallRegSet(g_rgprsUninstallNash[i], FALSE);
}
break;
default:
// Don't do anything
break;
}
return NOERROR;
}
void UninstallCurrentPlatformRegItems()
{
CHAR sz[MAX_PATH + 20]; // add some padding for arguments
DWORD cbData = SIZEOF(sz);
if (NO_ERROR == SHGetValueA(HKEY_CLASSES_ROOT, c_szHTMOpenNewCmd, "",
NULL, sz, &cbData))
{
// Remove IE4 shell integrated settings
UninstallPlatformRegItems(TRUE);
}
else if (AreWeInstallingOverIE())
{
// Remove IE3 / browser only settings
UninstallPlatformRegItems(FALSE);
}
}