Back to index

lightning-sunbird  0.9+nobinonly
xpnetHook.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Navigator.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Sean Su <ssu@netscape.com>
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 #include <string.h>
00039 #include <time.h>
00040 #include <sys\stat.h>
00041 
00042 #ifdef __cplusplus
00043 extern "C"
00044 {
00045 #endif /* __cplusplus */
00046 
00047 #include "extern.h"
00048 #include "extra.h"
00049 #include "dialogs.h"
00050 #include "xpnetHook.h"
00051 
00052 #ifdef __cplusplus
00053 }
00054 #endif /* __cplusplus */
00055 
00056 #include "nsFTPConn.h"
00057 #include "nsHTTPConn.h"
00058 #include "nsSocket.h"
00059 
00060 #define UPDATE_INTERVAL_STATUS          1
00061 #define UPDATE_INTERVAL_PROGRESS_BAR    1
00062 
00063 /* Cancel Status */
00064 #define CS_NONE         0x00000000
00065 #define CS_CANCEL       0x00000001
00066 #define CS_PAUSE        0x00000002
00067 #define CS_RESUME       0x00000003
00068 
00069 const int  kProxySrvrLen = 1024;
00070 const char kHTTP[8]      = "http://";
00071 const char kFTP[7]       = "ftp://";
00072 const char kLoclFile[7]  = "zzzFTP";
00073 const int  kModTimeOutValue = 3;
00074 
00075 static nsHTTPConn       *connHTTP = NULL;
00076 static nsFTPConn        *connFTP = NULL;
00077 static long             glLastBytesSoFar;
00078 static long             glAbsoluteBytesSoFar;
00079 static long             glBytesResumedFrom;
00080 static long             glTotalKb;
00081 char                    gszStrCopyingFile[MAX_BUF_MEDIUM];
00082 char                    gszCurrentDownloadPath[MAX_BUF];
00083 char                    gszCurrentDownloadFilename[MAX_BUF_TINY];
00084 char                    gszCurrentDownloadFileDescription[MAX_BUF_TINY];
00085 char                    gszUrl[MAX_BUF];
00086 char                    gszTo[MAX_BUF];
00087 char                    gszFileInfo[MAX_BUF];
00088 char                    *gszConfigIniFile;
00089 BOOL                    gbDlgDownloadMinimized;
00090 BOOL                    gbDlgDownloadJustMinimized;
00091 BOOL                    gbUrlChanged;
00092 BOOL                    gbShowDownloadRetryMsg;
00093 DWORD                   gdwDownloadDialogStatus;
00094 int                     giIndex;
00095 int                     giTotalArchivesToDownload;
00096 DWORD                   gdwTickStart;
00097 BOOL                    gbStartTickCounter;
00098 
00099 double GetPercentSoFar(void);
00100 
00101 static void UpdateGaugeFileProgressBar(double value);
00102        int  ProgressCB(int aBytesSoFar, int aTotalFinalSize);
00103        void InitDownloadDlg(void);
00104 
00105 /* local prototypes */
00106 siC *GetObjectFromArchiveName(char *szArchiveName);
00107 
00108 struct DownloadFileInfo
00109 {
00110   char szUrl[MAX_BUF];
00111   char szFile[MAX_BUF_TINY];
00112 } dlFileInfo;
00113 
00114 struct ExtractFilesDlgInfo
00115 {
00116        HWND   hWndDlg;
00117        int           nMaxFileBars;     // maximum number of bars that can be displayed
00118        int           nMaxArchiveBars;     // maximum number of bars that can be displayed
00119        int   nFileBars;           // current number of bars to display
00120        int           nArchiveBars;          // current number of bars to display
00121 } dlgInfo;
00122 
00123 struct TickInfo
00124 {
00125   DWORD dwTickBegin;
00126   DWORD dwTickEnd;
00127   DWORD dwTickDif;
00128   BOOL  bTickStarted;
00129   BOOL  bTickDownloadResumed;
00130 } gtiPaused;
00131 
00132 BOOL CheckInterval(long *lModLastValue, int iInterval)
00133 {
00134   BOOL bRv = FALSE;
00135   long lModCurrentValue;
00136 
00137   if(iInterval == 1)
00138   {
00139     lModCurrentValue = (long)time(NULL);
00140     if(lModCurrentValue != *lModLastValue)
00141       bRv = TRUE;
00142   }
00143   else
00144   {
00145     lModCurrentValue = (long)time(NULL) % iInterval;
00146     if((lModCurrentValue == 0) && (*lModLastValue != 0))
00147       bRv = TRUE;
00148   }
00149 
00150   *lModLastValue = lModCurrentValue;
00151   return(bRv);
00152 }
00153 
00154 char *GetTimeLeft(DWORD dwTimeLeft,
00155                   char *szTimeString,
00156                   DWORD dwTimeStringBufSize)
00157 {
00158   DWORD      dwTimeLeftPP;
00159   ULONG hour, minute, second;
00160 
00161   dwTimeLeftPP         = dwTimeLeft + 1;
00162   hour         = (unsigned)(dwTimeLeftPP / 60 / 60);
00163   minute       = (unsigned)((dwTimeLeftPP / 60) % 60);
00164   second       = (unsigned)(dwTimeLeftPP % 60);
00165 
00166   memset(szTimeString, 0, dwTimeStringBufSize);
00167   sprintf(szTimeString, "%d:%d:%d", hour, minute, second);
00168   return(szTimeString);
00169 }
00170 
00171 DWORD AddToTick(DWORD dwTick, DWORD dwTickMoreToAdd)
00172 {
00173   DWORD dwTickLeftTillWrap = 0;
00174 
00175   /* Since WinGetCurrentTime() is the number of milliseconds since the system
00176    * has been on and the return value is a DWORD, this value will wrap
00177    * every 49.71 days or 0xFFFFFFFF milliseconds. */
00178   dwTickLeftTillWrap = 0xFFFFFFFF - dwTick;
00179   if(dwTickMoreToAdd > dwTickLeftTillWrap)
00180     dwTick = dwTickMoreToAdd - dwTickLeftTillWrap;
00181   else
00182     dwTick = dwTick + dwTickMoreToAdd;
00183 
00184   return(dwTick);
00185 }
00186 
00187 DWORD GetTickDif(DWORD dwTickEnd, DWORD dwTickStart)
00188 {
00189   DWORD dwTickDif;
00190 
00191   /* Since WinGetCurrentTime(NULLHANDLE) is the number of milliseconds since the system
00192    * has been on and the return value is a DWORD, this value will wrap
00193    * every 49.71 days or 0xFFFFFFFF milliseconds. 
00194    *
00195    * Assumption: dwTickEnd has not wrapped _and_ passed dwTickStart */
00196   if(dwTickEnd < dwTickStart)
00197     dwTickDif = 0xFFFFFFFF - dwTickStart + dwTickEnd;
00198   else
00199     dwTickDif = dwTickEnd - dwTickStart;
00200 
00201   return(dwTickDif);
00202 }
00203 
00204 void InitTickInfo(void)
00205 {
00206   gtiPaused.dwTickBegin          = 0;
00207   gtiPaused.dwTickEnd            = 0;
00208   gtiPaused.dwTickDif            = 0;
00209   gtiPaused.bTickStarted         = FALSE;
00210   gtiPaused.bTickDownloadResumed = FALSE;
00211 }
00212 
00213 DWORD RoundDouble(double dValue)
00214 {
00215   if(0.5 <= (dValue - (DWORD)dValue))
00216     return((DWORD)dValue + 1);
00217   else
00218     return((DWORD)dValue);
00219 }
00220 
00221 void SetStatusStatus(void)
00222 {
00223   char        szStatusStatusLine[MAX_BUF_MEDIUM];
00224   char        szCurrentStatusInfo[MAX_BUF_MEDIUM];
00225   char        szPercentString[MAX_BUF_MEDIUM];
00226   char        szPercentageCompleted[MAX_BUF_MEDIUM];
00227   static long lModLastValue = 0;
00228   double        dRate;
00229   static double dRateCounter;
00230   DWORD         dwTickNow;
00231   DWORD         dwTickDif;
00232   DWORD         dwKBytesSoFar;
00233   DWORD         dwRoundedRate;
00234   char          szTimeLeft[MAX_BUF_TINY];
00235 
00236   /* If the user just clicked on the Resume button, then the time lapsed
00237    * between gdwTickStart and when the Resume button was clicked needs to
00238    * be subtracted taken into account when calculating dwTickDif.  So
00239    * "this" lapsed time needs to be added to gdwTickStart. */
00240   if(gtiPaused.bTickDownloadResumed)
00241   {
00242     gdwTickStart = AddToTick(gdwTickStart, gtiPaused.dwTickDif);
00243     InitTickInfo();
00244   }
00245 
00246   /* WinGetCurrentTime(NULLHANDLE) returns time in milliseconds.  This is more accurate,
00247    * which will allow us to get at a 2 decimal precision value for the
00248    * download rate. */
00249   dwTickNow = WinGetCurrentTime(NULLHANDLE);
00250   if((gdwTickStart == 0) && gbStartTickCounter)
00251     dwTickNow = gdwTickStart = WinGetCurrentTime(NULLHANDLE);
00252 
00253   dwTickDif = GetTickDif(dwTickNow, gdwTickStart);
00254 
00255   /* Only update the UI every UPDATE_INTERVAL_STATUS interval,
00256    * which is currently set to 1 sec. */
00257   if(!CheckInterval(&lModLastValue, UPDATE_INTERVAL_STATUS))
00258     return;
00259 
00260   if(glAbsoluteBytesSoFar == 0)
00261     dRateCounter = 0.0;
00262   else
00263     dRateCounter = dwTickDif / 1000;
00264 
00265   if(dRateCounter == 0.0)
00266     dRate = 0.0;
00267   else
00268     dRate = (glAbsoluteBytesSoFar - glBytesResumedFrom) / dRateCounter / 1024;
00269 
00270   dwKBytesSoFar = glAbsoluteBytesSoFar / 1024;
00271 
00272   /* Use a rate that is rounded to the nearest integer.  If dRate used directly,
00273    * the "Time Left" will jump around quite a bit due to the rate usually 
00274    * varying up and down by quite a bit. The rounded rate give a "more linear"
00275    * count down of the "Time Left". */
00276   dwRoundedRate = RoundDouble(dRate);
00277   if(dwRoundedRate > 0)
00278     GetTimeLeft((glTotalKb - dwKBytesSoFar) / dwRoundedRate,
00279                  szTimeLeft,
00280                  sizeof(szTimeLeft));
00281   else
00282     strcpy(szTimeLeft, "00:00:00");
00283 
00284   if(!gbShowDownloadRetryMsg)
00285   {
00286     GetPrivateProfileString("Strings",
00287                             "Status Download",
00288                             "",
00289                             szStatusStatusLine,
00290                             sizeof(szStatusStatusLine),
00291                             szFileIniConfig);
00292     if(*szStatusStatusLine != '\0')
00293       sprintf(szCurrentStatusInfo,
00294               szStatusStatusLine,
00295               szTimeLeft,
00296               dRate,
00297               dwKBytesSoFar,
00298               glTotalKb);
00299     else
00300       sprintf(szCurrentStatusInfo,
00301               "%s at %.2fKB/sec (%uKB of %uKB downloaded)",
00302               szTimeLeft,
00303               dRate,
00304               dwKBytesSoFar,
00305               glTotalKb);
00306   }
00307   else
00308   {
00309     GetPrivateProfileString("Strings",
00310                             "Status Retry",
00311                             "",
00312                             szStatusStatusLine,
00313                             sizeof(szStatusStatusLine),
00314                             szFileIniConfig);
00315     if(*szStatusStatusLine != '\0')
00316       sprintf(szCurrentStatusInfo,
00317               szStatusStatusLine,
00318               szTimeLeft,
00319               dRate,
00320               dwKBytesSoFar,
00321               glTotalKb);
00322     else
00323       sprintf(szCurrentStatusInfo,
00324               "%s at %.2KB/sec (%uKB of %uKB downloaded)",
00325               szTimeLeft,
00326               dRate,
00327               dwKBytesSoFar,
00328               glTotalKb);
00329   }
00330 
00331   GetPrivateProfileString("Strings",
00332                           "Status Percentage Completed",
00333                           "",
00334                           szPercentageCompleted,
00335                           sizeof(szPercentageCompleted),
00336                           szFileIniConfig);
00337   sprintf(szPercentString, szPercentageCompleted, (int)GetPercentSoFar());
00338 
00339   /* Set the download dialog title */
00340   WinSetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS_STATUS, szCurrentStatusInfo);
00341   WinSetDlgItemText(dlgInfo.hWndDlg, IDC_PERCENTAGE, szPercentString);
00342 }
00343 
00344 void SetStatusFile(void)
00345 {
00346   char szString[MAX_BUF];
00347 
00348   /* Set the download dialog status*/
00349   sprintf(szString, gszFileInfo, gszCurrentDownloadFileDescription);
00350   WinSetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS_FILE, szString);
00351   SetStatusStatus();
00352 }
00353 
00354 void SetStatusUrl(void)
00355 {
00356   /* display the current url being processed */
00357   if(gbUrlChanged)
00358   {
00359     char szUrlPathBuf[MAX_BUF];
00360     char szToPathBuf[MAX_BUF];
00361     HWND hStatusUrl = NULL;
00362     HWND hStatusTo  = NULL;
00363 
00364     hStatusUrl = WinWindowFromID(dlgInfo.hWndDlg, IDC_STATUS_URL);
00365     if(hStatusUrl)
00366       TruncateString(hStatusUrl, gszUrl, szUrlPathBuf, sizeof(szUrlPathBuf));
00367     else
00368       strcpy(szUrlPathBuf, gszUrl);
00369 
00370     hStatusTo = WinWindowFromID(dlgInfo.hWndDlg, IDC_STATUS_TO);
00371     if(hStatusTo)
00372       TruncateString(hStatusTo, gszTo, szToPathBuf, sizeof(szToPathBuf));
00373     else
00374       strcpy(szToPathBuf, gszTo);
00375 
00376     WinSetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS_URL, szUrlPathBuf);
00377     WinSetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS_TO,  szToPathBuf);
00378     SetStatusFile();
00379     gbUrlChanged = FALSE;
00380   }
00381 }
00382 
00383 double GetPercentSoFar(void)
00384 {
00385   return((double)(((double)(glAbsoluteBytesSoFar / 1024) / (double)glTotalKb) * (double)100));
00386 }
00387 
00388 void SetMinimizedDownloadTitle(DWORD dwPercentSoFar)
00389 {
00390   static DWORD dwLastPercentSoFar = 0;
00391   char szDownloadTitle[MAX_BUF_MEDIUM];
00392   char gszCurrentDownloadInfo[MAX_BUF_MEDIUM];
00393 
00394   GetPrivateProfileString("Strings", "Dialog Download Title Minimized", "", szDownloadTitle, sizeof(szDownloadTitle), szFileIniConfig);
00395 
00396   if(*szDownloadTitle != '\0')
00397     sprintf(gszCurrentDownloadInfo, szDownloadTitle, dwPercentSoFar, gszCurrentDownloadFilename);
00398   else
00399     sprintf(gszCurrentDownloadInfo, "%d%% for all files", dwPercentSoFar);
00400 
00401   /* check and save the current percent so far to minimize flickering */
00402   if((dwLastPercentSoFar != dwPercentSoFar) || gbDlgDownloadJustMinimized)
00403   {
00404     /* When the dialog is has just been minimized, the title is not set
00405      * until the percentage changes, which when downloading via modem,
00406      * could take several seconds.  This variable allows us to tell when
00407      * the dialog had *just* been minimized regardless if the percentage
00408      * had changed or not. */
00409     gbDlgDownloadJustMinimized = FALSE;
00410 
00411     /* Set the download dialog title */
00412     WinSetWindowText(dlgInfo.hWndDlg, gszCurrentDownloadInfo);
00413     dwLastPercentSoFar = dwPercentSoFar;
00414   }
00415 }
00416 
00417 void SetRestoredDownloadTitle(void)
00418 {
00419   /* Set the download dialog title */
00420   WinSetWindowText(dlgInfo.hWndDlg, diDownload.szTitle);
00421 }
00422 
00423 void GetTotalArchivesToDownload(int *iTotalArchivesToDownload, DWORD *dwTotalEstDownloadSize)
00424 {
00425   int  iIndex = 0;
00426   char szUrl[MAX_BUF];
00427   char szSection[MAX_INI_SK];
00428   char szDownloadSize[MAX_ITOA];
00429 
00430   *dwTotalEstDownloadSize = 0;
00431   iIndex = 0;
00432   sprintf(szSection, "File%d", iIndex);
00433   GetPrivateProfileString(szSection,
00434                           "url0",
00435                           "",
00436                           szUrl,
00437                           sizeof(szUrl),
00438                           gszConfigIniFile);
00439   while(*szUrl != '\0')
00440   {
00441     GetPrivateProfileString(szSection, "size", "", szDownloadSize, sizeof(szDownloadSize), gszConfigIniFile);
00442     if((strlen(szDownloadSize) < 32) && (*szDownloadSize != '\0'))
00443       /* size will be in kb.  31 bits (int minus the signed bit) of precision should sufice */
00444       *dwTotalEstDownloadSize += atoi(szDownloadSize);
00445 
00446     ++iIndex;
00447     sprintf(szSection, "File%d", iIndex);
00448     GetPrivateProfileString(szSection,
00449                             "url0",
00450                             "",
00451                             szUrl,
00452                             sizeof(szUrl),
00453                             gszConfigIniFile);
00454   }
00455   *iTotalArchivesToDownload = iIndex;
00456 }
00457 
00458 /* 
00459  * Name: ProcessWndMsgCB
00460  *
00461  * Arguments: None
00462  *
00463  * Description: Callback function invoked by socket code and by FTP and HTTP layers
00464  *                          to give the UI a chance to breath while we are in a look processing
00465  *                          incoming data, or looping in select()
00466  *
00467  * Author: syd@netscape.com 5/11/2001
00468  *
00469 */
00470 
00471 int
00472 ProcessWndMsgCB()
00473 {
00474   int iRv = nsFTPConn::OK;
00475 
00476        ProcessWindowsMessages();
00477   if((gdwDownloadDialogStatus == CS_CANCEL) ||
00478      (gdwDownloadDialogStatus == CS_PAUSE))
00479     iRv = nsFTPConn::E_USER_CANCEL;
00480 
00481        return(iRv);
00482 }
00483 
00484 /* Function used only to send the message stream error */
00485 int WGet(char *szUrl,
00486          char *szFile,
00487          char *szProxyServer,
00488          char *szProxyPort,
00489          char *szProxyUser,
00490          char *szProxyPasswd)
00491 {
00492   int        rv;
00493   char       proxyURL[MAX_BUF];
00494   nsHTTPConn *conn = NULL;
00495 
00496   if((szProxyServer != NULL) && (szProxyPort != NULL) &&
00497      (*szProxyServer != '\0') && (*szProxyPort != '\0'))
00498   {
00499     /* detected proxy information, let's use it */
00500     memset(proxyURL, 0, sizeof(proxyURL));
00501     sprintf(proxyURL, "http://%s:%s", szProxyServer, szProxyPort);
00502 
00503     conn = new nsHTTPConn(proxyURL);
00504     if(conn == NULL)
00505       return(WIZ_OUT_OF_MEMORY);
00506 
00507     if((szProxyUser != NULL) && (*szProxyUser != '\0') &&
00508        (szProxyPasswd != NULL) && (*szProxyPasswd != '\0'))
00509       /* detected user and password info */
00510       conn->SetProxyInfo(szUrl, szProxyUser, szProxyPasswd);
00511     else
00512       conn->SetProxyInfo(szUrl, NULL, NULL);
00513   }
00514   else
00515   {
00516     /* no proxy information supplied. set up normal http object */
00517     conn = new nsHTTPConn(szUrl, ProcessWndMsgCB);
00518     if(conn == NULL)
00519       return(WIZ_OUT_OF_MEMORY);
00520   }
00521   
00522   rv = conn->Open();
00523   if(rv == WIZ_OK)
00524   {
00525     rv = conn->Get(NULL, szFile);
00526     conn->Close();
00527   }
00528 
00529   if(conn)
00530     delete(conn);
00531 
00532   return(rv);
00533 }
00534 
00535 int DownloadViaProxyOpen(char *szUrl, char *szProxyServer, char *szProxyPort, char *szProxyUser, char *szProxyPasswd)
00536 {
00537   int  rv;
00538   char proxyURL[kProxySrvrLen];
00539 
00540   if((!szUrl) || (*szUrl == '\0'))
00541     return nsHTTPConn::E_PARAM;
00542 
00543   rv = nsHTTPConn::OK;
00544   memset(proxyURL, 0, kProxySrvrLen);
00545   sprintf(proxyURL, "http://%s:%s", szProxyServer, szProxyPort);
00546 
00547   connHTTP = new nsHTTPConn(proxyURL, ProcessWndMsgCB);
00548   if(connHTTP == NULL)
00549   {
00550     char szBuf[MAX_BUF_TINY];
00551 
00552     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), szFileIniConfig);
00553     PrintError(szBuf, ERROR_CODE_HIDE);
00554 
00555     return(WIZ_OUT_OF_MEMORY);
00556   }
00557 
00558   if((szProxyUser != NULL) && (*szProxyUser != '\0') &&
00559      (szProxyPasswd != NULL) && (*szProxyPasswd != '\0'))
00560     connHTTP->SetProxyInfo(szUrl, szProxyUser, szProxyPasswd);
00561   else
00562     connHTTP->SetProxyInfo(szUrl, NULL, NULL);
00563 
00564   rv = connHTTP->Open();
00565   return(rv);
00566 }
00567 
00568 void DownloadViaProxyClose(void)
00569 {
00570   gbStartTickCounter = FALSE;
00571   if(connHTTP)
00572   {
00573     connHTTP->Close();
00574     delete(connHTTP);
00575     connHTTP = NULL;
00576   }
00577 }
00578 
00579 int DownloadViaProxy(char *szUrl, char *szProxyServer, char *szProxyPort, char *szProxyUser, char *szProxyPasswd)
00580 {
00581   int  rv;
00582   char *file = NULL;
00583 
00584   rv = nsHTTPConn::OK;
00585   if((!szUrl) || (*szUrl == '\0'))
00586     return nsHTTPConn::E_PARAM;
00587 
00588   if(connHTTP == NULL)
00589   {
00590     rv = DownloadViaProxyOpen(szUrl,
00591                               szProxyServer,
00592                               szProxyPort,
00593                               szProxyUser,
00594                               szProxyPasswd);
00595 
00596     if(rv != nsHTTPConn::OK)
00597     {
00598       DownloadViaProxyClose();
00599       return(rv);
00600     }
00601   }
00602 
00603   if(connHTTP == NULL)
00604   {
00605     char szBuf[MAX_BUF_TINY];
00606 
00607     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), szFileIniConfig);
00608     PrintError(szBuf, ERROR_CODE_HIDE);
00609 
00610     return(WIZ_OUT_OF_MEMORY);
00611   }
00612 
00613   if(strrchr(szUrl, '/') != (szUrl + strlen(szUrl)))
00614     file = strrchr(szUrl, '/') + 1; // set to leaf name
00615 
00616   gbStartTickCounter = TRUE;
00617   rv = connHTTP->Get(ProgressCB, file); // use leaf from URL
00618   DownloadViaProxyClose();
00619   return(rv);
00620 }
00621 
00622 int DownloadViaHTTPOpen(char *szUrl)
00623 {
00624   int  rv;
00625 
00626   if((!szUrl) || (*szUrl == '\0'))
00627     return nsHTTPConn::E_PARAM;
00628 
00629   rv = nsHTTPConn::OK;
00630   connHTTP = new nsHTTPConn(szUrl, ProcessWndMsgCB);
00631   if(connHTTP == NULL)
00632   {
00633     char szBuf[MAX_BUF_TINY];
00634 
00635     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), gszConfigIniFile);
00636     PrintError(szBuf, ERROR_CODE_HIDE);
00637 
00638     return(WIZ_OUT_OF_MEMORY);
00639   }
00640   
00641   rv = connHTTP->Open();
00642   return(rv);
00643 }
00644 
00645 void DownloadViaHTTPClose(void)
00646 {
00647   gbStartTickCounter = FALSE;
00648   if(connHTTP)
00649   {
00650     connHTTP->Close();
00651     delete(connHTTP);
00652     connHTTP = NULL;
00653   }
00654 }
00655 
00656 int DownloadViaHTTP(char *szUrl)
00657 {
00658   int  rv;
00659   char *file = NULL;
00660 
00661   if((!szUrl) || (*szUrl == '\0'))
00662     return nsHTTPConn::E_PARAM;
00663 
00664   if(connHTTP == NULL)
00665   {
00666     rv = DownloadViaHTTPOpen(szUrl);
00667     if(rv != nsHTTPConn::OK)
00668     {
00669       DownloadViaHTTPClose();
00670       return(rv);
00671     }
00672   }
00673 
00674   if(connHTTP == NULL)
00675   {
00676     char szBuf[MAX_BUF_TINY];
00677 
00678     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), gszConfigIniFile);
00679     PrintError(szBuf, ERROR_CODE_HIDE);
00680 
00681     return(WIZ_OUT_OF_MEMORY);
00682   }
00683   
00684   rv = nsHTTPConn::OK;
00685   if(strrchr(szUrl, '/') != (szUrl + strlen(szUrl)))
00686     file = strrchr(szUrl, '/') + 1; // set to leaf name
00687 
00688   gbStartTickCounter = TRUE;
00689   rv = connHTTP->Get(ProgressCB, file);
00690   DownloadViaHTTPClose();
00691   return(rv);
00692 }
00693 
00694 int DownloadViaFTPOpen(char *szUrl)
00695 {
00696   char *host = 0, *path = 0, *file = (char*) kLoclFile;
00697   int port = 21;
00698   int rv;
00699 
00700   if((!szUrl) || (*szUrl == '\0'))
00701     return nsFTPConn::E_PARAM;
00702 
00703   rv = nsHTTPConn::ParseURL(kFTP, szUrl, &host, &port, &path);
00704 
00705   connFTP = new nsFTPConn(host, ProcessWndMsgCB);
00706   if(connFTP == NULL)
00707   {
00708     char szBuf[MAX_BUF_TINY];
00709 
00710     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), szFileIniConfig);
00711     PrintError(szBuf, ERROR_CODE_HIDE);
00712 
00713     return(WIZ_OUT_OF_MEMORY);
00714   }
00715 
00716   rv = connFTP->Open();
00717   if(host)
00718     free(host);
00719   if(path)
00720     free(path);
00721 
00722   return(rv);
00723 }
00724 
00725 void DownloadViaFTPClose(void)
00726 {
00727   gbStartTickCounter = FALSE;
00728   if(connFTP)
00729   {
00730     connFTP->Close();
00731     delete(connFTP);
00732     connFTP = NULL;
00733   }
00734 }
00735 
00736 int DownloadViaFTP(char *szUrl)
00737 {
00738   char *host = 0, *path = 0, *file = (char*) kLoclFile;
00739   int port = 21;
00740   int rv;
00741 
00742   if((!szUrl) || (*szUrl == '\0'))
00743     return nsFTPConn::E_PARAM;
00744 
00745   if(connFTP == NULL)
00746   {
00747     rv = DownloadViaFTPOpen(szUrl);
00748     if(rv != nsFTPConn::OK)
00749     {
00750       DownloadViaFTPClose();
00751       return(rv);
00752     }
00753   }
00754 
00755   if(connFTP == NULL)
00756   {
00757     char szBuf[MAX_BUF_TINY];
00758 
00759     GetPrivateProfileString("Strings", "Error Out Of Memory", "", szBuf, sizeof(szBuf), szFileIniConfig);
00760     PrintError(szBuf, ERROR_CODE_HIDE);
00761 
00762     return(WIZ_OUT_OF_MEMORY);
00763   }
00764 
00765   rv = nsHTTPConn::ParseURL(kFTP, szUrl, &host, &port, &path);
00766 
00767   if(strrchr(path, '/') != (path + strlen(path)))
00768     file = strrchr(path, '/') + 1; // set to leaf name
00769 
00770   gbStartTickCounter = TRUE;
00771   rv = connFTP->Get(path, file, nsFTPConn::BINARY, TRUE, ProgressCB);
00772 
00773   if(host)
00774     free(host);
00775   if(path)
00776     free(path);
00777 
00778   return(rv);
00779 }
00780 
00781 void PauseTheDownload(int rv, int *iFileDownloadRetries)
00782 {
00783   if(rv != nsFTPConn::E_USER_CANCEL)
00784   {
00785     WinSendMsg(dlgInfo.hWndDlg, WM_COMMAND, (MPARAM)IDPAUSE, 0);
00786     --*iFileDownloadRetries;
00787   }
00788 
00789   while(gdwDownloadDialogStatus == CS_PAUSE)
00790   {
00791     DosSleep(0);
00792     ProcessWindowsMessages();
00793   }
00794 }
00795 
00796 void CloseSocket(char *szProxyServer, char *szProxyPort)
00797 {
00798   /* Close the socket connection from the first attempt. */
00799   if((szProxyServer != NULL) && (szProxyPort != NULL) &&
00800      (*szProxyServer != '\0') && (*szProxyPort != '\0'))
00801       DownloadViaProxyClose();
00802   else
00803   {
00804     /* is this an HTTP URL? */
00805     if(strncmp(gszUrl, kHTTP, strlen(kHTTP)) == 0)
00806       DownloadViaHTTPClose();
00807     /* or is this an FTP URL? */
00808     else if(strncmp(gszUrl, kFTP, strlen(kFTP)) == 0)
00809       DownloadViaFTPClose();
00810   }
00811 }
00812 
00813 siC *GetObjectFromArchiveName(char *szArchiveName)
00814 {
00815   DWORD dwIndex;
00816   siC   *siCObject = NULL;
00817   siC   *siCNode   = NULL;
00818 
00819   dwIndex = 0;
00820   siCObject = SiCNodeGetObject(dwIndex, TRUE, AC_ALL);
00821   while(siCObject)
00822   {
00823     if(stricmp(szArchiveName, siCObject->szArchiveName) == 0)
00824     {
00825       siCNode = siCObject;
00826       break;
00827     }
00828 
00829     ++dwIndex;
00830     siCObject = SiCNodeGetObject(dwIndex, TRUE, AC_ALL);
00831   }
00832 
00833   return(siCNode);
00834 }
00835 
00836 int DownloadFiles(char *szInputIniFile,
00837                   char *szDownloadDir,
00838                   char *szProxyServer,
00839                   char *szProxyPort,
00840                   char *szProxyUser,
00841                   char *szProxyPasswd,
00842                   BOOL bShowRetryMsg,
00843                   BOOL bIgnoreAllNetworkErrors,
00844                   char *szFailedFile,
00845                   DWORD dwFailedFileSize)
00846 {
00847   char      szBuf[MAX_BUF];
00848   char      szCurrentFile[MAX_BUF];
00849   char      szSection[MAX_INI_SK];
00850   char      szKey[MAX_INI_SK];
00851   char      szSavedCwd[MAX_BUF_MEDIUM];
00852   int       iCounter;
00853   int       rv;
00854   int       iFileDownloadRetries;
00855   int       iIgnoreFileNetworkError;
00856   int       iLocalTimeOutCounter;
00857   DWORD     dwTotalEstDownloadSize;
00858   char      szPartiallyDownloadedFilename[MAX_BUF];
00859   BOOL      bDownloadInitiated;
00860   char      szTempURL[MAX_BUF];
00861   char      szWorkingURLPathOnly[MAX_BUF];
00862   siC       *siCCurrentFileObj = NULL;
00863   ULONG     ulBuf, ulDiskNum, ulDriveMap;
00864 
00865   memset(szTempURL, 0, sizeof(szTempURL));
00866   memset(szWorkingURLPathOnly, 0, sizeof(szWorkingURLPathOnly));
00867   if(szInputIniFile == NULL)
00868     return(WIZ_ERROR_UNDEFINED);
00869 
00870   if(szFailedFile)
00871     memset(szFailedFile, 0, dwFailedFileSize);
00872 
00873   InitTickInfo();
00874   ulBuf = sizeof(szSavedCwd-3);
00875   DosQueryCurrentDir(0, &szSavedCwd[3], &ulBuf);
00876   // Directory does not start with 'x:\', so add it.
00877   DosQueryCurrentDisk(&ulDiskNum, &ulDriveMap);
00878 
00879   // Follow the case of the first letter in the path.
00880   if (isupper(szSavedCwd[3]))
00881      szSavedCwd[0] = (char)('A' - 1 + ulDiskNum);
00882   else
00883      szSavedCwd[0] = (char)('a' - 1 + ulDiskNum);
00884   szSavedCwd[1] = ':';
00885   szSavedCwd[2] = '\\';
00886 
00887   if (toupper(szSavedCwd[0]) != toupper(szDownloadDir[0]))
00888      DosSetDefaultDisk(toupper(szDownloadDir[0]) - 'A' + 1);
00889   DosSetCurrentDir(szDownloadDir);
00890 
00891   rv                        = WIZ_OK;
00892   dwTotalEstDownloadSize    = 0;
00893   giTotalArchivesToDownload = 0;
00894   glLastBytesSoFar          = 0;
00895   glAbsoluteBytesSoFar      = 0;
00896   glBytesResumedFrom        = 0;
00897   gdwTickStart              = 0; /* Initialize the counter used to
00898                                   * calculate download rate */
00899   gbStartTickCounter        = FALSE; /* used to determine when to start
00900                                       * the tick counter used to calculate
00901                                       * the download rate */
00902   gbUrlChanged              = TRUE;
00903   gbDlgDownloadMinimized    = FALSE;
00904   gbDlgDownloadJustMinimized = FALSE;
00905   gdwDownloadDialogStatus   = CS_NONE;
00906   gbShowDownloadRetryMsg    = bShowRetryMsg;
00907   gszConfigIniFile          = szInputIniFile;
00908   bDownloadInitiated        = FALSE;
00909 
00910   GetTotalArchivesToDownload(&giTotalArchivesToDownload,
00911                              &dwTotalEstDownloadSize);
00912   glTotalKb                 = dwTotalEstDownloadSize;
00913   GetSetupCurrentDownloadFile(szPartiallyDownloadedFilename,
00914                               sizeof(szPartiallyDownloadedFilename));
00915 
00916   InitDownloadDlg();
00917 
00918   for(giIndex = 0; giIndex < giTotalArchivesToDownload; giIndex++)
00919   {
00920     /* set (or reset) the counter to 0 in order to read the
00921      * next files's 0'th url from the .idi file */
00922     iCounter     = 0;
00923     gbUrlChanged = TRUE; /* Update the download dialog with new URL */
00924     sprintf(szSection, "File%d", giIndex);
00925     sprintf(szKey,     "url%d",  iCounter);
00926     GetPrivateProfileString(szSection,
00927                             szKey,
00928                             "",
00929                             szTempURL,
00930                             sizeof(szTempURL),
00931                             gszConfigIniFile);
00932 
00933     if(*szTempURL == '\0')
00934       continue;
00935 
00936     if(!bDownloadInitiated)
00937     {
00938       ParsePath(szTempURL,
00939                 szWorkingURLPathOnly,
00940                 sizeof(szWorkingURLPathOnly),
00941                 TRUE, //use '/' as the path delimiter
00942                 PP_PATH_ONLY);
00943     }
00944 
00945     GetPrivateProfileString(szSection,
00946                             "desc",
00947                             "",
00948                             gszCurrentDownloadFileDescription,
00949                             sizeof(gszCurrentDownloadFileDescription),
00950                             gszConfigIniFile);
00951 #ifdef OLDCODE
00952     iIgnoreFileNetworkError = GetPrivateProfileInt(szSection,
00953                             "Ignore File Network Error",
00954                             0,
00955                             gszConfigIniFile);
00956 #endif
00957     iIgnoreFileNetworkError = 0;
00958 
00959     /* save the file name to be downloaded */
00960     ParsePath(szTempURL,
00961               szCurrentFile,
00962               sizeof(szCurrentFile),
00963               TRUE, //use '/' as the path delimiter
00964               PP_FILENAME_ONLY);
00965 
00966     RemoveSlash(szWorkingURLPathOnly);
00967     sprintf(gszUrl, "%s/%s", szWorkingURLPathOnly, szCurrentFile);
00968 
00969     /* retrieve the file's data structure */
00970     siCCurrentFileObj = GetObjectFromArchiveName(szCurrentFile);
00971 
00972     if((*szPartiallyDownloadedFilename != 0) &&
00973        (stricmp(szPartiallyDownloadedFilename, szCurrentFile) == 0))
00974     {
00975       struct stat statBuf;
00976 
00977       if(stat(szPartiallyDownloadedFilename, &statBuf) != -1)
00978       {
00979         glAbsoluteBytesSoFar += statBuf.st_size;
00980         glBytesResumedFrom    = statBuf.st_size;
00981       }
00982     }
00983 
00984     strcpy(gszTo, szDownloadDir);
00985     AppendBackSlash(gszTo, sizeof(gszTo));
00986     strcat(gszTo, szCurrentFile);
00987 
00988     if(gbDlgDownloadMinimized)
00989       SetMinimizedDownloadTitle((int)GetPercentSoFar());
00990     else
00991     {
00992       SetStatusUrl();
00993       SetRestoredDownloadTitle();
00994     }
00995 
00996     SetSetupCurrentDownloadFile(szCurrentFile);
00997     iFileDownloadRetries = 0;
00998     iLocalTimeOutCounter = 0;
00999     do
01000     {
01001       ProcessWindowsMessages();
01002       /* Download starts here */
01003       if((szProxyServer != NULL) && (szProxyPort != NULL) &&
01004          (*szProxyServer != '\0') && (*szProxyPort != '\0'))
01005         /* If proxy info is provided, use HTTP proxy */
01006         rv = DownloadViaProxy(gszUrl,
01007                               szProxyServer,
01008                               szProxyPort,
01009                               szProxyUser,
01010                               szProxyPasswd);
01011       else
01012       {
01013         /* is this an HTTP URL? */
01014         if(strncmp(gszUrl, kHTTP, strlen(kHTTP)) == 0)
01015           rv = DownloadViaHTTP(gszUrl);
01016         /* or is this an FTP URL? */
01017         else if(strncmp(gszUrl, kFTP, strlen(kFTP)) == 0)
01018           rv = DownloadViaFTP(gszUrl);
01019       }
01020 
01021       bDownloadInitiated = TRUE;
01022       if((rv == nsFTPConn::E_USER_CANCEL) ||
01023          (gdwDownloadDialogStatus == CS_PAUSE))
01024       {
01025         if(gdwDownloadDialogStatus == CS_PAUSE)
01026         {
01027           CloseSocket(szProxyServer, szProxyPort);
01028 
01029           /* rv needs to be set to something
01030            * other than E_USER_CANCEL or E_OK */
01031           rv = nsFTPConn::E_CMD_UNEXPECTED;
01032 
01033           PauseTheDownload(rv, &iFileDownloadRetries);
01034           bDownloadInitiated = FALSE; /* restart the download using
01035                                        * new socket connection */
01036         }
01037         else
01038         {
01039           /* user canceled; break out of the do loop */
01040           break;
01041         }
01042       }
01043       else if((rv != nsFTPConn::OK) &&
01044               (rv != nsFTPConn::E_CMD_FAIL) &&
01045               (rv != nsSocket::E_BIND) &&
01046               (rv != nsHTTPConn::E_HTTP_RESPONSE) &&
01047               (gdwDownloadDialogStatus != CS_CANCEL))
01048       {
01049         /* We timed out.  No response from the server, or 
01050          * we somehow lost connection. */
01051 
01052         char szTitle[MAX_BUF_SMALL];
01053         char szMsgDownloadPaused[MAX_BUF];
01054 
01055         /* Incrememt the time out counter on E_TIMEOUT */
01056         if(rv == nsSocket::E_TIMEOUT)
01057         {
01058           ++siCCurrentFileObj->iNetTimeOuts;
01059           ++iLocalTimeOutCounter;
01060         }
01061 
01062         CloseSocket(szProxyServer, szProxyPort);
01063 
01064         /* If the number of timeouts is %3 == 0, then let's pause
01065          * the download process.  Otherwise, just close the
01066          * connection and open a new one to see if the download
01067          * can be restarted automatically. */
01068         if((rv != nsSocket::E_TIMEOUT) ||
01069            (rv == nsSocket::E_TIMEOUT) && ((iLocalTimeOutCounter % kModTimeOutValue) == 0))
01070         {
01071           /* Start the pause tick counter here because we don't know how
01072            * long before the user will dismiss the MessageBox() */
01073           if(!gtiPaused.bTickStarted)
01074           {
01075             gtiPaused.dwTickBegin          = WinGetCurrentTime(NULLHANDLE);
01076             gtiPaused.bTickStarted         = TRUE;
01077             gtiPaused.bTickDownloadResumed = FALSE;
01078           }
01079 
01080           /* The connection unexepectedly dropped for some reason, so inform
01081            * the user that the download will be Paused, and then update the
01082            * Download dialog to show the Paused state. */
01083           GetPrivateProfileString("Messages",
01084                                   "MB_WARNING_STR",
01085                                   "",
01086                                   szTitle,
01087                                   sizeof(szTitle),
01088                                   szFileIniInstall);
01089           GetPrivateProfileString("Strings",
01090                                   "Message Download Paused",
01091                                   "",
01092                                   szMsgDownloadPaused,
01093                                   sizeof(szMsgDownloadPaused),
01094                                   szFileIniConfig);
01095           WinMessageBox(HWND_DESKTOP, dlgInfo.hWndDlg,
01096                         szMsgDownloadPaused,
01097                         szTitle, 0,
01098                         MB_ICONEXCLAMATION);
01099 
01100           /* Let's make sure we're in a paused state */
01101           gdwDownloadDialogStatus = CS_PAUSE;
01102           PauseTheDownload(rv, &iFileDownloadRetries);
01103         }
01104         else
01105           /* Let's make sure we're _not_ in a paused state */
01106           gdwDownloadDialogStatus = CS_NONE;
01107       }
01108 
01109       /* We don't count time outs as normal failures.  We're
01110        * keeping track of time outs differently. */
01111       if(rv != nsSocket::E_TIMEOUT)
01112         ++iFileDownloadRetries;
01113 
01114       if((iFileDownloadRetries > MAX_FILE_DOWNLOAD_RETRIES) &&
01115          (rv != nsFTPConn::E_USER_CANCEL) &&
01116          (gdwDownloadDialogStatus != CS_CANCEL))
01117       {
01118         /* since the download retries maxed out, increment the counter
01119          * to read the next url for the current file */
01120         ++iCounter;
01121         sprintf(szKey, "url%d",  iCounter);
01122         GetPrivateProfileString(szSection,
01123                                 szKey,
01124                                 "",
01125                                 szTempURL,
01126                                 sizeof(szTempURL),
01127                                 gszConfigIniFile);
01128         if(*szTempURL != '\0')
01129         {
01130           /* Found more urls to download from for the current file.
01131            * Update the dialog to show the new url and reset the
01132            * file download retries to 0 since it's a new url. */
01133           gbUrlChanged = TRUE;
01134           iFileDownloadRetries = 0;
01135           bDownloadInitiated = FALSE; // restart the download using new socket connection
01136           CloseSocket(szProxyServer, szProxyPort);
01137           ParsePath(szTempURL,
01138                     szWorkingURLPathOnly,
01139                     sizeof(szWorkingURLPathOnly),
01140                     TRUE, //use '/' as the path delimiter
01141                     PP_PATH_ONLY);
01142           RemoveSlash(szWorkingURLPathOnly);
01143           sprintf(gszUrl, "%s/%s", szWorkingURLPathOnly, szCurrentFile);
01144           SetStatusUrl();
01145         }
01146       }
01147     } while((rv != nsFTPConn::E_USER_CANCEL) &&
01148             (rv != nsFTPConn::OK) &&
01149             (gdwDownloadDialogStatus != CS_CANCEL) &&
01150             (iFileDownloadRetries <= MAX_FILE_DOWNLOAD_RETRIES));
01151 
01152     /* Save the number of retries for each file */
01153     siCCurrentFileObj->iNetRetries = iFileDownloadRetries < 1 ? 0:iFileDownloadRetries - 1;
01154 
01155     if((rv == nsFTPConn::E_USER_CANCEL) ||
01156        (gdwDownloadDialogStatus == CS_CANCEL))
01157     {
01158       /* make sure rv is E_USER_CANCEL when gdwDownloadDialogStatus
01159        * is CS_CANCEL */
01160       rv = nsFTPConn::E_USER_CANCEL;
01161 
01162       if(szFailedFile && ((DWORD)strlen(szCurrentFile) <= dwFailedFileSize))
01163         strcpy(szFailedFile, gszCurrentDownloadFileDescription);
01164 
01165       /* break out of for() loop */
01166       break;
01167     }
01168 
01169     if((rv != nsFTPConn::OK) &&
01170        (iFileDownloadRetries > MAX_FILE_DOWNLOAD_RETRIES) &&
01171        !bIgnoreAllNetworkErrors &&
01172        !iIgnoreFileNetworkError)
01173     {
01174       /* too many retries from failed downloads */
01175       char szMsg[MAX_BUF];
01176 
01177       if(szFailedFile && ((DWORD)strlen(szCurrentFile) <= dwFailedFileSize))
01178         strcpy(szFailedFile, gszCurrentDownloadFileDescription);
01179 
01180       GetPrivateProfileString("Strings",
01181                               "Error Too Many Network Errors",
01182                               "",
01183                               szMsg,
01184                               sizeof(szMsg),
01185                               szFileIniConfig);
01186       if(*szMsg != '\0')
01187       {
01188         sprintf(szBuf, szMsg, szCurrentFile);
01189         PrintError(szBuf, ERROR_CODE_HIDE);
01190       }
01191 
01192       /* Set return value and break out of for() loop.
01193        * We don't want to continue if there were too
01194        * many network errors on any file. */
01195       rv = WIZ_TOO_MANY_NETWORK_ERRORS;
01196       break;
01197     }
01198     else if(bIgnoreAllNetworkErrors || iIgnoreFileNetworkError)
01199       rv = nsFTPConn::OK;
01200 
01201     UnsetSetupCurrentDownloadFile();
01202   }
01203 
01204   CloseSocket(szProxyServer, szProxyPort);
01205   if(sgProduct.ulMode != SILENT) 
01206     WinDestroyWindow(dlgInfo.hWndDlg);
01207   if (toupper(szSavedCwd[0]) != toupper(szDownloadDir[0]))
01208      DosSetDefaultDisk(toupper(szSavedCwd[0]) -1 + 'A');
01209   DosSetCurrentDir(szSavedCwd);
01210 
01211   return(rv);
01212 }
01213 
01214 int ProgressCB(int aBytesSoFar, int aTotalFinalSize)
01215 {
01216   long   lBytesDiffSoFar;
01217   double dPercentSoFar;
01218   int    iRv = nsFTPConn::OK;
01219 
01220   if(sgProduct.ulMode != SILENT)
01221   {
01222     SetStatusUrl();
01223 
01224     if(glTotalKb == 0)
01225       glTotalKb = aTotalFinalSize;
01226 
01227     /* Calculate the difference between the last set of bytes read against
01228      * the current set of bytes read.  If the value is negative, that means
01229      * that it started a new file, so reset lBytesDiffSoFar to aBytesSoFar */
01230     lBytesDiffSoFar = ((aBytesSoFar - glLastBytesSoFar) < 1) ? aBytesSoFar : (aBytesSoFar - glLastBytesSoFar);
01231 
01232     /* Save the current bytes read as the last set of bytes read */
01233     glLastBytesSoFar = aBytesSoFar;
01234     glAbsoluteBytesSoFar += lBytesDiffSoFar;
01235 
01236     dPercentSoFar = GetPercentSoFar();
01237     if(gbDlgDownloadMinimized)
01238       SetMinimizedDownloadTitle((int)dPercentSoFar);
01239 
01240     UpdateGaugeFileProgressBar(dPercentSoFar);
01241     SetStatusStatus();
01242 
01243     if((gdwDownloadDialogStatus == CS_CANCEL) ||
01244        (gdwDownloadDialogStatus == CS_PAUSE))
01245       iRv = nsFTPConn::E_USER_CANCEL;
01246   }
01247 
01248   ProcessWindowsMessages();
01249   return(iRv);
01250 }
01251 
01253 // Progress bar
01254 // Centers the specified window over the desktop. Assumes the window is
01255 // smaller both horizontally and vertically than the desktop
01256 static void
01257 CenterWindow(HWND hWndDlg)
01258 {
01259   SWP swpDlg;
01260 
01261   WinQueryWindowPos(hWndDlg, &swpDlg);
01262   WinSetWindowPos(hWndDlg,
01263                   0,
01264                   (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)/2)-(swpDlg.cx/2),
01265                   (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)/2)-(swpDlg.cy/2),
01266                   0,
01267                   0,
01268                   SWP_MOVE);
01269 }
01270 
01271 // Window proc for dialog
01272 MRESULT EXPENTRY
01273 DownloadDlgProc(HWND hWndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
01274 {
01275   PSWP pswp;
01276 
01277   switch (msg)
01278   {
01279     case WM_INITDLG:
01280       AdjustDialogSize(hWndDlg);
01281       WinSetPresParam(hWndDlg, PP_FONTNAMESIZE,
01282                       strlen(sgInstallGui.szDefinedFont)+1, sgInstallGui.szDefinedFont);
01283       WinSendMsg(WinWindowFromID(hWndDlg, IDC_GAUGE_FILE), SLM_SETSLIDERINFO,
01284                                  MPFROM2SHORT(SMA_SHAFTDIMENSIONS, 0),
01285                                  (MPARAM)20);
01286       GetPrivateProfileString("Strings",
01287                               "Status File Info",
01288                               "",
01289                               gszFileInfo,
01290                               sizeof(gszFileInfo),
01291                               szFileIniConfig);
01292 //      DisableSystemMenuItems(hWndDlg, FALSE);
01293       CenterWindow(hWndDlg);
01294       if(gbShowDownloadRetryMsg)
01295         WinSetDlgItemText(hWndDlg, IDC_MESSAGE0, diDownload.szMessageRetry0);
01296       else
01297         WinSetDlgItemText(hWndDlg, IDC_MESSAGE0, diDownload.szMessageDownload0);
01298 
01299       WinEnableWindow(WinWindowFromID(hWndDlg, IDRESUME), FALSE);
01300       WinSetDlgItemText(hWndDlg, IDC_STATIC1, sgInstallGui.szFile);
01301       WinSetDlgItemText(hWndDlg, IDC_STATIC2, sgInstallGui.szUrl);
01302       WinSetDlgItemText(hWndDlg, IDC_STATIC3, sgInstallGui.szTo);
01303       WinSetDlgItemText(hWndDlg, IDC_STATIC4, sgInstallGui.szStatus);
01304       WinSetDlgItemText(hWndDlg, IDCANCEL, sgInstallGui.szCancel_);
01305       WinSetDlgItemText(hWndDlg, IDPAUSE, sgInstallGui.szPause_);
01306       WinSetDlgItemText(hWndDlg, IDRESUME, sgInstallGui.szResume_);
01307       break;
01308 
01309     case WM_ADJUSTWINDOWPOS:
01310       pswp = (PSWP)mp1;
01311       if (pswp->fl & SWP_MINIMIZE) {
01312         SetMinimizedDownloadTitle((int)GetPercentSoFar());
01313         gbDlgDownloadMinimized = TRUE;
01314         gbDlgDownloadJustMinimized = TRUE;
01315       }
01316       if (pswp->fl & SWP_RESTORE) {
01317         SetStatusUrl();
01318         SetRestoredDownloadTitle();
01319         gbDlgDownloadMinimized = FALSE;
01320       }
01321       break;
01322 
01323    case WM_CLOSE:
01324       if(AskCancelDlg(hWndDlg))
01325         gdwDownloadDialogStatus = CS_CANCEL;
01326       return (MRESULT)TRUE;
01327 
01328     case WM_COMMAND:
01329       switch ( SHORT1FROMMP( mp1 ) )
01330       {
01331         case IDCANCEL:
01332           if(AskCancelDlg(hWndDlg))
01333             gdwDownloadDialogStatus = CS_CANCEL;
01334           break;
01335 
01336         case IDPAUSE:
01337           if(!gtiPaused.bTickStarted)
01338           {
01339             gtiPaused.dwTickBegin          = WinGetCurrentTime(NULLHANDLE);
01340             gtiPaused.bTickStarted         = TRUE;
01341             gtiPaused.bTickDownloadResumed = FALSE;
01342           }
01343 
01344           WinEnableWindow(WinWindowFromID(hWndDlg, IDPAUSE),  FALSE);
01345           WinEnableWindow(WinWindowFromID(hWndDlg, IDRESUME), TRUE);
01346           gdwDownloadDialogStatus = CS_PAUSE;
01347           break;
01348 
01349         case IDRESUME:
01350           gtiPaused.dwTickEnd = WinGetCurrentTime(NULLHANDLE);
01351           gtiPaused.dwTickDif = GetTickDif(gtiPaused.dwTickEnd,
01352                                            gtiPaused.dwTickBegin);
01353           gtiPaused.bTickDownloadResumed = TRUE;
01354 
01355           WinEnableWindow(WinWindowFromID(hWndDlg, IDRESUME), FALSE);
01356           WinEnableWindow(WinWindowFromID(hWndDlg, IDPAUSE),  TRUE);
01357           gdwDownloadDialogStatus = CS_NONE;
01358           break;
01359 
01360         default:
01361           break;
01362       }
01363       return (MRESULT)TRUE;
01364   }
01365 
01366   return WinDefDlgProc(hWndDlg, msg, mp1, mp2);
01367 }
01368 
01369 // This routine will update the File Gauge progress bar to the specified percentage
01370 // (value between 0 and 100)
01371 static void
01372 UpdateGaugeFileProgressBar(double value)
01373 {
01374   if(sgProduct.ulMode != SILENT)
01375   {
01376     ULONG ulPercentage = 100*value/100;
01377     WinSendMsg(WinWindowFromID(dlgInfo.hWndDlg, IDC_GAUGE_FILE), SLM_SETSLIDERINFO,
01378                                MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE),
01379                                (MPARAM)(ulPercentage-1));
01380   }
01381 }
01382 
01383 void InitDownloadDlg(void)
01384 {
01385   if(sgProduct.ulMode != SILENT)
01386   {
01387     dlgInfo.hWndDlg = WinLoadDlg(HWND_DESKTOP, hWndMain, DownloadDlgProc, hSetupRscInst, DLG_DOWNLOADING, NULL);
01388     WinShowWindow(dlgInfo.hWndDlg, TRUE);
01389   }
01390 }
01391