Back to index

lightning-sunbird  0.9+nobinonly
XPInstallGlue.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; 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) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@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 "MacInstallWizard.h"
00041 
00042 #define XP_MAC 1
00043 #include "xpistub.h"
00044 
00045 /*-----------------------------------------------------------*
00046  *   XPInstall Glue
00047  *-----------------------------------------------------------*/
00048 
00049 /*================== XPI Stub Entry Points ================== */
00050 typedef              nsresult (*XPI_InitProc)(const FSSpec& aXPIStubDir, const FSSpec& aProgramDir, const char* aLogName, pfnXPIProgress progressCB);
00051 typedef       nsresult (*XPI_InstallProc)(const FSSpec& file, const char* args,long flags);
00052 typedef              nsresult (*XPI_ExitProc)();
00053 
00054 /*================== XPI Run APIs ============================*/
00055 OSErr         LoadXPIStub(XPI_InitProc* pfnInit, 
00056                                           XPI_InstallProc* pfnInstall, 
00057                                           XPI_ExitProc* pfnExit, 
00058                                           CFragConnectionID* connID,
00059                                           FSSpec& aTargetDir, Str255 msg);
00060 Boolean              UnloadXPIStub(CFragConnectionID* connID);
00061 OSErr         RunXPI(FSSpec&, XPI_InstallProc*);
00062 int                  CountSelectedXPIs();
00063 Boolean              IsArchiveXPI(StringPtr archive);
00064 void          ProgressMsgInit();
00065 
00066 /*================== Progress Bar Callbacks ==================*/
00067 void          xpicbProgress(const char* msg, PRInt32 val, PRInt32 max);
00068 
00069 /*================== Macros ==================================*/
00070 #define XPI_ERR_CHECK(_call)       \
00071 rv = _call;                                      \
00072 if (NS_FAILED(rv))                        \
00073 {                                                       \
00074        ErrorHandler(rv, nil);                    \
00075        return rv;                                \
00076 }
00077 
00078 #ifdef MIW_DEBUG
00079 #define XPISTUB_DLL "\pxpistubDebug.shlb"
00080 #else
00081 #define XPISTUB_DLL "\pxpistub.shlb"
00082 #endif
00083 
00084 static Boolean bMaxDiscovered = false;
00085 static Boolean bProgMsgInit = false;
00086 
00087 void          
00088 ProgressMsgInit()
00089 {
00090        Rect   r;
00091        
00092        if (gControls->tw->allProgressMsg)
00093        {
00094               HLock((Handle)gControls->tw->allProgressMsg);
00095               SetRect(&r, (*gControls->tw->allProgressMsg)->viewRect.left,
00096                             (*gControls->tw->allProgressMsg)->viewRect.top,
00097                             (*gControls->tw->allProgressMsg)->viewRect.right,
00098                             (*gControls->tw->allProgressMsg)->viewRect.bottom );
00099               HUnlock((Handle)gControls->tw->allProgressMsg);
00100               
00101               TESetText("", 0, gControls->tw->allProgressMsg);
00102               
00103               EraseRect(&r);
00104        }
00105        
00106        bProgMsgInit = true;
00107        
00108        return;
00109 }
00110 
00111 void   
00112 xpicbProgress(const char* msg, PRInt32 val, PRInt32 max)
00113 {
00114        Boolean indeterminateFlag = false;
00115        Rect   r;
00116        Str255 installingStr, fileStr, ofStr;
00117        char   *valStr, *maxStr, *leaf;
00118        StringPtr     pleaf = nil;
00119        long          last;
00120        GrafPtr oldPort;
00121        GetPort(&oldPort);
00122        
00123        if (gWPtr)
00124        {
00125               SetPort(gWPtr);
00126               if (gControls->tw->xpiProgressBar)
00127               {
00128                      if (!bProgMsgInit)
00129                             ProgressMsgInit();
00130                             
00131                      if (max!=0 && !bMaxDiscovered)
00132                      {
00133                             SetControlData(gControls->tw->xpiProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag,
00134                                                         sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
00135                             SetControlMaximum(gControls->tw->xpiProgressBar, max);
00136                             if (gControls->tw->allProgressBar)
00137                                    SetControlValue(gControls->tw->allProgressBar,
00138                                                                GetControlValue(gControls->tw->allProgressBar)+1);
00139                                                                
00140                             bMaxDiscovered = true;
00141                      }
00142                      else if (!bMaxDiscovered)
00143                      {
00144                             if (gWPtr)
00145                                    IdleControls(gWPtr);
00146                             if (gControls->tw->xpiProgressMsg)
00147                             {      
00148                                    HLock((Handle)gControls->tw->xpiProgressMsg);
00149                                    SetRect(&r, (*gControls->tw->xpiProgressMsg)->viewRect.left,
00150                                                         (*gControls->tw->xpiProgressMsg)->viewRect.top,
00151                                                         (*gControls->tw->xpiProgressMsg)->viewRect.right,
00152                                                         (*gControls->tw->xpiProgressMsg)->viewRect.bottom );
00153                                    HUnlock((Handle)gControls->tw->xpiProgressMsg);
00154                                    if (msg)
00155                                    {
00156                                           EraseRect(&r);
00157                                           
00158                                           GetResourcedString(installingStr, rInstList, sProcessing);
00159                                           leaf = strrchr(msg, ':');
00160                                           if (leaf)
00161                                           {
00162                                                  pleaf = CToPascal(leaf+1);
00163                                                  pstrcat(installingStr, pleaf);
00164                                           }
00165                                           else
00166                                           {
00167                                                  installingStr[0] = 1;
00168                                                  installingStr[1] = ' ';
00169                                           }
00170                                           
00171                                           last = installingStr[0] + 1;
00172                                           if (last > 255)
00173                                                  last = 255;
00174                                           installingStr[last] = 0;
00175                                           
00176                                           if (installingStr[0] > 0)   
00177                                                  TESetText(&installingStr[1], installingStr[0], gControls->tw->xpiProgressMsg);
00178                                                  
00179                                           TEUpdate(&r, gControls->tw->xpiProgressMsg);
00180                                           
00181                                           if (pleaf)
00182                                                  DisposePtr((Ptr) pleaf);
00183                                    }
00184                             }
00185                      }
00186                      
00187                      if (bMaxDiscovered)
00188                      {
00189                             SetControlValue(gControls->tw->xpiProgressBar, val);
00190                             
00191                             if (gControls->tw->xpiProgressMsg)
00192                             {
00193                                    GetResourcedString(installingStr, rInstList, sProcessing);
00194                                    GetResourcedString(fileStr, rInstList, sFileSp);
00195                                    GetResourcedString(ofStr, rInstList, sSpOfSp);
00196                                    HLock((Handle)gControls->tw->xpiProgressMsg);
00197                                    SetRect(&r, (*gControls->tw->xpiProgressMsg)->viewRect.left,
00198                                                         (*gControls->tw->xpiProgressMsg)->viewRect.top,
00199                                                         (*gControls->tw->xpiProgressMsg)->viewRect.right,
00200                                                         (*gControls->tw->xpiProgressMsg)->viewRect.bottom );
00201                                    HUnlock((Handle)gControls->tw->xpiProgressMsg);
00202                                                                
00203                                    valStr = ltoa(val);
00204                                    maxStr = ltoa(max);
00205                             
00206                                    EraseRect(&r);
00207                                    if (valStr && maxStr)
00208                                    {
00209                                           TESetText(&installingStr[1], installingStr[0], gControls->tw->xpiProgressMsg);
00210                                           TEInsert(&fileStr[1], fileStr[0], gControls->tw->xpiProgressMsg);
00211                                           TEInsert(valStr, strlen(valStr), gControls->tw->xpiProgressMsg);
00212                                           TEInsert(&ofStr[1], ofStr[0], gControls->tw->xpiProgressMsg);
00213                                           TEInsert(maxStr, strlen(maxStr), gControls->tw->xpiProgressMsg);
00214                                           TEUpdate(&r, gControls->tw->xpiProgressMsg);
00215                                    }
00216                                    
00217                                    if (valStr)
00218                                           free(valStr);
00219                                    if (maxStr)
00220                                           free(maxStr);
00221                             }
00222                      }
00223               }
00224        }
00225        
00226        SetPort(oldPort);
00227        return;
00228 }
00229 
00230 OSErr
00231 RunAllXPIs(short xpiVRefNum, long xpiDirID, short vRefNum, long dirID)
00232 {
00233        OSErr                       err = noErr;
00234        FSSpec                      tgtDirSpec, xpiStubDirSpec, xpiSpec;
00235        XPI_InitProc         xpi_initProc;
00236        XPI_InstallProc             xpi_installProc;
00237        XPI_ExitProc         xpi_exitProc;
00238        CFragConnectionID    connID;
00239        nsresult                    rv = NS_OK;
00240        StringPtr                   pcurrArchive;
00241        int                                i, len, compsDone = 0, numXPIs, currXPICount = 0, instChoice = gControls->opt->instChoice-1;
00242        Boolean                            isCurrXPI = false, indeterminateFlag = false;
00243        Str255                      installingStr, msg;
00244        StringPtr           pTargetSubfolder = "\p"; /* subfolder is optional so init empty */
00245        long                dummyDirID = 0;
00246        
00247     err = FSMakeFSSpec(vRefNum, dirID, kViewerFolder, &xpiStubDirSpec); /* xpistub dir */
00248     if (gControls->cfg->targetSubfolder)
00249     {
00250         HLock(gControls->cfg->targetSubfolder);
00251         if (*gControls->cfg->targetSubfolder)
00252             pTargetSubfolder = CToPascal(*gControls->cfg->targetSubfolder);
00253         HUnlock(gControls->cfg->targetSubfolder);
00254     }
00255     err = FSMakeFSSpec(gControls->opt->vRefNum, gControls->opt->dirID, /* program dir */
00256                           pTargetSubfolder, &tgtDirSpec);
00257        if (err == fnfErr)
00258            err = FSpDirCreate(&tgtDirSpec, smSystemScript, &dummyDirID);
00259            
00260        if (err != noErr)
00261     {
00262         ErrorHandler(err, nil);
00263         return err;
00264     }
00265 
00266        ERR_CHECK_MSG(LoadXPIStub(&xpi_initProc, &xpi_installProc, &xpi_exitProc, &connID, xpiStubDirSpec, msg), err, msg);
00267        XPI_ERR_CHECK(xpi_initProc( xpiStubDirSpec, tgtDirSpec, NULL, xpicbProgress ));
00268            
00269        // init overall xpi indicator
00270        numXPIs = CountSelectedXPIs();
00271        if (gControls->tw->allProgressBar)
00272        {
00273               SetControlMaximum(gControls->tw->allProgressBar, numXPIs*2); // numXPIs * 2 so that prog bar moves more
00274               SetControlData(gControls->tw->allProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag,
00275                                           sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
00276               SetControlValue(gControls->tw->allProgressBar, 0);
00277               Draw1Control(gControls->tw->allProgressBar);
00278        }
00279        
00280        if (gControls->tw->xpiProgressBar)
00281               ShowControl(gControls->tw->xpiProgressBar);
00282               
00283        // enumerate through all .xpi's
00284        // loop through 0 to kMaxComponents
00285        for(i=0; i<kMaxComponents; i++)
00286        {
00287            BreathFunc();
00288               // general test: if component in setup type
00289               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
00290                       (compsDone < gControls->cfg->st[instChoice].numComps) )
00291               { 
00292                      // if custom and selected, or not custom setup type
00293                      // add file to buffer
00294                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
00295                               (gControls->cfg->comp[i].selected == true)) ||
00296                              (instChoice < gControls->cfg->numSetupTypes-1) )
00297                      {
00298                             // if LAUNCHAPP and DOWNLOAD_ONLY attr wasn't set
00299                             if (!gControls->cfg->comp[i].launchapp && !gControls->cfg->comp[i].download_only)
00300                             {
00301                                    HLock(gControls->cfg->comp[i].archive);
00302                                    pcurrArchive = CToPascal(*gControls->cfg->comp[i].archive);
00303                                    HUnlock(gControls->cfg->comp[i].archive);
00304               
00305                                    isCurrXPI = IsArchiveXPI(pcurrArchive);
00306                                                         
00307                                    err = FSMakeFSSpec(xpiVRefNum, xpiDirID, pcurrArchive, &xpiSpec);
00308                                    if (err==noErr && isCurrXPI)
00309                                    {
00310                                           // update package display name
00311                                           if (gControls->tw->allProgressMsg)
00312                                           {
00313                                                  ProgressMsgInit();
00314                                                  GetResourcedString(installingStr, rInstList, sInstalling);
00315                                                  TEInsert(&installingStr[1], installingStr[0], gControls->tw->allProgressMsg);
00316                                                  HLock(gControls->cfg->comp[i].shortDesc);
00317                                                  len = strlen(*gControls->cfg->comp[i].shortDesc);
00318                                                  TEInsert(*gControls->cfg->comp[i].shortDesc, (len>64?64:len), gControls->tw->allProgressMsg);
00319                                                  HUnlock(gControls->cfg->comp[i].shortDesc);
00320                                           }
00321                                           
00322                                           err = RunXPI(xpiSpec, &xpi_installProc);
00323                                           BreathFunc();
00324                                           if (err != NS_OK)
00325                                               break;
00326                                           
00327                                           // update progess bar
00328                                           if (gControls->tw->allProgressBar)
00329                                                  SetControlValue(gControls->tw->allProgressBar,
00330                                                                              GetControlValue(gControls->tw->allProgressBar)+1);
00331                                    }
00332                                    if (pcurrArchive)
00333                                           DisposePtr((Ptr) pcurrArchive);
00334                             }
00335                             compsDone++;
00336                      }
00337               }
00338               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
00339                      break;  
00340        }
00341        
00342        xpi_exitProc();      
00343        UnloadXPIStub(&connID);
00344        
00345     if (pTargetSubfolder)
00346            DisposePtr((Ptr)pTargetSubfolder);
00347        return err;
00348 }
00349 
00350 OSErr
00351 RunXPI(FSSpec& aXPI, XPI_InstallProc *xpi_installProc)
00352 {      
00353        nsresult      rv;
00354        OSErr         err = noErr;
00355        long          flags = 0x1000; /* XPI_NO_NEW_THREAD = 0x1000 from nsISoftwareUpdate.h */
00356        Boolean              indeterminateFlag = true;
00357        
00358        XPI_ERR_CHECK((*xpi_installProc)( aXPI, "", flags ));
00359        
00360        /* reset progress bar to barber poll */
00361        bMaxDiscovered = false;
00362        if (gControls->tw->xpiProgressBar)
00363               SetControlData(gControls->tw->xpiProgressBar, kControlNoPart, kControlProgressBarIndeterminateTag,
00364                                           sizeof(indeterminateFlag), (Ptr) &indeterminateFlag);
00365        if (NS_FAILED(rv))
00366               return -1;
00367 
00368 
00369        return err;
00370 }
00371 
00372 int
00373 CountSelectedXPIs()
00374 {
00375        int i, instChoice = gControls->opt->instChoice - 1, compsDone = 0, numXPIs = 0;
00376        
00377        // enumerate through all .xpi's
00378        // loop through 0 to kMaxComponents
00379        for(i=0; i<kMaxComponents; i++)
00380        {
00381               // general test: if component in setup type
00382               if ( (gControls->cfg->st[instChoice].comp[i] == kInSetupType) &&
00383                       (compsDone < gControls->cfg->st[instChoice].numComps) )
00384               { 
00385                      // if custom and selected, or not custom setup type
00386                      // add file to buffer
00387                      if ( ((instChoice == gControls->cfg->numSetupTypes-1) && 
00388                               (gControls->cfg->comp[i].selected == true)) ||
00389                              (instChoice < gControls->cfg->numSetupTypes-1) )
00390                      {
00391                             // if LAUNCHAPP and DOWNLOAD_ONLY attr wasn't set
00392                             if (!gControls->cfg->comp[i].launchapp && !gControls->cfg->comp[i].download_only)
00393                                    numXPIs++;
00394                      }
00395               }
00396               else if (compsDone >= gControls->cfg->st[instChoice].numComps)
00397                      break;  
00398        }
00399        
00400        return numXPIs;
00401 }
00402 
00403 /*-------------------------------------------------------------------
00404  *   XPI Stub Load/Unload
00405  *-------------------------------------------------------------------*/
00406 OSErr
00407 LoadXPIStub(XPI_InitProc* pfnInit, XPI_InstallProc* pfnInstall, XPI_ExitProc* pfnExit, 
00408                      CFragConnectionID* connID, FSSpec& aTargetDir, Str255 errName)
00409 {
00410        OSErr                       err;
00411        FSSpec                      fslib;
00412        Str63                       fragName = XPISTUB_DLL;
00413        Ptr                                mainAddr, symAddr;
00414        CFragSymbolClass     symClass;
00415        long                        tgtDirID;
00416        Boolean                     isDir;
00417        
00418        err = FSpGetDirectoryID( &aTargetDir, &tgtDirID, &isDir );
00419        if (err!=noErr)
00420               return err;
00421        else if (!isDir)
00422               return paramErr;
00423               
00424        err = FSMakeFSSpec(aTargetDir.vRefNum, tgtDirID, fragName, &fslib);
00425        if (err!=noErr)
00426               return err;
00427               
00428        err = GetDiskFragment(&fslib, 0, kCFragGoesToEOF, nil, /*kPrivateCFragCopy*/kReferenceCFrag, connID, &mainAddr, errName);
00429                                                                          
00430        if ( err == noErr && *connID != NULL)
00431        {
00432               ERR_CHECK_RET( FindSymbol(*connID, "\pXPI_Init", &symAddr, &symClass), err );
00433               *pfnInit = (XPI_InitProc) symAddr;
00434               
00435               ERR_CHECK_RET( FindSymbol(*connID, "\pXPI_Install", &symAddr, &symClass), err);
00436               *pfnInstall = (XPI_InstallProc) symAddr;
00437               
00438               ERR_CHECK_RET( FindSymbol(*connID, "\pXPI_Exit", &symAddr, &symClass), err);
00439               *pfnExit = (XPI_ExitProc) symAddr;
00440        }
00441        
00442        return err;
00443 }
00444 
00445 Boolean
00446 UnloadXPIStub(CFragConnectionID* connID)
00447 {
00448     if ((connID != NULL) && (*connID != NULL))
00449        {
00450               CloseConnection(connID);
00451               *connID = NULL;
00452            return true;
00453        }
00454        
00455        return false; 
00456 }
00457 
00458 Boolean 
00459 IsArchiveXPI(StringPtr archive)
00460 {
00461        long   len = *archive;
00462        char   *extStart = (char*)(&archive[1] + len - 4); /* extension length of ".xpi" = 4 */
00463        
00464        if (strncmp(extStart, ".xpi", 4) == 0)
00465               return true;
00466        
00467        return false;
00468 }