mirror of https://github.com/lianthony/NT4.0
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.
1065 lines
23 KiB
1065 lines
23 KiB
/*
|
|
Enhanced NCSA Mosaic from Spyglass
|
|
"Guitar"
|
|
|
|
Copyright 1994 Spyglass, Inc.
|
|
All Rights Reserved
|
|
|
|
Author(s):
|
|
Eric W. Sink [email protected]
|
|
Jim Seidman [email protected]
|
|
Jeff Hostetler [email protected]
|
|
*/
|
|
|
|
#if WINNT //GUID
|
|
#define INITGUID //NTHACK -sc
|
|
#include <objbase.h>
|
|
#include <isguids.h>
|
|
#endif
|
|
|
|
#include "all.h"
|
|
#ifdef FEATURE_IMAGE_VIEWER
|
|
#include "winview.h"
|
|
#endif
|
|
#ifdef FEATURE_IMG_THREADS
|
|
#include "safestrm.h"
|
|
#include "decoder.h"
|
|
#endif
|
|
#include "olestock.h"
|
|
#include "olepig.h"
|
|
#include "contmenu.h"
|
|
#include "dataobjm.h"
|
|
#include "history.h"
|
|
#include "mime.h"
|
|
#include "wc_html.h"
|
|
#include "w32cmd.h"
|
|
#ifdef FEATURE_IAPI
|
|
#include "w32dde.h"
|
|
#endif
|
|
|
|
#ifdef FEATURE_INTL // isspace doesn't work with non-ascii characters
|
|
#undef isspace
|
|
#define isspace(c) ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')||(c=='\v')|| \
|
|
(c=='\f'))
|
|
#endif
|
|
|
|
static TCHAR szRootDirectory[_MAX_PATH];
|
|
#ifdef FEATURE_SPYGLASS_INIFILE
|
|
TCHAR AppIniFile[_MAX_PATH]; /* pathname of our .INI file */
|
|
#endif // FEATURE_SPYGLASS_INIFILE
|
|
|
|
|
|
// KIOSK MODE
|
|
//
|
|
// The following flag is set if we were called with "-k" to go
|
|
// into "kiosk" mode which will turn off all menus, toolbars, and url bar
|
|
//
|
|
|
|
#ifdef FEATURE_BRANDING
|
|
BOOL bKioskMode = FALSE;
|
|
#endif // FEATURE_BRANDING
|
|
|
|
BOOL bNetwork;
|
|
BOOL bOpenURL;
|
|
|
|
BOOL bGrabImages;
|
|
|
|
#ifdef FEATURE_SPLASH_WINDOW
|
|
|
|
static BOOL bNoSplash;
|
|
|
|
static HWND hWndSplash;
|
|
|
|
static UINT splash_timer;
|
|
|
|
#endif /* FEATURE_SPLASH_WINDOW */
|
|
|
|
static char szInitialURL[MAX_URL_STRING + 1];
|
|
|
|
HWND hwndModeless = NULL; /* currently active modeless dialog to receive messages */
|
|
|
|
#ifdef DEBUG
|
|
|
|
#pragma data_seg(DATA_SEG_READ_ONLY)
|
|
|
|
/* .ini file name and section used by inifile.c!SetIniSwitches() */
|
|
|
|
PCSTR g_pcszIniFile = "ohare.ini";
|
|
PCSTR g_pcszIniSection = "InternetExplorerDebugOptions";
|
|
|
|
/* module name used by debspew.c!SpewOut() */
|
|
|
|
PCSTR g_pcszSpewModule = "IExplorer";
|
|
|
|
#pragma data_seg()
|
|
|
|
#endif
|
|
|
|
/* -------------------------------------------------------------------------------- */
|
|
|
|
#ifdef FEATURE_SPLASH_WINDOW
|
|
|
|
void HideSplash(void)
|
|
{
|
|
if (!bNoSplash)
|
|
{
|
|
if (hWndSplash)
|
|
{
|
|
DestroyWindow(hWndSplash);
|
|
Splash_UnregisterClass();
|
|
hWndSplash = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID CALLBACK x_timerproc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
|
|
{
|
|
KillTimer(hWndSplash, splash_timer);
|
|
HideSplash();
|
|
}
|
|
|
|
void ShowSplash(void)
|
|
{
|
|
if (!bNoSplash)
|
|
{
|
|
if (Splash_RegisterClass())
|
|
{
|
|
hWndSplash = Splash_CreateWindow();
|
|
if (hWndSplash)
|
|
{
|
|
InvalidateRect(hWndSplash, NULL, TRUE);
|
|
UpdateWindow(hWndSplash);
|
|
splash_timer = SetTimer(hWndSplash, 1, 3000, x_timerproc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* FEATURE_SPLASH_WINDOW */
|
|
|
|
|
|
static char *x_next_option(char *s)
|
|
{
|
|
char *p;
|
|
|
|
if (!s)
|
|
{
|
|
return NULL;
|
|
}
|
|
p = s;
|
|
if (!isspace(*p))
|
|
{
|
|
/* skip until next whitespace */
|
|
while (*p && !isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
if (!*p)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
/* skip whitespace */
|
|
while (*p && isspace(*p))
|
|
{
|
|
p++;
|
|
}
|
|
if (!*p)
|
|
{
|
|
return NULL;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static void ProcessCommandLine(char *szCmdLine)
|
|
{
|
|
char *p;
|
|
|
|
p = szCmdLine;
|
|
|
|
do
|
|
{
|
|
if (p)
|
|
{
|
|
if (0 == _strnicmp(p, "-local", 6))
|
|
bNetwork = FALSE;
|
|
else if (0 == _strnicmp(p, "-grab", 5))
|
|
bGrabImages = TRUE;
|
|
else if (0 == _strnicmp(p, "-nohome", 7))
|
|
bOpenURL = FALSE;
|
|
#ifdef FEATURE_BRANDING
|
|
else if (0 == _strnicmp(p, "-k", 2))
|
|
bKioskMode = TRUE;
|
|
#endif //FEATURE_BRANDING
|
|
#ifdef FEATURE_SPLASH_WINDOW
|
|
else if (0 == _strnicmp(p, "-nosplash", 9))
|
|
bNoSplash = TRUE;
|
|
#endif /* FEATURE_SPLASH_WINDOW */
|
|
else if (p[0] != '-')
|
|
{
|
|
char *q;
|
|
char *t;
|
|
|
|
q = p;
|
|
t = szInitialURL;
|
|
while (*q && !isspace(*q))
|
|
{
|
|
*t++ = *q++;
|
|
}
|
|
*t = 0;
|
|
}
|
|
}
|
|
p = x_next_option(p);
|
|
}
|
|
while (p);
|
|
}
|
|
|
|
static void PigMessage(void)
|
|
{
|
|
char szMsg[256];
|
|
struct Mwin *tw = TW_FindTopmostWindow();
|
|
|
|
GTR_formatmsg(ERR_SUWEEEE_MSG,szMsg,sizeof(szMsg));
|
|
MessageBox(tw ? tw->hWndFrame:NULL, szMsg, NULL, MB_ICONSTOP|MB_OK|MB_SETFOREGROUND);
|
|
}
|
|
|
|
|
|
#define MEM_NEEDED_WHEN_VM_NOT_CONFIGURED 2 * MINIMUM_FOOTPRINT
|
|
|
|
//
|
|
// Wrapper function for call to GlobalMemoryStatus
|
|
//
|
|
// On entry:
|
|
// pMS: pointer to MEMORYSTATUS
|
|
//
|
|
// On exit:
|
|
// *pMS: has been filled with the result of calling GlobalMemoryStatus()
|
|
// pMS->dwAvailPageFile: if virtual memory isn't configured, this may be cooked up.
|
|
//
|
|
// Note:
|
|
// The called of this function is actually only interested in the dwAvailPageFile info
|
|
// that is returned by GlobalMemoryStatus. If the user doesn't have virtual memory
|
|
// enabled, this would normally return dwAvailPageFile of zero. When this happens,
|
|
// this routine attempts a malloc to determine if there is some free memory. If it
|
|
// succeeds, it free's the block and returns the size of the block in the dwAvailpageFile
|
|
// member. All of this is to overcome the fact that Win32 doesn't allow us to determine
|
|
// the amount of physical memory available.
|
|
//
|
|
static void EnhancedGlobalMemoryStatus( MEMORYSTATUS *pMS )
|
|
{
|
|
static BOOL bFirstTime = TRUE;
|
|
static BOOL bVirtualMemoryEnabled = TRUE;
|
|
|
|
// Do the normal GlobalMemoryStatus call
|
|
GlobalMemoryStatus( pMS );
|
|
|
|
// First time through, if dwAvailPageFile is zero, we can safely assume we're really
|
|
// on a machine with virtual memory disabled.
|
|
if ( bFirstTime && (pMS->dwAvailPageFile == 0) )
|
|
bVirtualMemoryEnabled = FALSE;
|
|
|
|
bFirstTime = FALSE;
|
|
|
|
if ( (pMS->dwAvailPageFile == 0) && !bVirtualMemoryEnabled ) {
|
|
// First check for available physical memory
|
|
if ( pMS->dwAvailPhys < MEM_NEEDED_WHEN_VM_NOT_CONFIGURED ) {
|
|
char *p = malloc( MEM_NEEDED_WHEN_VM_NOT_CONFIGURED );
|
|
|
|
// Not enough available physical, so do a malloc as a last resort
|
|
|
|
// When virtual memory is disabled, rather than return zero in dwAvailPageFile,
|
|
// we try to malloc a big block. If it succeeds, we free the block and stuff
|
|
// the size of the block into the dwAvailPageFile. This will fake our caller
|
|
// out, fooling it into thinking there is memory available. Which there is, of course.
|
|
if ( p ) {
|
|
pMS->dwAvailPageFile = MEM_NEEDED_WHEN_VM_NOT_CONFIGURED;
|
|
free( p );
|
|
}
|
|
} else {
|
|
// If there's enough available physical, use that rather than returning
|
|
// zero in dwAvailPageFile
|
|
pMS->dwAvailPageFile = pMS->dwAvailPhys;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ApplicationMsgLoop() -- message loop for MDI windows.
|
|
This version does not (currently) handle:
|
|
(*) non-modal dialogs;
|
|
*/
|
|
|
|
static LRESULT ApplicationMsgLoop(VOID)
|
|
{
|
|
MSG msg;
|
|
BOOL bNotWarned = TRUE;
|
|
BOOL bNotReduced = TRUE;
|
|
BOOL bWarnNow;
|
|
DWORD dwLastWarning;
|
|
DWORD dwLastReduce;
|
|
DWORD dwCurTime;
|
|
MEMORYSTATUS memStatus;
|
|
memStatus.dwLength = sizeof(MEMORYSTATUS);
|
|
|
|
|
|
do
|
|
{
|
|
if (PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if (msg.message == WM_QUIT)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (!IsWindow(hwndModeless) || !IsDialogMessage(hwndModeless, &msg))
|
|
{
|
|
/* The message is intended for a window (document window) */
|
|
|
|
if (!TranslateAccelerator(msg.hwnd, wg.hAccelCurrent, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
else if (msg.message == WM_KEYDOWN)
|
|
{
|
|
/* If an image viewer window is active, then allow the keystrokes to fall through,
|
|
so that all arrow keys can be used to move the image around. For other dialogs,
|
|
sending the key down message has no adverse effect. Do NOT translate and dispatch
|
|
the message here - this will cause duplicate messages to be sent to listboxes. */
|
|
|
|
if (!TranslateAccelerator(hwndModeless, wg.hAccelCurrent, &msg))
|
|
{
|
|
switch(msg.wParam)
|
|
{
|
|
case VK_LEFT:
|
|
case VK_RIGHT:
|
|
case VK_UP:
|
|
case VK_DOWN:
|
|
SendMessage(hwndModeless, WM_KEYDOWN, msg.wParam, msg.lParam);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Since dialogs can have accelerators too, check to see if we can translate the
|
|
message for the currently active dialog. */
|
|
|
|
if (hwndModeless)
|
|
{
|
|
TranslateAccelerator(hwndModeless, wg.hAccelCurrent, &msg);
|
|
}
|
|
}
|
|
}
|
|
else if (!Async_KeepGoing())
|
|
{
|
|
/* There are no messages pending and no threads going (or all threads
|
|
are blocked). Be friendly and just go to sleep until we get
|
|
another message.
|
|
*/
|
|
WaitMessage();
|
|
}
|
|
dwCurTime = GetCurrentTime();
|
|
bWarnNow = !bReserveSpace();
|
|
if (bWarnNow && ((bNotReduced || (dwCurTime-dwLastReduce) > REDUCE_INTERVAL)))
|
|
{
|
|
Image_ReduceMemory(-1, /*fOKToDelW3Docs=*/TRUE);
|
|
dwLastReduce = dwCurTime;
|
|
bNotReduced = FALSE;
|
|
bWarnNow = !bReserveSpace();
|
|
}
|
|
if (bNotWarned || (dwCurTime-dwLastWarning) > WARN_INTERVAL)
|
|
{
|
|
EnhancedGlobalMemoryStatus(&memStatus);
|
|
if (memStatus.dwAvailPageFile < MINIMUM_DELTAPRINT)
|
|
{
|
|
if (dwLastReduce != dwCurTime)
|
|
{
|
|
Image_ReduceMemory(-1, /*fOKToDelW3Docs=*/TRUE);
|
|
EnhancedGlobalMemoryStatus(&memStatus);
|
|
}
|
|
}
|
|
bWarnNow = bWarnNow || (memStatus.dwAvailPageFile < MINIMUM_DELTAPRINT);
|
|
}
|
|
if (bWarnNow && ((bNotWarned || (dwCurTime-dwLastWarning) > WARN_INTERVAL)))
|
|
{
|
|
PigMessage();
|
|
dwLastWarning = GetCurrentTime();
|
|
bNotWarned = FALSE;
|
|
}
|
|
|
|
} while (1);
|
|
|
|
return ((LRESULT) msg.wParam);
|
|
}
|
|
|
|
void main_EnterIdle(HWND hWnd, WPARAM wParam)
|
|
{
|
|
MSG msg;
|
|
|
|
/* we are given the handle to the frame window or dialog which
|
|
* received a WM_ENTERIDLE message along with the
|
|
* WPARAM arg of that message.
|
|
*
|
|
* wParam has 2 possible values:
|
|
* MSGF_MENU -- a menu bar is active
|
|
* MSGF_DIALOGBOX -- a dialog box is active
|
|
*
|
|
* our purpose here is to allow 'background' threads to continue
|
|
* progress while the user has some ui feature active in the
|
|
* 'foreground' -- such as a menu or a dialog.
|
|
*
|
|
* We spin here until a message shows up or all of the threads
|
|
* are done/blocked. (At which point we really do want to idle
|
|
* until another message shows up.)
|
|
*/
|
|
|
|
/* Note that the async code is not re-entrant, therefore we
|
|
* do not allow any background processing when we are called
|
|
* in a thread context. an implication of this is that modal
|
|
* dialogs raised by thread code (such as password-like security
|
|
* dialogs) would block all network activity. to avoid this,
|
|
* thread code needing to raise a modal dialog are required to
|
|
* use the mdft.c facility.
|
|
*/
|
|
|
|
XX_Assert((Async_GetCurrentThread()==0),("main_EnterIdle: called from thread context."));
|
|
|
|
while ( !PeekMessage(&msg, (HWND) NULL, 0, 0, PM_NOREMOVE)
|
|
&& Async_KeepGoing())
|
|
{
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
static BOOL SetAllIniSwitches(void)
|
|
{
|
|
BOOL bResult;
|
|
|
|
bResult = SetDebugModuleIniSwitches();
|
|
bResult = SetMemoryManagerModuleIniSwitches() && bResult;
|
|
|
|
return(bResult);
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
/* InitApplication() -- Initialize all APPLICATION-specific
|
|
information. This includes:
|
|
|
|
(*) create all window classes that we require.
|
|
*/
|
|
|
|
static BOOL InitApplication(VOID)
|
|
{
|
|
return(
|
|
#ifdef DEBUG
|
|
InitDebugModule() &&
|
|
#endif
|
|
#ifdef OLDSTYLE_TOOLBAR_NOT_USED
|
|
BHBar_Constructor() &&
|
|
#endif
|
|
Frame_Constructor() &&
|
|
Frame_RegisterClass() &&
|
|
Hidden_RegisterClass() &&
|
|
GWC_BASE_RegisterClass() && /* must be before GWC_'s */
|
|
#ifdef OLDSTYLE_TOOLBAR_NOT_USED
|
|
GWC_GDOC_RegisterClass() &&
|
|
#ifdef FEATURE_TOOLBAR
|
|
GWC_MENU_RegisterClass() &&
|
|
#endif
|
|
TBar_RegisterClass() &&
|
|
BHBar_RegisterClass() &&
|
|
#endif // OLDSTYLE_TOOLBAR_NOT_USED
|
|
GDOC_RegisterClass() &&
|
|
#ifdef OLDSTYLE_TOOLBAR_NOT_USED
|
|
PUSHBTN_RegisterClass() &&
|
|
#endif // OLDSTYLE_TOOLBAR_NOT_USED
|
|
ANIMBTN_RegisterClass() &&
|
|
#ifdef FEATURE_IAPI
|
|
InitDDE() &&
|
|
#endif
|
|
#ifdef COOKIES
|
|
OpenTheCookieJar() &&
|
|
#endif
|
|
InitializeDiskCache());
|
|
}
|
|
|
|
/* InitInstance() -- Initialize all INSTANCE-specific information.
|
|
(The distinction between APPLICATION- and INSTANCE-specific info
|
|
is nearly moot under NT (because of process isolation), but is
|
|
very important under Win3.1. Win32s probably falls somewhere in
|
|
the middle. (sigh!) */
|
|
|
|
static BOOL InitInstance(void)
|
|
{
|
|
if (!Hidden_CreateWindow())
|
|
return FALSE;
|
|
#ifdef FEATURE_IMG_THREADS
|
|
if (cbDC_Init(gPrefs.cbMaxImgThreads,wg.hWndHidden) != errNoError)
|
|
return FALSE;
|
|
#endif
|
|
#ifdef FEATURE_NO_NETWORK
|
|
WinSock_InitDLL(FALSE);
|
|
#else
|
|
WinSock_InitDLL(bNetwork);
|
|
Net_Init();
|
|
#endif
|
|
|
|
Async_Init();
|
|
|
|
#ifdef FEATURE_OPTIONS_MENU
|
|
SessionHist_Init();
|
|
#endif
|
|
GHist_Init();
|
|
#ifdef OLD_HOTLIST
|
|
HotList_Init();
|
|
#endif
|
|
STY_Init();
|
|
|
|
TEMP_Init();
|
|
|
|
if (! InitMIMEModule())
|
|
return(FALSE);
|
|
|
|
QuerySystemMetrics();
|
|
EVAL(RegisterClipboardFormats());
|
|
EVAL(ProcessInitOLEPigModule());
|
|
|
|
GTR_CreatePalette();
|
|
|
|
if (LoadImagePlaceholders())
|
|
return FALSE;
|
|
|
|
#if 0
|
|
{
|
|
HDC hdc;
|
|
|
|
hdc = GetDC(wg.hWndFrame);
|
|
GTR_RealizePalette(hdc);
|
|
ReleaseDC(wg.hWndFrame, hdc);
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef OLD_HELP
|
|
static VOID QuitHelp(VOID)
|
|
{
|
|
/* Get rid of the help viewer, if created */
|
|
|
|
char szExt[_MAX_EXT + 1];
|
|
char szHelp[_MAX_PATH + 1];
|
|
char path[_MAX_PATH + 1];
|
|
|
|
if (gPrefs.szHelpFile[0])
|
|
{
|
|
_splitpath(gPrefs.szHelpFile, NULL, NULL, NULL, szExt);
|
|
PREF_GetHelpDirectory(path);
|
|
if (0 == _stricmp(szExt, ".hlp"))
|
|
{
|
|
sprintf(szHelp, "%s%s", path, gPrefs.szHelpFile);
|
|
WinHelp(wg.hWndHidden, szHelp, HELP_QUIT, 0);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID OpenHelpWindow(HWND hWnd)
|
|
{
|
|
char *ext;
|
|
char szHelp[_MAX_PATH];
|
|
char path[_MAX_PATH];
|
|
|
|
if (gPrefs.szHelpFile[0])
|
|
{
|
|
ext = strrchr(gPrefs.szHelpFile, '.');
|
|
PREF_GetHelpDirectory(path);
|
|
if (ext && 0 == _stricmp(ext, ".hlp"))
|
|
{
|
|
sprintf(szHelp, "%s%s", path, gPrefs.szHelpFile);
|
|
WinHelp(wg.hWndHidden, szHelp, HELP_FINDER, 0);
|
|
}
|
|
else
|
|
{
|
|
sprintf(szHelp, "%s%s", path, gPrefs.szHelpFile);
|
|
OpenLocalDocument(hWnd, szHelp);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif // OLD_HELP
|
|
|
|
static VOID DestroyApplication(VOID)
|
|
{
|
|
register PDS_DESTRUCTOR p;
|
|
register PDS_DESTRUCTOR q;
|
|
|
|
for (p = pdsFirst; p; p = q)
|
|
{
|
|
(*(p->fn)) ();
|
|
q = p->next;
|
|
GTR_FREE(p);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef REGISTRATION
|
|
static void RegisterUser(void)
|
|
{
|
|
char buf[256];
|
|
BOOL bAlready;
|
|
|
|
bAlready = FALSE;
|
|
|
|
GetPrivateProfileString("Registration", "UserName", "", buf, 255, AppIniFile);
|
|
if (buf[0])
|
|
{
|
|
bAlready = TRUE;
|
|
}
|
|
|
|
GetPrivateProfileString("Registration", "Org", "", buf, 255, AppIniFile);
|
|
if (buf[0])
|
|
{
|
|
bAlready = TRUE;
|
|
}
|
|
|
|
GetPrivateProfileString("Registration", "Serial", "", buf, 255, AppIniFile);
|
|
if (buf[0])
|
|
{
|
|
bAlready = TRUE;
|
|
}
|
|
|
|
if (!bAlready)
|
|
{
|
|
DlgLOGO_RunDialog(NULL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static BOOL bWallowTooSmall(void)
|
|
{
|
|
MEMORYSTATUS memStatus;
|
|
memStatus.dwLength = sizeof(MEMORYSTATUS);
|
|
|
|
EnhancedGlobalMemoryStatus(&memStatus);
|
|
|
|
|
|
if (memStatus.dwAvailPageFile < MINIMUM_FOOTPRINT)
|
|
{
|
|
PigMessage();
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#define DEFAULT_PIXELS_PER_INCH 72
|
|
|
|
static int GetScreenPixelsPerInch()
|
|
{
|
|
int n = DEFAULT_PIXELS_PER_INCH;
|
|
HWND hWnd = GetDesktopWindow();
|
|
|
|
if ( hWnd ) {
|
|
HDC hDC = GetDC( hWnd ); // Get a DC to the screen
|
|
if (hDC ) {
|
|
n = GetDeviceCaps(hDC, LOGPIXELSX); // Get horz. pixels per inch
|
|
if ( n <= 0 )
|
|
n = DEFAULT_PIXELS_PER_INCH; // Revert to default
|
|
}
|
|
ReleaseDC( hWnd, hDC );
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/* WinMain() -- THE MAIN PROGRAM. */
|
|
|
|
DCL_WinMain()
|
|
{
|
|
#ifdef DAYTONA_BUILD
|
|
OSVERSIONINFO verinfo;
|
|
CHAR pathbuf[MAX_PATH];
|
|
CHAR tmpbuf[MAX_PATH];
|
|
#endif
|
|
LRESULT result = FALSE;
|
|
DWORD len;
|
|
HANDLE hExecMutex = NULL;
|
|
HANDLE hDieMutex = NULL;
|
|
DWORD dwResult = 0;
|
|
#ifdef NT_WARNING
|
|
OSVERSIONINFO osver;
|
|
CHAR szNTnotSupported[128];
|
|
CHAR szTitle[100];
|
|
#endif NT_WARNING
|
|
|
|
ASSERT(SetAllIniSwitches());
|
|
|
|
XX_Assert((hInstance), ("WinMain: hInstance is NULL"));
|
|
|
|
|
|
#ifdef NT_WARNING
|
|
/*
|
|
* Warn user that we are not compatible with Windows NT
|
|
*/
|
|
szNTnotSupported[0] = szTitle[0] = 0;
|
|
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if (GetVersionEx( &osver ) && (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) {
|
|
LoadString(hInstance, RES_STRING_NT_NOT_SUPPORTED, szNTnotSupported, sizeof(szNTnotSupported));
|
|
LoadString(hInstance, RES_STRING_NT_DETECTED, szTitle, sizeof(szTitle));
|
|
MessageBox(0, szNTnotSupported, szTitle, MB_OK | MB_ICONWARNING );
|
|
}
|
|
#endif NT_WARNING
|
|
|
|
|
|
EVAL(InitMemoryManagerModule());
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
#ifdef XX_DEBUG
|
|
#if 1
|
|
XX_DebugSetMask(DBG_IMAGE|DBG_WWW|DBG_LOAD);
|
|
#endif
|
|
#if 0
|
|
XX_DebugSetMask(DBG_IMAGE);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
memset(&wg, 0, sizeof(wg));
|
|
pdsFirst = NULL;
|
|
wg.hInstance = hInstance;
|
|
wg.iScreenPixelsPerInch = GetScreenPixelsPerInch();
|
|
#ifdef XX_DEBUG
|
|
#if 0
|
|
{
|
|
MEMORYSTATUS memStatus;
|
|
memStatus.dwLength = sizeof(MEMORYSTATUS);
|
|
|
|
while (1)
|
|
{
|
|
GlobalMemoryStatus(&memStatus);
|
|
XX_DMsg(DBG_IMAGE, ("REAL,SWAP,VIRT AVAILABLE: %d,%d,%d\n", memStatus.dwAvailPhys, memStatus.dwAvailPageFile, memStatus.dwAvailVirtual));
|
|
Sleep(20000);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
hExecMutex = CreateMutex(NULL,FALSE,"IEXPLORE.XXXYYYZZZ");
|
|
hDieMutex = CreateMutex(NULL,FALSE,"IEXPLORE.PPPQQQRRR");
|
|
#ifdef DAYTONA_BUILD
|
|
|
|
/*
|
|
** Get NT Version number, Since we have not inited the ieshlib yet
|
|
** we cannot use OnNT351.
|
|
*/
|
|
memset(&verinfo, (int)NULL, sizeof(OSVERSIONINFO));
|
|
verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
if(GetVersionEx(&verinfo) != TRUE) {
|
|
ASSERT(0);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
** If OS reports 3 the create temp file of url...
|
|
*/
|
|
if(verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
|
|
verinfo.dwBuildNumber == 1057) {
|
|
FILE *fp;
|
|
|
|
ProcessCommandLine(lpszCmdLine);
|
|
if(*szInitialURL) {
|
|
GetEnvironmentVariable("TEMP", tmpbuf, MAX_PATH-1);
|
|
sprintf(pathbuf, "%s\\urltmp.tmp", tmpbuf);
|
|
if(!(fp = fopen(pathbuf, "w"))) {
|
|
ASSERT(0);
|
|
return FALSE;
|
|
}
|
|
fprintf(fp, "%s\n", szInitialURL);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
if (hExecMutex)
|
|
{
|
|
dwResult = WaitForSingleObject(hExecMutex,100);
|
|
if (dwResult == WAIT_TIMEOUT)
|
|
{
|
|
HWND hwnd;
|
|
char achClassName[32];
|
|
|
|
sprintf(achClassName, "%s_Hidden", vv_Application);
|
|
if (hwnd = FindWindow(achClassName,NULL))
|
|
{
|
|
SendMessage(hwnd,WM_QUERYOPEN,0,0);
|
|
}
|
|
goto exitPoint;
|
|
}
|
|
}
|
|
if (hDieMutex)
|
|
{
|
|
dwResult = WaitForSingleObject(hDieMutex,INFINITE);
|
|
}
|
|
if (bWallowTooSmall())
|
|
goto exitPoint;
|
|
|
|
wg.hAccelCurrent = LoadAccelerators(wg.hInstance, MAKEINTRESOURCE(RES_ACC_FRAME));
|
|
|
|
#ifdef FEATURE_CTL3D
|
|
Ctl3dRegister(wg.hInstance);
|
|
|
|
Ctl3dAutoSubclass(wg.hInstance);
|
|
#endif /* FEATURE_CTL3D */
|
|
|
|
// zero out our global for Error Cert storage
|
|
// this is used when we have a error due to parsing a SSL
|
|
// Certificate. When that happens we need to save off
|
|
// the cert in case we have another cert that is the same
|
|
// this prevents us from giving multiple errors on the
|
|
// same bad cert.
|
|
|
|
SSLGlobals.nLastCertOk = 0;
|
|
SSLGlobals.pLastCertOk = NULL;
|
|
SSLGlobals.dwCertGlobalSettings = 0;
|
|
|
|
|
|
Sem_InitSem(&gModalDialogSemaphore);
|
|
|
|
len = GetModuleFileName(wg.hInstance, szRootDirectory, _MAX_PATH);
|
|
WV_TruncateEntrynameFromPath(szRootDirectory);
|
|
(LPTSTR) wg.szRootDirectory = szRootDirectory;
|
|
XX_DMsg(DBG_PREF, ("%s started from: [%s]\n", vv_Application, wg.szRootDirectory));
|
|
|
|
#ifdef FEATURE_VENDOR_PREFERENCES
|
|
/*
|
|
We give the Vendor preferences code a chance to set things up BEFORE
|
|
we read the INI or other user stuff. If Vendor_SetPrefsDirectory() returns
|
|
FALSE, we just abort the program.
|
|
*/
|
|
if (!Vendor_SetPrefsDirectory())
|
|
goto exitPoint;
|
|
#endif /* FEATURE_VENDOR_PREFERENCES */
|
|
|
|
#ifdef FEATURE_SPYGLASS_INIFILE
|
|
|
|
AppIniFile[0] = 0;
|
|
PREF_GetPrefsDirectory(AppIniFile);
|
|
strcat(AppIniFile, vv_IniFileName);
|
|
strcat(AppIniFile, ".ini");
|
|
|
|
/*
|
|
If the INI file does not exist in the Prefs directory,
|
|
then look for one in the EXE directory, and copy it to the
|
|
Prefs directory.
|
|
*/
|
|
{
|
|
FILE *fp;
|
|
|
|
fp = fopen(AppIniFile, "r");
|
|
if (fp)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
else
|
|
{
|
|
char otherIniFile[_MAX_PATH + 1];
|
|
|
|
otherIniFile[0] = 0;
|
|
PREF_GetRootDirectory(otherIniFile);
|
|
strcat(otherIniFile, vv_IniFileName);
|
|
strcat(otherIniFile, ".ini");
|
|
|
|
CopyFile(otherIniFile, AppIniFile, TRUE); /* this will fail if there is no INI file in the EXE dir, but that's ok */
|
|
SetFileAttributes(AppIniFile, FILE_ATTRIBUTE_NORMAL);
|
|
}
|
|
}
|
|
|
|
XX_DMsg(DBG_PREF, ("%s using %s\n", vv_Application, AppIniFile));
|
|
#endif // FEATURE_SPYGLASS_INIFILE
|
|
|
|
wg.sm_cyborder = GetSystemMetrics(SM_CYBORDER);
|
|
|
|
wg.fWindowsNT = ((GetVersion() & 0x80000000) == 0);
|
|
wg.iWindowsMajorVersion = (LOBYTE(LOWORD(GetVersion())));
|
|
|
|
wg.lppdPrintDlg = (LPPRINTDLG) NULL;
|
|
|
|
/* we consider VGA (640x480) and SVGA (800x600) as lo res screens
|
|
and anything higher (such as SVGA aka XGA (1024x768) and 1280x1024
|
|
as hi res. */
|
|
|
|
wg.fLoResScreen = (GetSystemMetrics(SM_CXFULLSCREEN) < 801);
|
|
|
|
|
|
/* with Win32 and process isolation, hPrevInstance should never
|
|
be set. (i read this somewhere in the documentation, but
|
|
other documentation stills lists it as valid...) */
|
|
|
|
if (hPrevInstance)
|
|
ER_Message(NO_ERROR, ERR_CODING_ERROR, "hPrevInstance not NULL");
|
|
|
|
#ifdef REGISTRATION
|
|
RegisterUser();
|
|
#endif
|
|
|
|
bNetwork = TRUE;
|
|
bOpenURL = TRUE;
|
|
|
|
ProcessCommandLine(lpszCmdLine);
|
|
#ifdef DAYTONA_BUILD
|
|
if(InitStubs() != TRUE) {
|
|
// TODO -- PUT UP NICE MESSAGE BOX HERE
|
|
goto exitPoint;
|
|
}
|
|
|
|
#endif
|
|
InitPreferences();
|
|
LoadPreferences();
|
|
if (gPrefs.bCheck_Associations) {
|
|
DetectAndFixAssociations(hInstance);
|
|
if (! gPrefs.bCheck_Associations)
|
|
SavePreferences();
|
|
}
|
|
|
|
wg.bEditHandlerExists = IsEditHandlerRegistered();
|
|
|
|
(void)HTSPM_OS_PreloadAllSPM(NULL);
|
|
|
|
if (bOpenURL && !szInitialURL[0])
|
|
{
|
|
PREF_GetHomeSearchURL(szInitialURL, TRUE);
|
|
if ( szInitialURL[0] == 0 )
|
|
bOpenURL = FALSE;
|
|
}
|
|
|
|
#ifdef FEATURE_SPLASH_WINDOW
|
|
ShowSplash();
|
|
#endif /* FEATURE_SPLASH_WINDOW */
|
|
|
|
if (InitApplication() &&
|
|
InitInstance())
|
|
{
|
|
if (!WinSock_AllOK())
|
|
{
|
|
if (bNetwork)
|
|
{
|
|
ERR_ReportError(NULL, errNetStartFail, "", "");
|
|
}
|
|
}
|
|
|
|
if (GTR_NewWindow(szInitialURL, NULL, 0, 0,
|
|
(bOpenURL ? 0 : GTR_NW_FL_DO_NOT_OPEN_URL), NULL,
|
|
NULL) < 0)
|
|
{
|
|
/* TODO deal with error loading initial document */
|
|
}
|
|
|
|
#if defined(XX_DEBUG) && defined(GTR_MEM_STATS)
|
|
GTR_MemStats();
|
|
#endif
|
|
|
|
result = ApplicationMsgLoop();
|
|
if (hExecMutex) ReleaseMutex(hExecMutex);
|
|
}
|
|
|
|
GHist_SaveToDisk();
|
|
|
|
#ifdef FEATURE_IMAGE_VIEWER
|
|
#ifndef FEATURE_IMG_INLINE
|
|
Viewer_CleanUp();
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef FEATURE_SOUND_PLAYER
|
|
SoundPlayer_CleanUp();
|
|
#endif
|
|
|
|
#ifdef FEATURE_IAPI
|
|
TerminateDDE();
|
|
#endif
|
|
|
|
#ifdef DAYTONA_BUILD
|
|
TerminateStubs();
|
|
#endif
|
|
TerminateDiskCache();
|
|
CleanupHistoryHotlistMenus();
|
|
|
|
ExitMIMEModule();
|
|
ProcessExitOLEPigModule();
|
|
|
|
HTSPM_UnRegisterAllProtocols();
|
|
HTSPM_OS_UnloadAllSPM(NULL);
|
|
|
|
Image_DeleteAll();
|
|
#ifdef OLD_HOTLIST
|
|
HotList_Destroy();
|
|
#endif
|
|
GHist_Destroy();
|
|
#ifdef FEATURE_OPTIONS_MENU
|
|
SessionHist_Destroy();
|
|
#endif
|
|
STY_DeleteAll();
|
|
|
|
#ifdef FEATURE_NEW_PAGESETUPDLG
|
|
if ( wg.hDevMode )
|
|
GlobalFree(wg.hDevMode);
|
|
if ( wg.hDevNames )
|
|
GlobalFree(wg.hDevNames);
|
|
#endif
|
|
|
|
HTAtom_deleteAll();
|
|
HTDisposeConversions();
|
|
HTDisposeProtocols();
|
|
|
|
GTR_DestroyPalette();
|
|
|
|
TEMP_Cleanup();
|
|
|
|
DestroyImagePlaceholders();
|
|
#ifdef OLD_HELP
|
|
QuitHelp();
|
|
#endif // BUGBUG: probably should really do this, first we need a common string for the actual helpfile
|
|
DestroyPreferences();
|
|
|
|
WinSock_Cleanup();
|
|
|
|
#ifdef FEATURE_IMG_THREADS
|
|
DC_Deinit();
|
|
#endif
|
|
|
|
if ( SSLGlobals.pLastCertOk )
|
|
free(SSLGlobals.pLastCertOk);
|
|
|
|
|
|
Hidden_DestroyWindow();
|
|
|
|
DestroyApplication();
|
|
|
|
#ifdef COOKIES
|
|
WriteCookieJar();
|
|
#endif
|
|
|
|
|
|
#if defined(XX_DEBUG) && defined(GTR_MEM_STATS)
|
|
GTR_MemStats();
|
|
#endif
|
|
|
|
#ifdef FEATURE_CTL3D
|
|
Ctl3dUnregister(wg.hInstance);
|
|
#endif /* FEATURE_CTL3D */
|
|
|
|
TW_UnloadDynaLinkedDLLs();
|
|
|
|
exitPoint:
|
|
ExitMemoryManagerModule();
|
|
if (hExecMutex) CloseHandle(hExecMutex);
|
|
if (hDieMutex) CloseHandle(hDieMutex);
|
|
return (result);
|
|
}
|
|
|