#include "iexplore.h" #include "rcids.h" #include "shlwapi.h" #include "msodw.h" #include #ifdef UNIX #include "unixstuff.h" #endif static const TCHAR c_szBrowseNewProcessReg[] = REGSTR_PATH_EXPLORER TEXT("\\BrowseNewProcess"); static const TCHAR c_szBrowseNewProcess[] = TEXT("BrowseNewProcess"); int WinMainT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow); STDAPI_(int) ModuleEntry(void) { int i; STARTUPINFOA si; #ifdef UNICODE LPTSTR pszCmdLine = GetCommandLine(); #else // for multibyte should make it unsigned BYTE * pszCmdLine = (BYTE *)GetCommandLine(); #endif #if defined(UNIX) // IEUNIX: On solaris we are getting out of file handles with new code pages added to mlang // causing more nls files to be mmapped. INCREASE_FILEHANDLE_LIMIT; #endif // // 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); if(StopWatchMode() & SPMODE_BROWSER) // Used to get the start of browser total download time { StopWatch_Start(SWID_BROWSER_FRAME, TEXT("Browser Frame Start"), SPMODE_BROWSER | SPMODE_DEBUGOUT); } if ( *pszCmdLine == TEXT('\"') ) { /* * Scan, and skip over, subsequent characters until * another double-quote or a null is encountered. */ while ( *++pszCmdLine && (*pszCmdLine != TEXT('\"')) ); /* * If we stopped on a double-quote (usual case), skip * over it. */ if ( *pszCmdLine == TEXT('\"') ) pszCmdLine++; } else { while (*pszCmdLine > TEXT(' ')) pszCmdLine++; } /* * Skip past any white space preceeding the second token. */ while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) { pszCmdLine++; } si.dwFlags = 0; si.cb = sizeof(si); GetStartupInfoA(&si); i = WinMainT(GetModuleHandle(NULL), NULL, (LPTSTR)pszCmdLine, si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT); #ifndef UNIX ExitThread(i); // We only come here when we are not the shell... #else // there seem to be some desirable side effect calling ExitThread on Windows ExitProcess(i); #endif return i; } // // Create a unique event name // HANDLE AppendEvent(COPYDATASTRUCT *pcds) { static DWORD dwNextID = 0; TCHAR szEvent[MAX_IEEVENTNAME]; wsprintf(szEvent, "IE-%08X-%08X", GetCurrentThreadId(), dwNextID++); HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, szEvent); if (hEvent) { // // Put the (UNICODE) event name at the end of the cds data // LPWSTR pwszBufferEvent = (LPWSTR)(((BYTE *)pcds->lpData) + pcds->cbData); #ifdef UNICODE lstrcpy(pwszBufferEvent, szEvent); #else MultiByteToWideChar(CP_ACP, 0, szEvent, -1, pwszBufferEvent, ARRAYSIZE(szEvent)); #endif pcds->cbData += (lstrlenW(pwszBufferEvent) + 1) * sizeof(WCHAR); } return hEvent; } BOOL IsCommandSwitch(LPTSTR lpszCmdLine, LPTSTR pszSwitch, BOOL fRemoveSwitch) { LPTSTR lpsz; if ((lpsz=StrStrI(lpszCmdLine, pszSwitch)) && (lpsz == lpszCmdLine)) { int cch = lstrlen(pszSwitch); if (*(lpsz+cch) == 0 || *(lpsz+cch) == TEXT(' ')) { while (*(lpsz+cch) == TEXT(' ')) cch++; if (fRemoveSwitch) { // Remove the switch by copying everything up. *lpsz=0; lstrcat(lpsz, lpsz+cch); } return TRUE; } } return FALSE; } BOOL CheckForNeedingAppCompatWindow(void) { // Which I could simply get the Process of who spawned me. For now // try hack to get the foreground window and go from there... TCHAR szClassName[80]; HWND hwnd = GetForegroundWindow(); if (hwnd && GetClassName(hwnd, szClassName, ARRAYSIZE(szClassName)) > 0) { if (lstrcmpi(szClassName, TEXT("MauiFrame")) == 0) return TRUE; } return FALSE; } // // AppCompat - Sequel NetPIM execs a browser and then waits forever // looking for a visible top level window owned by this process. // HWND CreateAppCompatWindow(HINSTANCE hinst) { HWND hwnd; static const TCHAR c_szClass[] = TEXT("IEDummyFrame"); // IE3 used "IEFrame" WNDCLASS wc = { 0, DefWindowProc, 0, 0, hinst, NULL, NULL, NULL, NULL, c_szClass }; RegisterClass(&wc); // Netmanage ECCO Pro asks to get the menu... HMENU hmenu = CreateMenu(); hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, c_szClass, TEXT(""), 0, 0x00007FF0, 0x00007FF0, 0, 0, NULL, hmenu, hinst, NULL); // Don't open SHOWDEFAULT or this turkey could end up maximized ShowWindow(hwnd, SW_SHOWNA); return hwnd; } #define USERAGENT_POST_PLATFORM_PATH_TO_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent\\Post Platform") void SetCompatModeUserAgentString(void) { HKEY hkey; const char szcompat[]=TEXT("compat"); if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, USERAGENT_POST_PLATFORM_PATH_TO_KEY, &hkey)) { RegSetValueEx( hkey, szcompat, 0, REG_BINARY, (LPBYTE)NULL, 0); RegCloseKey(hkey); } } // Tell the user they are running in compat mode and not all the features will be available. #define IECOMPAT_REG_VAL TEXT("CompatWarningFor") void WarnCompatMode(HINSTANCE hinst) { TCHAR szFqFilename[MAX_PATH]; TCHAR szRegVal[MAX_PATH]; TCHAR szTitle[255]; TCHAR szMsg[1024]; LPTSTR szFile; GetModuleFileName(NULL, szFqFilename, ARRAYSIZE(szFqFilename)); szFile = PathFindFileName(szFqFilename); // Build up string "compatmodewarningfor " as value for reg key lstrcpy(szRegVal, IECOMPAT_REG_VAL); lstrcat(szRegVal, szFile); LoadString(hinst, IDS_COMPATMODEWARNINGTITLE, szTitle, ARRAYSIZE(szTitle)); LoadString(hinst, IDS_COMPATMODEWARNING, szMsg, ARRAYSIZE(szMsg)); SHMessageBoxCheck(NULL, szMsg, szTitle, MB_OK, FALSE, szRegVal); } #ifdef WINNT // this is the same code that is in explorer.exe (initcab.c) #define RSA_PATH_TO_KEY TEXT("Software\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Base Cryptographic Provider v1.0") #define CSD_REG_PATH TEXT("System\\CurrentControlSet\\Control\\Windows") #define CSD_REG_VALUE TEXT("CSDVersion") // the signatures we are looking for in the regsitry so that we can patch up #ifdef _M_IX86 static BYTE SP3Sig[] = {0xbd, 0x9f, 0x13, 0xc5, 0x92, 0x12, 0x2b, 0x72, 0x4a, 0xba, 0xb6, 0x2a, 0xf9, 0xfc, 0x54, 0x46, 0x6f, 0xa1, 0xb4, 0xbb, 0x43, 0xa8, 0xfe, 0xf8, 0xa8, 0x23, 0x7d, 0xd1, 0x85, 0x84, 0x22, 0x6e, 0xb4, 0x58, 0x00, 0x3e, 0x0b, 0x19, 0x83, 0x88, 0x6a, 0x8d, 0x64, 0x02, 0xdf, 0x5f, 0x65, 0x7e, 0x3b, 0x4d, 0xd4, 0x10, 0x44, 0xb9, 0x46, 0x34, 0xf3, 0x40, 0xf4, 0xbc, 0x9f, 0x4b, 0x82, 0x1e, 0xcc, 0xa7, 0xd0, 0x2d, 0x22, 0xd7, 0xb1, 0xf0, 0x2e, 0xcd, 0x0e, 0x21, 0x52, 0xbc, 0x3e, 0x81, 0xb1, 0x1a, 0x86, 0x52, 0x4d, 0x3f, 0xfb, 0xa2, 0x9d, 0xae, 0xc6, 0x3d, 0xaa, 0x13, 0x4d, 0x18, 0x7c, 0xd2, 0x28, 0xce, 0x72, 0xb1, 0x26, 0x3f, 0xba, 0xf8, 0xa6, 0x4b, 0x01, 0xb9, 0xa4, 0x5c, 0x43, 0x68, 0xd3, 0x46, 0x81, 0x00, 0x7f, 0x6a, 0xd7, 0xd1, 0x69, 0x51, 0x47, 0x25, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #else // other than _M_IX86 static BYTE SP3Sig[] = {0x8a, 0x06, 0x01, 0x6d, 0xc2, 0xb5, 0xa2, 0x66, 0x12, 0x1b, 0x9c, 0xe4, 0x58, 0xb1, 0xf8, 0x7d, 0xad, 0x17, 0xc1, 0xf9, 0x3f, 0x87, 0xe3, 0x9c, 0xdd, 0xeb, 0xcc, 0xa8, 0x6b, 0x62, 0xd0, 0x72, 0xe7, 0xf2, 0xec, 0xd6, 0xd6, 0x36, 0xab, 0x2d, 0x28, 0xea, 0x74, 0x07, 0x0e, 0x6c, 0x6d, 0xe1, 0xf8, 0x17, 0x97, 0x13, 0x8d, 0xb1, 0x8b, 0x0b, 0x33, 0x97, 0xc5, 0x46, 0x66, 0x96, 0xb4, 0xf7, 0x03, 0xc5, 0x03, 0x98, 0xf7, 0x91, 0xae, 0x9d, 0x00, 0x1a, 0xc6, 0x86, 0x30, 0x5c, 0xc8, 0xc7, 0x05, 0x47, 0xed, 0x2d, 0xc2, 0x0b, 0x61, 0x4b, 0xce, 0xe5, 0xb7, 0xd7, 0x27, 0x0c, 0x9e, 0x2f, 0xc5, 0x25, 0xe3, 0x81, 0x13, 0x9d, 0xa2, 0x67, 0xb2, 0x26, 0xfc, 0x99, 0x9d, 0xce, 0x0e, 0xaf, 0x30, 0xf3, 0x30, 0xec, 0xa3, 0x0a, 0xfe, 0x16, 0xb6, 0xda, 0x16, 0x90, 0x9a, 0x9a, 0x74, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif // _M_IX86 void CheckForSP3RSAOverwrite( void ) { // check for them having installed NTSP3 over the top of IE4, it nukes // the RSABASE reg stuff, so we have to re-do it. (our default platform is NT + SP3, but this // problem doesn't occur on NT5, so ignore it. OSVERSIONINFO osVer; ZeroMemory(&osVer, sizeof(osVer)); osVer.dwOSVersionInfoSize = sizeof(osVer); if( GetVersionEx(&osVer) && (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVer.dwMajorVersion == 4)) { // now check to see we are on SP3 ... DWORD dwValue = 0; DWORD dwSize = sizeof( dwValue ); if ( ERROR_SUCCESS == SHGetValue( HKEY_LOCAL_MACHINE, CSD_REG_PATH, CSD_REG_VALUE, NULL, &dwValue, &dwSize) && LOWORD( dwValue ) == 0x300 ) { BYTE rgbSig[136]; dwSize = sizeof(rgbSig); if (ERROR_SUCCESS == SHGetValue ( HKEY_LOCAL_MACHINE, RSA_PATH_TO_KEY, TEXT("Signature"), NULL, rgbSig, &dwSize)) { if ((dwSize == sizeof(SP3Sig)) && (0 == memcmp(SP3Sig, rgbSig, sizeof(SP3Sig)))) { // need to do a DLLRegisterServer on RSABase HINSTANCE hInst = LoadLibrary(TEXT("rsabase.dll")); if ( hInst ) { FARPROC pfnDllReg = GetProcAddress( hInst, "DllRegisterServer"); if ( pfnDllReg ) { __try { pfnDllReg(); } __except( EXCEPTION_EXECUTE_HANDLER) { } __endexcept } FreeLibrary( hInst ); } } } } } } #else #define CheckForSP3RSAOverwrite() #endif #define TEN_SECONDS (10 * 1000) LONG WINAPI DwExceptionFilter(LPEXCEPTION_POINTERS pep) { EXCEPTION_RECORD *per; HANDLE hFileMap = NULL; DWSharedMem *pdwsm = NULL; SECURITY_ATTRIBUTES sa; LONG lReturn = 0; // we keep local copies of these in case another thread is trashing memory // it much more likely to trash the heap than our stack HANDLE hEventDone = NULL; // event DW signals when done HANDLE hEventAlive = NULL; // heartbeat event DW signals per EVENT_TIMEOUT HANDLE hMutex = NULL; // to protect the signaling of EventDone CHAR szCommandLine[MAX_PATH * 2]; DWORD dwSize, dwType, dw; TCHAR tchURL[INTERNET_MAX_URL_LENGTH]; BOOL fDwRunning; STARTUPINFOA si; PROCESS_INFORMATION pi; // init if (pep) { per = pep->ExceptionRecord; if (EXCEPTION_BREAKPOINT == per->ExceptionCode) goto Cleanup; } // create shared memory memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof(DWSharedMem), NULL); if (hFileMap == NULL) { lReturn = 1; goto Cleanup; } pdwsm = (DWSharedMem *) MapViewOfFile(hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (pdwsm == NULL) { lReturn = 1; goto Cleanup; } memset(pdwsm, 0, sizeof(DWSharedMem)); hEventAlive = CreateEvent(&sa, FALSE, FALSE, NULL); hEventDone = CreateEvent(&sa, FALSE, FALSE, NULL); hMutex = CreateMutex(&sa, FALSE, NULL); if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &pdwsm->hProc, PROCESS_ALL_ACCESS, TRUE, 0)) { lReturn = 1; goto Cleanup; } if (hEventAlive == NULL || hEventDone == NULL || hMutex == NULL || pdwsm->hProc == NULL) { lReturn = 1; goto Cleanup; } // setup interface structure pdwsm->pid = GetCurrentProcessId(); pdwsm->tid = GetCurrentThreadId(); pdwsm->hEventAlive = hEventAlive; pdwsm->hEventDone = hEventDone; pdwsm->hMutex = hMutex; pdwsm->dwSize = sizeof(DWSharedMem); pdwsm->pep = pep; if (pep) pdwsm->eip = (DWORD_PTR) pep->ExceptionRecord->ExceptionAddress; pdwsm->bfmsoctdsOffer = MSODWRESTARTQUIT; pdwsm->lcidUI = MLGetUILanguage(); StrCpyNW(pdwsm->wzFormalAppName, L"Microsoft Internet Explorer", DW_APPNAME_LENGTH); StrCpyN(pdwsm->szRegSubPath, "Microsoft\\Office\\10.0\\Common", DW_MAX_REGSUBPATH); // Our language key? StrCpyN(pdwsm->szLCIDKeyValue, "HKCU\\Software\\Microsoft\\Office\\10.0\\Common\\LanguageResources\\UILanguage", DW_MAX_PATH); // Hey, they're pointing to our PID! That's cool. StrCpyN(pdwsm->szPIDRegKey, "HKLM\\Software\\Microsoft\\Internet Explorer\\Registration\\DigitalProductID", DW_MAX_PATH); // Okay, I'll send it there. // dwSize = INTERNET_MAX_URL_LENGTH; if (ERROR_SUCCESS == SHGetValueA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer\\Main", "IEWatsonURL", &dwType, tchURL, &dwSize)) { StrCpyN(pdwsm->szServer, tchURL, DW_MAX_SERVERNAME); } else { StrCpyN(pdwsm->szServer, "watson.microsoft.com", DW_MAX_SERVERNAME); } // Do not set details string. //StrCpyNW(pdwsm->wzErrorMessage, L"Internet Explorer has encountered an internal error.", DW_MAX_ERROR_CWC); // Core modules StrCpyNW(pdwsm->wzDotDataDlls, L"browseui.dll\0shdocvw.dll\0mshtml.dll\0urlmon.dll\0wininet.dll\0", DW_MAX_PATH); // This will usually be "IEXPLORE.EXE" GetModuleFileNameWrapW(NULL, pdwsm->wzModuleFileName, DW_MAX_PATH); // ok, now we don't want to accidently change this memset(&si, 0, sizeof(STARTUPINFOA)); si.cb = sizeof(STARTUPINFOA); memset(&pi, 0, sizeof(PROCESS_INFORMATION)); wnsprintfA(szCommandLine, sizeof(szCommandLine), "dw15 -x -s %u", (DWORD_PTR) hFileMap); if (CreateProcessA(NULL, szCommandLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { fDwRunning = TRUE; while (fDwRunning) { if (WaitForSingleObject(hEventAlive, DW_TIMEOUT_VALUE) == WAIT_OBJECT_0) { if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0) { fDwRunning = FALSE; } continue; } // we timed-out waiting for DW to respond, try to quit dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE); if (dw == WAIT_TIMEOUT) fDwRunning = FALSE; // either DW's hung or crashed, we must carry on else if (dw == WAIT_ABANDONED) { fDwRunning = FALSE; ReleaseMutex(hMutex); } else { // DW has not woken up? if (WaitForSingleObject(hEventAlive, 1) != WAIT_OBJECT_0) // tell DW we're through waiting for it's sorry self { SetEvent(hEventDone); fDwRunning = FALSE; } else { // are we done if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0) fDwRunning = FALSE; } ReleaseMutex(hMutex); } } } // end if CreateProcess succeeded Cleanup: if (hEventAlive) CloseHandle(hEventAlive); if (hEventDone) CloseHandle(hEventDone); if (hMutex) CloseHandle(hMutex); if (pdwsm) UnmapViewOfFile(pdwsm); if (hFileMap) CloseHandle(hFileMap); return lReturn; } //--------------------------------------------------------------------------- int WinMainT(HINSTANCE hinst, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow) { #ifdef DEBUG CcshellGetDebugFlags(); #endif int iRet = TRUE; HWND hwndDesktop ; BOOL fNowait = FALSE; BOOL fInproc = FALSE; BOOL fEval = FALSE; #ifdef UNIX BOOL fRemote = FALSE; #endif // DwExceptionFilter(NULL); For testing. while (1) { #ifdef UNIX if (IsCommandSwitch(lpszCmdLine, TEXT("-remote"), TRUE)) { fRemote = TRUE; } #endif if (IsCommandSwitch(lpszCmdLine, TEXT("-eval"), TRUE)) { fInproc = TRUE; fEval = TRUE; } else if (IsCommandSwitch(lpszCmdLine, TEXT("-new"), TRUE)) { fInproc = TRUE; } else if (IsCommandSwitch(lpszCmdLine, TEXT("-nowait"), TRUE)) { fNowait = TRUE; } else break; } #ifndef UNIX if (!GetModuleHandle(TEXT("IEXPLORE.EXE"))) { // For side by side install auto dection, if IExplore.exe is renamed, assume this is a side by side do dah // and we want to run in "evaluation" mode. fInproc = TRUE; fEval = TRUE; } #endif // Should we run browser in a new process? if (fInproc || SHRegGetBoolUSValue(c_szBrowseNewProcessReg, c_szBrowseNewProcess, FALSE, FALSE)) { goto InThisProcess; } #ifdef UNIX if (!(fRemote && ConnectRemoteIE(lpszCmdLine, hinst))) #endif if (WhichPlatform() == PLATFORM_INTEGRATED && (hwndDesktop = GetShellWindow())) { // // Integrated browser mode - package up a bunch of data into a COPYDATASTRUCT, // and send it to the desktop window via SendMessage(WM_COPYDATA). // COPYDATASTRUCT cds; cds.dwData = nCmdShow; // // First piece of data is a wide string version of the command line params. // LPWSTR pwszBuffer = (LPWSTR)LocalAlloc(LPTR, (INTERNET_MAX_URL_LENGTH + 2 * MAX_IEEVENTNAME) * sizeof(WCHAR));; if (pwszBuffer) { #ifdef UNICODE lstrcpy(pwszBuffer, lpszCmdLine); #else int cch = MultiByteToWideChar(CP_ACP, 0, lpszCmdLine, -1, pwszBuffer, INTERNET_MAX_URL_LENGTH); Assert(cch); #endif cds.lpData = pwszBuffer; cds.cbData = sizeof(WCHAR) * (lstrlenW((LPCWSTR)cds.lpData) + 1); // // Second piece of data is the event to fire when // the browser window reaches WM_CREATE. // HANDLE hEventReady = AppendEvent(&cds); if (hEventReady) { // // Third piece of data is the event to fire when // the browser window closes. This is optional, // we only create it (and wait for it) when there // are command line parameters. // HANDLE hEventDead = NULL; // The hard part is to figure out when we need the command line and when // we don't. For the most part if there is a command line we will assume that // we will need it (potentially) we could look for the -nowait flag. But then // there are others like NetManage ECCO Pro who do their equiv of ShellExecute // who don't pass a command line... if ((*lpszCmdLine || CheckForNeedingAppCompatWindow()) && !fNowait) { hEventDead = AppendEvent(&cds); } if (hEventDead || !*lpszCmdLine || fNowait) { // // Send that message! // int iRet = (int)SendMessage(hwndDesktop, WM_COPYDATA, (WPARAM)hwndDesktop, (LPARAM)&cds); // // Nobody needs the string anymore. // LocalFree(pwszBuffer); pwszBuffer = NULL; if (iRet) { // // First, we wait for the browser window to hit WM_CREATE. // When this happens, all DDE servers will have been registered. // DWORD dwRet = WaitForSingleObject(hEventReady, TEN_SECONDS); ASSERT(dwRet == WAIT_OBJECT_0); if (hEventDead) { // // Create an offscreen IE-lookalike window // owned by this process for app compat reasons. // HWND hwnd = CreateAppCompatWindow(hinst); do { // // Calling MsgWait... will cause any threads blocked // on WaitForInputIdle(IEXPLORE) to resume execution. // This is fine because the browser has already // registered its DDE servers by now. // dwRet = MsgWaitForMultipleObjects(1, &hEventDead, FALSE, INFINITE, QS_ALLINPUT); if (dwRet == WAIT_OBJECT_0) { // // Kill our helper window cleanly too. // DestroyWindow(hwnd); } MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { // // We got a quit message, drop out. // dwRet = WAIT_OBJECT_0; break; } TranslateMessage(&msg); DispatchMessage(&msg); } } while(dwRet != WAIT_OBJECT_0); } } iRet = !iRet; } if (hEventDead) { CloseHandle(hEventDead); } CloseHandle(hEventReady); } } if (pwszBuffer) { LocalFree(pwszBuffer); pwszBuffer = NULL; } } else { InThisProcess: // Browser only mode, check the SP3 bug CheckForSP3RSAOverwrite(); if (fEval) { // Set "compat" mode user agent WarnCompatMode(hinst); // #75454... let the compat mode setup set useragent in HKLM. //SetCompatModeUserAgentString(); // Run in eval mode. So we want everything from this dir. LoadLibrary("comctl32.DLL"); LoadLibrary("browseui.DLL"); LoadLibrary("shdocvw.DLL"); LoadLibrary("wininet.dll"); LoadLibrary("urlmon.dll"); LoadLibrary("mlang.dll"); LoadLibrary("mshtml.dll"); LoadLibrary("jscript.DLL"); } // On downlevel (non-Whistler), we set up a top-level exception filter so that we can report faults // using the Watson technology. // // In Whistler, this support is built in to the Kernel so we don't run this code. // if (!IsOS(OS_WHISTLERORGREATER)) { DWORD dw, dwSize, dwType; // As a policy check, look at HKLM before HKCU // dw = 1; // Default to enabled. dwSize = sizeof(dw); if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Internet Explorer\\Main", "IEWatsonEnabled", &dwType, &dw, &dwSize)) { // Check current user if we didn't find anything for the local machine. dwSize = sizeof(dw); SHGetValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Internet Explorer\\Main", "IEWatsonEnabled", &dwType, &dw, &dwSize); } if (dw) { SetUnhandledExceptionFilter(DwExceptionFilter); } } iRet = IEWinMain(lpszCmdLine, nCmdShow); } return iRet; } // DllGetLCID // // this API is for Office to retrieve our UI language // when they are hosted by iexplore. // STDAPI_(LCID) DllGetLCID (IBindCtx * pbc) { return MLGetUILanguage(); }