Leaked source code of windows server 2003
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.
 
 
 
 
 
 

749 lines
24 KiB

/*
* ENTRY.C
*
* DLL entry functions for extended MAPI. Mostly for debugging
* purposes.
*/
#include <_apipch.h>
#include <advpub.h>
#include "htmlhelp.h"
#include <shlwapi.h>
#define _ENTRY_C
#ifdef MAC
#include <utilmac.h>
#define PvGetInstanceGlobals() PvGetInstanceGlobalsMac(kInstMAPIX)
#endif
#ifndef MB_SETFOREGROUND
#define MB_SETFOREGROUND 0
#endif
#ifdef DEBUG
void ExitCheckInstance(LPINST pinst);
void ExitCheckInstUtil(LPINSTUTIL pinstUtil);
#endif
HINSTANCE hinstMapiX = NULL; // Instance to the WAB resources module (wab32res.dll)
HINSTANCE hinstMapiXWAB = NULL; // Instance of the WAB32.dll module (this dll)
#if 0
// @todo [PaulHi] DLL Leak. Remove this or implement
extern CRITICAL_SECTION csOMIUnload;
#endif
BOOL fGlobalCSValid = FALSE;
// Global handle for CommCtrl DLL
HINSTANCE ghCommCtrlDLLInst = NULL;
ULONG gulCommCtrlDLLRefCount = 0;
extern void DeinitCommDlgLib();
// Global fontinit for UI
BOOL bInitFonts = FALSE;
BOOL g_bRunningOnNT = TRUE; // Checks the OS we run on so Unicode calls can be thunked to Win9x
BOOL bDNisByLN = FALSE; // Language dependent flag that tells us if the default
// display name should be by first name or last name.
TCHAR szResourceDNByLN[32]; // cache the formatting strings so we load them only once
TCHAR szResourceDNByFN[32];
TCHAR szResourceDNByCommaLN[32];
BOOL bPrintingOn = TRUE;// Locale dependent flag that tells us to remove printing entirely
// from the UI
// When running against Outlook, we need a way for Outlook
// to signal us about store changes so we can refresh the UI. There are 2
// events we are interested in - 1. to update the list of contact folders
// and 2 to update the list of contacts - we will use 2 events for this
//
HANDLE ghEventOlkRefreshContacts = NULL;
HANDLE ghEventOlkRefreshFolders = NULL;
static const char cszEventOlkRefreshContacts[] = "WAB_Outlook_Event_Refresh_Contacts";
static const char cszEventOlkRefreshFolders[] = "WAB_Outlook_Event_Refresh_Folders";
typedef HRESULT (CALLBACK* SHDLLGETVERSIONPROC)(DLLVERSIONINFO *);
typedef HINSTANCE (STDAPICALLTYPE *PFNMLLOADLIBARY)(LPCTSTR lpLibFileName, HMODULE hModule, DWORD dwCrossCodePage);
typedef int (STDAPICALLTYPE *PFNMLWINHELP)(HWND hWndCaller, LPCTSTR lpszHelp, UINT uCommand, DWORD_PTR dwData);
typedef HWND (STDAPICALLTYPE *PFNMLHTMLHELP)(HWND hWndCaller, LPCTSTR pszFile, UINT uCommand, DWORD_PTR dwData, DWORD dwCrossCodePage);
///////////////////////////////////////////////////////////////////////////////
// bCheckifRunningOnWinNT5
///////////////////////////////////////////////////////////////////////////////
BOOL bCheckifRunningOnWinNT5()
{
OSVERSIONINFO osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 5);
}
///////////////////////////////////////////////////////////////////////////////
// Load the WAB resource DLL. This is done every time the WAB32.DLL is loaded.
// If we have a version 5 or greater SHLWAPI.DLL then we should use the load
// library function API there. If we are running NT5 or greater then we
// use the special cross codepage support.
// Also use the new PlugUI version of WinHelp and HtmlHelp APIs in SHLWAPI.DLL
///////////////////////////////////////////////////////////////////////////////
// Copied from shlwapip.h, yuck.
#define ML_NO_CROSSCODEPAGE 0
#define ML_CROSSCODEPAGE_NT 1
static const TCHAR c_szShlwapiDll[] = TEXT("shlwapi.dll");
static const char c_szDllGetVersion[] = "DllGetVersion";
static const TCHAR c_szWABResourceDLL[] = TEXT("wab32res.dll");
static const TCHAR c_szWABDLL[] = TEXT("wab32.dll");
///////////////////////////////////////////////////////////////////////////////
// LoadWABResourceDLL
//
// Load the WAB resource DLL using the IE5 or greater Shlwapi.dll LoadLibrary
// function if available. Otherwise use the system LoadLibrary function.
//
// Input Params: hInstWAB32 - handle to WAB DLL
//
// Returns handle to the loaded resource DLL
///////////////////////////////////////////////////////////////////////////////
HINSTANCE LoadWABResourceDLL(HINSTANCE hInstWAB32)
{
TCHAR szPath[MAX_PATH];
HINSTANCE hInst = NULL;
HINSTANCE hinstShlwapi = LoadLibrary(c_szShlwapiDll);
PFNMLLOADLIBARY pfnLoadLibrary = NULL;
if (hinstShlwapi)
{
SHDLLGETVERSIONPROC pfnVersion;
DLLVERSIONINFO info = {0};
pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hinstShlwapi, c_szDllGetVersion);
if (pfnVersion)
{
info.cbSize = sizeof(DLLVERSIONINFO);
if (SUCCEEDED(pfnVersion(&info)))
{
if (info.dwMajorVersion >= 5)
pfnLoadLibrary = (PFNMLLOADLIBARY)GetProcAddress(hinstShlwapi, (LPCSTR)378); // UNICODE ordinal
}
}
}
// We have special cross codepage support on NT5 and on.
if (pfnLoadLibrary)
{
hInst = pfnLoadLibrary(c_szWABResourceDLL, hInstWAB32,
bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
}
if (!hInst)
hInst = LoadLibrary(c_szWABResourceDLL);
// Try full path name for resource DLL
if ( !hInst && (GetModuleFileName(hInstWAB32, szPath, CharSizeOf(szPath))) )
{
int iEnd;
iEnd = lstrlen(szPath) - lstrlen(c_szWABDLL);
StrCpyN(&szPath[iEnd], c_szWABResourceDLL, ARRAYSIZE(szPath)-iEnd);
if (pfnLoadLibrary)
{
hInst = pfnLoadLibrary(szPath, hInstWAB32,
bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
}
if (!hInst)
hInst = LoadLibrary(szPath);
}
if (hinstShlwapi)
FreeLibrary(hinstShlwapi);
AssertSz(hInst, TEXT("Failed to LoadLibrary Lang Dll"));
return(hInst);
}
// PlugUI version of WinHelp
BOOL WinHelpWrap(HWND hWndCaller, LPCTSTR pwszHelpFile, UINT uCommand, DWORD_PTR dwData)
{
static s_fChecked = FALSE; // Only look for s_pfnWinHelp once
static PFNMLWINHELP s_pfnWinHelp = NULL;
if (!s_pfnWinHelp && !s_fChecked)
{
HINSTANCE hShlwapi = DemandLoadShlwapi();
s_fChecked = TRUE;
if (hShlwapi)
{
// Check version of the shlwapi.dll
SHDLLGETVERSIONPROC pfnVersion;
DLLVERSIONINFO info = {0};
pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hShlwapi, c_szDllGetVersion);
if (pfnVersion)
{
info.cbSize = sizeof(DLLVERSIONINFO);
if (SUCCEEDED(pfnVersion(&info)))
{
if (info.dwMajorVersion >= 5)
s_pfnWinHelp = (PFNMLWINHELP)GetProcAddress(hShlwapi, (LPCSTR)397); // UNICODE ordinal
}
}
}
}
if (s_pfnWinHelp)
return s_pfnWinHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
// [PaulHi] Win9X version of WinHelpW doesn't work
if (g_bRunningOnNT)
return WinHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
else
{
LPSTR pszHelpFile = ConvertWtoA(pwszHelpFile);
BOOL bRtn = WinHelpA(hWndCaller, (LPCSTR)pszHelpFile, uCommand, dwData);
LocalFreeAndNull(&pszHelpFile);
return bRtn;
}
}
// PlugUI version of HtmlHelp
HWND HtmlHelpWrap(HWND hWndCaller, LPCTSTR pwszHelpFile, UINT uCommand, DWORD_PTR dwData)
{
static s_fChecked = FALSE; // Only look for s_pfnHtmlHelp once
static PFNMLHTMLHELP s_pfnHtmlHelp = NULL;
if (!s_pfnHtmlHelp && !s_fChecked)
{
HINSTANCE hShlwapi = DemandLoadShlwapi();
s_fChecked = TRUE;
if (hShlwapi)
{
// Check version of the shlwapi.dll
SHDLLGETVERSIONPROC pfnVersion;
DLLVERSIONINFO info = {0};
pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hShlwapi, c_szDllGetVersion);
if (pfnVersion)
{
info.cbSize = sizeof(DLLVERSIONINFO);
if (SUCCEEDED(pfnVersion(&info)))
{
if (info.dwMajorVersion >= 5)
s_pfnHtmlHelp = (PFNMLHTMLHELP)GetProcAddress(hShlwapi, (LPCSTR)398); // UNICODE ordinal
}
}
}
}
if (s_pfnHtmlHelp)
return s_pfnHtmlHelp(hWndCaller, pwszHelpFile, uCommand, dwData,
bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
// [PaulHi] Wide chars work Ok on Win9X
return HtmlHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
}
/*
-
- CheckifRunningOnWinNT
*
* Checks the OS we are running on and returns TRUE for WinNT
* False for Win9x
*/
BOOL bCheckifRunningOnWinNT()
{
OSVERSIONINFO osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#if defined(WIN32) && !defined(MAC)
/*
* DLL entry point for Win32
*/
BOOL WINAPI
DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpvReserved)
{
LPPTGDATA lpPTGData=NULL;
switch ((short)dwReason)
{
case DLL_PROCESS_ATTACH:
// allocate a TLS index
g_bRunningOnNT = bCheckifRunningOnWinNT();
if ((dwTlsIndex = TlsAlloc()) == 0xfffffff)
return FALSE;
hinstMapiXWAB = hinst;
hinstMapiX = LoadWABResourceDLL(hinstMapiXWAB);
Assert(hinstMapiX);
if(!hinstMapiX)
{
DWORD dwCode = GetLastError();
DebugTrace(TEXT("WAB32 Resource load failed: %d\n"), dwCode);
}
g_msgMSWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
bInitFonts = InitFonts();
// The WAB does a lot of DisplayName formatting and DisplayName parsing
// For western names we can always assume thathe the First Name comes
// first in the display name. However for FE and some locales like Hungarian,
// this is not true so the WAB needs to know when it can assume the
// First Name comes first and when it can Assume that the first name
// comes last ... so localizers set a flag .. if the string
// idsLangDisplayNameisByLastName is set to "1" then we know that the
// default names for this language start with the last name
// The localizers also set the format templates for defining how a name
// should be created from the First/Middle/Last names .. for example,
// in Japanese it is "L F" (no comma) while elsewhere it could be "L,F"
// All these things are set in localization...
{
TCHAR szBuf[32];
const LPTSTR lpszOne = TEXT("1");
const LPTSTR lpszDefFormatName = TEXT("%1% %2% %3");
LoadString(hinstMapiX, idsLangDisplayNameIsByLastName, szBuf, CharSizeOf(szBuf));
// if szBuf == "1" then Yes, its by last name .. else its not
TrimSpaces(szBuf);
if (!lstrcmpi(szBuf,lpszOne))
bDNisByLN = TRUE;
else
bDNisByLN = FALSE;
DebugTrace(TEXT("bDNisByLN: %d\n"),bDNisByLN);
// The DNbyLN can be formed using a comma for western and without a comma for most FE and hungarian ..
// So if the localizers set the lang default to be by LN, then we use the version without the comma,
// else we use the version with the comma ..
LoadString( hinstMapiX,idsDisplayNameByLastName,szResourceDNByLN,CharSizeOf(szResourceDNByLN));
if(!lstrlen(szResourceDNByLN)) //for whatever reason .. cant afford to fail here
StrCpyN(szResourceDNByLN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
LoadString( hinstMapiX,idsDisplayNameByCommaLastName,szResourceDNByCommaLN,CharSizeOf(szResourceDNByCommaLN));
if(!lstrlen(szResourceDNByCommaLN)) //for whatever reason .. cant afford to fail here
StrCpyN(szResourceDNByCommaLN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
LoadString(hinstMapiX,idsDisplayNameByFirstName,szResourceDNByFN,CharSizeOf(szResourceDNByFN));
if(!lstrlen(szResourceDNByFN)) //for whatever reason .. cant afford to fail here
StrCpyN(szResourceDNByFN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
LoadString(hinstMapiX, idsLangPrintingOn, szBuf, CharSizeOf(szBuf));
// if szBuf == "1" then Yes, its by last name .. else its not
TrimSpaces(szBuf);
if (!lstrcmpi(szBuf,lpszOne))
bPrintingOn = TRUE;
else
bPrintingOn = FALSE;
DebugTrace(TEXT("bPrintingOn: %d\n"),bPrintingOn);
}
{
// Create the events needed for synchronizing with the outlook store
ghEventOlkRefreshContacts = CreateEventA(NULL, // security attributes
TRUE, // Manual reset
FALSE, // initial state
cszEventOlkRefreshContacts);
ghEventOlkRefreshFolders = CreateEventA(NULL, // security attributes
TRUE, // Manual reset
FALSE, // initial state
cszEventOlkRefreshFolders);
}
// Check for commoncontrol presence for UI
InitCommonControlLib();
InitializeCriticalSection(&csUnkobjInit);
InitializeCriticalSection(&csMapiInit);
InitializeCriticalSection(&csHeap);
#if 0
// @todo [PaulHi] DLL Leak. Remove this or implement
InitializeCriticalSection(&csOMIUnload);
#endif
// Critical section to protect the Address Book's SearchPathCache
// This hack is used because we can't enter the IAB's critical
// section from ABProviders call to our AdviseSink::OnNotify for
// the Merged One-off and Hierarchy tables.
InitializeCriticalSection(&csMapiSearchPath);
InitDemandLoadedLibs();
// All the CSs have been initialized
fGlobalCSValid = TRUE;
// We don't need these, so tell the OS to stop 'em
// [PaulHi] 3/8/99 Raid 73731 We DO need these calls. This is the
// only way thread local storage is deallocated. Allocation are performed
// on demand through the WAB GetThreadStoragePointer() function.
#if 0
DisableThreadLibraryCalls(hinst);
#endif
ScInitMapiUtil(0);
// No Break here - fall through to DLL_THREAD_ATTACH
// for thread initialization
case DLL_THREAD_ATTACH:
DebugTrace(TEXT("DllEntryPoint: 0x%.8x THREAD_ATTACH\n"), GetCurrentThreadId());
// [PaulHi] 3/9/99 There is no need to allocate the thread global data here
// since the WAB will allocate whenever it needs the data through the
// GetThreadStoragePointer(), i.e., on demand.
// Memory leak mentioned below should now be fixed.
#if 0
lpPTGData = GetThreadStoragePointer();
// Note the above ThreadStoragePointer seems to leak in every process
// so avoid using it for anything more...
if(!lpPTGData)
{
DebugPrintError((TEXT("DoThreadAttach: LocalAlloc() failed for thread 0x%.8x\n"), GetCurrentThreadId()));
lpPTGData = NULL;
return FALSE;
}
#endif
break;
case DLL_PROCESS_DETACH:
DebugTrace(TEXT("LibMain: 0x%.8x PROCESS_DETACH\n"), GetCurrentThreadId());
/*
if (hMuidMutex) {
CloseHandle(hMuidMutex);
hMuidMutex = NULL;
}
*/
if(ghEventOlkRefreshContacts)
{
CloseHandle(ghEventOlkRefreshContacts);
ghEventOlkRefreshContacts = NULL;
}
if(ghEventOlkRefreshFolders)
{
CloseHandle(ghEventOlkRefreshFolders);
ghEventOlkRefreshFolders = NULL;
}
if (bInitFonts)
DeleteFonts();
if(hinstMapiX)
FreeLibrary(hinstMapiX);
// Fall into DLL_THREAD_DETACH to detach last thread
case DLL_THREAD_DETACH:
DebugTrace(TEXT("LibMain: 0x%.8x THREAD_DETACH\n"), GetCurrentThreadId());
// get the thread data
lpPTGData = TlsGetValue(dwTlsIndex);
if (!lpPTGData)
{
// the thread that detaches, did not attach to the DLL. This is allowed.
DebugTrace(TEXT("LibMain: thread %x didn't attach\n"),GetCurrentThreadId());
// if this is a PROCESS_DETACH, I still want to go through the process
// detach stuff, but if it a thread detach, I'm done
if (dwReason == DLL_PROCESS_DETACH)
goto do_process_detach;
else
break;
}
if(pt_hDefFont)
DeleteObject(pt_hDefFont);
if(pt_hDlgFont)
DeleteObject(pt_hDlgFont);
// For some reason code never hits this point a lot of times
// and the threadlocalstorage data leaks.
// [PaulHi] This was because the DLL_TRHEAD_DETACH calls were turned off above,
// through DisableThreadLibraryCalls(). The leak should be fixed now.
#ifdef HM_GROUP_SYNCING
LocalFreeAndNull(&(lpPTGData->lptszHMAccountId));
#endif
LocalFreeAndNull(&lpPTGData);
// if this is THREAD_DETACH, we're done
if (dwReason == DLL_THREAD_DETACH)
break;
//N clean up jump stuff in detach
do_process_detach:
// do process detach stuff here ...
DeinitMapiUtil();
#ifdef DEBUG
{
// Don't allow asserts to spin a thread
extern BOOL fInhibitTrapThread;
fInhibitTrapThread = TRUE;
ExitCheckInstance((LPINST)PvGetInstanceGlobals());
ExitCheckInstUtil((LPINSTUTIL)PvGetInstanceGlobalsEx(lpInstUtil));
}
#endif /* DEBUG */
// Unload Common control dll
if (ghCommCtrlDLLInst != NULL)
DeinitCommCtrlClientLib();
DeinitCommDlgLib();
// Tearing down all the global CSs
fGlobalCSValid = FALSE;
DeleteCriticalSection(&csUnkobjInit);
DeleteCriticalSection(&csMapiInit);
DeleteCriticalSection(&csHeap);
#if 0
// @todo [PaulHi] DLL Leak. Remove this or implement
DeleteCriticalSection(&csOMIUnload);
#endif
DeleteCriticalSection(&csMapiSearchPath);
// release the TLS index
TlsFree(dwTlsIndex);
DeinitCryptoLib();
FreeDemandLoadedLibs();
break;
default:
DebugTrace(TEXT("MAPIX FInitMapiDll: bad dwReason %ld\n"), dwReason);
break;
}
return TRUE;
}
#endif /* WIN32 && !MAC */
#ifdef DEBUG
void
ExitCheckInstance(LPINST pinst)
{
TCHAR rgch[MAX_PATH];
TCHAR rgchTitle[128];
BOOL fAssertLeaks;
if (!pinst)
return;
if (pinst->szModName[0])
wnsprintf(rgchTitle, ARRAYSIZE(rgchTitle), TEXT("MAPIX exit checks for '%s'"), pinst->szModName);
else
StrCpyN(rgchTitle, TEXT("MAPIX exit checks"), ARRAYSIZE(rgchTitle));
DebugTrace(TEXT("%s\n"), rgchTitle);
fAssertLeaks = GetPrivateProfileInt( TEXT("General"), TEXT("AssertLeaks"), 0, TEXT("wabdbg.ini"));
// Check for Init/Deinit imbalance
if (pinst->cRef)
{
wnsprintf(rgch, ARRAYSIZE(rgch), TEXT("MAPIX: leaked %ld references"), pinst->cRef);
TraceSz1( TEXT("%s\n"), rgch);
if (fAssertLeaks)
TrapSz(rgch);
}
// Generate memory leak reports.
#if 0 // LH_DumpLeaks is not exported
// if (pinst->hlhClient)
// LH_DumpLeaks(pinst->hlhClient);
if (pinst->hlhProvider)
LH_DumpLeaks(pinst->hlhProvider);
if (pinst->hlhInternal)
LH_DumpLeaks(pinst->hlhInternal);
#else
{
HLH hlh;
if (pinst->hlhProvider)
LH_Close(pinst->hlhProvider);
hlh = pinst->hlhInternal;
if (hlh)
{
LH_Free(hlh, pinst);
LH_Close(hlh);
}
}
#endif
}
void
ExitCheckInstUtil(LPINSTUTIL pinstUtil)
{
HLH hlh;
if (!pinstUtil)
return;
hlh = pinstUtil->hlhClient;
if (hlh)
{
LH_Free(hlh, pinstUtil);
LH_Close(hlh);
}
}
#endif /* DEBUG */
#ifndef WIN16
static const char c_szReg[] = "Reg";
static const char c_szRegHandlers[] = "RegisterHandlers";
static const char c_szUnReg[] = "UnReg";
static const char c_szAdvPackDll[] = "ADVPACK.DLL";
static const TCHAR c_szWabPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
static const TCHAR c_szRegWABVerInfo[] = TEXT("Software\\Microsoft\\WAB\\Version Info");
static const TCHAR c_szIEInstallMode[] = TEXT("InstallMode");
static char c_szWAB_EXE[] = "WAB_EXE";
BOOL FRedistMode()
{
HKEY hkey;
DWORD cb;
DWORD dwInstallMode=0;
BOOL fRedist = FALSE;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWABVerInfo, 0, KEY_READ, &hkey))
{
cb = sizeof(dwInstallMode);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIEInstallMode, 0, NULL, (LPBYTE)&dwInstallMode, &cb))
{
fRedist = (dwInstallMode > 0);
}
RegCloseKey(hkey);
}
return fRedist;
}
HRESULT CallRegInstall(LPCSTR szSection)
{
HRESULT hr;
HINSTANCE hAdvPack;
REGINSTALL pfnri;
TCHAR szExe[MAX_PATH];
STRENTRY seReg;
STRTABLE stReg;
DWORD cb;
hr = E_FAIL;
hAdvPack = LoadLibraryA(c_szAdvPackDll);
if (hAdvPack != NULL)
{
// Get Proc Address for registration util
pfnri = (REGINSTALL)GetProcAddress(hAdvPack, achREGINSTALL);
if (pfnri != NULL)
{
cb = CharSizeOf(szExe);
if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, c_szWabPath, szExe, &cb))
{
seReg.pszName = c_szWAB_EXE;
seReg.pszValue = ConvertWtoA(szExe);
stReg.cEntries = 1;
stReg.pse = &seReg;
// Call the self-reg routine
hr = pfnri(hinstMapiXWAB, szSection, &stReg);
LocalFreeAndNull(&seReg.pszValue);
}
}
FreeLibrary(hAdvPack);
}
return(hr);
}
STDAPI DllRegisterServer(void)
{
HRESULT hr = E_FAIL;
TCHAR szWABPath[MAX_PATH];
// Set the wab32.dll path in the registry under
// HKLM/Software/Microsoft/WAB/WAB4/DLLPath
//
if( hinstMapiXWAB &&
GetModuleFileName(hinstMapiXWAB, szWABPath, CharSizeOf(szWABPath)))
{
HKEY hSubKey = NULL;
DWORD dwDisp = 0;
if(ERROR_SUCCESS == RegCreateKeyEx( HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisp))
{
RegSetValueEx(hSubKey,szEmpty,0,REG_SZ, (LPBYTE)szWABPath, (lstrlen(szWABPath)+1) * sizeof(TCHAR) );
RegCloseKey(hSubKey);
hr = S_OK;
}
}
if(HR_FAILED(hr))
goto out;
// OE Bug 67540
// For some reason, need to do handlers then regular else
// default contact handler won't be taken
if (!FRedistMode())
// Try to register handlers as we are not in redist mode
CallRegInstall(c_szRegHandlers);
// Register things that are always registered
hr = CallRegInstall(c_szReg);
out:
return(hr);
}
STDAPI DllUnregisterServer(void)
{
HRESULT hr;
hr = CallRegInstall(c_szUnReg);
return(hr);
}
#endif