Back to index

lightning-sunbird  0.9+nobinonly
xpi.c
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 Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Sean Su <ssu@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "extern.h"
00041 #include "dialogs.h"
00042 #include "extra.h"
00043 #include "xpistub.h"
00044 #include "xpi.h"
00045 #include "xperr.h"
00046 #include "logging.h"
00047 #include "ifuncns.h"
00048 
00049 #define BDIR_RIGHT 1
00050 #define BDIR_LEFT  2
00051 
00052 typedef HRESULT (_cdecl *XpiInit)(const char *, const char *aLogName, pfnXPIProgress);
00053 typedef HRESULT (_cdecl *XpiInstall)(const char *, const char *, long);
00054 typedef void    (_cdecl *XpiExit)(void);
00055 typedef BOOL    (WINAPI *SetDllPathProc)(const char*);
00056 
00057 static XpiInit          pfnXpiInit;
00058 static XpiInstall       pfnXpiInstall;
00059 static XpiExit          pfnXpiExit;
00060 static SetDllPathProc   pfnSetDllPath = NULL;
00061 
00062 static long             lFileCounter;
00063 static long             lBarberCounter;
00064 static BOOL             bBarberBar;
00065 static DWORD            dwBarberDirection;
00066 static DWORD            dwCurrentArchive;
00067 static DWORD            dwTotalArchives;
00068 char                    szStrProcessingFile[MAX_BUF];
00069 char                    szStrCopyingFile[MAX_BUF];
00070 char                    szStrInstalling[MAX_BUF];
00071 static char             gSavedCwd[MAX_BUF];
00072 
00073 static void UpdateGaugeFileProgressBar(unsigned value);
00074 static void UpdateGaugeArchiveProgressBar(unsigned value);
00075 static void UpdateGaugeFileBarber(void);
00076 
00077 struct ExtractFilesDlgInfo
00078 {
00079        HWND   hWndDlg;
00080        int           nMaxFileBars;     // maximum number of bars that can be displayed
00081        int           nMaxArchiveBars;     // maximum number of bars that can be displayed
00082        int           nFileBars;               // current number of bars to display
00083        int           nArchiveBars;          // current number of bars to display
00084 } dlgInfo;
00085 
00086 HRESULT InitializeXPIStub(char *xpinstallPath)
00087 {
00088   char szBuf[MAX_BUF];
00089   char szXPIStubFile[MAX_BUF];
00090   char szEGetProcAddress[MAX_BUF];
00091   HANDLE hKernel;
00092 
00093   hXPIStubInst = NULL;
00094   GetCurrentDirectory(sizeof(gSavedCwd), gSavedCwd);
00095 
00096   if(!GetPrivateProfileString("Messages", "ERROR_GETPROCADDRESS", "", szEGetProcAddress, sizeof(szEGetProcAddress), szFileIniInstall))
00097     return(1);
00098 
00099   /* change current directory to where xpistub.dll */
00100   SetCurrentDirectory(xpinstallPath);
00101 
00102   /* Windows XP SP1 changed DLL search path strategy, setting current dir */
00103   /* is no longer sufficient. Use SetDLLDirectory() if available */
00104   if ((hKernel = LoadLibrary("kernel32.dll")) != NULL)
00105   {
00106     pfnSetDllPath = (SetDllPathProc)GetProcAddress(hKernel, "SetDllDirectoryA");
00107     if (pfnSetDllPath)
00108       pfnSetDllPath(xpinstallPath);
00109   }
00110 
00111   /* build full path to xpistub.dll */
00112   lstrcpy(szXPIStubFile, xpinstallPath);
00113   AppendBackSlash(szXPIStubFile, sizeof(szXPIStubFile));
00114   lstrcat(szXPIStubFile, "xpistub.dll");
00115 
00116   if(FileExists(szXPIStubFile) == FALSE)
00117     return(2);
00118 
00119   /* load xpistub.dll */
00120   if((hXPIStubInst = LoadLibraryEx(szXPIStubFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL)
00121   {
00122     wsprintf(szBuf, szEDllLoad, szXPIStubFile);
00123     PrintError(szBuf, ERROR_CODE_SHOW);
00124     return(1);
00125   }
00126   if(((FARPROC)pfnXpiInit = GetProcAddress(hXPIStubInst, "XPI_Init")) == NULL)
00127   {
00128     wsprintf(szBuf, szEGetProcAddress, "XPI_Init");
00129     PrintError(szBuf, ERROR_CODE_SHOW);
00130     return(1);
00131   }
00132   if(((FARPROC)pfnXpiInstall = GetProcAddress(hXPIStubInst, "XPI_Install")) == NULL)
00133   {
00134     wsprintf(szBuf, szEGetProcAddress, "XPI_Install");
00135     PrintError(szBuf, ERROR_CODE_SHOW);
00136     return(1);
00137   }
00138   if(((FARPROC)pfnXpiExit = GetProcAddress(hXPIStubInst, "XPI_Exit")) == NULL)
00139   {
00140     wsprintf(szBuf, szEGetProcAddress, "XPI_Exit");
00141     PrintError(szBuf, ERROR_CODE_SHOW);
00142     return(1);
00143   }
00144 
00145   return(0);
00146 }
00147 
00148 HRESULT DeInitializeXPIStub()
00149 {
00150   pfnXpiInit    = NULL;
00151   pfnXpiInstall = NULL;
00152   pfnXpiExit    = NULL;
00153 
00154   if(hXPIStubInst)
00155     FreeLibrary(hXPIStubInst);
00156 
00157   chdir(szSetupDir);
00158   if (pfnSetDllPath)
00159     pfnSetDllPath(NULL);
00160 
00161   SetCurrentDirectory(gSavedCwd);
00162   return(0);
00163 }
00164 
00165 void GetTotalArchivesToInstall(void)
00166 {
00167   DWORD     dwIndex0;
00168   siC       *siCObject = NULL;
00169 
00170   dwIndex0        = 0;
00171   dwTotalArchives = 0;
00172   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
00173   while(siCObject)
00174   {
00175     if((siCObject->dwAttributes & SIC_SELECTED) && !(siCObject->dwAttributes & SIC_LAUNCHAPP))
00176       ++dwTotalArchives;
00177 
00178     ++dwIndex0;
00179     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
00180   }
00181 }
00182 
00183 char *GetErrorString(DWORD dwError, char *szErrorString, DWORD dwErrorStringSize)
00184 {
00185   int  i = 0;
00186   char szErrorNumber[MAX_BUF];
00187 
00188   ZeroMemory(szErrorString, dwErrorStringSize);
00189   itoa(dwError, szErrorNumber, 10);
00190 
00191   /* map the error value to a string */
00192   while(TRUE)
00193   {
00194     if(*XpErrorList[i] == '\0')
00195       break;
00196 
00197     if(lstrcmpi(szErrorNumber, XpErrorList[i]) == 0)
00198     {
00199       if(*XpErrorList[i + 1] != '\0')
00200         lstrcpy(szErrorString, XpErrorList[i + 1]);
00201 
00202       break;
00203     }
00204 
00205     ++i;
00206   }
00207 
00208   return(szErrorString);
00209 }
00210 
00211 /* function that clears the file progress bar of the xpinstall progress
00212  * dialog.
00213  */
00214 void InvalidateBarberBarArea()
00215 {
00216   HWND hWndGauge;
00217   RECT rect;
00218 
00219   /* get the file progress bar gauge */
00220   hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE_FILE);
00221   /* get the dimensions of the gauge */
00222   GetClientRect(hWndGauge, &rect);
00223   /* invalidate the rect area of the gauge */
00224   InvalidateRect(hWndGauge, &rect, FALSE);
00225   /* update the dialog */
00226   UpdateWindow(dlgInfo.hWndDlg);
00227 }
00228 
00229 HRESULT SmartUpdateJars()
00230 {
00231   DWORD     dwIndex0;
00232   siC       *siCObject = NULL;
00233   HRESULT   hrResult;
00234   char      szBuf[MAX_BUF];
00235   char      szEXpiInstall[MAX_BUF];
00236   char      szArchive[MAX_BUF];
00237   char      szMsgSmartUpdateStart[MAX_BUF];
00238   char      szDlgExtractingTitle[MAX_BUF];
00239   char      xpinstallPath[MAX_BUF];
00240   char      xpiArgs[MAX_BUF];
00241 
00242   if(!GetPrivateProfileString("Messages", "MSG_SMARTUPDATE_START", "", szMsgSmartUpdateStart, sizeof(szMsgSmartUpdateStart), szFileIniInstall))
00243     return(1);
00244   if(!GetPrivateProfileString("Messages", "DLG_EXTRACTING_TITLE", "", szDlgExtractingTitle, sizeof(szDlgExtractingTitle), szFileIniInstall))
00245     return(1);
00246   if(!GetPrivateProfileString("Messages", "STR_PROCESSINGFILE", "", szStrProcessingFile, sizeof(szStrProcessingFile), szFileIniInstall))
00247     exit(1);
00248   if(!GetPrivateProfileString("Messages", "STR_INSTALLING", "", szStrInstalling, sizeof(szStrInstalling), szFileIniInstall))
00249     exit(1);
00250   if(!GetPrivateProfileString("Messages", "STR_COPYINGFILE", "", szStrCopyingFile, sizeof(szStrCopyingFile), szFileIniInstall))
00251     exit(1);
00252 
00253   ShowMessage(szMsgSmartUpdateStart, TRUE);
00254   GetXpinstallPath(xpinstallPath, sizeof(xpinstallPath));
00255   if(InitializeXPIStub(xpinstallPath) == WIZ_OK)
00256   {
00257     LogISXPInstall(W_START);
00258     lstrcpy(szBuf, sgProduct.szPath);
00259     if(*sgProduct.szSubPath != '\0')
00260     {
00261       AppendBackSlash(szBuf, sizeof(szBuf));
00262       lstrcat(szBuf, sgProduct.szSubPath);
00263     }
00264     hrResult = pfnXpiInit(szBuf, FILE_INSTALL_LOG, cbXPIProgress);
00265 
00266     ShowMessage(NULL, FALSE);
00267     InitProgressDlg();
00268     GetTotalArchivesToInstall();
00269     SetWindowText(dlgInfo.hWndDlg, szDlgExtractingTitle);
00270 
00271     dwIndex0          = 0;
00272     dwCurrentArchive  = 0;
00273     dwTotalArchives   = (dwTotalArchives * 2) + 1;
00274     bBarberBar        = FALSE;
00275     siCObject         = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
00276     while(siCObject)
00277     {
00278       if(siCObject->dwAttributes & SIC_SELECTED)
00279         /* Since the archive is selected, we need to process the file ops here */
00280          ProcessFileOps(T_PRE_ARCHIVE, siCObject->szReferenceName);
00281 
00282       /* launch smartupdate engine for earch jar to be installed */
00283       if((siCObject->dwAttributes & SIC_SELECTED)   &&
00284         !(siCObject->dwAttributes & SIC_LAUNCHAPP) &&
00285         !(siCObject->dwAttributes & SIC_DOWNLOAD_ONLY))
00286       {
00287         lFileCounter      = 0;
00288         lBarberCounter    = 0;
00289         dwBarberDirection = BDIR_RIGHT;
00290                        dlgInfo.nFileBars = 0;
00291         UpdateGaugeFileProgressBar(0);
00292 
00293         lstrcpy(szArchive, sgProduct.szAlternateArchiveSearchPath);
00294         AppendBackSlash(szArchive, sizeof(szArchive));
00295         lstrcat(szArchive, siCObject->szArchiveName);
00296         if((*sgProduct.szAlternateArchiveSearchPath == '\0') || (!FileExists(szArchive)))
00297         {
00298           lstrcpy(szArchive, szSetupDir);
00299           AppendBackSlash(szArchive, sizeof(szArchive));
00300           lstrcat(szArchive, siCObject->szArchiveName);
00301           if(!FileExists(szArchive))
00302           {
00303             lstrcpy(szArchive, szTempDir);
00304             AppendBackSlash(szArchive, sizeof(szArchive));
00305             lstrcat(szArchive, siCObject->szArchiveName);
00306             if(!FileExists(szArchive))
00307             {
00308               char szEFileNotFound[MAX_BUF];
00309 
00310               if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
00311               {
00312                 wsprintf(szBuf, szEFileNotFound, szArchive);
00313                 PrintError(szBuf, ERROR_CODE_HIDE);
00314               }
00315               return(1);
00316             }
00317           }
00318         }
00319 
00320         if(dwCurrentArchive == 0)
00321         {
00322           ++dwCurrentArchive;
00323           UpdateGaugeArchiveProgressBar((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00324           UpdateGREAppInstallerProgress((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00325         }
00326 
00327         wsprintf(szBuf, szStrInstalling, siCObject->szDescriptionShort);
00328         SetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS0, szBuf);
00329         LogISXPInstallComponent(siCObject->szDescriptionShort);
00330 
00331         /* XXX fix: we need to better support passing arguments to .xpi files.
00332          * This is a temporary hack to get greType passed to browser.xpi so that
00333          * it won't delete GRE files if GRE is installed in the mozilla dir.
00334          *
00335          * What should be done is have the arguments be described in each
00336          * component's section in config.ini and have it passed thru here. */
00337         *xpiArgs = '\0';
00338         if(lstrcmpi(siCObject->szArchiveName, "gre.xpi") == 0)
00339           MozCopyStr(sgProduct.szRegPath, xpiArgs, sizeof(xpiArgs));
00340         else if((lstrcmpi(siCObject->szArchiveName, "browser.xpi") == 0) &&
00341                 (sgProduct.greType == GRE_LOCAL))
00342           /* passing -greShared to browser.xpi will tell it to cleanup GRE files
00343            * from it's directory if they exist. */
00344           MozCopyStr("-greLocal", xpiArgs, sizeof(xpiArgs));
00345 
00346         hrResult = pfnXpiInstall(szArchive, xpiArgs, 0xFFFF);
00347         if(hrResult == E_REBOOT)
00348           bReboot = TRUE;
00349         else if((hrResult != WIZ_OK) &&
00350                !(siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
00351         {
00352           LogMSXPInstallStatus(siCObject->szArchiveName, hrResult);
00353           LogISXPInstallComponentResult(hrResult);
00354           if(GetPrivateProfileString("Messages", "ERROR_XPI_INSTALL", "", szEXpiInstall, sizeof(szEXpiInstall), szFileIniInstall))
00355           {
00356             char szErrorString[MAX_BUF];
00357 
00358             GetErrorString(hrResult, szErrorString, sizeof(szErrorString));
00359             wsprintf(szBuf, "%s - %s: %d %s", szEXpiInstall, siCObject->szDescriptionShort, hrResult, szErrorString);
00360             PrintError(szBuf, ERROR_CODE_HIDE);
00361           }
00362 
00363           /* break out of the siCObject while loop */
00364           break;
00365         }
00366 
00367         ++dwCurrentArchive;
00368         UpdateGaugeArchiveProgressBar((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00369         UpdateGREAppInstallerProgress((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00370 
00371         ProcessWindowsMessages();
00372         LogISXPInstallComponentResult(hrResult);
00373 
00374         if((hrResult != WIZ_OK) &&
00375           (siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
00376           /* reset the result to WIZ_OK if there was an error and the
00377            * component's attributes contains SIC_IGNORE_XPINSTALL_ERROR.
00378            * This should be done after LogISXPInstallComponentResult()
00379            * because we still should log the error value. */
00380           hrResult = WIZ_OK;
00381       }
00382 
00383       if(siCObject->dwAttributes & SIC_SELECTED)
00384         /* Since the archive is selected, we need to do the file ops here */
00385          ProcessFileOps(T_POST_ARCHIVE, siCObject->szReferenceName);
00386 
00387       ++dwIndex0;
00388       siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
00389     } /* while(siCObject) */
00390 
00391     SaveWindowPosition(dlgInfo.hWndDlg);
00392     //report 100% progress status for successful installs
00393     UpdateGREAppInstallerProgress(100);
00394     LogMSXPInstallStatus(NULL, hrResult);
00395     pfnXpiExit();
00396     DeInitProgressDlg();
00397   }
00398 
00399   DeInitializeXPIStub();
00400   LogISXPInstall(W_END);
00401 
00402   return(hrResult);
00403 }
00404 
00405 void cbXPIStart(const char *URL, const char *UIName)
00406 {
00407 }
00408 
00409 void cbXPIProgress(const char* msg, PRInt32 val, PRInt32 max)
00410 {
00411   char szFilename[MAX_BUF];
00412   char szStrProcessingFileBuf[MAX_BUF];
00413   char szStrCopyingFileBuf[MAX_BUF];
00414 
00415   if(sgProduct.mode != SILENT)
00416   {
00417     ParsePath((char *)msg, szFilename, sizeof(szFilename), FALSE, PP_FILENAME_ONLY);
00418 
00419     if(max == 0)
00420     {
00421       wsprintf(szStrProcessingFileBuf, szStrProcessingFile, szFilename);
00422       SetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS3, szStrProcessingFileBuf);
00423       bBarberBar = TRUE;
00424       UpdateGaugeFileBarber();
00425     }
00426     else
00427     {
00428       if(bBarberBar == TRUE)
00429       {
00430         dlgInfo.nFileBars = 0;
00431         ++dwCurrentArchive;
00432         UpdateGaugeArchiveProgressBar((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00433         UpdateGREAppInstallerProgress((unsigned)(((double)(dwCurrentArchive)/(double)dwTotalArchives)*(double)100));
00434 
00435         InvalidateBarberBarArea();
00436         bBarberBar = FALSE;
00437       }
00438 
00439       wsprintf(szStrCopyingFileBuf, szStrCopyingFile, szFilename);
00440       SetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS3, szStrCopyingFileBuf);
00441       UpdateGaugeFileProgressBar((unsigned)(((double)(val+1)/(double)max)*(double)100));
00442     }
00443   }
00444 
00445   ProcessWindowsMessages();
00446 }
00447 
00448 void cbXPIFinal(const char *URL, PRInt32 finalStatus)
00449 {
00450 }
00451 
00452 
00453 
00455 // Progress bar
00456 
00457 // Window proc for dialog
00458 LRESULT CALLBACK
00459 ProgressDlgProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
00460 {
00461        switch (msg)
00462   {
00463               case WM_INITDIALOG:
00464       DisableSystemMenuItems(hWndDlg, TRUE);
00465       SendDlgItemMessage (hWndDlg, IDC_STATUS0, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L); 
00466       SendDlgItemMessage (hWndDlg, IDC_GAUGE_ARCHIVE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L); 
00467       SendDlgItemMessage (hWndDlg, IDC_STATUS3, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L); 
00468       SendDlgItemMessage (hWndDlg, IDC_GAUGE_FILE, WM_SETFONT, (WPARAM)sgInstallGui.definedFont, 0L); 
00469                      RepositionWindow(hWndDlg, BANNER_IMAGE_INSTALLING);
00470       ClosePreviousDialog();
00471                      return FALSE;
00472 
00473               case WM_COMMAND:
00474                      return TRUE;
00475        }
00476 
00477        return FALSE;  // didn't handle the message
00478 }
00479 
00480 // This routine will update the File Gauge progress bar to the specified percentage
00481 // (value between 0 and 100)
00482 static void
00483 UpdateGaugeFileBarber()
00484 {
00485        int      nBars;
00486        HWND   hWndGauge;
00487        RECT   rect;
00488 
00489   if(sgProduct.mode != SILENT)
00490   {
00491          hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE_FILE);
00492     if(dwBarberDirection == BDIR_RIGHT)
00493     {
00494       // 121 is the (number of bars) + (number bars in barber bar).
00495       // this number determines how far to the right to draw the barber bat
00496       // so as to make it look like it disappears off the progress meter area.
00497       if(lBarberCounter < 121)
00498         ++lBarberCounter;
00499       else
00500         dwBarberDirection = BDIR_LEFT;
00501     }
00502     else if(dwBarberDirection == BDIR_LEFT)
00503     {
00504       if(lBarberCounter > 0)
00505         --lBarberCounter;
00506       else
00507         dwBarberDirection = BDIR_RIGHT;
00508     }
00509 
00510     // Figure out how many bars should be displayed
00511     nBars = (dlgInfo.nMaxFileBars * lBarberCounter / 100);
00512 
00513     // Update the gauge state before painting
00514     dlgInfo.nFileBars = nBars;
00515 
00516     // Only invalidate the part that needs updating
00517     GetClientRect(hWndGauge, &rect);
00518     InvalidateRect(hWndGauge, &rect, FALSE);
00519 
00520     // Update the whole extracting dialog. We do this because we don't
00521     // have a message loop to process WM_PAINT messages in case the
00522     // extracting dialog was exposed
00523     UpdateWindow(dlgInfo.hWndDlg);
00524   }
00525 }
00526 
00527 // This routine will update the File Gauge progress bar to the specified percentage
00528 // (value between 0 and 100)
00529 static void
00530 UpdateGaugeFileProgressBar(unsigned value)
00531 {
00532        int    nBars;
00533 
00534   if(sgProduct.mode != SILENT)
00535   {
00536     // Figure out how many bars should be displayed
00537     nBars = dlgInfo.nMaxFileBars * value / 100;
00538 
00539     // Only paint if we need to display more bars
00540     if((nBars > dlgInfo.nFileBars) || (dlgInfo.nFileBars == 0))
00541     {
00542       HWND    hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE_FILE);
00543       RECT    rect;
00544 
00545       // Update the gauge state before painting
00546       dlgInfo.nFileBars = nBars;
00547 
00548       // Only invalidate the part that needs updating
00549       GetClientRect(hWndGauge, &rect);
00550       InvalidateRect(hWndGauge, &rect, FALSE);
00551     
00552       // Update the whole extracting dialog. We do this because we don't
00553       // have a message loop to process WM_PAINT messages in case the
00554       // extracting dialog was exposed
00555       UpdateWindow(dlgInfo.hWndDlg);
00556     }
00557   }
00558 }
00559 
00560 // This routine will update the Archive Gauge progress bar to the specified percentage
00561 // (value between 0 and 100)
00562 static void
00563 UpdateGaugeArchiveProgressBar(unsigned value)
00564 {
00565        int    nBars;
00566 
00567   if(sgProduct.mode != SILENT)
00568   {
00569     // Figure out how many bars should be displayed
00570     nBars = dlgInfo.nMaxArchiveBars * value / 100;
00571 
00572     // Only paint if we need to display more bars
00573     if (nBars > dlgInfo.nArchiveBars)
00574     {
00575       HWND    hWndGauge = GetDlgItem(dlgInfo.hWndDlg, IDC_GAUGE_ARCHIVE);
00576       RECT    rect;
00577 
00578       // Update the gauge state before painting
00579       dlgInfo.nArchiveBars = nBars;
00580 
00581       // Only invalidate the part that needs updating
00582       GetClientRect(hWndGauge, &rect);
00583       InvalidateRect(hWndGauge, &rect, FALSE);
00584     
00585       // Update the whole extracting dialog. We do this because we don't
00586       // have a message loop to process WM_PAINT messages in case the
00587       // extracting dialog was exposed
00588       UpdateWindow(dlgInfo.hWndDlg);
00589     }
00590   }
00591 }
00592 
00593 // Draws a recessed border around the gauge
00594 static void
00595 DrawGaugeBorder(HWND hWnd)
00596 {
00597        HDC           hDC = GetWindowDC(hWnd);
00598        RECT   rect;
00599        int           cx, cy;
00600        HPEN   hShadowPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
00601        HGDIOBJ       hOldPen;
00602 
00603        GetWindowRect(hWnd, &rect);
00604        cx = rect.right - rect.left;
00605        cy = rect.bottom - rect.top;
00606 
00607        // Draw a dark gray line segment
00608        hOldPen = SelectObject(hDC, (HGDIOBJ)hShadowPen);
00609        MoveToEx(hDC, 0, cy - 1, NULL);
00610        LineTo(hDC, 0, 0);
00611        LineTo(hDC, cx - 1, 0);
00612 
00613        // Draw a white line segment
00614        SelectObject(hDC, GetStockObject(WHITE_PEN));
00615        MoveToEx(hDC, 0, cy - 1, NULL);
00616        LineTo(hDC, cx - 1, cy - 1);
00617        LineTo(hDC, cx - 1, 0);
00618 
00619        SelectObject(hDC, hOldPen);
00620        DeleteObject(hShadowPen);
00621        ReleaseDC(hWnd, hDC);
00622 }
00623 
00624 // Draws the progress bar
00625 static void
00626 DrawProgressBar(HWND hWnd, int nBars)
00627 {
00628   int         i;
00629        PAINTSTRUCT   ps;
00630        HDC         hDC;
00631        RECT        rect;
00632        HBRUSH      hBrush;
00633 
00634   hDC = BeginPaint(hWnd, &ps);
00635        GetClientRect(hWnd, &rect);
00636   if(nBars <= 0)
00637   {
00638     /* clear the bars */
00639     hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
00640     FillRect(hDC, &rect, hBrush);
00641   }
00642   else
00643   {
00644        // Draw the bars
00645     hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
00646          rect.left     = rect.top = BAR_MARGIN;
00647          rect.bottom  -= BAR_MARGIN;
00648          rect.right    = rect.left + BAR_WIDTH;
00649 
00650          for(i = 0; i < nBars; i++)
00651     {
00652                 RECT dest;
00653 
00654                 if(IntersectRect(&dest, &ps.rcPaint, &rect))
00655                        FillRect(hDC, &rect, hBrush);
00656 
00657       OffsetRect(&rect, BAR_WIDTH + BAR_SPACING, 0);
00658          }
00659   }
00660 
00661        DeleteObject(hBrush);
00662        EndPaint(hWnd, &ps);
00663 }
00664 
00665 // Draws the progress bar
00666 static void
00667 DrawBarberBar(HWND hWnd, int nBars)
00668 {
00669   int         i;
00670        PAINTSTRUCT   ps;
00671        HDC         hDC;
00672        RECT        rect;
00673        HBRUSH      hBrush      = NULL;
00674        HBRUSH      hBrushClear = NULL;
00675 
00676   hDC = BeginPaint(hWnd, &ps);
00677        GetClientRect(hWnd, &rect);
00678   if(nBars <= 0)
00679   {
00680     /* clear the bars */
00681     hBrushClear = CreateSolidBrush(GetSysColor(COLOR_MENU));
00682     FillRect(hDC, &rect, hBrushClear);
00683   }
00684   else
00685   {
00686        // Draw the bars
00687     hBrushClear   = CreateSolidBrush(GetSysColor(COLOR_MENU));
00688     hBrush        = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
00689          rect.left     = rect.top = BAR_MARGIN;
00690          rect.bottom  -= BAR_MARGIN;
00691          rect.right    = rect.left + BAR_WIDTH;
00692 
00693          for(i = 0; i < (nBars + 1); i++)
00694     {
00695                 RECT dest;
00696 
00697                 if(IntersectRect(&dest, &ps.rcPaint, &rect))
00698       {
00699         if((i >= (nBars - 15)) && (i < nBars))
00700                          FillRect(hDC, &rect, hBrush);
00701         else
00702                          FillRect(hDC, &rect, hBrushClear);
00703       }
00704 
00705       OffsetRect(&rect, BAR_WIDTH + BAR_SPACING, 0);
00706          }
00707   }
00708 
00709   if(hBrushClear)
00710     DeleteObject(hBrushClear);
00711 
00712   if(hBrush)
00713     DeleteObject(hBrush);
00714 
00715        EndPaint(hWnd, &ps);
00716 }
00717 
00718 // Adjusts the width of the gauge based on the maximum number of bars
00719 static void
00720 SizeToFitGauge(HWND hWnd, int nMaxBars)
00721 {
00722        RECT   rect;
00723        int           cx;
00724 
00725        // Get the window size in pixels
00726        GetWindowRect(hWnd, &rect);
00727 
00728        // Size the width to fit
00729        cx = 2 * GetSystemMetrics(SM_CXBORDER) + 2 * BAR_MARGIN +
00730               nMaxBars * BAR_WIDTH + (nMaxBars - 1) * BAR_SPACING;
00731 
00732        SetWindowPos(hWnd, NULL, -1, -1, cx, rect.bottom - rect.top,
00733               SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
00734 }
00735 
00736 // Window proc for file gauge
00737 LRESULT CALLBACK
00738 GaugeFileWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00739 {
00740        DWORD  dwStyle;
00741        RECT   rect;
00742 
00743        switch(msg)
00744   {
00745               case WM_NCCREATE:
00746                      dwStyle = GetWindowLong(hWnd, GWL_STYLE);
00747                      SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_BORDER);
00748                      return(TRUE);
00749 
00750               case WM_CREATE:
00751                      // Figure out the maximum number of bars that can be displayed
00752                      GetClientRect(hWnd, &rect);
00753                      dlgInfo.nFileBars = 0;
00754                      dlgInfo.nMaxFileBars = (rect.right - rect.left - 2 * BAR_MARGIN + BAR_SPACING) / (BAR_WIDTH + BAR_SPACING);
00755 
00756                      // Size the gauge to exactly fit the maximum number of bars
00757                      SizeToFitGauge(hWnd, dlgInfo.nMaxFileBars);
00758                      return(FALSE);
00759 
00760               case WM_NCPAINT:
00761                      DrawGaugeBorder(hWnd);
00762                      return(FALSE);
00763 
00764               case WM_PAINT:
00765       if(bBarberBar == TRUE)
00766                        DrawBarberBar(hWnd, dlgInfo.nFileBars);
00767       else
00768                        DrawProgressBar(hWnd, dlgInfo.nFileBars);
00769 
00770                      return(FALSE);
00771        }
00772 
00773        return(DefWindowProc(hWnd, msg, wParam, lParam));
00774 }
00775 
00776 // Window proc for file gauge
00777 LRESULT CALLBACK
00778 GaugeArchiveWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00779 {
00780        DWORD  dwStyle;
00781        RECT   rect;
00782 
00783        switch(msg)
00784   {
00785               case WM_NCCREATE:
00786                      dwStyle = GetWindowLong(hWnd, GWL_STYLE);
00787                      SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_BORDER);
00788                      return(TRUE);
00789 
00790               case WM_CREATE:
00791                      // Figure out the maximum number of bars that can be displayed
00792                      GetClientRect(hWnd, &rect);
00793                      dlgInfo.nArchiveBars = 0;
00794                      dlgInfo.nMaxArchiveBars = (rect.right - rect.left - 2 * BAR_MARGIN + BAR_SPACING) / (BAR_WIDTH + BAR_SPACING);
00795 
00796                      // Size the gauge to exactly fit the maximum number of bars
00797                      SizeToFitGauge(hWnd, dlgInfo.nMaxArchiveBars);
00798                      return(FALSE);
00799 
00800               case WM_NCPAINT:
00801                      DrawGaugeBorder(hWnd);
00802                      return(FALSE);
00803 
00804               case WM_PAINT:
00805                      DrawProgressBar(hWnd, dlgInfo.nArchiveBars);
00806                      return(FALSE);
00807        }
00808 
00809        return(DefWindowProc(hWnd, msg, wParam, lParam));
00810 }
00811 
00812 void InitProgressDlg()
00813 {
00814        WNDCLASS      wc;
00815 
00816   if(sgProduct.mode != SILENT)
00817   {
00818     memset(&wc, 0, sizeof(wc));
00819     wc.style          = CS_GLOBALCLASS;
00820     wc.hInstance      = hInst;
00821     wc.hbrBackground  = (HBRUSH)(COLOR_BTNFACE + 1);
00822     wc.lpfnWndProc    = (WNDPROC)GaugeFileWndProc;
00823     wc.lpszClassName  = "GaugeFile";
00824     RegisterClass(&wc);
00825 
00826     wc.lpfnWndProc    = (WNDPROC)GaugeArchiveWndProc;
00827     wc.lpszClassName  = "GaugeArchive";
00828     RegisterClass(&wc);
00829 
00830     // Display the dialog box
00831     dlgInfo.hWndDlg = CreateDialog(hSetupRscInst, MAKEINTRESOURCE(DLG_EXTRACTING), hWndMain, (WNDPROC)ProgressDlgProc);
00832     UpdateWindow(dlgInfo.hWndDlg);
00833   }
00834 }
00835 
00836 void DeInitProgressDlg()
00837 {
00838   if(sgProduct.mode != SILENT)
00839   {
00840     SaveWindowPosition(dlgInfo.hWndDlg);
00841     DestroyWindow(dlgInfo.hWndDlg);
00842     UnregisterClass("GaugeFile", hInst);
00843     UnregisterClass("GaugeArchive", hInst);
00844   }
00845 }