Windows2003-3790/inetcore/outlookexpress/shell/msimn.c
2020-09-30 16:53:55 +02:00

384 lines
12 KiB
C

// --------------------------------------------------------------------------------
// 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