Source code of Windows XP (NT5)
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.

804 lines
27 KiB

  1. #include "iexplore.h"
  2. #include "rcids.h"
  3. #include "shlwapi.h"
  4. #include "msodw.h"
  5. #include <platform.h>
  6. #ifdef UNIX
  7. #include "unixstuff.h"
  8. #endif
  9. static const TCHAR c_szBrowseNewProcessReg[] = REGSTR_PATH_EXPLORER TEXT("\\BrowseNewProcess");
  10. static const TCHAR c_szBrowseNewProcess[] = TEXT("BrowseNewProcess");
  11. int WinMainT(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow);
  12. STDAPI_(int) ModuleEntry(void)
  13. {
  14. int i;
  15. STARTUPINFOA si;
  16. #ifdef UNICODE
  17. LPTSTR pszCmdLine = GetCommandLine();
  18. #else
  19. // for multibyte should make it unsigned
  20. BYTE * pszCmdLine = (BYTE *)GetCommandLine();
  21. #endif
  22. #if defined(UNIX)
  23. // IEUNIX: On solaris we are getting out of file handles with new code pages added to mlang
  24. // causing more nls files to be mmapped.
  25. INCREASE_FILEHANDLE_LIMIT;
  26. #endif
  27. //
  28. // We don't want the "No disk in drive X:" requesters, so we set
  29. // the critical error mask such that calls will just silently fail
  30. //
  31. SetErrorMode(SEM_FAILCRITICALERRORS);
  32. if(StopWatchMode() & SPMODE_BROWSER) // Used to get the start of browser total download time
  33. {
  34. StopWatch_Start(SWID_BROWSER_FRAME, TEXT("Browser Frame Start"), SPMODE_BROWSER | SPMODE_DEBUGOUT);
  35. }
  36. if ( *pszCmdLine == TEXT('\"') ) {
  37. /*
  38. * Scan, and skip over, subsequent characters until
  39. * another double-quote or a null is encountered.
  40. */
  41. while ( *++pszCmdLine && (*pszCmdLine
  42. != TEXT('\"')) );
  43. /*
  44. * If we stopped on a double-quote (usual case), skip
  45. * over it.
  46. */
  47. if ( *pszCmdLine == TEXT('\"') )
  48. pszCmdLine++;
  49. }
  50. else {
  51. while (*pszCmdLine > TEXT(' '))
  52. pszCmdLine++;
  53. }
  54. /*
  55. * Skip past any white space preceeding the second token.
  56. */
  57. while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
  58. pszCmdLine++;
  59. }
  60. si.dwFlags = 0;
  61. si.cb = sizeof(si);
  62. GetStartupInfoA(&si);
  63. i = WinMainT(GetModuleHandle(NULL), NULL, (LPTSTR)pszCmdLine,
  64. si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  65. #ifndef UNIX
  66. ExitThread(i); // We only come here when we are not the shell...
  67. #else
  68. // there seem to be some desirable side effect calling ExitThread on Windows
  69. ExitProcess(i);
  70. #endif
  71. return i;
  72. }
  73. //
  74. // Create a unique event name
  75. //
  76. HANDLE AppendEvent(COPYDATASTRUCT *pcds)
  77. {
  78. static DWORD dwNextID = 0;
  79. TCHAR szEvent[MAX_IEEVENTNAME];
  80. wsprintf(szEvent, "IE-%08X-%08X", GetCurrentThreadId(), dwNextID++);
  81. HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, szEvent);
  82. if (hEvent)
  83. {
  84. //
  85. // Put the (UNICODE) event name at the end of the cds data
  86. //
  87. LPWSTR pwszBufferEvent = (LPWSTR)(((BYTE *)pcds->lpData) + pcds->cbData);
  88. #ifdef UNICODE
  89. lstrcpy(pwszBufferEvent, szEvent);
  90. #else
  91. MultiByteToWideChar(CP_ACP, 0, szEvent, -1, pwszBufferEvent, ARRAYSIZE(szEvent));
  92. #endif
  93. pcds->cbData += (lstrlenW(pwszBufferEvent) + 1) * sizeof(WCHAR);
  94. }
  95. return hEvent;
  96. }
  97. BOOL IsCommandSwitch(LPTSTR lpszCmdLine, LPTSTR pszSwitch, BOOL fRemoveSwitch)
  98. {
  99. LPTSTR lpsz;
  100. if ((lpsz=StrStrI(lpszCmdLine, pszSwitch)) && (lpsz == lpszCmdLine))
  101. {
  102. int cch = lstrlen(pszSwitch);
  103. if (*(lpsz+cch) == 0 || *(lpsz+cch) == TEXT(' '))
  104. {
  105. while (*(lpsz+cch) == TEXT(' '))
  106. cch++;
  107. if (fRemoveSwitch)
  108. {
  109. // Remove the switch by copying everything up.
  110. *lpsz=0;
  111. lstrcat(lpsz, lpsz+cch);
  112. }
  113. return TRUE;
  114. }
  115. }
  116. return FALSE;
  117. }
  118. BOOL CheckForNeedingAppCompatWindow(void)
  119. {
  120. // Which I could simply get the Process of who spawned me. For now
  121. // try hack to get the foreground window and go from there...
  122. TCHAR szClassName[80];
  123. HWND hwnd = GetForegroundWindow();
  124. if (hwnd && GetClassName(hwnd, szClassName, ARRAYSIZE(szClassName)) > 0)
  125. {
  126. if (lstrcmpi(szClassName, TEXT("MauiFrame")) == 0)
  127. return TRUE;
  128. }
  129. return FALSE;
  130. }
  131. //
  132. // AppCompat - Sequel NetPIM execs a browser and then waits forever
  133. // looking for a visible top level window owned by this process.
  134. //
  135. HWND CreateAppCompatWindow(HINSTANCE hinst)
  136. {
  137. HWND hwnd;
  138. static const TCHAR c_szClass[] = TEXT("IEDummyFrame"); // IE3 used "IEFrame"
  139. WNDCLASS wc = { 0, DefWindowProc, 0, 0, hinst, NULL, NULL, NULL, NULL, c_szClass };
  140. RegisterClass(&wc);
  141. // Netmanage ECCO Pro asks to get the menu...
  142. HMENU hmenu = CreateMenu();
  143. hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, c_szClass, TEXT(""), 0,
  144. 0x00007FF0, 0x00007FF0, 0, 0,
  145. NULL, hmenu, hinst, NULL);
  146. // Don't open SHOWDEFAULT or this turkey could end up maximized
  147. ShowWindow(hwnd, SW_SHOWNA);
  148. return hwnd;
  149. }
  150. #define USERAGENT_POST_PLATFORM_PATH_TO_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent\\Post Platform")
  151. void SetCompatModeUserAgentString(void)
  152. {
  153. HKEY hkey;
  154. const char szcompat[]=TEXT("compat");
  155. if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, USERAGENT_POST_PLATFORM_PATH_TO_KEY, &hkey))
  156. {
  157. RegSetValueEx( hkey,
  158. szcompat,
  159. 0,
  160. REG_BINARY,
  161. (LPBYTE)NULL, 0);
  162. RegCloseKey(hkey);
  163. }
  164. }
  165. // Tell the user they are running in compat mode and not all the features will be available.
  166. #define IECOMPAT_REG_VAL TEXT("CompatWarningFor")
  167. void WarnCompatMode(HINSTANCE hinst)
  168. {
  169. TCHAR szFqFilename[MAX_PATH];
  170. TCHAR szRegVal[MAX_PATH];
  171. TCHAR szTitle[255];
  172. TCHAR szMsg[1024];
  173. LPTSTR szFile;
  174. GetModuleFileName(NULL, szFqFilename, ARRAYSIZE(szFqFilename));
  175. szFile = PathFindFileName(szFqFilename);
  176. // Build up string "compatmodewarningfor <exe name>" as value for reg key
  177. lstrcpy(szRegVal, IECOMPAT_REG_VAL);
  178. lstrcat(szRegVal, szFile);
  179. LoadString(hinst, IDS_COMPATMODEWARNINGTITLE, szTitle, ARRAYSIZE(szTitle));
  180. LoadString(hinst, IDS_COMPATMODEWARNING, szMsg, ARRAYSIZE(szMsg));
  181. SHMessageBoxCheck(NULL, szMsg, szTitle, MB_OK, FALSE, szRegVal);
  182. }
  183. #ifdef WINNT
  184. // this is the same code that is in explorer.exe (initcab.c)
  185. #define RSA_PATH_TO_KEY TEXT("Software\\Microsoft\\Cryptography\\Defaults\\Provider\\Microsoft Base Cryptographic Provider v1.0")
  186. #define CSD_REG_PATH TEXT("System\\CurrentControlSet\\Control\\Windows")
  187. #define CSD_REG_VALUE TEXT("CSDVersion")
  188. // the signatures we are looking for in the regsitry so that we can patch up
  189. #ifdef _M_IX86
  190. static BYTE SP3Sig[] = {0xbd, 0x9f, 0x13, 0xc5, 0x92, 0x12, 0x2b, 0x72,
  191. 0x4a, 0xba, 0xb6, 0x2a, 0xf9, 0xfc, 0x54, 0x46,
  192. 0x6f, 0xa1, 0xb4, 0xbb, 0x43, 0xa8, 0xfe, 0xf8,
  193. 0xa8, 0x23, 0x7d, 0xd1, 0x85, 0x84, 0x22, 0x6e,
  194. 0xb4, 0x58, 0x00, 0x3e, 0x0b, 0x19, 0x83, 0x88,
  195. 0x6a, 0x8d, 0x64, 0x02, 0xdf, 0x5f, 0x65, 0x7e,
  196. 0x3b, 0x4d, 0xd4, 0x10, 0x44, 0xb9, 0x46, 0x34,
  197. 0xf3, 0x40, 0xf4, 0xbc, 0x9f, 0x4b, 0x82, 0x1e,
  198. 0xcc, 0xa7, 0xd0, 0x2d, 0x22, 0xd7, 0xb1, 0xf0,
  199. 0x2e, 0xcd, 0x0e, 0x21, 0x52, 0xbc, 0x3e, 0x81,
  200. 0xb1, 0x1a, 0x86, 0x52, 0x4d, 0x3f, 0xfb, 0xa2,
  201. 0x9d, 0xae, 0xc6, 0x3d, 0xaa, 0x13, 0x4d, 0x18,
  202. 0x7c, 0xd2, 0x28, 0xce, 0x72, 0xb1, 0x26, 0x3f,
  203. 0xba, 0xf8, 0xa6, 0x4b, 0x01, 0xb9, 0xa4, 0x5c,
  204. 0x43, 0x68, 0xd3, 0x46, 0x81, 0x00, 0x7f, 0x6a,
  205. 0xd7, 0xd1, 0x69, 0x51, 0x47, 0x25, 0x14, 0x40,
  206. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  207. #else // other than _M_IX86
  208. static BYTE SP3Sig[] = {0x8a, 0x06, 0x01, 0x6d, 0xc2, 0xb5, 0xa2, 0x66,
  209. 0x12, 0x1b, 0x9c, 0xe4, 0x58, 0xb1, 0xf8, 0x7d,
  210. 0xad, 0x17, 0xc1, 0xf9, 0x3f, 0x87, 0xe3, 0x9c,
  211. 0xdd, 0xeb, 0xcc, 0xa8, 0x6b, 0x62, 0xd0, 0x72,
  212. 0xe7, 0xf2, 0xec, 0xd6, 0xd6, 0x36, 0xab, 0x2d,
  213. 0x28, 0xea, 0x74, 0x07, 0x0e, 0x6c, 0x6d, 0xe1,
  214. 0xf8, 0x17, 0x97, 0x13, 0x8d, 0xb1, 0x8b, 0x0b,
  215. 0x33, 0x97, 0xc5, 0x46, 0x66, 0x96, 0xb4, 0xf7,
  216. 0x03, 0xc5, 0x03, 0x98, 0xf7, 0x91, 0xae, 0x9d,
  217. 0x00, 0x1a, 0xc6, 0x86, 0x30, 0x5c, 0xc8, 0xc7,
  218. 0x05, 0x47, 0xed, 0x2d, 0xc2, 0x0b, 0x61, 0x4b,
  219. 0xce, 0xe5, 0xb7, 0xd7, 0x27, 0x0c, 0x9e, 0x2f,
  220. 0xc5, 0x25, 0xe3, 0x81, 0x13, 0x9d, 0xa2, 0x67,
  221. 0xb2, 0x26, 0xfc, 0x99, 0x9d, 0xce, 0x0e, 0xaf,
  222. 0x30, 0xf3, 0x30, 0xec, 0xa3, 0x0a, 0xfe, 0x16,
  223. 0xb6, 0xda, 0x16, 0x90, 0x9a, 0x9a, 0x74, 0x7a,
  224. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  225. #endif // _M_IX86
  226. void CheckForSP3RSAOverwrite( void )
  227. {
  228. // check for them having installed NTSP3 over the top of IE4, it nukes
  229. // the RSABASE reg stuff, so we have to re-do it. (our default platform is NT + SP3, but this
  230. // problem doesn't occur on NT5, so ignore it.
  231. OSVERSIONINFO osVer;
  232. ZeroMemory(&osVer, sizeof(osVer));
  233. osVer.dwOSVersionInfoSize = sizeof(osVer);
  234. if( GetVersionEx(&osVer) && (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
  235. && (osVer.dwMajorVersion == 4))
  236. {
  237. // now check to see we are on SP3 ...
  238. DWORD dwValue = 0;
  239. DWORD dwSize = sizeof( dwValue );
  240. if ( ERROR_SUCCESS == SHGetValue( HKEY_LOCAL_MACHINE, CSD_REG_PATH, CSD_REG_VALUE, NULL,
  241. &dwValue, &dwSize) && LOWORD( dwValue ) == 0x300 )
  242. {
  243. BYTE rgbSig[136];
  244. dwSize = sizeof(rgbSig);
  245. if (ERROR_SUCCESS == SHGetValue ( HKEY_LOCAL_MACHINE, RSA_PATH_TO_KEY, TEXT("Signature"), NULL,
  246. rgbSig, &dwSize))
  247. {
  248. if ((dwSize == sizeof(SP3Sig)) &&
  249. (0 == memcmp(SP3Sig, rgbSig, sizeof(SP3Sig))))
  250. {
  251. // need to do a DLLRegisterServer on RSABase
  252. HINSTANCE hInst = LoadLibrary(TEXT("rsabase.dll"));
  253. if ( hInst )
  254. {
  255. FARPROC pfnDllReg = GetProcAddress( hInst, "DllRegisterServer");
  256. if ( pfnDllReg )
  257. {
  258. __try
  259. {
  260. pfnDllReg();
  261. }
  262. __except( EXCEPTION_EXECUTE_HANDLER)
  263. {
  264. }
  265. __endexcept
  266. }
  267. FreeLibrary( hInst );
  268. }
  269. }
  270. }
  271. }
  272. }
  273. }
  274. #else
  275. #define CheckForSP3RSAOverwrite()
  276. #endif
  277. #define TEN_SECONDS (10 * 1000)
  278. LONG WINAPI DwExceptionFilter(LPEXCEPTION_POINTERS pep)
  279. {
  280. EXCEPTION_RECORD *per;
  281. HANDLE hFileMap = NULL;
  282. DWSharedMem *pdwsm = NULL;
  283. SECURITY_ATTRIBUTES sa;
  284. LONG lReturn = 0;
  285. // we keep local copies of these in case another thread is trashing memory
  286. // it much more likely to trash the heap than our stack
  287. HANDLE hEventDone = NULL; // event DW signals when done
  288. HANDLE hEventAlive = NULL; // heartbeat event DW signals per EVENT_TIMEOUT
  289. HANDLE hMutex = NULL; // to protect the signaling of EventDone
  290. CHAR szCommandLine[MAX_PATH * 2];
  291. DWORD dwSize, dwType, dw;
  292. TCHAR tchURL[INTERNET_MAX_URL_LENGTH];
  293. BOOL fDwRunning;
  294. STARTUPINFOA si;
  295. PROCESS_INFORMATION pi;
  296. // init
  297. if (pep)
  298. {
  299. per = pep->ExceptionRecord;
  300. if (EXCEPTION_BREAKPOINT == per->ExceptionCode)
  301. goto Cleanup;
  302. }
  303. // create shared memory
  304. memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
  305. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  306. sa.bInheritHandle = TRUE;
  307. hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0,
  308. sizeof(DWSharedMem), NULL);
  309. if (hFileMap == NULL)
  310. {
  311. lReturn = 1;
  312. goto Cleanup;
  313. }
  314. pdwsm = (DWSharedMem *) MapViewOfFile(hFileMap,
  315. FILE_MAP_READ | FILE_MAP_WRITE,
  316. 0, 0, 0);
  317. if (pdwsm == NULL)
  318. {
  319. lReturn = 1;
  320. goto Cleanup;
  321. }
  322. memset(pdwsm, 0, sizeof(DWSharedMem));
  323. hEventAlive = CreateEvent(&sa, FALSE, FALSE, NULL);
  324. hEventDone = CreateEvent(&sa, FALSE, FALSE, NULL);
  325. hMutex = CreateMutex(&sa, FALSE, NULL);
  326. if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
  327. GetCurrentProcess(), &pdwsm->hProc, PROCESS_ALL_ACCESS,
  328. TRUE, 0))
  329. {
  330. lReturn = 1;
  331. goto Cleanup;
  332. }
  333. if (hEventAlive == NULL || hEventDone == NULL || hMutex == NULL
  334. || pdwsm->hProc == NULL)
  335. {
  336. lReturn = 1;
  337. goto Cleanup;
  338. }
  339. // setup interface structure
  340. pdwsm->pid = GetCurrentProcessId();
  341. pdwsm->tid = GetCurrentThreadId();
  342. pdwsm->hEventAlive = hEventAlive;
  343. pdwsm->hEventDone = hEventDone;
  344. pdwsm->hMutex = hMutex;
  345. pdwsm->dwSize = sizeof(DWSharedMem);
  346. pdwsm->pep = pep;
  347. if (pep)
  348. pdwsm->eip = (DWORD_PTR) pep->ExceptionRecord->ExceptionAddress;
  349. pdwsm->bfmsoctdsOffer = MSODWRESTARTQUIT;
  350. pdwsm->lcidUI = MLGetUILanguage();
  351. StrCpyNW(pdwsm->wzFormalAppName, L"Microsoft Internet Explorer", DW_APPNAME_LENGTH);
  352. StrCpyN(pdwsm->szRegSubPath, "Microsoft\\Office\\10.0\\Common", DW_MAX_REGSUBPATH);
  353. // Our language key?
  354. StrCpyN(pdwsm->szLCIDKeyValue,
  355. "HKCU\\Software\\Microsoft\\Office\\10.0\\Common\\LanguageResources\\UILanguage", DW_MAX_PATH);
  356. // Hey, they're pointing to our PID! That's cool.
  357. StrCpyN(pdwsm->szPIDRegKey,
  358. "HKLM\\Software\\Microsoft\\Internet Explorer\\Registration\\DigitalProductID", DW_MAX_PATH);
  359. // Okay, I'll send it there.
  360. //
  361. dwSize = INTERNET_MAX_URL_LENGTH;
  362. if (ERROR_SUCCESS == SHGetValueA(HKEY_LOCAL_MACHINE,
  363. "Software\\Microsoft\\Internet Explorer\\Main",
  364. "IEWatsonURL",
  365. &dwType, tchURL, &dwSize))
  366. {
  367. StrCpyN(pdwsm->szServer, tchURL, DW_MAX_SERVERNAME);
  368. }
  369. else
  370. {
  371. StrCpyN(pdwsm->szServer, "watson.microsoft.com", DW_MAX_SERVERNAME);
  372. }
  373. // Do not set details string.
  374. //StrCpyNW(pdwsm->wzErrorMessage, L"Internet Explorer has encountered an internal error.", DW_MAX_ERROR_CWC);
  375. // Core modules
  376. StrCpyNW(pdwsm->wzDotDataDlls, L"browseui.dll\0shdocvw.dll\0mshtml.dll\0urlmon.dll\0wininet.dll\0", DW_MAX_PATH);
  377. // This will usually be "IEXPLORE.EXE"
  378. GetModuleFileNameWrapW(NULL, pdwsm->wzModuleFileName, DW_MAX_PATH);
  379. // ok, now we don't want to accidently change this
  380. memset(&si, 0, sizeof(STARTUPINFOA));
  381. si.cb = sizeof(STARTUPINFOA);
  382. memset(&pi, 0, sizeof(PROCESS_INFORMATION));
  383. wnsprintfA(szCommandLine, sizeof(szCommandLine),
  384. "dw15 -x -s %u",
  385. (DWORD_PTR) hFileMap);
  386. if (CreateProcessA(NULL, szCommandLine, NULL, NULL, TRUE,
  387. CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL,
  388. NULL, &si, &pi))
  389. {
  390. fDwRunning = TRUE;
  391. while (fDwRunning)
  392. {
  393. if (WaitForSingleObject(hEventAlive, DW_TIMEOUT_VALUE)
  394. == WAIT_OBJECT_0)
  395. {
  396. if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0)
  397. {
  398. fDwRunning = FALSE;
  399. }
  400. continue;
  401. }
  402. // we timed-out waiting for DW to respond, try to quit
  403. dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE);
  404. if (dw == WAIT_TIMEOUT)
  405. fDwRunning = FALSE; // either DW's hung or crashed, we must carry on
  406. else if (dw == WAIT_ABANDONED)
  407. {
  408. fDwRunning = FALSE;
  409. ReleaseMutex(hMutex);
  410. }
  411. else
  412. {
  413. // DW has not woken up?
  414. if (WaitForSingleObject(hEventAlive, 1) != WAIT_OBJECT_0)
  415. // tell DW we're through waiting for it's sorry self
  416. {
  417. SetEvent(hEventDone);
  418. fDwRunning = FALSE;
  419. }
  420. else
  421. {
  422. // are we done
  423. if (WaitForSingleObject(hEventDone, 1)
  424. == WAIT_OBJECT_0)
  425. fDwRunning = FALSE;
  426. }
  427. ReleaseMutex(hMutex);
  428. }
  429. }
  430. } // end if CreateProcess succeeded
  431. Cleanup:
  432. if (hEventAlive)
  433. CloseHandle(hEventAlive);
  434. if (hEventDone)
  435. CloseHandle(hEventDone);
  436. if (hMutex)
  437. CloseHandle(hMutex);
  438. if (pdwsm)
  439. UnmapViewOfFile(pdwsm);
  440. if (hFileMap)
  441. CloseHandle(hFileMap);
  442. return lReturn;
  443. }
  444. //---------------------------------------------------------------------------
  445. int WinMainT(HINSTANCE hinst, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow)
  446. {
  447. #ifdef DEBUG
  448. CcshellGetDebugFlags();
  449. #endif
  450. int iRet = TRUE;
  451. HWND hwndDesktop ;
  452. BOOL fNowait = FALSE;
  453. BOOL fInproc = FALSE;
  454. BOOL fEval = FALSE;
  455. #ifdef UNIX
  456. BOOL fRemote = FALSE;
  457. #endif
  458. // DwExceptionFilter(NULL); For testing.
  459. while (1) {
  460. #ifdef UNIX
  461. if (IsCommandSwitch(lpszCmdLine, TEXT("-remote"), TRUE))
  462. {
  463. fRemote = TRUE;
  464. }
  465. #endif
  466. if (IsCommandSwitch(lpszCmdLine, TEXT("-eval"), TRUE))
  467. {
  468. fInproc = TRUE;
  469. fEval = TRUE;
  470. } else if (IsCommandSwitch(lpszCmdLine, TEXT("-new"), TRUE))
  471. {
  472. fInproc = TRUE;
  473. }
  474. else if (IsCommandSwitch(lpszCmdLine, TEXT("-nowait"), TRUE))
  475. {
  476. fNowait = TRUE;
  477. }
  478. else
  479. break;
  480. }
  481. #ifndef UNIX
  482. if (!GetModuleHandle(TEXT("IEXPLORE.EXE")))
  483. {
  484. // For side by side install auto dection, if IExplore.exe is renamed, assume this is a side by side do dah
  485. // and we want to run in "evaluation" mode.
  486. fInproc = TRUE;
  487. fEval = TRUE;
  488. }
  489. #endif
  490. // Should we run browser in a new process?
  491. if (fInproc || SHRegGetBoolUSValue(c_szBrowseNewProcessReg, c_szBrowseNewProcess, FALSE, FALSE))
  492. {
  493. goto InThisProcess;
  494. }
  495. #ifdef UNIX
  496. if (!(fRemote && ConnectRemoteIE(lpszCmdLine, hinst)))
  497. #endif
  498. if (WhichPlatform() == PLATFORM_INTEGRATED && (hwndDesktop = GetShellWindow()))
  499. {
  500. //
  501. // Integrated browser mode - package up a bunch of data into a COPYDATASTRUCT,
  502. // and send it to the desktop window via SendMessage(WM_COPYDATA).
  503. //
  504. COPYDATASTRUCT cds;
  505. cds.dwData = nCmdShow;
  506. //
  507. // First piece of data is a wide string version of the command line params.
  508. //
  509. LPWSTR pwszBuffer = (LPWSTR)LocalAlloc(LPTR, (INTERNET_MAX_URL_LENGTH + 2 * MAX_IEEVENTNAME) * sizeof(WCHAR));;
  510. if (pwszBuffer)
  511. {
  512. #ifdef UNICODE
  513. lstrcpy(pwszBuffer, lpszCmdLine);
  514. #else
  515. int cch = MultiByteToWideChar(CP_ACP, 0, lpszCmdLine, -1, pwszBuffer, INTERNET_MAX_URL_LENGTH);
  516. Assert(cch);
  517. #endif
  518. cds.lpData = pwszBuffer;
  519. cds.cbData = sizeof(WCHAR) * (lstrlenW((LPCWSTR)cds.lpData) + 1);
  520. //
  521. // Second piece of data is the event to fire when
  522. // the browser window reaches WM_CREATE.
  523. //
  524. HANDLE hEventReady = AppendEvent(&cds);
  525. if (hEventReady)
  526. {
  527. //
  528. // Third piece of data is the event to fire when
  529. // the browser window closes. This is optional,
  530. // we only create it (and wait for it) when there
  531. // are command line parameters.
  532. //
  533. HANDLE hEventDead = NULL;
  534. // The hard part is to figure out when we need the command line and when
  535. // we don't. For the most part if there is a command line we will assume that
  536. // we will need it (potentially) we could look for the -nowait flag. But then
  537. // there are others like NetManage ECCO Pro who do their equiv of ShellExecute
  538. // who don't pass a command line...
  539. if ((*lpszCmdLine || CheckForNeedingAppCompatWindow()) && !fNowait)
  540. {
  541. hEventDead = AppendEvent(&cds);
  542. }
  543. if (hEventDead || !*lpszCmdLine || fNowait)
  544. {
  545. //
  546. // Send that message!
  547. //
  548. int iRet = (int)SendMessage(hwndDesktop, WM_COPYDATA, (WPARAM)hwndDesktop, (LPARAM)&cds);
  549. //
  550. // Nobody needs the string anymore.
  551. //
  552. LocalFree(pwszBuffer);
  553. pwszBuffer = NULL;
  554. if (iRet)
  555. {
  556. //
  557. // First, we wait for the browser window to hit WM_CREATE.
  558. // When this happens, all DDE servers will have been registered.
  559. //
  560. DWORD dwRet = WaitForSingleObject(hEventReady, TEN_SECONDS);
  561. ASSERT(dwRet == WAIT_OBJECT_0);
  562. if (hEventDead)
  563. {
  564. //
  565. // Create an offscreen IE-lookalike window
  566. // owned by this process for app compat reasons.
  567. //
  568. HWND hwnd = CreateAppCompatWindow(hinst);
  569. do
  570. {
  571. //
  572. // Calling MsgWait... will cause any threads blocked
  573. // on WaitForInputIdle(IEXPLORE) to resume execution.
  574. // This is fine because the browser has already
  575. // registered its DDE servers by now.
  576. //
  577. dwRet = MsgWaitForMultipleObjects(1, &hEventDead, FALSE, INFINITE, QS_ALLINPUT);
  578. if (dwRet == WAIT_OBJECT_0)
  579. {
  580. //
  581. // Kill our helper window cleanly too.
  582. //
  583. DestroyWindow(hwnd);
  584. }
  585. MSG msg;
  586. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  587. {
  588. if (msg.message == WM_QUIT)
  589. {
  590. //
  591. // We got a quit message, drop out.
  592. //
  593. dwRet = WAIT_OBJECT_0;
  594. break;
  595. }
  596. TranslateMessage(&msg);
  597. DispatchMessage(&msg);
  598. }
  599. }
  600. while(dwRet != WAIT_OBJECT_0);
  601. }
  602. }
  603. iRet = !iRet;
  604. }
  605. if (hEventDead)
  606. {
  607. CloseHandle(hEventDead);
  608. }
  609. CloseHandle(hEventReady);
  610. }
  611. }
  612. if (pwszBuffer)
  613. {
  614. LocalFree(pwszBuffer);
  615. pwszBuffer = NULL;
  616. }
  617. }
  618. else
  619. {
  620. InThisProcess:
  621. // Browser only mode, check the SP3 bug
  622. CheckForSP3RSAOverwrite();
  623. if (fEval)
  624. {
  625. // Set "compat" mode user agent
  626. WarnCompatMode(hinst);
  627. // #75454... let the compat mode setup set useragent in HKLM.
  628. //SetCompatModeUserAgentString();
  629. // Run in eval mode. So we want everything from this dir.
  630. LoadLibrary("comctl32.DLL");
  631. LoadLibrary("browseui.DLL");
  632. LoadLibrary("shdocvw.DLL");
  633. LoadLibrary("wininet.dll");
  634. LoadLibrary("urlmon.dll");
  635. LoadLibrary("mlang.dll");
  636. LoadLibrary("mshtml.dll");
  637. LoadLibrary("jscript.DLL");
  638. }
  639. // On downlevel (non-Whistler), we set up a top-level exception filter so that we can report faults
  640. // using the Watson technology.
  641. //
  642. // In Whistler, this support is built in to the Kernel so we don't run this code.
  643. //
  644. if (!IsOS(OS_WHISTLERORGREATER))
  645. {
  646. DWORD dw, dwSize, dwType;
  647. // As a policy check, look at HKLM before HKCU
  648. //
  649. dw = 1; // Default to enabled.
  650. dwSize = sizeof(dw);
  651. if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE,
  652. "Software\\Microsoft\\Internet Explorer\\Main",
  653. "IEWatsonEnabled",
  654. &dwType, &dw, &dwSize))
  655. {
  656. // Check current user if we didn't find anything for the local machine.
  657. dwSize = sizeof(dw);
  658. SHGetValue(HKEY_CURRENT_USER,
  659. "Software\\Microsoft\\Internet Explorer\\Main",
  660. "IEWatsonEnabled",
  661. &dwType, &dw, &dwSize);
  662. }
  663. if (dw)
  664. {
  665. SetUnhandledExceptionFilter(DwExceptionFilter);
  666. }
  667. }
  668. iRet = IEWinMain(lpszCmdLine, nCmdShow);
  669. }
  670. return iRet;
  671. }
  672. // DllGetLCID
  673. //
  674. // this API is for Office to retrieve our UI language
  675. // when they are hosted by iexplore.
  676. //
  677. STDAPI_(LCID) DllGetLCID (IBindCtx * pbc)
  678. {
  679. return MLGetUILanguage();
  680. }