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

  1. /*
  2. * ENTRY.C
  3. *
  4. * DLL entry functions for extended MAPI. Mostly for debugging
  5. * purposes.
  6. */
  7. #include <_apipch.h>
  8. #include <advpub.h>
  9. #include "htmlhelp.h"
  10. #include <shlwapi.h>
  11. #define _ENTRY_C
  12. #ifdef MAC
  13. #include <utilmac.h>
  14. #define PvGetInstanceGlobals() PvGetInstanceGlobalsMac(kInstMAPIX)
  15. #endif
  16. #ifndef MB_SETFOREGROUND
  17. #define MB_SETFOREGROUND 0
  18. #endif
  19. #ifdef DEBUG
  20. void ExitCheckInstance(LPINST pinst);
  21. void ExitCheckInstUtil(LPINSTUTIL pinstUtil);
  22. #endif
  23. HINSTANCE hinstMapiX = NULL; // Instance to the WAB resources module (wab32res.dll)
  24. HINSTANCE hinstMapiXWAB = NULL; // Instance of the WAB32.dll module (this dll)
  25. #if 0
  26. // @todo [PaulHi] DLL Leak. Remove this or implement
  27. extern CRITICAL_SECTION csOMIUnload;
  28. #endif
  29. BOOL fGlobalCSValid = FALSE;
  30. // Global handle for CommCtrl DLL
  31. HINSTANCE ghCommCtrlDLLInst = NULL;
  32. ULONG gulCommCtrlDLLRefCount = 0;
  33. extern void DeinitCommDlgLib();
  34. // Global fontinit for UI
  35. BOOL bInitFonts = FALSE;
  36. BOOL g_bRunningOnNT = TRUE; // Checks the OS we run on so Unicode calls can be thunked to Win9x
  37. BOOL bDNisByLN = FALSE; // Language dependent flag that tells us if the default
  38. // display name should be by first name or last name.
  39. TCHAR szResourceDNByLN[32]; // cache the formatting strings so we load them only once
  40. TCHAR szResourceDNByFN[32];
  41. TCHAR szResourceDNByCommaLN[32];
  42. BOOL bPrintingOn = TRUE;// Locale dependent flag that tells us to remove printing entirely
  43. // from the UI
  44. // When running against Outlook, we need a way for Outlook
  45. // to signal us about store changes so we can refresh the UI. There are 2
  46. // events we are interested in - 1. to update the list of contact folders
  47. // and 2 to update the list of contacts - we will use 2 events for this
  48. //
  49. HANDLE ghEventOlkRefreshContacts = NULL;
  50. HANDLE ghEventOlkRefreshFolders = NULL;
  51. static const char cszEventOlkRefreshContacts[] = "WAB_Outlook_Event_Refresh_Contacts";
  52. static const char cszEventOlkRefreshFolders[] = "WAB_Outlook_Event_Refresh_Folders";
  53. typedef HRESULT (CALLBACK* SHDLLGETVERSIONPROC)(DLLVERSIONINFO *);
  54. typedef HINSTANCE (STDAPICALLTYPE *PFNMLLOADLIBARY)(LPCTSTR lpLibFileName, HMODULE hModule, DWORD dwCrossCodePage);
  55. typedef int (STDAPICALLTYPE *PFNMLWINHELP)(HWND hWndCaller, LPCTSTR lpszHelp, UINT uCommand, DWORD_PTR dwData);
  56. typedef HWND (STDAPICALLTYPE *PFNMLHTMLHELP)(HWND hWndCaller, LPCTSTR pszFile, UINT uCommand, DWORD_PTR dwData, DWORD dwCrossCodePage);
  57. ///////////////////////////////////////////////////////////////////////////////
  58. // bCheckifRunningOnWinNT5
  59. ///////////////////////////////////////////////////////////////////////////////
  60. BOOL bCheckifRunningOnWinNT5()
  61. {
  62. OSVERSIONINFO osvi = {0};
  63. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  64. GetVersionEx(&osvi);
  65. return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 5);
  66. }
  67. ///////////////////////////////////////////////////////////////////////////////
  68. // Load the WAB resource DLL. This is done every time the WAB32.DLL is loaded.
  69. // If we have a version 5 or greater SHLWAPI.DLL then we should use the load
  70. // library function API there. If we are running NT5 or greater then we
  71. // use the special cross codepage support.
  72. // Also use the new PlugUI version of WinHelp and HtmlHelp APIs in SHLWAPI.DLL
  73. ///////////////////////////////////////////////////////////////////////////////
  74. // Copied from shlwapip.h, yuck.
  75. #define ML_NO_CROSSCODEPAGE 0
  76. #define ML_CROSSCODEPAGE_NT 1
  77. static const TCHAR c_szShlwapiDll[] = TEXT("shlwapi.dll");
  78. static const char c_szDllGetVersion[] = "DllGetVersion";
  79. static const TCHAR c_szWABResourceDLL[] = TEXT("wab32res.dll");
  80. static const TCHAR c_szWABDLL[] = TEXT("wab32.dll");
  81. ///////////////////////////////////////////////////////////////////////////////
  82. // LoadWABResourceDLL
  83. //
  84. // Load the WAB resource DLL using the IE5 or greater Shlwapi.dll LoadLibrary
  85. // function if available. Otherwise use the system LoadLibrary function.
  86. //
  87. // Input Params: hInstWAB32 - handle to WAB DLL
  88. //
  89. // Returns handle to the loaded resource DLL
  90. ///////////////////////////////////////////////////////////////////////////////
  91. HINSTANCE LoadWABResourceDLL(HINSTANCE hInstWAB32)
  92. {
  93. TCHAR szPath[MAX_PATH];
  94. HINSTANCE hInst = NULL;
  95. HINSTANCE hinstShlwapi = LoadLibrary(c_szShlwapiDll);
  96. PFNMLLOADLIBARY pfnLoadLibrary = NULL;
  97. if (hinstShlwapi)
  98. {
  99. SHDLLGETVERSIONPROC pfnVersion;
  100. DLLVERSIONINFO info = {0};
  101. pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hinstShlwapi, c_szDllGetVersion);
  102. if (pfnVersion)
  103. {
  104. info.cbSize = sizeof(DLLVERSIONINFO);
  105. if (SUCCEEDED(pfnVersion(&info)))
  106. {
  107. if (info.dwMajorVersion >= 5)
  108. pfnLoadLibrary = (PFNMLLOADLIBARY)GetProcAddress(hinstShlwapi, (LPCSTR)378); // UNICODE ordinal
  109. }
  110. }
  111. }
  112. // We have special cross codepage support on NT5 and on.
  113. if (pfnLoadLibrary)
  114. {
  115. hInst = pfnLoadLibrary(c_szWABResourceDLL, hInstWAB32,
  116. bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
  117. }
  118. if (!hInst)
  119. hInst = LoadLibrary(c_szWABResourceDLL);
  120. // Try full path name for resource DLL
  121. if ( !hInst && (GetModuleFileName(hInstWAB32, szPath, CharSizeOf(szPath))) )
  122. {
  123. int iEnd;
  124. iEnd = lstrlen(szPath) - lstrlen(c_szWABDLL);
  125. StrCpyN(&szPath[iEnd], c_szWABResourceDLL, ARRAYSIZE(szPath)-iEnd);
  126. if (pfnLoadLibrary)
  127. {
  128. hInst = pfnLoadLibrary(szPath, hInstWAB32,
  129. bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
  130. }
  131. if (!hInst)
  132. hInst = LoadLibrary(szPath);
  133. }
  134. if (hinstShlwapi)
  135. FreeLibrary(hinstShlwapi);
  136. AssertSz(hInst, TEXT("Failed to LoadLibrary Lang Dll"));
  137. return(hInst);
  138. }
  139. // PlugUI version of WinHelp
  140. BOOL WinHelpWrap(HWND hWndCaller, LPCTSTR pwszHelpFile, UINT uCommand, DWORD_PTR dwData)
  141. {
  142. static s_fChecked = FALSE; // Only look for s_pfnWinHelp once
  143. static PFNMLWINHELP s_pfnWinHelp = NULL;
  144. if (!s_pfnWinHelp && !s_fChecked)
  145. {
  146. HINSTANCE hShlwapi = DemandLoadShlwapi();
  147. s_fChecked = TRUE;
  148. if (hShlwapi)
  149. {
  150. // Check version of the shlwapi.dll
  151. SHDLLGETVERSIONPROC pfnVersion;
  152. DLLVERSIONINFO info = {0};
  153. pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hShlwapi, c_szDllGetVersion);
  154. if (pfnVersion)
  155. {
  156. info.cbSize = sizeof(DLLVERSIONINFO);
  157. if (SUCCEEDED(pfnVersion(&info)))
  158. {
  159. if (info.dwMajorVersion >= 5)
  160. s_pfnWinHelp = (PFNMLWINHELP)GetProcAddress(hShlwapi, (LPCSTR)397); // UNICODE ordinal
  161. }
  162. }
  163. }
  164. }
  165. if (s_pfnWinHelp)
  166. return s_pfnWinHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
  167. // [PaulHi] Win9X version of WinHelpW doesn't work
  168. if (g_bRunningOnNT)
  169. return WinHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
  170. else
  171. {
  172. LPSTR pszHelpFile = ConvertWtoA(pwszHelpFile);
  173. BOOL bRtn = WinHelpA(hWndCaller, (LPCSTR)pszHelpFile, uCommand, dwData);
  174. LocalFreeAndNull(&pszHelpFile);
  175. return bRtn;
  176. }
  177. }
  178. // PlugUI version of HtmlHelp
  179. HWND HtmlHelpWrap(HWND hWndCaller, LPCTSTR pwszHelpFile, UINT uCommand, DWORD_PTR dwData)
  180. {
  181. static s_fChecked = FALSE; // Only look for s_pfnHtmlHelp once
  182. static PFNMLHTMLHELP s_pfnHtmlHelp = NULL;
  183. if (!s_pfnHtmlHelp && !s_fChecked)
  184. {
  185. HINSTANCE hShlwapi = DemandLoadShlwapi();
  186. s_fChecked = TRUE;
  187. if (hShlwapi)
  188. {
  189. // Check version of the shlwapi.dll
  190. SHDLLGETVERSIONPROC pfnVersion;
  191. DLLVERSIONINFO info = {0};
  192. pfnVersion = (SHDLLGETVERSIONPROC)GetProcAddress(hShlwapi, c_szDllGetVersion);
  193. if (pfnVersion)
  194. {
  195. info.cbSize = sizeof(DLLVERSIONINFO);
  196. if (SUCCEEDED(pfnVersion(&info)))
  197. {
  198. if (info.dwMajorVersion >= 5)
  199. s_pfnHtmlHelp = (PFNMLHTMLHELP)GetProcAddress(hShlwapi, (LPCSTR)398); // UNICODE ordinal
  200. }
  201. }
  202. }
  203. }
  204. if (s_pfnHtmlHelp)
  205. return s_pfnHtmlHelp(hWndCaller, pwszHelpFile, uCommand, dwData,
  206. bCheckifRunningOnWinNT5() ? ML_CROSSCODEPAGE_NT : ML_NO_CROSSCODEPAGE);
  207. // [PaulHi] Wide chars work Ok on Win9X
  208. return HtmlHelp(hWndCaller, pwszHelpFile, uCommand, dwData);
  209. }
  210. /*
  211. -
  212. - CheckifRunningOnWinNT
  213. *
  214. * Checks the OS we are running on and returns TRUE for WinNT
  215. * False for Win9x
  216. */
  217. BOOL bCheckifRunningOnWinNT()
  218. {
  219. OSVERSIONINFO osvi = {0};
  220. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  221. GetVersionEx(&osvi);
  222. return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  223. }
  224. #if defined(WIN32) && !defined(MAC)
  225. /*
  226. * DLL entry point for Win32
  227. */
  228. BOOL WINAPI
  229. DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpvReserved)
  230. {
  231. LPPTGDATA lpPTGData=NULL;
  232. switch ((short)dwReason)
  233. {
  234. case DLL_PROCESS_ATTACH:
  235. // allocate a TLS index
  236. g_bRunningOnNT = bCheckifRunningOnWinNT();
  237. if ((dwTlsIndex = TlsAlloc()) == 0xfffffff)
  238. return FALSE;
  239. hinstMapiXWAB = hinst;
  240. hinstMapiX = LoadWABResourceDLL(hinstMapiXWAB);
  241. Assert(hinstMapiX);
  242. if(!hinstMapiX)
  243. {
  244. DWORD dwCode = GetLastError();
  245. DebugTrace(TEXT("WAB32 Resource load failed: %d\n"), dwCode);
  246. }
  247. g_msgMSWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
  248. bInitFonts = InitFonts();
  249. // The WAB does a lot of DisplayName formatting and DisplayName parsing
  250. // For western names we can always assume thathe the First Name comes
  251. // first in the display name. However for FE and some locales like Hungarian,
  252. // this is not true so the WAB needs to know when it can assume the
  253. // First Name comes first and when it can Assume that the first name
  254. // comes last ... so localizers set a flag .. if the string
  255. // idsLangDisplayNameisByLastName is set to "1" then we know that the
  256. // default names for this language start with the last name
  257. // The localizers also set the format templates for defining how a name
  258. // should be created from the First/Middle/Last names .. for example,
  259. // in Japanese it is "L F" (no comma) while elsewhere it could be "L,F"
  260. // All these things are set in localization...
  261. {
  262. TCHAR szBuf[32];
  263. const LPTSTR lpszOne = TEXT("1");
  264. const LPTSTR lpszDefFormatName = TEXT("%1% %2% %3");
  265. LoadString(hinstMapiX, idsLangDisplayNameIsByLastName, szBuf, CharSizeOf(szBuf));
  266. // if szBuf == "1" then Yes, its by last name .. else its not
  267. TrimSpaces(szBuf);
  268. if (!lstrcmpi(szBuf,lpszOne))
  269. bDNisByLN = TRUE;
  270. else
  271. bDNisByLN = FALSE;
  272. DebugTrace(TEXT("bDNisByLN: %d\n"),bDNisByLN);
  273. // The DNbyLN can be formed using a comma for western and without a comma for most FE and hungarian ..
  274. // So if the localizers set the lang default to be by LN, then we use the version without the comma,
  275. // else we use the version with the comma ..
  276. LoadString( hinstMapiX,idsDisplayNameByLastName,szResourceDNByLN,CharSizeOf(szResourceDNByLN));
  277. if(!lstrlen(szResourceDNByLN)) //for whatever reason .. cant afford to fail here
  278. StrCpyN(szResourceDNByLN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
  279. LoadString( hinstMapiX,idsDisplayNameByCommaLastName,szResourceDNByCommaLN,CharSizeOf(szResourceDNByCommaLN));
  280. if(!lstrlen(szResourceDNByCommaLN)) //for whatever reason .. cant afford to fail here
  281. StrCpyN(szResourceDNByCommaLN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
  282. LoadString(hinstMapiX,idsDisplayNameByFirstName,szResourceDNByFN,CharSizeOf(szResourceDNByFN));
  283. if(!lstrlen(szResourceDNByFN)) //for whatever reason .. cant afford to fail here
  284. StrCpyN(szResourceDNByFN, lpszDefFormatName, ARRAYSIZE(szResourceDNByLN));
  285. LoadString(hinstMapiX, idsLangPrintingOn, szBuf, CharSizeOf(szBuf));
  286. // if szBuf == "1" then Yes, its by last name .. else its not
  287. TrimSpaces(szBuf);
  288. if (!lstrcmpi(szBuf,lpszOne))
  289. bPrintingOn = TRUE;
  290. else
  291. bPrintingOn = FALSE;
  292. DebugTrace(TEXT("bPrintingOn: %d\n"),bPrintingOn);
  293. }
  294. {
  295. // Create the events needed for synchronizing with the outlook store
  296. ghEventOlkRefreshContacts = CreateEventA(NULL, // security attributes
  297. TRUE, // Manual reset
  298. FALSE, // initial state
  299. cszEventOlkRefreshContacts);
  300. ghEventOlkRefreshFolders = CreateEventA(NULL, // security attributes
  301. TRUE, // Manual reset
  302. FALSE, // initial state
  303. cszEventOlkRefreshFolders);
  304. }
  305. // Check for commoncontrol presence for UI
  306. InitCommonControlLib();
  307. InitializeCriticalSection(&csUnkobjInit);
  308. InitializeCriticalSection(&csMapiInit);
  309. InitializeCriticalSection(&csHeap);
  310. #if 0
  311. // @todo [PaulHi] DLL Leak. Remove this or implement
  312. InitializeCriticalSection(&csOMIUnload);
  313. #endif
  314. // Critical section to protect the Address Book's SearchPathCache
  315. // This hack is used because we can't enter the IAB's critical
  316. // section from ABProviders call to our AdviseSink::OnNotify for
  317. // the Merged One-off and Hierarchy tables.
  318. InitializeCriticalSection(&csMapiSearchPath);
  319. InitDemandLoadedLibs();
  320. // All the CSs have been initialized
  321. fGlobalCSValid = TRUE;
  322. // We don't need these, so tell the OS to stop 'em
  323. // [PaulHi] 3/8/99 Raid 73731 We DO need these calls. This is the
  324. // only way thread local storage is deallocated. Allocation are performed
  325. // on demand through the WAB GetThreadStoragePointer() function.
  326. #if 0
  327. DisableThreadLibraryCalls(hinst);
  328. #endif
  329. ScInitMapiUtil(0);
  330. // No Break here - fall through to DLL_THREAD_ATTACH
  331. // for thread initialization
  332. case DLL_THREAD_ATTACH:
  333. DebugTrace(TEXT("DllEntryPoint: 0x%.8x THREAD_ATTACH\n"), GetCurrentThreadId());
  334. // [PaulHi] 3/9/99 There is no need to allocate the thread global data here
  335. // since the WAB will allocate whenever it needs the data through the
  336. // GetThreadStoragePointer(), i.e., on demand.
  337. // Memory leak mentioned below should now be fixed.
  338. #if 0
  339. lpPTGData = GetThreadStoragePointer();
  340. // Note the above ThreadStoragePointer seems to leak in every process
  341. // so avoid using it for anything more...
  342. if(!lpPTGData)
  343. {
  344. DebugPrintError((TEXT("DoThreadAttach: LocalAlloc() failed for thread 0x%.8x\n"), GetCurrentThreadId()));
  345. lpPTGData = NULL;
  346. return FALSE;
  347. }
  348. #endif
  349. break;
  350. case DLL_PROCESS_DETACH:
  351. DebugTrace(TEXT("LibMain: 0x%.8x PROCESS_DETACH\n"), GetCurrentThreadId());
  352. /*
  353. if (hMuidMutex) {
  354. CloseHandle(hMuidMutex);
  355. hMuidMutex = NULL;
  356. }
  357. */
  358. if(ghEventOlkRefreshContacts)
  359. {
  360. CloseHandle(ghEventOlkRefreshContacts);
  361. ghEventOlkRefreshContacts = NULL;
  362. }
  363. if(ghEventOlkRefreshFolders)
  364. {
  365. CloseHandle(ghEventOlkRefreshFolders);
  366. ghEventOlkRefreshFolders = NULL;
  367. }
  368. if (bInitFonts)
  369. DeleteFonts();
  370. if(hinstMapiX)
  371. FreeLibrary(hinstMapiX);
  372. // Fall into DLL_THREAD_DETACH to detach last thread
  373. case DLL_THREAD_DETACH:
  374. DebugTrace(TEXT("LibMain: 0x%.8x THREAD_DETACH\n"), GetCurrentThreadId());
  375. // get the thread data
  376. lpPTGData = TlsGetValue(dwTlsIndex);
  377. if (!lpPTGData)
  378. {
  379. // the thread that detaches, did not attach to the DLL. This is allowed.
  380. DebugTrace(TEXT("LibMain: thread %x didn't attach\n"),GetCurrentThreadId());
  381. // if this is a PROCESS_DETACH, I still want to go through the process
  382. // detach stuff, but if it a thread detach, I'm done
  383. if (dwReason == DLL_PROCESS_DETACH)
  384. goto do_process_detach;
  385. else
  386. break;
  387. }
  388. if(pt_hDefFont)
  389. DeleteObject(pt_hDefFont);
  390. if(pt_hDlgFont)
  391. DeleteObject(pt_hDlgFont);
  392. // For some reason code never hits this point a lot of times
  393. // and the threadlocalstorage data leaks.
  394. // [PaulHi] This was because the DLL_TRHEAD_DETACH calls were turned off above,
  395. // through DisableThreadLibraryCalls(). The leak should be fixed now.
  396. #ifdef HM_GROUP_SYNCING
  397. LocalFreeAndNull(&(lpPTGData->lptszHMAccountId));
  398. #endif
  399. LocalFreeAndNull(&lpPTGData);
  400. // if this is THREAD_DETACH, we're done
  401. if (dwReason == DLL_THREAD_DETACH)
  402. break;
  403. //N clean up jump stuff in detach
  404. do_process_detach:
  405. // do process detach stuff here ...
  406. DeinitMapiUtil();
  407. #ifdef DEBUG
  408. {
  409. // Don't allow asserts to spin a thread
  410. extern BOOL fInhibitTrapThread;
  411. fInhibitTrapThread = TRUE;
  412. ExitCheckInstance((LPINST)PvGetInstanceGlobals());
  413. ExitCheckInstUtil((LPINSTUTIL)PvGetInstanceGlobalsEx(lpInstUtil));
  414. }
  415. #endif /* DEBUG */
  416. // Unload Common control dll
  417. if (ghCommCtrlDLLInst != NULL)
  418. DeinitCommCtrlClientLib();
  419. DeinitCommDlgLib();
  420. // Tearing down all the global CSs
  421. fGlobalCSValid = FALSE;
  422. DeleteCriticalSection(&csUnkobjInit);
  423. DeleteCriticalSection(&csMapiInit);
  424. DeleteCriticalSection(&csHeap);
  425. #if 0
  426. // @todo [PaulHi] DLL Leak. Remove this or implement
  427. DeleteCriticalSection(&csOMIUnload);
  428. #endif
  429. DeleteCriticalSection(&csMapiSearchPath);
  430. // release the TLS index
  431. TlsFree(dwTlsIndex);
  432. DeinitCryptoLib();
  433. FreeDemandLoadedLibs();
  434. break;
  435. default:
  436. DebugTrace(TEXT("MAPIX FInitMapiDll: bad dwReason %ld\n"), dwReason);
  437. break;
  438. }
  439. return TRUE;
  440. }
  441. #endif /* WIN32 && !MAC */
  442. #ifdef DEBUG
  443. void
  444. ExitCheckInstance(LPINST pinst)
  445. {
  446. TCHAR rgch[MAX_PATH];
  447. TCHAR rgchTitle[128];
  448. BOOL fAssertLeaks;
  449. if (!pinst)
  450. return;
  451. if (pinst->szModName[0])
  452. wnsprintf(rgchTitle, ARRAYSIZE(rgchTitle), TEXT("MAPIX exit checks for '%s'"), pinst->szModName);
  453. else
  454. StrCpyN(rgchTitle, TEXT("MAPIX exit checks"), ARRAYSIZE(rgchTitle));
  455. DebugTrace(TEXT("%s\n"), rgchTitle);
  456. fAssertLeaks = GetPrivateProfileInt( TEXT("General"), TEXT("AssertLeaks"), 0, TEXT("wabdbg.ini"));
  457. // Check for Init/Deinit imbalance
  458. if (pinst->cRef)
  459. {
  460. wnsprintf(rgch, ARRAYSIZE(rgch), TEXT("MAPIX: leaked %ld references"), pinst->cRef);
  461. TraceSz1( TEXT("%s\n"), rgch);
  462. if (fAssertLeaks)
  463. TrapSz(rgch);
  464. }
  465. // Generate memory leak reports.
  466. #if 0 // LH_DumpLeaks is not exported
  467. // if (pinst->hlhClient)
  468. // LH_DumpLeaks(pinst->hlhClient);
  469. if (pinst->hlhProvider)
  470. LH_DumpLeaks(pinst->hlhProvider);
  471. if (pinst->hlhInternal)
  472. LH_DumpLeaks(pinst->hlhInternal);
  473. #else
  474. {
  475. HLH hlh;
  476. if (pinst->hlhProvider)
  477. LH_Close(pinst->hlhProvider);
  478. hlh = pinst->hlhInternal;
  479. if (hlh)
  480. {
  481. LH_Free(hlh, pinst);
  482. LH_Close(hlh);
  483. }
  484. }
  485. #endif
  486. }
  487. void
  488. ExitCheckInstUtil(LPINSTUTIL pinstUtil)
  489. {
  490. HLH hlh;
  491. if (!pinstUtil)
  492. return;
  493. hlh = pinstUtil->hlhClient;
  494. if (hlh)
  495. {
  496. LH_Free(hlh, pinstUtil);
  497. LH_Close(hlh);
  498. }
  499. }
  500. #endif /* DEBUG */
  501. #ifndef WIN16
  502. static const char c_szReg[] = "Reg";
  503. static const char c_szRegHandlers[] = "RegisterHandlers";
  504. static const char c_szUnReg[] = "UnReg";
  505. static const char c_szAdvPackDll[] = "ADVPACK.DLL";
  506. static const TCHAR c_szWabPath[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
  507. static const TCHAR c_szRegWABVerInfo[] = TEXT("Software\\Microsoft\\WAB\\Version Info");
  508. static const TCHAR c_szIEInstallMode[] = TEXT("InstallMode");
  509. static char c_szWAB_EXE[] = "WAB_EXE";
  510. BOOL FRedistMode()
  511. {
  512. HKEY hkey;
  513. DWORD cb;
  514. DWORD dwInstallMode=0;
  515. BOOL fRedist = FALSE;
  516. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWABVerInfo, 0, KEY_READ, &hkey))
  517. {
  518. cb = sizeof(dwInstallMode);
  519. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIEInstallMode, 0, NULL, (LPBYTE)&dwInstallMode, &cb))
  520. {
  521. fRedist = (dwInstallMode > 0);
  522. }
  523. RegCloseKey(hkey);
  524. }
  525. return fRedist;
  526. }
  527. HRESULT CallRegInstall(LPCSTR szSection)
  528. {
  529. HRESULT hr;
  530. HINSTANCE hAdvPack;
  531. REGINSTALL pfnri;
  532. TCHAR szExe[MAX_PATH];
  533. STRENTRY seReg;
  534. STRTABLE stReg;
  535. DWORD cb;
  536. hr = E_FAIL;
  537. hAdvPack = LoadLibraryA(c_szAdvPackDll);
  538. if (hAdvPack != NULL)
  539. {
  540. // Get Proc Address for registration util
  541. pfnri = (REGINSTALL)GetProcAddress(hAdvPack, achREGINSTALL);
  542. if (pfnri != NULL)
  543. {
  544. cb = CharSizeOf(szExe);
  545. if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, c_szWabPath, szExe, &cb))
  546. {
  547. seReg.pszName = c_szWAB_EXE;
  548. seReg.pszValue = ConvertWtoA(szExe);
  549. stReg.cEntries = 1;
  550. stReg.pse = &seReg;
  551. // Call the self-reg routine
  552. hr = pfnri(hinstMapiXWAB, szSection, &stReg);
  553. LocalFreeAndNull(&seReg.pszValue);
  554. }
  555. }
  556. FreeLibrary(hAdvPack);
  557. }
  558. return(hr);
  559. }
  560. STDAPI DllRegisterServer(void)
  561. {
  562. HRESULT hr = E_FAIL;
  563. TCHAR szWABPath[MAX_PATH];
  564. // Set the wab32.dll path in the registry under
  565. // HKLM/Software/Microsoft/WAB/WAB4/DLLPath
  566. //
  567. if( hinstMapiXWAB &&
  568. GetModuleFileName(hinstMapiXWAB, szWABPath, CharSizeOf(szWABPath)))
  569. {
  570. HKEY hSubKey = NULL;
  571. DWORD dwDisp = 0;
  572. if(ERROR_SUCCESS == RegCreateKeyEx( HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY,
  573. 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hSubKey, &dwDisp))
  574. {
  575. RegSetValueEx(hSubKey,szEmpty,0,REG_SZ, (LPBYTE)szWABPath, (lstrlen(szWABPath)+1) * sizeof(TCHAR) );
  576. RegCloseKey(hSubKey);
  577. hr = S_OK;
  578. }
  579. }
  580. if(HR_FAILED(hr))
  581. goto out;
  582. // OE Bug 67540
  583. // For some reason, need to do handlers then regular else
  584. // default contact handler won't be taken
  585. if (!FRedistMode())
  586. // Try to register handlers as we are not in redist mode
  587. CallRegInstall(c_szRegHandlers);
  588. // Register things that are always registered
  589. hr = CallRegInstall(c_szReg);
  590. out:
  591. return(hr);
  592. }
  593. STDAPI DllUnregisterServer(void)
  594. {
  595. HRESULT hr;
  596. hr = CallRegInstall(c_szUnReg);
  597. return(hr);
  598. }
  599. #endif