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

434 lines
12 KiB
C++

// dllreg.c -- autmatic registration and unregistration
//
#include "priv.h"
#include <advpub.h>
#include <comcat.h>
#include <winineti.h>
#include "resource.h"
#include "regkeys.h"
#include "DllRegHelper.h"
#ifdef UNIX
#include "unixstuff.h"
#endif
void AddNotepadToOpenWithList();
//=--------------------------------------------------------------------------=
// miscellaneous [useful] numerical constants
//=--------------------------------------------------------------------------=
// the length of a guid once printed out with -'s, leading and trailing bracket,
// plus 1 for NULL
//
#define GUID_STR_LEN 40
// ISSUE/010429/davidjen need to register typelib LIBID_BrowseUI
// before checkin in verify if this typelib already gets registered by setup!!!!!!!
#ifndef ATL_ENABLED
#define ATL_ENABLED
#endif
//=--------------------------------------------------------------------------=
// UnregisterTypeLibrary
//=--------------------------------------------------------------------------=
// blows away the type library keys for a given libid.
//
// Parameters:
// REFCLSID - [in] libid to blow away.
//
// Output:
// BOOL - TRUE OK, FALSE bad.
//
// Notes:
// - WARNING: this function just blows away the entire type library section,
// including all localized versions of the type library. mildly anti-
// social, but not killer.
//
#ifdef ATL_ENABLED
BOOL UnregisterTypeLibrary
(
const CLSID* piidLibrary
)
{
TCHAR szScratch[GUID_STR_LEN];
HKEY hk;
// convert the libid into a string.
//
SHStringFromGUID(*piidLibrary, szScratch, ARRAYSIZE(szScratch));
if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_READ|KEY_WRITE, &hk))
{
SHDeleteKey(hk, szScratch);
RegCloseKey(hk);
}
return TRUE;
}
#endif
#ifdef ATL_ENABLED
HRESULT SHRegisterTypeLib(void)
{
HRESULT hr = S_OK;
ITypeLib *pTypeLib;
DWORD dwPathLen;
WCHAR wzModuleName[MAX_PATH];
// Load and register our type library.
//
dwPathLen = GetModuleFileName(HINST_THISDLL, wzModuleName, ARRAYSIZE(wzModuleName));
#ifdef UNIX
dwPathLen = ConvertModuleNameToUnix( wzModuleName );
#endif
hr = LoadTypeLib(wzModuleName, &pTypeLib);
if (SUCCEEDED(hr))
{
// call the unregister type library as we had some old junk that
// was registered by a previous version of OleAut32, which is now causing
// the current version to not work on NT...
UnregisterTypeLibrary(&LIBID_BrowseUI);
hr = RegisterTypeLib(pTypeLib, wzModuleName, NULL);
if (FAILED(hr))
{
TraceMsg(DM_WARNING, "sccls: RegisterTypeLib failed (%x)", hr);
}
pTypeLib->Release();
}
else
{
TraceMsg(DM_WARNING, "sccls: LoadTypeLib failed (%x)", hr);
}
return hr;
}
#endif
void SetBrowseNewProcess(void)
// We want to enable browse new process by default on high capacity
// machines. We do this in the per user section so that people can
// disable it if they want.
{
static const TCHAR c_szBrowseNewProcessReg[] = REGSTR_PATH_EXPLORER TEXT("\\BrowseNewProcess");
static const TCHAR c_szBrowseNewProcess[] = TEXT("BrowseNewProcess");
// no way if less than ~30 meg (allow some room for debuggers, checked build etc)
MEMORYSTATUS ms;
SYSTEM_INFO si;
ms.dwLength=sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);
GetSystemInfo(&si);
if (!g_fRunningOnNT && ((si.dwProcessorType == PROCESSOR_INTEL_486) ||
(si.dwProcessorType == PROCESSOR_INTEL_386)))
{
// Bail if Win9x and 386 or 486 cpu
return;
}
if (ms.dwTotalPhys < 30*1024*1024)
return;
SHRegSetUSValue(c_szBrowseNewProcessReg, c_szBrowseNewProcess, REG_SZ, TEXT("yes"), SIZEOF(TEXT("yes")), SHREGSET_FORCE_HKLM);
}
/*----------------------------------------------------------
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: --
*/
#define SIZE_FLAG sizeof(" -nohome")
BOOL
GetIEPath(
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 != RegOpenKeyExA(HKEY_LOCAL_MACHINE, SZ_REGKEY_IEXPLOREA, 0, KEY_QUERY_VALUE, &hkey))
{
TraceMsg(TF_ERROR, "GetIEPath(): RegOpenKey( %s ) Failed", c_szIexploreKey) ;
}
else
{
DWORD cbBrowser;
DWORD dwType;
if (bInsertQuotes)
lstrcatA(pszBuf, "\"");
cbBrowser = CbFromCchA(cchBuf - SIZE_FLAG - 4);
if (NO_ERROR != RegQueryValueExA(hkey, "", NULL, &dwType,
(LPBYTE)&pszBuf[bInsertQuotes?1:0], &cbBrowser))
{
TraceMsg(TF_ERROR, "GetIEPath(): RegQueryValueEx() for Iexplore path failed");
}
else
{
bRet = TRUE;
}
if (bInsertQuotes)
lstrcatA(pszBuf, "\"");
RegCloseKey(hkey);
}
return bRet;
}
//
// The actual functions called
//
/*----------------------------------------------------------
Purpose: Calls the ADVPACK entry-point which executes an inf
file section.
*/
HRESULT
CallRegInstall(
LPSTR pszSection,
BOOL bUninstall)
{
HRESULT hr = E_FAIL;
HINSTANCE hinstAdvPack = LoadLibraryA("ADVPACK.DLL");
if (hinstAdvPack)
{
REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
if (pfnri)
{
char szIEPath[MAX_PATH];
STRENTRY seReg[] = {
{ "MSIEXPLORE", szIEPath },
// These two NT-specific entries must be at the end
{ "25", "%SystemRoot%" },
{ "11", "%SystemRoot%\\system32" },
};
STRTABLE stReg = { ARRAYSIZE(seReg) - 2, seReg };
// Get the location of iexplore from the registry
if ( !GetIEPath(szIEPath, SIZECHARS(szIEPath), TRUE) )
{
#ifndef UNIX
// Failed, just say "iexplore"
lstrcpyA(szIEPath, "iexplore.exe");
AssertMsg(0, TEXT("IE.INF either hasn't run or hasn't set the AppPath key. NOT AN IE BUG. Look for changes to IE.INX."));
#else
lstrcpyA(szIEPath, "iexplorer");
#endif
}
if (g_fRunningOnNT)
{
// If on NT, we want custom action for %25% %11%
// so that it uses %SystemRoot% in writing the
// path to the registry.
stReg.cEntries += 2;
}
hr = pfnri(g_hinst, pszSection, &stReg);
if (bUninstall)
{
// ADVPACK will return E_UNEXPECTED if you try to uninstall
// (which does a registry restore) on an INF section that was
// never installed. We uninstall sections that may never have
// been installed, so ignore this error
hr = ((E_UNEXPECTED == hr) ? S_OK : hr);
}
}
else
TraceMsg(DM_ERROR, "DLLREG CallRegInstall() calling GetProcAddress(hinstAdvPack, \"RegInstall\") failed");
FreeLibrary(hinstAdvPack);
}
else
TraceMsg(DM_ERROR, "DLLREG CallRegInstall() Failed to load ADVPACK.DLL");
return hr;
}
const CATID * const c_InfoBandClasses[] =
{
&CLSID_SearchBand,
&CLSID_MediaBand,
NULL
};
void RegisterCategories(BOOL fRegister)
{
enum DRH_REG_MODE eRegister = fRegister ? CCR_REG : CCR_UNREG;
DRH_RegisterOneCategory(&CATID_InfoBand, IDS_CATINFOBAND, c_InfoBandClasses, eRegister);
}
STDAPI DllRegisterServer(void)
{
HRESULT hr = S_OK;
HRESULT hrExternal = S_OK; //used to return the first failure
TraceMsg(DM_TRACE, "DLLREG DllRegisterServer() Beginning");
#ifdef DEBUG
if (IsFlagSet(g_dwBreakFlags, BF_ONAPIENTER))
{
TraceMsg(TF_ALWAYS, "Stopping in DllRegisterServer");
DEBUG_BREAK;
}
#endif
// Delete any old registration entries, then add the new ones.
// Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
// (The inf engine doesn't guarantee DelReg/AddReg order, that's
// why we explicitly unreg and reg here.)
//
HINSTANCE hinstAdvPack = LoadLibraryA("ADVPACK.DLL");
hr = THR(CallRegInstall("InstallControls", FALSE));
if (SUCCEEDED(hrExternal))
hrExternal = hr;
if (hinstAdvPack)
FreeLibrary(hinstAdvPack);
#ifdef ATL_ENABLED
// registers object, typelib and all interfaces in typelib
hr = SHRegisterTypeLib();
if (SUCCEEDED(hrExternal))
hrExternal = hr;
#endif
return hrExternal;
}
STDAPI DllUnregisterServer(void)
{
HRESULT hr;
TraceMsg(DM_TRACE, "DLLREG DllUnregisterServer() Beginning");
// UnInstall the registry values
hr = THR(CallRegInstall("UnInstallControls", TRUE));
return hr;
}
void ImportQuickLinks();
/*----------------------------------------------------------
Purpose: Install/uninstall user settings
Description: Note that this function has special error handling.
The function will keep hrExternal with the worse error
but will only stop executing util the internal error (hr)
gets really bad. This is because we need the external
error to catch incorrectly authored INFs but the internal
error to be robust in attempting to install other INF sections
even if one doesn't make it.
*/
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
{
HRESULT hr = S_OK;
HRESULT hrExternal = S_OK;
HRESULT hrInit = SHCoInitialize();
if (bInstall)
{
// "U" means it's the per user install call
if (pszCmdLine && (lstrcmpiW(pszCmdLine, L"U") == 0))
{
ImportQuickLinks();
if (GetUIVersion() >= 5)
{
// don't upgrade these on XP -> XPSP#
BOOL fUpgradeUserSettings = TRUE;
WCHAR szVersion[50]; // plenty big for aaaa,bbbb,cccc,dddd
DWORD cbVersion = sizeof(szVersion);
if (ERROR_SUCCESS==SHGetValueW(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11cf-8B85-00AA005B4383}",L"Version", // guid is ie4uninit's Active Setup (it calls browseu's selfreg)
NULL, szVersion, &cbVersion))
{
__int64 nverUpgradeFrom;
__int64 nverWinXP;
if (SUCCEEDED(GetVersionFromString64(szVersion, &nverUpgradeFrom)) &&
SUCCEEDED(GetVersionFromString64(L"6,0,2600,0000", &nverWinXP)))
{
fUpgradeUserSettings = nverUpgradeFrom < nverWinXP;
}
}
if (fUpgradeUserSettings)
{
hr = THR(CallRegInstall("InstallPerUser_BrowseUIShell", FALSE));
}
}
}
else
{
SetBrowseNewProcess();
// Backup current associations because InstallPlatformRegItems() may overwrite.
if (GetUIVersion() < 5)
hr = THR(CallRegInstall("InstallBrowseUINonShell", FALSE));
else
hr = THR(CallRegInstall("InstallBrowseUIShell", FALSE));
if (SUCCEEDED(hrExternal))
hrExternal = hr;
if (!IsOS(OS_WHISTLERORGREATER))
{
hr = THR(CallRegInstall("InstallBrowseUIPreWhistler", FALSE));
if (SUCCEEDED(hrExternal))
hrExternal = hr;
}
if (IsOS(OS_NT))
{
hr = THR(CallRegInstall("InstallBrowseUINTOnly", FALSE));
if (SUCCEEDED(hrExternal))
hrExternal = hr;
}
RegisterCategories(TRUE);
#ifdef ATL_ENABLED
SHRegisterTypeLib();
#endif
}
// Add Notepad to the OpenWithList for .htm files
AddNotepadToOpenWithList();
}
else
{
hr = THR(CallRegInstall("UnInstallBrowseUI", TRUE));
if (SUCCEEDED(hrExternal))
hrExternal = hr;
#ifdef ATL_ENABLED
UnregisterTypeLibrary(&LIBID_BrowseUI);
#endif
RegisterCategories(FALSE);
}
SHCoUninitialize(hrInit);
return hrExternal;
}