1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the NPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the NPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
38
/****************************************************************************
44
This little win32 application knows how to load the modules for
45
intalled version netscape and mozilla browsers. It preloads these
46
modules in order to make overall startup time seem faster to our
50
We assume that this preloader is stored with the mozilla/netscape
51
install somewhere, and that a link to that file is stored in either
52
the CURRENT_USER startup folder or the ALL_USERS startup folder.
53
If it's get's put somewhere else (like DEFAULT_USERS) then the
54
code we use to remove ourselves from the startup folder needs to
55
be adjusted accordingly.
59
==================================================================
60
rickg 03.15.01 Version 1.0 of the preloader; proof of concept.
62
rickg 04.16.01 changed code to use system-tray API's directly
63
rickg 04.17.01 added menu code to system tray to allow user to disable us
64
rickg 04.18.01 added code to auto-remove the preloader from startup folder
65
rickg 04.18.01 switched strings to resource files for easier localization.
66
rickg 04.23.01 added code to prevent multiple instances
67
rickg 04.23.01 added code to prevent preloader operation if browser is already running
68
rickg 04.23.01 added code to display unique icon (ugly yellow) if browser is already running.
69
rickg 04.23.01 added code to get/set "tuning" config settings from config dialog
70
rickg 04.24.01 added code to get/set "tuning" settings from registry
71
rickg 04.24.01 added accelerators to menu, and changed tooltip
72
rickg 04.24.01 moved more strings to resource file
73
rickg 04.24.01 hooked up "tuning" config settings for gModulePercent and gFrequencyPercent
74
rickg 04.27.01 hooked up "tuning" config settings for gEntryPercent
75
rickg 04.27.01 added a new config setting that specifies which browser instance to preload
77
****************************************************************************/
87
//trayicon notification message
88
#define WM_TRAY WM_USER+0x100+5
90
static NOTIFYICONDATA gTrayData = {0,0,0,0,0,0,0};
91
static HWND gMainWindow=0;
92
static HICON gCheckIcons[2] = {0,0};
93
static HICON gBrowserRunningIcon = {0};
95
static const int kLoadTimerID = 2;
96
static const int kPingModuleTimerID = 3;
98
static char gExePath[1024]={0}; //used to keep a path to our executable...
99
static const char* thePathSep="\\";
100
static const char* gBrowserWindowName=0;
101
static const char *gRegKey=0;
102
static const char *gRegSubKey=0;
104
static HINSTANCE gMainInst=0; //application main instance handle
105
static int gModulePercent = 100; //This tells us the percent of modules to load (default value)
106
static int gEntryPercent = 50; //Tells us the % of entry points per module (default value)
107
static int gFrequencyPercent = 50; //Tells us relative frequency to call entry points (default value)
109
/***********************************************************
110
call this to change the icon shown for our tray app
111
***********************************************************/
112
void SetTrayIcon(const HICON hIcon){
113
gTrayData.hIcon=hIcon;
114
Shell_NotifyIcon(NIM_MODIFY, &gTrayData);
117
/***********************************************************
118
call this to change the tooltip shown for our tray app
119
***********************************************************/
120
void SetTrayToolTip(const char *aTip){
122
if(!gTrayData.szTip[0]) //if previously no tooltip
123
gTrayData.uFlags=gTrayData.uFlags | NIF_TIP;
124
strcpy(gTrayData.szTip, aTip);
126
else gTrayData.uFlags=NIF_ICON | NIF_MESSAGE;
127
Shell_NotifyIcon(NIM_MODIFY, &gTrayData);
130
/***********************************************************
131
call this to init and display the tray app.
132
***********************************************************/
133
void ShowTrayApp(bool aVisible) {
136
gTrayData.cbSize=sizeof(NOTIFYICONDATA);
137
gTrayData.hWnd=gMainWindow;
138
gTrayData.uID=IDI_CHECK; //our tray ID
139
gTrayData.uFlags= NIF_ICON | NIF_MESSAGE | NIF_TIP;
140
gTrayData.uCallbackMessage=WM_TRAY; //send a WM_TRAY message when users clicks in our tray window
141
gTrayData.hIcon=gCheckIcons[0]; //init our default icon
143
Shell_NotifyIcon(NIM_ADD, &gTrayData); //now show our tray icon
146
if(LoadString(gMainInst,IDS_TOOLTIP,theTip,sizeof(theTip))){
147
SetTrayToolTip(theTip);
149
else SetTrayToolTip("Click to configure moz-preloader");
150
SetTrayIcon(gCheckIcons[0]);
153
Shell_NotifyIcon(NIM_DELETE, &gTrayData);
157
//********************************************************************
160
static bool gUseFullModuleList = false;
163
//this enum distinguishes version of netscape (and mozilla).
164
enum eAppVersion {eNetscape65, eNetscape60, eMozilla, eNetscapePre60, eUserPath,eUnknownVersion,eAutoDetect};
166
static eAppVersion gAppVersion=eNetscape65;
168
//Constants for my DLL loader to use...
169
static char gMozPath[2048]= {0};
170
static char gUserPath[2048]= {0};
171
static int gPreloadJava = 1;
173
static char gMozModuleList[4096] = {0};
174
static char* gModuleCP = gMozModuleList;
175
static int gModuleCount=0;
176
static int gMozPathLen=0;
177
static int gUserPathLen=0;
179
static const char *theMozPath=0;
180
static int gDLLIndex=0;
183
/*********************************************************
184
This counts the number of unique modules in the given
185
list of modules, by counting semicolons.
186
*********************************************************/
187
int CountModules(char*&aModuleList) {
188
char *cp=aModuleList;
196
char *theSemi=strchr(cp,';');
198
cp=theSemi+1; //skip the semi
205
/*********************************************************
206
This list describes the set of modules for NS6.0
207
XXX This data should really live in a string table too.
208
*********************************************************/
209
int Get60ModuleList(char*&aModuleList) {
211
static char* theModuleList =
213
"nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \
215
"gkgfxwin;gkwidget;" \
217
"components\\gkparser;" \
222
"components\\jsloader;" \
224
"components\\activation;" \
225
"components\\appcomps;" \
226
"components\\addrbook;" \
227
"components\\appshell;" \
228
"components\\caps;" \
229
"components\\chardet;" \
230
"components\\chrome;" \
231
"components\\cookie;" \
232
"components\\docshell;" \
233
"components\\editor;" \
234
"components\\gkhtml;" \
235
"components\\gkplugin;" \
236
"components\\gkview;" \
238
"components\\jar50;" \
239
"components\\lwbrk;" \
241
"components\\necko;" \
242
"components\\nsgif;" \
243
"components\\nslocale;" \
244
"components\\nsprefm;" \
245
"components\\profile;" \
246
"components\\psmglue;" \
248
"components\\shistory;" \
249
"components\\strres;" \
250
"components\\txmgr;" \
251
"components\\txtsvc;" \
252
"components\\ucharuti;" \
253
"components\\uconv;" \
254
"components\\ucvlatin;" \
255
"components\\ucvcn;" \
256
"components\\ucvja;" \
257
"components\\urildr;" \
258
"components\\wallet;" \
259
"components\\xpc3250;" \
260
"components\\xpinstal;" \
261
"components\\xppref32;" \
262
"components\\mozbrwsr;" \
263
"components\\nsjpg;" \
267
"components\\mork;" \
268
"components\\msglocal;" \
274
strcpy(aModuleList,theModuleList);
275
return CountModules(theModuleList);
278
/*********************************************************
279
This list describes the set of modules for NS6.5
280
XXX This data should really live in a string table too.
281
*********************************************************/
282
int Get65ModuleList(char *&aModuleList) {
283
static char* theModuleList =
285
"nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \
287
"gkgfxwin;gkwidget;" \
289
"components\\gkparser;" \
294
"components\\jsloader;" \
296
"components\\activation;" \
297
"components\\addrbook;" \
298
"components\\appcomps;" \
299
"components\\appshell;" \
300
"components\\embedcomponents;"
301
"components\\caps;" \
302
"components\\chardet;" \
303
"components\\chrome;" \
304
"components\\cookie;" \
305
"components\\docshell;" \
306
"components\\editor;" \
307
"components\\gkplugin;" \
308
"components\\gkview;" \
311
"components\\jar50;" \
312
"components\\lwbrk;" \
313
"components\\necko;" \
314
"components\\nsgif;" \
315
"components\\nslocale;" \
316
"components\\nsprefm;" \
317
"components\\profile;" \
318
"components\\psmglue;" \
320
"components\\shistory;" \
321
"components\\strres;" \
322
"components\\txmgr;" \
323
"components\\txtsvc;" \
324
"components\\ucharuti;" \
325
"components\\uconv;" \
326
"components\\ucvlatin;" \
327
"components\\ucvcn;" \
328
"components\\ucvja;" \
329
"components\\urildr;" \
330
"components\\wallet;" \
331
"components\\xpc3250;" \
332
"components\\xpinstal;" \
333
"components\\xppref32;" \
334
"components\\xmlextras;" \
336
"components\\gklayout;" \
337
"components\\gkcontent;" \
338
"components\\mozbrwsr;" \
339
"components\\nsjpg;" \
343
"components\\mork;" \
344
"components\\msglocal;" \
350
strcpy(aModuleList,theModuleList);
351
return CountModules(theModuleList);
355
/*********************************************************
357
*********************************************************/
358
static char gKeyBuffer[512]={0};
359
static char gSubKeyBuffer[128]={0};
360
static char gWinNameBuffer[128]={0}; //this is the expected browser name.
362
void GetPathFromRegistry(eAppVersion aVersion, const char *&aKey, const char *&aSubkey, char *&aModuleList, int &aSize) {
368
aKey=(LoadString(gMainInst,IDS_MOZ_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Mozilla.org\\Mozilla\\0.8 (en)\\Main";
370
aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory";
372
gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla";
374
aSize=Get65ModuleList(aModuleList);
380
aKey=(LoadString(gMainInst,IDS_NS65_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.5 (en)\\Main";
382
aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory";
384
gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
386
aSize=Get65ModuleList(aModuleList);
392
aKey=(LoadString(gMainInst,IDS_NS60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.0 (en)\\Main";
394
aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path";
396
gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
398
aSize=Get60ModuleList(aModuleList);
404
aKey=(LoadString(gMainInst,IDS_PRE60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\netscp6.exe";
406
aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path";
408
gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
410
aSize=Get60ModuleList(aModuleList);
417
strcpy(gMozPath,gUserPath);
419
aSize=Get65ModuleList(aModuleList);
421
gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla";
425
case eUnknownVersion:
430
/*********************************************************
431
Get the path to the netscape6 browser via the registry...
432
*********************************************************/
433
bool GetMozillaRegistryInfo(eAppVersion &aVersion) {
435
//first we try to get the registry info based on the command line settings.
436
//if that fails, we try others.
439
LONG theOpenResult = 1; //any non-zero will do to initialize this...
441
if ( aVersion == eUserPath) {
445
while((ERROR_SUCCESS!=theOpenResult) && (aVersion<eUnknownVersion)) {
447
GetPathFromRegistry(aVersion,gRegKey,gRegSubKey,gModuleCP,gModuleCount);
451
if((eUserPath!=aVersion) && (gRegKey)) {
452
theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
454
if(ERROR_SUCCESS==theOpenResult) {
457
theRegKey.QueryValue(gMozPath,gRegSubKey,&theSize);
459
if((ERROR_SUCCESS==theOpenResult) && (aVersion!=eUserPath)) {
462
char theCachedModuleList[1024] = {0};
464
theRegKey.QueryValue(theCachedModuleList,"Modules",&theSize);
466
if(theCachedModuleList[0]) {
467
strcpy(gMozModuleList,theCachedModuleList);
470
theRegKey.Create(HKEY_LOCAL_MACHINE,gRegKey);
471
theRegKey.SetValue( HKEY_LOCAL_MACHINE, gRegKey, gMozModuleList, "Modules");
479
aVersion=eAppVersion(int(aVersion)+1);
483
gMozPathLen=strlen(gMozPath);
484
gModuleCP = gMozModuleList;
490
/*********************************************************
491
Extract the "next" module name from our module name list.
492
XXX The module names should come from string resources.
493
*********************************************************/
494
void GetNextModuleName(char* aName) {
495
//scan ahead to find the next ';' or the end of the string...
501
char *theCP=gModuleCP;
510
if(theCP!=gModuleCP) {
511
size_t theSize=theCP-gModuleCP;
512
strncpy(aName,gModuleCP,theSize);
515
while(';'==*gModuleCP)
521
/****************************************************************
522
The following types are fraudulent. They're just here so
523
we can write up calls entry points in each module.
524
****************************************************************/
526
const int gMaxDLLCount=256;
527
const int gMaxProcCount=512;
528
static HINSTANCE gInstances[gMaxDLLCount];
529
static long* gFuncTable[gMaxDLLCount][gMaxProcCount];
530
static int gDLLCount=0;
531
static int gMaxEntryIndex=0;
534
/****************************************************************
535
This helper function is called by LoadModule. We separated this
536
stuff out so we can use the same code to load java modules
537
that aren't in the mozilla directory.
538
****************************************************************/
539
HINSTANCE LoadModuleFromPath(const char* aPath) {
541
HINSTANCE theInstance=gInstances[gDLLCount++]=LoadLibrary(aPath);
543
//we'll constrain the steprate to the range 1..20.
544
static double kPercent=(100-gEntryPercent)/100.0;
545
static const int kEntryStepRate=1+int(20*kPercent);
549
//let's get addresses throughout the module, skipping by the rate of kEntryStepRate.
550
for(int theEntryPoint=0;theEntryPoint<gMaxProcCount;theEntryPoint++){
551
long *entry=(long*)::GetProcAddress(theInstance,MAKEINTRESOURCE(1+(kEntryStepRate*theEntryPoint)));
553
gFuncTable[gDLLCount-1][theEntryCount++]=entry;
559
if(theEntryCount>gMaxEntryIndex)
560
gMaxEntryIndex=theEntryCount; //we track the highest index we find.
567
/****************************************************************
568
Call this once for each module you want to preload.
569
We use gEntryPercent to determine what percentage of entry
570
p oints to acquire (we will always get at least 1, and we'll
571
skip at most 20 entry points at a time).
572
****************************************************************/
573
HINSTANCE LoadModule(const char* aName) {
575
//we operate on gMozPath directly to avoid an unnecessary string copy.
576
//when we're done with this method, we reset gMozpath to it's original value for reuse.
578
strcat(gMozPath,aName);
579
strcat(gMozPath,".dll");
581
HINSTANCE theInstance = LoadModuleFromPath(gMozPath);
583
gMozPath[gMozPathLen]=0;
588
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam ) {
591
if(GetWindowText(hwnd,buf,sizeof(buf))){
592
if(strstr(buf,gBrowserWindowName)) {
593
return FALSE; //stop iterating now...
599
/****************************************************************
600
Call this to detect whether the browser is running.
601
We cache the result to speed up this function (by preventing
602
subsuquent searches of top level windows).
603
****************************************************************/
604
bool BrowserIsRunning() {
605
static bool gBrowserIsRunning=false;
607
if(!gBrowserIsRunning) {
608
if(!EnumWindows(EnumWindowsProc,0)) {
609
gBrowserIsRunning=true;
613
return gBrowserIsRunning;
616
/****************************************************************
617
This function get's called repeatedly to call on a timer,
618
and it calls GetProcAddr() to keep modules from paging.
620
NOTE: This method uses gFrequencyPercent to determine how much
621
work to do each time it gets called.
623
****************************************************************/
624
VOID CALLBACK KeepAliveTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ) {
626
//let's go see if mozilla is running.
627
//if so, then bail out without pinging modules...
629
if(BrowserIsRunning()) {
633
static bool theTimerIsRunning=false;
634
static int theCurrentModule=0;
635
static int theCurrentProc=0;
637
if(!theTimerIsRunning) { //ignore other timer calls till we're done.
638
theTimerIsRunning=true;
640
//constrain the step to 1..gDLLCount
641
static const double kPercent=gFrequencyPercent/100.0;
642
static const int kMaxSteps=1+int(3*gDLLCount*kPercent);
646
//this version iterates the entry points in each module before moving to the next module
648
while(count<kMaxSteps) {
650
volatile long *p=(long*)gFuncTable[theCurrentModule][theCurrentProc];
654
//don't actually invoke it, just cause it to load into memory...
655
//note that modules have different number of entry points.
656
//so not all modules have an entry point at theCurrentProc index.
664
if(theCurrentModule >= gDLLCount) {
665
theCurrentModule = 0;
666
theCurrentProc = (theCurrentProc>=gMaxEntryIndex) ? 0 : theCurrentProc+1;
672
#else //breadth first...
674
if(theCurrentProc >= gMaxEntryIndex) {
676
theCurrentModule = (theCurrentModule>=gDLLCount) ? 0 : theCurrentModule+1;
686
theTimerIsRunning=false;
691
/****************************************************************
692
This gets called repeatedly by a windows timer, and loads
693
the modules that it gets from the modulelist (see top of this file).
695
This routine has been updated to account for the gModulesPercent
696
setting (1-100). We'll load modules until we cross over this
698
****************************************************************/
699
VOID CALLBACK LoadModuleTimerProc(HWND hwnd, UINT uMsg, UINT idEvent,DWORD dwTime) {
701
static bool theTimerIsRunning=false;
702
static int gTrayIconIndex = 0;
704
if(!theTimerIsRunning) {
705
theTimerIsRunning=true;
707
//gDLLCount is the number of modules loaded so far
708
//gModuleCount is the total number of modules we know about
709
//gModulePercent is the total % of modules we're being asked to load (config setting)
711
double theMaxPercentToLoad=gModulePercent/100.0;
713
//we'll only load more modules if haven't loaded the max percentage of modules
714
//based on the configuration UI (stored in gModulePercent).
716
const int theModulePerCallCount = 3; // specifies how many modules to load per timer callback.
719
for(int theModuleIndex=0;theModuleIndex<theModulePerCallCount;theModuleIndex++) {
721
SetTrayIcon(gCheckIcons[gTrayIconIndex]);
723
gTrayIconIndex = (gTrayIconIndex==1) ? 0 : gTrayIconIndex+1; //this toggles the preloader icon to show activity...
725
char theDLLName[512];
726
GetNextModuleName(theDLLName);
729
if(gDLLCount/(gModuleCount*1.0)<=theMaxPercentToLoad) {
730
HINSTANCE theInstance=LoadModule(theDLLName);
738
//if they've asked us to preload java, then do so here...
741
char kJavaRegStr[512] = {0};
742
if(LoadString(gMainInst,IDS_JAVAREGSTR,kJavaRegStr,sizeof(kJavaRegStr))){
746
LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,kJavaRegStr,KEY_QUERY_VALUE);
747
if(ERROR_SUCCESS==theOpenResult) {
749
char kJavaRegPath[128] = {0};
750
if(LoadString(gMainInst,IDS_JAVAREGPATH,kJavaRegPath,sizeof(kJavaRegPath))){
752
char thePath[1024] = {0};
753
DWORD theSize=sizeof(thePath);
754
theRegKey.QueryValue(thePath,kJavaRegPath,&theSize);
757
//here we go; let's load java and awt...
758
char theTempPath[1024]={0};
760
sprintf(theTempPath,"%s\\hotspot\\jvm.dll",thePath);
761
LoadModuleFromPath(theTempPath);
763
sprintf(theTempPath,"%s\\verify.dll",thePath);
764
LoadModuleFromPath(theTempPath);
766
sprintf(theTempPath,"%s\\jpins32.dll",thePath);
767
LoadModuleFromPath(theTempPath);
769
sprintf(theTempPath,"%s\\jpishare.dll",thePath);
770
LoadModuleFromPath(theTempPath);
772
sprintf(theTempPath,"%s\\NPOJI600.dll",thePath);
773
LoadModuleFromPath(theTempPath);
775
sprintf(theTempPath,"%s\\java.dll",thePath);
776
LoadModuleFromPath(theTempPath);
778
sprintf(theTempPath,"%s\\awt.dll",thePath);
779
LoadModuleFromPath(theTempPath);
788
KillTimer(gMainWindow,kLoadTimerID);
789
SetTrayIcon(gCheckIcons[1]);
791
//now make a new timer that calls GetProcAddr()...
792
//we take gFrequencyPercent into account. We assume a timer range (min..max) of ~1second.
794
int theFreq=50+(100-gFrequencyPercent)*10;
796
UINT result=SetTimer(gMainWindow,kPingModuleTimerID,theFreq,KeepAliveTimerProc);
801
theTimerIsRunning=false;
805
/****************************************
806
we support the following args:
807
-f(+/-) : use FULL module list (not really supported yet)
808
-m : use mozilla installation
809
-n : use netscape installation (this is the default)
810
-p : use the given path (use this when you're running from a debug build rather than an installed version)
811
****************************************/
812
void ParseArgs(LPSTR &CmdLineArgs,eAppVersion &anAppVersion) {
814
const char* cp=CmdLineArgs;
818
if(('-'==theChar) || ('/'==theChar)){
819
//we found a valid command, go get it...
826
anAppVersion=eNetscape65;
831
anAppVersion=eMozilla;
838
gUseFullModuleList=true;
844
cp++; //skip over the command, then get the install path the user wants us to use.
845
anAppVersion=eUserPath;
846
while(*cp) { //skip whitespace...
852
gMozPathLen=gUserPathLen=0;
853
if('"'==*cp) { // Allow spaces in the path ie "C:\Program Files"
857
gUserPath[gUserPathLen++]=*cp;
865
gUserPath[gUserPathLen++]=*cp;
870
if(gUserPath[gUserPathLen-1]!= '\\') // make sure there's a \ on the end.
871
gUserPath[gUserPathLen++] = '\\';
872
gUserPath[gUserPathLen]=0;
884
/*********************************************************
885
This is the event loop controller for our diable
887
*********************************************************/
888
BOOL CALLBACK DisableDialogProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
896
//The rect code below is used to put our dialog right by the taskbar.
897
//It makes it's presence more obvious to the user.
899
HWND theTopWnd=GetDesktopWindow();
900
GetClientRect(theTopWnd,&cr1);
901
GetClientRect(hwnd,&cr2);
902
int w=cr2.right-cr2.left;
903
int h=cr2.bottom-cr2.top;
905
SetWindowPos(hwnd,HWND_TOP,cr1.right-(w+50),cr1.bottom-(h+70),0,0,SWP_NOSIZE);
910
switch(LOWORD(wParam)) {
928
/*********************************************************
929
This is the event loop controller for our performance
930
conifuration dialog box UI.
931
*********************************************************/
932
BOOL CALLBACK ConfigureDialogProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
942
//The rect code below is used to put our dialog right by the taskbar.
943
//It makes it's presence more obvious to the user.
945
HWND theTopWnd=GetDesktopWindow();
946
GetClientRect(theTopWnd,&cr1);
947
GetClientRect(hwnd,&cr2);
948
int w=cr2.right-cr2.left;
949
int h=cr2.bottom-cr2.top;
952
/*---------------------------------------------------------------
953
Add members to our list control...
954
---------------------------------------------------------------*/
956
HWND theListCtrl=GetDlgItem(hwnd,IDC_PRELOAD);
958
SendMessage(theListCtrl, CB_RESETCONTENT, 0, 0);
959
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Auto");
960
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Mozilla");
961
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Netscape-6.0");
962
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Netscape-6.5");
963
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Pre-Netscape-6.0");
964
SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"User-defined");
967
switch(gAppVersion) {
968
case eNetscape65: theSel=3; break;
969
case eNetscape60: theSel=2; break;
970
case eMozilla: theSel=1; break;
971
case eNetscapePre60: theSel=4; break;
972
case eUserPath: theSel=5; break;
977
SendMessage(theListCtrl, CB_SETCURSEL, (WPARAM)theSel, 0);
979
/*---------------------------------------------------------------
980
Set the text of our edit control...
981
---------------------------------------------------------------*/
983
HWND theEditCtrl=GetDlgItem(hwnd,IDC_EDIT1);
984
SendMessage(theEditCtrl, WM_CLEAR, 0, 0);
985
SendMessage(theEditCtrl, EM_REPLACESEL, 0, (LPARAM)gMozPath);
987
/*---------------------------------------------------------------
988
Set the state of our JAVA checkbox...
989
---------------------------------------------------------------*/
991
HWND theJavaCheckBox =GetDlgItem(hwnd,IDC_JAVA);
992
SendMessage(theJavaCheckBox, BM_SETCHECK, gPreloadJava, 0);
994
/*---------------------------------------------------------------
995
add code here to set the range of our sliders...
996
---------------------------------------------------------------*/
998
HWND theSlider=GetDlgItem(hwnd,IDC_MODULES);
999
gModulePercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gModulePercent);
1001
theSlider=GetDlgItem(hwnd,IDC_ENTRIES);
1002
gEntryPercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gEntryPercent);
1004
theSlider=GetDlgItem(hwnd,IDC_FREQUENCY);
1005
gFrequencyPercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gFrequencyPercent);
1007
SetWindowPos(hwnd,HWND_TOP,cr1.right-(w+50),cr1.bottom-(h+70),0,0,SWP_NOSIZE);
1012
switch(LOWORD(wParam)) {
1017
HWND theSlider=GetDlgItem(hwnd,IDC_MODULES);
1018
gModulePercent = SendMessage(theSlider, TBM_GETPOS, 0, 0);
1020
theSlider=GetDlgItem(hwnd,IDC_ENTRIES);
1021
gEntryPercent = SendMessage(theSlider, TBM_GETPOS, 0, 0);
1023
theSlider=GetDlgItem(hwnd,IDC_FREQUENCY);
1024
gFrequencyPercent = SendMessage(theSlider, TBM_GETPOS, 0, 0);
1026
theSlider=GetDlgItem(hwnd,IDC_JAVA);
1027
gPreloadJava = (int)SendMessage(theSlider, BM_GETCHECK, 0, 0);
1031
//and now, let's save the configuration settings...
1035
LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
1036
if(ERROR_SUCCESS!=theOpenResult) {
1037
theRegKey.Create(HKEY_LOCAL_MACHINE,gRegKey);
1040
char theSettings[128];
1041
sprintf(theSettings,"%i %i %i %i %s",gModulePercent,gEntryPercent,gFrequencyPercent,gPreloadJava,gUserPath);
1042
theRegKey.SetValue( HKEY_LOCAL_MACHINE, gRegKey, theSettings, "Settings");
1062
/*********************************************************
1063
The user asked us to disable the preloader. So we'll try
1064
to remove ourselves from both the current user start
1065
menu and ALL-USERS start menu.
1067
This ASSUMES that the installer put us into the startup
1068
folder using a shortcut to our current exe name.
1070
So, if the exe is called "preloader.exe", then we assume
1071
that the installer put us into the startup folder as:
1073
"shortcut to preloader.exe.lnk".
1074
*********************************************************/
1075
void RemoveFromStartupFolder() {
1077
//Using the name of our running application, let's derive the
1078
//name of the link to it in the startup folder.
1080
char theAppName[128]={0};
1081
char theFilename[128]={0};
1082
char theFullPath[1024]={0};
1084
const char *theLastSep=strrchr(gExePath,thePathSep[0]);
1087
theLastSep++; //skip the slash
1089
char prefix[512]={0};
1091
if(LoadString(gMainInst,IDS_STARTUP_FOLDER_PREFIX,prefix,sizeof(prefix))){
1093
char suffix[512]={0};
1095
if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUFFIX,suffix,sizeof(suffix))){
1096
strcpy(theFilename,prefix);
1097
strcat(theFilename,theLastSep);
1098
strcat(theFilename,suffix);
1104
if(theFilename) { //dont try if you can't get a reasonable guess to the path in the startup folder.
1106
//-----------------------------------------------------------------------------
1107
//first, let's try to remove ourselves from the current users's startup folder...
1108
//-----------------------------------------------------------------------------
1110
char theUserKey[256]={0};
1111
if(LoadString(gMainInst,IDS_STARTUP_FOLDER_KEY,theUserKey,sizeof(theUserKey))) {
1115
LONG theOpenResult=theRegKey.Open(HKEY_CURRENT_USER,theUserKey,KEY_QUERY_VALUE);
1117
if(ERROR_SUCCESS==theOpenResult) {
1119
DWORD theSize=sizeof(theFullPath);
1121
char theSubKey[128]={0};
1123
if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUBKEY1,theSubKey,sizeof(theSubKey))) {
1125
theRegKey.QueryValue(theFullPath,theSubKey,&theSize);
1128
//Now let's construct a complete path to our preloader.exe.lnk.
1130
strcat(theFullPath,thePathSep);
1131
strcat(theFullPath,theFilename);
1133
//Ask the OS to remove us from the startup folder...
1135
DeleteFile(theFullPath);
1141
//-----------------------------------------------------------------------------
1142
//Next, let's try to remove ourselves from ALL_USERS startup folder...
1143
//-----------------------------------------------------------------------------
1147
LONG theOpenResult=theRegKey2.Open(HKEY_LOCAL_MACHINE,theUserKey,KEY_QUERY_VALUE);
1149
if(ERROR_SUCCESS==theOpenResult) {
1151
DWORD theSize=sizeof(theFullPath);
1153
char theSubKey[128]={0};
1155
if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUBKEY2,theSubKey,sizeof(theSubKey))) {
1157
theRegKey2.QueryValue(theFullPath,theSubKey,&theSize);
1160
//Now let's construct a complete path to our preloader.exe.lnk.
1162
strcat(theFullPath,thePathSep);
1163
strcat(theFullPath,theFilename);
1165
//Ask the OS to remove us from the startup folder...
1167
DeleteFile(theFullPath);
1176
/*********************************************************
1178
*********************************************************/
1179
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
1181
static HMENU hPopup=0; //menu handle
1182
static int gState=0;
1183
static bool gConfigDialogShowing=false;
1190
gCheckIcons[0]=LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_CHECK));
1191
gCheckIcons[1]=LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_CHECK1));
1192
gBrowserRunningIcon = LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_BROWSERRUNNING));
1194
//initialize popup menu
1195
hPopup=LoadMenu(gMainInst, MAKEINTRESOURCE(IDR_MENU1));
1198
ShowTrayApp(true); //now display our app in the system tray
1202
//notification from trayicon received
1205
//if right mouse button pressed
1206
if(lParam == WM_RBUTTONDOWN && (!gConfigDialogShowing)) {
1208
GetCursorPos(&pt); //get cursor position
1209
SetForegroundWindow(hwnd); //set window to foreground
1210
//display popup menu
1211
BOOL bRes=TrackPopupMenu(GetSubMenu(hPopup, 0), TPM_BOTTOMALIGN | TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
1212
pt.x, pt.y, 0, hwnd, 0);
1213
//send dummy message to window
1214
SendMessage(hwnd, WM_NULL, 0, 0);
1218
//notification from menu received
1221
switch(LOWORD(wParam)) {
1225
if(!gConfigDialogShowing) {
1226
gConfigDialogShowing=true;
1227
if(DialogBox(gMainInst,MAKEINTRESOURCE(IDD_PERFORMANCE),hwnd,ConfigureDialogProc)) {
1229
gConfigDialogShowing=false;
1235
//show them the disable preloader dialog. If they say yes, remove ourselves from
1236
//the start menu (if that's where we were launched from) and quit.
1237
//now fall through on purpose...
1238
if(DialogBox(gMainInst,MAKEINTRESOURCE(DISABLE),hwnd,DisableDialogProc)) {
1239
//a non-zero result means we are supposed to kill the preloader
1240
//and remove it from the startup folder.
1242
RemoveFromStartupFolder();
1249
DestroyWindow(hwnd);
1252
//change icon in system tray; why bother?
1266
//release used resources
1270
DestroyIcon(gCheckIcons[0]);
1271
DestroyIcon(gCheckIcons[1]);
1273
DestroyMenu(hPopup);
1278
return DefWindowProc(hwnd, Msg, wParam, lParam);
1284
/*********************************************************
1286
*********************************************************/
1287
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgs,int nWinMode){
1289
memset(gFuncTable,0,sizeof(gFuncTable)); //init this to empty ptr's for good housekeeping...
1291
::CreateMutex(NULL, FALSE, "YourMutexName");
1292
if (GetLastError() == ERROR_ALREADY_EXISTS ) {
1293
//Bail out if we already have one instance running.
1299
static char theClassName[128];
1300
if(!LoadString(hInstance,IDS_CLASSNAME,theClassName,sizeof(theClassName)))
1301
strcpy(theClassName,"MozPreloader"); //as a backup; just being paranoid.
1303
//register window class
1304
WinClass.hInstance=hInstance;
1306
//---------------------------------------------------------------
1307
// We hang on to the app name in case they disable us.
1308
// We'll remove a .lnk entry of this name from the startup folder.
1309
//---------------------------------------------------------------
1311
GetModuleFileName(hInstance,gExePath,sizeof(gExePath)); //remember where we were run from in case we get disabled.
1314
//---------------------------------------------------------------
1315
// Now let's init and register our window class...
1316
//---------------------------------------------------------------
1318
gMainInst=hInstance;
1319
WinClass.lpszClassName=theClassName; //specify class name
1320
WinClass.lpfnWndProc=WindowFunc; //specify callback function
1322
WinClass.hIcon=LoadIcon(NULL, IDI_APPLICATION); //specify icon
1323
WinClass.hCursor=LoadCursor(NULL, IDC_ARROW); //specify cursor
1324
WinClass.lpszMenuName=0;
1325
WinClass.cbClsExtra=0;
1326
WinClass.cbWndExtra=0;
1327
WinClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //specify window background
1329
if(!RegisterClass(&WinClass))
1333
HWND hwnd=CreateWindow(theClassName,0,WS_OVERLAPPEDWINDOW,10,10,10,10,HWND_DESKTOP,NULL,hInstance,NULL);
1337
ShowWindow(hwnd, SW_HIDE);
1339
//---------------------------------------------------------------
1340
// Now let's grab the module settings info...
1341
//---------------------------------------------------------------
1343
bool useDebugModuleList=false;
1345
ParseArgs(lpszArgs,gAppVersion);
1347
if(GetMozillaRegistryInfo(gAppVersion)) {
1349
SetTrayIcon(gBrowserRunningIcon); //by default.
1351
//---------------------------------------------------------------
1352
// Now let's grab the config settings (if they happen to exist)
1353
//---------------------------------------------------------------
1357
LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
1358
if(ERROR_SUCCESS==theOpenResult) {
1360
const int theSize=1024;
1362
char theSettings[theSize] = {0};
1364
theOpenResult=theRegKey.QueryValue(theSettings,"Settings",&size);
1365
if(ERROR_SUCCESS==theOpenResult) {
1366
//now let's decode the settings from the string
1367
char *cp=theSettings;
1369
gModulePercent = atoi(cp);
1370
cp=strchr(cp,' '); //skip ahead to the next space...
1371
cp++; //and step over it
1373
gEntryPercent = atoi(cp);
1375
cp=strchr(cp,' '); //skip ahead to the next space...
1377
cp++; //and step over it
1378
gFrequencyPercent = atoi(cp);
1381
cp=strchr(cp,' '); //skip ahead to the next space...
1383
cp++; //and step over it
1384
gPreloadJava = atoi(cp);
1388
if(!gUserPath[0]) { //dont override something they provide at the
1390
cp=strchr(cp,'['); //seek to the separator for the pathname (optional)
1392
char *endcp=strchr(cp,']'); //now grab the (optional) user defined path...
1394
strcpy(gUserPath,cp);
1402
//---------------------------------------------------------------
1403
// And start the timer...
1404
//---------------------------------------------------------------
1406
if(!BrowserIsRunning()) {
1407
SetTimer(hwnd,kLoadTimerID,50,LoadModuleTimerProc); //don't bother with the preloader if the browser is already up...
1412
//start message pump
1414
while(GetMessage(&WinMsg, NULL, 0, 0)) {
1415
TranslateMessage(&WinMsg);
1416
DispatchMessage(&WinMsg);
1419
return WinMsg.wParam;