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.
627 lines
18 KiB
627 lines
18 KiB
// --------------------------------------------------------------------------------
|
|
// Migrate.cpp
|
|
// --------------------------------------------------------------------------------
|
|
#define INITGUID
|
|
#include "pch.hxx"
|
|
#include <initguid.h>
|
|
#define DEFINE_STRCONST
|
|
#include <mimeole.h>
|
|
#include "migrate.h"
|
|
#include "utility.h"
|
|
#include "resource.h"
|
|
#include "migerror.h"
|
|
#include <oestore.h>
|
|
#include "structs.h"
|
|
#include "strparse.h"
|
|
#include "msident.h"
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Debug Strings
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
static const TCHAR c_szDebug[] = "mshtmdbg.dll";
|
|
static const TCHAR c_szDebugUI[] = "DoTracePointsDialog";
|
|
static const TCHAR c_szRegSpy[] = "DbgRegisterMallocSpy";
|
|
static const TCHAR c_szInvokeUI[] = "/d";
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MSHTMDBG.DLL Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
typedef void (STDAPICALLTYPE *PFNDEBUGUI)(BOOL);
|
|
typedef void (STDAPICALLTYPE *PFNREGSPY)(void);
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Debug Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
#ifdef DEBUG
|
|
HINSTANCE g_hInstDebug=NULL;
|
|
void LoadMSHTMDBG(LPSTR pszCmdLine);
|
|
#endif
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Globals
|
|
// --------------------------------------------------------------------------------
|
|
IMalloc *g_pMalloc=NULL;
|
|
HINSTANCE g_hInst=NULL;
|
|
DWORD g_dwTlsMsgBuffIndex=0xffffffff;
|
|
DWORD g_cbDiskNeeded=0;
|
|
DWORD g_cbDiskFree=0;
|
|
ACCOUNTTABLE g_AcctTable={0};
|
|
BOOL g_fQuiet = FALSE;
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Prototypes
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT DowngradeV5B1(MIGRATETOTYPE tyMigrate, LPCSTR pszStoreRoot, LPPROGRESSINFO pProgress, LPFILEINFO *ppHeadFile);
|
|
INT_PTR CALLBACK MigrageErrorDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
HRESULT UpgradeV5(MIGRATETOTYPE tyMigrate, LPCSTR pszStoreSrc, LPCSTR pszStoreDst, LPPROGRESSINFO pProgress, LPFILEINFO *ppHeadFile);
|
|
HRESULT ParseCommandLine(LPCSTR pszCmdLine, LPSTR pszMigrate, DWORD cbMigrateMax,
|
|
LPSTR pszStoreSrc, DWORD cbStoreSrc, LPSTR pszStoreDst, DWORD cbStoreDst,
|
|
LPSTR pszUserKey, DWORD cbUserKey);
|
|
HRESULT RemapUsersKey(LPSTR pszUsersKey);
|
|
void ThreadAllocateTlsMsgBuffer(void);
|
|
void ThreadFreeTlsMsgBuffer(void);
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// How big is the thread local storage string buffer
|
|
// -------------------------------------------------------------------------------
|
|
#define CBMAX_THREAD_TLS_BUFFER 512
|
|
|
|
#define ICC_FLAGS (ICC_PROGRESS_CLASS|ICC_NATIVEFNTCTL_CLASS)
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// WinMain
|
|
//
|
|
// Command Line Format:
|
|
// --------------------
|
|
// /type:V1+V4-V5 /src:"Source Store Root" /dst:"Destination Store Root"
|
|
// --------------------------------------------------------------------------------
|
|
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR pszCmdLine, int nCmdShow)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
PROGRESSINFO Progress={0};
|
|
CHAR szMigrate[50];
|
|
CHAR szStoreSrc[MAX_PATH];
|
|
CHAR szStoreDst[MAX_PATH];
|
|
CHAR szUsersKey[MAX_PATH];
|
|
LPFILEINFO pHeadFile=NULL;
|
|
MIGRATETOTYPE tyMigrate;
|
|
CHAR szMsg[512];
|
|
HANDLE hMutex=NULL;
|
|
INITCOMMONCONTROLSEX icex = { sizeof(icex), ICC_FLAGS };
|
|
|
|
// Tracing
|
|
TraceCall("WinMain");
|
|
|
|
// Validation
|
|
Assert(sizeof(TABLEHEADERV5B1) == sizeof(TABLEHEADERV5));
|
|
|
|
// Create Mutex
|
|
IF_NULLEXIT(hMutex = CreateMutex(NULL, FALSE, "OutlookExpressMigration"));
|
|
|
|
// Wait for the Mutex
|
|
if (WAIT_FAILED == WaitForSingleObject(hMutex, INFINITE))
|
|
{
|
|
hr = TraceResult(E_FAIL);
|
|
goto exit;
|
|
}
|
|
|
|
// Initialzie OLE
|
|
IF_FAILEXIT(hr = CoInitialize(NULL));
|
|
|
|
// Save hInst
|
|
g_hInst = hInst;
|
|
|
|
// Load Debug DLL
|
|
IF_DEBUG(LoadMSHTMDBG(pszCmdLine);)
|
|
|
|
szUsersKey[0] = 0;
|
|
|
|
// Crack the command line
|
|
IF_FAILEXIT(hr = ParseCommandLine(pszCmdLine, szMigrate, ARRAYSIZE(szMigrate), szStoreSrc, ARRAYSIZE(szStoreSrc), szStoreDst, ARRAYSIZE(szStoreDst), szUsersKey, ARRAYSIZE(szUsersKey)));
|
|
|
|
// Load the user hive, if needed
|
|
IF_FAILEXIT(RemapUsersKey(szUsersKey));
|
|
|
|
// Initialzie Common Controls
|
|
InitCommonControlsEx(&icex);
|
|
|
|
// Get the task allocator
|
|
IF_FAILEXIT(hr = CoGetMalloc(MEMCTX_TASK, &g_pMalloc));
|
|
|
|
// Tlsalloc
|
|
g_dwTlsMsgBuffIndex = TlsAlloc();
|
|
|
|
// allocat
|
|
ThreadAllocateTlsMsgBuffer();
|
|
|
|
// Create Dialog
|
|
if(!g_fQuiet)
|
|
{
|
|
Progress.hwndProgress = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_PROGRESS), GetDesktopWindow(), MigrageDlgProc);
|
|
|
|
// Bad Mojo
|
|
if (NULL == Progress.hwndProgress)
|
|
{
|
|
hr = TraceResult(E_FAIL);
|
|
goto exit;
|
|
}
|
|
|
|
// Center
|
|
CenterDialog(Progress.hwndProgress);
|
|
|
|
// Show the Window
|
|
ShowWindow(Progress.hwndProgress, SW_NORMAL);
|
|
}
|
|
|
|
// V5-V4
|
|
if (lstrcmpi(szMigrate, "V5-V4") == 0)
|
|
{
|
|
// Locals
|
|
CHAR szRes[255];
|
|
CHAR szCaption[255];
|
|
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_IMPORTMSG, szRes, ARRAYSIZE(szRes));
|
|
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_TITLE, szCaption, ARRAYSIZE(szCaption));
|
|
|
|
// Message
|
|
if(!g_fQuiet)
|
|
MessageBox(NULL, szRes, szCaption, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
// Done
|
|
goto exit;
|
|
}
|
|
|
|
// V5-V1
|
|
else if (lstrcmpi(szMigrate, "V5-V1") == 0)
|
|
{
|
|
// Locals
|
|
CHAR szRes[255];
|
|
CHAR szCaption[255];
|
|
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_V1NYI, szRes, ARRAYSIZE(szRes));
|
|
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_TITLE, szCaption, ARRAYSIZE(szCaption));
|
|
|
|
// Message
|
|
if(!g_fQuiet)
|
|
MessageBox(NULL, szRes, szCaption, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
// Done
|
|
goto exit;
|
|
}
|
|
|
|
// V1-V5 or V4-V5
|
|
else if (lstrcmpi(szMigrate, "V1+V4-V5") == 0)
|
|
{
|
|
// Build the Account Table - Takes path to accounts not IAM
|
|
IF_FAILEXIT(hr = BuildAccountTable(HKEY_CURRENT_USER, "Software\\Microsoft\\Internet Account Manager\\Accounts", szStoreSrc, &g_AcctTable));
|
|
|
|
// Set tyMigrate
|
|
tyMigrate = UPGRADE_V1_OR_V4_TO_V5;
|
|
|
|
// RegressFromV5ToV4orV1
|
|
hr = UpgradeV5(tyMigrate, szStoreSrc, szStoreDst, &Progress, &pHeadFile);
|
|
}
|
|
|
|
// V5B1-V1
|
|
else if (lstrcmpi(szMigrate, "V5B1-V1") == 0)
|
|
{
|
|
// Set tyMigrate
|
|
tyMigrate = DOWNGRADE_V5B1_TO_V4;
|
|
|
|
hr = DowngradeV5B1(tyMigrate, szStoreSrc, &Progress, &pHeadFile);
|
|
}
|
|
|
|
// V5B1-V4
|
|
else if (lstrcmpi(szMigrate, "V5B1-V4") == 0)
|
|
{
|
|
// Set tyMigrate
|
|
tyMigrate = DOWNGRADE_V5B1_TO_V4;
|
|
|
|
hr = DowngradeV5B1(tyMigrate, szStoreSrc, &Progress, &pHeadFile);
|
|
}
|
|
|
|
// Bad Command Line
|
|
else
|
|
{
|
|
// Bad Command Line
|
|
AssertSz(FALSE, "Invalid Command line arguments passed into oemig50.exe");
|
|
|
|
// Failure
|
|
hr = TraceResult(E_FAIL);
|
|
|
|
// Done
|
|
goto exit;
|
|
}
|
|
|
|
// Kill the Window
|
|
if(!g_fQuiet)
|
|
DestroyWindow(Progress.hwndProgress);
|
|
Progress.hwndProgress = NULL;
|
|
|
|
// Write Migration Log File
|
|
WriteMigrationLogFile(hr, GetLastError(), szStoreSrc, szMigrate, pszCmdLine, pHeadFile);
|
|
|
|
// Trace It
|
|
if (FAILED(hr))
|
|
{
|
|
// Trace It
|
|
TraceResult(hr);
|
|
|
|
// Handle the Error message
|
|
if (MIGRATE_E_NOTENOUGHDISKSPACE == hr)
|
|
{
|
|
// Locals
|
|
CHAR szRes[255];
|
|
CHAR szScratch1[50];
|
|
CHAR szScratch2[50];
|
|
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_DISKSPACEERROR, szRes, ARRAYSIZE(szRes));
|
|
|
|
// Format the Error
|
|
wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, StrFormatByteSize64A(g_cbDiskNeeded, szScratch1, ARRAYSIZE(szScratch1)), StrFormatByteSize64A(g_cbDiskFree, szScratch2, ARRAYSIZE(szScratch2)));
|
|
}
|
|
|
|
// Sharing Violation...
|
|
else if (MIGRATE_E_SHARINGVIOLATION == hr)
|
|
{
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_SHARINGVIOLATION, szMsg, ARRAYSIZE(szMsg));
|
|
}
|
|
|
|
// General Failure
|
|
else
|
|
{
|
|
// LoadString
|
|
LoadString(g_hInst, IDS_GENERALERROR, szMsg, ARRAYSIZE(szMsg));
|
|
}
|
|
|
|
// Do the dialog
|
|
if(!g_fQuiet)
|
|
hr = (HRESULT) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MIGRATEERROR), NULL, MigrageErrorDlgProc, (LPARAM)szMsg);
|
|
}
|
|
|
|
// Otherwise, success
|
|
else
|
|
hr = MIGRATE_S_SUCCESS;
|
|
|
|
exit:
|
|
// Cleanup
|
|
SafeMemFree(g_AcctTable.prgAccount);
|
|
FreeFileList(&pHeadFile);
|
|
if (Progress.hwndProgress)
|
|
DestroyWindow(Progress.hwndProgress);
|
|
ThreadFreeTlsMsgBuffer();
|
|
if (0xffffffff != g_dwTlsMsgBuffIndex)
|
|
TlsFree(g_dwTlsMsgBuffIndex);
|
|
SafeRelease(g_pMalloc);
|
|
|
|
IF_DEBUG(if (g_hInstDebug) FreeLibrary(g_hInstDebug);)
|
|
|
|
// Cleanup
|
|
CoUninitialize();
|
|
|
|
// Release the mutex
|
|
if (hMutex)
|
|
{
|
|
ReleaseMutex(hMutex);
|
|
CloseHandle(hMutex);
|
|
}
|
|
|
|
// Done
|
|
return (INT)hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ParseCommandLine
|
|
// -------------------------------------------------------------------------------
|
|
HRESULT ParseCommandLine(LPCSTR pszCmdLine, LPSTR pszMigrate, DWORD cbMigrate,
|
|
LPSTR pszStoreSrc, DWORD cbStoreSrc, LPSTR pszStoreDst, DWORD cbStoreDst,
|
|
LPSTR pszUsersKey, DWORD cbUsersKey)
|
|
{
|
|
// Locals
|
|
HRESULT hr=S_OK;
|
|
CHAR chToken;
|
|
CStringParser cParser;
|
|
|
|
// Trace
|
|
TraceCall("ParseCommandLine");
|
|
|
|
// Initialize
|
|
*pszMigrate = *pszStoreSrc = *pszStoreDst = '\0';
|
|
|
|
// Init
|
|
cParser.Init(pszCmdLine, lstrlen(pszCmdLine), PSF_DBCS | PSF_NOTRAILWS | PSF_NOFRONTWS);
|
|
|
|
// Parse to first /
|
|
chToken = cParser.ChParse("/");
|
|
if ('/' != chToken)
|
|
goto exit;
|
|
|
|
// Parse to :
|
|
chToken = cParser.ChParse(":");
|
|
if (':' != chToken)
|
|
goto exit;
|
|
|
|
// Check parameter name
|
|
if (0 != lstrcmpi(cParser.PszValue(), "type"))
|
|
goto exit;
|
|
|
|
// Parse to /
|
|
chToken = cParser.ChParse("/");
|
|
if ('/' != chToken)
|
|
goto exit;
|
|
|
|
// Copy the Value
|
|
StrCpyN(pszMigrate, cParser.PszValue(), cbMigrate - 1);
|
|
|
|
// Parse to :
|
|
chToken = cParser.ChParse(":");
|
|
if (':' != chToken)
|
|
goto exit;
|
|
|
|
// Check parameter name
|
|
if (0 != lstrcmpi(cParser.PszValue(), "src"))
|
|
goto exit;
|
|
|
|
// Parse to /
|
|
chToken = cParser.ChParse("/");
|
|
if ('/' != chToken)
|
|
goto exit;
|
|
|
|
// Copy the Value
|
|
StrCpyN(pszStoreSrc, cParser.PszValue(), cbStoreSrc - 1);
|
|
|
|
// Parse to :
|
|
chToken = cParser.ChParse(":");
|
|
if (':' != chToken)
|
|
goto exit;
|
|
|
|
// Check parameter name
|
|
if (0 != lstrcmpi(cParser.PszValue(), "dst"))
|
|
goto exit;
|
|
|
|
// Parse to /
|
|
chToken = cParser.ChParse("/");
|
|
if (('/' != chToken) && ('\0' != chToken))
|
|
goto exit;
|
|
|
|
// Copy the Value
|
|
StrCpyN(pszStoreDst, cParser.PszValue(), cbStoreDst - 1);
|
|
|
|
if ('/' == chToken)
|
|
{
|
|
chToken = cParser.ChParse("/");
|
|
if ('\0' == chToken || '/' == chToken)
|
|
{
|
|
if (0 == lstrcmpi(cParser.PszValue(), "quiet"))
|
|
g_fQuiet = TRUE;
|
|
}
|
|
}
|
|
|
|
if ('/' == chToken)
|
|
{
|
|
// Parse to :
|
|
chToken = cParser.ChParse(":");
|
|
if (':' == chToken)
|
|
{
|
|
// Check parameter name
|
|
if (0 == lstrcmpi(cParser.PszValue(), "key"))
|
|
{
|
|
// Parse to end
|
|
chToken = cParser.ChParse("");
|
|
if ('\0' == chToken)
|
|
{
|
|
// Copy the Value
|
|
StrCpyN(pszUsersKey, cParser.PszValue(), cbUsersKey - 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
// Failure Already
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
// Set hr
|
|
hr = (*pszMigrate == '\0' || *pszStoreSrc == '\0' || *pszStoreDst == '\0') ? E_FAIL : S_OK;
|
|
|
|
// Assert
|
|
AssertSz(SUCCEEDED(hr), "Invalid Command line passed into oemig50.exe.");
|
|
|
|
// Done
|
|
return(hr);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// LoadUserHive
|
|
// -------------------------------------------------------------------------------
|
|
HRESULT RemapUsersKey(LPSTR pszUsersKey)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
HKEY hKey;
|
|
|
|
if (pszUsersKey && *pszUsersKey) {
|
|
// Open the user's key
|
|
hr = RegOpenKey (HKEY_USERS, pszUsersKey, &hKey);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
// Remap HKCU to point to the user's key
|
|
hr = RegOverridePredefKey (HKEY_CURRENT_USER, hKey);
|
|
|
|
// Close the key
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadAllocateTlsMsgBuffer
|
|
// -------------------------------------------------------------------------------
|
|
void ThreadAllocateTlsMsgBuffer(void)
|
|
{
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
TlsSetValue(g_dwTlsMsgBuffIndex, NULL);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// ThreadFreeTlsMsgBuffer
|
|
// -------------------------------------------------------------------------------
|
|
void ThreadFreeTlsMsgBuffer(void)
|
|
{
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
{
|
|
LPSTR psz = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
|
|
SafeMemFree(psz);
|
|
SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, NULL));
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// PszGetTlsBuffer
|
|
// -------------------------------------------------------------------------------
|
|
LPSTR PszGetTlsBuffer(void)
|
|
{
|
|
// Get the buffer
|
|
LPSTR pszBuffer = (LPSTR)TlsGetValue(g_dwTlsMsgBuffIndex);
|
|
|
|
// If buffer has not been allocated
|
|
if (NULL == pszBuffer)
|
|
{
|
|
// Allocate it
|
|
pszBuffer = (LPSTR)g_pMalloc->Alloc(CBMAX_THREAD_TLS_BUFFER);
|
|
|
|
// Store it
|
|
Assert(pszBuffer);
|
|
SideAssert(0 != TlsSetValue(g_dwTlsMsgBuffIndex, pszBuffer));
|
|
}
|
|
|
|
// Done
|
|
return pszBuffer;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// _MSG - Used to build a string from variable length args, thread-safe
|
|
// -------------------------------------------------------------------------------
|
|
LPCSTR _MSG(LPSTR pszFormat, ...)
|
|
{
|
|
// Locals
|
|
va_list arglist;
|
|
LPSTR pszBuffer=NULL;
|
|
|
|
// I use tls to hold the buffer
|
|
if (g_dwTlsMsgBuffIndex != 0xffffffff)
|
|
{
|
|
// Setup the arglist
|
|
va_start(arglist, pszFormat);
|
|
|
|
// Get the Buffer
|
|
pszBuffer = PszGetTlsBuffer();
|
|
|
|
// If we have a buffer
|
|
if (pszBuffer)
|
|
{
|
|
// Format the data
|
|
wvnsprintf(pszBuffer, CBMAX_THREAD_TLS_BUFFER, pszFormat, arglist);
|
|
}
|
|
|
|
// End the arglist
|
|
va_end(arglist);
|
|
}
|
|
|
|
return ((LPCSTR)pszBuffer);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MigrageErrorDlgProc
|
|
// --------------------------------------------------------------------------------
|
|
INT_PTR CALLBACK MigrageErrorDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetForegroundWindow(hwnd);
|
|
CenterDialog(hwnd);
|
|
SetDlgItemText(hwnd, IDS_MESSAGE, (LPSTR)lParam);
|
|
CheckDlgButton(hwnd, IDR_DONTSTARTOE, BST_CHECKED);
|
|
SetFocus(GetDlgItem(hwnd, IDR_DONTSTARTOE));
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
switch(GET_WM_COMMAND_ID(wParam,lParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
if (IsDlgButtonChecked(hwnd, IDR_DONTSTARTOE))
|
|
EndDialog(hwnd, MIGRATE_E_NOCONTINUE);
|
|
else if (IsDlgButtonChecked(hwnd, IDR_STARTOE))
|
|
EndDialog(hwnd, MIGRATE_S_SUCCESS);
|
|
return 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Done
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
// --------------------------------------------------------------------------------
|
|
// LoadMSHTMDBG
|
|
// --------------------------------------------------------------------------------
|
|
void LoadMSHTMDBG(LPSTR pszCmdLine)
|
|
{
|
|
// Load mshtmdbg.dll
|
|
HINSTANCE g_hInstDebug = LoadLibrary(c_szDebug);
|
|
|
|
// Did it load ?
|
|
if (NULL != g_hInstDebug)
|
|
{
|
|
// Locals
|
|
PFNREGSPY pfnRegSpy;
|
|
|
|
// If the user passed /d on the command line, lets configure mshtmdbg.dll
|
|
if (0 == lstrcmpi(pszCmdLine, c_szInvokeUI))
|
|
{
|
|
// Locals
|
|
PFNDEBUGUI pfnDebugUI;
|
|
|
|
// Get the proc address of the UI
|
|
pfnDebugUI = (PFNDEBUGUI)GetProcAddress(g_hInstDebug, c_szDebugUI);
|
|
if (NULL != pfnDebugUI)
|
|
{
|
|
(*pfnDebugUI)(TRUE);
|
|
goto exit;
|
|
}
|
|
|
|
// Done
|
|
exit(1);
|
|
}
|
|
|
|
// Get the process address of the registration
|
|
pfnRegSpy = (PFNREGSPY)GetProcAddress(g_hInstDebug, c_szRegSpy);
|
|
if (NULL != pfnRegSpy)
|
|
(*pfnRegSpy)();
|
|
}
|
|
|
|
exit:
|
|
// Done
|
|
return;
|
|
}
|
|
#endif // DEBUG
|
|
|