windows-nt/Source/XPSP1/NT/shell/shdocvw/mainloop.cpp
2020-09-26 16:20:57 +08:00

444 lines
12 KiB
C++

#include "priv.h"
#include <iethread.h>
#include "winlist.h"
#include "htregmng.h"
#include "resource.h"
#include "inetnot.h"
#include <mluisupp.h>
// Inststub uses kernel string funcions and unbounded buffer functions
#undef lstrcpyn
#undef lstrcmp
#undef lstrcpy
#undef lstrcmpi
#undef StrCpyW
#define lstrcpy StrCpyW
#define lstrcpyn StrCpyNW
#define lstrcmp StrCmpW
#define lstrcmpi StrCmpIW
// need these defined before including <runonce.c> which is included by <inststub.h>
BOOL g_fCleanBoot = FALSE;
BOOL g_fEndSession = FALSE;
#include <inststub.h>
#undef lstrcpyn
#undef lstrcmp
#undef lstrcpy
#undef lstrcmpi
#define lstrcpyn Do_not_use_lstrcpyn_use_StrCpyN
#define lstrcmp Do_not_use_lstrcmp_use_StrCmp
#define lstrcpy Do_not_use_lstrcpy_use_StrCpyN
#define lstrcmpi Do_not_use_lstrcmpi_use_StrCmpI
#define StrCpyW Do_not_use_StrCpyW_use_StrCpyNW
#ifdef UNIX
#include "unixstuff.h"
#endif
/* Old install stub API (no parameters) for compatibility for a few builds */
EXTERN_C void RunInstallUninstallStubs(void)
{
RunInstallUninstallStubs2(NULL);
}
void IERevokeClassFactoryObject(void);
#ifndef POSTPOSTSPLIT
// This value will be initialized to 0 only when we are under IExplorer.exe
UINT g_tidParking = 0;
#endif
#define DM_FAVORITES 0
#ifdef BETA_WARNING
#pragma message("buidling with time bomb enabled")
void DoTimebomb(HWND hwnd)
{
SYSTEMTIME st;
GetSystemTime(&st);
//
// Revision History:
// End of October, 1996
// April, 1997
// September, 1997 (for beta-1)
// November 15th, 1997 (for beta-2)
//
if (st.wYear > 1997 || (st.wYear==1997 && st.wMonth > 11) ||
(st.wYear==1997 && st.wMonth == 11 && st.wDay > 15))
{
TCHAR szTitle[128];
TCHAR szBeta[512];
MLLoadShellLangString(IDS_CABINET, szTitle, ARRAYSIZE(szTitle));
MLLoadShellLangString(IDS_BETAEXPIRED, szBeta, ARRAYSIZE(szBeta));
MessageBox(hwnd, szBeta, szTitle, MB_OK);
}
}
#else
#define DoTimebomb(hwnd)
#endif
/*----------------------------------------------------------
Purpose: Initialize the favorites folder if it doesn't exist.
Returns: --
Cond: As a side-effect, SHGetSpecialFolderPath calls Ole
functions. So this function must be called after
OleInitialize has been called.
Note: This is only really required on win95 / NT4 in
browser only mode. The shell32.dll that ships
with IE4 can handle CSIDL_FAVORITES with fCreate=TRUE.
*/
void InitFavoritesDir()
{
TCHAR szPath[MAX_PATH];
if (!SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE))
{
TCHAR szFavorites[80];
TraceMsg(DM_FAVORITES, "InitFavoritesDir -- no favorites");
// if this failed, that means we need to create it ourselves
GetWindowsDirectory(szPath, ARRAYSIZE(szPath));
MLLoadString(IDS_FAVORITES, szFavorites, ARRAYSIZE(szFavorites));
PathCombine(szPath, szPath, szFavorites);
SHCreateDirectory(NULL, szPath);
HKEY hkExplorer;
if (RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER, &hkExplorer) == ERROR_SUCCESS)
{
HKEY hkUSF;
if (RegCreateKey(hkExplorer, TEXT("User Shell Folders"), &hkUSF) == ERROR_SUCCESS)
{
BOOL f;
TraceMsg(DM_FAVORITES, "InitFavoritesDir -- created in %s", szPath);
RegSetValueEx(hkUSF, TEXT("Favorites"), 0, REG_SZ, (LPBYTE)szPath, (1 + lstrlen(szPath)) * SIZEOF(TCHAR));
f = SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE);
TraceMsg(DM_FAVORITES, "InitFavoritesDir -- cached at %d %s", f, szPath);
ASSERT(f);
RegCloseKey(hkUSF);
}
RegCloseKey(hkExplorer);
}
}
}
#ifdef ENABLE_CHANNELS
//
// Copy ChanBarSetAutoLaunchRegValue from browseui.
//
//extern void ChanBarSetAutoLaunchRegValue(BOOL fAutoLaunch);
void ChanBarSetAutoLaunchRegValue(BOOL fAutoLaunch)
{
SHRegSetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
TEXT("Show_ChannelBand"), REG_SZ,
fAutoLaunch ? TEXT("yes") : TEXT("no"),
sizeof(fAutoLaunch ? TEXT("yes") : TEXT("no")),
SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
}
#endif // ENABLE_CHANNELS
STDAPI SHCreateSplashScreen(ISplashScreen ** pSplash);
typedef BOOL (*PFNISDEBUGGERPRESENT)(void);
void CUrlHistory_CleanUp();
//
// Mean Time To Failure check routines
//
#define REG_STR_IE TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main")
#define REG_STR_CLEAN TEXT("CleanBrowserShutdown")
LONG GetSessionCount();
void WriteCleanBrowserShutdown(BOOL fClean)
{
HKEY hkey;
DWORD dwValue = (DWORD)fClean;
//
// Only do MTTF on the first browser session
//
if (GetSessionCount() != 0)
return;
if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_STR_IE, 0, KEY_WRITE, &hkey)
== ERROR_SUCCESS)
{
RegSetValueEx(hkey, REG_STR_CLEAN,
0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
RegCloseKey(hkey);
}
}
BOOL ReadCleanBrowserShutdown()
{
HKEY hkey;
DWORD dwValue = 1; // default to clean shutdown
DWORD dwSize;
//
// Only do MTTF on the first browser session
//
if (GetSessionCount() != 0)
return TRUE;
if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_STR_IE, 0, KEY_READ, &hkey)
== ERROR_SUCCESS)
{
RegQueryValueEx(hkey, REG_STR_CLEAN, NULL, NULL, (LPBYTE)&dwValue, &dwSize);
RegCloseKey(hkey);
}
return (BOOL)dwValue;
}
void _TweakCurrentDirectory()
{
#ifndef UNIX
TCHAR szPath[MAX_PATH];
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
SetCurrentDirectory(szPath);
#endif
}
BOOL _IsDebuggerPresent()
{
static BOOL bDebugger = -1;
if (bDebugger == -1)
{
bDebugger = FALSE;
// See if a debugger is present and bail on splash screen
// so we don't get in the way of people... This api is only
// present on NT...
if (g_fRunningOnNT)
{
PFNISDEBUGGERPRESENT pfndebugger = (PFNISDEBUGGERPRESENT)GetProcAddress(GetModuleHandle(TEXT("KERNEL32")), "IsDebuggerPresent");
if (pfndebugger)
bDebugger = pfndebugger();
}
}
return bDebugger;
}
PCWSTR IEGetArgs(PCWSTR pszCmd)
{
if (*pszCmd == TEXT('\"'))
{
// just strip the first quoted string
while (*++pszCmd)
{
if (*pszCmd == L'\"')
{
pszCmd++;
break;
}
}
}
else
{
while (*pszCmd > TEXT(' '))
pszCmd++;
}
// strip the leading spaces
while (*pszCmd && *pszCmd <= L' ')
pszCmd++;
return pszCmd;
}
PCWSTR EatIExploreArgs(PCWSTR pszArgs)
{
// this switches match the switches that are conumed/checked
// in iexplore\mainloop.cpp. most params are in SHParseIECommandLine
// but these few apply only to IExplore.exe
static const PCWSTR s_pszEatArgs[] =
{
L"-eval",
L"-new",
L"-nowait"
};
pszArgs = IEGetArgs(pszArgs);
for (int i = 0; i < ARRAYSIZE(s_pszEatArgs); i++)
{
int cch = lstrlenW(s_pszEatArgs[i]);
if (0 == StrCmpNIW(s_pszEatArgs[i], pszArgs, cch))
{
if (!pszArgs[cch] || pszArgs[cch] == L' ')
pszArgs += cch;
// strip the spaces
while (pszArgs[0] == L' ')
pszArgs++;
// start over, we need to go through this list until we get them all
i = -1;
}
}
return pszArgs;
}
BOOL g_fBrowserOnlyProcess = FALSE;
// this entry is used by IEXPLORE.EXE to run the browser in a separate process. this is the
// standard setting, but browsers (IE) can also be run in the same process if BrowseInSeparateProcess
// is turned off (for better perf, worse stability)
STDAPI_(int) IEWinMain(LPSTR pszCmdLine, int nCmdShow)
{
// this flag indicates that this
// browser is running in its own process
// and is not integrated with the shell
// even if it is running on an intgrated shell
g_fBrowserOnlyProcess = TRUE;
_TweakCurrentDirectory();
if (g_dwProfileCAP & 0x00000001)
StartCAP();
#ifdef FULL_DEBUG
// Turn off GDI batching so that paints are performed immediately
GdiSetBatchLimit(1);
#endif
ASSERT(g_tidParking == 0);
g_tidParking = GetCurrentThreadId();
ISplashScreen *pSplash = NULL;
#ifndef UNIX
// Show splash screen, be simple for beta 1...
if (!_IsDebuggerPresent())
{
if (SUCCEEDED(SHCreateSplashScreen(&pSplash)))
{
HWND hSplash;
pSplash->Show( HINST_THISDLL, -1, -1, &hSplash );
}
}
#endif
if (SUCCEEDED(OleInitialize(NULL)))
{
BOOL fWeOwnWinList = WinList_Init();
IETHREADPARAM* piei = SHCreateIETHREADPARAM(NULL, nCmdShow, NULL, NULL);
if (piei)
{
//
// Create favorites dir (by hand if necessary).
//
InitFavoritesDir();
//
// If we are opening IE with no parameter, check if this is
// the very first open.
//
piei->pSplash = pSplash;
if (pszCmdLine && pszCmdLine[0])
{
USES_CONVERSION;
// we are passed the an ANSI cmd line from IExplore.exe
// this is lame on NT when we can have UNICODE file names.
// on win9x, of course, GetCommandLineW() will return NULL
// so we use the one passed to use from IExplore.exe
LPCWSTR pwszCmdLine;
if (IsOS(OS_NT))
pwszCmdLine = EatIExploreArgs(GetCommandLineW());
else
pwszCmdLine = A2W(pszCmdLine);
SHParseIECommandLine(&pwszCmdLine, piei);
// If the "-channelband" option is selected, turn it ON by default
#ifdef ENABLE_CHANNELS
if (piei->fDesktopChannel)
ChanBarSetAutoLaunchRegValue(TRUE);
#endif // ENABLE_CHANNELS
piei->pszCmdLine = StrDupW(pwszCmdLine);
}
else
{
piei->fCheckFirstOpen = TRUE;
}
#ifdef UNIX
if ( piei->fShouldStart && CheckAndDisplayEULA() )
{
#ifndef NO_SPLASHSCREEN
// IEUNIX - should show after parsing the commandline options.
if (!_IsDebuggerPresent())
{
if (SUCCEEDED(SHCreateSplashScreen(&pSplash)))
{
HWND hSplash;
pSplash->Show( HINST_THISDLL, -1, -1, &hSplash );
}
}
#endif
#endif
DoTimebomb(NULL);
piei->uFlags |= (COF_CREATENEWWINDOW | COF_NOFINDWINDOW | COF_INPROC | COF_IEXPLORE);
SHOpenFolderWindow(piei);
#ifdef UNIX
} // Start browser only if user accepts the license.
#endif
}
IERevokeClassFactoryObject();
CUrlHistory_CleanUp();
if (fWeOwnWinList)
WinList_Terminate();
CWinInetNotify::GlobalDisable();
InternetSetOption(NULL, INTERNET_OPTION_DIGEST_AUTH_UNLOAD, NULL, 0);
OleUninitialize();
}
ATOMICRELEASE(g_psfInternet);
#ifdef DEBUG
CoFreeUnusedLibraries();
#endif
TraceMsg(TF_SHDTHREAD, "IEWinMain about to call ExitProcess");
if (g_dwProfileCAP & 0x00020000)
StopCAP();
#ifdef UNIX
MwExecuteAtExit();
if (g_dwStopWatchMode)
StopWatchFlush();
#endif
ExitProcess(0);
return TRUE;
}