|
|
#include "pch.hxx"
#include <regutil.h>
#ifndef THOR_SETUP
#include <strconst.h>
#include "shared.h"
#else
#include "strings.h"
#include "util.h"
#endif
#include <ourguid.h>
#include <resource.h>
#ifndef THOR_SETUP
#include <shlwapi.h>
#include "shlwapip.h"
#define strstr StrStr
#define RegDeleteKeyRecursive SHDeleteKey
#endif // THOR_SETUP
#include "demand.h"
typedef HINSTANCE (STDAPICALLTYPE FGETCOMPONENTPATH)(); typedef FGETCOMPONENTPATH *LPFGETCOMPONENTPATH; typedef HINSTANCE (STDAPICALLTYPE FIXMAPI)(); typedef FIXMAPI *LPFIXMAPI;
BOOL IsXPSP1OrLater() { BOOL fResult = FALSE; OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (GetVersionEx(&osvi)) { if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) { if (osvi.dwMajorVersion > 5) { fResult = TRUE; } else if (osvi.dwMajorVersion == 5) { if (osvi.dwMinorVersion > 1) { fResult = TRUE; } else if (osvi.dwMinorVersion == 1) { if (osvi.dwBuildNumber > 2600) { fResult = TRUE; } else if (osvi.dwBuildNumber == 2600) { HKEY hkey;
// HIVESFT.INF and UPDATE.INF set this for service packs:
// HKLM,SYSTEM\CurrentControlSet\Control\Windows,"CSDVersion",0x10001,0x100
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Windows"), 0, KEY_QUERY_VALUE, &hkey);
if (ERROR_SUCCESS == lResult) { DWORD dwValue; DWORD cbValue = sizeof(dwValue); DWORD dwType;
lResult = RegQueryValueEx(hkey, TEXT("CSDVersion"), NULL, &dwType, (LPBYTE)&dwValue, &cbValue);
if ((ERROR_SUCCESS == lResult) && (REG_DWORD == dwType) && (dwValue >= 0x100)) { fResult = TRUE; } RegCloseKey(hkey); } } } } } }
return fResult; }
// ********* Tests
// Looks in the registry at a value placed there by msoe.dll's selfreg
BOOL GetAthenaRegPath(TCHAR *szAthenaDll, DWORD cch) { BOOL fRet; HKEY hkey; TCHAR szPath[MAX_PATH], szExpanded[MAX_PATH]; DWORD dwType, cb; LPTSTR psz; szPath[0] = '\0'; fRet = FALSE; wnsprintf(szExpanded, ARRAYSIZE(szExpanded), c_szProtocolPath, c_szMail, c_szMOE); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szExpanded, 0, KEY_QUERY_VALUE, &hkey)) { cb = sizeof(szPath); if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegDllPath, 0, &dwType, (LPBYTE)szPath, &cb) && cb) { // Remove %values% if needed
if (REG_EXPAND_SZ == dwType) { ExpandEnvironmentStrings(szPath, szExpanded, ARRAYSIZE(szExpanded)); psz = szExpanded; } else psz = szPath; StrCpyN(szAthenaDll, psz, cch); fRet = TRUE; } RegCloseKey(hkey); } return(fRet); }
#ifdef THOR_SETUP
BOOL GetExePath(LPCTSTR szExe, TCHAR *szPath, DWORD cch, BOOL fDirOnly) { BOOL fRet; HKEY hkey; DWORD dwType, cb; TCHAR sz[MAX_PATH], szT[MAX_PATH]; Assert(szExe != NULL); Assert(szPath != NULL); fRet = FALSE; wnsprintf(sz, ARRAYSIZE(sz),c_szPathFileFmt, c_szAppPaths, szExe); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey)) { cb = sizeof(szT); if (ERROR_SUCCESS == RegQueryValueEx(hkey, fDirOnly ? c_szRegPath : NULL, 0, &dwType, (LPBYTE)szT, &cb) && cb) { if (dwType == REG_EXPAND_SZ) { cb = ExpandEnvironmentStrings(szT, szPath, cch); if (cb != 0 && cb <= cch) fRet = TRUE; } else { Assert(dwType == REG_SZ); StrCpyN(szPath, szT, cch); fRet = TRUE; } } RegCloseKey(hkey); } return(fRet); } #endif
HRESULT GetCLSIDFromSubKey(HKEY hKey, LPSTR rgchBuf, ULONG *pcbBuf) { HKEY hKeyCLSID; DWORD dwType; HRESULT hr=E_FAIL; // Lets open they server key
if (RegOpenKeyEx(hKey, c_szCLSID, 0, KEY_READ, &hKeyCLSID) == ERROR_SUCCESS) { if (ERROR_SUCCESS == RegQueryValueEx(hKeyCLSID, NULL, 0, &dwType, (LPBYTE)rgchBuf, pcbBuf) && *pcbBuf) hr = S_OK; RegCloseKey(hKeyCLSID); } return hr; }
// FUNCTION: FAssocsOK()
//
// PURPOSE: Checks to see if our file-type associations are in place
//
// Returns:
BOOL FAssocsOK(LPCTSTR pszClient, LPCTSTR pszProduct) { HKEY hkeyProtocols; HKEY hkeyRealProt; HKEY hkeyAppsProt; TCHAR szProtPath[MAX_PATH]; TCHAR szRealPath[MAX_PATH]; TCHAR szAppPath [MAX_PATH]; TCHAR szTemp [MAX_PATH]; DWORD dwIndex = 0; DWORD cb; DWORD cbMaxProtocolLen; DWORD dwType, dwType2; LPTSTR pszURL; BOOL fNoProbs = TRUE; // Open up the corresponding protocols key
wnsprintf(szProtPath, ARRAYSIZE(szProtPath), c_szProtocolPath, pszClient, pszProduct); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szProtPath, 0, KEY_READ, &hkeyProtocols)) { // Figure out the longest protocol name
if (ERROR_SUCCESS == RegQueryInfoKey(hkeyProtocols, NULL, NULL, NULL, NULL, &cbMaxProtocolLen, NULL, NULL, NULL, NULL, NULL, NULL))
{ // Allow for "\Shell\Open\Command" whose length is 19 + 1 for NT's RegQueryInfoKey
cbMaxProtocolLen += 20;
// Allocate buffer for string
if (MemAlloc((LPVOID*)&pszURL, cbMaxProtocolLen * sizeof(TCHAR))) { // Enumerate the protocol subkeys
cb = cbMaxProtocolLen; while (fNoProbs && ERROR_SUCCESS == RegEnumKeyEx(hkeyProtocols, dwIndex++, pszURL, &cb, NULL, NULL, NULL, NULL)) { fNoProbs = FALSE; StrCatBuff(pszURL, c_szRegOpen, cbMaxProtocolLen); // Open up the real protocol\shell\open\command key
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, pszURL, 0, KEY_READ, &hkeyRealProt)) { // Open up app's protocol\shell\open\command key
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyProtocols, pszURL, 0, KEY_READ, &hkeyAppsProt)) { // Grab the current registered handler
cb = ARRAYSIZE(szRealPath); if (ERROR_SUCCESS == RegQueryValueEx(hkeyRealProt, NULL, 0, &dwType, (LPBYTE)szRealPath, &cb)) { // Grab the App's Path
cb = ARRAYSIZE(szAppPath); if (ERROR_SUCCESS == RegQueryValueEx(hkeyAppsProt, NULL, 0, &dwType2, (LPBYTE)szAppPath, &cb)) { if (REG_EXPAND_SZ == dwType2) { ExpandEnvironmentStrings(szAppPath, szTemp, ARRAYSIZE(szTemp)); StrCpyN(szAppPath, szTemp, ARRAYSIZE(szAppPath)); }
if (REG_EXPAND_SZ == dwType) { ExpandEnvironmentStrings(szRealPath, szTemp, ARRAYSIZE(szTemp)); StrCpyN(szRealPath, szTemp, ARRAYSIZE(szRealPath)); }
// Do a simple case insensitive comparison
if (!lstrcmpi(szAppPath, szRealPath)) fNoProbs = TRUE; } } RegCloseKey(hkeyAppsProt); } RegCloseKey(hkeyRealProt); } // Reset cb
cb = cbMaxProtocolLen; } MemFree(pszURL); } } RegCloseKey(hkeyProtocols); }
return (fNoProbs); }
// FUNCTION: FExchangeServerInstalled()
//
// PURPOSE: Checks to see if Exchange Server is installed
//
// Based on code provided by msmith from OL
//
BOOL FExchangeServerInstalled() { HKEY hkeyServices; BOOL fInstalled = FALSE; // Get HKLM\Software\Microsoft\Exchange\Setup registry key
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szExchangeSetup, 0, KEY_READ, &hkeyServices)) { // Does Services registry value exist?
fInstalled = ERROR_SUCCESS == RegQueryValueEx(hkeyServices, c_szServices, NULL, NULL, NULL, NULL); RegCloseKey(hkeyServices); } return (fInstalled); }
// FUNCTION: FMapiStub()
//
// PURPOSE: Checks to see if the mapi32.dll is Outlook's
//
// Based on code provided by [email protected]
//
// Return Value: TRUE - all is well
// *pdw = Failure type if Return value is FALSE:
// 1 = No mapi32.dll
// 2 = Different mapi32.dll
//
BOOL FMapiStub(DWORD *pdw) { HINSTANCE hMapiStub; TCHAR szSystemPath[MAX_PATH]; TCHAR szMapiPath[MAX_PATH]; BOOL fMapiStub = FALSE;
Assert(pdw);
*pdw = 0; // If Exchange server is installed, their stub is in place, so leave it be
if (FExchangeServerInstalled()) return TRUE; // Build a path to mapi32.dll
GetSystemDirectory(szSystemPath, ARRAYSIZE(szSystemPath)); MakeFilePath(szSystemPath, c_szMAPIDLL, c_szEmpty, szMapiPath, ARRAYSIZE(szMapiPath));
hMapiStub = LoadLibrary(szMapiPath); if (hMapiStub) { fMapiStub = NULL != (LPFGETCOMPONENTPATH)GetProcAddress(hMapiStub, TEXT("FGetComponentPath")); // STRING_OK Msmith
if (!fMapiStub) *pdw = 2; FreeLibrary(hMapiStub); } else *pdw = 1; return fMapiStub; }
BOOL FValidClient(LPCTSTR pszClient, LPCTSTR pszProduct) { TCHAR szBuffer[MAX_PATH]; HKEY hkey2; BOOL fValid = FALSE; wnsprintf(szBuffer, ARRAYSIZE(szBuffer), c_szRegPathSpecificClient, pszClient, pszProduct); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_QUERY_VALUE, &hkey2)) { RegCloseKey(hkey2); fValid = TRUE; } return fValid; }
int DefaultClientSet(LPCTSTR pszClient) { int iRet; TCHAR sz[MAX_PATH], sz2[MAX_PATH]; HKEY hkey, hkeyT; DWORD dwType, cb; iRet = NOT_HANDLED; wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szRegPathClients, pszClient); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey)) { cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(hkey, NULL, NULL, &dwType, (LPBYTE)&sz, &cb)) { // Sanity check - is the current client even valid?
wnsprintf(sz2, ARRAYSIZE(sz2), c_szRegPathSpecificClient, pszClient, sz); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz2, 0, KEY_QUERY_VALUE, &hkeyT)) { RegCloseKey(hkeyT); if (0 == lstrcmpi(c_szMOE, sz)) iRet = HANDLED_CURR; else if (0 == lstrcmpi(c_szIMN, sz)) iRet = NOT_HANDLED; else if (0 == lstrcmpi(c_szOutlook, sz)) iRet = HANDLED_OUTLOOK; else if (0 == lstrcmpi(c_szNT, sz)) iRet = NOT_HANDLED; else if (*sz != 0) iRet = HANDLED_OTHER; } } RegCloseKey(hkey); } return(iRet); }
//
// FUNCTION: FIsDefaultNewsConfiged()
//
// PURPOSE: Determines if Athena is currently the default news handler.
//
BOOL WINAPI FIsDefaultNewsConfiged(DWORD dwFlags) { BOOL fRet; if (0 == (dwFlags & DEFAULT_OUTNEWS)) fRet = (HANDLED_CURR == DefaultClientSet(c_szNews)) && FAssocsOK(c_szNews, c_szMOE); else fRet = (HANDLED_OUTLOOK == DefaultClientSet(c_szNews)) && FAssocsOK(c_szNews, c_szOutlook); return(fRet); }
//
// FUNCTION: FIsDefaultMailConfiged()
//
// PURPOSE: Determines if Athena is currently the default mail handler.
//
BOOL WINAPI FIsDefaultMailConfiged() { DWORD dwTemp; return (HANDLED_CURR == DefaultClientSet(c_szMail) && FAssocsOK(c_szMail, c_szMOE) && FMapiStub(&dwTemp)); }
// ********* Actions
// Set up the URL with our handler
BOOL AddUrlHandler(LPCTSTR pszURL, LPCTSTR pszClient, LPCTSTR pszProduct, DWORD dwFlags) { HKEY hKey, hKeyProt; TCHAR szBuffer[MAX_PATH], szBuffer1[MAX_PATH]; DWORD dwDisp, cb; BOOL fCreate = TRUE;
// Try to detect if this URL is set or not...
if (dwFlags & DEFAULT_DONTFORCE) { DWORD dwLen = lstrlen(pszURL); LPTSTR pszTemp;
// 20 = 19 (length of "\Shell\Open\Command") + 1 for NULL
DWORD cchSize = (dwLen+20);
if (MemAlloc((LPVOID*)&pszTemp, cchSize * sizeof(pszTemp[0]))) { StrCpyN(pszTemp, pszURL, cchSize); StrCatBuff(pszTemp, c_szRegOpen, cchSize);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, pszTemp, 0, KEY_READ, &hKey)) { cb = sizeof(szBuffer); if (ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, 0, NULL, (LPBYTE)szBuffer, &cb)) { // Special case URL.DLL and MAILNEWS.DLL as okay to overwrite
if (!strstr(szBuffer, c_szUrlDll) && !strstr(szBuffer, c_szMailNewsDllOld)) fCreate = FALSE; } RegCloseKey(hKey); }
MemFree(pszTemp); } }
// Clear out any old info about this URL
if (fCreate) { RegDeleteKeyRecursive(HKEY_CLASSES_ROOT, pszURL); // Figure out the source for the info
wnsprintf(szBuffer1, ARRAYSIZE(szBuffer1), c_szProtocolPath, pszClient, pszProduct); wnsprintf(szBuffer, ARRAYSIZE(szBuffer), c_szPathFileFmt, szBuffer1, pszURL); // Copy the info to its new location
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKeyProt)) { if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, pszURL, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp)) { CopyRegistry(hKeyProt, hKey); RegCloseKey(hKey); } RegCloseKey(hKeyProt); } } return(TRUE); }
void SetDefaultClient(LPCTSTR pszClient, LPCTSTR pszProduct, DWORD dwFlags) { TCHAR sz[MAX_PATH]; HKEY hkey; DWORD dwDisp; BOOL fOK = TRUE;
if (DEFAULT_DONTFORCE & dwFlags) { if (NOT_HANDLED != DefaultClientSet(pszClient)) fOK = FALSE; }
if (fOK) { wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szRegPathClients, pszClient); if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, sz, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisp)) { RegSetValueEx(hkey, NULL, 0, REG_SZ, (LPBYTE)pszProduct, (lstrlen(pszProduct) + 1) * sizeof(TCHAR));
#ifndef THOR_SETUP
// Bug 32136 in IE6 database
SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)sz); #endif // THOR_SETUP
RegCloseKey(hkey); } } }
// Make sure MAPI32.dll is really Outlook's MAPISTUB
BOOL EnsureMAPIStub(DWORD dwFlags) { BOOL fOK = FALSE; DWORD dwReason, dwReason2; HINSTANCE hMapiStub = NULL; TCHAR szSystemPath[MAX_PATH]; TCHAR szPath[MAX_PATH]; LPFGETCOMPONENTPATH pfnFixMAPI; HKEY hkeyRunOnce; BOOL fUI = dwFlags & DEFAULT_UI; UINT cch;
// Is the mapistub already in place?
if (FMapiStub(&dwReason)) { fOK = TRUE; goto exit; }
switch (dwReason) { case 0: AssertSz(FALSE, "EnsureMAPIStub failed for no reason."); goto exit; case 1: // NonExistent
case 2: // Different
// Should be able to just load mapistub and FixMAPI
// Build a path to mapistub.dll
cch = GetSystemDirectory(szSystemPath, ARRAYSIZE(szSystemPath)); if (cch && cch <= ARRAYSIZE(szSystemPath)) { MakeFilePath(szSystemPath, c_szMAPIStub, c_szEmpty, szPath, ARRAYSIZE(szPath));
// Try to load
hMapiStub = LoadLibrary(szPath); } // else we fall through with NULL hMapiStub to failure case
if (hMapiStub) { // Look for the FixMAPI function
pfnFixMAPI = (LPFIXMAPI)GetProcAddress(hMapiStub, TEXT("FixMAPI")); if (pfnFixMAPI) { // Found the entry point, run it
pfnFixMAPI(); // Did that fix mapi32?
if (!FMapiStub(&dwReason2)) { // No, maybe the old one was in use...
if (2 == dwReason) { // Add a runonce entry for fixmapi
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szMAPIRunOnce, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyRunOnce, &dwReason)) { // 12 = (11 + 1) where 11 is length of fixmapi.exe + 1 for the null
if (ERROR_SUCCESS == RegSetValueEx(hkeyRunOnce, c_szMAPIRunOnceEntry, 0, REG_SZ, (LPBYTE)c_szFixMAPI, 12 * sizeof(TCHAR))) { #ifndef THOR_SETUP
// Tell the user to reboot
if (fUI) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBNeedsReboot), NULL, MB_OK); #endif
// Probable success
fOK = TRUE; } RegCloseKey(hkeyRunOnce); } } else { #ifndef THOR_SETUP
if (fUI) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBFailed), NULL, MB_OK); #endif
} } else // Success!
fOK = TRUE; } // Eek, where is FixMAPI?
else { #ifndef THOR_SETUP
if (fUI) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBMissingExport), NULL, MB_OK); #endif
} FreeLibrary(hMapiStub); } else { // Dll missing or unloadable
#ifndef THOR_SETUP
if (fUI) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBNoLoad), NULL, MB_OK); #endif
} break;
default: AssertSz(FALSE, "EnsureMAPIStub returned an unknown failure. Bailing"); goto exit; }
exit: return fOK; }
// Change the Default News handler
HRESULT ISetDefaultNewsHandler(LPCTSTR pszProduct, DWORD dwFlags) { AddUrlHandler(c_szURLNews, c_szNews, pszProduct, dwFlags); AddUrlHandler(c_szURLNNTP, c_szNews, pszProduct, dwFlags); AddUrlHandler(c_szURLSnews, c_szNews, pszProduct, dwFlags); SetDefaultClient(c_szNews, pszProduct, dwFlags); return (S_OK); }
// Change the Default Mail handler
HRESULT ISetDefaultMailHandler(LPCTSTR pszProduct, DWORD dwFlags) { // May change default handler to owner of mapi32.dll
EnsureMAPIStub(dwFlags);
AddUrlHandler(c_szURLMailTo, c_szMail, pszProduct, dwFlags);
if ((dwFlags & DEFAULT_SETUPMODE) && IsXPSP1OrLater()) { // running setup50.exe on XPSP1 or later, let OE Access handle it from here.
} else { // Non setup50.exe case (like "would you like to make OE your default mail client?")
// or we're running downlevel -- go ahead and do it.
SetDefaultClient(c_szMail, pszProduct, dwFlags); }
return (S_OK); }
//
// FUNCTION: SetDefaultMailHandler()
//
// PURPOSE: Adds the keys to the registry to make Athena the user's
// default mail reader.
//
// RETURN VALUE:
// HRESULT
//
// ATTENZIONE! if you change the parameters for this function, make sure
// that you make the proper change to athena\msoeacct\silent.cpp (it calls
// this via GetProcAddress)
HRESULT WINAPI SetDefaultMailHandler(DWORD dwFlags) { return ISetDefaultMailHandler(c_szMOE, dwFlags | DEFAULT_MAIL); }
//
// FUNCTION: SetDefaultNewsHandler()
//
// PURPOSE: Adds the keys to the registry to make Athena the user's
// default news reader.
//
// RETURN VALUE:
// HRESULT
//
// ATTENZIONE! if you change the parameters for this function, make sure
// that you make the proper change to athena\msoeacct\silent.cpp (it calls
// this via GetProcAddress)
HRESULT WINAPI SetDefaultNewsHandler(DWORD dwFlags) { if (dwFlags & DEFAULT_OUTNEWS) return ISetDefaultNewsHandler(c_szOutlook, dwFlags); else return ISetDefaultNewsHandler(c_szMOE, dwFlags | DEFAULT_NEWS); }
|