mirror of https://github.com/tongzx/nt5src
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
804 lines
27 KiB
#include "iexplore.h"
|
|
#include "rcids.h"
|
|
#include "shlwapi.h"
|
|
#include "msodw.h"
|
|
|
|
#include <platform.h>
|
|
|
|
#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 <exe name>" 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();
|
|
}
|
|
|