// -------------------------------------------------------------------------------- // Dllmain.cpp // Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved // Steven J. Bailey // -------------------------------------------------------------------------------- #include "pch.hxx" #include #define DEFINE_STRING_CONSTANTS #define DEFINE_STRCONST #define DEFINE_PROPSYMBOLS #define DEFINE_TRIGGERS #include "mimeole.h" #include "symcache.h" #include "strconst.h" #include "htmlstr.h" #include "thorsspi.h" #include "sicily.h" #include "ixputil.h" #include "olealloc.h" #include "smime.h" #include "objheap.h" #include "internat.h" #include "icoint.h" #include "msoert.h" #include "dllmain.h" #include "mhtmlurl.h" #include "mlang.h" #include #include "shared.h" #include "shlwapi.h" #include "demand.h" #include "fontcash.h" #include "util.h" #include "resource.h" #include "../imnxport/asynconn.h" // -------------------------------------------------------------------------------- // Globals - Object count and lock count // -------------------------------------------------------------------------------- CRITICAL_SECTION g_csDllMain={0}; CRITICAL_SECTION g_csRAS={0}; CRITICAL_SECTION g_csCounter={0}; CRITICAL_SECTION g_csMLANG={0}; CRITICAL_SECTION g_csCSAPI3T1={0}; BOOL g_fAttached = FALSE; DWORD g_dwCounter=0; // boundary/cid/mid ratchet LONG g_cRef=0; LONG g_cLock=0; HINSTANCE g_hInst=NULL; HINSTANCE g_hLocRes=NULL; CMimeInternational *g_pInternat=NULL; BOOL g_fWinsockInit=FALSE; DWORD g_dwSysPageSize; UINT CF_HTML=0; UINT CF_INETMSG=0; UINT CF_RFC822=0; CMimeAllocator * g_pMoleAlloc=NULL; LPINETCSETINFO g_pDefBodyCset=NULL; LPINETCSETINFO g_pDefHeadCset=NULL; LPSYMBOLCACHE g_pSymCache=NULL; IMalloc *g_pMalloc=NULL; HINSTANCE g_hinstMLANG=NULL; HINSTANCE g_hinstRAS=NULL; HINSTANCE g_hinstCSAPI3T1=NULL; LPMHTMLURLCACHE g_pUrlCache=NULL; BOOL g_fCanEditBiDi=FALSE; DWORD g_dwCompatMode=0; IF_DEBUG(DWORD TAG_SSPI=0); SYSTEM_INFO g_SystemInfo={0}; OSVERSIONINFO g_OSInfo={0}; ULONG g_ulUpperCentury = 0; ULONG g_ulY2kThreshold = 2029; IFontCache *g_lpIFontCache=NULL; HCERTSTORE g_hCachedStoreMy = NULL; HCERTSTORE g_hCachedStoreAddressBook = NULL; LPSRVIGNORABLEERROR g_pSrvErrRoot = NULL; BOOL fIsNT5() { return((g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (g_OSInfo.dwMajorVersion >= 5)); } // -------------------------------------------------------------------------------- // Debug Globals // -------------------------------------------------------------------------------- #ifdef DEBUG DWORD dwDOUTLevel=0; DWORD dwDOUTLMod=0; DWORD dwDOUTLModLevel=0; #endif #ifdef WIN16 // -------------------------------------------------------------------------------- // From main.c of the build // -------------------------------------------------------------------------------- extern "C" { void FreeGlobalVars(); }; #endif #ifdef SMIME_V3 STDAPI EssRegisterServer(void); BOOL WINAPI EssASNDllMain(HMODULE hInst, ULONG ulReason, LPVOID lpv); #endif // SMIME_V3 HRESULT GetDllPathName(WCHAR **ppszW); // These lines should be hardcoded! (YST) static const TCHAR sc_szLangDll[] = "INETRES.DLL"; // -------------------------------------------------------------------------------- // GetDllMajorVersion // -------------------------------------------------------------------------------- STDAPI_(OEDLLVERSION) GetDllMajorVersion(void) { return OEDLL_VERSION_CURRENT; } extern BOOL CanEditBiDi(void); // -------------------------------------------------------------------------------- // InitGlobalVars // -------------------------------------------------------------------------------- void InitGlobalVars(void) { // Locals SYSTEM_INFO rSystemInfo; TCHAR szY2kThreshold[16]; TCHAR rgch[MAX_PATH]; HKEY hkey = NULL; HRESULT hr; DWORD cb; // Initialize Global Critical Sections InitializeCriticalSection(&g_csDllMain); InitializeCriticalSection(&g_csRAS); InitializeCriticalSection(&g_csCounter); InitializeCriticalSection(&g_csMLANG); InitializeCriticalSection(&g_csCSAPI3T1); g_fAttached = TRUE; // This for the winsock multi-thread hostname lookup InitLookupCache(); // Get System & OS Info GetPCAndOSTypes(&g_SystemInfo, &g_OSInfo); g_dwSysPageSize = g_SystemInfo.dwPageSize; // Create OLE Task Memory Allocator CoGetMalloc(1, &g_pMalloc); Assert(g_pMalloc); // Create our global allocator g_pMoleAlloc = new CMimeAllocator; Assert(g_pMoleAlloc); // Security Initialize SecurityInitialize(); // Initialize Demand-loaded Libs InitDemandLoadedLibs(); // INit crit sect g_pSymCache = new CPropertySymbolCache; Assert(g_pSymCache); // Initialize the Symbol Table SideAssert(SUCCEEDED(g_pSymCache->Init())); // Init Body Object Heap InitObjectHeaps(); // Init International InitInternational(); // Init ActiveUrl Cache g_pUrlCache = new CMimeActiveUrlCache; Assert(g_pUrlCache); // Check if the system can edit Bidi documents g_fCanEditBiDi = CanEditBiDi(); // Register clipboard formats CF_HTML = RegisterClipboardFormat(STR_CF_HTML); Assert(CF_HTML != 0); CF_INETMSG = RegisterClipboardFormat(STR_CF_INETMSG); Assert(CF_INETMSG != 0); CF_RFC822 = RegisterClipboardFormat(STR_CF_RFC822); Assert(CF_RFC822 != 0); // --- Calculate Y2K cut off information // See http://officeweb/specs/excel/CYu/nty2k.htm if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_Y2K_THRESHOLD, 0, KEY_READ, &hkey)) { cb = sizeof(szY2kThreshold); if(ERROR_SUCCESS == RegQueryValueEx(hkey, "1", NULL, NULL, (LPBYTE)szY2kThreshold, &cb)) { g_ulY2kThreshold = (ULONG)StrToInt(szY2kThreshold); } RegCloseKey(hkey); } g_ulUpperCentury = g_ulY2kThreshold / 100; g_ulY2kThreshold %= 100; // Create the Font Cache Object if (NULL == g_lpIFontCache) { hr = CFontCache::CreateInstance(NULL, (IUnknown **)&g_lpIFontCache); if(SUCCEEDED(hr)) { StrCpyN(rgch, c_szExplorerRegPath, ARRAYSIZE(rgch)); StrCatBuff(rgch, "\\International", ARRAYSIZE(rgch)); hr = g_lpIFontCache->Init(HKEY_CURRENT_USER, rgch, 0); } if(FAILED(hr)) { AthMessageBox(HWND_DESKTOP, MAKEINTRESOURCE(IDS_APPNAME), MAKEINTRESOURCE(idsFontCacheError), NULL, MB_OK | MB_ICONSTOP); } } } // -------------------------------------------------------------------------------- // FreeGlobalVars // -------------------------------------------------------------------------------- void FreeGlobalVars(void) { // Server ignorable errors if(g_pSrvErrRoot) FreeSrvErr(g_pSrvErrRoot); // Cache stores if (g_hCachedStoreMy) CertCloseStore(g_hCachedStoreMy, 0); if (g_hCachedStoreAddressBook) CertCloseStore(g_hCachedStoreAddressBook, 0); // Release ActiveUrlCache Assert(g_pUrlCache); SafeRelease(g_pUrlCache); // Free Address Info Heap (must be before release of g_pSymCache) FreeObjectHeaps(); // Release Symbol CAche Assert(g_pSymCache); SafeRelease(g_pSymCache); // Unload RAS Dll EnterCriticalSection(&g_csRAS); SafeFreeLibrary(g_hinstRAS); LeaveCriticalSection(&g_csRAS); // Uninitialize Security SSPIUninitialize(); UnloadSecurity(); // Unload S/MIME CSMime::UnloadAll(); // Must be before UnInitializeWinsock() DeInitLookupCache(); // Cleanup Winsock if (g_fWinsockInit) UnInitializeWinsock(); // Free libraries that demand.cpp loaded FreeDemandLoadedLibs(); // Free CSAPI3T1 EnterCriticalSection(&g_csCSAPI3T1); SafeFreeLibrary(g_hinstCSAPI3T1); LeaveCriticalSection(&g_csCSAPI3T1); // Free mlang lib EnterCriticalSection(&g_csMLANG); SafeFreeLibrary(g_hinstMLANG); LeaveCriticalSection(&g_csMLANG); // Release Font Cache SafeRelease(g_lpIFontCache); // Release g_pInternat Assert(g_pInternat); SafeRelease(g_pInternat); // Free INETRES.DLL (g_hLocRes) SafeFreeLibrary(g_hLocRes); // Delete Global Critical Sections g_fAttached = FALSE; DeleteCriticalSection(&g_csCSAPI3T1); DeleteCriticalSection(&g_csMLANG); DeleteCriticalSection(&g_csCounter); DeleteCriticalSection(&g_csRAS); DeleteCriticalSection(&g_csDllMain); // Release Global Memory allocator SafeRelease(g_pMoleAlloc); // Release Global Memory allocator SafeRelease(g_pMalloc); //Don't SafeRelease() anything after here, as the allocator has been Released() #ifdef WIN16 // Need uninitialize it to clean the ole garbage. CoUninitialize(); #endif // WIN16 } #ifndef WIN16 // -------------------------------------------------------------------------------- // Win32 Dll Entry Point // -------------------------------------------------------------------------------- EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved) { // Handle Attach - detach reason switch (dwReason) { case DLL_PROCESS_ATTACH: SHFusionInitialize(NULL); #ifdef DEBUG dwDOUTLevel=GetPrivateProfileInt("Debug", "ICLevel", 0, "athena.ini"); dwDOUTLMod=GetPrivateProfileInt("Debug", "Mod", 0, "athena.ini"); dwDOUTLModLevel=GetPrivateProfileInt("Debug", "ModLevel", 0, "athena.ini"); TAG_SSPI = GetDebugTraceTagMask("InetCommSSPI", TAG_SSPI); #endif g_hInst = hInst; g_hLocRes = LoadLangDll(g_hInst, c_szInetResDll, fIsNT5()); if(g_hLocRes == NULL) { Assert(FALSE); return FALSE; } InitGlobalVars(); SideAssert(DisableThreadLibraryCalls(hInst)); #ifdef SMIME_V3 if (!EssASNDllMain(hInst, dwReason, lpReserved)) { return FALSE; } #endif // SMIME_V3 break; case DLL_PROCESS_DETACH: #ifdef SMIME_V3 if (!EssASNDllMain(hInst, dwReason, lpReserved)) { return FALSE; } #endif // SMIME_V3 FreeGlobalVars(); SHFusionUninitialize(); break; } // Done return TRUE; } #else // -------------------------------------------------------------------------------- // Win16 Dll Entry Point // -------------------------------------------------------------------------------- BOOL FAR PASCAL LibMain (HINSTANCE hDll, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine) { // Win16 specific CoInitialize(NULL); // Set global instance handle g_hInst = hDll; // Initialize Global Variables InitGlobalVars(); #ifdef DEBUG dwDOUTLevel=GetPrivateProfileInt("Debug", "ICLevel", 0, "athena.ini"); dwDOUTLMod=GetPrivateProfileInt("Debug", "Mod", 0, "athena.ini"); dwDOUTLModLevel=GetPrivateProfileInt("Debug", "ModLevel", 0, "athena.ini"); #endif // Done return TRUE; } #endif // !WIN16 // -------------------------------------------------------------------------------- // DwCounterNext // -------------------------------------------------------------------------------- DWORD DwCounterNext(void) { EnterCriticalSection(&g_csCounter); DWORD dwCounter = g_dwCounter++; LeaveCriticalSection(&g_csCounter); return dwCounter; } // -------------------------------------------------------------------------------- // DllAddRef // -------------------------------------------------------------------------------- ULONG DllAddRef(void) { TraceCall("DllAddRef"); return (ULONG)InterlockedIncrement(&g_cRef); } // -------------------------------------------------------------------------------- // DllRelease // -------------------------------------------------------------------------------- ULONG DllRelease(void) { TraceCall("DllRelease"); return (ULONG)InterlockedDecrement(&g_cRef); } // -------------------------------------------------------------------------------- // DllCanUnloadNow // -------------------------------------------------------------------------------- STDAPI DllCanUnloadNow(void) { // Tracing TraceCall("DllCanUnloadNow"); if(!g_fAttached) // critacal sections was deleted (or not created): we defently can be unloaded return S_OK; // Thread Safety EnterCriticalSection(&g_csDllMain); // Trace This // DebugTrace("DllCanUnloadNow: %s - Reference Count: %d, LockServer Count: %d\n", __FILE__, g_cRef, g_cLock); // Can We Unload HRESULT hr = (0 == g_cRef && 0 == g_cLock) ? S_OK : S_FALSE; // Thread Safety LeaveCriticalSection(&g_csDllMain); // Done return hr; } // -------------------------------------------------------------------------------- // RegTypeLib // -------------------------------------------------------------------------------- __inline HRESULT RegTypeLib(HINSTANCE hInstRes) { AssertSz(hInstRes, "[ARGS] RegTypeLib: NULL hInstRes"); HRESULT hr = E_FAIL; CHAR szDll[MAX_PATH]; WCHAR wszDll[MAX_PATH]; GetModuleFileName(hInstRes, szDll, ARRAYSIZE(szDll)); // Convert the module path to Wide-String if (MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szDll, -1, wszDll, ARRAYSIZE(wszDll))) { ITypeLib *pTypeLib; hr = LoadTypeLib(wszDll, &pTypeLib); if (SUCCEEDED(hr)) { // Register the typelib hr = RegisterTypeLib(pTypeLib, wszDll, NULL); pTypeLib->Release(); } } return hr; } // -------------------------------------------------------------------------------- // DllRegisterServer // -------------------------------------------------------------------------------- STDAPI DllRegisterServer(void) { // Locals HRESULT hr=S_OK; // Trace TraceCall("DllRegisterServer"); #ifdef SMIME_V3 // Register the ESS routines hr = EssRegisterServer(); if (FAILED(hr)) { return hr; } #endif // SMIME_V3 // CallRegInstall and RegTypeLib are in staticRT/shared.cpp if (SUCCEEDED(hr = CallRegInstall(g_hInst, g_hInst, c_szReg, NULL))) return RegTypeLib(g_hInst); else return hr; } // -------------------------------------------------------------------------------- // DllUnregisterServer // -------------------------------------------------------------------------------- STDAPI DllUnregisterServer(void) { // Locals HRESULT hr=S_OK; // Trace TraceCall("DllUnregisterServer"); // UnRegister IF_FAILEXIT(hr = CallRegInstall(g_hInst, g_hInst, c_szUnReg, NULL)); exit: // Done return hr; } HRESULT GetTypeLibrary(ITypeLib **ppTypeLib) { HRESULT hr; WCHAR *pszModuleW=0; hr = GetDllPathName(&pszModuleW); if (!FAILED(hr)) { hr = LoadTypeLib(pszModuleW, ppTypeLib); SafeMemFree(pszModuleW); } return hr; } HRESULT GetDllPathName(WCHAR **ppszW) { HRESULT hr; TCHAR rgch[MAX_PATH]; WCHAR *pszModuleW=0; *ppszW=NULL; if (!GetModuleFileName(g_hInst, rgch, sizeof(rgch)/sizeof(TCHAR))) return E_FAIL; *ppszW = PszToUnicode(CP_ACP, rgch); return *ppszW ? S_OK : E_OUTOFMEMORY; } HCERTSTORE WINAPI OpenCachedHKCUStore( IN OUT HCERTSTORE *phStoreCache, IN LPCWSTR pwszStore ) { HCERTSTORE hStore; // This caching optimization is only supported on WXP if (g_OSInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || g_OSInfo.dwMajorVersion < 5 || (g_OSInfo.dwMajorVersion == 5 && g_OSInfo.dwMinorVersion < 1)) { return CertOpenStore( CERT_STORE_PROV_SYSTEM_W, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG, (const void *) pwszStore ); } hStore = *phStoreCache; if (NULL == hStore) { hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_W, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_STORE_SHARE_CONTEXT_FLAG, (const void *) pwszStore ); if (hStore) { HCERTSTORE hPrevStore; CertControlStore( hStore, 0, // dwFlags CERT_STORE_CTRL_AUTO_RESYNC, NULL // pvCtrlPara ); hPrevStore = InterlockedCompareExchangePointer( phStoreCache, hStore, NULL); if (hPrevStore) { CertCloseStore(hStore, 0); hStore = hPrevStore; } } } if (hStore) hStore = CertDuplicateStore(hStore); return hStore; } HCERTSTORE WINAPI OpenCachedMyStore() { return OpenCachedHKCUStore(&g_hCachedStoreMy, L"My"); } HCERTSTORE WINAPI OpenCachedAddressBookStore() { return OpenCachedHKCUStore(&g_hCachedStoreAddressBook, L"AddressBook"); }