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  *   Ben Goodger <ben@mozilla.org>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "extern.h"
00042 #include "dialogs.h"
00043 #include "extra.h"
00044 #include "xpistub.h"
00045 #include "xpi.h"
00046 #include "xperr.h"
00047 #include "logging.h"
00048 #include "ifuncns.h"
00049 
00050 #define BDIR_RIGHT 1
00051 #define BDIR_LEFT  2
00052 
00053 typedef HRESULT (_cdecl *XpiInit)(const char *, const char *aLogName, pfnXPIProgress);
00054 typedef HRESULT (_cdecl *XpiInstall)(const char *, const char *, long);
00055 typedef void    (_cdecl *XpiExit)(void);
00056 typedef BOOL    (WINAPI *SetDllPathProc)(const char*);
00057 
00058 static XpiInit          pfnXpiInit;
00059 static XpiInstall       pfnXpiInstall;
00060 static XpiExit          pfnXpiExit;
00061 static SetDllPathProc   pfnSetDllPath = NULL;
00062 
00063 static long             lFileCounter;
00064 static long             lBarberCounter;
00065 static DWORD            dwCurrentFile;
00066 static DWORD            dwTotalFiles;
00067 char                    szStrProcessingFile[MAX_BUF];
00068 char                    szStrCopyingFile[MAX_BUF];
00069 char                    szStrInstalling[MAX_BUF];
00070 static char             gSavedCwd[MAX_BUF];
00071 
00072 static void UpdateArchiveInstallProgress(int aValue);
00073 
00074 struct ExtractFilesDlgInfo
00075 {
00076        HWND   hWndDlg;
00077        int           nMaxFileBars;     // maximum number of bars that can be displayed
00078        int           nMaxArchiveBars;     // maximum number of bars that can be displayed
00079        int           nFileBars;               // current number of bars to display
00080        int           nArchiveBars;          // current number of bars to display
00081 } dlgInfo;
00082 
00083 HRESULT InitializeXPIStub(char *xpinstallPath)
00084 {
00085   char szBuf[MAX_BUF];
00086   char szXPIStubFile[MAX_BUF];
00087   char szEGetProcAddress[MAX_BUF];
00088   HANDLE hKernel;
00089 
00090   hXPIStubInst = NULL;
00091   GetCurrentDirectory(sizeof(gSavedCwd), gSavedCwd);
00092 
00093   if(!GetPrivateProfileString("Messages", "ERROR_GETPROCADDRESS", "", szEGetProcAddress, sizeof(szEGetProcAddress), szFileIniInstall))
00094     return(1);
00095 
00096   /* change current directory to where xpistub.dll */
00097   SetCurrentDirectory(xpinstallPath);
00098 
00099   /* Windows XP SP1 changed DLL search path strategy, setting current dir */
00100   /* is no longer sufficient. Use SetDLLDirectory() if available */
00101   if ((hKernel = LoadLibrary("kernel32.dll")) != NULL)
00102   {
00103     pfnSetDllPath = (SetDllPathProc)GetProcAddress(hKernel, "SetDllDirectoryA");
00104     if (pfnSetDllPath)
00105       pfnSetDllPath(xpinstallPath);
00106   }
00107 
00108   /* build full path to xpistub.dll */
00109   lstrcpy(szXPIStubFile, xpinstallPath);
00110   AppendBackSlash(szXPIStubFile, sizeof(szXPIStubFile));
00111   lstrcat(szXPIStubFile, "xpistub.dll");
00112 
00113   if(FileExists(szXPIStubFile) == FALSE)
00114     return(2);
00115 
00116   /* load xpistub.dll */
00117   if((hXPIStubInst = LoadLibraryEx(szXPIStubFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL)
00118   {
00119     wsprintf(szBuf, szEDllLoad, szXPIStubFile);
00120     PrintError(szBuf, ERROR_CODE_SHOW);
00121     return(1);
00122   }
00123   if(((FARPROC)pfnXpiInit = GetProcAddress(hXPIStubInst, "XPI_Init")) == NULL)
00124   {
00125     wsprintf(szBuf, szEGetProcAddress, "XPI_Init");
00126     PrintError(szBuf, ERROR_CODE_SHOW);
00127     return(1);
00128   }
00129   if(((FARPROC)pfnXpiInstall = GetProcAddress(hXPIStubInst, "XPI_Install")) == NULL)
00130   {
00131     wsprintf(szBuf, szEGetProcAddress, "XPI_Install");
00132     PrintError(szBuf, ERROR_CODE_SHOW);
00133     return(1);
00134   }
00135   if(((FARPROC)pfnXpiExit = GetProcAddress(hXPIStubInst, "XPI_Exit")) == NULL)
00136   {
00137     wsprintf(szBuf, szEGetProcAddress, "XPI_Exit");
00138     PrintError(szBuf, ERROR_CODE_SHOW);
00139     return(1);
00140   }
00141 
00142   return(0);
00143 }
00144 
00145 HRESULT DeInitializeXPIStub()
00146 {
00147   pfnXpiInit    = NULL;
00148   pfnXpiInstall = NULL;
00149   pfnXpiExit    = NULL;
00150 
00151   if(hXPIStubInst)
00152     FreeLibrary(hXPIStubInst);
00153 
00154   chdir(szSetupDir);
00155   if (pfnSetDllPath)
00156     pfnSetDllPath(NULL);
00157 
00158   SetCurrentDirectory(gSavedCwd);
00159   return(0);
00160 }
00161 
00162 void GetTotalArchivesToInstall(void)
00163 {
00164   DWORD i = 0;
00165   siC *siCObject = NULL;
00166 
00167   dwTotalFiles = 0;
00168   
00169   siCObject = SiCNodeGetObject(i, TRUE, AC_ALL);
00170   while (siCObject) {
00171     if ((siCObject->dwAttributes & SIC_SELECTED) && 
00172         !(siCObject->dwAttributes & SIC_LAUNCHAPP))
00173       dwTotalFiles += siCObject->iFileCount;
00174 
00175     siCObject = SiCNodeGetObject(++i, TRUE, AC_ALL);
00176   }
00177 }
00178 
00179 char *GetErrorString(DWORD dwError, char *szErrorString, DWORD dwErrorStringSize)
00180 {
00181   int  i = 0;
00182   char szErrorNumber[MAX_BUF];
00183 
00184   ZeroMemory(szErrorString, dwErrorStringSize);
00185   itoa(dwError, szErrorNumber, 10);
00186 
00187   /* map the error value to a string */
00188   while(TRUE)
00189   {
00190     if(*XpErrorList[i] == '\0')
00191       break;
00192 
00193     if(lstrcmpi(szErrorNumber, XpErrorList[i]) == 0)
00194     {
00195       if(*XpErrorList[i + 1] != '\0')
00196         lstrcpy(szErrorString, XpErrorList[i + 1]);
00197 
00198       break;
00199     }
00200 
00201     ++i;
00202   }
00203 
00204   return(szErrorString);
00205 }
00206 
00207 HRESULT SmartUpdateJars(HWND aWizardPanel)
00208 {
00209   DWORD     i = 0;
00210   siC       *siCObject = NULL;
00211   HRESULT   hrResult;
00212   char      szBuf[MAX_BUF];
00213   char      szEXpiInstall[MAX_BUF];
00214   char      szArchive[MAX_BUF];
00215   char      szMsgSmartUpdateStart[MAX_BUF];
00216   char      szDlgExtractingTitle[MAX_BUF];
00217   char      xpinstallPath[MAX_BUF];
00218   char      xpiArgs[MAX_BUF];
00219 
00220   // Save the handle to the dialog window so the installer procedures
00221   // can send messages to it. 
00222   dlgInfo.hWndDlg = aWizardPanel;
00223 
00224   if (!GetPrivateProfileString("Messages", "DLG_EXTRACTING_TITLE", 
00225                                "", szDlgExtractingTitle, 
00226                                sizeof(szDlgExtractingTitle), 
00227                                szFileIniInstall))
00228     return 1;
00229 
00230   if (!GetPrivateProfileString("Messages", "STR_PROCESSINGFILE", 
00231                                "", szStrProcessingFile, 
00232                                sizeof(szStrProcessingFile), 
00233                                szFileIniInstall) ||
00234       !GetPrivateProfileString("Messages", "STR_INSTALLING", 
00235                                "", szStrInstalling, 
00236                                sizeof(szStrInstalling), 
00237                                szFileIniInstall) ||
00238       !GetPrivateProfileString("Messages", "STR_COPYINGFILE", 
00239                                "", szStrCopyingFile, 
00240                                sizeof(szStrCopyingFile), 
00241                                szFileIniInstall))
00242     exit(1);
00243 
00244   GetXpinstallPath(xpinstallPath, sizeof(xpinstallPath));
00245   if(InitializeXPIStub(xpinstallPath) == WIZ_OK)
00246   {
00247     LogISXPInstall(W_START);
00248     lstrcpy(szBuf, sgProduct.szPath);
00249     if(*sgProduct.szSubPath != '\0')
00250     {
00251       AppendBackSlash(szBuf, sizeof(szBuf));
00252       lstrcat(szBuf, sgProduct.szSubPath);
00253     }
00254     hrResult = pfnXpiInit(szBuf, FILE_INSTALL_LOG, cbXPIProgress);
00255 
00256     SetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS0, szMsgSmartUpdateStart);
00257 
00258     GetTotalArchivesToInstall();
00259 
00260     SendDlgItemMessage(dlgInfo.hWndDlg, IDC_PROGRESS_ARCHIVE, PBM_SETRANGE, 
00261                        0, MAKELPARAM(0, dwTotalFiles));
00262 
00263     dwCurrentFile = 0;
00264     siCObject = SiCNodeGetObject(i, TRUE, AC_ALL);
00265     while (siCObject) {
00266       if(siCObject->dwAttributes & SIC_SELECTED)
00267         /* Since the archive is selected, we need to process the file ops here */
00268          ProcessFileOps(T_PRE_ARCHIVE, siCObject->szReferenceName);
00269 
00270       /* launch smartupdate engine for earch jar to be installed */
00271       if((siCObject->dwAttributes & SIC_SELECTED)   &&
00272         !(siCObject->dwAttributes & SIC_LAUNCHAPP) &&
00273         !(siCObject->dwAttributes & SIC_DOWNLOAD_ONLY))
00274       {
00275         lFileCounter      = 0;
00276         lBarberCounter    = 0;
00277                        dlgInfo.nFileBars = 0;
00278 
00279         // We need to send this message otherwise the progress bars will paint
00280         // over the completion page for some unknown reason! -ben
00281         SendMessage(aWizardPanel, WM_PAINT, 0, 0);
00282 
00283         lstrcpy(szArchive, sgProduct.szAlternateArchiveSearchPath);
00284         AppendBackSlash(szArchive, sizeof(szArchive));
00285         lstrcat(szArchive, siCObject->szArchiveName);
00286         if((*sgProduct.szAlternateArchiveSearchPath == '\0') || (!FileExists(szArchive)))
00287         {
00288           lstrcpy(szArchive, szSetupDir);
00289           AppendBackSlash(szArchive, sizeof(szArchive));
00290           lstrcat(szArchive, siCObject->szArchiveName);
00291           if(!FileExists(szArchive))
00292           {
00293             lstrcpy(szArchive, szTempDir);
00294             AppendBackSlash(szArchive, sizeof(szArchive));
00295             lstrcat(szArchive, siCObject->szArchiveName);
00296             if(!FileExists(szArchive))
00297             {
00298               char szEFileNotFound[MAX_BUF];
00299 
00300               if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
00301               {
00302                 wsprintf(szBuf, szEFileNotFound, szArchive);
00303                 PrintError(szBuf, ERROR_CODE_HIDE);
00304               }
00305               return(1);
00306             }
00307           }
00308         }
00309 
00310         wsprintf(szBuf, szStrInstalling, siCObject->szDescriptionShort);
00311         SetDlgItemText(dlgInfo.hWndDlg, IDC_STATUS0, szBuf);
00312         LogISXPInstallComponent(siCObject->szDescriptionShort);
00313 
00314         /* XXX fix: we need to better support passing arguments to .xpi files.
00315          * This is a temporary hack to get greType passed to browser.xpi so that
00316          * it won't delete GRE files if GRE is installed in the mozilla dir.
00317          *
00318          * What should be done is have the arguments be described in each
00319          * component's section in config.ini and have it passed thru here. */
00320         *xpiArgs = '\0';
00321         if(lstrcmpi(siCObject->szArchiveName, "gre.xpi") == 0)
00322           MozCopyStr(sgProduct.szRegPath, xpiArgs, sizeof(xpiArgs));
00323         else if((lstrcmpi(siCObject->szArchiveName, "browser.xpi") == 0) &&
00324                 (sgProduct.greType == GRE_LOCAL))
00325           /* passing -greShared to browser.xpi will tell it to cleanup GRE files
00326            * from it's directory if they exist. */
00327           MozCopyStr("-greLocal", xpiArgs, sizeof(xpiArgs));
00328 
00329         hrResult = pfnXpiInstall(szArchive, xpiArgs, 0xFFFF);
00330         if(hrResult == E_REBOOT)
00331           bReboot = TRUE;
00332         else if((hrResult != WIZ_OK) &&
00333                !(siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
00334         {
00335           LogMSXPInstallStatus(siCObject->szArchiveName, hrResult);
00336           LogISXPInstallComponentResult(hrResult);
00337           if(GetPrivateProfileString("Messages", "ERROR_XPI_INSTALL", "", szEXpiInstall, sizeof(szEXpiInstall), szFileIniInstall))
00338           {
00339             char szErrorString[MAX_BUF];
00340 
00341             GetErrorString(hrResult, szErrorString, sizeof(szErrorString));
00342             wsprintf(szBuf, "%s - %s: %d %s", szEXpiInstall, siCObject->szDescriptionShort, hrResult, szErrorString);
00343             PrintError(szBuf, ERROR_CODE_HIDE);
00344           }
00345 
00346           /* break out of the siCObject while loop */
00347           break;
00348         }
00349 
00350         LogISXPInstallComponentResult(hrResult);
00351 
00352         if((hrResult != WIZ_OK) &&
00353           (siCObject->dwAttributes & SIC_IGNORE_XPINSTALL_ERROR))
00354           /* reset the result to WIZ_OK if there was an error and the
00355            * component's attributes contains SIC_IGNORE_XPINSTALL_ERROR.
00356            * This should be done after LogISXPInstallComponentResult()
00357            * because we still should log the error value. */
00358           hrResult = WIZ_OK;
00359       }
00360 
00361       if(siCObject->dwAttributes & SIC_SELECTED)
00362         /* Since the archive is selected, we need to do the file ops here */
00363          ProcessFileOps(T_POST_ARCHIVE, siCObject->szReferenceName);
00364 
00365       siCObject = SiCNodeGetObject(++i, TRUE, AC_ALL);
00366     } /* while(siCObject) */
00367 
00368     //report 100% progress status for successful installs
00369     UpdateGREInstallProgress(100);
00370     LogMSXPInstallStatus(NULL, hrResult);
00371     pfnXpiExit();
00372   }
00373 
00374   DeInitializeXPIStub();
00375   LogISXPInstall(W_END);
00376 
00377   return(hrResult);
00378 }
00379 
00380 void cbXPIStart(const char *URL, const char *UIName)
00381 {
00382 }
00383 
00384 void cbXPIProgress(const char* msg, PRInt32 val, PRInt32 max)
00385 {
00386   char szFilename[MAX_BUF];
00387   char szStrProcessingFileBuf[MAX_BUF];
00388   char szStrCopyingFileBuf[MAX_BUF];
00389 
00390   if(sgProduct.mode != SILENT)
00391   {
00392     ParsePath((char *)msg, szFilename, sizeof(szFilename), FALSE, PP_FILENAME_ONLY);
00393 
00394     dlgInfo.nFileBars = 0;
00395     
00396     // XXXben this is a really nasty hack. We shouldn't be parsing the msg value
00397     // to find out what sort of progress notification this is. Really, the installer
00398     // listener system needs to be rearchitected to send out a message type (int) 
00399     // and a message value, and the listeners can synthesize a display message if
00400     // they want to. As it stands, the strings that are used here are NOT localizable
00401     // (hard coded over in mozilla/xpinstall/src), which blows dead goats through
00402     // straws. 
00403     if ((!strncmp(msg, "Installing: ", 12) ||
00404          !strncmp(msg, "Replacing: ", 11)) 
00405          && (max != 0 && val <= max)) {
00406       ++dwCurrentFile;
00407 
00408       UpdateArchiveInstallProgress((int)dwCurrentFile);
00409       UpdateGREInstallProgress((int)dwCurrentFile);
00410     }
00411 
00412     ProcessWindowsMessages();
00413   }
00414 }
00415 
00416 void cbXPIFinal(const char *URL, PRInt32 finalStatus)
00417 {
00418 }
00419 
00420 
00421 
00422 // Update the Archive Progress Bar to the specified percentage. 
00423 static void UpdateArchiveInstallProgress(int aValue)
00424 {
00425   if (sgProduct.mode != SILENT) {
00426     SendDlgItemMessage(dlgInfo.hWndDlg, IDC_PROGRESS_ARCHIVE, PBM_SETPOS, 
00427                        (WPARAM)aValue, 0);
00428     Sleep(5);
00429   }
00430 }
00431