Windows2000/private/shell/shdocvw/htregmng.c.1475
2020-09-30 17:12:32 +02:00

2244 lines
77 KiB
Plaintext

/*
* Registry Management
*
* HTREGMNG.C
*
* Copyright (c) 1995 Microsoft Corporation
*
*/
#include "priv.h"
#include "htregmng.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.
//
//
// Make the tables more compact
#define HKCR HKEY_CLASSES_ROOT
#define HKLM HKEY_LOCAL_MACHINE
#define HKCU HKEY_CURRENT_USER
BOOL InstallRegSet(const RegSet *prs, BOOL bDontIntrude);
const CHAR c_szIexploreKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE";
#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];
ASSERT(pre);
ASSERT(pszBuf);
if (HKEY_CLASSES_ROOT == pre->hkeyRoot)
{
lstrcpy(szRoot, TEXT("HKCR"));
}
else if (HKEY_CURRENT_USER == pre->hkeyRoot)
{
lstrcpy(szRoot, TEXT("HKCU"));
}
else if (HKEY_LOCAL_MACHINE == pre->hkeyRoot)
{
lstrcpy(szRoot, TEXT("HKLM"));
}
else
{
lstrcpy(szRoot, TEXT("????"));
ASSERT(0);
}
wsprintf(pszBuf, TEXT("%s\\%hs\\%hs"), szRoot, pre->pszKey, pre->pszValName);
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
GetIEPath(
OUT LPSTR pszBuf,
IN DWORD cchBuf)
{
BOOL bRet = FALSE;
HKEY hkey;
*pszBuf = '\0';
// Get the path of Internet Explorer
if (NO_ERROR != RegOpenKey(HKEY_LOCAL_MACHINE, c_szIexploreKey, &hkey))
{
TraceMsg(TF_ERROR, "InstallRegSet(): RegOpenKey( %s ) Failed", c_szIexploreKey) ;
}
else
{
DWORD cbBrowser;
DWORD dwType;
lstrcatA(pszBuf, "\"");
cbBrowser = CbFromCchA(cchBuf - lstrlen(" -nohome") - 4);
if (NO_ERROR != RegQueryValueExA(hkey, "", NULL, &dwType,
(LPBYTE)&pszBuf[1], &cbBrowser))
{
TraceMsg(TF_ERROR, "InstallRegSet(): RegQueryValueEx() for Iexplore path failed");
}
else
{
bRet = TRUE;
}
lstrcatA(pszBuf, "\"");
RegCloseKey(hkey);
}
return bRet;
}
/*----------------------------------------------------------
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)
{
BOOL bRet;
// Get the path of the Explorer
if (g_fRunningOnNT)
{
lstrcpyA (pszBuf, "%SystemRoot%");
bRet = TRUE;
}
else
bRet = (0 < GetWindowsDirectoryA(pszBuf, cchBuf));
if (bRet)
{
lstrcatA(pszBuf, "\\Explorer.exe");
}
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);
/*----------------------------------------------------------
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 = pvData;
int cch;
DWORD dwType; //local type.
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
switch (nMsg)
{
case RSCB_QUERY:
if (g_fRunningOnNT)
lstrcpyA (sz, "%SystemRoot%\\system32");
else
GetSystemDirectoryA(sz, SIZECHARS(sz));
cch = lstrlenA(sz);
wsprintfA(&sz[cch], "\\URL.DLL,%u", (UINT)pre->lParam);
if (0 != lstrnicmpA(sz, pszPath, dwData / SIZEOF(CHAR)) &&
0 != lstrcmpiA(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:
ASSERT(REG_SZ == pre->dwType);
if (g_fRunningOnNT)
lstrcpyA (sz, "%SystemRoot%\\system32");
else
GetSystemDirectoryA(sz, SIZECHARS(sz));
cch = lstrlenA(sz);
wsprintfA(&sz[cch], "\\URL.DLL,%u", (UINT)pre->lParam);
dwType = g_fRunningOnNT ? REG_EXPAND_SZ : (DWORD)pre->dwType;
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
LPCSTR pszPath = pvData;
int cch;
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
switch (nMsg)
{
case RSCB_QUERY:
if (GetIEPath(sz, SIZECHARS(sz)))
{
cch = lstrlenA(sz) - 1;
if (*sz && sz[cch] == ';')
sz[cch] = '\0';
if (pre->lParam)
lstrcatA(sz, (LPSTR)pre->lParam);
if (0 != lstrnicmpA(pszPath, sz, 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 (GetIEPath(sz, SIZECHARS(sz)))
{
DWORD dwType;
cch = lstrlenA(sz) - 1;
if (*sz && sz[cch] == ';')
sz[cch] = '\0';
if (pre->lParam)
lstrcatA(sz, (LPTSTR)pre->lParam);
ASSERT(REG_SZ == pre->dwType);
dwType = g_fRunningOnNT ? REG_EXPAND_SZ : (DWORD)pre->dwType;
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 sets the Explorer path.
Returns: varies
Cond: --
*/
BOOL
CALLBACK
HTReg_ShellPathProc(
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 = pvData;
DEBUG_CODE( TCHAR szDbg[MAX_PATH]; )
ASSERT(RSCB_QUERY == nMsg && pvData ||
RSCB_INSTALL == nMsg && !pvData);
switch (nMsg)
{
case RSCB_QUERY:
if (GetExplorerPath(sz, SIZECHARS(sz)))
{
if (pre->lParam)
lstrcatA(sz, (LPSTR)pre->lParam);
if (0 != lstrnicmpA(pszPath, sz, 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 (GetExplorerPath(sz, SIZECHARS(sz)))
{
DWORD dwType;
if (pre->lParam)
lstrcatA(sz, (LPTSTR)pre->lParam);
ASSERT(REG_SZ == pre->dwType);
dwType = g_fRunningOnNT ? REG_EXPAND_SZ : (DWORD)pre->dwType;
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!
lstrcpy(szT, sz);
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->lParam)
InstallRegSet((const RegSet *)pre->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;
LPCTSTR pszExe;
// HACKHACK: we overload dwType to indicate the platform that
// we are uninstalling.
if (PLATFORM_NASH == pre->dwType)
pszExe = TEXT("explorer.exe");
else
pszExe = TEXT("iexplore.exe");
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 "iexplore.exe"?
wsprintf(szKey, TEXT("%hs\\shell\\open\\command"), pre->pszKey);
cbSize = sizeof(sz);
if (NO_ERROR == SHGetValue(pre->hkeyRoot, szKey, TEXT(""),
NULL, sz, &cbSize) &&
StrStrI(sz, pszExe))
{
// Yes; proceed to prune this key of all of our values
TraceMsg(TF_REGCHECK, "Pruning HKCR\\%hs", pre->pszKey);
ASSERT(pre->lParam);
InstallRegSet((const RegSet *)pre->lParam, FALSE);
}
break;
}
return TRUE;
}
// NOTE: these are ANSI strings by design.
const INT vEditFlags2 = 0x02;
const INT vEditFlagsSafe = 0x010002;
const DWORD c_dwFaveAttr = 0xe0000000;
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[] = "shell32.dll,OpenURL %l";
const CHAR c_szURL[] = "url.dll";
const CHAR c_szShell32[] = "shell32.dll";
const CHAR c_szAlphaNashOnDesktop[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace\\{3DC7A020-0ACD-11CF-A9BB-00AA004AE837}";
const CHAR c_szCheckAssnSwitch[] = "Software\\Microsoft\\Internet Explorer\\Main";
const CHAR c_szDDE_Default[] = "\"%1\",,-1,,,,,";
const CHAR c_szDDE_FileDefault[] = "\"file:%1\",,-1,,,,,";
const CHAR c_szViewFolderTemp[] = "[ViewFolder(\"%l\",\"%l\",%S)]";
const CHAR c_szExploreFolderTemp[] = "[ExploreFolder(\"%l\",\"%l\",%S)]";
const CHAR c_szViewAppendage[] = " /idlist,%l,%L";
const CHAR c_szExploreAppendage[] = " /e,/idlist,%l,%L";
// BUGBUG (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_szHTTPDdeIfExec[] = "http\\shell\\open\\ddeexec\\IfExec";
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_szHTTPSDdeIfExec[] = "https\\shell\\open\\ddeexec\\IfExec";
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_szFTPDdeIfExec[] = "ftp\\shell\\open\\ddeexec\\IfExec";
const CHAR c_szFTPDdeApp[] = "ftp\\shell\\open\\ddeexec\\Application";
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_szGOPHERDdeIfExec[] = "gopher\\shell\\open\\ddeexec\\IfExec";
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_szFileDdeexec[] = "file\\shell\\open\\ddeexec";
const CHAR c_szFileDdeTopic[] = "file\\shell\\open\\ddeexec\\Topic";
const CHAR c_szFileDdeIfExec[] = "file\\shell\\open\\ddeexec\\IfExec";
const CHAR c_szFileDdeApp[] = "file\\shell\\open\\ddeexec\\Application";
const CHAR c_szHTMOpenCmd[] = "htmlfile\\shell\\open\\command";
const CHAR c_szHTMDdeexec[] = "htmlfile\\shell\\open\\ddeexec";
const CHAR c_szHTMDdeTopic[] = "htmlfile\\shell\\open\\ddeexec\\Topic";
const CHAR c_szHTMDdeIfExec[] = "htmlfile\\shell\\open\\ddeexec\\IfExec";
const CHAR c_szHTMDdeApp[] = "htmlfile\\shell\\open\\ddeexec\\Application";
const CHAR c_szHTMExploreCmd[] = "htmlfile\\shell\\explore\\command";
const CHAR c_szHTMExploreDdeexec[] = "htmlfile\\shell\\explore\\ddeexec";
const CHAR c_szHTMExploreDdeTopic[] = "htmlfile\\shell\\explore\\ddeexec\\Topic";
const CHAR c_szHTMExploreDdeIfExec[] = "htmlfile\\shell\\explore\\ddeexec\\IfExec";
const CHAR c_szHTMExploreDdeApp[] = "htmlfile\\shell\\explore\\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_szCLSIDIntshcut[] = "{FBF23B40-E3F0-101B-8488-00AA003E56F8}";
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";
const CHAR c_szFaveShellFolder[] = "CLSID\\{1A9BA3A0-143A-11CF-8350-444553540000}\\ShellFolder";
//
// General associations shared across IE 3.0 and 4.0
//
const RegList g_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_BINARY, sizeof(vEditFlags2), (LPVOID) &vEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTP, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szHTTPDefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPS, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szHTTPSDefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTP, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szFTPDefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHER, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szGOPHERDefIcon, "", REG_SZ, 0, HTReg_UrlIconProc },
// File protocol
{ RC_ADD, REF_NORMAL, HKCR, c_szFile, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_FILENAME) },
{ RC_ADD, REF_NORMAL, HKCR, c_szFile, "EditFlags", REG_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_NORMAL, HKCR, c_szFile, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_NOTNEEDED, HKCR, c_szFileDefIcon, "", REG_SZ, 0, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szFileOpenCmd, "", REG_SZ, sizeof(c_szFileHandler), c_szFileHandler },
// Telnet
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_TELNETNAME) },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "EditFlags", REG_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTelnet, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szTelnetDefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szRLogin, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szRLoginDefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szTN3270, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szTN3270DefIcon, "", REG_SZ, 0, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szMailTo, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szMailToDefIcon, "", REG_SZ, 2, 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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKCR, c_szNews, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKCR, c_szNewsDefIcon, "", REG_SZ, 1, 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_BINARY, sizeof(vEditFlagsSafe), (LPSTR) &vEditFlagsSafe },
{ 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_SZ, 0, 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, "ThreadingModel", REG_SZ, sizeof("Apartment"), "Apartment" },
};
const RegSet g_rsAssoc = {
ARRAYSIZE(g_rlAssoc),
g_rlAssoc
};
//
// .htm, .html assocations for IE 3.0 and IE 4.0
//
// This is run when the browser is opened, and considered a requirement
// to make IE be the default browser.
const RegList g_rlAssocHTM = {
// .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 g_rsAssocHTM = {
ARRAYSIZE(g_rlAssocHTM),
g_rlAssocHTM
};
// This is needed just to insure webview works.
//
const RegList g_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 g_rsAssocHTM_WV = {
ARRAYSIZE(g_rlAssocHTM_WV),
g_rlAssocHTM_WV
};
//
// IE 3.0 specific association settings
//
const RegList g_rlAssoc_IE = {
// 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"), "IExplore" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTTPDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
// 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"), "IExplore" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTTPSDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
// FTP
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szFTPOpenCmd, "", REG_SZ, (LPARAM)" -nohome", 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"), "IExplore" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szFTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_DEL, REF_NUKE, 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"), "IExplore" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szGOPHERDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_DEL, REF_NUKE, HKCR, c_szGOPHERDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
// .html
{ RC_CALLBACK, REF_DONTINTRUDE, HKCR, c_szHTMOpenCmd, "", REG_SZ, (LPARAM)" -nohome", HTReg_IEPathProc },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMDdeexec, "", REG_SZ, sizeof(c_szDDE_FileDefault), c_szDDE_FileDefault },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMDdeApp, "", REG_SZ, sizeof("IExplore"), "IExplore" },
{ RC_ADD, REF_DONTINTRUDE, HKCR, c_szHTMDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTMDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
// Other stuff
{ RC_RUNDLL, REF_NORMAL, HKCR, c_szIntShcutOpenCmd, "", REG_SZ, sizeof(c_szOpenURL), c_szOpenURL },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "", REG_SZ, sizeof(c_szURL), c_szURL },
{ 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 g_rsAssoc_IE = {
ARRAYSIZE(g_rlAssoc_IE),
g_rlAssoc_IE
};
//
// defaults in case INF defaults not present
//
const CHAR c_szDefaultHome[] = "Software\\Microsoft\\Internet Explorer\\Main";
const RegList g_rlPages_IE = {
{ RC_ADD, REF_IFEMPTY, HKCU, c_szDefaultHome, "Start Page", REG_SZ, 0, MAKEINTRESOURCE(IDS_DEF_HOME)},
{ RC_ADD, REF_IFEMPTY, HKCU, c_szDefaultHome, "Search Page", REG_SZ, 0, MAKEINTRESOURCE(IDS_DEF_SEARCH)},
};
const RegSet g_rsPages_IE = {
ARRAYSIZE (g_rlPages_IE),
g_rlPages_IE
};
//
// Nashville specific association settings
//
// BUGBUG (scotth): we are explicitly removing this because our beta1
// rollout to mscorp added it. Having ifexec breaks
// Netscape. We don't need to explicitly remove these
// values by RTM.
const RegList g_rlAssoc_Nash = {
// HTTP
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTTPOpenCmd, "", REG_SZ, (LPARAM)c_szViewAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPDdeApp, "", REG_SZ, sizeof("IExplore"), "IExplore" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTTPDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// HTTPS
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTTPSOpenCmd, "", REG_SZ, (LPARAM)c_szViewAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPSDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPSDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPSDdeApp, "", REG_SZ, sizeof("IExplore"), "IExplore" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTTPSDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTTPSDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// FTP
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szFTPOpenCmd, "", REG_SZ, (LPARAM)c_szViewAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTPDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTPDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTPDdeApp, "", REG_SZ, sizeof("IExplore"), "IExplore" },
{ RC_DEL, REF_NUKE, HKCR, c_szFTPDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szFTPDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// Gopher
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szGOPHEROpenCmd, "", REG_SZ, (LPARAM)c_szViewAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHERDdeexec, "", REG_SZ, sizeof(c_szDDE_Default), c_szDDE_Default },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHERDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHERDdeApp, "", REG_SZ, sizeof("IExplore"), "IExplore" },
{ RC_DEL, REF_NUKE, HKCR, c_szGOPHERDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szGOPHERDdeTopic, "", REG_SZ, sizeof("WWW_OpenURL"), "WWW_OpenURL" },
// File protocol
{ RC_ADD, REF_NORMAL, HKCR, c_szFileDdeexec, "", REG_SZ, sizeof(c_szViewFolderTemp), c_szViewFolderTemp },
{ RC_ADD, REF_NORMAL, HKCR, c_szFileDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szFileDdeApp, "", REG_SZ, sizeof("Folders"), "Folders" },
{ RC_ADD, REF_NORMAL, HKCR, c_szFileDdeTopic, "", REG_SZ, sizeof("AppProperties"), "AppProperties" },
// .htm
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTMOpenCmd, "", REG_SZ, (LPARAM)c_szViewAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMDdeexec, "", REG_SZ, sizeof(c_szViewFolderTemp), c_szViewFolderTemp },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMDdeApp, "", REG_SZ, sizeof("Folders"), "Folders" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTMDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMDdeTopic, "", REG_SZ, sizeof("AppProperties"), "AppProperties" },
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szHTMExploreCmd, "", REG_SZ, (LPARAM)c_szExploreAppendage, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMExploreDdeexec, "", REG_SZ, sizeof(c_szExploreFolderTemp), c_szExploreFolderTemp },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMExploreDdeexec, "NoActivateHandler", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMExploreDdeApp, "", REG_SZ, sizeof("Folders"), "Folders" },
{ RC_DEL, REF_NUKE, HKCR, c_szHTMExploreDdeIfExec, "", REG_SZ, sizeof("[]"), "[]" },
{ RC_ADD, REF_NORMAL, HKCR, c_szHTMExploreDdeTopic, "", REG_SZ, sizeof("AppProperties"), "AppProperties" },
// 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 },
// BUGBUG (scotth): remove this at RTM. Alpha 1 set this.
{ RC_DEL, REF_NORMAL, HKCR, c_szIntShcutOpen, "DontAddToMenu", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutCMHandler, "", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutInproc, "", REG_SZ, sizeof(c_szShell32), c_szShell32 },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntshcutMayChange, "", REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKCR, c_szIntShcutPropHandler, "", REG_SZ, sizeof(c_szCLSIDIntshcut), c_szCLSIDIntshcut },
// Other stuff
{ RC_CALLBACK, REF_NORMAL, HKCR, c_szIEFrameAuto, "", REG_SZ, 0, HTReg_ShellPathProc },
{ RC_ADD, REF_NORMAL, HKCR, c_szFaveShellFolder, "Attributes", REG_BINARY, SIZEOF(c_dwFaveAttr), (LPVOID) &c_dwFaveAttr },
};
const RegSet g_rsAssoc_Nash = {
ARRAYSIZE(g_rlAssoc_Nash),
g_rlAssoc_Nash
};
//
// General IE 3.0 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 RegList g_rlGeneral_IE = {
{ RC_ADD, REF_NORMAL, HKLM, c_szIEOnDesktop, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_THEINTERNET) },
{ RC_ADD, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDIntshcut, REG_SZ, 1, "" },
{ RC_ADD, REF_NORMAL, HKLM, c_szFileTypesHook, "", REG_SZ, sizeof(c_szCLSIDMIME), c_szCLSIDMIME },
};
const RegSet g_rsGeneral_IE = {
ARRAYSIZE(g_rlGeneral_IE),
g_rlGeneral_IE
};
//
// General Nashville-only settings
//
const RegList g_rlGeneral_Nash = {
{ RC_DEL, REF_NORMAL, HKLM, c_szIEOnDesktop, "", REG_SZ, 0, NULL },
{ RC_ADD, REF_NORMAL, HKLM, c_szShellExecHook, c_szCLSIDIntshcut, REG_SZ, 1, "" },
{ RC_DEL, REF_NUKE, HKLM, c_szFileTypesHook, "", REG_SZ, sizeof(c_szCLSIDMIME), c_szCLSIDMIME },
{ RC_DEL, REF_NUKE, HKLM, c_szAlphaNashOnDesktop, "", REG_SZ, 0, MAKEINTRESOURCE(IDS_REG_THEINTERNET) },
};
const RegSet g_rsGeneral_Nash = {
ARRAYSIZE(g_rlGeneral_Nash),
g_rlGeneral_Nash
};
/*
* 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 RegList g_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_BINARY, sizeof(vEditFlags2), (LPSTR) &vEditFlags2 },
{ RC_ADD, REF_IFEMPTY, HKLM, SZ_EXMAILTO, "URL Protocol", REG_SZ, 1, "" },
{ RC_CALLBACK, REF_IFEMPTY, HKLM, SZ_EXMAILTO "\\DefaultIcon", "", REG_SZ, 2, HTReg_UrlIconProc },
{ RC_RUNDLL, REF_IFEMPTY, HKLM, SZ_EXMAILTO "\\Shell\\Open\\Command", "", REG_SZ, sizeof(c_szMailToHandler), c_szMailToHandler },
};
const RegSet g_rsExchange = {
ARRAYSIZE(g_rlExchange),
g_rlExchange
};
const RegList g_rlAthena = {
{ RC_CALLBACK, REF_NORMAL, HKLM, "", "", REG_SZ, (LPARAM)&g_rsExchange, HTReg_ExchangeProc },
};
const RegSet g_rsAthena = {
ARRAYSIZE(g_rlAthena),
g_rlAthena
};
/*
* U N I N S T A L L S E T T I N G S
*
*/
// Protocol-specific uninstall (for both IE 3.0 and 4.0)
const RegList g_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 g_rsUnHTTP = {
ARRAYSIZE(g_rlUnHTTP),
g_rlUnHTTP
};
const RegList g_rlUnHTTPS = {
{ 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 g_rsUnHTTPS = {
ARRAYSIZE(g_rlUnHTTPS),
g_rlUnHTTPS
};
const RegList g_rlUnFTP = {
{ 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 g_rsUnFTP = {
ARRAYSIZE(g_rlUnFTP),
g_rlUnFTP
};
const RegList g_rlUnGopher = {
{ 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 g_rsUnGopher = {
ARRAYSIZE(g_rlUnGopher),
g_rlUnGopher
};
const RegList g_rlUnHTM = {
{ RC_DEL, REF_NORMAL, HKCR, "htmlfile\\DefaultIcon", "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMDdeexec, "", 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 },
};
const RegSet g_rsUnHTM = {
ARRAYSIZE(g_rlUnHTM),
g_rlUnHTM
};
// Protocol-specific uninstall for Nashville
const RegList g_rlUnHTTP_Nash = {
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet g_rsUnHTTP_Nash = {
ARRAYSIZE(g_rlUnHTTP_Nash),
g_rlUnHTTP_Nash
};
const RegList g_rlUnHTTPS_Nash = {
{ RC_DEL, REF_NORMAL, HKCR, c_szHTTPSDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet g_rsUnHTTPS_Nash = {
ARRAYSIZE(g_rlUnHTTPS_Nash),
g_rlUnHTTPS_Nash
};
const RegList g_rlUnFTP_Nash = {
{ RC_DEL, REF_NORMAL, HKCR, c_szFTPDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet g_rsUnFTP_Nash = {
ARRAYSIZE(g_rlUnFTP_Nash),
g_rlUnFTP_Nash
};
const RegList g_rlUnGopher_Nash = {
{ RC_DEL, REF_NORMAL, HKCR, c_szGOPHERDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
};
const RegSet g_rsUnGopher_Nash = {
ARRAYSIZE(g_rlUnGopher_Nash),
g_rlUnGopher_Nash
};
const RegList g_rlUnHTM_Nash = {
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMExploreDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMExploreDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMExploreDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szHTMExploreDdeexec, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szHTMExploreCmd, "", REG_SZ, 0, NULL },
};
const RegSet g_rsUnHTM_Nash = {
ARRAYSIZE(g_rlUnHTM_Nash),
g_rlUnHTM_Nash
};
//
// IE 3.0 uninstall
//
const RegList g_rlUninstall_IE = {
{ 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 },
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_IE3, (LPARAM)&g_rsUnHTTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_IE3, (LPARAM)&g_rsUnHTTPS, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_IE3, (LPARAM)&g_rsUnFTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_IE3, (LPARAM)&g_rsUnGopher, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_IE3, (LPARAM)&g_rsUnHTM, HTReg_UninstallProc },
};
const RegSet g_rsUninstall_IE = {
ARRAYSIZE(g_rlUninstall_IE),
g_rlUninstall_IE
};
//
// Nashville uninstall
//
const RegList g_rlUninstall_Nash = {
// 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 },
// File protocol
{ RC_DEL, REF_NORMAL, HKCR, c_szFileDdeApp, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFileDdeTopic, "", REG_SZ, 0, NULL },
{ RC_DEL, REF_NORMAL, HKCR, c_szFileDdeexec, "NoActivateHandler", REG_SZ, 0, NULL },
{ RC_DEL, REF_PRUNE, HKCR, c_szFileDdeexec, "", REG_SZ, 0, NULL },
// Favorite folder
{ RC_DEL, REF_PRUNE, HKCR, c_szFaveShellFolder, "Attributes", REG_BINARY, SIZEOF(c_dwFaveAttr), (LPVOID) &c_dwFaveAttr },
// Protocol associations
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTTP_Nash, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "http", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTTPS_Nash, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "https", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTTPS, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_NASH, (LPARAM)&g_rsUnFTP_Nash, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "ftp", "", PLATFORM_NASH, (LPARAM)&g_rsUnFTP, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_NASH, (LPARAM)&g_rsUnGopher_Nash, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "gopher", "", PLATFORM_NASH, (LPARAM)&g_rsUnGopher, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTM_Nash, HTReg_UninstallProc },
{ RC_CALLBACK, REF_NORMAL, HKCR, "htmlfile", "", PLATFORM_NASH, (LPARAM)&g_rsUnHTM, HTReg_UninstallProc },
};
const RegSet g_rsUninstall_Nash = {
ARRAYSIZE(g_rlUninstall_Nash),
g_rlUninstall_Nash
};
/*
* D E F A U L T S E T O F R E G S E T S
*
*/
// Common association settings for both IE and Nashville
// 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.
const RegSet * g_rgprsWebview[] = {
&g_rsAssocHTM_WV,
};
// This is the minimum set that is queried every time a browser window
// opens (but not an explorer window).
const RegSet * g_rgprsMin_IE[] = {
&g_rsPages_IE,
};
// 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 * g_rgprsDefault[] = {
&g_rsAssoc,
&g_rsAssocHTM,
};
// IE 3.0 specific associations
const RegSet * g_rgprsDefault_IE[] = {
&g_rsAssoc_IE,
};
// Nashville specific associations
const RegSet * g_rgprsDefault_Nash[] = {
&g_rsAssoc_Nash,
};
//
// Other registry settings
//
const RegSet * g_rgprsIE30Only[] =
{
&g_rsGeneral_IE,
&g_rsAthena,
};
const RegSet *g_rgprsNashOnly[] =
{
&g_rsGeneral_Nash,
&g_rsAthena,
};
const RegSet *g_rgprsUninstallIE30[] =
{
&g_rsUninstall_IE,
};
const RegSet *g_rgprsUninstallNash[] =
{
&g_rsUninstall_Nash,
};
/*----------------------------------------------------------
Purpose: Determine if a particular RegSet is installed
Returns:
Cond: --
*/
BOOL
IsRegSetInstalled(
IN const RegSet * prs)
{
BOOL bRet = FALSE;
UINT i;
HKEY hkey;
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 == HIWORD(pre->pvValue))
{
// Yes; load it
dwSizeExpect = LoadStringA(g_hinst, (UINT)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)
{
wsprintfA(szT, "rundll32.exe %s", (LPSTR)pre->pvValue);
pvValue = szT;
// Add null and convert to bytes
dwSizeExpect = CbFromCchA(lstrlenA(szT) + 1);
}
else
{
pvValue = pre->pvValue;
if (0 == pre->dwSize)
dwSizeExpect = CbFromCchA(lstrlenA(pvValue) + 1);
else
dwSizeExpect = pre->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 != lstrnicmpA((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->dwSize)
{
TraceMsg(TF_REGCHECK, "IsRegSetInstalled: %s size is %d, expecting %d", Dbg_RegStr(pre, szDbg), dwSize, pre->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);
lstrcpyA(szPath, pszKey);
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;
TCHAR 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 (IsFlagSet(pre->dwFlags, REF_IFEMPTY) ||
bDontIntrude && IsFlagSet(pre->dwFlags, REF_DONTINTRUDE))
{
// 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 == HIWORD(pre->pvValue))
{
// Yes; load it
dwSize = LoadStringA(g_hinst, (UINT)pre->pvValue, 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);
wsprintfA(szBuffer, "rundll32.exe %s", (LPSTR)pre->pvValue);
pvValue = szBuffer;
dwSize = CbFromCchA(lstrlenA(szBuffer) + 1);
}
else
{
// Normal case
pvValue = pre->pvValue;
if (0 == pre->dwSize && REG_SZ == pre->dwType)
dwSize = CbFromCchA(lstrlenA(pvValue) + 1);
else
dwSize = pre->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 value or the key?
if (*pre->pszValName)
{
// 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);
wScreen = GetDeviceCaps (hdc, HORZRES);
hScreen = GetDeviceCaps (hdc, VERTRES);
ReleaseDC (hwndChild, hdc);
// 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
Returns:
Cond: --
*/
BOOL
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());
// Initialize Checkbox
Button_SetCheck(GetDlgItem(hdlg, IDC_ASSOC_CHECK), IsCheckAssociationsOn());
// Show the right text
if (PLATFORM_NASH == WhichPlatform())
{
ShowWindow(GetDlgItem(hdlg, IDC_ASSOC_IE30), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, IDC_ASSOC_IE40), SW_SHOWNA);
}
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
Returns:
Cond: --
*/
BOOL
AskUserShouldFixReg()
{
return IDYES == DialogBox( HINST_THISDLL, MAKEINTRESOURCE(IDD_ASSOC), NULL, (DLGPROC)AssociationDialogProc);
}
/*----------------------------------------------------------
Purpose: Install file and protocol association settings in
registry.
Returns:
Cond: --
*/
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_IE3:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_IE); i++)
InstallRegSet(g_rgprsDefault_IE[i], bDontIntrude);
break;
case PLATFORM_NASH:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Nash); i++)
InstallRegSet(g_rgprsDefault_Nash[i], bDontIntrude);
break;
default:
ASSERT(0);
break;
}
return NOERROR;
}
/*----------------------------------------------------------
Purpose: Set the CheckAssocation setting in the registry
Returns:
Cond: --
*/
void
SetCheckAssociations(
BOOL fCheck)
{
HKEY hk;
if (RegOpenKeyEx( 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.
Returns:
Cond: --
*/
BOOL IsCheckAssociationsOn()
{
BOOL rval = TRUE;
TCHAR szBuf[20];
DWORD dwSize = sizeof(szBuf);
DWORD dwValType;
if (NO_ERROR == SHGetValue(HKEY_CURRENT_USER, c_szCheckAssnSwitch,
TEXT("Check_Associations"), &dwValType,
szBuf, &dwSize))
{
if ((dwValType == REG_SZ) && (dwSize < sizeof(szBuf))) {
if (lstrcmpi( szBuf, TEXT("No")) == 0)
rval = FALSE;
}
}
return( rval );
}
/*----------------------------------------------------------
Purpose: Queries a registry set. If the registry doesn't have
the right values, this function applies the registry
set changes to the registry.
Returns: --
Cond: --
*/
void
QueryAndApplyRegSet(
IN RegSet ** rgprs,
IN UINT cprs)
{
UINT i;
for (i = 0; i < cprs; i++)
{
// Does the registry have the right settings?
if (!IsRegSetInstalled(rgprs[i]))
{
// No; apply the settings
for (i = 0; i < ARRAYSIZE(rgprs); i++)
InstallRegSet(rgprs[i], FALSE);
break;
}
}
}
void EnsureWebViewRegSettings()
{
// We do the following mini-check regardless of the user's settings,
// and for every window we open
QueryAndApplyRegSet(g_rgprsWebview, ARRAYSIZE(g_rgprsWebview));
}
/*----------------------------------------------------------
Purpose: Function that determines if we are the default browser.
Returns:
Cond: --
*/
void
DetectAndFixAssociations()
{
TraceMsg(TF_WARNING, "Performing expensive registry query for default browser!");
// This ensures we have a valid Start and Search Page in the registry
// for this user, regardless of Profile.
QueryAndApplyRegSet(g_rgprsMin_IE, ARRAYSIZE(g_rgprsMin_IE));
// If we already checked once, or the user doesn't
// want us to check the associations then don't do the check
if ( IsCheckAssociationsOn() )
{
int i;
BOOL bNeedFix = FALSE;
UINT nInstall = WhichPlatform();
// Check the settings common to all platforms
for (i = 0; i < ARRAYSIZE(g_rgprsDefault); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault[i]))
{
bNeedFix = TRUE;
break;
}
}
if (!bNeedFix)
{
// Check specific to IE or Nashville
switch (nInstall)
{
case PLATFORM_IE3:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_IE); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault_IE[i]))
{
bNeedFix = TRUE;
break;
}
}
break;
case PLATFORM_NASH:
for (i = 0; i < ARRAYSIZE(g_rgprsDefault_Nash); i++)
{
if (! IsRegSetInstalled(g_rgprsDefault_Nash[i]))
{
bNeedFix = TRUE;
break;
}
}
break;
default:
ASSERT(0);
break;
}
}
if (bNeedFix && AskUserShouldFixReg())
InstallRegAssoc(nInstall, FALSE);
}
}
/*----------------------------------------------------------
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
Cond: --
*/
BOOL
AreWeInstallingOverIE(void)
{
BOOL bRet = FALSE;
TCHAR sz[MAX_PATH + 20]; // add some padding for arguments
DWORD cbData = SIZEOF(sz);
if (NO_ERROR == SHGetValue(HKEY_CLASSES_ROOT, c_szHTTPOpenCmd, TEXT(""),
NULL, sz, &cbData) &&
StrStrI(sz, TEXT("iexplore.exe")))
{
TraceMsg(TF_REGCHECK, "Installing over IEXPLORE.EXE");
bRet = TRUE;
}
return bRet;
}
/*----------------------------------------------------------
Purpose: Install registry info based upon which shell we're running
Returns:
Cond: --
*/
HRESULT
InstallPlatformRegItems(void)
{
int i;
UINT nInstall = WhichPlatform();
BOOL bDontIntrude;
// If we aren't installing over a previous IE build, don't intrude
// until IE is invoked.
bDontIntrude = !AreWeInstallingOverIE();
// Install file and protocol associations
InstallRegAssoc(nInstall, bDontIntrude);
// Install other registry settings
switch (nInstall)
{
case PLATFORM_IE3:
for (i = 0; i < ARRAYSIZE(g_rgprsIE30Only); i++)
{
InstallRegSet(g_rgprsIE30Only[i], bDontIntrude);
}
break;
case PLATFORM_NASH:
for (i = 0; i < ARRAYSIZE(g_rgprsNashOnly); i++)
{
InstallRegSet(g_rgprsNashOnly[i], bDontIntrude);
}
break;
default:
ASSERT(0);
break;
}
return NOERROR;
}
/*----------------------------------------------------------
Purpose: Uninstall registry info based on given platform
Returns:
Cond: --
*/
HRESULT
UninstallPlatformRegItems(
IN UINT uPlatform)
{
int i;
switch (uPlatform)
{
case PLATFORM_IE3:
for (i = 0; i < ARRAYSIZE(g_rgprsUninstallIE30); i++)
{
InstallRegSet(g_rgprsUninstallIE30[i], FALSE);
}
break;
case PLATFORM_NASH:
for (i = 0; i < ARRAYSIZE(g_rgprsUninstallNash); i++)
{
InstallRegSet(g_rgprsUninstallNash[i], FALSE);
}
break;
default:
// Don't do anything
break;
}
return NOERROR;
}