Back to index

lightning-sunbird  0.9+nobinonly
preloader.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /****************************************************************************
00039 
00040   Module Notes:
00041   =============
00042 
00043   Overview:
00044     This little win32 application knows how to load the modules for
00045     intalled version netscape and mozilla browsers. It preloads these
00046     modules in order to make overall startup time seem faster to our
00047     end users. 
00048 
00049   Notes:
00050     We assume that this preloader is stored with the mozilla/netscape
00051     install somewhere, and that a link to that file is stored in either 
00052     the CURRENT_USER startup folder or the ALL_USERS startup folder. 
00053     If it's get's put somewhere else (like DEFAULT_USERS) then the 
00054     code we use to remove ourselves from the startup folder needs to 
00055     be adjusted accordingly.
00056 
00057 
00058   Who       When      What Changed
00059   ==================================================================
00060   rickg   03.15.01    Version 1.0 of the preloader; proof of concept. 
00061 
00062   rickg   04.16.01    changed code to use system-tray API's directly
00063   rickg   04.17.01    added menu code to system tray to allow user to disable us
00064   rickg   04.18.01    added code to auto-remove the preloader from startup folder
00065   rickg   04.18.01    switched strings to resource files for easier localization.
00066   rickg   04.23.01    added code to prevent multiple instances
00067   rickg   04.23.01    added code to prevent preloader operation if browser is already running
00068   rickg   04.23.01    added code to display unique icon (ugly yellow) if browser is already running.
00069   rickg   04.23.01    added code to get/set "tuning" config settings from config dialog 
00070   rickg   04.24.01    added code to get/set "tuning" settings from registry
00071   rickg   04.24.01    added accelerators to menu, and changed tooltip    
00072   rickg   04.24.01    moved more strings to resource file
00073   rickg   04.24.01    hooked up "tuning" config settings for gModulePercent and gFrequencyPercent
00074   rickg   04.27.01    hooked up "tuning" config settings for gEntryPercent
00075   rickg   04.27.01    added a new config setting that specifies which browser instance to preload
00076 
00077  ****************************************************************************/
00078 
00079 
00080 //additional includes
00081 #include "resrc1.h"
00082 #include <atlbase.h>
00083 #include <windows.h>
00084 #include <commctrl.h>
00085 #include <stdio.h>
00086 
00087 //trayicon notification message
00088 #define WM_TRAY   WM_USER+0x100+5
00089 
00090 static  NOTIFYICONDATA gTrayData = {0,0,0,0,0,0,0};
00091 static  HWND gMainWindow=0;
00092 static  HICON gCheckIcons[2] = {0,0};
00093 static  HICON gBrowserRunningIcon = {0};
00094 
00095 static  const int kLoadTimerID = 2;
00096 static  const int kPingModuleTimerID = 3;
00097 
00098 static  char  gExePath[1024]={0};   //used to keep a path to our executable...
00099 static  const char* thePathSep="\\";
00100 static  const char* gBrowserWindowName=0;
00101 static  const char *gRegKey=0;
00102 static  const char *gRegSubKey=0;
00103 
00104 static  HINSTANCE gMainInst=0;      //application main instance handle
00105 static  int gModulePercent = 100;   //This tells us the percent of modules to load (default value)
00106 static  int gEntryPercent  = 50;    //Tells us the % of entry points per module (default value)
00107 static  int gFrequencyPercent = 50; //Tells us relative frequency to call entry points (default value)
00108 
00109 /***********************************************************
00110   call this to change the icon shown for our tray app 
00111  ***********************************************************/
00112 void SetTrayIcon(const HICON hIcon){
00113   gTrayData.hIcon=hIcon;
00114   Shell_NotifyIcon(NIM_MODIFY, &gTrayData);
00115 }
00116 
00117 /***********************************************************
00118   call this to change the tooltip shown for our tray app
00119  ***********************************************************/
00120 void SetTrayToolTip(const char *aTip){
00121   if(aTip) {
00122     if(!gTrayData.szTip[0])  //if previously no tooltip
00123       gTrayData.uFlags=gTrayData.uFlags | NIF_TIP;
00124     strcpy(gTrayData.szTip, aTip);
00125   }
00126   else gTrayData.uFlags=NIF_ICON | NIF_MESSAGE;
00127   Shell_NotifyIcon(NIM_MODIFY, &gTrayData);
00128 }
00129 
00130 /***********************************************************
00131   call this to init and display the tray app.
00132  ***********************************************************/
00133 void ShowTrayApp(bool aVisible) {
00134 
00135   if(aVisible) {
00136     gTrayData.cbSize=sizeof(NOTIFYICONDATA);
00137     gTrayData.hWnd=gMainWindow;
00138     gTrayData.uID=IDI_CHECK;  //our tray ID
00139     gTrayData.uFlags= NIF_ICON | NIF_MESSAGE | NIF_TIP;
00140     gTrayData.uCallbackMessage=WM_TRAY; //send a WM_TRAY message when users clicks in our tray window
00141     gTrayData.hIcon=gCheckIcons[0]; //init our default icon
00142   
00143     Shell_NotifyIcon(NIM_ADD, &gTrayData); //now show our tray icon
00144 
00145     char theTip[256];
00146     if(LoadString(gMainInst,IDS_TOOLTIP,theTip,sizeof(theTip))){
00147       SetTrayToolTip(theTip);  
00148     }
00149     else SetTrayToolTip("Click to configure moz-preloader");
00150     SetTrayIcon(gCheckIcons[0]);
00151   }
00152   else {
00153     Shell_NotifyIcon(NIM_DELETE, &gTrayData);
00154   }
00155 }
00156 
00157 //********************************************************************
00158 
00159 
00160 static bool  gUseFullModuleList = false;
00161 
00162 
00163 //this enum distinguishes version of netscape (and mozilla).
00164 enum eAppVersion {eNetscape65, eNetscape60, eMozilla, eNetscapePre60, eUserPath,eUnknownVersion,eAutoDetect};
00165 
00166 static eAppVersion  gAppVersion=eNetscape65;
00167 
00168 //Constants for my DLL loader to use...
00169 static char gMozPath[2048]= {0};
00170 static char gUserPath[2048]= {0};
00171 static int  gPreloadJava = 1;
00172 
00173 static char gMozModuleList[4096] = {0};
00174 static char* gModuleCP = gMozModuleList;
00175 static int  gModuleCount=0;
00176 static int gMozPathLen=0;
00177 static int gUserPathLen=0;
00178 
00179 static const char *theMozPath=0;
00180 static int  gDLLIndex=0;
00181 
00182 
00183 /*********************************************************
00184   This counts the number of unique modules in the given
00185   list of modules, by counting semicolons.
00186  *********************************************************/
00187 int CountModules(char*&aModuleList) {
00188   char *cp=aModuleList;
00189   
00190   int count=0;
00191 
00192   while(*cp) {
00193     if(*cp) {
00194       count++;
00195     }
00196     char *theSemi=strchr(cp,';');
00197     if(theSemi) {
00198       cp=theSemi+1; //skip the semi
00199     }
00200   }
00201   return count;
00202 }
00203 
00204 
00205 /*********************************************************
00206   This list describes the set of modules for NS6.0
00207   XXX This data should really live in a string table too.
00208  *********************************************************/
00209 int Get60ModuleList(char*&aModuleList) {
00210   
00211   static char* theModuleList = 
00212 
00213     "nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \
00214 
00215     "gkgfxwin;gkwidget;" \
00216 
00217     "components\\gkparser;" \
00218     "jpeg3250;" \
00219     "js3250;" \
00220     "jsj3250;" \
00221     "jsdom;" \
00222     "components\\jsloader;" \
00223 
00224     "components\\activation;" \
00225     "components\\appcomps;" \
00226     "components\\addrbook;" \
00227     "components\\appshell;" \
00228     "components\\caps;" \
00229     "components\\chardet;" \
00230     "components\\chrome;" \
00231     "components\\cookie;" \
00232     "components\\docshell;" \
00233     "components\\editor;" \
00234     "components\\gkhtml;" \
00235     "components\\gkplugin;" \
00236     "components\\gkview;" \
00237     "gkwidget;" \
00238     "components\\jar50;" \
00239     "components\\lwbrk;" \
00240     "mozreg;" \
00241     "components\\necko;" \
00242     "components\\nsgif;" \
00243     "components\\nslocale;" \
00244     "components\\nsprefm;" \
00245     "components\\profile;" \
00246     "components\\psmglue;" \
00247     "components\\rdf;" \
00248     "components\\shistory;" \
00249     "components\\strres;" \
00250     "components\\txmgr;" \
00251     "components\\txtsvc;" \
00252     "components\\ucharuti;" \
00253     "components\\uconv;" \
00254     "components\\ucvlatin;" \
00255     "components\\ucvcn;" \
00256     "components\\ucvja;" \
00257     "components\\urildr;" \
00258     "components\\wallet;" \
00259     "components\\xpc3250;" \
00260     "components\\xpinstal;" \
00261     "components\\xppref32;" \
00262     "components\\mozbrwsr;" \
00263     "components\\nsjpg;" \
00264     "components\\oji;" \
00265 
00266     "msgbsutl;" \
00267     "components\\mork;" \
00268     "components\\msglocal;" \
00269 
00270     "xprt;" \
00271     "xptl;" \
00272     "xpcs;";
00273 
00274   strcpy(aModuleList,theModuleList);
00275   return CountModules(theModuleList);
00276 }
00277 
00278 /*********************************************************
00279   This list describes the set of modules for NS6.5
00280   XXX This data should really live in a string table too.
00281  *********************************************************/
00282 int Get65ModuleList(char *&aModuleList) {
00283   static char* theModuleList = 
00284 
00285   "nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \
00286 
00287   "gkgfxwin;gkwidget;" \
00288 
00289   "components\\gkparser;" \
00290   "jpeg3250;" \
00291   "js3250;" \
00292   "jsj3250;" \
00293   "jsdom;" \
00294   "components\\jsloader;" \
00295 
00296   "components\\activation;" \
00297   "components\\addrbook;" \
00298   "components\\appcomps;" \
00299   "components\\appshell;" \
00300   "components\\embedcomponents;"
00301   "components\\caps;" \
00302   "components\\chardet;" \
00303   "components\\chrome;" \
00304   "components\\cookie;" \
00305   "components\\docshell;" \
00306   "components\\editor;" \
00307   "components\\gkplugin;" \
00308   "components\\gkview;" \
00309   "gkwidget;" \
00310   "gfx2;" \
00311   "components\\jar50;" \
00312   "components\\lwbrk;" \
00313   "components\\necko;" \
00314   "components\\nsgif;" \
00315   "components\\nslocale;" \
00316   "components\\nsprefm;" \
00317   "components\\profile;" \
00318   "components\\psmglue;" \
00319   "components\\rdf;" \
00320   "components\\shistory;" \
00321   "components\\strres;" \
00322   "components\\txmgr;" \
00323   "components\\txtsvc;" \
00324   "components\\ucharuti;" \
00325   "components\\uconv;" \
00326   "components\\ucvlatin;" \
00327   "components\\ucvcn;" \
00328   "components\\ucvja;" \
00329   "components\\urildr;" \
00330   "components\\wallet;" \
00331   "components\\xpc3250;" \
00332   "components\\xpinstal;" \
00333   "components\\xppref32;" \
00334   "components\\xmlextras;" \
00335 
00336   "components\\gklayout;" \
00337   "components\\gkcontent;" \
00338   "components\\mozbrwsr;" \
00339   "components\\nsjpg;" \
00340   "components\\oji;" \
00341 
00342   "msgbsutl;" \
00343   "components\\mork;" \
00344   "components\\msglocal;" \
00345 
00346   "xprt;" \
00347   "xptl;" \
00348   "xpcs;";
00349 
00350   strcpy(aModuleList,theModuleList);
00351   return CountModules(theModuleList);
00352 }
00353 
00354 
00355 /*********************************************************
00356   ...
00357  *********************************************************/
00358 static char gKeyBuffer[512]={0};
00359 static char gSubKeyBuffer[128]={0};
00360 static char gWinNameBuffer[128]={0};     //this is the expected browser name.
00361 
00362 void GetPathFromRegistry(eAppVersion aVersion, const char *&aKey, const char *&aSubkey, char *&aModuleList, int &aSize) {
00363   
00364   switch(aVersion) { 
00365   
00366     case eMozilla:
00367 
00368       aKey=(LoadString(gMainInst,IDS_MOZ_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Mozilla.org\\Mozilla\\0.8 (en)\\Main"; 
00369 
00370       aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory";
00371 
00372       gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla";
00373 
00374       aSize=Get65ModuleList(aModuleList);
00375 
00376       break;
00377     
00378     case eNetscape65:
00379 
00380       aKey=(LoadString(gMainInst,IDS_NS65_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.5 (en)\\Main"; 
00381 
00382       aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory";
00383 
00384       gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
00385 
00386       aSize=Get65ModuleList(aModuleList);
00387 
00388       break;
00389     
00390     case eNetscape60:
00391 
00392       aKey=(LoadString(gMainInst,IDS_NS60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.0 (en)\\Main"; 
00393 
00394       aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path";
00395 
00396       gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
00397 
00398       aSize=Get60ModuleList(aModuleList);
00399 
00400       break;
00401 
00402     case eNetscapePre60:
00403 
00404       aKey=(LoadString(gMainInst,IDS_PRE60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\netscp6.exe"; 
00405 
00406       aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path";
00407 
00408       gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6";
00409 
00410       aSize=Get60ModuleList(aModuleList);
00411 
00412       break;
00413 
00414     case eUserPath:
00415       aKey  = 0;
00416       aSubkey= 0;
00417       strcpy(gMozPath,gUserPath);
00418 
00419       aSize=Get65ModuleList(aModuleList);
00420 
00421       gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla";
00422 
00423       break;
00424 
00425     case eUnknownVersion:
00426       break;
00427   }
00428 }
00429 
00430 /*********************************************************
00431   Get the path to the netscape6 browser via the registry...
00432  *********************************************************/
00433 bool GetMozillaRegistryInfo(eAppVersion &aVersion) {
00434 
00435   //first we try to get the registry info based on the command line settings.
00436   //if that fails, we try others.
00437 
00438   bool found=false;
00439   LONG theOpenResult = 1; //any non-zero will do to initialize this...
00440 
00441   if ( aVersion == eUserPath) {
00442     found=true;
00443   }  
00444 
00445   while((ERROR_SUCCESS!=theOpenResult) && (aVersion<eUnknownVersion)) {
00446      
00447     GetPathFromRegistry(aVersion,gRegKey,gRegSubKey,gModuleCP,gModuleCount);
00448 
00449     CRegKey theRegKey;
00450 
00451     if((eUserPath!=aVersion) && (gRegKey)) {
00452       theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
00453 
00454       if(ERROR_SUCCESS==theOpenResult) {
00455         DWORD theSize=1024;
00456 
00457         theRegKey.QueryValue(gMozPath,gRegSubKey,&theSize);
00458 
00459         if((ERROR_SUCCESS==theOpenResult) && (aVersion!=eUserPath)) {
00460 
00461           theSize=1024;
00462           char theCachedModuleList[1024] = {0};
00463 
00464           theRegKey.QueryValue(theCachedModuleList,"Modules",&theSize);
00465 
00466           if(theCachedModuleList[0]) {
00467             strcpy(gMozModuleList,theCachedModuleList);
00468           }
00469           else {
00470             theRegKey.Create(HKEY_LOCAL_MACHINE,gRegKey);
00471             theRegKey.SetValue( HKEY_LOCAL_MACHINE, gRegKey, gMozModuleList, "Modules");
00472           }
00473         }
00474 
00475         found=true;
00476         break;
00477       }
00478     }
00479     aVersion=eAppVersion(int(aVersion)+1);
00480     
00481   } //while
00482 
00483   gMozPathLen=strlen(gMozPath);
00484   gModuleCP = gMozModuleList;
00485 
00486   return found;
00487 }
00488 
00489 
00490 /*********************************************************
00491   Extract the "next" module name from our module name list.
00492   XXX The module names should come from string resources.
00493  *********************************************************/
00494 void GetNextModuleName(char* aName) {
00495   //scan ahead to find the next ';' or the end of the string...
00496   bool done=false;
00497   char theChar=0;
00498 
00499   aName[0]=0;
00500 
00501   char *theCP=gModuleCP;
00502 
00503   while(*theCP) {
00504     theChar=*theCP;
00505     if(';'==theChar)
00506       break;
00507     else theCP++;
00508   }
00509 
00510   if(theCP!=gModuleCP) {
00511     size_t theSize=theCP-gModuleCP;
00512     strncpy(aName,gModuleCP,theSize);
00513     aName[theSize]=0;
00514     gModuleCP=theCP;
00515     while(';'==*gModuleCP)
00516       gModuleCP++;
00517   }
00518 
00519 }
00520 
00521 /****************************************************************
00522   The following types are fraudulent. They're just here so 
00523   we can write up calls entry points in each module.
00524  ****************************************************************/
00525 
00526 const  int        gMaxDLLCount=256;
00527 const  int        gMaxProcCount=512;
00528 static HINSTANCE  gInstances[gMaxDLLCount];
00529 static long*      gFuncTable[gMaxDLLCount][gMaxProcCount];
00530 static int        gDLLCount=0;
00531 static int        gMaxEntryIndex=0;
00532 
00533 
00534 /****************************************************************
00535   This helper function is called by LoadModule. We separated this
00536   stuff out so we can use the same code to load java modules 
00537   that aren't in the mozilla directory. 
00538  ****************************************************************/
00539 HINSTANCE LoadModuleFromPath(const char* aPath) {
00540  
00541   HINSTANCE theInstance=gInstances[gDLLCount++]=LoadLibrary(aPath);
00542 
00543     //we'll constrain the steprate to the range 1..20.
00544   static double kPercent=(100-gEntryPercent)/100.0;
00545   static const int kEntryStepRate=1+int(20*kPercent);
00546   int theEntryCount=0;
00547 
00548   if(theInstance) {
00549     //let's get addresses throughout the module, skipping by the rate of kEntryStepRate.
00550     for(int theEntryPoint=0;theEntryPoint<gMaxProcCount;theEntryPoint++){
00551       long *entry=(long*)::GetProcAddress(theInstance,MAKEINTRESOURCE(1+(kEntryStepRate*theEntryPoint)));
00552       if(entry) {
00553         gFuncTable[gDLLCount-1][theEntryCount++]=entry;
00554       }
00555       else {
00556         break;
00557       }
00558     }
00559     if(theEntryCount>gMaxEntryIndex)
00560       gMaxEntryIndex=theEntryCount; //we track the highest index we find.
00561   }
00562 
00563   return theInstance;
00564 }
00565 
00566 
00567 /****************************************************************
00568   Call this once for each module you want to preload.
00569   We use gEntryPercent to determine what percentage of entry 
00570   p oints to acquire (we will always get at least 1, and we'll
00571   skip at most 20 entry points at a time).
00572  ****************************************************************/
00573 HINSTANCE LoadModule(const char* aName) {
00574 
00575   //we operate on gMozPath directly to avoid an unnecessary string copy.
00576   //when we're done with this method, we reset gMozpath to it's original value for reuse.
00577 
00578   strcat(gMozPath,aName);
00579   strcat(gMozPath,".dll");
00580 
00581   HINSTANCE theInstance = LoadModuleFromPath(gMozPath);
00582 
00583   gMozPath[gMozPathLen]=0;
00584   return theInstance;
00585 }
00586 
00587 
00588 BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam ) {
00589 
00590   char buf[256]={0};
00591   if(GetWindowText(hwnd,buf,sizeof(buf))){
00592     if(strstr(buf,gBrowserWindowName)) {
00593       return FALSE; //stop iterating now...
00594     }
00595   }
00596   return TRUE;
00597 }
00598 
00599 /****************************************************************
00600   Call this to detect whether the browser is running.
00601   We cache the result to speed up this function (by preventing
00602   subsuquent searches of top level windows).
00603  ****************************************************************/
00604 bool BrowserIsRunning() {
00605   static bool gBrowserIsRunning=false;
00606   
00607   if(!gBrowserIsRunning) {
00608     if(!EnumWindows(EnumWindowsProc,0)) {
00609       gBrowserIsRunning=true;
00610     }
00611   }
00612 
00613   return gBrowserIsRunning;
00614 }
00615 
00616 /****************************************************************
00617   This function get's called repeatedly to call on a timer,
00618   and it calls GetProcAddr() to keep modules from paging.
00619 
00620   NOTE: This method uses gFrequencyPercent to determine how much
00621   work to do each time it gets called.
00622 
00623  ****************************************************************/
00624 VOID CALLBACK KeepAliveTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime  ) {
00625 
00626   //let's go see if mozilla is running.
00627   //if so, then bail out without pinging modules...
00628   
00629   if(BrowserIsRunning()) {
00630     return;
00631   }
00632 
00633   static bool theTimerIsRunning=false;
00634   static int  theCurrentModule=0;
00635   static int  theCurrentProc=0;
00636 
00637   if(!theTimerIsRunning) { //ignore other timer calls till we're done.
00638     theTimerIsRunning=true;
00639 
00640       //constrain the step to 1..gDLLCount
00641     static const double kPercent=gFrequencyPercent/100.0;
00642     static const int kMaxSteps=1+int(3*gDLLCount*kPercent);
00643 
00644     int count=0;
00645 
00646     //this version iterates the entry points in each module before moving to the next module
00647 
00648     while(count<kMaxSteps) {
00649 
00650       volatile long *p=(long*)gFuncTable[theCurrentModule][theCurrentProc];
00651       count++;
00652       if (p) {
00653         if (*p && p){  
00654         //don't actually invoke it, just cause it to load into memory...
00655         //note that modules have different number of entry points.
00656         //so not all modules have an entry point at theCurrentProc index.
00657           int x=10;
00658         }
00659       }
00660 
00661 #define _DEPTH_FIRST
00662 #ifdef _DEPTH_FIRST
00663       
00664       if(theCurrentModule >= gDLLCount) {
00665         theCurrentModule = 0;
00666         theCurrentProc = (theCurrentProc>=gMaxEntryIndex) ? 0 : theCurrentProc+1;
00667       }
00668       else {
00669         theCurrentModule++;
00670       }
00671 
00672 #else //breadth first...
00673 
00674       if(theCurrentProc >= gMaxEntryIndex) {
00675         theCurrentProc=0;
00676         theCurrentModule = (theCurrentModule>=gDLLCount) ? 0 : theCurrentModule+1;
00677       }
00678       else {
00679         theCurrentProc++;
00680       }
00681 
00682 #endif
00683 
00684     }
00685 
00686     theTimerIsRunning=false;
00687   }
00688 }
00689 
00690 
00691 /****************************************************************
00692   This gets called repeatedly by a windows timer, and loads
00693   the modules that it gets from the modulelist (see top of this file).
00694 
00695   This routine has been updated to account for the gModulesPercent
00696   setting (1-100). We'll load modules until we cross over this 
00697   percentage.
00698  ****************************************************************/
00699 VOID CALLBACK LoadModuleTimerProc(HWND hwnd, UINT uMsg, UINT idEvent,DWORD dwTime) {
00700 
00701   static bool theTimerIsRunning=false;
00702   static int  gTrayIconIndex = 0;
00703 
00704   if(!theTimerIsRunning) {
00705     theTimerIsRunning=true;
00706 
00707       //gDLLCount is the number of modules loaded so far
00708       //gModuleCount is the total number of modules we know about
00709       //gModulePercent is the total % of modules we're being asked to load (config setting)
00710 
00711     double theMaxPercentToLoad=gModulePercent/100.0;
00712 
00713       //we'll only load more modules if haven't loaded the max percentage of modules
00714       //based on the configuration UI (stored in gModulePercent).
00715 
00716     const int theModulePerCallCount = 3; // specifies how many modules to load per timer callback.
00717     bool  done=false;
00718 
00719     for(int theModuleIndex=0;theModuleIndex<theModulePerCallCount;theModuleIndex++) {
00720 
00721       SetTrayIcon(gCheckIcons[gTrayIconIndex]);
00722 
00723       gTrayIconIndex = (gTrayIconIndex==1) ? 0 : gTrayIconIndex+1; //this toggles the preloader icon to show activity...
00724 
00725       char theDLLName[512];
00726       GetNextModuleName(theDLLName);
00727 
00728       if(theDLLName[0]) {
00729         if(gDLLCount/(gModuleCount*1.0)<=theMaxPercentToLoad) {
00730           HINSTANCE theInstance=LoadModule(theDLLName);
00731         }
00732         else done=true;
00733       }
00734       else done=true;
00735 
00736       if(done) {
00737 
00738           //if they've asked us to preload java, then do so here...
00739         if(gPreloadJava) {
00740 
00741           char kJavaRegStr[512] = {0};
00742           if(LoadString(gMainInst,IDS_JAVAREGSTR,kJavaRegStr,sizeof(kJavaRegStr))){
00743 
00744             CRegKey theRegKey;
00745 
00746             LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,kJavaRegStr,KEY_QUERY_VALUE);
00747             if(ERROR_SUCCESS==theOpenResult) {
00748 
00749               char kJavaRegPath[128] = {0};
00750               if(LoadString(gMainInst,IDS_JAVAREGPATH,kJavaRegPath,sizeof(kJavaRegPath))){
00751 
00752                 char thePath[1024] = {0};
00753                 DWORD theSize=sizeof(thePath);
00754                 theRegKey.QueryValue(thePath,kJavaRegPath,&theSize);
00755 
00756                 if(thePath) {
00757                   //here we go; let's load java and awt...
00758                   char theTempPath[1024]={0};
00759 
00760                   sprintf(theTempPath,"%s\\hotspot\\jvm.dll",thePath);
00761                   LoadModuleFromPath(theTempPath);
00762 
00763                   sprintf(theTempPath,"%s\\verify.dll",thePath);
00764                   LoadModuleFromPath(theTempPath);
00765 
00766                   sprintf(theTempPath,"%s\\jpins32.dll",thePath);
00767                   LoadModuleFromPath(theTempPath);
00768 
00769                   sprintf(theTempPath,"%s\\jpishare.dll",thePath);
00770                   LoadModuleFromPath(theTempPath);
00771 
00772                   sprintf(theTempPath,"%s\\NPOJI600.dll",thePath);
00773                   LoadModuleFromPath(theTempPath);
00774 
00775                   sprintf(theTempPath,"%s\\java.dll",thePath);
00776                   LoadModuleFromPath(theTempPath);
00777 
00778                   sprintf(theTempPath,"%s\\awt.dll",thePath);
00779                   LoadModuleFromPath(theTempPath);
00780 
00781                 }
00782               }
00783             }
00784           }
00785 
00786         }
00787 
00788         KillTimer(gMainWindow,kLoadTimerID);     
00789         SetTrayIcon(gCheckIcons[1]);
00790     
00791         //now make a new timer that calls GetProcAddr()...
00792         //we take gFrequencyPercent into account. We assume a timer range (min..max) of ~1second.
00793 
00794         int theFreq=50+(100-gFrequencyPercent)*10;
00795 
00796         UINT result=SetTimer(gMainWindow,kPingModuleTimerID,theFreq,KeepAliveTimerProc);
00797         return; //bail out    
00798       }
00799     }
00800 
00801     theTimerIsRunning=false;
00802   }
00803 }
00804  
00805 /****************************************
00806   we support the following args:
00807     -f(+/-) : use FULL module list (not really supported yet)
00808     -m : use mozilla installation
00809     -n : use netscape installation (this is the default)
00810     -p : use the given path (use this when you're running from a debug build rather than an installed version)
00811  ****************************************/
00812 void ParseArgs(LPSTR &CmdLineArgs,eAppVersion &anAppVersion) {
00813 
00814   const char* cp=CmdLineArgs;
00815   
00816   while(*cp) {
00817     char theChar=*cp;
00818     if(('-'==theChar) || ('/'==theChar)){
00819       //we found a valid command, go get it...
00820       ++cp;
00821       char theCmd=*cp;
00822 
00823       switch(theCmd) {
00824         case 'n':
00825         case 'N':
00826           anAppVersion=eNetscape65;
00827           break;
00828 
00829         case 'm':
00830         case 'M':
00831           anAppVersion=eMozilla;
00832           break;
00833 
00834         case 'f':
00835         case 'F':
00836           ++cp;          
00837           if('+'==*cp) {
00838             gUseFullModuleList=true;
00839           }
00840           break;
00841 
00842         case 'p':
00843         case 'P':
00844           cp++; //skip over the command, then get the install path the user wants us to use.
00845           anAppVersion=eUserPath;
00846           while(*cp) {              //skip whitespace...
00847             if(' '!=*cp)
00848               break;
00849             cp++;
00850           }
00851             //now eat the path
00852           gMozPathLen=gUserPathLen=0;
00853           if('"'==*cp) { // Allow spaces in the path ie "C:\Program Files"
00854             cp++; // skip the "
00855             while(*cp) {
00856               if('"'!=*cp) {
00857                 gUserPath[gUserPathLen++]=*cp;
00858               }
00859               cp++;
00860             }
00861           }
00862           else {
00863             while(*cp) {
00864               if(' '!=*cp) {
00865                 gUserPath[gUserPathLen++]=*cp;
00866               }
00867               cp++;
00868             }
00869           }
00870           if(gUserPath[gUserPathLen-1]!= '\\') // make sure there's a \ on the end. 
00871             gUserPath[gUserPathLen++] = '\\';
00872           gUserPath[gUserPathLen]=0;
00873           continue;
00874           break;
00875         default:
00876           break;
00877       }
00878     }
00879     cp++; 
00880   }
00881 
00882 }
00883 
00884 /*********************************************************
00885   This is the event loop controller for our diable 
00886   dialog box UI.
00887  *********************************************************/
00888 BOOL CALLBACK DisableDialogProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
00889 
00890   switch(Msg) {
00891 
00892     case WM_INITDIALOG:
00893       {
00894         RECT cr1,cr2;
00895 
00896           //The rect code below is used to put our dialog right by the taskbar.
00897           //It makes it's presence more obvious to the user.
00898 
00899         HWND theTopWnd=GetDesktopWindow();
00900         GetClientRect(theTopWnd,&cr1);
00901         GetClientRect(hwnd,&cr2);
00902         int w=cr2.right-cr2.left;
00903         int h=cr2.bottom-cr2.top;
00904 
00905         SetWindowPos(hwnd,HWND_TOP,cr1.right-(w+50),cr1.bottom-(h+70),0,0,SWP_NOSIZE);
00906         return TRUE;
00907       }
00908   
00909     case WM_COMMAND:
00910       switch(LOWORD(wParam)) {
00911         case IDOK:
00912           EndDialog(hwnd,1);
00913           break;
00914         case IDCANCEL:
00915           EndDialog(hwnd,0);
00916           return TRUE;
00917           break;
00918         default:
00919           break;
00920       }//switch
00921     default:
00922       break;
00923   }
00924   
00925   return FALSE;
00926 }
00927 
00928 /*********************************************************
00929   This is the event loop controller for our performance
00930   conifuration dialog box UI.
00931  *********************************************************/
00932 BOOL CALLBACK ConfigureDialogProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
00933 
00934   int x=0;
00935 
00936   switch(Msg) {
00937 
00938     case WM_INITDIALOG:
00939       {
00940         RECT cr1,cr2;
00941 
00942           //The rect code below is used to put our dialog right by the taskbar.
00943           //It makes it's presence more obvious to the user.
00944 
00945         HWND theTopWnd=GetDesktopWindow();
00946         GetClientRect(theTopWnd,&cr1);
00947         GetClientRect(hwnd,&cr2);
00948         int w=cr2.right-cr2.left;
00949         int h=cr2.bottom-cr2.top;
00950 
00951 
00952         /*---------------------------------------------------------------
00953           Add members to our list control...
00954          ---------------------------------------------------------------*/
00955 
00956         HWND theListCtrl=GetDlgItem(hwnd,IDC_PRELOAD);
00957 
00958         SendMessage(theListCtrl, CB_RESETCONTENT, 0, 0);
00959         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Auto"); 
00960         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Mozilla"); 
00961         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Netscape-6.0"); 
00962         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Netscape-6.5"); 
00963         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"Pre-Netscape-6.0"); 
00964         SendMessage(theListCtrl, CB_ADDSTRING, 0, (LPARAM)"User-defined"); 
00965         
00966         int theSel=0;
00967         switch(gAppVersion) {
00968           case eNetscape65: theSel=3; break;
00969           case eNetscape60: theSel=2; break;
00970           case eMozilla:    theSel=1; break;
00971           case eNetscapePre60:  theSel=4; break;
00972           case eUserPath:   theSel=5; break;
00973           default:
00974             break;
00975         }
00976         
00977         SendMessage(theListCtrl, CB_SETCURSEL, (WPARAM)theSel, 0);
00978 
00979         /*---------------------------------------------------------------
00980           Set the text of our edit control...
00981          ---------------------------------------------------------------*/
00982 
00983         HWND theEditCtrl=GetDlgItem(hwnd,IDC_EDIT1);
00984         SendMessage(theEditCtrl, WM_CLEAR, 0, 0); 
00985         SendMessage(theEditCtrl, EM_REPLACESEL, 0, (LPARAM)gMozPath); 
00986 
00987         /*---------------------------------------------------------------
00988           Set the state of our JAVA checkbox...
00989          ---------------------------------------------------------------*/
00990 
00991         HWND theJavaCheckBox =GetDlgItem(hwnd,IDC_JAVA);
00992         SendMessage(theJavaCheckBox, BM_SETCHECK, gPreloadJava, 0); 
00993 
00994         /*---------------------------------------------------------------
00995           add code here to set the range of our sliders...
00996          ---------------------------------------------------------------*/
00997 
00998         HWND theSlider=GetDlgItem(hwnd,IDC_MODULES);
00999         gModulePercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gModulePercent); 
01000 
01001         theSlider=GetDlgItem(hwnd,IDC_ENTRIES);
01002         gEntryPercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gEntryPercent); 
01003 
01004         theSlider=GetDlgItem(hwnd,IDC_FREQUENCY);
01005         gFrequencyPercent = SendMessage(theSlider, TBM_SETPOS, (BOOL)TRUE, (LONG)gFrequencyPercent); 
01006         
01007         SetWindowPos(hwnd,HWND_TOP,cr1.right-(w+50),cr1.bottom-(h+70),0,0,SWP_NOSIZE);
01008         return TRUE;
01009       }
01010 
01011     case WM_COMMAND:
01012       switch(LOWORD(wParam)) {
01013 
01014         case IDOK:
01015 
01016           {
01017             HWND theSlider=GetDlgItem(hwnd,IDC_MODULES);
01018             gModulePercent = SendMessage(theSlider, TBM_GETPOS, 0, 0); 
01019 
01020             theSlider=GetDlgItem(hwnd,IDC_ENTRIES);
01021             gEntryPercent = SendMessage(theSlider, TBM_GETPOS, 0, 0); 
01022 
01023             theSlider=GetDlgItem(hwnd,IDC_FREQUENCY);
01024             gFrequencyPercent = SendMessage(theSlider, TBM_GETPOS, 0, 0); 
01025 
01026             theSlider=GetDlgItem(hwnd,IDC_JAVA);
01027             gPreloadJava = (int)SendMessage(theSlider, BM_GETCHECK, 0, 0); 
01028 
01029             EndDialog(hwnd,1);
01030 
01031             //and now, let's save the configuration settings...
01032 
01033             CRegKey theRegKey;
01034 
01035             LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
01036             if(ERROR_SUCCESS!=theOpenResult) {
01037               theRegKey.Create(HKEY_LOCAL_MACHINE,gRegKey);
01038             }
01039 
01040             char theSettings[128];
01041             sprintf(theSettings,"%i %i %i %i %s",gModulePercent,gEntryPercent,gFrequencyPercent,gPreloadJava,gUserPath);
01042             theRegKey.SetValue( HKEY_LOCAL_MACHINE, gRegKey, theSettings, "Settings");
01043           }
01044           
01045           break;
01046 
01047         case IDCANCEL:
01048           EndDialog(hwnd,0);
01049           return TRUE;
01050           break;
01051 
01052         default:
01053           break;
01054       }//switch
01055     default:
01056       break;
01057   }
01058   
01059   return FALSE;
01060 }
01061 
01062 /*********************************************************
01063   The user asked us to disable the preloader. So we'll try
01064   to remove ourselves from both the current user start
01065   menu and ALL-USERS start menu.
01066 
01067   This ASSUMES that the installer put us into the startup
01068   folder using a shortcut to our current exe name.
01069 
01070   So, if the exe is called "preloader.exe", then we assume
01071   that the installer put us into the startup folder as:
01072 
01073   "shortcut to preloader.exe.lnk".
01074  *********************************************************/
01075 void RemoveFromStartupFolder() {
01076   
01077   //Using the name of our running application, let's derive the
01078   //name of the link to it in the startup folder.
01079 
01080   char theAppName[128]={0};
01081   char theFilename[128]={0};
01082   char theFullPath[1024]={0};
01083 
01084   const char *theLastSep=strrchr(gExePath,thePathSep[0]);
01085 
01086   if(theLastSep) {
01087     theLastSep++; //skip the slash
01088 
01089     char prefix[512]={0};
01090     
01091     if(LoadString(gMainInst,IDS_STARTUP_FOLDER_PREFIX,prefix,sizeof(prefix))){
01092       
01093       char suffix[512]={0};
01094     
01095       if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUFFIX,suffix,sizeof(suffix))){
01096         strcpy(theFilename,prefix);
01097         strcat(theFilename,theLastSep);
01098         strcat(theFilename,suffix);
01099       }
01100     
01101     }
01102   }
01103 
01104   if(theFilename) { //dont try if you can't get a reasonable guess to the path in the startup folder.
01105   
01106     //-----------------------------------------------------------------------------
01107     //first, let's try to remove ourselves from the current users's startup folder...
01108     //-----------------------------------------------------------------------------
01109 
01110     char theUserKey[256]={0};
01111     if(LoadString(gMainInst,IDS_STARTUP_FOLDER_KEY,theUserKey,sizeof(theUserKey))) {
01112 
01113       CRegKey theRegKey;
01114 
01115       LONG theOpenResult=theRegKey.Open(HKEY_CURRENT_USER,theUserKey,KEY_QUERY_VALUE);
01116 
01117       if(ERROR_SUCCESS==theOpenResult) {
01118     
01119         DWORD theSize=sizeof(theFullPath);
01120 
01121         char theSubKey[128]={0};
01122         
01123         if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUBKEY1,theSubKey,sizeof(theSubKey))) {
01124          
01125           theRegKey.QueryValue(theFullPath,theSubKey,&theSize);
01126           if(theFullPath) {
01127 
01128             //Now let's construct a complete path to our preloader.exe.lnk.
01129 
01130             strcat(theFullPath,thePathSep);
01131             strcat(theFullPath,theFilename);
01132 
01133             //Ask the OS to remove us from the startup folder...
01134 
01135             DeleteFile(theFullPath);
01136           }
01137         }
01138       }
01139     }
01140 
01141     //-----------------------------------------------------------------------------
01142     //Next, let's try to remove ourselves from ALL_USERS startup folder...
01143     //-----------------------------------------------------------------------------
01144 
01145     CRegKey theRegKey2;
01146 
01147     LONG theOpenResult=theRegKey2.Open(HKEY_LOCAL_MACHINE,theUserKey,KEY_QUERY_VALUE);
01148 
01149     if(ERROR_SUCCESS==theOpenResult) {
01150   
01151       DWORD theSize=sizeof(theFullPath);
01152 
01153       char theSubKey[128]={0};
01154       
01155       if(LoadString(gMainInst,IDS_STARTUP_FOLDER_SUBKEY2,theSubKey,sizeof(theSubKey))) {
01156        
01157         theRegKey2.QueryValue(theFullPath,theSubKey,&theSize);
01158         if(theFullPath) {
01159 
01160           //Now let's construct a complete path to our preloader.exe.lnk.
01161 
01162           strcat(theFullPath,thePathSep);
01163           strcat(theFullPath,theFilename);
01164 
01165           //Ask the OS to remove us from the startup folder...
01166 
01167           DeleteFile(theFullPath);
01168         }
01169       }
01170     }
01171 
01172   }
01173 }
01174 
01175 
01176 /*********************************************************
01177   
01178  *********************************************************/
01179 LRESULT CALLBACK WindowFunc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
01180 
01181   static HMENU hPopup=0;           //menu handle
01182   static int   gState=0;
01183   static bool  gConfigDialogShowing=false;
01184 
01185   switch(Msg) {
01186 
01187     case WM_CREATE: 
01188       //initialize icons
01189 
01190       gCheckIcons[0]=LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_CHECK));
01191       gCheckIcons[1]=LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_CHECK1));
01192       gBrowserRunningIcon = LoadIcon(gMainInst, MAKEINTRESOURCE(IDI_BROWSERRUNNING));
01193 
01194       //initialize popup menu
01195       hPopup=LoadMenu(gMainInst, MAKEINTRESOURCE(IDR_MENU1));
01196 
01197       gMainWindow=hwnd;
01198       ShowTrayApp(true); //now display our app in the system tray
01199 
01200       break;
01201 
01202     //notification from trayicon received
01203     case WM_TRAY:
01204 
01205       //if right mouse button pressed
01206       if(lParam == WM_RBUTTONDOWN && (!gConfigDialogShowing)) {
01207         POINT pt;
01208         GetCursorPos(&pt);  //get cursor position
01209         SetForegroundWindow(hwnd);  //set window to foreground
01210         //display popup menu
01211         BOOL bRes=TrackPopupMenu(GetSubMenu(hPopup, 0), TPM_BOTTOMALIGN | TPM_RIGHTALIGN | TPM_RIGHTBUTTON,
01212                                  pt.x, pt.y, 0, hwnd, 0);
01213         //send dummy message to window
01214         SendMessage(hwnd, WM_NULL, 0, 0);
01215       }
01216       break;
01217 
01218     //notification from menu received
01219     case WM_COMMAND:
01220 
01221       switch(LOWORD(wParam)) {
01222 
01223         case IDM_CONFIGURE:
01224           {
01225             if(!gConfigDialogShowing) {
01226               gConfigDialogShowing=true;
01227               if(DialogBox(gMainInst,MAKEINTRESOURCE(IDD_PERFORMANCE),hwnd,ConfigureDialogProc)) {
01228               }
01229               gConfigDialogShowing=false;
01230             }
01231           }
01232           break;
01233 
01234         case IDM_REMOVE:
01235           //show them the disable preloader dialog. If they say yes, remove ourselves from
01236           //the start menu (if that's where we were launched from) and quit.
01237           //now fall through on purpose...
01238           if(DialogBox(gMainInst,MAKEINTRESOURCE(DISABLE),hwnd,DisableDialogProc)) {
01239             //a non-zero result means we are supposed to kill the preloader 
01240             //and remove it from the startup folder.
01241 
01242             RemoveFromStartupFolder();
01243             //now fall thru...
01244 
01245           }
01246           else break;
01247                 
01248         case IDM_EXIT:
01249           DestroyWindow(hwnd);
01250           break;
01251 
01252         //change icon in system tray; why bother?
01253         case IDM_CHANGE:
01254           if(!gState) {
01255             gState=1;
01256           } 
01257           else {
01258             gState=0;
01259           }
01260           break;
01261       }
01262       break;
01263 
01264     //exit application
01265     case WM_DESTROY:
01266       //release used resources
01267 
01268       ShowTrayApp(false);
01269 
01270       DestroyIcon(gCheckIcons[0]);
01271       DestroyIcon(gCheckIcons[1]);
01272 
01273       DestroyMenu(hPopup);
01274       PostQuitMessage(0);
01275       break;
01276 
01277     default:
01278       return DefWindowProc(hwnd, Msg, wParam, lParam);
01279   }
01280   return 0;
01281 }
01282 
01283  
01284 /*********************************************************
01285   Main 
01286  *********************************************************/
01287 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgs,int nWinMode){
01288 
01289   memset(gFuncTable,0,sizeof(gFuncTable)); //init this to empty ptr's for good housekeeping...
01290    
01291   ::CreateMutex(NULL, FALSE, "YourMutexName");
01292   if (GetLastError()  == ERROR_ALREADY_EXISTS ) {
01293     //Bail out if we already have one instance running.
01294     exit(0);
01295   }
01296 
01297   WNDCLASS WinClass;
01298 
01299   static char theClassName[128];
01300   if(!LoadString(hInstance,IDS_CLASSNAME,theClassName,sizeof(theClassName)))
01301     strcpy(theClassName,"MozPreloader"); //as a backup; just being paranoid.
01302 
01303   //register window class
01304   WinClass.hInstance=hInstance;
01305 
01306   //---------------------------------------------------------------
01307   //  We hang on to the app name in case they disable us.
01308   //  We'll remove a .lnk entry of this name from the startup folder.
01309   //---------------------------------------------------------------
01310 
01311   GetModuleFileName(hInstance,gExePath,sizeof(gExePath)); //remember where we were run from in case we get disabled. 
01312 
01313 
01314   //---------------------------------------------------------------
01315   //  Now let's init and register our window class...
01316   //---------------------------------------------------------------
01317 
01318   gMainInst=hInstance;
01319   WinClass.lpszClassName=theClassName;  //specify class name
01320   WinClass.lpfnWndProc=WindowFunc;    //specify callback function
01321   WinClass.style=0;
01322   WinClass.hIcon=LoadIcon(NULL, IDI_APPLICATION); //specify icon
01323   WinClass.hCursor=LoadCursor(NULL, IDC_ARROW);   //specify cursor
01324   WinClass.lpszMenuName=0;
01325   WinClass.cbClsExtra=0;
01326   WinClass.cbWndExtra=0;
01327   WinClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //specify window background
01328 
01329   if(!RegisterClass(&WinClass))
01330     return 0;
01331 
01332   //create window
01333   HWND hwnd=CreateWindow(theClassName,0,WS_OVERLAPPEDWINDOW,10,10,10,10,HWND_DESKTOP,NULL,hInstance,NULL);
01334   gMainWindow=hwnd;
01335 
01336   //hide window
01337   ShowWindow(hwnd, SW_HIDE);
01338 
01339   //---------------------------------------------------------------
01340   //  Now let's grab the module settings info...
01341   //---------------------------------------------------------------
01342 
01343   bool useDebugModuleList=false;
01344   
01345   ParseArgs(lpszArgs,gAppVersion);
01346 
01347   if(GetMozillaRegistryInfo(gAppVersion)) {
01348 
01349     SetTrayIcon(gBrowserRunningIcon); //by default.
01350 
01351     //---------------------------------------------------------------
01352     //  Now let's grab the config settings (if they happen to exist)
01353     //---------------------------------------------------------------
01354 
01355     CRegKey theRegKey;
01356 
01357     LONG theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE);
01358     if(ERROR_SUCCESS==theOpenResult) {
01359 
01360       const int theSize=1024;
01361       DWORD size=theSize;
01362       char theSettings[theSize] = {0};
01363 
01364       theOpenResult=theRegKey.QueryValue(theSettings,"Settings",&size);
01365       if(ERROR_SUCCESS==theOpenResult) {
01366         //now let's decode the settings from the string
01367         char *cp=theSettings;
01368         
01369         gModulePercent = atoi(cp);
01370         cp=strchr(cp,' '); //skip ahead to the next space...
01371         cp++; //and step over it
01372 
01373         gEntryPercent = atoi(cp);
01374 
01375         cp=strchr(cp,' '); //skip ahead to the next space...
01376         if(cp) {
01377           cp++; //and step over it
01378           gFrequencyPercent = atoi(cp);
01379         }
01380 
01381         cp=strchr(cp,' '); //skip ahead to the next space...
01382         if(cp) {
01383           cp++; //and step over it
01384           gPreloadJava = atoi(cp);
01385         }
01386 
01387 
01388         if(!gUserPath[0]) { //dont override something they provide at the 
01389           if(cp){
01390             cp=strchr(cp,'['); //seek to the separator for the pathname (optional)
01391             if(cp && *cp) {
01392               char *endcp=strchr(cp,']'); //now grab the (optional) user defined path...
01393               if(endcp) {
01394                 strcpy(gUserPath,cp);
01395               }
01396             }
01397           }
01398         }
01399       }
01400     }
01401 
01402     //---------------------------------------------------------------
01403     //  And start the timer...
01404     //---------------------------------------------------------------
01405 
01406     if(!BrowserIsRunning()) {
01407       SetTimer(hwnd,kLoadTimerID,50,LoadModuleTimerProc); //don't bother with the preloader if the browser is already up...
01408     }
01409 
01410   }
01411 
01412   //start message pump
01413   MSG WinMsg;
01414   while(GetMessage(&WinMsg, NULL, 0, 0)) {
01415     TranslateMessage(&WinMsg);
01416     DispatchMessage(&WinMsg);
01417   }
01418 
01419   return WinMsg.wParam;
01420 }
01421