You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
12 KiB
383 lines
12 KiB
// --------------------------------------------------------------------------------
|
|
// MSIMN.C
|
|
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
// --------------------------------------------------------------------------------
|
|
#include "pch.h"
|
|
#define DEFINE_STRCONST
|
|
#include <msoeapi.h>
|
|
#include "msimnp.h"
|
|
#include "res.h"
|
|
#include "../msoeres/resource.h"
|
|
#include "shared.h"
|
|
#include "msoert.h"
|
|
#include "shlwapi.h"
|
|
#include "shlwapip.h"
|
|
#include <mapicode.h>
|
|
#include "error.h"
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// String Consts
|
|
// --------------------------------------------------------------------------------
|
|
static const WCHAR c_wszRegCmd[] = L"/reg";
|
|
static const WCHAR c_wszUnRegCmd[] = L"/unreg";
|
|
static const WCHAR c_wszEmpty[] = L"";
|
|
static const char c_szLangDll[] = "MSOERES.DLL";
|
|
static const char c_szOLNewsKey[] = "Software\\Clients\\News\\Microsoft Outlook";
|
|
static const char c_szRegOLNews[] = "OLNews";
|
|
static const char c_szRegFlat[] = "Software\\Microsoft\\Outlook Express";
|
|
static const char c_szDontUpgradeOLNews[] = "NoUpgradeOLNews";
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Debug Strings
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
static const TCHAR c_szDebug[] = "mshtmdbg.dll";
|
|
static const TCHAR c_szDebugUI[] = "DbgExDoTracePointsDialog";
|
|
static const TCHAR c_szRegSpy[] = "DbgExGetMallocSpy";
|
|
static const WCHAR c_wszInvokeUI[] = L"/d";
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MSHTMDBG.DLL Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
typedef void (STDAPICALLTYPE *PFNDEBUGUI)(BOOL);
|
|
typedef void *(STDAPICALLTYPE *PFNREGSPY)(void);
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Debug Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
void LoadMSHTMDBG(LPWSTR pwszCmdLine);
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
int WinMainT(HINSTANCE hInst, HINSTANCE hInstPrev, LPWSTR pwszCmdLine, int nCmdShow);
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// UpgradeOLNewsReader()
|
|
// --------------------------------------------------------------------------------
|
|
void UpgradeOLNewsReader(HINSTANCE hInst)
|
|
{
|
|
HKEY hkey;
|
|
BOOL fOK = TRUE;
|
|
DWORD dwDont, cb;
|
|
|
|
// Make sure this functionality hasn't been disabled
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFlat, 0, KEY_READ, &hkey))
|
|
{
|
|
cb = sizeof(dwDont);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szDontUpgradeOLNews, 0, NULL, (LPBYTE)&dwDont, &cb))
|
|
fOK = 0 == dwDont;
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (fOK && ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szOLNewsKey, 0, KEY_READ, &hkey))
|
|
{
|
|
RegCloseKey(hkey);
|
|
|
|
CallRegInstall(hInst, hInst, c_szRegOLNews, (LPSTR)c_szOLNewsKey);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ModuleEntry - Stolen from the CRT, used to shirink our code
|
|
// --------------------------------------------------------------------------------
|
|
int _stdcall ModuleEntry(void)
|
|
{
|
|
// Locals
|
|
int i;
|
|
STARTUPINFOA si;
|
|
LPWSTR pwszCmdLine;
|
|
|
|
// Get the command line
|
|
pwszCmdLine = GetCommandLineW();
|
|
|
|
// We don't want the "No disk in drive X:" requesters, so we set the critical error mask such that calls will just silently fail
|
|
SetErrorMode(SEM_FAILCRITICALERRORS);
|
|
|
|
// Parse the command line
|
|
if ( *pwszCmdLine == L'\"')
|
|
{
|
|
// Scan, and skip over, subsequent characters until another double-quote or a null is encountered.
|
|
while ( *++pwszCmdLine && (*pwszCmdLine != L'\"'))
|
|
{};
|
|
|
|
// If we stopped on a double-quote (usual case), skip over it.
|
|
if (*pwszCmdLine == L'\"')
|
|
pwszCmdLine++;
|
|
}
|
|
else
|
|
{
|
|
while (*pwszCmdLine > L' ')
|
|
pwszCmdLine++;
|
|
}
|
|
|
|
// Skip past any white space preceeding the second token.
|
|
while (*pwszCmdLine && (*pwszCmdLine <= L' '))
|
|
pwszCmdLine++;
|
|
|
|
// Get startup information...
|
|
si.dwFlags = 0;
|
|
GetStartupInfoA(&si);
|
|
|
|
// Call the real winmain
|
|
i = WinMainT(GetModuleHandle(NULL), NULL, pwszCmdLine, (si.dwFlags & STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOWDEFAULT);
|
|
|
|
// Since we now have a way for an extension to tell us when it is finished, we will terminate all processes when the main thread goes away.
|
|
ExitProcess(i);
|
|
|
|
// Done
|
|
return i;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// WinMain
|
|
// --------------------------------------------------------------------------------
|
|
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR pszCmdLine, int nCmdShow)
|
|
{
|
|
// Just call ModuleEntry
|
|
return(ModuleEntry());
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// WinMainT
|
|
// --------------------------------------------------------------------------------
|
|
int WinMainT(HINSTANCE hInst, HINSTANCE hInstPrev, LPWSTR pwszCmdLine, int nCmdShow)
|
|
{
|
|
// Locals
|
|
HANDLE hMutex=NULL;
|
|
HWND hwnd;
|
|
DWORD dwWait, dwError;
|
|
INT nErrorIds=0;
|
|
PFNSTART pfnStart;
|
|
HINSTANCE hInstMSOEDLL=NULL;
|
|
HRESULT hrOE;
|
|
HINSTANCE hInstUSER=NULL;
|
|
static BOOL fFirstID=TRUE;
|
|
|
|
// Register
|
|
if (0 == StrCmpIW(c_wszRegCmd, pwszCmdLine))
|
|
{
|
|
CallRegInstall(hInst, hInst, c_szReg, NULL);
|
|
|
|
// It not great to do this here, but we've only just written the OEOL keys,
|
|
// and it would be worst to hit the reg during startup
|
|
UpgradeOLNewsReader(hInst);
|
|
|
|
return(1);
|
|
}
|
|
|
|
// Unregister
|
|
else if (0 == StrCmpIW(c_wszUnRegCmd, pwszCmdLine))
|
|
{
|
|
CallRegInstall(hInst, hInst, c_szUnReg, NULL);
|
|
return(1);
|
|
}
|
|
|
|
// Create the start shared mutex
|
|
hMutex = CreateMutex(NULL, FALSE, STR_MSOEAPI_INSTANCEMUTEX);
|
|
if (NULL == hMutex)
|
|
{
|
|
nErrorIds = idsStartupCantCreateMutex;
|
|
goto exit;
|
|
}
|
|
|
|
// Wait for any current startups/shutdowns to finish
|
|
dwWait = WaitForSingleObject(hMutex, (1000 * 60));
|
|
if (dwWait != WAIT_OBJECT_0)
|
|
{
|
|
nErrorIds = idsStartupCantWaitForMutex;
|
|
goto exit;
|
|
}
|
|
|
|
// Look for a current instance of the application
|
|
hwnd = FindWindowWrapW(STRW_MSOEAPI_INSTANCECLASS, NULL);
|
|
|
|
// is there another instance running already?
|
|
if (NULL != hwnd)
|
|
{
|
|
// Locals
|
|
COPYDATASTRUCT cds;
|
|
DWORD_PTR dwResult;
|
|
|
|
// Some friendly output
|
|
IF_DEBUG(OutputDebugString("Another instance of Athena was found...\n\n");)
|
|
|
|
// Initialize the Copy data structure
|
|
cds.dwData = MSOEAPI_ACDM_CMDLINE;
|
|
cds.cbData = pwszCmdLine ? (lstrlenW(pwszCmdLine)+1)*sizeof(*pwszCmdLine) : 0;
|
|
cds.lpData = pwszCmdLine;
|
|
|
|
// On NT5, we need to call this to allow our window in the other process to take the foreground
|
|
hInstUSER = LoadLibrary("USER32.DLL");
|
|
if (hInstUSER)
|
|
{
|
|
FARPROC pfn = GetProcAddress(hInstUSER, "AllowSetForegroundWindow");
|
|
if (pfn)
|
|
{
|
|
DWORD dwProcessId;
|
|
GetWindowThreadProcessId(hwnd, &dwProcessId);
|
|
(*pfn)(dwProcessId);
|
|
}
|
|
|
|
FreeLibrary(hInstUSER);
|
|
}
|
|
|
|
// Show the window into the foreground
|
|
SetForegroundWindow(hwnd);
|
|
SendMessageTimeout(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds, SMTO_ABORTIFHUNG, 1500, &dwResult);
|
|
}
|
|
|
|
// Lets load msoe.dll
|
|
else
|
|
{
|
|
// Load Debug DLL
|
|
IF_DEBUG(LoadMSHTMDBG(pwszCmdLine);)
|
|
|
|
// Get the proc address of MSOE.DLL
|
|
hInstMSOEDLL = LoadLibrary(STR_MSOEAPI_DLLNAME);
|
|
|
|
// Did we load the dll
|
|
if (NULL == hInstMSOEDLL)
|
|
{
|
|
dwError = GetLastError();
|
|
if (dwError == ERROR_MOD_NOT_FOUND)
|
|
{
|
|
if (0xffffffff == GetFileAttributes(STR_MSOEAPI_DLLNAME))
|
|
nErrorIds = idsStartupCantFindMSOEDLL;
|
|
else
|
|
nErrorIds = idsStartupModNotFoundMSOEDLL;
|
|
}
|
|
else if (dwError == ERROR_DLL_INIT_FAILED)
|
|
{
|
|
if (0xffffffff == GetFileAttributes(c_szLangDll))
|
|
nErrorIds = idsStartupCantFindResMSOEDLL;
|
|
else
|
|
nErrorIds = idsStartupDllInitFailedMSOEDLL;
|
|
}
|
|
else
|
|
{
|
|
nErrorIds = idsStartupCantLoadMSOEDLL;
|
|
}
|
|
|
|
goto exit;
|
|
}
|
|
|
|
// Unlikely that this will fail
|
|
pfnStart = (PFNSTART)GetProcAddress(hInstMSOEDLL, STR_MSOEAPI_START);
|
|
|
|
// Did that Fail
|
|
if (NULL == pfnStart)
|
|
{
|
|
nErrorIds = idsStartupCantLoadMSOEDLL;
|
|
goto exit;
|
|
}
|
|
|
|
hrOE = S_RESTART_OE;
|
|
|
|
while (S_RESTART_OE == hrOE)
|
|
{
|
|
hrOE = pfnStart(MSOEAPI_START_APPLICATION, (fFirstID ? pwszCmdLine : c_wszEmpty), nCmdShow);
|
|
fFirstID = FALSE;
|
|
}
|
|
|
|
// NB: pfnInit will not return until the main message pump terminates
|
|
if (SUCCEEDED(hrOE))
|
|
{
|
|
CloseHandle(hMutex);
|
|
hMutex = NULL;
|
|
}
|
|
|
|
// The dll couldn't be loaded, as long as it wasn't due to need for ICW, display error
|
|
else if (hrOE != hrUserCancel && hrOE != MAPI_E_USER_CANCEL)
|
|
{
|
|
nErrorIds = idsStartupCantInitMSOEDLL;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
// Cleanup
|
|
if (hMutex)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
CloseHandle(hMutex);
|
|
}
|
|
|
|
// Free msoe.dll
|
|
if (hInstMSOEDLL)
|
|
FreeLibrary(hInstMSOEDLL);
|
|
|
|
// Show an error ?
|
|
if (0 != nErrorIds)
|
|
{
|
|
// Locals
|
|
CHAR szRes[255];
|
|
CHAR szTitle[100];
|
|
|
|
// Load the
|
|
LoadString(hInst, idsOutlookExpress, szTitle, ARRAYSIZE(szTitle));
|
|
|
|
// Load the
|
|
LoadString(hInst, nErrorIds, szRes, ARRAYSIZE(szRes));
|
|
|
|
// Show the error message
|
|
MessageBox(NULL, szRes, szTitle, MB_OK | MB_SETFOREGROUND | MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
|
|
IF_DEBUG(CoRevokeMallocSpy());
|
|
|
|
// Done
|
|
return nErrorIds;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
// --------------------------------------------------------------------------------
|
|
// LoadMSHTMDBG
|
|
// --------------------------------------------------------------------------------
|
|
void LoadMSHTMDBG(LPWSTR pwszCmdLine)
|
|
{
|
|
// Load mshtmdbg.dll
|
|
HINSTANCE hInstDebug = LoadLibrary(c_szDebug);
|
|
|
|
// Did it load ?
|
|
if (NULL != hInstDebug)
|
|
{
|
|
// Locals
|
|
PFNREGSPY pfnRegSpy;
|
|
|
|
// If the user passed /d on the command line, lets configure mshtmdbg.dll
|
|
if (0 == StrCmpIW(pwszCmdLine, c_wszInvokeUI))
|
|
{
|
|
// Locals
|
|
PFNDEBUGUI pfnDebugUI;
|
|
|
|
// Get the proc address of the UI
|
|
pfnDebugUI = (PFNDEBUGUI)GetProcAddress(hInstDebug, c_szDebugUI);
|
|
if (NULL != pfnDebugUI)
|
|
{
|
|
(*pfnDebugUI)(TRUE);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// Get the process address of the registration
|
|
pfnRegSpy = (PFNREGSPY)GetProcAddress(hInstDebug, c_szRegSpy);
|
|
if (NULL != pfnRegSpy)
|
|
{
|
|
LPMALLOCSPY pSpy = (IMallocSpy *)(*pfnRegSpy)();
|
|
SideAssert(SUCCEEDED(CoRegisterMallocSpy(pSpy)));
|
|
}
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return;
|
|
}
|
|
#endif // DEBUG
|