Back to index

lightning-sunbird  0.9+nobinonly
extra.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  *   Curt Patrick <curt@netscape.com>
00026  *   Ben Goodger <ben@mozilla.org>
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "extern.h"
00043 #include "extra.h"
00044 #include "process.h"
00045 #include "dialogs.h"
00046 #include "ifuncns.h"
00047 #include "xpnetHook.h"
00048 #include "time.h"
00049 #include "xpi.h"
00050 #include "logging.h"
00051 #include "nsEscape.h"
00052 #include <logkeys.h>
00053 #include <winnls.h>
00054 #include <winver.h>
00055 
00056 // shellapi.h is needed to build with WIN32_LEAN_AND_MEAN
00057 #include <shellapi.h>
00058 
00059 #define HIDWORD(l)   ((DWORD) (((ULONG) (l) >> 32) & 0xFFFF))
00060 #define LODWORD(l)   ((DWORD) (l))
00061 
00062 #define DEFAULT_ICON_SIZE   32
00063 
00064 #define FTPSTR_LEN (sizeof(szFtp) - 1)
00065 #define HTTPSTR_LEN (sizeof(szHttp) - 1)
00066 
00067 ULONG  (PASCAL *NS_GetDiskFreeSpace)(LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
00068 ULONG  (PASCAL *NS_GetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00069 HRESULT InitGre(greInfo *gre);
00070 void    DeInitGre(greInfo *gre);
00071 void    UpdateGreInstallerCmdLine(greInfo *aGre, char *aParameter, DWORD aParameterBufSize, BOOL forExistingGre);
00072 void    LaunchExistingGreInstaller(greInfo *gre);
00073 HRESULT GetInstalledGreConfigIni(greInfo *aGre, char *aGreConfigIni, DWORD aGreConfigIniBufSize);
00074 HRESULT GetInfoFromInstalledGreConfigIni(greInfo *aGre);
00075 HRESULT DetermineGreComponentDestinationPath(char *aInPath, char *aOutPath, DWORD aOutPathBufSize);
00076 BOOL    IsOkToRemoveFileOrDirname(char *aFileOrDirname, char **aListToIgnore,
00077 int     aListToIgnoreLength, char **aListProfileObjects, int aListProfileLength);
00078 int     GetTotalNumKeys(char *aSectionName, char *aBaseKeyName);
00079 void    CleanupArrayList(char **aList, int aListLength);
00080 char    **BuildArrayList(char *aSectionName, char *aBaseKeyName, int *aArrayLength);
00081 BOOL    IsDirAProfileDir(char *aParentPath, char **aListProfileObjects, int aListLength);
00082 
00083 static greInfo gGre;
00084 
00085 char *ArchiveExtensions[] = {"zip",
00086                              "xpi",
00087                              "jar",
00088                              ""};
00089 
00090 // Path and filename to the GRE's uninstaller.  This is used to cleanup
00091 // old versions of GRE that have been orphaned when upgrading mozilla.
00092 #define GRE_UNINSTALLER_FILE "[WINDIR]\\GREUninstall.exe"
00093 
00094 #define GRE_REG_KEY "Software\\mozilla.org\\GRE"
00095 #define SETUP_STATE_REG_KEY "Software\\%s\\%s\\%s\\Setup"
00096 #define APP_PATHS_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s"
00097 
00098 //GRE app installer progress bar integration
00099 typedef LONG (CALLBACK* LPFNDLLFUNC)(LPCTSTR,INT);
00100 
00101 #define GRE_APP_INSTALLER_PROXY_DLL      "ProgUpd.dll"
00102 #define GRE_PROXY_UPD_FUNC               "StdUpdateProgress"
00103 #define GRE_INSTALLER_ID                 "gre"
00104 
00105 #define FOR_EXISTING_GRE                 TRUE
00106 #define FOR_NEW_GRE                      FALSE
00107 
00108 LPSTR szProxyDLLPath;
00109 LPFNDLLFUNC lpfnProgressUpd;
00110 HINSTANCE hGREAppInstallerProxyDLL;
00111 
00112 BOOL gGreInstallerHasRun = FALSE;
00113 
00114 BOOL InitDialogClass(HINSTANCE hInstance, HINSTANCE hSetupRscInst)
00115 {
00116   WNDCLASS  wc;
00117 
00118   wc.style         = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
00119   wc.lpfnWndProc   = DefDlgProc;
00120   wc.cbClsExtra    = 0;
00121   wc.cbWndExtra    = DLGWINDOWEXTRA;
00122   wc.hInstance     = hSetupRscInst;
00123   wc.hIcon         = LoadIcon(hSetupRscInst, MAKEINTRESOURCE(IDI_SETUP));
00124   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
00125   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
00126   wc.lpszMenuName  = NULL;
00127   wc.lpszClassName = CLASS_NAME_SETUP_DLG;
00128 
00129   return(RegisterClass(&wc));
00130 }
00131 
00132 BOOL InitApplication(HINSTANCE hInstance, HINSTANCE hSetupRscInst)
00133 {
00134   BOOL     bRv;
00135   WNDCLASS wc;
00136 
00137   wc.style         = CS_HREDRAW | CS_VREDRAW | CS_PARENTDC | CS_SAVEBITS;
00138   wc.lpfnWndProc   = DefWindowProc;
00139   wc.cbClsExtra    = 0;
00140   wc.cbWndExtra    = 0;
00141   wc.hInstance     = hInstance;
00142   wc.hIcon         = LoadIcon(hSetupRscInst, MAKEINTRESOURCE(IDI_SETUP));
00143   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
00144   wc.hbrBackground = (HBRUSH)(COLOR_ACTIVECAPTION + 1);
00145   wc.lpszMenuName  = NULL;
00146   wc.lpszClassName = CLASS_NAME_SETUP;
00147 
00148   bRv = RegisterClass(&wc);
00149   if(bRv == FALSE)
00150     return(bRv);
00151 
00152   return(InitDialogClass(hInstance, hSetupRscInst));
00153 }
00154 
00155 BOOL InitInstance(HINSTANCE hInstance, DWORD dwCmdShow)
00156 {
00157   HWND hWnd;
00158 
00159   gSystemInfo.dwScreenX = GetSystemMetrics(SM_CXSCREEN);
00160   gSystemInfo.dwScreenY = GetSystemMetrics(SM_CYSCREEN);
00161 
00162   gSystemInfo.lastWindowPosCenterX = gSystemInfo.dwScreenX / 2;
00163   gSystemInfo.lastWindowPosCenterY = gSystemInfo.dwScreenY / 2;
00164 
00165   hInst = hInstance;
00166 
00167   /* This window is only for the purpose of allowing the self-extracting .exe
00168    * code to detect that a setup.exe is currenly running and do the appropriate
00169    * action given certain conditions.  This window is created and left in the
00170    * invisible state.
00171    * There's no other purpose for this window at this time.
00172    */
00173   hWnd = CreateWindow(CLASS_NAME_SETUP,
00174                       DEFAULT_SETUP_WINDOW_NAME,
00175                       WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
00176                       -150,
00177                       -50,
00178                       1,
00179                       1,
00180                       NULL,
00181                       NULL,
00182                       hInstance,
00183                       NULL);
00184 
00185   if(!hWnd)
00186     return(FALSE);
00187 
00188   hWndMain = NULL;
00189 
00190   return(TRUE);
00191 }
00192 
00193 void PrintError(LPSTR szMsg, DWORD dwErrorCodeSH)
00194 {
00195   DWORD dwErr;
00196   char  szErrorString[MAX_BUF];
00197 
00198   if(dwErrorCodeSH == ERROR_CODE_SHOW)
00199   {
00200     dwErr = GetLastError();
00201     wsprintf(szErrorString, "%d : %s", dwErr, szMsg);
00202   }
00203   else
00204     wsprintf(szErrorString, "%s", szMsg);
00205 
00206   if((sgProduct.mode != SILENT) && (sgProduct.mode != AUTO))
00207   {
00208     MessageBox(hWndMain, szErrorString, NULL, MB_ICONEXCLAMATION);
00209   }
00210   else if(sgProduct.mode == AUTO)
00211   {
00212     ShowMessage(szErrorString, TRUE);
00213     Delay(5);
00214     ShowMessage(szErrorString, FALSE);
00215   }
00216 }
00217 
00218 /* Windows API does offer a GlobalReAlloc() routine, but it kept
00219  * returning an out of memory error for subsequent calls to it
00220  * after the first time, thus the reason for this routine. */
00221 void *NS_GlobalReAlloc(HGLOBAL *hgMemory,
00222                        DWORD dwMemoryBufSize,
00223                        DWORD dwNewSize)
00224 {
00225   HGLOBAL hgPtr = NULL;
00226 
00227   if((hgPtr = NS_GlobalAlloc(dwNewSize)) == NULL)
00228     return(NULL);
00229   else
00230   {
00231     memcpy(hgPtr, *hgMemory, dwMemoryBufSize);
00232     FreeMemory(hgMemory);
00233     *hgMemory = hgPtr;
00234     return(hgPtr);
00235   }
00236 }
00237 
00238 void *NS_GlobalAlloc(DWORD dwMaxBuf)
00239 {
00240   void *vBuf = NULL;
00241 
00242   if((vBuf = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, dwMaxBuf)) == NULL)
00243   {     
00244     if((szEGlobalAlloc == NULL) || (*szEGlobalAlloc == '\0'))
00245       PrintError(TEXT("Memory allocation error."), ERROR_CODE_HIDE);
00246     else
00247       PrintError(szEGlobalAlloc, ERROR_CODE_SHOW);
00248 
00249     return(NULL);
00250   }
00251   else
00252     return(vBuf);
00253 }
00254 
00255 void FreeMemory(void **vPointer)
00256 {
00257   if(*vPointer != NULL)
00258     *vPointer = GlobalFree(*vPointer);
00259 }
00260 
00261 HRESULT NS_LoadStringAlloc(HANDLE hInstance, DWORD dwID, LPSTR *szStringBuf, DWORD dwStringBuf)
00262 {
00263   char szBuf[MAX_BUF];
00264 
00265   if((*szStringBuf = NS_GlobalAlloc(MAX_BUF)) == NULL)
00266     exit(1);
00267   
00268   if(!LoadString(hInstance, dwID, *szStringBuf, dwStringBuf))
00269   {
00270     if((szEStringLoad == NULL) ||(*szEStringLoad == '\0'))
00271       wsprintf(szBuf, "Could not load string resource ID %d", dwID);
00272     else
00273       wsprintf(szBuf, szEStringLoad, dwID);
00274 
00275     PrintError(szBuf, ERROR_CODE_SHOW);
00276     return(1);
00277   }
00278   return(0);
00279 }
00280 
00281 HRESULT NS_LoadString(HANDLE hInstance, DWORD dwID, LPSTR szStringBuf, DWORD dwStringBuf)
00282 {
00283   char szBuf[MAX_BUF];
00284 
00285   if(!LoadString(hInstance, dwID, szStringBuf, dwStringBuf))
00286   {
00287     if((szEStringLoad == NULL) ||(*szEStringLoad == '\0'))
00288       wsprintf(szBuf, "Could not load string resource ID %d", dwID);
00289     else
00290       wsprintf(szBuf, szEStringLoad, dwID);
00291 
00292     PrintError(szBuf, ERROR_CODE_SHOW);
00293     return(1);
00294   }
00295   return(WIZ_OK);
00296 }
00297 
00298 void Delay(DWORD dwSeconds)
00299 {
00300   SleepEx(dwSeconds * 1000, FALSE);
00301 }
00302 
00303 BOOL VerifyRestrictedAccess(void)
00304 {
00305   char  szSubKey[MAX_BUF];
00306   char  szSubKeyToTest[] = "Software\\%s - Test Key";
00307   BOOL  bRv;
00308   DWORD dwDisp = 0;
00309   DWORD dwErr;
00310   HKEY  hkRv;
00311 
00312   wsprintf(szSubKey, szSubKeyToTest, sgProduct.szCompanyName);
00313   dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
00314                          szSubKey,
00315                          0,
00316                          NULL,
00317                          REG_OPTION_NON_VOLATILE,
00318                          KEY_WRITE,
00319                          NULL,
00320                          &hkRv,
00321                          &dwDisp);
00322   if(dwErr == ERROR_SUCCESS)
00323   {
00324     RegCloseKey(hkRv);
00325     switch(dwDisp)
00326     {
00327       case REG_CREATED_NEW_KEY:
00328         RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);
00329         break;
00330 
00331       case REG_OPENED_EXISTING_KEY:
00332         break;
00333     }
00334     bRv = FALSE;
00335   }
00336   else
00337     bRv = TRUE;
00338 
00339   return(bRv);
00340 }
00341 
00342 void SetInstallFilesVar(LPSTR szProdDir)
00343 {
00344   char szProgramPath[MAX_BUF];
00345 
00346   if(szProdDir[lstrlen(szProdDir) - 1] == '\\')
00347     wsprintf(szProgramPath, "%s%s", szProdDir, sgProduct.szProgramName);
00348   else
00349     wsprintf(szProgramPath, "%s\\%s", szProdDir, sgProduct.szProgramName);
00350 
00351   if((!gbForceInstall) && FileExists(szProgramPath))
00352     sgProduct.bInstallFiles = FALSE;
00353 }
00354 
00355 void UnsetSetupState(void)
00356 {
00357   char szKey[MAX_BUF_TINY];
00358 
00359   wsprintf(szKey,
00360            SETUP_STATE_REG_KEY,
00361            sgProduct.szCompanyName,
00362            sgProduct.szProductNameInternal,
00363            sgProduct.szUserAgent);
00364   DeleteWinRegValue(HKEY_CURRENT_USER, szKey, "Setup State");
00365 }
00366 
00367 void SetSetupState(char *szState)
00368 {
00369   char szKey[MAX_BUF_TINY];
00370 
00371   wsprintf(szKey,
00372            SETUP_STATE_REG_KEY,
00373            sgProduct.szCompanyName,
00374            sgProduct.szProductNameInternal,
00375            sgProduct.szUserAgent);
00376 
00377   SetWinReg(HKEY_CURRENT_USER, szKey, TRUE, "Setup State", TRUE,
00378             REG_SZ, szState, lstrlen(szState), TRUE, FALSE);
00379 }
00380 
00381 DWORD GetPreviousUnfinishedState(void)
00382 {
00383   char szBuf[MAX_BUF_TINY];
00384   char szKey[MAX_BUF_TINY];
00385   DWORD dwRv = PUS_NONE;
00386 
00387   if(sgProduct.szCompanyName &&
00388      sgProduct.szProductNameInternal &&
00389      sgProduct.szUserAgent)
00390   {
00391     wsprintf(szKey,
00392              SETUP_STATE_REG_KEY,
00393              sgProduct.szCompanyName,
00394              sgProduct.szProductNameInternal,
00395              sgProduct.szUserAgent);
00396     GetWinReg(HKEY_CURRENT_USER, szKey, "Setup State", szBuf, sizeof(szBuf));
00397     if(lstrcmpi(szBuf, SETUP_STATE_DOWNLOAD) == 0)
00398       dwRv = PUS_DOWNLOAD;
00399     else if(lstrcmpi(szBuf, SETUP_STATE_UNPACK_XPCOM) == 0)
00400       dwRv = PUS_UNPACK_XPCOM;
00401     else if(lstrcmpi(szBuf, SETUP_STATE_INSTALL_XPI) == 0)
00402       dwRv = PUS_INSTALL_XPI;
00403   }
00404 
00405   return(dwRv);
00406 }
00407 
00408 void UnsetSetupCurrentDownloadFile(void)
00409 {
00410   char szKey[MAX_BUF];
00411 
00412   wsprintf(szKey,
00413            SETUP_STATE_REG_KEY,
00414            sgProduct.szCompanyName,
00415            sgProduct.szProductNameInternal,
00416            sgProduct.szUserAgent);
00417   DeleteWinRegValue(HKEY_CURRENT_USER,
00418                     szKey,
00419                     "Setup Current Download");
00420 }
00421 
00422 void SetSetupCurrentDownloadFile(char *szCurrentFilename)
00423 {
00424   char szKey[MAX_BUF];
00425 
00426   wsprintf(szKey,
00427            SETUP_STATE_REG_KEY,
00428            sgProduct.szCompanyName,
00429            sgProduct.szProductNameInternal,
00430            sgProduct.szUserAgent);
00431   SetWinReg(HKEY_CURRENT_USER,
00432             szKey,
00433             TRUE,
00434             "Setup Current Download",
00435             TRUE,
00436             REG_SZ,
00437             szCurrentFilename,
00438             lstrlen(szCurrentFilename),
00439             TRUE,
00440             FALSE);
00441 }
00442 
00443 char *GetSetupCurrentDownloadFile(char *szCurrentDownloadFile,
00444                                   DWORD dwCurrentDownloadFileBufSize)
00445 {
00446   char szKey[MAX_BUF];
00447 
00448   if(!szCurrentDownloadFile)
00449     return(NULL);
00450 
00451   ZeroMemory(szCurrentDownloadFile, dwCurrentDownloadFileBufSize);
00452   if(sgProduct.szCompanyName &&
00453      sgProduct.szProductNameInternal &&
00454      sgProduct.szUserAgent)
00455   {
00456     wsprintf(szKey,
00457              SETUP_STATE_REG_KEY,
00458              sgProduct.szCompanyName,
00459              sgProduct.szProductNameInternal,
00460              sgProduct.szUserAgent);
00461     GetWinReg(HKEY_CURRENT_USER,
00462               szKey,
00463               "Setup Current Download", 
00464               szCurrentDownloadFile,
00465               dwCurrentDownloadFileBufSize);
00466   }
00467 
00468   return(szCurrentDownloadFile);
00469 }
00470 
00471 void UpdateGREInstallProgress(int percent)
00472 {
00473   if (lpfnProgressUpd)
00474     lpfnProgressUpd(GRE_INSTALLER_ID, percent);
00475 }
00476 
00477 BOOL UpdateFile(char *szInFilename, char *szOutFilename, char *szIgnoreStr)
00478 {
00479   FILE *ifp;
00480   FILE *ofp;
00481   char szLineRead[MAX_BUF];
00482   char szLCIgnoreLongStr[MAX_BUF];
00483   char szLCIgnoreShortStr[MAX_BUF];
00484   char szLCLineRead[MAX_BUF];
00485   BOOL bFoundIgnoreStr = FALSE;
00486 
00487   if((ifp = fopen(szInFilename, "rt")) == NULL)
00488     return(bFoundIgnoreStr);
00489   if((ofp = fopen(szOutFilename, "w+t")) == NULL)
00490   {
00491     fclose(ifp);
00492     return(bFoundIgnoreStr);
00493   }
00494 
00495   if(lstrlen(szIgnoreStr) < sizeof(szLCIgnoreLongStr))
00496   {
00497     lstrcpy(szLCIgnoreLongStr, szIgnoreStr);
00498     CharLower(szLCIgnoreLongStr);
00499   }
00500   if(lstrlen(szIgnoreStr) < sizeof(szLCIgnoreShortStr))
00501   {
00502     GetShortPathName(szIgnoreStr, szLCIgnoreShortStr, sizeof(szLCIgnoreShortStr));
00503     CharLower(szLCIgnoreShortStr);
00504   }
00505 
00506   while(fgets(szLineRead, sizeof(szLineRead), ifp) != NULL)
00507   {
00508     lstrcpy(szLCLineRead, szLineRead);
00509     CharLower(szLCLineRead);
00510     if(!strstr(szLCLineRead, szLCIgnoreLongStr) && !strstr(szLCLineRead, szLCIgnoreShortStr))
00511       fputs(szLineRead, ofp);
00512     else
00513       bFoundIgnoreStr = TRUE;
00514   }
00515   fclose(ifp);
00516   fclose(ofp);
00517 
00518   return(bFoundIgnoreStr);
00519 }
00520 
00521 /* Function: RemoveDelayedDeleteFileEntries()
00522  *
00523  *       in: const char *aPathToMatch - path to match against
00524  *
00525  *  purpose: To remove windows registry entries (normally set by the uninstaller)
00526  *           that dictates what files to remove at system remove.
00527  *           The windows registry key that will be parsed is:
00528  *
00529  *             key : HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager
00530  *             name: PendingFileRenameOperations
00531  *
00532  *           This will not remove any entries that are set to be 'renamed'
00533  *           at system remove, only to be 'deleted'.
00534  *
00535  *           This function is multibyte safe.
00536  *
00537  *           To see what format the value of the var is in, look up the win32 API:
00538  *             MoveFileEx()
00539  */
00540 void RemoveDelayedDeleteFileEntries(const char *aPathToMatch)
00541 {
00542   HKEY  hkResult;
00543   DWORD dwErr;
00544   DWORD dwType = REG_NONE;
00545   DWORD oldMaxValueLen = 0;
00546   DWORD newMaxValueLen = 0;
00547   DWORD lenToEnd = 0;
00548   char  *multiStr = NULL;
00549   const char key[] = "SYSTEM\\CurrentControlSet\\Control\\Session Manager";
00550   const char name[] = "PendingFileRenameOperations";
00551   char  *pathToMatch;
00552   char  *lcName;
00553   char  *pName;
00554   char  *pRename;
00555   int   nameLen, renameLen;
00556 
00557   assert(aPathToMatch);
00558 
00559   /* if not NT systems (win2k, winXP) return */
00560   if (!(gSystemInfo.dwOSType & OS_NT))
00561     return;
00562 
00563   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ|KEY_WRITE, &hkResult) != ERROR_SUCCESS)
00564     return;
00565 
00566   dwErr = RegQueryValueEx(hkResult, name, 0, &dwType, NULL, &oldMaxValueLen);
00567   if (dwErr != ERROR_SUCCESS || oldMaxValueLen == 0 || dwType != REG_MULTI_SZ)
00568   {
00569     /* no value, no data, or wrong type */
00570     return;
00571   }
00572 
00573   multiStr = calloc(oldMaxValueLen, sizeof(BYTE));
00574   if (!multiStr)
00575     return;
00576 
00577   pathToMatch = strdup(aPathToMatch);
00578   if (!pathToMatch)
00579   {
00580       free(multiStr);
00581       return;
00582   }
00583 
00584   if (RegQueryValueEx(hkResult, name, 0, NULL, multiStr, &oldMaxValueLen) == ERROR_SUCCESS)
00585   {
00586       // The registry value consists of name/newname pairs of null-terminated
00587       // strings, with a final extra null termination. We're only interested
00588       // in files to be deleted, which are indicated by a null newname.
00589       CharLower(pathToMatch);
00590       lenToEnd = newMaxValueLen = oldMaxValueLen;
00591       pName = multiStr;
00592       while(*pName && lenToEnd > 0)
00593       {
00594           // find the locations and lengths of the current pair. Count the
00595           // nulls,  we need to know how much data to skip or move
00596           nameLen = strlen(pName) + 1;
00597           pRename = pName + nameLen;
00598           renameLen = strlen(pRename) + 1;
00599 
00600           // How much remains beyond the current pair
00601           lenToEnd -= (nameLen + renameLen);
00602 
00603           if (*pRename == '\0')
00604           {
00605               // No new name, it's a delete. Is it the one we want?
00606               lcName = strdup(pName);
00607               if (lcName)
00608               {
00609                   CharLower(lcName);
00610                   if (strstr(lcName, pathToMatch))
00611                   {
00612                       // It's a match--
00613                       // delete this pair by moving the remainder on top
00614                       memmove(pName, pRename + renameLen, lenToEnd);
00615 
00616                       // update the total length to reflect the missing pair
00617                       newMaxValueLen -= (nameLen + renameLen);
00618 
00619                       // next pair is in place, continue w/out moving pName
00620                       free(lcName);
00621                       continue;
00622                   }
00623                   free(lcName);
00624               }
00625           }
00626           // on to the next pair
00627           pName = pRename + renameLen;
00628       }
00629 
00630       if (newMaxValueLen != oldMaxValueLen)
00631       {
00632           // We've deleted something, save the changed data
00633           RegSetValueEx(hkResult, name, 0, REG_MULTI_SZ, multiStr, newMaxValueLen);
00634           RegFlushKey(hkResult);
00635       }
00636   }
00637 
00638   RegCloseKey(hkResult);
00639   free(multiStr);
00640   free(pathToMatch);
00641 }
00642 
00643 HRESULT Initialize(HINSTANCE hInstance)
00644 {
00645   char szBuf[MAX_BUF];
00646   char szCurrentProcessDir[MAX_BUF];
00647 
00648   bSDUserCanceled        = FALSE;
00649   hDlgMessage            = NULL;
00650 
00651   /* load strings from setup.exe */
00652   if(NS_LoadStringAlloc(hInstance, IDS_ERROR_GLOBALALLOC, &szEGlobalAlloc, MAX_BUF))
00653     return(1);
00654   if(NS_LoadStringAlloc(hInstance, IDS_ERROR_STRING_LOAD, &szEStringLoad,  MAX_BUF))
00655     return(1);
00656   if(NS_LoadStringAlloc(hInstance, IDS_ERROR_DLL_LOAD,    &szEDllLoad,     MAX_BUF))
00657     return(1);
00658   if(NS_LoadStringAlloc(hInstance, IDS_ERROR_STRING_NULL, &szEStringNull,  MAX_BUF))
00659     return(1);
00660   if(NS_LoadStringAlloc(hInstance, IDS_ERROR_OUTOFMEMORY, &szEOutOfMemory, MAX_BUF))
00661     return(1);
00662 
00663   GetModuleFileName(NULL, szBuf, sizeof(szBuf));
00664   ParsePath(szBuf, szCurrentProcessDir,
00665             sizeof(szCurrentProcessDir),
00666             FALSE,
00667             PP_PATH_ONLY);
00668   hAccelTable = LoadAccelerators(hInstance, CLASS_NAME_SETUP_DLG);
00669 
00670   if((hSetupRscInst = LoadLibraryEx("Setuprsc.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL)
00671   {
00672     char szFullFilename[MAX_BUF];
00673 
00674     lstrcpy(szFullFilename, szCurrentProcessDir);
00675     AppendBackSlash(szFullFilename, sizeof(szFullFilename));
00676     lstrcat(szFullFilename, "Setuprsc.dll");
00677     if((hSetupRscInst = LoadLibraryEx(szFullFilename, NULL, 0)) == NULL)
00678     {
00679       wsprintf(szBuf, szEDllLoad, szFullFilename);
00680       PrintError(szBuf, ERROR_CODE_HIDE);
00681       return(WIZ_ERROR_LOADING_RESOURCE_LIB);
00682     }
00683   }
00684 
00685   dwWizardState          = DLG_NONE;
00686   dwTempSetupType        = dwWizardState;
00687   siComponents           = NULL;
00688   bCreateDestinationDir  = FALSE;
00689   bReboot                = FALSE;
00690   gdwUpgradeValue        = UG_NONE;
00691   gdwSiteSelectorStatus  = SS_SHOW;
00692   gbILUseTemp            = TRUE;
00693   gbIgnoreRunAppX        = FALSE;
00694   gbIgnoreProgramFolderX = FALSE;
00695 
00696   if((szSetupDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00697     return(1);
00698   lstrcpy(szSetupDir, szCurrentProcessDir);
00699 
00700   if((szTempDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00701     return(1);
00702 
00703   if((szOSTempDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00704     return(1);
00705 
00706   if((szProxyDLLPath = NS_GlobalAlloc(MAX_BUF)) == NULL)
00707     return(1);
00708 
00709   if((szFileIniInstall = NS_GlobalAlloc(MAX_BUF)) == NULL)
00710     return(1);
00711 
00712   // determine the system's TEMP path
00713   if(GetTempPath(MAX_BUF, szTempDir) == 0)
00714   {
00715     if(GetWindowsDirectory(szTempDir, MAX_BUF) == 0)
00716     {
00717       char szEGetWinDirFailed[MAX_BUF];
00718 
00719       if(GetPrivateProfileString("Messages", "ERROR_GET_WINDOWS_DIRECTORY_FAILED", "", szEGetWinDirFailed, sizeof(szEGetWinDirFailed), szFileIniInstall))
00720         PrintError(szEGetWinDirFailed, ERROR_CODE_SHOW);
00721 
00722       return(1);
00723     }
00724 
00725     AppendBackSlash(szTempDir, MAX_BUF);
00726     lstrcat(szTempDir, "TEMP");
00727   }
00728   lstrcpy(szOSTempDir, szTempDir);
00729   AppendBackSlash(szTempDir, MAX_BUF);
00730   lstrcat(szTempDir, WIZ_TEMP_DIR);
00731 
00732   /*  if multiple installer instances are allowed; 
00733       each instance requires a unique temp directory
00734    */
00735   if(gbAllowMultipleInstalls)
00736   {
00737     DWORD dwLen = lstrlen(szTempDir);
00738 
00739     if (strncmp(szSetupDir, szTempDir, dwLen) == 0)
00740     {
00741       lstrcpy(szTempDir, szSetupDir);
00742     }
00743     else
00744     {
00745       int i;
00746       for(i = 1; i <= 100 && (FileExists(szTempDir) != FALSE); i++)
00747       {
00748         itoa(i, (szTempDir + dwLen), 10);
00749       }
00750     
00751       if (FileExists(szTempDir) != FALSE)
00752       {
00753         MessageBox(hWndMain, "Cannot create temp directory", NULL, MB_OK | MB_ICONEXCLAMATION);
00754         exit(1);
00755       }
00756     }
00757   }
00758   else
00759   {
00760     // we're not running in mmi mode (allow multiple instances of installer
00761     // to run at the same time), we should look for and remove the dirs
00762     // that are created in the mmi mode.
00763     DWORD dwLen;
00764     char tempDirToCleanup[MAX_BUF];
00765     int i = 1;
00766 
00767     lstrcpy(tempDirToCleanup, szTempDir);
00768     dwLen = lstrlen(tempDirToCleanup);
00769     itoa(i, (tempDirToCleanup + dwLen), 10);
00770     for(i = 2; i <= 100 && (FileExists(tempDirToCleanup)); i++)
00771     {
00772       DirectoryRemove(tempDirToCleanup, TRUE);
00773       itoa(i, (tempDirToCleanup + dwLen), 10);
00774     }
00775   }
00776 
00777   if(!FileExists(szTempDir))
00778   {
00779     AppendBackSlash(szTempDir, MAX_BUF);
00780     CreateDirectoriesAll(szTempDir, DO_NOT_ADD_TO_UNINSTALL_LOG);
00781     if(!FileExists(szTempDir))
00782     {
00783       char szECreateTempDir[MAX_BUF];
00784 
00785       if(GetPrivateProfileString("Messages", "ERROR_CREATE_TEMP_DIR", "", szECreateTempDir, sizeof(szECreateTempDir), szFileIniInstall))
00786       {
00787         wsprintf(szBuf, szECreateTempDir, szTempDir);
00788         PrintError(szBuf, ERROR_CODE_HIDE);
00789       }
00790       return(1);
00791     }
00792     RemoveBackSlash(szTempDir);
00793   }
00794 
00795   /* Check if we need to load GRE App installer proxy DLL;
00796      this DLL lives in the Windows temp directory when the 
00797      external GRE app installer is running. If found, it 
00798      will be loaded and fed with incremental progress updates.
00799   */  
00800 
00801   GetTempPath(MAX_BUF, szProxyDLLPath);
00802   AppendBackSlash(szProxyDLLPath, MAX_BUF);
00803   strcat(szProxyDLLPath, GRE_APP_INSTALLER_PROXY_DLL);
00804   
00805   if (FileExists(szProxyDLLPath) != FALSE)
00806     hGREAppInstallerProxyDLL = LoadLibrary(szProxyDLLPath);
00807   
00808   if (hGREAppInstallerProxyDLL != NULL)
00809     lpfnProgressUpd = (LPFNDLLFUNC) GetProcAddress(hGREAppInstallerProxyDLL, GRE_PROXY_UPD_FUNC);
00810                              
00811 
00812   hbmpBoxChecked         = LoadBitmap(hSetupRscInst, MAKEINTRESOURCE(IDB_BOX_CHECKED));
00813   hbmpBoxCheckedDisabled = LoadBitmap(hSetupRscInst, MAKEINTRESOURCE(IDB_BOX_CHECKED_DISABLED));
00814   hbmpBoxUnChecked       = LoadBitmap(hSetupRscInst, MAKEINTRESOURCE(IDB_BOX_UNCHECKED));
00815 
00816   DeleteIdiGetConfigIni();
00817   bIdiArchivesExists = DeleteIdiGetArchives();
00818   DeleteIdiGetRedirect();
00819   DeleteInstallLogFile(FILE_INSTALL_LOG);
00820   DeleteInstallLogFile(FILE_INSTALL_STATUS_LOG);
00821   LogISTime(W_START);
00822   DetermineOSVersionEx();
00823 
00824   SystemParametersInfo(SPI_GETSCREENREADER, 0, &(gSystemInfo.bScreenReader), 0);
00825 
00826   return(0);
00827 }
00828 
00829 /* Function to remove quotes from a string */
00830 void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize)
00831 {
00832   char *lpszBegin;
00833 
00834   if(lstrlen(lpszSrc) > iDestSize)
00835     return;
00836 
00837   if(*lpszSrc == '\"')
00838     lpszBegin = &lpszSrc[1];
00839   else
00840     lpszBegin = lpszSrc;
00841 
00842   lstrcpy(lpszDest, lpszBegin);
00843 
00844   if(lpszDest[lstrlen(lpszDest) - 1] == '\"')
00845     lpszDest[lstrlen(lpszDest) - 1] = '\0';
00846 }
00847 
00848 /* Function to copy strings safely.
00849  *   returns the amount of memory required (including NULL byte) if there's not enough
00850  *   else, it returns 0 for success.
00851  */
00852 int MozCopyStr(LPSTR szSrc, LPSTR szDest, DWORD dwDestBufSize)
00853 {
00854   DWORD length;
00855 
00856   assert(szSrc);
00857   assert(szDest);
00858 
00859   length = lstrlen(szSrc) + 1;
00860   strncpy(szDest, szSrc, dwDestBufSize);
00861   if(length > dwDestBufSize)
00862   {
00863     szDest[dwDestBufSize - 1] = '\0';
00864     return(length);
00865   }
00866   return(0);
00867 }
00868 
00869 /* Function to locate the first non space character in a string,
00870  * and return a pointer to it. */
00871 LPSTR GetFirstNonSpace(LPSTR lpszString)
00872 {
00873   int   i;
00874   int   iStrLength;
00875 
00876   iStrLength = lstrlen(lpszString);
00877 
00878   for(i = 0; i < iStrLength; i++)
00879   {
00880     if(!isspace(lpszString[i]))
00881       return(&lpszString[i]);
00882   }
00883 
00884   return(NULL);
00885 }
00886 
00887 /* Function to locate the first character c in lpszString,
00888  * and return a pointer to it. */
00889 LPSTR MozStrChar(LPSTR lpszString, char c)
00890 {
00891   char* p = lpszString;
00892 
00893   if(!p)
00894     return NULL;
00895 
00896   while (*p && (*p != c))
00897     p = CharNext(p);
00898 
00899   if (*p == '\0')  // null means end of string
00900     return NULL;
00901 
00902   return p;
00903 }
00904 
00905 /* Function to return the argument count given a command line input
00906  * format string */
00907 int GetArgC(LPSTR lpszCommandLine)
00908 {
00909   int   i;
00910   int   iArgCount;
00911   int   iStrLength;
00912   LPSTR lpszBeginStr;
00913   BOOL  bFoundQuote;
00914   BOOL  bFoundSpace;
00915 
00916   iArgCount    = 0;
00917   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00918 
00919   if(lpszBeginStr == NULL)
00920     return(iArgCount);
00921 
00922   iStrLength   = lstrlen(lpszBeginStr);
00923   bFoundQuote  = FALSE;
00924   bFoundSpace  = TRUE;
00925 
00926   for(i = 0; i < iStrLength; i++)
00927   {
00928     if(lpszCommandLine[i] == '\"')
00929     {
00930       if(bFoundQuote == FALSE)
00931       {
00932         ++iArgCount;
00933         bFoundQuote = TRUE;
00934       }
00935       else
00936       {
00937         bFoundQuote = FALSE;
00938       }
00939     }
00940     else if(bFoundQuote == FALSE)
00941     {
00942       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
00943       {
00944         ++iArgCount;
00945         bFoundSpace = FALSE;
00946       }
00947       else if(isspace(lpszCommandLine[i]))
00948       {
00949         bFoundSpace = TRUE;
00950       }
00951     }
00952   }
00953 
00954   return(iArgCount);
00955 }
00956 
00957 /* Function to return a specific argument parameter from a given command line input
00958  * format string. */
00959 LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize)
00960 {
00961   int   i;
00962   int   j;
00963   int   iArgCount;
00964   int   iStrLength;
00965   LPSTR lpszBeginStr;
00966   LPSTR lpszDestTemp;
00967   BOOL  bFoundQuote;
00968   BOOL  bFoundSpace;
00969 
00970   iArgCount    = 0;
00971   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00972 
00973   if(lpszBeginStr == NULL)
00974     return(NULL);
00975 
00976   lpszDestTemp = (char *)calloc(iDestSize, sizeof(char));
00977   if(lpszDestTemp == NULL)
00978   {
00979     PrintError("Out of memory", ERROR_CODE_HIDE);
00980     exit(1);
00981   }
00982 
00983   ZeroMemory(lpszDest, iDestSize);
00984   iStrLength    = lstrlen(lpszBeginStr);
00985   bFoundQuote   = FALSE;
00986   bFoundSpace   = TRUE;
00987   j             = 0;
00988 
00989   for(i = 0; i < iStrLength; i++)
00990   {
00991     if(lpszCommandLine[i] == '\"')
00992     {
00993       if(bFoundQuote == FALSE)
00994       {
00995         ++iArgCount;
00996         bFoundQuote = TRUE;
00997       }
00998       else
00999       {
01000         bFoundQuote = FALSE;
01001       }
01002     }
01003     else if(bFoundQuote == FALSE)
01004     {
01005       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
01006       {
01007         ++iArgCount;
01008         bFoundSpace = FALSE;
01009       }
01010       else if(isspace(lpszCommandLine[i]))
01011       {
01012         bFoundSpace = TRUE;
01013       }
01014     }
01015 
01016     if((iIndex == (iArgCount - 1)) &&
01017       ((bFoundQuote == TRUE) || (bFoundSpace == FALSE) ||
01018       ((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"'))))
01019     {
01020       if(j < iDestSize)
01021       {
01022         lpszDestTemp[j] = lpszCommandLine[i];
01023         ++j;
01024       }
01025       else
01026       {
01027         lpszDestTemp[j] = '\0';
01028       }
01029     }
01030   }
01031 
01032   RemoveQuotes(lpszDestTemp, lpszDest, iDestSize);
01033   free(lpszDestTemp);
01034   return(lpszDest);
01035 }
01036 
01037 BOOL IsInArchivesLst(siC *siCObject, BOOL bModify)
01038 {
01039   char *szBufPtr;
01040   char szBuf[MAX_BUF];
01041   char szArchiveLstFile[MAX_BUF_MEDIUM];
01042   BOOL bRet = FALSE;
01043 
01044   lstrcpy(szArchiveLstFile, szTempDir);
01045   AppendBackSlash(szArchiveLstFile, sizeof(szArchiveLstFile));
01046   lstrcat(szArchiveLstFile, "Archive.lst");
01047   GetPrivateProfileString("Archives", NULL, "", szBuf, sizeof(szBuf), szArchiveLstFile);
01048   if(*szBuf != '\0')
01049   {
01050     szBufPtr = szBuf;
01051     while(*szBufPtr != '\0')
01052     {
01053       if(lstrcmpi(siCObject->szArchiveName, szBufPtr) == 0)
01054       {
01055         if(bModify)
01056         {
01057           /* jar file found.  Unset attribute to download from the net */
01058           siCObject->dwAttributes &= ~SIC_DOWNLOAD_REQUIRED;
01059           /* save the path of where jar was found at */
01060           lstrcpy(siCObject->szArchivePath, szTempDir);
01061           AppendBackSlash(siCObject->szArchivePath, MAX_BUF);
01062         }
01063         bRet = TRUE;
01064 
01065         /* found what we're looking for.  No need to continue */
01066         break;
01067       }
01068       szBufPtr += lstrlen(szBufPtr) + 1;
01069     }
01070   }
01071   return(bRet);
01072 }
01073 
01074 HRESULT ParseSetupIni()
01075 {
01076   char szBuf[MAX_BUF];
01077   char szFileIniSetup[MAX_BUF];
01078   char szFileIdiGetConfigIni[MAX_BUF];
01079 
01080   lstrcpy(szFileIdiGetConfigIni, szTempDir);
01081   AppendBackSlash(szFileIdiGetConfigIni, sizeof(szFileIdiGetConfigIni));
01082   lstrcat(szFileIdiGetConfigIni, FILE_IDI_GETCONFIGINI);
01083 
01084   lstrcpy(szFileIniSetup, szSetupDir);
01085   AppendBackSlash(szFileIniSetup, sizeof(szFileIniSetup));
01086   lstrcat(szFileIniSetup, FILE_INI_SETUP);
01087 
01088   CopyFile(szFileIniSetup, szFileIdiGetConfigIni, FALSE);
01089 
01090   if(!FileExists(szFileIdiGetConfigIni))
01091   {
01092     char szEFileNotFound[MAX_BUF];
01093 
01094     if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
01095     {
01096       wsprintf(szBuf, szEFileNotFound, szFileIdiGetConfigIni);
01097       PrintError(szBuf, ERROR_CODE_HIDE);
01098     }
01099     return(1);
01100   }
01101 
01102   return(0);
01103 }
01104 
01105 static char szFileIniConfig[MAX_BUF];
01106 
01107 HRESULT GetConfigIni()
01108 {
01109   char    szFileIniTempDir[MAX_BUF];
01110   char    szFileIniSetupDir[MAX_BUF];
01111   char    szMsgRetrieveConfigIni[MAX_BUF];
01112   char    szBuf[MAX_BUF];
01113   HRESULT hResult = 0;
01114 
01115   if(!GetPrivateProfileString("Messages", "MSG_RETRIEVE_CONFIGINI", "", szMsgRetrieveConfigIni, sizeof(szMsgRetrieveConfigIni), szFileIniInstall))
01116     return(1);
01117     
01118   lstrcpy(szFileIniTempDir, szTempDir);
01119   AppendBackSlash(szFileIniTempDir, sizeof(szFileIniTempDir));
01120   lstrcat(szFileIniTempDir, FILE_INI_CONFIG);
01121 
01122   /* set default value for szFileIniConfig here */
01123   lstrcpy(szFileIniConfig, szFileIniTempDir);
01124 
01125   lstrcpy(szFileIniSetupDir, szSetupDir);
01126   AppendBackSlash(szFileIniSetupDir, sizeof(szFileIniSetupDir));
01127   lstrcat(szFileIniSetupDir, FILE_INI_CONFIG);
01128 
01129   /* if config.ini exists, then use it, else download config.ini from the net */
01130   if(!FileExists(szFileIniTempDir))
01131   {
01132     if(FileExists(szFileIniSetupDir))
01133     {
01134       lstrcpy(szFileIniConfig, szFileIniSetupDir);
01135       hResult = 0;
01136     }
01137     else
01138     {
01139       char szEFileNotFound[MAX_BUF];
01140 
01141     if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
01142       {
01143         wsprintf(szBuf, szEFileNotFound, FILE_INI_CONFIG);
01144         PrintError(szBuf, ERROR_CODE_HIDE);
01145       }
01146       hResult = 1;
01147     }
01148   }
01149   else
01150     hResult = 0;
01151 
01152   return(hResult);
01153 }
01154 
01155 DWORD
01156 GetConfigIniProfileString(const char *aSection, const char *aKey,
01157                           const char *aDefault, char *aResult, DWORD aMaxLen)
01158 {
01159   DWORD length;
01160 
01161   char *c;
01162 
01163   char *varend;
01164   DWORD varlen;
01165   char* replacevalue = (char*) _alloca(aMaxLen);
01166   DWORD replacelen;
01167 
01168   length = GetPrivateProfileString(aSection, aKey, aDefault,
01169                                    aResult, aMaxLen, szFileIniConfig);
01170 
01171   // loop through the string looking for {VAR}, to replace with [Messages]
01172   // from install.ini
01173   c = aResult;
01174 
01175   while (*c) {
01176     if (*c == '{') {
01177       varend = ++c;
01178       // c is now the beginning of VAR
01179 
01180       while (*varend != '}') {
01181         if (*varend == '\0') {
01182           // This is malformed, as we found a { without a }
01183           // but we don't have a way to assert, so we just return.
01184           return length;
01185         }
01186 
01187         ++varend;
01188       }
01189 
01190       // varlen is the length of {VAR} with the braces.
01191       varlen = varend - c + 2;
01192 
01193       if (varlen > 2) {
01194         *varend = '\0';
01195 
01196         // In order to honor aMaxLen, cap the length of the replacement value.
01197         replacelen =
01198           GetPrivateProfileString("Messages", c, c,
01199                                   replacevalue, aMaxLen - length + varlen,
01200                                   szFileIniInstall);
01201 
01202         if (replacelen != varlen) {
01203           // Move the end of the buffer forward/back to compensate for
01204           // the difference in length.
01205           memmove(c + replacelen - 1, varend + 1, (aResult + length) - varend);
01206           length += replacelen - varlen;
01207         }
01208 
01209         // copy the replacevalue over the {VAR}
01210         memcpy(c - 1, replacevalue, replacelen);
01211 
01212         c += replacelen - 1;
01213       }
01214       else {
01215         // If we encountered a plain {}, just advance the outer loop.
01216         // This should really be an assertion.
01217         c = varend + 1;
01218       }
01219     }
01220     else {
01221       ++c;
01222     }
01223   }
01224 
01225   return length;
01226 }
01227 
01228 HRESULT GetInstallIni()
01229 {
01230   char    szFileIniTempDir[MAX_BUF];
01231   char    szFileIniSetupDir[MAX_BUF];
01232   char    szMsgRetrieveInstallIni[MAX_BUF];
01233   char    szBuf[MAX_BUF];
01234   HRESULT hResult = 0;
01235 
01236   if(NS_LoadString(hSetupRscInst, IDS_MSG_RETRIEVE_INSTALLINI, szMsgRetrieveInstallIni, MAX_BUF) != WIZ_OK)
01237     return(1);
01238     
01239   lstrcpy(szFileIniTempDir, szTempDir);
01240   AppendBackSlash(szFileIniTempDir, sizeof(szFileIniTempDir));
01241   lstrcat(szFileIniTempDir, FILE_INI_INSTALL);
01242 
01243   /* set default value for szFileIniInstall here */
01244   lstrcpy(szFileIniInstall, szFileIniTempDir);
01245 
01246   lstrcpy(szFileIniSetupDir, szSetupDir);
01247   AppendBackSlash(szFileIniSetupDir, sizeof(szFileIniSetupDir));
01248   lstrcat(szFileIniSetupDir, FILE_INI_INSTALL);
01249 
01250   /* if install.ini exists, then use it, else download install.ini from the net */
01251   if(!FileExists(szFileIniTempDir))
01252   {
01253     if(FileExists(szFileIniSetupDir))
01254     {
01255       lstrcpy(szFileIniInstall, szFileIniSetupDir);
01256       hResult = 0;
01257     }
01258     else
01259     {
01260       char szEFileNotFound[MAX_BUF];
01261 
01262       if(NS_LoadString(hSetupRscInst, IDS_ERROR_FILE_NOT_FOUND, szEFileNotFound, MAX_BUF) == WIZ_OK)
01263       {
01264         wsprintf(szBuf, szEFileNotFound, FILE_INI_INSTALL);
01265         PrintError(szBuf, ERROR_CODE_HIDE);
01266       }
01267       hResult = 1;
01268     }
01269   }
01270   else
01271     hResult = 0;
01272 
01273   return(hResult);
01274 }
01275 
01276 int LocateJar(siC *siCObject, LPSTR szPath, int dwPathSize, BOOL bIncludeTempDir)
01277 {
01278   BOOL bRet;
01279   char szBuf[MAX_BUF * 2];
01280   char szSEADirTemp[MAX_BUF];
01281   char szSetupDirTemp[MAX_BUF];
01282   char szTempDirTemp[MAX_BUF];
01283 
01284   /* initialize default behavior */
01285   bRet = AP_NOT_FOUND;
01286   if(szPath != NULL)
01287     ZeroMemory(szPath, dwPathSize);
01288   siCObject->dwAttributes |= SIC_DOWNLOAD_REQUIRED;
01289 
01290   lstrcpy(szSEADirTemp, sgProduct.szAlternateArchiveSearchPath);
01291   AppendBackSlash(szSEADirTemp, sizeof(szSEADirTemp));
01292   lstrcat(szSEADirTemp, siCObject->szArchiveName);
01293 
01294   /* XXX_QUICK_FIX 
01295    * checking sgProduct.szAlternateArchiveSearchPath for empty string
01296    * should be done prior to AppendBackSlash() above.
01297    * This is a quick fix for the time frame that we are currently in. */
01298   if((*sgProduct.szAlternateArchiveSearchPath != '\0') && (FileExists(szSEADirTemp)))
01299   {
01300     /* jar file found.  Unset attribute to download from the net */
01301     siCObject->dwAttributes &= ~SIC_DOWNLOAD_REQUIRED;
01302     /* save the path of where jar was found at */
01303     lstrcpy(siCObject->szArchivePath, sgProduct.szAlternateArchiveSearchPath);
01304     AppendBackSlash(siCObject->szArchivePath, MAX_BUF);
01305     bRet = AP_ALTERNATE_PATH;
01306 
01307     /* save path where archive is located */
01308     if((szPath != NULL) && (lstrlen(sgProduct.szAlternateArchiveSearchPath) < dwPathSize))
01309       lstrcpy(szPath, sgProduct.szAlternateArchiveSearchPath);
01310   }
01311   else
01312   {
01313     lstrcpy(szSetupDirTemp, szSetupDir);
01314     AppendBackSlash(szSetupDirTemp, sizeof(szSetupDirTemp));
01315 
01316     lstrcpy(szTempDirTemp,  szTempDir);
01317     AppendBackSlash(szTempDirTemp, sizeof(szTempDirTemp));
01318 
01319     if(lstrcmpi(szTempDirTemp, szSetupDirTemp) == 0)
01320     {
01321       /* check the temp dir for the .xpi file */
01322       lstrcpy(szBuf, szTempDirTemp);
01323       AppendBackSlash(szBuf, sizeof(szBuf));
01324       lstrcat(szBuf, siCObject->szArchiveName);
01325 
01326       if(FileExists(szBuf))
01327       {
01328         if(bIncludeTempDir == TRUE)
01329         {
01330           /* jar file found.  Unset attribute to download from the net */
01331           siCObject->dwAttributes &= ~SIC_DOWNLOAD_REQUIRED;
01332           /* save the path of where jar was found at */
01333           lstrcpy(siCObject->szArchivePath, szTempDirTemp);
01334           AppendBackSlash(siCObject->szArchivePath, MAX_BUF);
01335           bRet = AP_TEMP_PATH;
01336         }
01337 
01338         /* if the archive name is in the archive.lst file, then it was uncompressed
01339          * by the self extracting .exe file.  Assume that the .xpi file exists.
01340          * This is a safe assumption because the self extracting.exe creates the
01341          * archive.lst with what it uncompresses everytime it is run. */
01342         if(IsInArchivesLst(siCObject, TRUE))
01343           bRet = AP_SETUP_PATH;
01344 
01345         /* save path where archive is located */
01346         if((szPath != NULL) && (lstrlen(szTempDirTemp) < dwPathSize))
01347           lstrcpy(szPath, szTempDirTemp);
01348       }
01349     }
01350     else
01351     {
01352       /* check the setup dir for the .xpi file */
01353       lstrcpy(szBuf, szSetupDirTemp);
01354       AppendBackSlash(szBuf, sizeof(szBuf));
01355       lstrcat(szBuf, siCObject->szArchiveName);
01356 
01357       if(FileExists(szBuf))
01358       {
01359         /* jar file found.  Unset attribute to download from the net */
01360         siCObject->dwAttributes &= ~SIC_DOWNLOAD_REQUIRED;
01361         /* save the path of where jar was found at */
01362         lstrcpy(siCObject->szArchivePath, szSetupDirTemp);
01363         AppendBackSlash(siCObject->szArchivePath, MAX_BUF);
01364         bRet = AP_SETUP_PATH;
01365 
01366         /* save path where archive is located */
01367         if((szPath != NULL) && (lstrlen(sgProduct.szAlternateArchiveSearchPath) < dwPathSize))
01368           lstrcpy(szPath, szSetupDirTemp);
01369       }
01370       else
01371       {
01372         /* check the ns_temp dir for the .xpi file */
01373         lstrcpy(szBuf, szTempDirTemp);
01374         AppendBackSlash(szBuf, sizeof(szBuf));
01375         lstrcat(szBuf, siCObject->szArchiveName);
01376 
01377         if(FileExists(szBuf))
01378         {
01379           if(bIncludeTempDir == TRUE)
01380           {
01381             /* jar file found.  Unset attribute to download from the net */
01382             siCObject->dwAttributes &= ~SIC_DOWNLOAD_REQUIRED;
01383             /* save the path of where jar was found at */
01384             lstrcpy(siCObject->szArchivePath, szTempDirTemp);
01385             AppendBackSlash(siCObject->szArchivePath, MAX_BUF);
01386             bRet = AP_TEMP_PATH;
01387           }
01388 
01389           /* save path where archive is located */
01390           if((szPath != NULL) && (lstrlen(sgProduct.szAlternateArchiveSearchPath) < dwPathSize))
01391             lstrcpy(szPath, szTempDirTemp);
01392         }
01393       }
01394     }
01395   }
01396   return(bRet);
01397 }
01398 
01399 void SwapFTPAndHTTP(char *szInUrl, DWORD dwInUrlSize)
01400 {
01401   char szTmpBuf[MAX_BUF];
01402   char *ptr       = NULL;
01403   char szFtp[]    = "ftp://";
01404   char szHttp[]   = "http://";
01405 
01406   if((!szInUrl) || !diAdditionalOptions.bUseProtocolSettings)
01407     return;
01408 
01409   ZeroMemory(szTmpBuf, sizeof(szTmpBuf));
01410   switch(diAdditionalOptions.dwUseProtocol)
01411   {
01412     case UP_HTTP:
01413       if((strncmp(szInUrl, szFtp, FTPSTR_LEN) == 0) &&
01414          ((int)dwInUrlSize > lstrlen(szInUrl) + 1))
01415       {
01416         ptr = szInUrl + FTPSTR_LEN;
01417         memmove(ptr + 1, ptr, lstrlen(ptr) + 1);
01418         memcpy(szInUrl, szHttp, HTTPSTR_LEN);
01419       }
01420       break;
01421 
01422     case UP_FTP:
01423     default:
01424       if((strncmp(szInUrl, szHttp, HTTPSTR_LEN) == 0) &&
01425          ((int)dwInUrlSize > lstrlen(szInUrl) + 1))
01426       {
01427         ptr = szInUrl + HTTPSTR_LEN;
01428         memmove(ptr - 1, ptr, lstrlen(ptr) + 1);
01429         memcpy(szInUrl, szFtp, FTPSTR_LEN);
01430       }
01431       break;
01432   }
01433 }
01434 
01435 int UpdateIdiFile(char  *szPartialUrl,
01436                   DWORD dwPartialUrlBufSize,
01437                   siC   *siCObject,
01438                   char  *szSection,
01439                   char  *szKey,
01440                   char  *szFileIdiGetArchives)
01441 {
01442   char      szUrl[MAX_BUF];
01443   char      szBuf[MAX_BUF];
01444   char      szBufTemp[MAX_BUF];
01445 
01446   SwapFTPAndHTTP(szPartialUrl, dwPartialUrlBufSize);
01447   RemoveSlash(szPartialUrl);
01448   wsprintf(szUrl, "%s/%s", szPartialUrl, siCObject->szArchiveName);
01449   if(WritePrivateProfileString(szSection,
01450                                szKey,
01451                                szUrl,
01452                                szFileIdiGetArchives) == 0)
01453   {
01454     char szEWPPS[MAX_BUF];
01455 
01456     if(GetPrivateProfileString("Messages", "ERROR_WRITEPRIVATEPROFILESTRING", "", szEWPPS, sizeof(szEWPPS), szFileIniInstall))
01457     {
01458       wsprintf(szBufTemp,
01459                "%s\n    [%s]\n    url=%s",
01460                szFileIdiGetArchives,
01461                szSection,
01462                szUrl);
01463       wsprintf(szBuf, szEWPPS, szBufTemp);
01464       PrintError(szBuf, ERROR_CODE_SHOW);
01465     }
01466     return(1);
01467   }
01468   return(0);
01469 }
01470 
01471 HRESULT AddArchiveToIdiFile(siC *siCObject,
01472                             char *szSection,
01473                             char *szFileIdiGetArchives)
01474 {
01475   char      szFile[MAX_BUF];
01476   char      szBuf[MAX_BUF];
01477   char      szUrl[MAX_BUF];
01478   char      szIdentifier[MAX_BUF];
01479   char      szArchiveSize[MAX_ITOA];
01480   char      szKey[MAX_BUF_TINY];
01481   int       iIndex = 0;
01482   ssi       *ssiSiteSelectorTemp;
01483 
01484   WritePrivateProfileString(szSection,
01485                             "desc",
01486                             siCObject->szDescriptionShort,
01487                             szFileIdiGetArchives);
01488   _ui64toa(siCObject->ullInstallSizeArchive, szArchiveSize, 10);
01489   WritePrivateProfileString(szSection,
01490                             "size",
01491                             szArchiveSize,
01492                             szFileIdiGetArchives);
01493   itoa(siCObject->dwAttributes & SIC_IGNORE_DOWNLOAD_ERROR, szBuf, 10);
01494   WritePrivateProfileString(szSection,
01495                             "Ignore File Network Error",
01496                             szBuf,
01497                             szFileIdiGetArchives);
01498 
01499   lstrcpy(szFile, szTempDir);
01500   AppendBackSlash(szFile, sizeof(szFile));
01501   lstrcat(szFile, FILE_INI_REDIRECT);
01502 
01503   ZeroMemory(szIdentifier, sizeof(szIdentifier));
01504   ssiSiteSelectorTemp = SsiGetNode(szSiteSelectorDescription);
01505 
01506   GetConfigIniProfileString("Redirect", "Status", "",
01507                             szBuf, sizeof(szBuf));
01508   if(lstrcmpi(szBuf, "ENABLED") != 0)
01509   {
01510     /* redirect.ini is *not* enabled, so use the url from the
01511      * config.ini's [Site Selector] section */
01512     if(*ssiSiteSelectorTemp->szDomain != '\0')
01513     {
01514       wsprintf(szKey, "url%d", iIndex);
01515       lstrcpy(szUrl, ssiSiteSelectorTemp->szDomain);
01516       UpdateIdiFile(szUrl, sizeof(szUrl), siCObject, szSection, szKey, szFileIdiGetArchives);
01517       ++iIndex;
01518     }
01519 
01520     /* use the url from the config.ini's [General] section as well */
01521     GetConfigIniProfileString("General", "url", "",
01522                               szUrl, sizeof(szUrl));
01523     if(*szUrl != 0)
01524     {
01525       wsprintf(szKey, "url%d", iIndex);
01526       UpdateIdiFile(szUrl, sizeof(szUrl), siCObject, szSection, szKey, szFileIdiGetArchives);
01527     }
01528   }
01529   else if(FileExists(szFile))
01530   {
01531     /* redirect.ini is enabled *and* it exists */
01532     GetPrivateProfileString("Site Selector",
01533                             ssiSiteSelectorTemp->szIdentifier,
01534                             "",
01535                             szUrl,
01536                             sizeof(szUrl),
01537                             szFile);
01538     if(*szUrl != '\0')
01539     {
01540       wsprintf(szKey, "url%d", iIndex);
01541       UpdateIdiFile(szUrl, sizeof(szUrl), siCObject, szSection, szKey, szFileIdiGetArchives);
01542       ++iIndex;
01543     }
01544 
01545     /* use the url from the config.ini's [General] section as well */
01546     GetConfigIniProfileString("General", "url", "",
01547                               szUrl, sizeof(szUrl));
01548     if(*szUrl != 0)
01549     {
01550       wsprintf(szKey, "url%d", iIndex);
01551       UpdateIdiFile(szUrl, sizeof(szUrl), siCObject, szSection, szKey, szFileIdiGetArchives);
01552     }
01553   }
01554   else
01555   {
01556     /* redirect.ini is enabled, but the file does not exist,
01557      * so fail over to the url from the config.ini's [General] section */
01558     GetConfigIniProfileString("General", "url", "",
01559                               szUrl, sizeof(szUrl));
01560     if(*szUrl != 0)
01561     {
01562       wsprintf(szKey, "url%d", iIndex);
01563       UpdateIdiFile(szUrl, sizeof(szUrl), siCObject, szSection, szKey, szFileIdiGetArchives);
01564     }
01565   }
01566 
01567   return(0);
01568 }
01569 
01570 void SetSetupRunMode(LPSTR szMode)
01571 {
01572   /* Check to see if mode has already been set.  If so,
01573    * then do not override it.
01574    * We don't want to override this value because it could have been
01575    * set via the command line argument as opposed to the config.ini
01576    * having been parse.  Command line arguments take precedence.
01577    */
01578   if(sgProduct.mode != NOT_SET)
01579     return;
01580 
01581   if(lstrcmpi(szMode, "NORMAL") == 0)
01582     sgProduct.mode = NORMAL;
01583   if(lstrcmpi(szMode, "AUTO") == 0)
01584     sgProduct.mode = AUTO;
01585   if(lstrcmpi(szMode, "SILENT") == 0)
01586     sgProduct.mode = SILENT;
01587 }
01588 
01589 BOOL CheckForArchiveExtension(LPSTR szFile)
01590 {
01591   int  i;
01592   BOOL bRv = FALSE;
01593   char szExtension[MAX_BUF_TINY];
01594 
01595   /* if there is no extension in szFile, szExtension will be zero'ed out */
01596   ParsePath(szFile, szExtension, sizeof(szExtension), FALSE, PP_EXTENSION_ONLY);
01597   i = 0;
01598   while(*ArchiveExtensions[i] != '\0')
01599   {
01600     if(lstrcmpi(szExtension, ArchiveExtensions[i]) == 0)
01601     {
01602       bRv = TRUE;
01603       break;
01604     }
01605 
01606     ++i;
01607   }
01608   return(bRv);
01609 }
01610 
01611 long RetrieveRedirectFile()
01612 {
01613   long      lResult;
01614   char      szBuf[MAX_BUF];
01615   char      szBufUrl[MAX_BUF];
01616   char      szBufTemp[MAX_BUF];
01617   char      szIndex0[MAX_BUF];
01618   char      szFileIdiGetRedirect[MAX_BUF];
01619   char      szFileIniRedirect[MAX_BUF];
01620   ssi       *ssiSiteSelectorTemp;
01621 
01622   if(GetTotalArchivesToDownload() == 0)
01623     return(0);
01624 
01625   lstrcpy(szFileIniRedirect, szTempDir);
01626   AppendBackSlash(szFileIniRedirect, sizeof(szFileIniRedirect));
01627   lstrcat(szFileIniRedirect, FILE_INI_REDIRECT);
01628 
01629   if(FileExists(szFileIniRedirect))
01630     DeleteFile(szFileIniRedirect);
01631 
01632   GetConfigIniProfileString("Redirect", "Status", "", szBuf, sizeof(szBuf));
01633   if(lstrcmpi(szBuf, "ENABLED") != 0)
01634     return(0);
01635 
01636   ssiSiteSelectorTemp = SsiGetNode(szSiteSelectorDescription);
01637   if(ssiSiteSelectorTemp != NULL)
01638   {
01639     if(ssiSiteSelectorTemp->szDomain != NULL)
01640       lstrcpy(szBufUrl, ssiSiteSelectorTemp->szDomain);
01641   }
01642   else
01643     /* No domain to download the redirect.ini file from.
01644      * Assume that it does not exist.
01645      * This should trigger the backup/alternate url. */
01646     return(0);
01647 
01648   lstrcpy(szFileIdiGetRedirect, szTempDir);
01649   AppendBackSlash(szFileIdiGetRedirect, sizeof(szFileIdiGetRedirect));
01650   lstrcat(szFileIdiGetRedirect, FILE_IDI_GETREDIRECT);
01651 
01652   GetConfigIniProfileString("Redirect", "Description", "", szBuf, sizeof(szBuf));
01653   WritePrivateProfileString("File0", "desc", szBuf, szFileIdiGetRedirect);
01654   GetConfigIniProfileString("Redirect", "Server Path", "", szBuf, sizeof(szBuf));
01655   AppendSlash(szBufUrl, sizeof(szBufUrl));
01656   lstrcat(szBufUrl, szBuf);
01657   SwapFTPAndHTTP(szBufUrl, sizeof(szBufUrl));
01658   if(WritePrivateProfileString("File0", "url", szBufUrl, szFileIdiGetRedirect) == 0)
01659   {
01660     char szEWPPS[MAX_BUF];
01661 
01662     if(GetPrivateProfileString("Messages", "ERROR_WRITEPRIVATEPROFILESTRING", "", szEWPPS, sizeof(szEWPPS), szFileIniInstall))
01663     {
01664       wsprintf(szBufTemp, "%s\n    [%s]\n    %s=%s", szFileIdiGetRedirect, "File0", szIndex0, szBufUrl);
01665       wsprintf(szBuf, szEWPPS, szBufTemp);
01666       PrintError(szBuf, ERROR_CODE_SHOW);
01667     }
01668     return(1);
01669   }
01670 
01671   lResult = DownloadFiles(szFileIdiGetRedirect,               /* input idi file to parse                 */
01672                           szTempDir,                          /* download directory                      */
01673                           diAdvancedSettings.szProxyServer,   /* proxy server name                       */
01674                           diAdvancedSettings.szProxyPort,     /* proxy server port                       */
01675                           diAdvancedSettings.szProxyUser,     /* proxy server user (optional)            */
01676                           diAdvancedSettings.szProxyPasswd,   /* proxy password (optional)               */
01677                           FALSE,                              /* show retry message                      */
01678                           TRUE,                               /* ignore network error                    */
01679                           NULL,                               /* buffer to store the name of failed file */
01680                           0);                                 /* size of failed file name buffer         */
01681   return(lResult);
01682 }
01683 
01684 int CRCCheckDownloadedArchives(char *szCorruptedArchiveList,
01685                                DWORD dwCorruptedArchiveListSize,
01686                                char *szFileIdiGetArchives)
01687 {
01688   DWORD dwIndex0;
01689   DWORD dwFileCounter;
01690   siC   *siCObject = NULL;
01691   char  szArchivePathWithFilename[MAX_BUF];
01692   char  szArchivePath[MAX_BUF];
01693   char  szMsgCRCCheck[MAX_BUF];
01694   char  szSection[MAX_INI_SK];
01695   int   iRv;
01696   int   iResult;
01697 
01698   /* delete the getarchives.idi file because it needs to be recreated
01699    * if there are any files that fails the CRC check */
01700   if(szFileIdiGetArchives)
01701     DeleteFile(szFileIdiGetArchives);
01702 
01703   if(szCorruptedArchiveList != NULL)
01704     ZeroMemory(szCorruptedArchiveList, dwCorruptedArchiveListSize);
01705 
01706   GetConfigIniProfileString("Strings", "Message Verifying Archives", "", szMsgCRCCheck, sizeof(szMsgCRCCheck));
01707   ShowMessage(szMsgCRCCheck, TRUE);
01708   
01709   iResult           = WIZ_CRC_PASS;
01710   dwIndex0          = 0;
01711   dwFileCounter     = 0;
01712   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
01713   while(siCObject)
01714   {
01715     if((siCObject->dwAttributes & SIC_SELECTED) &&
01716       !(siCObject->dwAttributes & SIC_IGNORE_DOWNLOAD_ERROR))
01717     {
01718       if((iRv = LocateJar(siCObject, szArchivePath, sizeof(szArchivePath), TRUE)) == AP_NOT_FOUND)
01719       {
01720         char szBuf[MAX_BUF];
01721         char szEFileNotFound[MAX_BUF];
01722 
01723        if(GetPrivateProfileString("Messages", "ERROR_FILE_NOT_FOUND", "", szEFileNotFound, sizeof(szEFileNotFound), szFileIniInstall))
01724         {
01725           wsprintf(szBuf, szEFileNotFound, siCObject->szArchiveName);
01726           PrintError(szBuf, ERROR_CODE_HIDE);
01727         }
01728         iResult = WIZ_ARCHIVES_MISSING; // not all .xpi files were downloaded
01729         break;
01730       }
01731 
01732       if(lstrlen(szArchivePath) < sizeof(szArchivePathWithFilename))
01733         lstrcpy(szArchivePathWithFilename, szArchivePath);
01734 
01735       AppendBackSlash(szArchivePathWithFilename, sizeof(szArchivePathWithFilename));
01736       if((lstrlen(szArchivePathWithFilename) + lstrlen(siCObject->szArchiveName)) < sizeof(szArchivePathWithFilename))
01737         lstrcat(szArchivePathWithFilename, siCObject->szArchiveName);
01738 
01739       if(CheckForArchiveExtension(szArchivePathWithFilename))
01740       {
01741         /* Make sure that the Archive that failed is located in the TEMP
01742          * folder.  This means that it was downloaded at one point and not
01743          * simply uncompressed from the self-extracting exe file. */
01744         if(VerifyArchive(szArchivePathWithFilename) != ZIP_OK)
01745         {
01746           if(iRv == AP_TEMP_PATH)
01747           {
01748             /* Delete the archive even though the download lib will automatically
01749              * overwrite the file.  This is in case that Setup is canceled, at the
01750              * next restart, the file will be downloaded during the first attempt,
01751              * not after a VerifyArchive() call. */
01752             DeleteFile(szArchivePathWithFilename);
01753             wsprintf(szSection, "File%d", dwFileCounter);
01754             ++dwFileCounter;
01755             if(szFileIdiGetArchives)
01756               if((AddArchiveToIdiFile(siCObject,
01757                                       szSection,
01758                                       szFileIdiGetArchives)) != 0)
01759                 return(WIZ_ERROR_UNDEFINED);
01760 
01761             ++siCObject->iCRCRetries;
01762             if(szCorruptedArchiveList != NULL)
01763             {
01764               if((DWORD)(lstrlen(szCorruptedArchiveList) + lstrlen(siCObject->szArchiveName + 1)) < dwCorruptedArchiveListSize)
01765               {
01766                 lstrcat(szCorruptedArchiveList, "        ");
01767                 lstrcat(szCorruptedArchiveList, siCObject->szArchiveName);
01768                 lstrcat(szCorruptedArchiveList, "\n");
01769               }
01770             }
01771           }
01772           iResult = WIZ_CRC_FAIL;
01773         }
01774       }
01775     }
01776 
01777     ++dwIndex0;
01778     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
01779   }
01780   ShowMessage(szMsgCRCCheck, FALSE);
01781   return(iResult);
01782 }
01783 
01784 long RetrieveArchives()
01785 {
01786   DWORD     dwIndex0;
01787   DWORD     dwFileCounter;
01788   BOOL      bDone;
01789   siC       *siCObject = NULL;
01790   long      lResult;
01791   char      szFileIdiGetArchives[MAX_BUF];
01792   char      szSection[MAX_BUF];
01793   char      szCorruptedArchiveList[MAX_BUF];
01794   char      szFailedFile[MAX_BUF];
01795   char      szBuf[MAX_BUF];
01796   char      szPartiallyDownloadedFilename[MAX_BUF];
01797   int       iCRCRetries;
01798   int       iRv;
01799 
01800   /* retrieve the redirect.ini file */
01801   RetrieveRedirectFile();
01802 
01803   ZeroMemory(szCorruptedArchiveList, sizeof(szCorruptedArchiveList));
01804   lstrcpy(szFileIdiGetArchives, szTempDir);
01805   AppendBackSlash(szFileIdiGetArchives, sizeof(szFileIdiGetArchives));
01806   lstrcat(szFileIdiGetArchives, FILE_IDI_GETARCHIVES);
01807   GetSetupCurrentDownloadFile(szPartiallyDownloadedFilename,
01808                               sizeof(szPartiallyDownloadedFilename));
01809 
01810   gbDownloadTriggered= FALSE;
01811   lResult            = WIZ_OK;
01812   dwIndex0           = 0;
01813   dwFileCounter      = 0;
01814   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
01815   while(siCObject)
01816   {
01817     if(siCObject->dwAttributes & SIC_SELECTED)
01818     {
01819       /* If a previous unfinished setup was detected, then
01820        * include the TEMP dir when searching for archives.
01821        * Only download jars if not already in the local machine.
01822        * Also if the last file being downloaded should be resumed.
01823        * The resume detection is done automatically. */
01824       if((LocateJar(siCObject,
01825                     NULL,
01826                     0,
01827                     gbPreviousUnfinishedDownload) == AP_NOT_FOUND) ||
01828          (lstrcmpi(szPartiallyDownloadedFilename,
01829                    siCObject->szArchiveName) == 0))
01830       {
01831         wsprintf(szSection, "File%d", dwFileCounter);
01832         if((lResult = AddArchiveToIdiFile(siCObject,
01833                                           szSection,
01834                                           szFileIdiGetArchives)) != 0)
01835           return(lResult);
01836 
01837         ++dwFileCounter;
01838       }
01839     }
01840 
01841     ++dwIndex0;
01842     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
01843   }
01844 
01845   SetSetupState(SETUP_STATE_DOWNLOAD);
01846 
01847   /* iCRCRetries is initially set to 0 because the first attemp at downloading
01848    * the archives is not considered a "retry".  Subsequent downloads are
01849    * considered retries. */
01850   iCRCRetries = 0;
01851   bDone = FALSE;
01852   do
01853   {
01854     /* the existence of the getarchives.idi file determines if there are
01855        any archives needed to be downloaded */
01856     if(FileExists(szFileIdiGetArchives))
01857     {
01858       gbDownloadTriggered = TRUE;
01859       lResult = DownloadFiles(szFileIdiGetArchives,               /* input idi file to parse                 */
01860                               szTempDir,                          /* download directory                      */
01861                               diAdvancedSettings.szProxyServer,   /* proxy server name                       */
01862                               diAdvancedSettings.szProxyPort,     /* proxy server port                       */
01863                               diAdvancedSettings.szProxyUser,     /* proxy server user (optional)            */
01864                               diAdvancedSettings.szProxyPasswd,   /* proxy password (optional)               */
01865                               iCRCRetries,                        /* show retry message                      */
01866                               FALSE,                              /* ignore network error                    */
01867                               szFailedFile,                       /* buffer to store the name of failed file */
01868                               sizeof(szFailedFile));              /* size of failed file name buffer         */
01869       if(lResult == WIZ_OK)
01870       {
01871         /* CRC check only the archives that were downloaded.
01872          * It will regenerate the idi file with the list of files
01873          * that have not passed the CRC check. */
01874         iRv = CRCCheckDownloadedArchives(szCorruptedArchiveList,
01875                                          sizeof(szCorruptedArchiveList),
01876                                          szFileIdiGetArchives);
01877         switch(iRv)
01878         {
01879           case WIZ_CRC_PASS:
01880             bDone = TRUE;
01881             break;
01882 
01883           default:
01884             bDone = FALSE;
01885             break;
01886         }
01887       }
01888       else
01889       {
01890         /* Download failed.  Error message was already shown by DownloadFiles().
01891          * Simple exit loop here  */
01892         bDone = TRUE;
01893       }
01894     }
01895     else
01896       /* no idi file, so exit loop */
01897       bDone = TRUE;
01898 
01899     if(!bDone)
01900     {
01901       ++iCRCRetries;
01902       if(iCRCRetries > MAX_CRC_FAILED_DOWNLOAD_RETRIES)
01903         bDone = TRUE;
01904     }
01905 
01906   } while(!bDone);
01907 
01908   if(iCRCRetries > MAX_CRC_FAILED_DOWNLOAD_RETRIES)
01909   {
01910     /* too many retries from failed CRC checks */
01911     char szMsg[MAX_BUF];
01912 
01913     LogISComponentsFailedCRC(szCorruptedArchiveList, W_DOWNLOAD);
01914     GetConfigIniProfileString("Strings", "Error Too Many CRC Failures", "", szMsg, sizeof(szMsg));
01915     if(*szMsg != '\0')
01916       PrintError(szMsg, ERROR_CODE_HIDE);
01917 
01918     lResult = WIZ_CRC_FAIL;
01919   }
01920   else
01921   {
01922     if(gbDownloadTriggered)
01923       LogISComponentsFailedCRC(NULL, W_DOWNLOAD);
01924   }
01925 
01926   LogISDownloadProtocol(diAdditionalOptions.dwUseProtocol);
01927   LogMSDownloadProtocol(diAdditionalOptions.dwUseProtocol);
01928 
01929   if(lResult == WIZ_OK)
01930   {
01931     LogISDownloadStatus("ok", NULL);
01932   }
01933   else if(gbDownloadTriggered)
01934   {
01935     wsprintf(szBuf, "failed: %d", lResult);
01936     LogISDownloadStatus(szBuf, szFailedFile);
01937   }
01938 
01939   /* We want to log the download status regardless if we downloaded or not. */
01940   LogMSDownloadStatus(lResult);
01941 
01942   if(lResult == WIZ_OK)
01943   {
01944     UnsetSetupCurrentDownloadFile();
01945     UnsetSetupState();
01946   }
01947 
01948   return(lResult);
01949 }
01950 
01951 void RemoveBackSlash(LPSTR szInput)
01952 {
01953   DWORD dwInputLen;
01954   BOOL  bDone;
01955   char  *ptrChar = NULL;
01956 
01957   if(szInput)
01958   {
01959     dwInputLen = lstrlen(szInput);
01960     bDone = FALSE;
01961     ptrChar = &szInput[dwInputLen];
01962     while(!bDone)
01963     {
01964       ptrChar = CharPrev(szInput, ptrChar);
01965       if(*ptrChar == '\\')
01966         *ptrChar = '\0';
01967       else
01968         bDone = TRUE;
01969     }
01970   }
01971 }
01972 
01973 void AppendBackSlash(LPSTR szInput, DWORD dwInputSize)
01974 {
01975   DWORD dwInputLen = lstrlen(szInput);
01976 
01977   if(szInput)
01978   {
01979     if(*szInput == '\0')
01980     {
01981       if((dwInputLen + 1) < dwInputSize)
01982       {
01983         lstrcat(szInput, "\\");
01984       }
01985     }
01986     else if(*CharPrev(szInput, &szInput[dwInputLen]) != '\\')
01987     {
01988       if((dwInputLen + 1) < dwInputSize)
01989       {
01990         lstrcat(szInput, "\\");
01991       }
01992     }
01993   }
01994 }
01995 
01996 void RemoveSlash(LPSTR szInput)
01997 {
01998   DWORD dwInputLen;
01999   BOOL  bDone;
02000   char  *ptrChar = NULL;
02001 
02002   if(szInput)
02003   {
02004     dwInputLen = lstrlen(szInput);
02005     bDone = FALSE;
02006     ptrChar = &szInput[dwInputLen];
02007     while(!bDone)
02008     {
02009       ptrChar = CharPrev(szInput, ptrChar);
02010       if(*ptrChar == '/')
02011         *ptrChar = '\0';
02012       else
02013         bDone = TRUE;
02014     }
02015   }
02016 }
02017 
02018 void AppendSlash(LPSTR szInput, DWORD dwInputSize)
02019 {
02020   DWORD dwInputLen = lstrlen(szInput);
02021 
02022   if(szInput)
02023   {
02024     if(*szInput == '\0')
02025     {
02026       if((dwInputLen + 1) < dwInputSize)
02027       {
02028         lstrcat(szInput, "/");
02029       }
02030     }
02031     else if(*CharPrev(szInput, &szInput[dwInputLen]) != '/')
02032     {
02033       if((dwInputLen + 1) < dwInputSize)
02034       {
02035         lstrcat(szInput, "/");
02036       }
02037     }
02038   }
02039 }
02040 
02041 void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, BOOL bURLPath, DWORD dwType)
02042 {
02043   int   iFoundDelimiter;
02044   DWORD dwInputLen;
02045   DWORD dwOutputLen;
02046   BOOL  bFound;
02047   BOOL  bDone = FALSE;
02048   char  cDelimiter;
02049   char  *ptrChar = NULL;
02050   char  *ptrLastChar = NULL;
02051 
02052   if(bURLPath)
02053     cDelimiter = '/';
02054   else
02055     cDelimiter = '\\';
02056 
02057   if(szInput && szOutput)
02058   {
02059     bFound        = TRUE;
02060     dwInputLen    = lstrlen(szInput);
02061     ZeroMemory(szOutput, dwOutputSize);
02062 
02063     if(dwInputLen < dwOutputSize)
02064     {
02065       switch(dwType)
02066       {
02067         case PP_FILENAME_ONLY:
02068           ptrChar = &szInput[dwInputLen];
02069           bDone = FALSE;
02070           while(!bDone)
02071           {
02072             ptrChar = CharPrev(szInput, ptrChar);
02073             if(*ptrChar == cDelimiter)
02074             {
02075               lstrcpy(szOutput, CharNext(ptrChar));
02076               bDone = TRUE;
02077             }
02078             else if(ptrChar == szInput)
02079             {
02080               /* we're at the beginning of the string and still
02081                * nothing found.  So just return the input string. */
02082               lstrcpy(szOutput, szInput);
02083               bDone = TRUE;
02084             }
02085           }
02086           break;
02087 
02088         case PP_PATH_ONLY:
02089           lstrcpy(szOutput, szInput);
02090           dwOutputLen = lstrlen(szOutput);
02091           ptrChar = &szOutput[dwOutputLen];
02092           bDone = FALSE;
02093           while(!bDone)
02094           {
02095             ptrChar = CharPrev(szOutput, ptrChar);
02096             if(*ptrChar == cDelimiter)
02097             {
02098               *CharNext(ptrChar) = '\0';
02099               bDone = TRUE;
02100             }
02101             else if(ptrChar == szOutput)
02102             {
02103               /* we're at the beginning of the string and still
02104                * nothing found.  So just return the input string. */
02105               bDone = TRUE;
02106             }
02107           }
02108           break;
02109 
02110         case PP_EXTENSION_ONLY:
02111           /* check the last character first */
02112           ptrChar = CharPrev(szInput, &szInput[dwInputLen]);
02113           if(*ptrChar == '.')
02114             break;
02115 
02116           bDone = FALSE;
02117           while(!bDone)
02118           {
02119             ptrChar = CharPrev(szInput, ptrChar);
02120             if(*ptrChar == cDelimiter)
02121               /* found path delimiter before '.' */
02122               bDone = TRUE;
02123             else if(*ptrChar == '.')
02124             {
02125               lstrcpy(szOutput, CharNext(ptrChar));
02126               bDone = TRUE;
02127             }
02128             else if(ptrChar == szInput)
02129               bDone = TRUE;
02130           }
02131           break;
02132 
02133         case PP_ROOT_ONLY:
02134           lstrcpy(szOutput, szInput);
02135           dwOutputLen = lstrlen(szOutput);
02136           ptrLastChar = CharPrev(szOutput, &szOutput[dwOutputLen]);
02137           ptrChar     = CharNext(szOutput);
02138           if(*ptrChar == ':')
02139           {
02140             ptrChar = CharNext(ptrChar);
02141             *ptrChar = cDelimiter;
02142             *CharNext(ptrChar) = '\0';
02143           }
02144           else
02145           {
02146             iFoundDelimiter = 0;
02147             ptrChar = szOutput;
02148             while(!bDone)
02149             {
02150               if(*ptrChar == cDelimiter)
02151                 ++iFoundDelimiter;
02152 
02153               if(iFoundDelimiter == 4)
02154               {
02155                 *CharNext(ptrChar) = '\0';
02156                 bDone = TRUE;
02157               }
02158               else if(ptrChar == ptrLastChar)
02159                 bDone = TRUE;
02160               else
02161                 ptrChar = CharNext(ptrChar);
02162             }
02163           }
02164           break;
02165       }
02166     }
02167   }
02168 }
02169 
02170 /* Function: UpdateGreInstallerCmdLine()
02171  *       in: greInfo *aGre - contains infor needed by this function
02172  *           BOOL forExistingGre - to determine if the caller is needing the
02173  *               aParameter to be used by an existing GRE installer or by
02174  *               a new GRE installer.
02175  *   in/out: char *aParameter.
02176  *  purpose: To update the default GRE installer's command line parameters
02177  *           with new defaults depending on config.ini or cmdline arguments
02178  *           to this app's installer.
02179  *           It will also check to make sure GRE's default destination path
02180  *           is writable.  If not, it will change the GRE's destination path
02181  *           to [product path]\GRE\[gre ver].
02182  */
02183 void UpdateGreInstallerCmdLine(greInfo *aGre, char *aParameter, DWORD aParameterBufSize, BOOL forExistingGre)
02184 {
02185   char productPath[MAX_BUF];
02186 
02187   MozCopyStr(sgProduct.szPath, productPath, sizeof(productPath));
02188   RemoveBackSlash(productPath);
02189 
02190   /* Decide GRE installer's run mode.  Default should be -ma (AUTO).
02191    * The only other possibility is -ms (SILENT).  We don't want to allow
02192    * the GRE installer to run in NORMAL mode because we don't want to
02193    * let the user see more dialogs than they need to. */
02194   if(sgProduct.mode == SILENT)
02195     lstrcat(aParameter, " -ms");
02196   else
02197     lstrcat(aParameter, " -ma");
02198 
02199   /* Force the install of GRE if '-greForce' is passed or if GRE
02200    * is to be local.
02201    *
02202    * Passing '-f' to GRE's installer will force it to install
02203    * regardless of version found on system.  If '-f' is already
02204    * present in the parameter, it will do no harm to pass it again. */
02205   if(gbForceInstallGre || (sgProduct.greType == GRE_LOCAL))
02206     lstrcat(aParameter, " -f");
02207 
02208   /* If GRE is to be local, then instruct the GRE's installer to
02209    * install to this application's destination path stored in
02210    * sgProduct.szPath.
02211    *
02212    * We need to also instruct the GRE's installer to create a
02213    * private windows registry GRE key instead of the default one, so
02214    * that other apps attempting to use the global GRE will not find
02215    * this private, local copy.  They should not find this copy! */
02216   if(sgProduct.greType == GRE_LOCAL)
02217   {
02218     char buf[MAX_BUF];
02219 
02220     wsprintf(buf, " -dd \"%s\" -reg_path %s", productPath, sgProduct.grePrivateKey);
02221     lstrcat(aParameter, buf);
02222   }
02223   else if(!forExistingGre)
02224   {
02225     char buf[MAX_BUF];
02226 
02227     assert(aGre);
02228     assert(*aGre->homePath);
02229     assert(*aGre->userAgent);
02230 
02231     /* Append a backslash to the path so CreateDirectoriesAll() will see the
02232      * the last directory name as a directory instead of a file. */
02233     AppendBackSlash(aGre->homePath, sizeof(aGre->homePath));
02234 
02235     /* Attempt to create the GRE destination directory.  If it fails, we don't
02236      * have sufficient access to the default path.  We then need to install
02237      * GRE to:
02238      *   [product path]\GRE\[gre id]
02239      *
02240      * This path should be guaranteed to be writable because the user had
02241      * already created the parent path ([product path]). */
02242     if(DirHasWriteAccess(aGre->homePath) != WIZ_OK)
02243     {
02244       int rv = WIZ_OK;
02245 
02246       /* Update the homePath to the new destination path of where GRE will be
02247        * installed to. homePath is used elsewhere and it needs to be
02248        * referencing the new path, else things will break. */
02249       _snprintf(aGre->homePath, sizeof(aGre->homePath), "%s\\GRE\\%s\\", productPath, aGre->userAgent);
02250       aGre->homePath[sizeof(aGre->homePath) - 1] = '\0';
02251 
02252       /* CreateDirectoriesAll() is guaranteed to succeed using the new GRE
02253        * destination path because it is a subdir of this product's destination
02254        * path that has already been created successfully. */
02255       rv = CreateDirectoriesAll(aGre->homePath, ADD_TO_UNINSTALL_LOG);
02256       assert(rv == WIZ_OK);
02257 
02258       /* When using the -dd option to override the GRE's destination path, the
02259        * path must be a path which includes the GRE ID, ie:
02260        *   C:\Program Files\mozilla.org\Mozilla\GRE\1.4_0000000000
02261        */
02262       _snprintf(buf, sizeof(buf), " -dd \"%s\"", aGre->homePath);
02263       buf[sizeof(buf) - 1] = '\0';
02264       lstrcat(aParameter, buf);
02265     }
02266   }
02267 }
02268 
02269 /* Function: GetInstalledGreConfigIni()
02270  *       in: greInfo *aGre: gre class containing the location of GRE
02271  *           already installed.
02272  *      out: char *aGreConfigIni, DWORD aGreConfigIniBufSize: contains
02273  *           the full path to the installed GRE installer's config.ini
02274  *           file.
02275  *  purpose: To get the full path to the installed GRE installer's
02276  *           config.ini file.
02277  */
02278 HRESULT GetInstalledGreConfigIni(greInfo *aGre, char *aGreConfigIni, DWORD aGreConfigIniBufSize)
02279 {
02280   char buf[MAX_BUF];
02281 
02282   if(!aGre || !aGreConfigIni || (*aGre->homePath == '\0'))
02283     return(WIZ_ERROR_UNDEFINED);
02284 
02285   *aGreConfigIni = '\0';
02286   MozCopyStr(aGre->homePath, buf, sizeof(buf));
02287   AppendBackSlash(buf, sizeof(buf));
02288   wsprintf(aGreConfigIni, "%s%s\\%s", buf, GRE_SETUP_DIR_NAME, FILE_INI_CONFIG);
02289   return(WIZ_OK);
02290 }
02291 
02292 /* Function: GetInfoFromInstalledGreConfigIni()
02293  *       in: greInfo *aGre: gre class to fill the info for.
02294  *      out: returns info in aGre.
02295  *  purpose: To retrieve the GRE uninstaller file (full path) from
02296  *           the installed GRE's config.ini file.
02297  *           GetInfoFromGreInstaller() retrieves information from
02298  *           the (to be run) GRE installer's config.ini, not from the
02299  *           installed GRE installer's config.ini file.
02300  */
02301 HRESULT GetInfoFromInstalledGreConfigIni(greInfo *aGre)
02302 {
02303   HRESULT rv = WIZ_ERROR_UNDEFINED;
02304   char    greConfigIni[MAX_BUF];
02305   char    buf[MAX_BUF];
02306   char    greUninstallerFilename[MAX_BUF];
02307 
02308   if(!aGre)
02309     return(rv);
02310 
02311   *aGre->uninstallerAppPath = '\0';
02312   rv = GetInstalledGreConfigIni(aGre, greConfigIni, sizeof(greConfigIni));
02313   if(WIZ_OK == rv)
02314   {
02315     GetPrivateProfileString("General", "Uninstall Filename", "", greUninstallerFilename, sizeof(greUninstallerFilename), greConfigIni);
02316     wsprintf(buf, "[WINDIR]\\%s", greUninstallerFilename);
02317     DecryptString(aGre->uninstallerAppPath, buf);
02318     GetPrivateProfileString("General", "User Agent", "", aGre->userAgent, sizeof(aGre->userAgent), greConfigIni);
02319   }
02320   return(rv);
02321 }
02322 
02323 /* Function: GetInfoFromGreInstaller()
02324  *       in: char    *aGreInstallerFile: full path to the GRE installer.
02325  *           greInfo *aGre: gre class to fill the homePath for.
02326  *      out: returns homePath in aGre.
02327  *  purpose: To retrieve the GRE home path from the GRE installer.
02328  */
02329 void GetInfoFromGreInstaller(char *aGreInstallerFile, greInfo *aGre)
02330 {
02331   char szBuf[MAX_BUF];
02332   char extractedConfigFile[MAX_BUF];
02333   int  size = 0;
02334 
02335   if(!aGre)
02336     return;
02337 
02338   /* If GRE is to be installed locally, then set it to the
02339    * application's destination path. */
02340   if(sgProduct.greType == GRE_LOCAL)
02341   {
02342     MozCopyStr(sgProduct.szPath, aGre->homePath, sizeof(aGre->homePath));
02343     return;
02344   }
02345 
02346   *aGre->homePath = '\0';
02347 
02348   /* uncompress GRE installer's config.ini file in order to parse for:
02349    *   [General]
02350    *   Path=
02351    *   User Agent=
02352    */
02353   wsprintf(szBuf, "-mmi -ms -u %s", FILE_INI_CONFIG);
02354   WinSpawn(aGreInstallerFile, szBuf, szOSTempDir, SW_SHOWNORMAL, WS_WAIT);
02355   MozCopyStr(szOSTempDir, extractedConfigFile, sizeof(extractedConfigFile));
02356   AppendBackSlash(extractedConfigFile, sizeof(extractedConfigFile));
02357   lstrcat(extractedConfigFile, FILE_INI_CONFIG);
02358   GetPrivateProfileString("General", "Path", "", szBuf, sizeof(szBuf), extractedConfigFile);
02359   DecryptString(aGre->homePath, szBuf);
02360   GetPrivateProfileString("General", "User Agent", "", aGre->userAgent, sizeof(aGre->userAgent), extractedConfigFile);
02361   DeleteFile(extractedConfigFile);
02362 }
02363 
02364 /* Function: CleanupOrphanedGREs()
02365  *       in: none.
02366  *      out: none.
02367  *  purpose: To clean up GREs that were left on the system by previous
02368  *           installations of this product only (not by any other product).
02369  */
02370 HRESULT CleanupOrphanedGREs()
02371 {
02372   HKEY      greIDKeyHandle;
02373   HKEY      greAppListKeyHandle;
02374   DWORD     totalGreIDSubKeys;
02375   DWORD     totalGREAppListSubKeys;
02376   char      **greIDListToClean = NULL;
02377   char      **greAppListToClean = NULL;
02378   char      greKeyID[MAX_BUF_MEDIUM];
02379   char      greRegKey[MAX_BUF];
02380   char      greKeyAppList[MAX_BUF_MEDIUM];
02381   char      greAppListKeyPath[MAX_BUF];
02382   char      greUninstaller[MAX_BUF];
02383   DWORD     idKeySize;
02384   DWORD     appListKeySize;
02385   DWORD     indexOfGREID;
02386   DWORD     indexOfGREAppList;
02387   int       rv = WIZ_OK;
02388   int       regRv = WIZ_OK;
02389   char      buf[MAX_BUF];
02390 
02391   DecryptString(greUninstaller, GRE_UNINSTALLER_FILE);
02392 
02393   _snprintf(buf, sizeof(buf), "    GRE Cleanup Orphans: %s\n", sgProduct.greCleanupOrphans ? "true" : "false");
02394   buf[sizeof(buf) - 1] = '\0';
02395   UpdateInstallStatusLog(buf);
02396 
02397   _snprintf(buf, sizeof(buf), "    GRE Uninstaller Path: %s\n", greUninstaller);
02398   buf[sizeof(buf) - 1] = '\0';
02399   UpdateInstallStatusLog(buf);
02400 
02401   _snprintf(buf, sizeof(buf), "    GRE Uninstaller found: %s\n", FileExists(greUninstaller) ? "true" : "false");
02402   buf[sizeof(buf) - 1] = '\0';
02403   UpdateInstallStatusLog(buf);
02404 
02405   // If greCleanupOrphans is false (set either in config.ini or passed in
02406   // thru the cmdline) or GRE's uninstaller file does not exist, then
02407   // simply do nothing and return.
02408   if(!sgProduct.greCleanupOrphans || !FileExists(greUninstaller))
02409   {
02410     _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return: %d\n", WIZ_OK);
02411     buf[sizeof(buf) - 1] = '\0';
02412     UpdateInstallStatusLog(buf);
02413     return(WIZ_OK);
02414   }
02415 
02416   // If GRE is installed locally, then use the private GRE key, else
02417   // use the default global GRE key in the windows registry.
02418   if(sgProduct.greType == GRE_LOCAL)
02419     DecryptString(greRegKey, sgProduct.grePrivateKey);
02420   else
02421     MozCopyStr(GRE_REG_KEY, greRegKey, sizeof(greRegKey));
02422 
02423   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, greRegKey, 0, KEY_READ, &greIDKeyHandle) != ERROR_SUCCESS)
02424   {
02425     _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return (RegOpenKeyEx: %s): %d\n", greRegKey, WIZ_ERROR_UNDEFINED);
02426     buf[sizeof(buf) - 1] = '\0';
02427     UpdateInstallStatusLog(buf);
02428     return(WIZ_ERROR_UNDEFINED);
02429   }
02430 
02431   // Build the list of GRE's given greRegKey.  For example, if greRegKey is:
02432   //
02433   //   HKLM\Software\mozilla.org\GRE
02434   //
02435   // then build a list of the GRE IDs inside this key.
02436   totalGreIDSubKeys = 0;
02437   regRv = RegQueryInfoKey(greIDKeyHandle, NULL, NULL, NULL, &totalGreIDSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
02438   if((regRv != ERROR_SUCCESS) || (totalGreIDSubKeys == 0))
02439   {
02440     rv = WIZ_ERROR_UNDEFINED;
02441     _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return (RegQueryInfoKey: all keys): %d\n", rv);
02442     buf[sizeof(buf) - 1] = '\0';
02443     UpdateInstallStatusLog(buf);
02444     return(rv);
02445   }
02446 
02447   if((rv == WIZ_OK) && (greIDListToClean = NS_GlobalAlloc(sizeof(char *) * totalGreIDSubKeys)) == NULL)
02448   {
02449     RegCloseKey(greIDKeyHandle);
02450     _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to allocate memory for greIDListToClean: %d\n", WIZ_OUT_OF_MEMORY);
02451     buf[sizeof(buf) - 1] = '\0';
02452     UpdateInstallStatusLog(buf);
02453     return(WIZ_OUT_OF_MEMORY);
02454   }
02455 
02456   // Show message that orphaned GREs are being cleaned up
02457   if(*sgProduct.greCleanupOrphansMessage != '\0')
02458     ShowMessage(sgProduct.greCleanupOrphansMessage, TRUE);
02459 
02460   if(rv == WIZ_OK)
02461   {
02462     // Initialize the array of pointers (of GRE ID keys) to NULL
02463     for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
02464       greIDListToClean[indexOfGREID] = NULL;
02465 
02466     // Enumerate the GRE ID list and save the GRE ID to each of its array element
02467     for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
02468     {
02469       idKeySize = sizeof(greKeyID);
02470       if(RegEnumKeyEx(greIDKeyHandle, indexOfGREID, greKeyID, &idKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
02471       {
02472         if((greIDListToClean[indexOfGREID] = NS_GlobalAlloc(sizeof(char) * (idKeySize + 1))) == NULL)
02473         {
02474           RegCloseKey(greIDKeyHandle);
02475           rv = WIZ_OUT_OF_MEMORY;
02476           _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to add %s to greIDListToClean[]: %d\n", greKeyID, rv);
02477           buf[sizeof(buf) - 1] = '\0';
02478           UpdateInstallStatusLog(buf);
02479           break;
02480         }
02481         MozCopyStr(greKeyID, greIDListToClean[indexOfGREID], idKeySize + 1);
02482       }
02483     }
02484     RegCloseKey(greIDKeyHandle);
02485 
02486     if(rv == WIZ_OK)
02487     {
02488       // Enumerate the GRE ID list built from above to get to each of it's AppList key.
02489       // The list that we need to build now is from the following key:
02490       //
02491       //   HKLM\Software\mozilla.org\GRE\[GRE ID]\AppList
02492       for(indexOfGREID = 0; indexOfGREID < totalGreIDSubKeys; indexOfGREID++)
02493       {
02494         // If we find the same GRE version as what we're trying to install,
02495         // then we don't want to process it because if we do, it will
02496         // uninstall it.  Which means that it'll reinstall it again.  We don't
02497         // want to have reinstall when we don't need to.
02498         //
02499         // szUserAgent is the GRE unique id if this instance of the installer is
02500         // installing GRE.
02501         if(strcmpi(sgProduct.szUserAgent, greIDListToClean[indexOfGREID]) == 0)
02502           continue;
02503 
02504         _snprintf(greAppListKeyPath, sizeof(greAppListKeyPath), "%s\\%s\\AppList",
02505             GRE_REG_KEY, greIDListToClean[indexOfGREID]);
02506         greAppListKeyPath[sizeof(greAppListKeyPath) - 1] = '\0';
02507         if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, greAppListKeyPath, 0, KEY_READ, &greAppListKeyHandle) != ERROR_SUCCESS)
02508         {
02509           rv = WIZ_ERROR_UNDEFINED;
02510           _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to open key %s: %d\n", greAppListKeyPath, rv);
02511           buf[sizeof(buf) - 1] = '\0';
02512           UpdateInstallStatusLog(buf);
02513           break;
02514         }
02515 
02516         totalGREAppListSubKeys = 0;
02517         if(RegQueryInfoKey(greAppListKeyHandle, NULL, NULL, NULL, &totalGREAppListSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
02518         {
02519           RegCloseKey(greAppListKeyHandle);
02520           rv = WIZ_ERROR_UNDEFINED;
02521           _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to regquery for all keys in %s: %d\n", greAppListKeyPath, rv);
02522           buf[sizeof(buf) - 1] = '\0';
02523           UpdateInstallStatusLog(buf);
02524           break;
02525         }
02526     
02527         if((rv == WIZ_OK) && (greAppListToClean = NS_GlobalAlloc(sizeof(char *) * totalGREAppListSubKeys)) == NULL)
02528         {
02529           RegCloseKey(greAppListKeyHandle);
02530           rv = WIZ_OUT_OF_MEMORY;
02531           _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to allocate memory for greAppListToClean: %d\n", rv);
02532           buf[sizeof(buf) - 1] = '\0';
02533           UpdateInstallStatusLog(buf);
02534           break;
02535         }
02536 
02537         // Initialize the GREAppList elements to NULL.
02538         for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
02539           greAppListToClean[indexOfGREAppList] = NULL;
02540 
02541         // enumerate the GRE AppList key and build a list.
02542         for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
02543         {
02544           appListKeySize = sizeof(greKeyAppList);
02545           if(RegEnumKeyEx(greAppListKeyHandle, indexOfGREAppList, greKeyAppList, &appListKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
02546           {
02547             if((greAppListToClean[indexOfGREAppList] = NS_GlobalAlloc(sizeof(char) * (appListKeySize + 1))) == NULL)
02548             {
02549               RegCloseKey(greAppListKeyHandle);
02550               rv = WIZ_OUT_OF_MEMORY;
02551               _snprintf(buf, sizeof(buf), "    Cleanup Orphaned GRE premature return.  Failed to add %s to greAppListToClean[]: %d\n", greKeyAppList, rv);
02552               buf[sizeof(buf) - 1] = '\0';
02553               UpdateInstallStatusLog(buf);
02554               break;
02555             }
02556             MozCopyStr(greKeyAppList, greAppListToClean[indexOfGREAppList], appListKeySize + 1);
02557           }
02558         }
02559         RegCloseKey(greAppListKeyHandle);
02560 
02561         if(rv != WIZ_OK)
02562           break;
02563 
02564         UpdateInstallStatusLog("\n    Cleanup Orphaned GRE's uninstall commandline:\n");
02565         // Enumerate the saved GREAppList and start calling GREUninstall.exe
02566         // to remove them if appropriate.
02567         // GREUninstall.exe will take care of determining if the particular
02568         // GRE should be fully removed or not.
02569         // We need to enumerate the list again instead of doing this in the
02570         // save loop as above because deleting keys while at the same time
02571         // enumerating thru its parent key is a Bad Thing(TM).
02572         for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
02573         {
02574           char programNamePath[MAX_BUF];
02575           char greUninstallParam[MAX_BUF];
02576 
02577           DecryptString(programNamePath, sgProduct.szAppPath);
02578           _snprintf(greUninstallParam, sizeof(greUninstallParam), "-mmi -ms -ua \"%s\" -app \"%s\" -app_path \"%s\"",
02579               greIDListToClean[indexOfGREID], greAppListToClean[indexOfGREAppList], programNamePath);
02580           greUninstallParam[sizeof(greUninstallParam) - 1] = '\0';
02581           UpdateInstallStatusLog("        ");
02582           UpdateInstallStatusLog(greUninstallParam);
02583           UpdateInstallStatusLog("\n");
02584           WinSpawn(greUninstaller, greUninstallParam, szTempDir, SW_SHOWNORMAL, WS_WAIT);
02585         }
02586 
02587         // Cleanup allocated memory
02588         for(indexOfGREAppList = 0; indexOfGREAppList < totalGREAppListSubKeys; indexOfGREAppList++)
02589           FreeMemory(&greAppListToClean[indexOfGREAppList]);
02590         if(greAppListToClean)
02591           GlobalFree(greAppListToClean);
02592       }
02593     }
02594   }
02595 
02596   //
02597   // Cleanup allocated memory
02598   CleanupArrayList(greIDListToClean, totalGreIDSubKeys);
02599   if(greIDListToClean)
02600     GlobalFree(greIDListToClean);
02601 
02602   // Hide message that orphaned GREs are being cleaned up
02603   if(*sgProduct.greCleanupOrphansMessage != '\0')
02604     ShowMessage(sgProduct.greCleanupOrphansMessage, FALSE);
02605 
02606   return(rv);
02607 }
02608 
02609 void LaunchOneComponent(siC *siCObject, greInfo *aGre)
02610 {
02611   BOOL      bArchiveFound;
02612   char      szArchive[MAX_BUF];
02613   char      szMsg[MAX_BUF];
02614 
02615   if(!siCObject)
02616     /* nothing to do return */
02617     return;
02618 
02619   GetPrivateProfileString("Messages", "MSG_CONFIGURING", "", szMsg, sizeof(szMsg), szFileIniInstall);
02620 
02621   /* launch 3rd party executable */
02622   if((siCObject->dwAttributes & SIC_SELECTED) && (siCObject->dwAttributes & SIC_LAUNCHAPP))
02623   {
02624     bArchiveFound = TRUE;
02625     lstrcpy(szArchive, sgProduct.szAlternateArchiveSearchPath);
02626     AppendBackSlash(szArchive, sizeof(szArchive));
02627     lstrcat(szArchive, siCObject->szArchiveName);
02628     if((*sgProduct.szAlternateArchiveSearchPath == '\0') || !FileExists(szArchive))
02629     {
02630       lstrcpy(szArchive, szSetupDir);
02631       AppendBackSlash(szArchive, sizeof(szArchive));
02632       lstrcat(szArchive, siCObject->szArchiveName);
02633       if(!FileExists(szArchive))
02634       {
02635         lstrcpy(szArchive, szTempDir);
02636         AppendBackSlash(szArchive, sizeof(szArchive));
02637         lstrcat(szArchive, siCObject->szArchiveName);
02638         if(!FileExists(szArchive))
02639         {
02640           bArchiveFound = FALSE;
02641         }
02642       }
02643     }
02644 
02645     if(bArchiveFound)
02646     {
02647       char szParameterBuf[MAX_BUF];
02648       char szSpawnFile[MAX_BUF];
02649       char szMessageString[MAX_BUF];
02650       DWORD dwErr = FO_SUCCESS;
02651 
02652       *szMessageString = '\0';
02653       if(*szMsg != '\0')
02654       {
02655         wsprintf(szMessageString, szMsg, siCObject->szDescriptionShort);
02656         ShowMessage(szMessageString, TRUE);
02657       }
02658 
02659       DecryptString(szParameterBuf, siCObject->szParameter);
02660       lstrcpy(szSpawnFile, szArchive);
02661       if(siCObject->dwAttributes & SIC_UNCOMPRESS)
02662       {
02663         if((dwErr = FileUncompress(szArchive, szTempDir)) == FO_SUCCESS)
02664         {
02665           lstrcpy(szSpawnFile, szTempDir);
02666           AppendBackSlash(szSpawnFile, sizeof(szSpawnFile));
02667           lstrcat(szSpawnFile, siCObject->szArchiveNameUncompressed);
02668         }
02669 
02670         LogISLaunchAppsComponentUncompress(siCObject->szDescriptionShort, dwErr);
02671         if(dwErr != FO_SUCCESS)
02672         {
02673           if(*szMessageString != '\0')
02674             ShowMessage(szMessageString, FALSE);
02675           return;
02676         }
02677       }
02678 
02679       if(aGre)
02680       {
02681         GetInfoFromGreInstaller(szSpawnFile, aGre);
02682         UpdateGreInstallerCmdLine(aGre, szParameterBuf, sizeof(szParameterBuf), FOR_NEW_GRE);
02683       }
02684 
02685       LogISLaunchAppsComponent(siCObject->szDescriptionShort);
02686       WinSpawn(szSpawnFile, szParameterBuf, szTempDir, SW_SHOWNORMAL, WS_WAIT);
02687 
02688       if(siCObject->dwAttributes & SIC_UNCOMPRESS)
02689         FileDelete(szSpawnFile);
02690 
02691       if(*szMessageString != '\0')
02692         ShowMessage(szMessageString, FALSE);
02693     }
02694   }
02695 }
02696 
02697 void LaunchExistingGreInstaller(greInfo *aGre)
02698 {
02699   char      szMsg[MAX_BUF];
02700   char      szParameterBuf[MAX_BUF];
02701   char      szMessageString[MAX_BUF];
02702   siC       *siCObject = aGre->siCGreComponent;
02703 
02704   if((!siCObject) || !FileExists(aGre->installerAppPath))
02705     /* nothing to do return */
02706     return;
02707 
02708   GetPrivateProfileString("Messages", "MSG_CONFIGURING", "", szMsg, sizeof(szMsg), szFileIniInstall);
02709 
02710   *szMessageString = '\0';
02711   if(*szMsg != '\0')
02712   {
02713     wsprintf(szMessageString, szMsg, siCObject->szDescriptionShort);
02714     ShowMessage(szMessageString, TRUE);
02715   }
02716 
02717   DecryptString(szParameterBuf, siCObject->szParameter);
02718   UpdateGreInstallerCmdLine(NULL, szParameterBuf, sizeof(szParameterBuf), FOR_EXISTING_GRE);
02719   LogISLaunchAppsComponent(siCObject->szDescriptionShort);
02720   WinSpawn(aGre->installerAppPath, szParameterBuf, szTempDir, SW_SHOWNORMAL, WS_WAIT);
02721   if(*szMessageString != '\0')
02722     ShowMessage(szMessageString, FALSE);
02723 }
02724 
02725 HRESULT LaunchApps()
02726 {
02727   DWORD     dwIndex0;
02728   siC       *siCObject = NULL;
02729 
02730   LogISLaunchApps(W_START);
02731   dwIndex0 = 0;
02732   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
02733   while(siCObject)
02734   {
02735     /* launch 3rd party executable */
02736     LaunchOneComponent(siCObject, NULL);
02737     ++dwIndex0;
02738     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
02739   }
02740 
02741   LogISLaunchApps(W_END);
02742   return(0);
02743 }
02744 
02745 /* Function: IsPathWithinWindir()
02746  *       in: char *aTargetPath
02747  *      out: returns a BOOL type indicating whether the install path chosen
02748  *           by the user is within the %windir% or not.
02749  *  purpose: To see if aTargetPath is within the %windir% path.
02750  */
02751 BOOL IsPathWithinWindir(char *aTargetPath)
02752 {
02753   char windir[MAX_PATH];
02754   char targetPath[MAX_PATH];
02755 
02756   assert(aTargetPath);
02757 
02758   if(GetWindowsDirectory(windir, sizeof(windir)))
02759   {
02760     MozCopyStr(aTargetPath, targetPath, sizeof(targetPath));
02761     AppendBackSlash(targetPath, sizeof targetPath);
02762     CharUpperBuff(targetPath, sizeof(targetPath));
02763     AppendBackSlash(windir, sizeof(windir));
02764     CharUpperBuff(windir, sizeof(windir));
02765     if(strstr(targetPath, windir) == targetPath)
02766       return(TRUE);
02767   }
02768   else
02769   {
02770     /* If we can't get the windows path, just show error message and assume
02771      * the install path is not within the windows dir. */
02772     char szEGetWindirFailed[MAX_BUF];
02773 
02774     if(GetPrivateProfileString("Messages", "ERROR_GET_WINDOWS_DIRECTORY_FAILED", "", szEGetWindirFailed, sizeof(szEGetWindirFailed), szFileIniInstall))
02775       PrintError(szEGetWindirFailed, ERROR_CODE_SHOW);
02776   }
02777   return(FALSE);
02778 }
02779 
02780 /* Function: CleanupArrayList()
02781  *       in: char **aList - array to cleanup
02782  *           int  aListLength - length of array
02783  *      out: none.
02784  *  purpose: Cleans up memory.
02785  */
02786 void CleanupArrayList(char **aList, int aListLength)
02787 {
02788   int index = 0;
02789 
02790   // Free allocated memory
02791   for(index = 0; index < aListLength; index++)
02792     FreeMemory(&aList[index]);
02793 }
02794 
02795 /* Function: GetTotalNumKeys()
02796  *       in: char *aSectionName - name of section to get info on
02797  *           char *aBaseKeyName - base name of key to count
02798  *      out: none.
02799  *  purpose: To get the total number of 'aBaseKeyName's in aSection.
02800  *           A base key name is just the name of the key without the
02801  *           numbers, ie:
02802  *             base key name          : Object
02803  *             actual key in .ini file: Object0, Object1, etc...
02804  */
02805 int GetTotalNumKeys(char *aSectionName, char *aBaseKeyName)
02806 {
02807   int index = 0;
02808   char keyName[MAX_BUF_TINY];
02809   char buf[MAX_BUF];
02810 
02811   assert(aSectionName);
02812   assert(aBaseKeyName);
02813 
02814   _snprintf(keyName, sizeof(keyName), "%s%d", aBaseKeyName, index);
02815   keyName[sizeof(keyName) - 1] = '\0';
02816   GetConfigIniProfileString(aSectionName, keyName, "", buf, sizeof(buf));
02817   while(*buf != '\0')
02818   {
02819     ++index;
02820     _snprintf(keyName, sizeof(keyName), "%s%d", aBaseKeyName, index);
02821     keyName[sizeof(keyName) - 1] = '\0';
02822     GetConfigIniProfileString(aSectionName, keyName, "", buf, sizeof(buf));
02823   }
02824 
02825   return(index);
02826 }
02827 
02828 /* Function: BuildArrayList()
02829  *       in: char *aSectionName - section name to look for info to build array
02830  *           char *aBaseKeyName - base key name to use to build array from
02831  *      out: returns char ** - array list built
02832  *           int *aArrayLength - length of array built
02833  *  purpose: To build an Array list given the aSectionName and aBaseKeyName.
02834  *           Caller is responsible for cleaning up of allocated memory done
02835  *           in this function!
02836  */
02837 char **BuildArrayList(char *aSectionName, char *aBaseKeyName, int *aArrayLength)
02838 {
02839   int index = 0;
02840   int totalKeys = 0;
02841   char **list;
02842   char keyName[MAX_BUF_TINY];
02843   char buf[MAX_BUF];
02844 
02845   *aArrayLength = 0;
02846   totalKeys = GetTotalNumKeys(aSectionName, aBaseKeyName);
02847 
02848   // if totalKeys is <= 0, then there's nothing to do.
02849   if(totalKeys <= 0)
02850     return(NULL);
02851 
02852   if((list = NS_GlobalAlloc(sizeof(char *) * totalKeys)) == NULL)
02853     return(NULL);
02854 
02855   // Create and initialize the array of pointers
02856   for(index = 0; index < totalKeys; index++)
02857   {
02858     // build the actual key name to use.
02859     _snprintf(keyName, sizeof(keyName), "%s%d", aBaseKeyName, index);
02860     keyName[sizeof(keyName) - 1] = '\0';
02861     GetConfigIniProfileString(aSectionName, keyName, "", buf, sizeof(buf));
02862     if(*buf != '\0')
02863     {
02864       if((list[index] = NS_GlobalAlloc(sizeof(char) * (lstrlen(buf) + 1))) == NULL)
02865       {
02866         // couldn't allocate memory for an array, cleanup the array list that
02867         // has been currently built, and return NULL.
02868         CleanupArrayList(list, index);
02869         if(list)
02870           GlobalFree(list);
02871 
02872         return(NULL);
02873       }
02874       MozCopyStr(buf, list[index], lstrlen(buf) + 1);
02875     }
02876     else
02877       list[index] = NULL;
02878   }
02879   *aArrayLength = index;
02880 
02881   // caller is responsible for garbage cleanup of list.
02882   return(list);
02883 }
02884 
02885 /* Function: IsDirAProfileDir()
02886  *       in: char *aParentPath - path to start the check.
02887  *           char **aListProfileObjects - array list of profile files/dirs to
02888  *                  use to determine if a dir is a profile dir or not.
02889  *           int  aListLength
02890  *      out: BOOL
02891  *  purpose: To check to see if a dir is a profile dir or not.  If any of it's
02892  *           subdirectories is a profile dir, then the initial aParentPath is
02893  *           considered to be a profile dir.
02894  */
02895 BOOL IsDirAProfileDir(char *aParentPath, char **aListProfileObjects, int aListLength)
02896 {
02897   HANDLE          fileHandle;
02898   WIN32_FIND_DATA fdFile;
02899   char            destPathTemp[MAX_BUF];
02900   BOOL            found;
02901   BOOL            isProfileDir;
02902   int             index;
02903 
02904   if((aListLength <= 0) || !aListProfileObjects || !*aListProfileObjects)
02905     return(FALSE);
02906 
02907   /* check the initial aParentPath to see if the dir contains the
02908    * files/dirs that contitute a profile dir */
02909   isProfileDir = TRUE;
02910   for(index = 0; index < aListLength; index++)
02911   {
02912     /* create full path */
02913     _snprintf(destPathTemp, sizeof(destPathTemp), "%s\\%s", aParentPath, aListProfileObjects[index]);
02914     destPathTemp[sizeof(destPathTemp) - 1] = '\0';
02915 
02916     /* if any of the files/dirs that make up a profile dir is missing,
02917      * then it's not a profile dir */
02918     if(!FileExists(destPathTemp))
02919     {
02920       isProfileDir = FALSE;
02921       break;
02922     }
02923   }
02924 
02925   /* If it's determined to be a profile dir, then return immediately.  If it's
02926    * not, then continue searching the other dirs to see if any constitute a
02927    * profile dir. */
02928   if(isProfileDir)
02929     return(TRUE);
02930 
02931   _snprintf(destPathTemp, sizeof(destPathTemp), "%s\\*", aParentPath);
02932   destPathTemp[sizeof(destPathTemp) - 1] = '\0';
02933 
02934   found = TRUE;
02935   fileHandle = FindFirstFile(destPathTemp, &fdFile);
02936   while((fileHandle != INVALID_HANDLE_VALUE) && found)
02937   {
02938     if((lstrcmpi(fdFile.cFileName, ".") != 0) && (lstrcmpi(fdFile.cFileName, "..") != 0))
02939     {
02940       // if it's a directory, there we need to traverse it to see if there are
02941       // dirs that are profile dirs.
02942       if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
02943       {
02944         _snprintf(destPathTemp, sizeof(destPathTemp), "%s\\%s", aParentPath, fdFile.cFileName);
02945         destPathTemp[sizeof(destPathTemp) - 1] = '\0';
02946         isProfileDir = IsDirAProfileDir(destPathTemp, aListProfileObjects, aListLength);
02947         if(isProfileDir)
02948           break;
02949           
02950       }
02951     }
02952     found = FindNextFile(fileHandle, &fdFile);
02953   }
02954 
02955   FindClose(fileHandle);
02956   return(isProfileDir);
02957 }
02958 
02959 /* Function: IsOkToRemoveFileOrDir()
02960  *       in: char *aFileOrDirname
02961  *      out: bool return type
02962  *  purpose: To check if the file or dirname is not in the aListToIgnore.
02963  */
02964 BOOL IsOkToRemoveFileOrDirname(char *aFileOrDirname, char **aListToIgnore,
02965     int aListToIgnoreLength, char **aListProfileObjects, int aListProfileLength)
02966 {
02967   int  i;
02968   char filename[MAX_BUF];
02969 
02970   if(!aListToIgnore || !*aListToIgnore)
02971     return(TRUE);
02972 
02973   ParsePath(aFileOrDirname, filename, sizeof(filename), FALSE, PP_FILENAME_ONLY);
02974 
02975   // check to see if this is a profile folder
02976   if(FileExists(aFileOrDirname) & FILE_ATTRIBUTE_DIRECTORY)
02977     if(IsDirAProfileDir(aFileOrDirname, aListProfileObjects, aListProfileLength))
02978       return(FALSE);
02979 
02980   for(i = 0; i < aListToIgnoreLength; i++)
02981   {
02982     if(lstrcmpi(filename, aListToIgnore[i]) == 0)
02983       return(FALSE);
02984   }
02985   return(TRUE);
02986 }
02987 
02988 /* Function: CleanupOnUpgrade()
02989  *       in: none.
02990  *      out: none.
02991  *  purpose: To cleanup/remove files and dirs within the user chosen
02992  *           installation path, excluding the list in
02993  *           aListToIgnore.
02994  */
02995 void CleanupOnUpgrade()
02996 {
02997   HANDLE          fileHandle;
02998   WIN32_FIND_DATA fdFile;
02999   char            destPathTemp[MAX_BUF];
03000   char            targetPath[MAX_BUF];
03001   char            buf[MAX_BUF];
03002   BOOL            found;
03003   char            **listObjectsToIgnore;
03004   int             listTotalObjectsToIgnore;
03005   char            **listProfileObjects;
03006   int             listTotalProfileObjects;
03007   int             index;
03008 
03009   MozCopyStr(sgProduct.szPath, targetPath, sizeof(targetPath));
03010   RemoveBackSlash(targetPath);
03011 
03012   if(!FileExists(targetPath))
03013     return;
03014 
03015   UpdateInstallStatusLog("\n    Files/Dirs deleted on upgrade:\n");
03016 
03017   /* Check to see if the installation path is within the %windir%.  If so,
03018    * warn the user and do not delete any file! */
03019   if(IsPathWithinWindir(targetPath))
03020   {
03021     if(sgProduct.mode == NORMAL)
03022     {
03023       GetConfigIniProfileString("Strings", "Message Cleanup On Upgrade Windir", "",
03024                                 buf, sizeof(buf));
03025       MessageBox(hWndMain, buf, NULL, MB_ICONEXCLAMATION);
03026     }
03027 
03028     _snprintf(buf, sizeof(buf), "        None.  Installation path is within %windir%:\n            %s\n", targetPath);
03029     buf[sizeof(buf) - 1] = '\0';
03030     UpdateInstallStatusLog(buf);
03031     return;
03032   }
03033 
03034   // param1: section name
03035   // param2: base key name within section name
03036   //         ie: ObjectToIgnore0=
03037   //             ObjectToIgnore1=
03038   //             ObjectToIgnore2=
03039   listObjectsToIgnore = BuildArrayList("Cleanup On Upgrade", "ObjectToIgnore", &listTotalObjectsToIgnore);
03040   listProfileObjects  = BuildArrayList("Profile Dir Object List", "Object", &listTotalProfileObjects);
03041 
03042   _snprintf(destPathTemp, sizeof(destPathTemp), "%s\\*", targetPath);
03043   destPathTemp[sizeof(destPathTemp) - 1] = '\0';
03044 
03045   found = TRUE;
03046   fileHandle = FindFirstFile(destPathTemp, &fdFile);
03047   while((fileHandle != INVALID_HANDLE_VALUE) && found)
03048   {
03049     if((lstrcmpi(fdFile.cFileName, ".") != 0) && (lstrcmpi(fdFile.cFileName, "..") != 0))
03050     {
03051       /* create full path */
03052       _snprintf(destPathTemp, sizeof(destPathTemp), "%s\\%s", targetPath, fdFile.cFileName);
03053       destPathTemp[sizeof(destPathTemp) - 1] = '\0';
03054 
03055       if(IsOkToRemoveFileOrDirname(destPathTemp, listObjectsToIgnore,
03056             listTotalObjectsToIgnore, listProfileObjects, listTotalProfileObjects))
03057       {
03058         if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
03059         {
03060           AppendBackSlash(destPathTemp, sizeof(destPathTemp));
03061           DirectoryRemove(destPathTemp, TRUE);
03062         }
03063         else
03064           DeleteFile(destPathTemp);
03065 
03066         /* Check to see if the file/dir was deleted successfully */
03067         if(!FileExists(destPathTemp))
03068           _snprintf(buf, sizeof(buf), "        ok: %s\n", destPathTemp);
03069         else
03070           _snprintf(buf, sizeof(buf), "    failed: %s\n", destPathTemp);
03071       }
03072       else
03073         _snprintf(buf, sizeof(buf), "   skipped: %s\n", destPathTemp);
03074 
03075       buf[sizeof(buf) - 1] = '\0';
03076       UpdateInstallStatusLog(buf);
03077     }
03078 
03079     found = FindNextFile(fileHandle, &fdFile);
03080   }
03081 
03082   FindClose(fileHandle);
03083 
03084   // Log the array lists to make sure it matches the list of files/dirs that
03085   // were processed.
03086   UpdateInstallStatusLog("\n    Files/Dirs list to ignore:\n");
03087   for(index = 0; index < listTotalObjectsToIgnore; index++)
03088   {
03089     _snprintf(buf, sizeof(buf), "        ObjectToIgnore%d: %s\n", index + 1, listObjectsToIgnore[index]);
03090     buf[sizeof(buf) - 1] = '\0';
03091     UpdateInstallStatusLog(buf);
03092   }
03093 
03094   CleanupArrayList(listObjectsToIgnore, listTotalObjectsToIgnore);
03095   if(listObjectsToIgnore)
03096     GlobalFree(listObjectsToIgnore);
03097 
03098   UpdateInstallStatusLog("\n    Files/Dirs list to verify dir is a Profile dir:\n");
03099   for(index = 0; index < listTotalProfileObjects; index++)
03100   {
03101     _snprintf(buf, sizeof(buf), "        Object%d: %s\n", index + 1, listProfileObjects[index]);
03102     buf[sizeof(buf) - 1] = '\0';
03103     UpdateInstallStatusLog(buf);
03104   }
03105 
03106   CleanupArrayList(listProfileObjects, listTotalProfileObjects);
03107   if(listProfileObjects)
03108     GlobalFree(listProfileObjects);
03109 
03110 }
03111 
03112 /* Function: ProcessGre()
03113  *       in: none.
03114  *      out: path to where GRE is installed at.
03115  *  purpose: To install GRE on the system, so this installer can use it's
03116  *           xpinstall engine.  It uses gre->homePath to see if GRE is already
03117  *           installed on the system.  If GRE is already present on the system,
03118  *           gre->homePath is guaranteed to contain it's destination path.
03119  */
03120 HRESULT ProcessGre(greInfo *aGre)
03121 {
03122   char greUninstallCommand[MAX_BUF];
03123 
03124   if(!aGre)
03125     return(WIZ_OK);
03126 
03127   /* If aGre->homePath does not exist, it means that a compatible version of GRE was
03128    * not found on the system, so we need to install one.  We also need to get the
03129    * path to where it's going to install the GRE for in case we need to use it
03130    * as the xpinstall engine.
03131    *
03132    * If gbForceInstallGre is true, then force an installation of GRE regardless
03133    * if it's already on the system.  Also save the GRE's destination path to
03134    * aGre->homePath.
03135    *
03136    * If aGre->homePath does exist, then we simply call LaunchExistingGreInstaller()
03137    * to run the existing GRE's installer app to register mozilla.
03138    */
03139   UpdateInstallStatusLog("\n");
03140   if((*aGre->homePath == '\0') || (gbForceInstallGre))
03141     LaunchOneComponent(aGre->siCGreComponent, aGre);
03142   else
03143     LaunchExistingGreInstaller(aGre);
03144 
03145   /* XXX instead of unsetting the SELECTED attribute, set the DOWNLOAD_ONLY attribute
03146    * in the config.ini file.
03147    */
03148   /* Unset "Component GRE"'s SELECTED attribute so it doesn't get spawned again later from LaunchApps() */
03149   gGreInstallerHasRun = TRUE;
03150   if(aGre->siCGreComponent)
03151     aGre->siCGreComponent->dwAttributes &= ~SIC_SELECTED;
03152 
03153   /* Log the GRE uninstall command to call in order for this app's uninstaller to
03154    * uninstall GRE.
03155    */
03156   if(GetInfoFromInstalledGreConfigIni(aGre) == WIZ_OK)
03157   {
03158     /* If were installing GRE locally, then update the app's uninstall command
03159      * to pass the local/private windows GRE key path to GRE's uninstaller
03160      * during uninstall. */
03161     if(sgProduct.greType == GRE_LOCAL)
03162       wsprintf(greUninstallCommand,
03163                "\"%s\" -mmi -ms -app \"%s %s\" -ua \"%s\" -reg_path %s",
03164                aGre->uninstallerAppPath,
03165                sgProduct.szProductNameInternal,
03166                sgProduct.szUserAgent,
03167                aGre->userAgent,
03168                sgProduct.grePrivateKey);
03169     else
03170       wsprintf(greUninstallCommand,
03171                "\"%s\" -mmi -ms -app \"%s %s\" -ua \"%s\"",
03172                aGre->uninstallerAppPath,
03173                sgProduct.szProductNameInternal,
03174                sgProduct.szUserAgent,
03175                aGre->userAgent);
03176     UpdateInstallLog(KEY_UNINSTALL_COMMAND, greUninstallCommand, DNU_UNINSTALL);
03177   }
03178   return(WIZ_OK);
03179 }
03180 
03181 /* Function: GetXpinstallPath()
03182  *       in: none.
03183  *      out: path to where xpinstall engine is at.
03184  *  purpose: To retrieve the full path of where a valid xpinstall engine is
03185  *           installed at.
03186  *           * If we're using xpcom.xpi, then append 'bin' to the returned
03187  *             path because when xpcom.xpi is uncompressed, xpinstall will be
03188  *             within a 'bin' subdir.
03189  *           * If we're using GRE, then simply just return the GRE
03190  *             destination path.
03191  */
03192 void GetXpinstallPath(char *aPath, int aPathBufSize)
03193 {
03194   if(siCFXpcomFile.bStatus == STATUS_ENABLED)
03195   {
03196     MozCopyStr(siCFXpcomFile.szDestination, aPath, aPathBufSize);
03197     AppendBackSlash(aPath, aPathBufSize);
03198     lstrcat(aPath, "bin");
03199   }
03200   else
03201     MozCopyStr(gGre.homePath, aPath, aPathBufSize);
03202 }
03203 
03204 /* Function: ProcessXpinstallEngine()
03205  *       in: none.
03206  *      out: none.
03207  *  purpose: To setup the xpinstall engine either by:
03208  *             1) uncompressing xpcom.xpi into the temp dir.
03209  *             2) locating existing compatible version of GRE.
03210  *             3) installing GRE that was downloaded with this product.
03211  *
03212  *           Since GRE installer uses the same native installer as the Mozilla
03213  *           installer, xpcom.xpi should be used only by the GRE installer.
03214  *           All other installers should be using GRE (either finding one on
03215  *           the local system, or installer its own copy).
03216  */
03217 HRESULT ProcessXpinstallEngine()
03218 {
03219   HRESULT rv = WIZ_OK;
03220 
03221   /* If product to be installed is _not_ GRE, then call ProcessGRE.
03222    * ProcessGre() will either install GRE or simply run the existing
03223    * GRE's installer that's already on the system.  This will setup
03224    * GRE so it can be used as the xpinstall engine (if it's needed).
03225    */
03226   if(!IsInstallerProductGRE())
03227     rv = ProcessGre(&gGre);
03228 
03229   if((WIZ_OK == rv) && (siCFXpcomFile.bStatus == STATUS_ENABLED))
03230     rv = ProcessXpcomFile();
03231 
03232   return(rv);
03233 }
03234 
03235 char *GetOSTypeString(char *szOSType, DWORD dwOSTypeBufSize)
03236 {
03237   ZeroMemory(szOSType, dwOSTypeBufSize);
03238 
03239   if(gSystemInfo.dwOSType & OS_WIN95_DEBUTE)
03240     lstrcpy(szOSType, "Win95 debute");
03241   else if(gSystemInfo.dwOSType & OS_WIN95)
03242     lstrcpy(szOSType, "Win95");
03243   else if(gSystemInfo.dwOSType & OS_WIN98)
03244     lstrcpy(szOSType, "Win98");
03245   else if(gSystemInfo.dwOSType & OS_NT3)
03246     lstrcpy(szOSType, "NT3");
03247   else if(gSystemInfo.dwOSType & OS_NT4)
03248     lstrcpy(szOSType, "NT4");
03249   else if(gSystemInfo.dwOSType & OS_NT50)
03250     lstrcpy(szOSType, "NT50");
03251   else if(gSystemInfo.dwOSType & OS_NT51)
03252     lstrcpy(szOSType, "NT51");
03253   else
03254     lstrcpy(szOSType, "NT5");
03255 
03256   return(szOSType);
03257 }
03258 
03259 void DetermineOSVersionEx()
03260 {
03261   BOOL          bIsWin95Debute;
03262   char          szBuf[MAX_BUF];
03263   char          szOSType[MAX_BUF];
03264   char          szESetupRequirement[MAX_BUF];
03265   DWORD         dwStrLen;
03266   OSVERSIONINFO osVersionInfo;
03267   MEMORYSTATUS  msMemoryInfo;
03268 
03269   gSystemInfo.dwOSType = 0;
03270   osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
03271   if(!GetVersionEx(&osVersionInfo))
03272   {
03273     /* GetVersionEx() failed for some reason.  It's not fatal, but could cause
03274      * some complications during installation */
03275     char szEMsg[MAX_BUF_TINY];
03276 
03277     if(GetPrivateProfileString("Messages", "ERROR_GETVERSION", "", szEMsg, sizeof(szEMsg), szFileIniInstall))
03278       PrintError(szEMsg, ERROR_CODE_SHOW);
03279   }
03280 
03281   bIsWin95Debute  = IsWin95Debute();
03282   switch(osVersionInfo.dwPlatformId)
03283   {
03284     case VER_PLATFORM_WIN32_WINDOWS:
03285       gSystemInfo.dwOSType |= OS_WIN9x;
03286       if(osVersionInfo.dwMinorVersion == 0)
03287       {
03288         gSystemInfo.dwOSType |= OS_WIN95;
03289         if(bIsWin95Debute)
03290           gSystemInfo.dwOSType |= OS_WIN95_DEBUTE;
03291       }
03292       else
03293         gSystemInfo.dwOSType |= OS_WIN98;
03294       break;
03295 
03296     case VER_PLATFORM_WIN32_NT:
03297       gSystemInfo.dwOSType |= OS_NT;
03298       switch(osVersionInfo.dwMajorVersion)
03299       {
03300         case 3:
03301           gSystemInfo.dwOSType |= OS_NT3;
03302           break;
03303 
03304         case 4:
03305           gSystemInfo.dwOSType |= OS_NT4;
03306           break;
03307 
03308         default:
03309           gSystemInfo.dwOSType |= OS_NT5;
03310           switch(osVersionInfo.dwMinorVersion)
03311           {
03312             case 0:
03313               /* a minor version of 0 (major.minor.build) indicates Win2000 */
03314               gSystemInfo.dwOSType |= OS_NT50;
03315               break;
03316 
03317             case 1:
03318               /* a minor version of 1 (major.minor.build) indicates WinXP */
03319               gSystemInfo.dwOSType |= OS_NT51;
03320           break;
03321       }
03322       break;
03323       }
03324       break;
03325 
03326     default:
03327       if(GetPrivateProfileString("Messages", "ERROR_SETUP_REQUIREMENT", "", szESetupRequirement, sizeof(szESetupRequirement), szFileIniInstall))
03328         PrintError(szESetupRequirement, ERROR_CODE_HIDE);
03329       break;
03330   }
03331 
03332   gSystemInfo.dwMajorVersion = osVersionInfo.dwMajorVersion;
03333   gSystemInfo.dwMinorVersion = osVersionInfo.dwMinorVersion;
03334   gSystemInfo.dwBuildNumber  = (DWORD)(LOWORD(osVersionInfo.dwBuildNumber));
03335 
03336   dwStrLen = sizeof(gSystemInfo.szExtraString) >
03337                     lstrlen(osVersionInfo.szCSDVersion) ?
03338                     lstrlen(osVersionInfo.szCSDVersion) :
03339                     sizeof(gSystemInfo.szExtraString) - 1;
03340   ZeroMemory(gSystemInfo.szExtraString, sizeof(gSystemInfo.szExtraString));
03341   strncpy(gSystemInfo.szExtraString, osVersionInfo.szCSDVersion, dwStrLen);
03342 
03343   msMemoryInfo.dwLength = sizeof(MEMORYSTATUS);
03344   GlobalMemoryStatus(&msMemoryInfo);
03345   gSystemInfo.dwMemoryTotalPhysical = msMemoryInfo.dwTotalPhys/1024;
03346   gSystemInfo.dwMemoryAvailablePhysical = msMemoryInfo.dwAvailPhys/1024;
03347 
03348   GetOSTypeString(szOSType, sizeof(szOSType));
03349   wsprintf(szBuf,
03350 "    System Info:\n\
03351         OS Type: %s\n\
03352         Major Version: %d\n\
03353         Minor Version: %d\n\
03354         Build Number: %d\n\
03355         Extra String: %s\n\
03356         Total Physical Memory: %dKB\n\
03357         Total Available Physical Memory: %dKB\n",
03358            szOSType,
03359            gSystemInfo.dwMajorVersion,
03360            gSystemInfo.dwMinorVersion,
03361            gSystemInfo.dwBuildNumber,
03362            gSystemInfo.szExtraString,
03363            gSystemInfo.dwMemoryTotalPhysical,
03364            gSystemInfo.dwMemoryAvailablePhysical);
03365 
03366   UpdateInstallStatusLog(szBuf);
03367 }
03368 
03369 HRESULT WinSpawn(LPSTR szClientName, LPSTR szParameters, LPSTR szCurrentDir, int iShowCmd, BOOL bWait)
03370 {
03371   SHELLEXECUTEINFO seInfo;
03372 
03373   seInfo.cbSize       = sizeof(SHELLEXECUTEINFO);
03374   seInfo.fMask        = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS;
03375   seInfo.hwnd         = hWndMain;
03376   seInfo.lpVerb       = NULL;
03377   seInfo.lpFile       = szClientName;
03378   seInfo.lpParameters = szParameters;
03379   seInfo.lpDirectory  = szCurrentDir;
03380   seInfo.nShow        = SW_SHOWNORMAL;
03381   seInfo.hInstApp     = 0;
03382   seInfo.lpIDList     = NULL;
03383   seInfo.lpClass      = NULL;
03384   seInfo.hkeyClass    = 0;
03385   seInfo.dwHotKey     = 0;
03386   seInfo.hIcon        = 0;
03387   seInfo.hProcess     = 0;
03388 
03389   if((ShellExecuteEx(&seInfo) != 0) && (seInfo.hProcess != NULL))
03390   {
03391     if(bWait)
03392     {
03393       for(;;)
03394       {
03395         if(WaitForSingleObject(seInfo.hProcess, 200) == WAIT_OBJECT_0)
03396           break;
03397 
03398         ProcessWindowsMessages();
03399       }
03400     }
03401     return(TRUE);
03402   }
03403   return(FALSE);
03404 }
03405 
03406 HRESULT InitDlgWelcome(diW *diDialog)
03407 {
03408   diDialog->bShowDialog = FALSE;
03409   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03410     return(1);
03411   if((diDialog->szMessageWelcome = NS_GlobalAlloc(MAX_BUF)) == NULL)
03412     return(1);
03413   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03414     return(1);
03415   if((diDialog->szMessage1 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03416     return(1);
03417   if((diDialog->szMessage2 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03418     return(1);
03419   if((diDialog->szMessage3 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03420     return(1);
03421 
03422   return(0);
03423 }
03424 
03425 void DeInitDlgWelcome(diW *diDialog)
03426 {
03427   FreeMemory(&(diDialog->szTitle));
03428   FreeMemory(&(diDialog->szMessageWelcome));
03429   FreeMemory(&(diDialog->szMessage0));
03430   FreeMemory(&(diDialog->szMessage1));
03431   FreeMemory(&(diDialog->szMessage2));
03432   FreeMemory(&(diDialog->szMessage3));
03433 }
03434 
03435 HRESULT InitDlgLicense(diL *diDialog)
03436 {
03437   diDialog->bShowDialog = FALSE;
03438   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03439     return(1);
03440   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03441     return(1);
03442   if((diDialog->szLicenseFilename = NS_GlobalAlloc(MAX_BUF)) == NULL)
03443     return(1);
03444   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03445     return(1);
03446   if((diDialog->szRadioAccept = NS_GlobalAlloc(MAX_BUF)) == NULL)
03447     return(1);
03448   if((diDialog->szRadioDecline = NS_GlobalAlloc(MAX_BUF)) == NULL)
03449     return(1);
03450 
03451   return(0);
03452 }
03453 
03454 void DeInitDlgLicense(diL *diDialog)
03455 {
03456   FreeMemory(&(diDialog->szTitle));
03457   FreeMemory(&(diDialog->szSubTitle));
03458   FreeMemory(&(diDialog->szLicenseFilename));
03459   FreeMemory(&(diDialog->szMessage0));
03460   FreeMemory(&(diDialog->szRadioAccept));
03461   FreeMemory(&(diDialog->szRadioDecline));
03462 }
03463 
03464 HRESULT InitDlgQuickLaunch(diQL *diDialog)
03465 {
03466   diDialog->bTurboMode         = FALSE;
03467   diDialog->bTurboModeEnabled  = FALSE;
03468   diDialog->bShowDialog = FALSE;
03469   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03470     return(1);
03471   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03472     return(1);
03473   if((diDialog->szMessage1 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03474     return(1);
03475   if((diDialog->szMessage2 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03476     return(1);
03477 
03478   return(0);
03479 }
03480 
03481 void DeInitDlgQuickLaunch(diQL *diDialog)
03482 {
03483   FreeMemory(&(diDialog->szTitle));
03484   FreeMemory(&(diDialog->szMessage0));
03485   FreeMemory(&(diDialog->szMessage1));
03486   FreeMemory(&(diDialog->szMessage2));
03487 }
03488 
03489 HRESULT InitDlgSetupType(diST *diDialog)
03490 {
03491   diDialog->bShowDialog = FALSE;
03492 
03493   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03494     return(1);
03495   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03496     return(1);
03497   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03498     return(1);
03499 
03500   diDialog->stSetupType0.dwCItems = 0;
03501   diDialog->stSetupType1.dwCItems = 0;
03502   if((diDialog->stSetupType0.szDescriptionShort = NS_GlobalAlloc(MAX_BUF)) == NULL)
03503     return(1);
03504   if((diDialog->stSetupType0.szDescriptionLong = NS_GlobalAlloc(MAX_BUF)) == NULL)
03505     return(1);
03506 
03507   if((diDialog->stSetupType1.szDescriptionShort = NS_GlobalAlloc(MAX_BUF)) == NULL)
03508     return(1);
03509   if((diDialog->stSetupType1.szDescriptionLong = NS_GlobalAlloc(MAX_BUF)) == NULL)
03510     return(1);
03511 
03512   return(0);
03513 }
03514 
03515 void DeInitDlgSetupType(diST *diDialog)
03516 {
03517   FreeMemory(&(diDialog->szTitle));
03518   FreeMemory(&(diDialog->szSubTitle));
03519   FreeMemory(&(diDialog->szMessage0));
03520 
03521   FreeMemory(&(diDialog->stSetupType0.szDescriptionShort));
03522   FreeMemory(&(diDialog->stSetupType0.szDescriptionLong));
03523   FreeMemory(&(diDialog->stSetupType1.szDescriptionShort));
03524   FreeMemory(&(diDialog->stSetupType1.szDescriptionLong));
03525 }
03526 
03527 HRESULT InitDlgSelectComponents(diSC *diDialog, DWORD dwSM)
03528 {
03529   diDialog->bShowDialog = FALSE;
03530 
03531   /* set to show the Single dialog or the Multi dialog for the SelectComponents dialog */
03532   diDialog->bShowDialogSM = dwSM;
03533   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03534     return(1);
03535   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03536     return(1);
03537   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03538     return(1);
03539 
03540   return(0);
03541 }
03542 
03543 void DeInitDlgSelectComponents(diSC *diDialog)
03544 {
03545   FreeMemory(&(diDialog->szTitle));
03546   FreeMemory(&(diDialog->szSubTitle));
03547   FreeMemory(&(diDialog->szMessage0));
03548 }
03549 
03550 HRESULT InitDlgSelectInstallPath(diSIP *diDialog)
03551 {
03552   diDialog->bShowDialog = FALSE;
03553 
03554   /* set to show the Single dialog or the Multi dialog for the SelectComponents dialog */
03555   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03556     return(1);
03557   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03558     return(1);
03559   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03560     return(1);
03561 
03562   return(0);
03563 }
03564 
03565 void DeInitDlgSelectInstallPath(diSIP *diDialog)
03566 {
03567   FreeMemory(&(diDialog->szTitle));
03568   FreeMemory(&(diDialog->szSubTitle));
03569   FreeMemory(&(diDialog->szMessage0));
03570 }
03571 
03572 HRESULT InitDlgUpgrade(diU *diDialog)
03573 {
03574   diDialog->bShowDialog = FALSE;
03575   diDialog->bShowInEasyInstall = FALSE;
03576 
03577   /* set to show the Single dialog or the Multi dialog for the SelectComponents dialog */
03578   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03579     return(1);
03580   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03581     return(1);
03582   if((diDialog->szMessageCleanup = NS_GlobalAlloc(MAX_BUF)) == NULL)
03583     return(1);
03584   if((diDialog->szCheckboxSafeInstall = NS_GlobalAlloc(MAX_BUF)) == NULL)
03585     return(1);
03586   if((diDialog->szSafeInstallInfo = NS_GlobalAlloc(MAX_BUF)) == NULL)
03587     return(1);
03588   if((diDialog->szUnsafeInstallInfo = NS_GlobalAlloc(MAX_BUF)) == NULL)
03589     return(1);
03590   if((diDialog->szNoSafeUpgradeWindir = NS_GlobalAlloc(MAX_BUF)) == NULL)
03591     return(1);
03592 
03593   return(0);
03594 }
03595 
03596 void DeInitDlgUpgrade(diU *diDialog)
03597 {
03598   FreeMemory(&(diDialog->szTitle));
03599   FreeMemory(&(diDialog->szSubTitle));
03600   FreeMemory(&(diDialog->szMessageCleanup));
03601   FreeMemory(&(diDialog->szCheckboxSafeInstall));
03602   FreeMemory(&(diDialog->szSafeInstallInfo));
03603   FreeMemory(&(diDialog->szUnsafeInstallInfo));
03604   FreeMemory(&(diDialog->szNoSafeUpgradeWindir));
03605 }
03606 
03607 HRESULT InitDlgWindowsIntegration(diWI *diDialog)
03608 {
03609   diDialog->bShowDialog = FALSE;
03610   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03611     exit(1);
03612   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03613     exit(1);
03614   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03615     exit(1);
03616   if((diDialog->szRegistryKey = NS_GlobalAlloc(MAX_BUF)) == NULL)
03617     exit(1);
03618 
03619   diDialog->wiCB0.bEnabled = FALSE;
03620   diDialog->wiCB1.bEnabled = FALSE;
03621   diDialog->wiCB2.bEnabled = FALSE;
03622   
03623   diDialog->wiCB0.bCheckBoxState = FALSE;
03624   diDialog->wiCB1.bCheckBoxState = FALSE;
03625   diDialog->wiCB2.bCheckBoxState = FALSE;
03626   
03627   if((diDialog->wiCB0.szDescription = NS_GlobalAlloc(MAX_BUF)) == NULL)
03628     return(1);
03629   if((diDialog->wiCB1.szDescription = NS_GlobalAlloc(MAX_BUF)) == NULL)
03630     return(1);
03631   if((diDialog->wiCB2.szDescription = NS_GlobalAlloc(MAX_BUF)) == NULL)
03632     return(1);
03633 
03634   if((diDialog->wiCB0.szArchive = NS_GlobalAlloc(MAX_BUF)) == NULL)
03635     return(1);
03636   if((diDialog->wiCB1.szArchive = NS_GlobalAlloc(MAX_BUF)) == NULL)
03637     return(1);
03638   if((diDialog->wiCB2.szArchive = NS_GlobalAlloc(MAX_BUF)) == NULL)
03639     return(1);
03640 
03641   return(0);
03642 }
03643 
03644 void DeInitDlgWindowsIntegration(diWI *diDialog)
03645 {
03646   FreeMemory(&(diDialog->szTitle));
03647   FreeMemory(&(diDialog->szSubTitle));
03648   FreeMemory(&(diDialog->szMessage0));
03649   FreeMemory(&(diDialog->szRegistryKey));
03650 
03651   FreeMemory(&(diDialog->wiCB0.szDescription));
03652   FreeMemory(&(diDialog->wiCB1.szDescription));
03653   FreeMemory(&(diDialog->wiCB2.szDescription));
03654   FreeMemory(&(diDialog->wiCB0.szArchive));
03655   FreeMemory(&(diDialog->wiCB1.szArchive));
03656   FreeMemory(&(diDialog->wiCB2.szArchive));
03657 }
03658 
03659 HRESULT InitDlgProgramFolder(diPF *diDialog)
03660 {
03661   diDialog->bShowDialog = FALSE;
03662   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03663     return(1);
03664   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03665     return(1);
03666 
03667   return(0);
03668 }
03669 
03670 void DeInitDlgProgramFolder(diPF *diDialog)
03671 {
03672   FreeMemory(&(diDialog->szTitle));
03673   FreeMemory(&(diDialog->szMessage0));
03674 }
03675 
03676 HRESULT InitDlgAdditionalOptions(diDO *diDialog)
03677 {
03678   diDialog->bShowDialog           = FALSE;
03679   diDialog->bSaveInstaller        = FALSE;
03680   diDialog->dwUseProtocol         = UP_FTP;
03681   diDialog->bUseProtocolSettings  = TRUE;
03682   diDialog->bShowProtocols        = TRUE;
03683   if((diDialog->szTitle           = NS_GlobalAlloc(MAX_BUF)) == NULL)
03684     return(1);
03685   if((diDialog->szMessage0        = NS_GlobalAlloc(MAX_BUF)) == NULL)
03686     return(1);
03687   if((diDialog->szMessage1        = NS_GlobalAlloc(MAX_BUF)) == NULL)
03688     return(1);
03689 
03690   return(0);
03691 }
03692 
03693 void DeInitDlgAdditionalOptions(diDO *diDialog)
03694 {
03695   FreeMemory(&(diDialog->szTitle));
03696   FreeMemory(&(diDialog->szMessage0));
03697   FreeMemory(&(diDialog->szMessage1));
03698 }
03699 
03700 HRESULT InitDlgAdvancedSettings(diAS *diDialog)
03701 {
03702   diDialog->bShowDialog       = FALSE;
03703   if((diDialog->szTitle       = NS_GlobalAlloc(MAX_BUF)) == NULL)
03704     return(1);
03705   if((diDialog->szMessage0    = NS_GlobalAlloc(MAX_BUF)) == NULL)
03706     return(1);
03707   if((diDialog->szProxyServer = NS_GlobalAlloc(MAX_BUF)) == NULL)
03708     return(1);
03709   if((diDialog->szProxyPort   = NS_GlobalAlloc(MAX_BUF)) == NULL)
03710     return(1);
03711   if((diDialog->szProxyUser   = NS_GlobalAlloc(MAX_BUF)) == NULL)
03712     return(1);
03713   if((diDialog->szProxyPasswd = NS_GlobalAlloc(MAX_BUF)) == NULL)
03714     return(1);
03715 
03716   return(0);
03717 }
03718 
03719 void DeInitDlgAdvancedSettings(diAS *diDialog)
03720 {
03721   FreeMemory(&(diDialog->szTitle));
03722   FreeMemory(&(diDialog->szMessage0));
03723   FreeMemory(&(diDialog->szProxyServer));
03724   FreeMemory(&(diDialog->szProxyPort));
03725   FreeMemory(&(diDialog->szProxyUser));
03726   FreeMemory(&(diDialog->szProxyPasswd));
03727 }
03728 
03729 HRESULT InitDlgStartInstall(diSI *diDialog)
03730 {
03731   diDialog->bShowDialog        = FALSE;
03732   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03733     return(1);
03734   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03735     return(1);
03736   if((diDialog->szMessageInstall = NS_GlobalAlloc(MAX_BUF)) == NULL)
03737     return(1);
03738   if((diDialog->szMessageDownload = NS_GlobalAlloc(MAX_BUF)) == NULL)
03739     return(1);
03740   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03741     return(1);
03742 
03743   return(0);
03744 }
03745 
03746 void DeInitDlgStartInstall(diSI *diDialog)
03747 {
03748   FreeMemory(&(diDialog->szTitle));
03749   FreeMemory(&(diDialog->szSubTitle));
03750   FreeMemory(&(diDialog->szMessageInstall));
03751   FreeMemory(&(diDialog->szMessageDownload));
03752   FreeMemory(&(diDialog->szMessage0));
03753 }
03754 
03755 HRESULT InitDlgDownloading(diDL *diDialog)
03756 {
03757   diDialog->bShowDialog = FALSE;
03758   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03759     return(1);
03760   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03761     return(1);
03762   if((diDialog->szBlurb = NS_GlobalAlloc(MAX_BUF)) == NULL)
03763     return(1);
03764   if((diDialog->szFileNameKey = NS_GlobalAlloc(MAX_BUF)) == NULL)
03765     return(1);
03766   if((diDialog->szTimeRemainingKey = NS_GlobalAlloc(MAX_BUF)) == NULL)
03767     return(1);
03768 
03769   return(0);
03770 }
03771 
03772 void DeInitDlgDownloading(diDL *diDialog)
03773 {
03774   FreeMemory(&(diDialog->szTitle));
03775   FreeMemory(&(diDialog->szSubTitle));
03776   FreeMemory(&(diDialog->szBlurb));
03777   FreeMemory(&(diDialog->szFileNameKey));
03778   FreeMemory(&(diDialog->szTimeRemainingKey));
03779 }
03780 
03781 HRESULT InitDlgInstalling(diI *diDialog)
03782 {
03783   diDialog->bShowDialog = FALSE;
03784   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03785     return(1);
03786   if((diDialog->szSubTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03787     return(1);
03788   if((diDialog->szBlurb = NS_GlobalAlloc(MAX_BUF)) == NULL)
03789     return(1);
03790   if((diDialog->szStatusFile = NS_GlobalAlloc(MAX_BUF)) == NULL)
03791     return(1);
03792   if((diDialog->szStatusComponent = NS_GlobalAlloc(MAX_BUF)) == NULL)
03793     return(1);
03794 
03795   return(0);
03796 }
03797 
03798 void DeInitDlgInstalling(diI *diDialog)
03799 {
03800   FreeMemory(&(diDialog->szTitle));
03801   FreeMemory(&(diDialog->szSubTitle));
03802   FreeMemory(&(diDialog->szBlurb));
03803   FreeMemory(&(diDialog->szStatusFile));
03804   FreeMemory(&(diDialog->szStatusComponent));
03805 }
03806 
03807 HRESULT InitDlgInstallSuccessful(diIS *diDialog)
03808 {
03809   diDialog->bShowDialog = FALSE;
03810   diDialog->bLaunchAppChecked = TRUE;
03811   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
03812     return(1);
03813   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03814     return(1);
03815   if((diDialog->szMessage1 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03816     return(1);
03817   if((diDialog->szLaunchApp = NS_GlobalAlloc(MAX_BUF)) == NULL)
03818     return(1);
03819   if((diDialog->szRegistryKey = NS_GlobalAlloc(MAX_BUF)) == NULL)
03820     return(1);
03821   if((diDialog->szMessageHeader = NS_GlobalAlloc(MAX_BUF)) == NULL)
03822     return(1);
03823 
03824   return 0;
03825 }
03826 
03827 void DeInitDlgInstallSuccessful(diIS *diDialog)
03828 {
03829   FreeMemory(&(diDialog->szTitle));
03830   FreeMemory(&(diDialog->szMessage0));
03831   FreeMemory(&(diDialog->szMessage1));
03832   FreeMemory(&(diDialog->szLaunchApp));
03833   FreeMemory(&(diDialog->szRegistryKey));
03834   FreeMemory(&(diDialog->szMessageHeader));
03835 }
03836 
03837 HRESULT InitDlgDownload(diD *diDialog)
03838 {
03839   diDialog->bShowDialog = FALSE;
03840   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF_TINY)) == NULL)
03841     return(1);
03842   if((diDialog->szMessageDownload0 = NS_GlobalAlloc(MAX_BUF_MEDIUM)) == NULL)
03843     return(1);
03844   if((diDialog->szMessageRetry0 = NS_GlobalAlloc(MAX_BUF_MEDIUM)) == NULL)
03845     return(1);
03846 
03847   return(0);
03848 }
03849 
03850 void DeInitDlgDownload(diD *diDialog)
03851 {
03852   FreeMemory(&(diDialog->szTitle));
03853   FreeMemory(&(diDialog->szMessageDownload0));
03854   FreeMemory(&(diDialog->szMessageRetry0));
03855 }
03856 
03857 DWORD InitDlgReboot(diR *diDialog)
03858 {
03859   diDialog->dwShowDialog = FALSE;
03860   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF_MEDIUM)) == NULL)
03861     return(1);
03862   GetPrivateProfileString("Messages", "DLG_REBOOT_TITLE", "", diDialog->szTitle, MAX_BUF_MEDIUM, szFileIniInstall);
03863 
03864   return(0);
03865 }
03866 
03867 void DeInitDlgReboot(diR *diDialog)
03868 {
03869   FreeMemory(&(diDialog->szTitle));
03870 }
03871 
03872 HRESULT InitSetupGeneral()
03873 {
03874   gSystemInfo.bRefreshIcons      = FALSE; 
03875   sgProduct.mode                 = NOT_SET;
03876   sgProduct.bSharedInst          = FALSE;
03877   sgProduct.bInstallFiles        = TRUE;
03878   sgProduct.checkCleanupOnUpgrade = FALSE;
03879   sgProduct.doCleanupOnUpgrade    = TRUE;
03880   sgProduct.greType              = GRE_TYPE_NOT_SET;
03881   sgProduct.dwCustomType         = ST_RADIO0;
03882   sgProduct.dwNumberOfComponents = 0;
03883   sgProduct.bLockPath            = FALSE;
03884 
03885   if((sgProduct.szPath                        = NS_GlobalAlloc(MAX_BUF)) == NULL)
03886     return(1);
03887   if((sgProduct.szSubPath                     = NS_GlobalAlloc(MAX_BUF)) == NULL)
03888     return(1);
03889   if((sgProduct.szProgramName                 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03890     return(1);
03891   if((sgProduct.szCompanyName                 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03892     return(1);
03893   if((sgProduct.szProductName                 = NS_GlobalAlloc(MAX_BUF)) == NULL)
03894     return(1);
03895   if((sgProduct.szProductNameInternal         = NS_GlobalAlloc(MAX_BUF)) == NULL)
03896     return(1);
03897   if((sgProduct.szProductNamePrevious         = NS_GlobalAlloc(MAX_BUF)) == NULL)
03898     return(1);
03899   if((sgProduct.szUserAgent                   = NS_GlobalAlloc(MAX_BUF)) == NULL)
03900     return(1);
03901   if((sgProduct.szProgramFolderName           = NS_GlobalAlloc(MAX_BUF)) == NULL)
03902     return(1);
03903   if((sgProduct.szProgramFolderPath           = NS_GlobalAlloc(MAX_BUF)) == NULL)
03904     return(1);
03905   if((sgProduct.szAlternateArchiveSearchPath  = NS_GlobalAlloc(MAX_BUF)) == NULL)
03906     return(1);
03907   if((sgProduct.szParentProcessFilename       = NS_GlobalAlloc(MAX_BUF)) == NULL)
03908     return(1);
03909   if((szTempSetupPath                         = NS_GlobalAlloc(MAX_BUF)) == NULL)
03910     return(1);
03911 
03912   if((szSiteSelectorDescription               = NS_GlobalAlloc(MAX_BUF)) == NULL)
03913     return(1);
03914   if((sgProduct.szAppID                       = NS_GlobalAlloc(MAX_BUF)) == NULL)
03915     return(1);
03916   if((sgProduct.szAppPath                     = NS_GlobalAlloc(MAX_BUF)) == NULL)
03917     return(1);
03918   if((sgProduct.szRegPath                     = NS_GlobalAlloc(MAX_BUF)) == NULL)
03919     return(1);
03920 
03921   sgProduct.greCleanupOrphans = FALSE;
03922   *sgProduct.greCleanupOrphansMessage = '\0';
03923   *sgProduct.greID         = '\0';
03924   *sgProduct.grePrivateKey = '\0';
03925   return(0);
03926 }
03927 
03928 void DeInitSetupGeneral()
03929 {
03930   FreeMemory(&(sgProduct.szPath));
03931   FreeMemory(&(sgProduct.szSubPath));
03932   FreeMemory(&(sgProduct.szProgramName));
03933   FreeMemory(&(sgProduct.szCompanyName));
03934   FreeMemory(&(sgProduct.szProductName));
03935   FreeMemory(&(sgProduct.szProductNameInternal));
03936   FreeMemory(&(sgProduct.szProductNamePrevious));
03937   FreeMemory(&(sgProduct.szUserAgent));
03938   FreeMemory(&(sgProduct.szProgramFolderName));
03939   FreeMemory(&(sgProduct.szProgramFolderPath));
03940   FreeMemory(&(sgProduct.szAlternateArchiveSearchPath));
03941   FreeMemory(&(sgProduct.szParentProcessFilename));
03942   FreeMemory(&(sgProduct.szAppID));
03943   FreeMemory(&(sgProduct.szAppPath));
03944   FreeMemory(&(sgProduct.szRegPath));
03945   FreeMemory(&(szTempSetupPath));
03946   FreeMemory(&(szSiteSelectorDescription));
03947 }
03948 
03949 HRESULT InitSDObject()
03950 {
03951   if((siSDObject.szXpcomFile = NS_GlobalAlloc(MAX_BUF)) == NULL)
03952     return(1);
03953   if((siSDObject.szXpcomDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
03954     return(1);
03955   if((siSDObject.szNoAds = NS_GlobalAlloc(MAX_BUF)) == NULL)
03956     return(1);
03957   if((siSDObject.szSilent = NS_GlobalAlloc(MAX_BUF)) == NULL)
03958     return(1);
03959   if((siSDObject.szExecution = NS_GlobalAlloc(MAX_BUF)) == NULL)
03960     return(1);
03961   if((siSDObject.szConfirmInstall = NS_GlobalAlloc(MAX_BUF)) == NULL)
03962     return(1);
03963   if((siSDObject.szExtractMsg = NS_GlobalAlloc(MAX_BUF)) == NULL)
03964     return(1);
03965   if((siSDObject.szExe = NS_GlobalAlloc(MAX_BUF)) == NULL)
03966     return(1);
03967   if((siSDObject.szExeParam = NS_GlobalAlloc(MAX_BUF)) == NULL)
03968     return(1);
03969   if((siSDObject.szXpcomFilePath = NS_GlobalAlloc(MAX_BUF)) == NULL)
03970     return(1);
03971 
03972   return(0);
03973 }
03974 
03975 void DeInitSDObject()
03976 {
03977   FreeMemory(&(siSDObject.szXpcomFile));
03978   FreeMemory(&(siSDObject.szXpcomDir));
03979   FreeMemory(&(siSDObject.szNoAds));
03980   FreeMemory(&(siSDObject.szSilent));
03981   FreeMemory(&(siSDObject.szExecution));
03982   FreeMemory(&(siSDObject.szConfirmInstall));
03983   FreeMemory(&(siSDObject.szExtractMsg));
03984   FreeMemory(&(siSDObject.szExe));
03985   FreeMemory(&(siSDObject.szExeParam));
03986   FreeMemory(&(siSDObject.szXpcomFilePath));
03987 }
03988 
03989 HRESULT InitSXpcomFile()
03990 {
03991   if((siCFXpcomFile.szSource = NS_GlobalAlloc(MAX_BUF)) == NULL)
03992     return(1);
03993   if((siCFXpcomFile.szDestination = NS_GlobalAlloc(MAX_BUF)) == NULL)
03994     return(1);
03995   if((siCFXpcomFile.szMessage = NS_GlobalAlloc(MAX_BUF)) == NULL)
03996     return(1);
03997 
03998   siCFXpcomFile.bCleanup         = TRUE;
03999   siCFXpcomFile.bStatus          = STATUS_ENABLED;
04000   siCFXpcomFile.ullInstallSize   = 0;
04001   return(0);
04002 }
04003 
04004 void DeInitSXpcomFile()
04005 {
04006   FreeMemory(&(siCFXpcomFile.szSource));
04007   FreeMemory(&(siCFXpcomFile.szDestination));
04008   FreeMemory(&(siCFXpcomFile.szMessage));
04009 }
04010 
04011 /* Function: InitGre()
04012  *       in: gre structure.
04013  *      out: gre structure.
04014  *  purpose: To initialize a newly created greInfo structure.
04015  */
04016 HRESULT InitGre(greInfo *gre)
04017 {
04018   gre->homePath[0]           = '\0';
04019   gre->installerAppPath[0]   = '\0';
04020   gre->uninstallerAppPath[0] = '\0';
04021   gre->userAgent[0]          = '\0';
04022   gre->minVersion.ullMajor   = 0;
04023   gre->minVersion.ullMinor   = 0;
04024   gre->minVersion.ullRelease = 0;
04025   gre->minVersion.ullBuild   = 0;
04026   gre->maxVersion.ullMajor   = 0;
04027   gre->maxVersion.ullMinor   = 0;
04028   gre->maxVersion.ullRelease = 0;
04029   gre->maxVersion.ullBuild   = 0;
04030   gre->greSupersedeList      = NULL;
04031   gre->greInstalledList      = NULL;
04032   gre->siCGreComponent       = NULL;
04033   return(WIZ_OK);
04034 }
04035 
04036 /* Function: DeInitGre()
04037  *       in: gre structure.
04038  *      out: gre structure.
04039  *  purpose: To cleanup allocated memory to a greInfo structure.
04040  */
04041 void DeInitGre(greInfo *gre)
04042 {
04043   DeleteGverList(gre->greSupersedeList);
04044   DeleteGverList(gre->greInstalledList);
04045 }
04046 
04047 siC *CreateSiCNode()
04048 {
04049   siC *siCNode;
04050 
04051   if((siCNode = NS_GlobalAlloc(sizeof(struct sinfoComponent))) == NULL)
04052     exit(1);
04053 
04054   siCNode->dwAttributes             = 0;
04055   siCNode->ullInstallSize           = 0;
04056   siCNode->ullInstallSizeSystem     = 0;
04057   siCNode->ullInstallSizeArchive    = 0;
04058   siCNode->lRandomInstallPercentage = 0;
04059   siCNode->lRandomInstallValue      = 0;
04060   siCNode->bForceUpgrade            = FALSE;
04061 
04062   if((siCNode->szArchiveName = NS_GlobalAlloc(MAX_BUF)) == NULL)
04063     exit(1);
04064   if((siCNode->szArchiveNameUncompressed = NS_GlobalAlloc(MAX_BUF)) == NULL)
04065     exit(1);
04066   if((siCNode->szArchivePath = NS_GlobalAlloc(MAX_BUF)) == NULL)
04067     exit(1);
04068   if((siCNode->szDestinationPath = NS_GlobalAlloc(MAX_BUF)) == NULL)
04069     exit(1);
04070   if((siCNode->szDescriptionShort = NS_GlobalAlloc(MAX_BUF)) == NULL)
04071     exit(1);
04072   if((siCNode->szDescriptionLong = NS_GlobalAlloc(MAX_BUF)) == NULL)
04073     exit(1);
04074   if((siCNode->szParameter = NS_GlobalAlloc(MAX_BUF)) == NULL)
04075     exit(1);
04076   if((siCNode->szReferenceName = NS_GlobalAlloc(MAX_BUF)) == NULL)
04077     exit(1);
04078 
04079   siCNode->iNetRetries      = 0;
04080   siCNode->iCRCRetries      = 0;
04081   siCNode->iNetTimeOuts     = 0;
04082   siCNode->siCDDependencies = NULL;
04083   siCNode->siCDDependees    = NULL;
04084   siCNode->Next             = NULL;
04085   siCNode->Prev             = NULL;
04086 
04087   return(siCNode);
04088 }
04089 
04090 void SiCNodeInsert(siC **siCHead, siC *siCTemp)
04091 {
04092   if(*siCHead == NULL)
04093   {
04094     *siCHead          = siCTemp;
04095     (*siCHead)->Next  = *siCHead;
04096     (*siCHead)->Prev  = *siCHead;
04097   }
04098   else
04099   {
04100     siCTemp->Next           = *siCHead;
04101     siCTemp->Prev           = (*siCHead)->Prev;
04102     (*siCHead)->Prev->Next  = siCTemp;
04103     (*siCHead)->Prev        = siCTemp;
04104   }
04105 }
04106 
04107 void SiCNodeDelete(siC *siCTemp)
04108 {
04109   if(siCTemp != NULL)
04110   {
04111     DeInitSiCDependencies(siCTemp->siCDDependencies);
04112     DeInitSiCDependencies(siCTemp->siCDDependees);
04113 
04114     siCTemp->Next->Prev = siCTemp->Prev;
04115     siCTemp->Prev->Next = siCTemp->Next;
04116     siCTemp->Next       = NULL;
04117     siCTemp->Prev       = NULL;
04118 
04119     FreeMemory(&(siCTemp->szDestinationPath));
04120     FreeMemory(&(siCTemp->szArchivePath));
04121     FreeMemory(&(siCTemp->szArchiveName));
04122     FreeMemory(&(siCTemp->szArchiveNameUncompressed));
04123     FreeMemory(&(siCTemp->szParameter));
04124     FreeMemory(&(siCTemp->szReferenceName));
04125     FreeMemory(&(siCTemp->szDescriptionLong));
04126     FreeMemory(&(siCTemp->szDescriptionShort));
04127     FreeMemory(&siCTemp);
04128   }
04129 }
04130 
04131 siCD *CreateSiCDepNode()
04132 {
04133   siCD *siCDepNode;
04134 
04135   if((siCDepNode = NS_GlobalAlloc(sizeof(struct sinfoComponentDep))) == NULL)
04136     exit(1);
04137 
04138   if((siCDepNode->szDescriptionShort = NS_GlobalAlloc(MAX_BUF)) == NULL)
04139     exit(1);
04140   if((siCDepNode->szReferenceName = NS_GlobalAlloc(MAX_BUF)) == NULL)
04141     exit(1);
04142   siCDepNode->Next = NULL;
04143   siCDepNode->Prev = NULL;
04144 
04145   return(siCDepNode);
04146 }
04147 
04148 void SiCDepNodeInsert(siCD **siCDepHead, siCD *siCDepTemp)
04149 {
04150   if(*siCDepHead == NULL)
04151   {
04152     *siCDepHead          = siCDepTemp;
04153     (*siCDepHead)->Next  = *siCDepHead;
04154     (*siCDepHead)->Prev  = *siCDepHead;
04155   }
04156   else
04157   {
04158     siCDepTemp->Next           = *siCDepHead;
04159     siCDepTemp->Prev           = (*siCDepHead)->Prev;
04160     (*siCDepHead)->Prev->Next  = siCDepTemp;
04161     (*siCDepHead)->Prev        = siCDepTemp;
04162   }
04163 }
04164 
04165 void SiCDepNodeDelete(siCD *siCDepTemp)
04166 {
04167   if(siCDepTemp != NULL)
04168   {
04169     siCDepTemp->Next->Prev = siCDepTemp->Prev;
04170     siCDepTemp->Prev->Next = siCDepTemp->Next;
04171     siCDepTemp->Next       = NULL;
04172     siCDepTemp->Prev       = NULL;
04173 
04174     FreeMemory(&(siCDepTemp->szDescriptionShort));
04175     FreeMemory(&(siCDepTemp->szReferenceName));
04176     FreeMemory(&siCDepTemp);
04177   }
04178 }
04179 
04180 ssi *CreateSsiSiteSelectorNode()
04181 {
04182   ssi *ssiNode;
04183 
04184   if((ssiNode = NS_GlobalAlloc(sizeof(struct ssInfo))) == NULL)
04185     exit(1);
04186   if((ssiNode->szDescription = NS_GlobalAlloc(MAX_BUF)) == NULL)
04187     exit(1);
04188   if((ssiNode->szDomain = NS_GlobalAlloc(MAX_BUF)) == NULL)
04189     exit(1);
04190   if((ssiNode->szIdentifier = NS_GlobalAlloc(MAX_BUF)) == NULL)
04191     exit(1);
04192 
04193   ssiNode->Next = NULL;
04194   ssiNode->Prev = NULL;
04195 
04196   return(ssiNode);
04197 }
04198 
04199 void SsiSiteSelectorNodeInsert(ssi **ssiHead, ssi *ssiTemp)
04200 {
04201   if(*ssiHead == NULL)
04202   {
04203     *ssiHead          = ssiTemp;
04204     (*ssiHead)->Next  = *ssiHead;
04205     (*ssiHead)->Prev  = *ssiHead;
04206   }
04207   else
04208   {
04209     ssiTemp->Next           = *ssiHead;
04210     ssiTemp->Prev           = (*ssiHead)->Prev;
04211     (*ssiHead)->Prev->Next  = ssiTemp;
04212     (*ssiHead)->Prev        = ssiTemp;
04213   }
04214 }
04215 
04216 void SsiSiteSelectorNodeDelete(ssi *ssiTemp)
04217 {
04218   if(ssiTemp != NULL)
04219   {
04220     ssiTemp->Next->Prev = ssiTemp->Prev;
04221     ssiTemp->Prev->Next = ssiTemp->Next;
04222     ssiTemp->Next       = NULL;
04223     ssiTemp->Prev       = NULL;
04224 
04225     FreeMemory(&(ssiTemp->szDescription));
04226     FreeMemory(&(ssiTemp->szDomain));
04227     FreeMemory(&(ssiTemp->szIdentifier));
04228     FreeMemory(&ssiTemp);
04229   }
04230 }
04231 
04232 HRESULT SiCNodeGetAttributes(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04233 {
04234   DWORD dwCount = 0;
04235   siC   *siCTemp = siComponents;
04236 
04237   if(siCTemp != NULL)
04238   {
04239     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04240        ((dwACFlag == AC_ALL) ||
04241        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04242        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04243     {
04244       if(dwIndex == 0)
04245         return(siCTemp->dwAttributes);
04246 
04247       ++dwCount;
04248     }
04249 
04250     siCTemp = siCTemp->Next;
04251     while((siCTemp != NULL) && (siCTemp != siComponents))
04252     {
04253       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04254          ((dwACFlag == AC_ALL) ||
04255          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04256          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04257       {
04258         if(dwIndex == dwCount)
04259           return(siCTemp->dwAttributes);
04260 
04261         ++dwCount;
04262       }
04263       
04264       siCTemp = siCTemp->Next;
04265     }
04266   }
04267   return(-1);
04268 }
04269 
04270 void SiCNodeSetAttributes(DWORD dwIndex, DWORD dwAttributes, BOOL bSet, BOOL bIncludeInvisible, DWORD dwACFlag, HWND hwndListBox)
04271 {
04272   DWORD dwCount        = 0;
04273   DWORD dwVisibleIndex = 0;
04274   siC   *siCTemp       = siComponents;
04275 
04276   LPSTR szTmpString;
04277   TCHAR tchBuffer[MAX_BUF];
04278 
04279   if(siCTemp != NULL)
04280   {
04281     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04282        ((dwACFlag == AC_ALL) ||
04283        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04284        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04285     {
04286       if(dwIndex == 0)
04287       {
04288         if(bSet)
04289           siCTemp->dwAttributes |= dwAttributes;
04290         else
04291           siCTemp->dwAttributes &= ~dwAttributes;
04292 
04293         if((!(siCTemp->dwAttributes & SIC_INVISIBLE))
04294            && (dwAttributes == SIC_SELECTED) 
04295            && gSystemInfo.bScreenReader 
04296            && hwndListBox)
04297         {
04298           szTmpString = SiCNodeGetDescriptionShort(dwVisibleIndex, FALSE, dwACFlag);
04299           lstrcpy(tchBuffer, szTmpString);
04300           lstrcat(tchBuffer, " - ");
04301           if(bSet)
04302             lstrcat(tchBuffer, sgInstallGui.szChecked);
04303           else
04304             lstrcat(tchBuffer, sgInstallGui.szUnchecked);
04305 
04306           //We've got to actually change the text in the listbox for the screen reader to see it.
04307           SendMessage(hwndListBox, LB_INSERTSTRING, 0, (LPARAM)tchBuffer);
04308           SendMessage(hwndListBox, LB_DELETESTRING, 1, 0);
04309         }
04310       }
04311 
04312       ++dwCount;
04313       if(!(siCTemp->dwAttributes & SIC_INVISIBLE))
04314         ++dwVisibleIndex;
04315     }
04316 
04317     siCTemp = siCTemp->Next;
04318     while((siCTemp != NULL) && (siCTemp != siComponents))
04319     {
04320       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04321          ((dwACFlag == AC_ALL) ||
04322          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04323          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04324       {
04325         if(dwIndex == dwCount)
04326         {
04327           if(bSet)
04328             siCTemp->dwAttributes |= dwAttributes;
04329           else
04330             siCTemp->dwAttributes &= ~dwAttributes;
04331 
04332           if((!(siCTemp->dwAttributes & SIC_INVISIBLE))
04333              && (dwAttributes == SIC_SELECTED) 
04334              && gSystemInfo.bScreenReader 
04335              && hwndListBox)
04336           {
04337             szTmpString = SiCNodeGetDescriptionShort(dwVisibleIndex, FALSE, dwACFlag);
04338             lstrcpy(tchBuffer, szTmpString);
04339             lstrcat(tchBuffer, " - ");
04340             if(bSet)
04341               lstrcat(tchBuffer, sgInstallGui.szChecked);
04342             else
04343               lstrcat(tchBuffer, sgInstallGui.szUnchecked);
04344 
04345             //We've got to actually change the text in the listbox for the screen reader to see it.
04346             SendMessage(hwndListBox, LB_INSERTSTRING, dwVisibleIndex, (LPARAM)tchBuffer);
04347             SendMessage(hwndListBox, LB_DELETESTRING, dwVisibleIndex+1, 0);
04348           }
04349         }
04350 
04351         ++dwCount;
04352         if(!(siCTemp->dwAttributes & SIC_INVISIBLE))
04353           ++dwVisibleIndex;
04354       }
04355 
04356       siCTemp = siCTemp->Next;
04357     }
04358   }
04359 }
04360 
04361 BOOL IsInList(DWORD dwCurrentItem, DWORD dwItems, DWORD *dwItemsSelected)
04362 {
04363   DWORD i;
04364 
04365   for(i = 0; i < dwItems; i++)
04366   {
04367     if(dwItemsSelected[i] == dwCurrentItem)
04368       return(TRUE);
04369   }
04370 
04371   return(FALSE);
04372 }
04373 
04374 void RestoreInvisibleFlag(siC *siCNode)
04375 {
04376   char szBuf[MAX_BUF_TINY];
04377   char szAttribute[MAX_BUF_TINY];
04378 
04379   GetConfigIniProfileString(siCNode->szReferenceName, "Attributes", "", szBuf, sizeof(szBuf));
04380   lstrcpy(szAttribute, szBuf);
04381   CharUpperBuff(szAttribute, sizeof(szAttribute));
04382 
04383   if(strstr(szAttribute, "INVISIBLE") || siCNode->bSupersede)
04384     siCNode->dwAttributes |= SIC_INVISIBLE;
04385   else
04386     siCNode->dwAttributes &= ~SIC_INVISIBLE;
04387 }
04388 
04389 void RestoreAdditionalFlag(siC *siCNode)
04390 {
04391   char szBuf[MAX_BUF_TINY];
04392   char szAttribute[MAX_BUF_TINY];
04393 
04394   GetConfigIniProfileString(siCNode->szReferenceName, "Attributes", "", szBuf, sizeof(szBuf));
04395   lstrcpy(szAttribute, szBuf);
04396   CharUpperBuff(szAttribute, sizeof(szAttribute));
04397 
04398   if(strstr(szAttribute, "ADDITIONAL") && !strstr(szAttribute, "NOTADDITIONAL"))
04399     siCNode->dwAttributes |= SIC_ADDITIONAL;
04400   else
04401     siCNode->dwAttributes &= ~SIC_ADDITIONAL;
04402 }
04403 
04404 void RestoreEnabledFlag(siC *siCNode)
04405 {
04406   char szBuf[MAX_BUF_TINY];
04407   char szAttribute[MAX_BUF_TINY];
04408 
04409   GetConfigIniProfileString(siCNode->szReferenceName, "Attributes", "", szBuf, sizeof(szBuf));
04410   lstrcpy(szAttribute, szBuf);
04411   CharUpperBuff(szAttribute, sizeof(szAttribute));
04412 
04413   if(strstr(szAttribute, "ENABLED") && !strstr(szAttribute, "DISABLED"))
04414     siCNode->dwAttributes |= SIC_DISABLED;
04415   else
04416     siCNode->dwAttributes &= ~SIC_DISABLED;
04417 }
04418 
04419 //  This function:
04420 //  - Zeros the SELECTED and ADDITIONAL attributes of all components.
04421 //  - Set all attributes as specified for the specific Setup Type
04422 //  - Overrides attributes designated in any [Component XXX-Overwrite-Setup TypeX]
04423 //    sections for the specific Setup Type.
04424 void SiCNodeSetItemsSelected(DWORD dwSetupType)
04425 {
04426   siC  *siCNode;
04427   char szBuf[MAX_BUF];
04428   char szSTSection[MAX_BUF];
04429   char szComponentKey[MAX_BUF];
04430   char szComponentSection[MAX_BUF];
04431   char szOverrideSection[MAX_BUF];
04432   char szOverrideAttributes[MAX_BUF];
04433   DWORD dwIndex0;
04434 
04435   lstrcpy(szSTSection, "Setup Type");
04436   itoa(dwSetupType, szBuf, 10);
04437   lstrcat(szSTSection, szBuf);
04438 
04439   // For each component in the global list unset its SELECTED and ADDITIONAL attributes
04440   siCNode = siComponents;
04441   do
04442   {
04443     if(siCNode == NULL)
04444       break;
04445 
04446     /* clear these flags for all components so they can be
04447      * reset later if they belong to the setup type the user
04448      * selected */
04449     siCNode->dwAttributes &= ~SIC_SELECTED;
04450     siCNode->dwAttributes &= ~SIC_ADDITIONAL;
04451     siCNode->dwAttributes |= SIC_INVISIBLE;
04452 
04453     /* Force Upgrade needs to be performed here because the user has just
04454      * selected the destination path for the product.  The destination path is
04455      * critical to the checking of the Force Upgrade. */
04456     ResolveForceUpgrade(siCNode);
04457     ResolveSupersede(siCNode, &gGre);
04458     siCNode = siCNode->Next;
04459   } while((siCNode != NULL) && (siCNode != siComponents));
04460 
04461   /* for each component in a setup type, set its ATTRIBUTES to the right values */
04462   dwIndex0 = 0;
04463   wsprintf(szComponentKey, "C%d", dwIndex0);
04464   GetConfigIniProfileString(szSTSection, szComponentKey, "", szComponentSection, sizeof(szComponentSection));
04465   while(*szComponentSection != '\0')
04466   {
04467     if((siCNode = SiCNodeFind(siComponents, szComponentSection)) != NULL)
04468     {
04469       /* Component is in the Setup Type the user selected, so we now need to
04470        * reset the INVISIBLE and ADDITIONAL flags because they were unset
04471        * above and also are not reset anywhere else. */
04472       RestoreInvisibleFlag(siCNode);
04473       RestoreAdditionalFlag(siCNode);
04474 
04475       wsprintf(szOverrideSection, "%s-Override-%s", siCNode->szReferenceName, szSTSection);
04476       GetConfigIniProfileString(szOverrideSection, "Attributes", "", szOverrideAttributes, sizeof(szOverrideAttributes));
04477 
04478       if((siCNode->lRandomInstallPercentage != 0) &&
04479          (siCNode->lRandomInstallPercentage <= siCNode->lRandomInstallValue) &&
04480          !(siCNode->dwAttributes & SIC_DISABLED))
04481       {
04482         /* Random Install Percentage check passed *and* the component
04483          * is not DISABLED */
04484         if(*szOverrideAttributes != '\0')
04485           siCNode->dwAttributes = ParseComponentAttributes(szOverrideAttributes, siCNode->dwAttributes, TRUE);
04486         siCNode->dwAttributes &= ~SIC_SELECTED;
04487       }
04488       else if(sgProduct.dwCustomType != dwSetupType)
04489       {
04490         /* Setup Type other than custom detected, so
04491          * make sure all components from this Setup Type
04492          * is selected (regardless if it's DISABLED or not). 
04493          * Don't select components that are Superseded */
04494         if(!siCNode->bSupersede)
04495           siCNode->dwAttributes |= SIC_SELECTED;
04496 
04497         /* We need to restore the ENBLED/DISABLED flag for this component
04498          * from config.ini because it could have been altered in
04499          * ResolveForceUpgrade().  We need to restore it here so the override
04500          * attribute can override it here. */
04501         RestoreEnabledFlag(siCNode);
04502         if(*szOverrideAttributes != '\0')
04503           siCNode->dwAttributes = ParseComponentAttributes(szOverrideAttributes, siCNode->dwAttributes, TRUE);
04504       }
04505       else if(!(siCNode->dwAttributes & SIC_DISABLED) && !siCNode->bForceUpgrade && !siCNode->bSupersede)
04506       {
04507         /* Custom setup type detected and the component is
04508          * not DISABLED and FORCE_UPGRADE.  Reset the component's 
04509          * attribute to default.  If the component is DISABLED and
04510          * happens not be SELECTED in the config.ini file, we leave
04511          * it as is.  The user will see the component in the Options
04512          * Dialogs as not selected and DISABLED.  Not sure why we
04513          * want this, but marketing might find it useful someday. */
04514 
04515         GetConfigIniProfileString(siCNode->szReferenceName, "Attributes", "", szBuf, sizeof(szBuf));
04516         siCNode->dwAttributes = ParseComponentAttributes(szBuf, 0, FALSE);
04517         if(*szOverrideAttributes != '\0')
04518           siCNode->dwAttributes = ParseComponentAttributes(szOverrideAttributes, siCNode->dwAttributes, TRUE);
04519       }
04520     }
04521 
04522     ++dwIndex0;
04523     wsprintf(szComponentKey, "C%d", dwIndex0);
04524     GetConfigIniProfileString(szSTSection, szComponentKey, "", szComponentSection, sizeof(szComponentSection));
04525   }
04526 }
04527 
04528 char *SiCNodeGetReferenceName(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04529 {
04530   DWORD dwCount = 0;
04531   siC   *siCTemp = siComponents;
04532 
04533   if(siCTemp != NULL)
04534   {
04535     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04536        ((dwACFlag == AC_ALL) ||
04537        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04538        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04539     {
04540       if(dwIndex == 0)
04541         return(siCTemp->szReferenceName);
04542 
04543       ++dwCount;
04544     }
04545 
04546     siCTemp = siCTemp->Next;
04547     while((siCTemp != NULL) && (siCTemp != siComponents))
04548     {
04549       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04550          ((dwACFlag == AC_ALL) ||
04551          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04552          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04553       {
04554         if(dwIndex == dwCount)
04555           return(siCTemp->szReferenceName);
04556       
04557         ++dwCount;
04558       }
04559 
04560       siCTemp = siCTemp->Next;
04561     }
04562   }
04563   return(NULL);
04564 }
04565 
04566 char *SiCNodeGetDescriptionShort(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04567 {
04568   DWORD dwCount = 0;
04569   siC   *siCTemp = siComponents;
04570 
04571   if(siCTemp != NULL)
04572   {
04573     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04574        ((dwACFlag == AC_ALL) ||
04575        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04576        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04577     {
04578       if(dwIndex == 0)
04579         return(siCTemp->szDescriptionShort);
04580 
04581       ++dwCount;
04582     }
04583 
04584     siCTemp = siCTemp->Next;
04585     while((siCTemp != NULL) && (siCTemp != siComponents))
04586     {
04587       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04588          ((dwACFlag == AC_ALL) ||
04589          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04590          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04591       {
04592         if(dwIndex == dwCount)
04593           return(siCTemp->szDescriptionShort);
04594       
04595         ++dwCount;
04596       }
04597 
04598       siCTemp = siCTemp->Next;
04599     }
04600   }
04601   return(NULL);
04602 }
04603 
04604 char *SiCNodeGetDescriptionLong(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04605 {
04606   DWORD dwCount = 0;
04607   siC   *siCTemp = siComponents;
04608 
04609   if(siCTemp != NULL)
04610   {
04611     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04612        ((dwACFlag == AC_ALL) ||
04613        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04614        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04615     {
04616       if(dwIndex == 0)
04617         return(siCTemp->szDescriptionLong);
04618 
04619       ++dwCount;
04620     }
04621 
04622     siCTemp = siCTemp->Next;
04623     while((siCTemp != NULL) && (siCTemp != siComponents))
04624     {
04625       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04626          ((dwACFlag == AC_ALL) ||
04627          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04628          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04629       {
04630         if(dwIndex == dwCount)
04631           return(siCTemp->szDescriptionLong);
04632       
04633         ++dwCount;
04634       }
04635 
04636       siCTemp = siCTemp->Next;
04637     }
04638   }
04639   return(NULL);
04640 }
04641 
04642 ULONGLONG SiCNodeGetInstallSize(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04643 {
04644   DWORD dwCount   = 0;
04645   siC   *siCTemp  = siComponents;
04646 
04647   if(siCTemp != NULL)
04648   {
04649     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04650        ((dwACFlag == AC_ALL) ||
04651        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04652        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04653     {
04654       if(dwIndex == 0)
04655         return(siCTemp->ullInstallSize);
04656 
04657       ++dwCount;
04658     }
04659     
04660     siCTemp = siCTemp->Next;
04661     while((siCTemp != NULL) && (siCTemp != siComponents))
04662     {
04663       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04664          ((dwACFlag == AC_ALL) ||
04665          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04666          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04667       {
04668         if(dwIndex == dwCount)
04669           return(siCTemp->ullInstallSize);
04670       
04671         ++dwCount;
04672       }
04673       
04674       siCTemp = siCTemp->Next;
04675     }
04676   }
04677   return(0L);
04678 }
04679 
04680 ULONGLONG SiCNodeGetInstallSizeSystem(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04681 {
04682   DWORD dwCount   = 0;
04683   siC   *siCTemp  = siComponents;
04684 
04685   if(siCTemp != NULL)
04686   {
04687     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04688        ((dwACFlag == AC_ALL) ||
04689        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04690        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04691     {
04692       if(dwIndex == 0)
04693         return(siCTemp->ullInstallSizeSystem);
04694 
04695       ++dwCount;
04696     }
04697     
04698     siCTemp = siCTemp->Next;
04699     while((siCTemp != NULL) && (siCTemp != siComponents))
04700     {
04701       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04702          ((dwACFlag == AC_ALL) ||
04703          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04704          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04705       {
04706         if(dwIndex == dwCount)
04707           return(siCTemp->ullInstallSizeSystem);
04708       
04709         ++dwCount;
04710       }
04711       
04712       siCTemp = siCTemp->Next;
04713     }
04714   }
04715   return(0L);
04716 }
04717 
04718 ULONGLONG SiCNodeGetInstallSizeArchive(DWORD dwIndex, BOOL bIncludeInvisible, DWORD dwACFlag)
04719 {
04720   DWORD dwCount   = 0;
04721   siC   *siCTemp  = siComponents;
04722 
04723   if(siCTemp != NULL)
04724   {
04725     if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04726        ((dwACFlag == AC_ALL) ||
04727        ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04728        ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04729     {
04730       if(dwIndex == 0)
04731         return(siCTemp->ullInstallSizeArchive);
04732 
04733       ++dwCount;
04734     }
04735     
04736     siCTemp = siCTemp->Next;
04737     while((siCTemp != NULL) && (siCTemp != siComponents))
04738     {
04739       if(((bIncludeInvisible == TRUE) || ((bIncludeInvisible == FALSE) && (!(siCTemp->dwAttributes & SIC_INVISIBLE)))) &&
04740          ((dwACFlag == AC_ALL) ||
04741          ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04742          ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04743       {
04744         if(dwIndex == dwCount)
04745           return(siCTemp->ullInstallSizeArchive);
04746       
04747         ++dwCount;
04748       }
04749       
04750       siCTemp = siCTemp->Next;
04751     }
04752   }
04753   return(0L);
04754 }
04755 
04756 /* retrieve Index of node containing short description */
04757 int SiCNodeGetIndexDS(char *szInDescriptionShort)
04758 {
04759   DWORD dwCount = 0;
04760   siC   *siCTemp = siComponents;
04761 
04762   if(siCTemp != NULL)
04763   {
04764     if(lstrcmpi(szInDescriptionShort, siCTemp->szDescriptionShort) == 0)
04765       return(dwCount);
04766 
04767     ++dwCount;
04768     siCTemp = siCTemp->Next;
04769     while((siCTemp != NULL) && (siCTemp != siComponents))
04770     {
04771       if(lstrcmpi(szInDescriptionShort, siCTemp->szDescriptionShort) == 0)
04772         return(dwCount);
04773       
04774       ++dwCount;
04775       siCTemp = siCTemp->Next;
04776     }
04777   }
04778   return(-1);
04779 }
04780 
04781 /* retrieve Index of node containing Reference Name */
04782 int SiCNodeGetIndexRN(char *szInReferenceName)
04783 {
04784   DWORD dwCount = 0;
04785   siC   *siCTemp = siComponents;
04786 
04787   if(siCTemp != NULL)
04788   {
04789     if(lstrcmpi(szInReferenceName, siCTemp->szReferenceName) == 0)
04790       return(dwCount);
04791 
04792     ++dwCount;
04793     siCTemp = siCTemp->Next;
04794     while((siCTemp != NULL) && (siCTemp != siComponents))
04795     {
04796       if(lstrcmpi(szInReferenceName, siCTemp->szReferenceName) == 0)
04797         return(dwCount);
04798       
04799       ++dwCount;
04800       siCTemp = siCTemp->Next;
04801     }
04802   }
04803   return(-1);
04804 }
04805 
04806 siC *SiCNodeGetObject(DWORD dwIndex, BOOL bIncludeInvisibleObjs, DWORD dwACFlag)
04807 {
04808   DWORD dwCount = -1;
04809   siC   *siCTemp = siComponents;
04810 
04811   if(siCTemp != NULL)
04812   {
04813     if((bIncludeInvisibleObjs) &&
04814       ((dwACFlag == AC_ALL) ||
04815       ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04816       ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04817     {
04818       ++dwCount;
04819     }
04820     else if((!(siCTemp->dwAttributes & SIC_INVISIBLE)) &&
04821            ((dwACFlag == AC_ALL) ||
04822            ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04823            ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04824     {
04825       ++dwCount;
04826     }
04827 
04828     if(dwIndex == dwCount)
04829       return(siCTemp);
04830 
04831     siCTemp = siCTemp->Next;
04832     while((siCTemp != siComponents) && (siCTemp != NULL))
04833     {
04834       if(bIncludeInvisibleObjs)
04835       {
04836         ++dwCount;
04837       }
04838       else if((!(siCTemp->dwAttributes & SIC_INVISIBLE)) &&
04839              ((dwACFlag == AC_ALL) ||
04840              ((dwACFlag == AC_COMPONENTS)            && (!(siCTemp->dwAttributes & SIC_ADDITIONAL))) ||
04841              ((dwACFlag == AC_ADDITIONAL_COMPONENTS) &&   (siCTemp->dwAttributes & SIC_ADDITIONAL))))
04842       {
04843         ++dwCount;
04844       }
04845 
04846       if(dwIndex == dwCount)
04847         return(siCTemp);
04848       
04849       siCTemp = siCTemp->Next;
04850     }
04851   }
04852   return(NULL);
04853 }
04854 
04855 DWORD GetAdditionalComponentsCount()
04856 {
04857   DWORD dwCount  = 0;
04858   siC   *siCTemp = siComponents;
04859 
04860   if(siCTemp != NULL)
04861   {
04862     if(siCTemp->dwAttributes & SIC_ADDITIONAL)
04863     {
04864       ++dwCount;
04865     }
04866 
04867     siCTemp = siCTemp->Next;
04868     while((siCTemp != siComponents) && (siCTemp != NULL))
04869     {
04870       if(siCTemp->dwAttributes & SIC_ADDITIONAL)
04871       {
04872         ++dwCount;
04873       }
04874       
04875       siCTemp = siCTemp->Next;
04876     }
04877   }
04878   return(dwCount);
04879 }
04880 
04881 dsN *CreateDSNode()
04882 {
04883   dsN *dsNode;
04884 
04885   if((dsNode = NS_GlobalAlloc(sizeof(struct diskSpaceNode))) == NULL)
04886     exit(1);
04887 
04888   dsNode->ullSpaceRequired = 0;
04889 
04890   if((dsNode->szVDSPath = NS_GlobalAlloc(MAX_BUF)) == NULL)
04891     exit(1);
04892   if((dsNode->szPath = NS_GlobalAlloc(MAX_BUF)) == NULL)
04893     exit(1);
04894   dsNode->Next             = dsNode;
04895   dsNode->Prev             = dsNode;
04896 
04897   return(dsNode);
04898 }
04899 
04900 void DsNodeInsert(dsN **dsNHead, dsN *dsNTemp)
04901 {
04902   if(*dsNHead == NULL)
04903   {
04904     *dsNHead          = dsNTemp;
04905     (*dsNHead)->Next  = *dsNHead;
04906     (*dsNHead)->Prev  = *dsNHead;
04907   }
04908   else
04909   {
04910     dsNTemp->Next           = *dsNHead;
04911     dsNTemp->Prev           = (*dsNHead)->Prev;
04912     (*dsNHead)->Prev->Next  = dsNTemp;
04913     (*dsNHead)->Prev        = dsNTemp;
04914   }
04915 }
04916 
04917 void DsNodeDelete(dsN **dsNTemp)
04918 {
04919   if(*dsNTemp != NULL)
04920   {
04921     (*dsNTemp)->Next->Prev = (*dsNTemp)->Prev;
04922     (*dsNTemp)->Prev->Next = (*dsNTemp)->Next;
04923     (*dsNTemp)->Next       = NULL;
04924     (*dsNTemp)->Prev       = NULL;
04925 
04926     FreeMemory(&((*dsNTemp)->szVDSPath));
04927     FreeMemory(&((*dsNTemp)->szPath));
04928     FreeMemory(dsNTemp);
04929   }
04930 }
04931 
04932 BOOL IsWin95Debute()
04933 {
04934   HINSTANCE hLib;
04935   BOOL      bIsWin95Debute;
04936 
04937   bIsWin95Debute = FALSE;
04938   if((hLib = LoadLibraryEx("kernel32.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) != NULL)
04939   {
04940     if(((FARPROC)NS_GetDiskFreeSpaceEx = GetProcAddress(hLib, "GetDiskFreeSpaceExA")) == NULL)
04941     {
04942       (FARPROC)NS_GetDiskFreeSpace = GetProcAddress(hLib, "GetDiskFreeSpaceA");
04943       bIsWin95Debute = TRUE;
04944     }
04945 
04946     FreeLibrary(hLib);
04947   }
04948   return(bIsWin95Debute);
04949 }
04950 
04951 /* returns the value in kilobytes */
04952 ULONGLONG GetDiskSpaceRequired(DWORD dwType)
04953 {
04954   ULONGLONG ullTotalSize = 0;
04955   siC       *siCTemp     = siComponents;
04956 
04957   if(siCTemp != NULL)
04958   {
04959     if(siCTemp->dwAttributes & SIC_SELECTED)
04960     {
04961       switch(dwType)
04962       {
04963         case DSR_DESTINATION:
04964           ullTotalSize += siCTemp->ullInstallSize;
04965           break;
04966 
04967         case DSR_SYSTEM:
04968           ullTotalSize += siCTemp->ullInstallSizeSystem;
04969           break;
04970 
04971         case DSR_TEMP:
04972         case DSR_DOWNLOAD_SIZE:
04973           if((LocateJar(siCTemp, NULL, 0, gbPreviousUnfinishedDownload) == AP_NOT_FOUND) ||
04974              (dwType == DSR_DOWNLOAD_SIZE))
04975             ullTotalSize += siCTemp->ullInstallSizeArchive;
04976           break;
04977       }
04978     }
04979 
04980     siCTemp = siCTemp->Next;
04981     while((siCTemp != NULL) && (siCTemp != siComponents))
04982     {
04983       if(siCTemp->dwAttributes & SIC_SELECTED)
04984       {
04985         switch(dwType)
04986         {
04987           case DSR_DESTINATION:
04988             ullTotalSize += siCTemp->ullInstallSize;
04989             break;
04990 
04991           case DSR_SYSTEM:
04992             ullTotalSize += siCTemp->ullInstallSizeSystem;
04993             break;
04994 
04995           case DSR_TEMP:
04996           case DSR_DOWNLOAD_SIZE:
04997             if((LocateJar(siCTemp, NULL, 0, gbPreviousUnfinishedDownload) == AP_NOT_FOUND) ||
04998                (dwType == DSR_DOWNLOAD_SIZE))
04999               ullTotalSize += siCTemp->ullInstallSizeArchive;
05000             break;
05001         }
05002       }
05003 
05004       siCTemp = siCTemp->Next;
05005     }
05006   }
05007 
05008   /* add the amount of disk space it will take for the 
05009      xpinstall engine in the TEMP area */
05010   if(dwType == DSR_TEMP)
05011     if(siCFXpcomFile.bStatus == STATUS_ENABLED)
05012       ullTotalSize += siCFXpcomFile.ullInstallSize;
05013 
05014   return(ullTotalSize);
05015 }
05016 
05017 int LocateExistingPath(char *szPath, char *szExistingPath, DWORD dwExistingPathSize)
05018 {
05019   char szBuf[MAX_BUF];
05020 
05021   lstrcpy(szExistingPath, szPath);
05022   AppendBackSlash(szExistingPath, dwExistingPathSize);
05023   while((FileExists(szExistingPath) == FALSE))
05024   {
05025     RemoveBackSlash(szExistingPath);
05026     ParsePath(szExistingPath, szBuf, sizeof(szBuf), FALSE, PP_PATH_ONLY);
05027     lstrcpy(szExistingPath, szBuf);
05028     AppendBackSlash(szExistingPath, dwExistingPathSize);
05029   }
05030   return(WIZ_OK);
05031 }
05032 
05033 /* returns the value in bytes */
05034 ULONGLONG GetDiskSpaceAvailable(LPSTR szPath)
05035 {
05036   char            szTempPath[MAX_BUF];
05037   char            szBuf[MAX_BUF];
05038   char            szExistingPath[MAX_BUF];
05039   char            szBuf2[MAX_BUF];
05040   ULARGE_INTEGER  uliFreeBytesAvailableToCaller;
05041   ULARGE_INTEGER  uliTotalNumberOfBytesToCaller;
05042   ULARGE_INTEGER  uliTotalNumberOfFreeBytes;
05043   ULONGLONG       ullReturn = 0;
05044   DWORD           dwSectorsPerCluster;
05045   DWORD           dwBytesPerSector;
05046   DWORD           dwNumberOfFreeClusters;
05047   DWORD           dwTotalNumberOfClusters;
05048 
05049   if((gSystemInfo.dwOSType & OS_WIN95_DEBUTE) && (NS_GetDiskFreeSpace != NULL))
05050   {
05051     ParsePath(szPath, szTempPath, MAX_BUF, FALSE, PP_ROOT_ONLY);
05052     NS_GetDiskFreeSpace(szTempPath, 
05053                         &dwSectorsPerCluster,
05054                         &dwBytesPerSector,
05055                         &dwNumberOfFreeClusters,
05056                         &dwTotalNumberOfClusters);
05057     ullReturn = ((ULONGLONG)dwBytesPerSector * (ULONGLONG)dwSectorsPerCluster * (ULONGLONG)dwNumberOfFreeClusters);
05058   }
05059   else if(NS_GetDiskFreeSpaceEx != NULL)
05060   {
05061     LocateExistingPath(szPath, szExistingPath, sizeof(szExistingPath));
05062     AppendBackSlash(szExistingPath, sizeof(szExistingPath));
05063 
05064     /* Appearently under Win9x, the path still needs to be in 8.3 format
05065      * or GetDiskFreeSpaceEx() will fail. */
05066     if(gSystemInfo.dwOSType & OS_WIN9x)
05067     {
05068       lstrcpy(szBuf, szExistingPath);
05069       GetShortPathName(szBuf, szExistingPath, sizeof(szExistingPath));
05070     }
05071 
05072     if(NS_GetDiskFreeSpaceEx(szExistingPath,
05073                              &uliFreeBytesAvailableToCaller,
05074                              &uliTotalNumberOfBytesToCaller,
05075                              &uliTotalNumberOfFreeBytes) == FALSE)
05076     {
05077       char szEDeterminingDiskSpace[MAX_BUF];
05078 
05079       if(GetPrivateProfileString("Messages", "ERROR_DETERMINING_DISK_SPACE", "", szEDeterminingDiskSpace, sizeof(szEDeterminingDiskSpace), szFileIniInstall))
05080       {
05081         lstrcpy(szBuf2, "\n    ");
05082         lstrcat(szBuf2, szPath);
05083         wsprintf(szBuf, szEDeterminingDiskSpace, szBuf2);
05084         PrintError(szBuf, ERROR_CODE_SHOW);
05085       }
05086     }
05087     ullReturn = uliFreeBytesAvailableToCaller.QuadPart;
05088   }
05089 
05090   if(ullReturn > 1024)
05091     ullReturn /= 1024;
05092   else
05093     ullReturn = 0;
05094 
05095   return(ullReturn);
05096 }
05097 
05098 HRESULT ErrorMsgDiskSpace(ULONGLONG ullDSAvailable, ULONGLONG ullDSRequired, LPSTR szPath, BOOL bCrutialMsg)
05099 {
05100   char      szBuf0[MAX_BUF];
05101   char      szBuf1[MAX_BUF];
05102   char      szBuf2[MAX_BUF];
05103   char      szBuf3[MAX_BUF];
05104   char      szBufRootPath[MAX_BUF];
05105   char      szBufMsg[MAX_BUF];
05106   char      szDSAvailable[MAX_BUF];
05107   char      szDSRequired[MAX_BUF];
05108   char      szDlgDiskSpaceCheckTitle[MAX_BUF];
05109   char      szDlgDiskSpaceCheckMsg[MAX_BUF];
05110   DWORD     dwDlgType;
05111 
05112   if(!GetPrivateProfileString("Messages", "DLG_DISK_SPACE_CHECK_TITLE", "", szDlgDiskSpaceCheckTitle, sizeof(szDlgDiskSpaceCheckTitle), szFileIniInstall))
05113     exit(1);
05114 
05115   if(bCrutialMsg)
05116   {
05117     dwDlgType = MB_RETRYCANCEL;
05118     if(!GetPrivateProfileString("Messages", "DLG_DISK_SPACE_CHECK_CRUTIAL_MSG", "", szDlgDiskSpaceCheckMsg, sizeof(szDlgDiskSpaceCheckMsg), szFileIniInstall))
05119       exit(1);
05120   }
05121   else
05122   {
05123     dwDlgType = MB_OK;
05124     if(!GetPrivateProfileString("Messages", "DLG_DISK_SPACE_CHECK_MSG", "", szDlgDiskSpaceCheckMsg, sizeof(szDlgDiskSpaceCheckMsg), szFileIniInstall))
05125       exit(1);
05126   }
05127 
05128   ParsePath(szPath, szBufRootPath, sizeof(szBufRootPath), FALSE, PP_ROOT_ONLY);
05129   RemoveBackSlash(szBufRootPath);
05130   lstrcpy(szBuf0, szPath);
05131   RemoveBackSlash(szBuf0);
05132 
05133   _ui64toa(ullDSAvailable, szDSAvailable, 10);
05134   _ui64toa(ullDSRequired, szDSRequired, 10);
05135 
05136   wsprintf(szBuf1, "\n\n    %s\n\n    ", szBuf0);
05137   wsprintf(szBuf2, "%s KB\n    ",        szDSRequired);
05138   wsprintf(szBuf3, "%s KB\n\n",          szDSAvailable);
05139   wsprintf(szBufMsg, szDlgDiskSpaceCheckMsg, szBufRootPath, szBuf1, szBuf2, szBuf3);
05140 
05141   if((sgProduct.mode != SILENT) && (sgProduct.mode != AUTO))
05142   {
05143     return(MessageBox(hWndMain, szBufMsg, szDlgDiskSpaceCheckTitle, dwDlgType | MB_ICONEXCLAMATION | MB_DEFBUTTON2 | MB_APPLMODAL | MB_SETFOREGROUND));
05144   }
05145   else if(sgProduct.mode == AUTO)
05146   {
05147     ShowMessage(szBufMsg, TRUE);
05148     Delay(5);
05149     ShowMessage(szBufMsg, FALSE);
05150     exit(1);
05151   }
05152 
05153   return(IDCANCEL);
05154 }
05155 
05156 BOOL ContainsReparseTag(char *szPath, char *szReparsePath, DWORD dwReparsePathSize)
05157 {
05158   BOOL  bFoundReparseTag  = FALSE;
05159   DWORD dwOriginalLen     = lstrlen(szPath);
05160   DWORD dwLen             = dwOriginalLen;
05161   char  *szPathTmp        = NULL;
05162   char  *szBuf            = NULL;
05163 
05164   if((szPathTmp = NS_GlobalAlloc(dwLen + 1)) == NULL)
05165     exit(1);
05166   if((szBuf = NS_GlobalAlloc(dwLen + 1)) == NULL)
05167     exit(1);
05168 
05169   lstrcpy(szPathTmp, szPath);
05170   while((szPathTmp[dwLen - 2] != ':') && (szPathTmp[dwLen - 2] != '\\'))
05171   {
05172     if(FileExists(szPathTmp) & FILE_ATTRIBUTE_REPARSE_POINT)
05173     {
05174       if((DWORD)lstrlen(szPathTmp) <= dwReparsePathSize)
05175         lstrcpy(szReparsePath, szPathTmp);
05176       else
05177         ZeroMemory(szReparsePath, dwReparsePathSize);
05178 
05179       bFoundReparseTag = TRUE;
05180       break;
05181     }
05182 
05183     lstrcpy(szBuf, szPathTmp);
05184     RemoveBackSlash(szBuf);
05185     ParsePath(szBuf, szPathTmp, dwOriginalLen + 1, FALSE, PP_PATH_ONLY);
05186     dwLen = lstrlen(szPathTmp);
05187   }
05188 
05189   FreeMemory(&szBuf);
05190   FreeMemory(&szPathTmp);
05191   return(bFoundReparseTag);
05192 }
05193 
05194 void UpdatePathDiskSpaceRequired(LPSTR szPath, ULONGLONG ullSize, dsN **dsnComponentDSRequirement)
05195 {
05196   BOOL  bFound = FALSE;
05197   dsN   *dsnTemp = *dsnComponentDSRequirement;
05198   char  szReparsePath[MAX_BUF];
05199   char  szVDSPath[MAX_BUF];
05200   char  szRootPath[MAX_BUF];
05201 
05202   if(ullSize > 0)
05203   {
05204     ParsePath(szPath, szRootPath, sizeof(szRootPath), FALSE, PP_ROOT_ONLY);
05205 
05206     if(gSystemInfo.dwOSType & OS_WIN95_DEBUTE)
05207       // check for Win95 debute version
05208       lstrcpy(szVDSPath, szRootPath);
05209     else if((gSystemInfo.dwOSType & OS_NT5) &&
05210              ContainsReparseTag(szPath, szReparsePath, sizeof(szReparsePath)))
05211     {
05212       // check for Reparse Tag (mount points under NT5 only)
05213       if(*szReparsePath == '\0')
05214       {
05215         // szReparsePath is not big enough to hold the Reparse path.  This is a
05216         // non fatal error.  Keep going using szPath instead.
05217         lstrcpy(szVDSPath, szPath);
05218       }
05219       else if(GetDiskSpaceAvailable(szReparsePath) == GetDiskSpaceAvailable(szPath))
05220         // Check for user quota on path.  It is very unlikely that the user quota
05221         // for the path will be the same as the quota for its root path when user
05222         // quota is enabled.
05223         //
05224         // If it happens to be the same, then I'm assuming that the disk space on
05225         // the path's root path will decrease at the same rate as the path with
05226         // user quota enabled.
05227         //
05228         // If user quota is not enabled on the folder, then use the root path.
05229         lstrcpy(szVDSPath, szReparsePath);
05230       else
05231         lstrcpy(szVDSPath, szPath);
05232     }
05233     else if(GetDiskSpaceAvailable(szRootPath) == GetDiskSpaceAvailable(szPath))
05234       // Check for user quota on path.  It is very unlikely that the user quota
05235       // for the path will be the same as the quota for its root path when user
05236       // quota is enabled.
05237       //
05238       // If it happens to be the same, then I'm assuming that the disk space on
05239       // the path's root path will decrease at the same rate as the path with
05240       // user quota enabled.
05241       //
05242       // If user quota is not enabled on the folder, then use the root path.
05243       lstrcpy(szVDSPath, szRootPath);
05244     else
05245       lstrcpy(szVDSPath, szPath);
05246 
05247     do
05248     {
05249       if(*dsnComponentDSRequirement == NULL)
05250       {
05251         *dsnComponentDSRequirement = CreateDSNode();
05252         dsnTemp = *dsnComponentDSRequirement;
05253         strcpy(dsnTemp->szVDSPath, szVDSPath);
05254         strcpy(dsnTemp->szPath, szPath);
05255         dsnTemp->ullSpaceRequired = ullSize;
05256         bFound = TRUE;
05257       }
05258       else if(lstrcmpi(dsnTemp->szVDSPath, szVDSPath) == 0)
05259       {
05260         dsnTemp->ullSpaceRequired += ullSize;
05261         bFound = TRUE;
05262       }
05263       else
05264         dsnTemp = dsnTemp->Next;
05265 
05266     } while((dsnTemp != *dsnComponentDSRequirement) && (dsnTemp != NULL) && (bFound == FALSE));
05267 
05268     if(bFound == FALSE)
05269     {
05270       dsnTemp = CreateDSNode();
05271       strcpy(dsnTemp->szVDSPath, szVDSPath);
05272       strcpy(dsnTemp->szPath, szPath);
05273       dsnTemp->ullSpaceRequired = ullSize;
05274       DsNodeInsert(dsnComponentDSRequirement, dsnTemp);
05275     }
05276   }
05277 }
05278 
05279 /* Function: DetermineGreComponentDestinationPath()
05280  *
05281  *       in: char *aInPath - original path to where the 'Component GRE' is to
05282  *               be installed to.
05283  *           char *aOutPath - out buffer of what the new destinaton path will
05284  *               be for 'Component GRE'.  This can be the same as aInPath.
05285  *
05286  *  purpose: To figure determine if the original path is writable or not.  If
05287  *           not, then use following as the new destination path:
05288  *
05289  *               [product path]\GRE\[gre id]
05290  *
05291  *           This path is guaranteed to work because the user chose it.  There
05292  *           is logic to make sure we have write access to this new path thru
05293  *           the Setup Type dialog.
05294  *           This path is also the same path that will be passed on to the GRE
05295  *           installer in it's -dd command line parameter.
05296  */
05297 HRESULT DetermineGreComponentDestinationPath(char *aInPath, char *aOutPath, DWORD aOutPathBufSize)
05298 {
05299   int  rv = WIZ_OK;
05300   char inPath[MAX_BUF];
05301 
05302   MozCopyStr(aInPath, inPath, sizeof(inPath));
05303   AppendBackSlash(inPath, sizeof(inPath));
05304   if(DirHasWriteAccess(inPath) != WIZ_OK)
05305   {
05306     char productPath[MAX_BUF];
05307 
05308     MozCopyStr(sgProduct.szPath, productPath, sizeof(productPath));
05309     RemoveBackSlash(productPath);
05310 
05311     assert(*sgProduct.greID);
05312     _snprintf(aOutPath, aOutPathBufSize, "%s\\GRE\\%s", productPath, sgProduct.greID);
05313     aOutPath[aOutPathBufSize - 1] = '\0';
05314   }
05315   else
05316     MozCopyStr(aInPath, aOutPath, aOutPathBufSize);
05317 
05318   return(rv);
05319 }
05320 
05321 HRESULT InitComponentDiskSpaceInfo(dsN **dsnComponentDSRequirement)
05322 {
05323   DWORD     dwIndex0;
05324   siC       *siCObject = NULL;
05325   HRESULT   hResult    = 0;
05326   char      szBuf[MAX_BUF];
05327   char      szIndex0[MAX_BUF];
05328   char      szSysPath[MAX_BUF];
05329   char      szBufSysPath[MAX_BUF];
05330   char      szBufTempPath[MAX_BUF];
05331 
05332   if(GetSystemDirectory(szSysPath, MAX_BUF) == 0)
05333   {
05334     ZeroMemory(szSysPath, MAX_BUF);
05335     ZeroMemory(szBufSysPath, MAX_BUF);
05336   }
05337   else
05338   {
05339     ParsePath(szSysPath, szBufSysPath, sizeof(szBufSysPath), FALSE, PP_ROOT_ONLY);
05340     AppendBackSlash(szBufSysPath, sizeof(szBufSysPath));
05341   }
05342 
05343   ParsePath(szTempDir, szBufTempPath, sizeof(szBufTempPath), FALSE, PP_ROOT_ONLY);
05344   AppendBackSlash(szBufTempPath, sizeof(szBufTempPath));
05345 
05346   dwIndex0 = 0;
05347   itoa(dwIndex0, szIndex0, 10);
05348   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
05349   while(siCObject)
05350   {
05351     if(siCObject->dwAttributes & SIC_SELECTED)
05352     {
05353       if(*(siCObject->szDestinationPath) == '\0')
05354         lstrcpy(szBuf, sgProduct.szPath);
05355       else if((lstrcmpi(siCObject->szReferenceName, "Component GRE") == 0) &&
05356               !IsInstallerProductGRE())
05357         /* We found 'Component GRE' and this product is not 'GRE'.  The GRE
05358          * product happens to also have a 'Component GRE', but we don't
05359          * care about that one. */
05360         DetermineGreComponentDestinationPath(siCObject->szDestinationPath, szBuf, sizeof(szBuf));
05361       else
05362         lstrcpy(szBuf, siCObject->szDestinationPath);
05363 
05364       AppendBackSlash(szBuf, sizeof(szBuf));
05365       UpdatePathDiskSpaceRequired(szBuf, siCObject->ullInstallSize, dsnComponentDSRequirement);
05366 
05367       if(*szTempDir != '\0')
05368         UpdatePathDiskSpaceRequired(szTempDir, siCObject->ullInstallSizeArchive, dsnComponentDSRequirement);
05369 
05370       if(*szSysPath != '\0')
05371         UpdatePathDiskSpaceRequired(szSysPath, siCObject->ullInstallSizeSystem, dsnComponentDSRequirement);
05372     }
05373 
05374     ++dwIndex0;
05375     itoa(dwIndex0, szIndex0, 10);
05376     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
05377   }
05378 
05379   /* take the uncompressed size of Xpcom into account */
05380   if(*szTempDir != '\0')
05381     if(siCFXpcomFile.bStatus == STATUS_ENABLED)
05382       UpdatePathDiskSpaceRequired(szTempDir, siCFXpcomFile.ullInstallSize, dsnComponentDSRequirement);
05383 
05384   return(hResult);
05385 }
05386 
05387 HRESULT VerifyDiskSpace()
05388 {
05389   ULONGLONG ullDSAvailable;
05390   HRESULT   hRetValue = FALSE;
05391   dsN       *dsnTemp = NULL;
05392 
05393   DeInitDSNode(&gdsnComponentDSRequirement);
05394   InitComponentDiskSpaceInfo(&gdsnComponentDSRequirement);
05395   if(gdsnComponentDSRequirement != NULL)
05396   {
05397     dsnTemp = gdsnComponentDSRequirement;
05398 
05399     do
05400     {
05401       if(dsnTemp != NULL)
05402       {
05403         ullDSAvailable = GetDiskSpaceAvailable(dsnTemp->szVDSPath);
05404         if(ullDSAvailable < dsnTemp->ullSpaceRequired)
05405         {
05406           hRetValue = ErrorMsgDiskSpace(ullDSAvailable, dsnTemp->ullSpaceRequired, dsnTemp->szPath, FALSE);
05407           break;
05408         }
05409 
05410         dsnTemp = dsnTemp->Next;
05411       }
05412     } while((dsnTemp != NULL) && (dsnTemp != gdsnComponentDSRequirement));
05413   }
05414   return(hRetValue);
05415 }
05416 
05417 /* Function: ParseOSType
05418  *
05419  * Input: char *
05420  *
05421  * Return: DWORD
05422  *
05423  * Description: This function parses an input string (szOSType) for specific
05424  * string keys:
05425  *     WIN95_DEBUTE, WIN95, WIN98, NT3, NT4, NT5, NT50, NT51
05426  *
05427  * It then stores the information in a DWORD, each bit corresponding to a
05428  * particular OS type.
05429  */ 
05430 DWORD ParseOSType(char *szOSType)
05431 {
05432   char  szBuf[MAX_BUF];
05433   DWORD dwOSType = 0;
05434 
05435   lstrcpy(szBuf, szOSType);
05436   CharUpperBuff(szBuf, sizeof(szBuf));
05437 
05438   if(strstr(szBuf, "WIN95 DEBUTE"))
05439     dwOSType |= OS_WIN95_DEBUTE;
05440   if(strstr(szBuf, "WIN95") &&
05441      !strstr(szBuf, "WIN95 DEBUTE"))
05442     dwOSType |= OS_WIN95;
05443   if(strstr(szBuf, "WIN98"))
05444     dwOSType |= OS_WIN98;
05445   if(strstr(szBuf, "NT3"))
05446     dwOSType |= OS_NT3;
05447   if(strstr(szBuf, "NT4"))
05448     dwOSType |= OS_NT4;
05449   if(strstr(szBuf, "NT50"))
05450     dwOSType |= OS_NT50;
05451   if(strstr(szBuf, "NT51"))
05452     dwOSType |= OS_NT51;
05453   if(strstr(szBuf, "NT5") &&
05454      !strstr(szBuf, "NT50") &&
05455      !strstr(szBuf, "NT51"))
05456     dwOSType |= OS_NT5;
05457 
05458   return(dwOSType);
05459 }
05460 
05461 HRESULT ParseComponentAttributes(char *szAttribute, DWORD dwAttributes, BOOL bOverride)
05462 {
05463   char  szBuf[MAX_BUF];
05464 
05465   lstrcpy(szBuf, szAttribute);
05466   CharUpperBuff(szBuf, sizeof(szBuf));
05467 
05468   if(bOverride != TRUE)
05469   {
05470     if(strstr(szBuf, "LAUNCHAPP"))
05471       dwAttributes |= SIC_LAUNCHAPP;
05472     if(strstr(szBuf, "DOWNLOAD_ONLY"))
05473       dwAttributes |= SIC_DOWNLOAD_ONLY;
05474     if(strstr(szBuf, "FORCE_UPGRADE"))
05475       dwAttributes |= SIC_FORCE_UPGRADE;
05476     if(strstr(szBuf, "IGNORE_DOWNLOAD_ERROR"))
05477       dwAttributes |= SIC_IGNORE_DOWNLOAD_ERROR;
05478     if(strstr(szBuf, "IGNORE_XPINSTALL_ERROR"))
05479       dwAttributes |= SIC_IGNORE_XPINSTALL_ERROR;
05480     if(strstr(szBuf, "UNCOMPRESS"))
05481       dwAttributes |= SIC_UNCOMPRESS;
05482     if(strstr(szBuf, "MAIN_COMPONENT"))
05483       dwAttributes |= SIC_MAIN_COMPONENT;
05484   }
05485 
05486   if(strstr(szBuf, "UNSELECTED"))
05487     dwAttributes &= ~SIC_SELECTED;
05488   else if(strstr(szBuf, "SELECTED"))
05489     dwAttributes |= SIC_SELECTED;
05490 
05491   if(strstr(szBuf, "INVISIBLE"))
05492     dwAttributes |= SIC_INVISIBLE;
05493   else if(strstr(szBuf, "VISIBLE"))
05494     dwAttributes &= ~SIC_INVISIBLE;
05495 
05496   if(strstr(szBuf, "DISABLED"))
05497     dwAttributes |= SIC_DISABLED;
05498   if(strstr(szBuf, "ENABLED"))
05499     dwAttributes &= ~SIC_DISABLED;
05500 
05501   if(strstr(szBuf, "NOTADDITIONAL"))
05502     dwAttributes &= ~SIC_ADDITIONAL;
05503   else if(strstr(szBuf, "ADDITIONAL"))
05504     dwAttributes |= SIC_ADDITIONAL;
05505 
05506   if(strstr(szBuf, "NOTSUPERSEDE"))
05507     dwAttributes &= ~SIC_SUPERSEDE;
05508   else if(strstr(szBuf, "SUPERSEDE"))
05509     dwAttributes |= SIC_SUPERSEDE;
05510    
05511 
05512   return(dwAttributes);
05513 }
05514 
05515 long RandomSelect()
05516 {
05517   long lArbitrary = 0;
05518 
05519   srand((unsigned)time(NULL));
05520   lArbitrary = rand() % 100;
05521   return(lArbitrary);
05522 }
05523 
05524 siC *SiCNodeFind(siC *siCHeadNode, char *szInReferenceName)
05525 {
05526   siC *siCNode = siCHeadNode;
05527 
05528   do
05529   {
05530     if(siCNode == NULL)
05531       break;
05532 
05533     if(lstrcmpi(siCNode->szReferenceName, szInReferenceName) == 0)
05534       return(siCNode);
05535 
05536     siCNode = siCNode->Next;
05537   } while((siCNode != NULL) && (siCNode != siCHeadNode));
05538 
05539   return(NULL);
05540 }
05541 
05542 BOOL ResolveForceUpgrade(siC *siCObject)
05543 {
05544   DWORD dwIndex;
05545   char  szFilePath[MAX_BUF];
05546   char  szKey[MAX_BUF_TINY];
05547   char  szForceUpgradeFile[MAX_BUF];
05548 
05549   siCObject->bForceUpgrade = FALSE;
05550   if(siCObject->dwAttributes & SIC_FORCE_UPGRADE)
05551   {
05552     if(!sgProduct.doCleanupOnUpgrade)
05553     {
05554       dwIndex = 0;
05555       BuildNumberedString(dwIndex, NULL, "Force Upgrade File", szKey, sizeof(szKey));
05556       GetConfigIniProfileString(siCObject->szReferenceName, szKey, "", szForceUpgradeFile, sizeof(szForceUpgradeFile));
05557       while(*szForceUpgradeFile != '\0')
05558       {
05559         DecryptString(szFilePath, szForceUpgradeFile);
05560         if(FileExists(szFilePath))
05561         {
05562           siCObject->bForceUpgrade = TRUE;
05563 
05564           /* Found at least one file, so break out of while loop */
05565           break;
05566         }
05567 
05568         BuildNumberedString(++dwIndex, NULL, "Force Upgrade File", szKey, sizeof(szKey));
05569         GetConfigIniProfileString(siCObject->szReferenceName, szKey, "", szForceUpgradeFile, sizeof(szForceUpgradeFile));
05570       }
05571     }
05572 
05573     if(siCObject->bForceUpgrade)
05574     {
05575       siCObject->dwAttributes |= SIC_SELECTED;
05576       siCObject->dwAttributes |= SIC_DISABLED;
05577     }
05578     else
05579       /* Make sure to unset the DISABLED bit.  If the Setup Type is other than
05580        * Custom, then we don't care if it's DISABLED or not because this flag
05581        * is only used in the Custom dialogs.
05582        *
05583        * If the Setup Type is Custom and this component is DISABLED by default
05584        * via the config.ini, it's default value will be restored in the
05585        * SiCNodeSetItemsSelected() function that called ResolveForceUpgrade(). */
05586       siCObject->dwAttributes &= ~SIC_DISABLED;
05587   }
05588   return(siCObject->bForceUpgrade);
05589 }
05590 
05591 void InitSiComponents()
05592 {
05593   DWORD dwIndex0;
05594   DWORD dwIndex1;
05595   int   iCurrentLoop;
05596   char  szIndex0[MAX_BUF];
05597   char  szIndex1[MAX_BUF];
05598   char  szBuf[MAX_BUF];
05599   char  szComponentKey[MAX_BUF];
05600   char  szComponentSection[MAX_BUF];
05601   char  szDependency[MAX_BUF];
05602   char  szDependee[MAX_BUF];
05603   char  szSTSection[MAX_BUF];
05604   char  szDPSection[MAX_BUF];
05605   siC   *siCTemp            = NULL;
05606   siCD  *siCDepTemp         = NULL;
05607   siCD  *siCDDependeeTemp   = NULL;
05608 
05609   /* clean up the list before reading new components given the Setup Type */
05610   DeInitSiComponents(&siComponents);
05611 
05612   /* Parse the Setup Type sections in reverse order because
05613    * the Custom Setup Type is always last.  It needs to be parsed
05614    * first because the component list it has will be shown in its
05615    * other custom dialogs.  Order matters! */
05616   for(iCurrentLoop = 3; iCurrentLoop >= 0; iCurrentLoop--)
05617   {
05618     lstrcpy(szSTSection, "Setup Type");
05619     itoa(iCurrentLoop, szBuf, 10);
05620     lstrcat(szSTSection, szBuf);
05621 
05622     /* read in each component given a setup type */
05623     dwIndex0 = 0;
05624     itoa(dwIndex0, szIndex0, 10);
05625     lstrcpy(szComponentKey, "C");
05626     lstrcat(szComponentKey, szIndex0);
05627     GetConfigIniProfileString(szSTSection, szComponentKey, "", szComponentSection, sizeof(szComponentSection));
05628     while(*szComponentSection != '\0')
05629     {
05630       GetConfigIniProfileString(szComponentSection, "Archive", "", szBuf, sizeof(szBuf));
05631       if((*szBuf != '\0') && (SiCNodeFind(siComponents, szComponentSection) == NULL))
05632       {
05633         /* create and initialize empty node */
05634         siCTemp = CreateSiCNode();
05635 
05636         /* store name of archive for component */
05637         lstrcpy(siCTemp->szArchiveName, szBuf);
05638 
05639         /* store name of the uncompressed archive for the component */
05640         GetConfigIniProfileString(szComponentSection, "Archive Uncompressed", "",
05641                                   siCTemp->szArchiveNameUncompressed, sizeof(szBuf));
05642         
05643         /* get short description of component */
05644         GetConfigIniProfileString(szComponentSection, "Description Short", "", szBuf, sizeof(szBuf));
05645         lstrcpy(siCTemp->szDescriptionShort, szBuf);
05646 
05647         /* get long description of component */
05648         GetConfigIniProfileString(szComponentSection, "Description Long", "", szBuf, sizeof(szBuf));
05649         lstrcpy(siCTemp->szDescriptionLong, szBuf);
05650 
05651         /* get commandline parameter for component */
05652         GetConfigIniProfileString(szComponentSection, "Parameter", "", siCTemp->szParameter, MAX_BUF);
05653 
05654         /* set reference name for component */
05655         lstrcpy(siCTemp->szReferenceName, szComponentSection);
05656 
05657         /* get install size required in destination for component.  Sould be in Kilobytes */
05658         GetConfigIniProfileString(szComponentSection, "Install Size", "", szBuf, sizeof(szBuf));
05659         if(*szBuf != '\0')
05660           siCTemp->ullInstallSize = _atoi64(szBuf);
05661         else
05662           siCTemp->ullInstallSize = 0;
05663 
05664         /* get install size required in system for component.  Sould be in Kilobytes */
05665         GetConfigIniProfileString(szComponentSection, "Install Size System", "", szBuf, sizeof(szBuf));
05666         if(*szBuf != '\0')
05667           siCTemp->ullInstallSizeSystem = _atoi64(szBuf);
05668         else
05669           siCTemp->ullInstallSizeSystem = 0;
05670 
05671         /* get install size required in temp for component.  Sould be in Kilobytes */
05672         GetConfigIniProfileString(szComponentSection, "Install Size Archive", "", szBuf, sizeof(szBuf));
05673         if(*szBuf != '\0')
05674           siCTemp->ullInstallSizeArchive = _atoi64(szBuf);
05675         else
05676           siCTemp->ullInstallSizeArchive = 0;
05677 
05678         /* get attributes of component */
05679         GetConfigIniProfileString(szComponentSection, "Attributes", "", szBuf, sizeof(szBuf));
05680         siCTemp->dwAttributes = ParseComponentAttributes(szBuf, 0, FALSE);
05681 
05682         /* get the component's file count */
05683         GetConfigIniProfileString(szComponentSection, "FileCount", "", szBuf, sizeof(szBuf));
05684         siCTemp->iFileCount = atoi(szBuf);
05685 
05686         /* get the random percentage value and select or deselect the component (by default) for
05687          * installation */
05688         GetConfigIniProfileString(szComponentSection, "Random Install Percentage", "", szBuf, sizeof(szBuf));
05689         if(*szBuf != '\0')
05690         {
05691           siCTemp->lRandomInstallPercentage = atol(szBuf);
05692           if(siCTemp->lRandomInstallPercentage != 0)
05693             siCTemp->lRandomInstallValue = RandomSelect();
05694         }
05695 
05696         /* get all dependencies for this component */
05697         dwIndex1 = 0;
05698         itoa(dwIndex1, szIndex1, 10);
05699         lstrcpy(szDependency, "Dependency");
05700         lstrcat(szDependency, szIndex1);
05701         GetConfigIniProfileString(szComponentSection, szDependency, "", szBuf, sizeof(szBuf));
05702         while(*szBuf != '\0')
05703         {
05704           /* create and initialize empty node */
05705           siCDepTemp = CreateSiCDepNode();
05706 
05707           /* store name of archive for component */
05708           lstrcpy(siCDepTemp->szReferenceName, szBuf);
05709 
05710           /* inserts the newly created component into the global component list */
05711           SiCDepNodeInsert(&(siCTemp->siCDDependencies), siCDepTemp);
05712 
05713           ProcessWindowsMessages();
05714           ++dwIndex1;
05715           itoa(dwIndex1, szIndex1, 10);
05716           lstrcpy(szDependency, "Dependency");
05717           lstrcat(szDependency, szIndex1);
05718           GetConfigIniProfileString(szComponentSection, szDependency, "", szBuf, sizeof(szBuf));
05719         }
05720 
05721         /* get all dependees for this component */
05722         dwIndex1 = 0;
05723         itoa(dwIndex1, szIndex1, 10);
05724         lstrcpy(szDependee, "Dependee");
05725         lstrcat(szDependee, szIndex1);
05726         GetConfigIniProfileString(szComponentSection, szDependee, "", szBuf, sizeof(szBuf));
05727         while(*szBuf != '\0')
05728         {
05729           /* create and initialize empty node */
05730           siCDDependeeTemp = CreateSiCDepNode();
05731 
05732           /* store name of archive for component */
05733           lstrcpy(siCDDependeeTemp->szReferenceName, szBuf);
05734 
05735           /* inserts the newly created component into the global component list */
05736           SiCDepNodeInsert(&(siCTemp->siCDDependees), siCDDependeeTemp);
05737 
05738           ProcessWindowsMessages();
05739           ++dwIndex1;
05740           itoa(dwIndex1, szIndex1, 10);
05741           lstrcpy(szDependee, "Dependee");
05742           lstrcat(szDependee, szIndex1);
05743           GetConfigIniProfileString(szComponentSection, szDependee, "", szBuf, sizeof(szBuf));
05744         }
05745 
05746         // locate previous path if necessary
05747         lstrcpy(szDPSection, szComponentSection);
05748         lstrcat(szDPSection, "-Destination Path");
05749         if(LocatePreviousPath(szDPSection, siCTemp->szDestinationPath, MAX_PATH) == FALSE)
05750           ZeroMemory(siCTemp->szDestinationPath, MAX_PATH);
05751 
05752         /* inserts the newly created component into the global component list */
05753         SiCNodeInsert(&siComponents, siCTemp);
05754       }
05755 
05756       ProcessWindowsMessages();
05757       ++dwIndex0;
05758       itoa(dwIndex0, szIndex0, 10);
05759       lstrcpy(szComponentKey, "C");
05760       lstrcat(szComponentKey, szIndex0);
05761       GetConfigIniProfileString(szSTSection, szComponentKey, "", szComponentSection, sizeof(szComponentSection));
05762     }
05763   }
05764 
05765   sgProduct.dwNumberOfComponents = dwIndex0;
05766 }
05767 
05768 void ResetComponentAttributes(char *szFileIni)
05769 {
05770   char  szIndex[MAX_BUF];
05771   char  szBuf[MAX_BUF];
05772   char  szComponentItem[MAX_BUF];
05773   siC   *siCTemp;
05774   DWORD dwCounter;
05775 
05776   for(dwCounter = 0; dwCounter < sgProduct.dwNumberOfComponents; dwCounter++)
05777   {
05778     itoa(dwCounter, szIndex, 10);
05779     lstrcpy(szComponentItem, "Component");
05780     lstrcat(szComponentItem, szIndex);
05781 
05782     siCTemp = SiCNodeGetObject(dwCounter, TRUE, AC_ALL);
05783     GetPrivateProfileString(szComponentItem, "Attributes", "", szBuf, sizeof(szBuf), szFileIni);
05784     siCTemp->dwAttributes = ParseComponentAttributes(szBuf, 0, FALSE);
05785   }
05786 }
05787 
05788 void UpdateSiteSelector()
05789 {
05790   DWORD dwIndex;
05791   char  szIndex[MAX_BUF];
05792   char  szKDescription[MAX_BUF];
05793   char  szDescription[MAX_BUF];
05794   char  szKDomain[MAX_BUF];
05795   char  szDomain[MAX_BUF];
05796   char  szFileIniRedirect[MAX_BUF];
05797   ssi   *ssiSiteSelectorTemp;
05798 
05799   lstrcpy(szFileIniRedirect, szTempDir);
05800   AppendBackSlash(szFileIniRedirect, sizeof(szFileIniRedirect));
05801   lstrcat(szFileIniRedirect, FILE_INI_REDIRECT);
05802 
05803   if(FileExists(szFileIniRedirect) == FALSE)
05804     return;
05805 
05806   /* get all dependees for this component */
05807   dwIndex = 0;
05808   itoa(dwIndex, szIndex, 10);
05809   lstrcpy(szKDescription, "Description");
05810   lstrcpy(szKDomain,      "Domain");
05811   lstrcat(szKDescription, szIndex);
05812   lstrcat(szKDomain,      szIndex);
05813   GetPrivateProfileString("Site Selector", szKDescription, "", szDescription, sizeof(szDescription), szFileIniRedirect);
05814   while(*szDescription != '\0')
05815   {
05816     if(lstrcmpi(szDescription, szSiteSelectorDescription) == 0)
05817     {
05818       GetPrivateProfileString("Site Selector", szKDomain, "", szDomain, sizeof(szDomain), szFileIniRedirect);
05819       if(*szDomain != '\0')
05820       {
05821         ssiSiteSelectorTemp = SsiGetNode(szDescription);
05822         if(ssiSiteSelectorTemp != NULL)
05823         {
05824           lstrcpy(ssiSiteSelectorTemp->szDomain, szDomain);
05825         }
05826         else
05827         {
05828           /* no match found for the given domain description, so assume there's nothing
05829            * to change. just return. */
05830           return;
05831         }
05832       }
05833       else
05834       {
05835         /* found matched description, but domain was not set, so assume there's no
05836          * redirect required, just return. */
05837         return;
05838       }
05839     }
05840 
05841     ++dwIndex;
05842     itoa(dwIndex, szIndex, 10);
05843     lstrcpy(szKDescription, "Description");
05844     lstrcpy(szKDomain,      "Domain");
05845     lstrcat(szKDescription, szIndex);
05846     lstrcat(szKDomain,      szIndex);
05847     ZeroMemory(szDescription, sizeof(szDescription));
05848     ZeroMemory(szDomain,      sizeof(szDomain));
05849     GetPrivateProfileString("Site Selector", szKDescription, "", szDescription, sizeof(szDescription), szFileIniRedirect);
05850   }
05851 }
05852 
05853 void InitSiteSelector()
05854 {
05855   DWORD dwIndex;
05856   char  szIndex[MAX_BUF];
05857   char  szKDescription[MAX_BUF];
05858   char  szDescription[MAX_BUF];
05859   char  szKDomain[MAX_BUF];
05860   char  szDomain[MAX_BUF];
05861   char  szKIdentifier[MAX_BUF];
05862   char  szIdentifier[MAX_BUF];
05863   ssi   *ssiSiteSelectorNewNode;
05864 
05865   ssiSiteSelector = NULL;
05866 
05867   /* get all dependees for this component */
05868   dwIndex = 0;
05869   itoa(dwIndex, szIndex, 10);
05870   lstrcpy(szKDescription, "Description");
05871   lstrcpy(szKDomain,      "Domain");
05872   lstrcpy(szKIdentifier,  "Identifier");
05873   lstrcat(szKDescription, szIndex);
05874   lstrcat(szKDomain,      szIndex);
05875   lstrcat(szKIdentifier,  szIndex);
05876   GetConfigIniProfileString("Site Selector", szKDescription, "", szDescription, sizeof(szDescription));
05877   while(*szDescription != '\0')
05878   {
05879     /* if the Domain and Identifier are not set, then skip */
05880     GetConfigIniProfileString("Site Selector", szKDomain,     "", szDomain,     sizeof(szDomain));
05881     GetConfigIniProfileString("Site Selector", szKIdentifier, "", szIdentifier, sizeof(szIdentifier));
05882     if((*szDomain != '\0') && (*szIdentifier != '\0'))
05883     {
05884       /* create and initialize empty node */
05885       ssiSiteSelectorNewNode = CreateSsiSiteSelectorNode();
05886 
05887       lstrcpy(ssiSiteSelectorNewNode->szDescription, szDescription);
05888       lstrcpy(ssiSiteSelectorNewNode->szDomain,      szDomain);
05889       lstrcpy(ssiSiteSelectorNewNode->szIdentifier,  szIdentifier);
05890 
05891       /* inserts the newly created node into the global node list */
05892       SsiSiteSelectorNodeInsert(&(ssiSiteSelector), ssiSiteSelectorNewNode);
05893     }
05894 
05895     ProcessWindowsMessages();
05896     ++dwIndex;
05897     itoa(dwIndex, szIndex, 10);
05898     lstrcpy(szKDescription, "Description");
05899     lstrcpy(szKDomain,      "Domain");
05900     lstrcpy(szKIdentifier,  "Identifier");
05901     lstrcat(szKDescription, szIndex);
05902     lstrcat(szKDomain,      szIndex);
05903     lstrcat(szKIdentifier,  szIndex);
05904     ZeroMemory(szDescription, sizeof(szDescription));
05905     ZeroMemory(szDomain,      sizeof(szDomain));
05906     ZeroMemory(szIdentifier,  sizeof(szIdentifier));
05907     GetConfigIniProfileString("Site Selector", szKDescription, "", szDescription, sizeof(szDescription));
05908   }
05909 }
05910 
05911 void InitErrorMessageStream()
05912 {
05913   char szBuf[MAX_BUF_TINY];
05914 
05915   GetConfigIniProfileString("Message Stream", "Status", "",
05916                             szBuf, sizeof(szBuf));
05917 
05918   if(lstrcmpi(szBuf, "disabled") == 0)
05919     gErrorMessageStream.bEnabled = FALSE;
05920   else
05921     gErrorMessageStream.bEnabled = TRUE;
05922 
05923   GetConfigIniProfileString("Message Stream", "url", "",
05924                             gErrorMessageStream.szURL, sizeof(gErrorMessageStream.szURL));
05925 
05926   GetConfigIniProfileString("Message Stream", "Show Confirmation", "",
05927                             szBuf, sizeof(szBuf));
05928   if(strcmpi(szBuf, "FALSE") == 0)
05929     gErrorMessageStream.bShowConfirmation = FALSE;
05930   else
05931     gErrorMessageStream.bShowConfirmation = TRUE;
05932 
05933   GetConfigIniProfileString("Message Stream", "Confirmation Message", "",
05934                             gErrorMessageStream.szConfirmationMessage, sizeof(szBuf));
05935 
05936   gErrorMessageStream.bSendMessage = FALSE;
05937   gErrorMessageStream.dwMessageBufSize = MAX_BUF;
05938   gErrorMessageStream.szMessage = NS_GlobalAlloc(gErrorMessageStream.dwMessageBufSize);
05939 }
05940 
05941 void DeInitErrorMessageStream()
05942 {
05943   FreeMemory(&gErrorMessageStream.szMessage);
05944 }
05945 
05946 #ifdef SSU_DEBUG
05947 void ViewSiComponentsDependency(char *szBuffer, char *szIndentation, siC *siCNode)
05948 {
05949   siC  *siCNodeTemp;
05950   siCD *siCDependencyTemp;
05951 
05952   siCDependencyTemp = siCNode->siCDDependencies;
05953   if(siCDependencyTemp != NULL)
05954   {
05955     char  szIndentationPadding[MAX_BUF];
05956     DWORD dwIndex;
05957 
05958     lstrcpy(szIndentationPadding, szIndentation);
05959     lstrcat(szIndentationPadding, "    ");
05960 
05961     do
05962     {
05963       lstrcat(szBuffer, szIndentationPadding);
05964       lstrcat(szBuffer, siCDependencyTemp->szReferenceName);
05965       lstrcat(szBuffer, "::");
05966 
05967       if((dwIndex = SiCNodeGetIndexRN(siCDependencyTemp->szReferenceName)) != -1)
05968         lstrcat(szBuffer, SiCNodeGetDescriptionShort(dwIndex, TRUE, AC_ALL));
05969       else
05970         lstrcat(szBuffer, "Component does not exist");
05971 
05972       lstrcat(szBuffer, ":");
05973       lstrcat(szBuffer, "\n");
05974 
05975       if(dwIndex != -1)
05976       {
05977         if((siCNodeTemp = SiCNodeGetObject(dwIndex, TRUE, AC_ALL)) != NULL)
05978           ViewSiComponentsDependency(szBuffer, szIndentationPadding, siCNodeTemp);
05979         else
05980           lstrcat(szBuffer, "Node not found");
05981       }
05982 
05983       siCDependencyTemp = siCDependencyTemp->Next;
05984     }while((siCDependencyTemp != NULL) && (siCDependencyTemp != siCNode->siCDDependencies));
05985   }
05986 }
05987 
05988 void ViewSiComponentsDependee(char *szBuffer, char *szIndentation, siC *siCNode)
05989 {
05990   siC  *siCNodeTemp;
05991   siCD *siCDependeeTemp;
05992 
05993   siCDependeeTemp = siCNode->siCDDependees;
05994   if(siCDependeeTemp != NULL)
05995   {
05996     char  szIndentationPadding[MAX_BUF];
05997     DWORD dwIndex;
05998 
05999     lstrcpy(szIndentationPadding, szIndentation);
06000     lstrcat(szIndentationPadding, "    ");
06001 
06002     do
06003     {
06004       lstrcat(szBuffer, szIndentationPadding);
06005       lstrcat(szBuffer, siCDependeeTemp->szReferenceName);
06006       lstrcat(szBuffer, "::");
06007 
06008       if((dwIndex = SiCNodeGetIndexRN(siCDependeeTemp->szReferenceName)) != -1)
06009         lstrcat(szBuffer, SiCNodeGetDescriptionShort(dwIndex, TRUE, AC_ALL));
06010       else
06011         lstrcat(szBuffer, "Component does not exist");
06012 
06013       lstrcat(szBuffer, ":");
06014       lstrcat(szBuffer, "\n");
06015 
06016       if(dwIndex != -1)
06017       {
06018         if((siCNodeTemp = SiCNodeGetObject(dwIndex, TRUE, AC_ALL)) != NULL)
06019           ViewSiComponentsDependency(szBuffer, szIndentationPadding, siCNodeTemp);
06020         else
06021           lstrcat(szBuffer, "Node not found");
06022       }
06023 
06024       siCDependeeTemp = siCDependeeTemp->Next;
06025     }while((siCDependeeTemp != NULL) && (siCDependeeTemp != siCNode->siCDDependees));
06026   }
06027 }
06028 
06029 void ViewSiComponents()
06030 {
06031   char  szBuf[MAX_BUF];
06032   siC   *siCTemp = siComponents;
06033 
06034   // build dependency list
06035   ZeroMemory(szBuf, sizeof(szBuf));
06036   lstrcpy(szBuf, "Dependency:\n");
06037 
06038   do
06039   {
06040     if(siCTemp == NULL)
06041       break;
06042 
06043     lstrcat(szBuf, "    ");
06044     lstrcat(szBuf, siCTemp->szReferenceName);
06045     lstrcat(szBuf, "::");
06046     lstrcat(szBuf, siCTemp->szDescriptionShort);
06047     lstrcat(szBuf, ":\n");
06048 
06049     ViewSiComponentsDependency(szBuf, "    ", siCTemp);
06050 
06051     siCTemp = siCTemp->Next;
06052   } while((siCTemp != NULL) && (siCTemp != siComponents));
06053 
06054   MessageBox(hWndMain, szBuf, NULL, MB_ICONEXCLAMATION);
06055 
06056   // build dependee list
06057   ZeroMemory(szBuf, sizeof(szBuf));
06058   lstrcpy(szBuf, "Dependee:\n");
06059 
06060   do
06061   {
06062     if(siCTemp == NULL)
06063       break;
06064 
06065     lstrcat(szBuf, "    ");
06066     lstrcat(szBuf, siCTemp->szReferenceName);
06067     lstrcat(szBuf, "::");
06068     lstrcat(szBuf, siCTemp->szDescriptionShort);
06069     lstrcat(szBuf, ":\n");
06070 
06071     ViewSiComponentsDependee(szBuf, "    ", siCTemp);
06072 
06073     siCTemp = siCTemp->Next;
06074   } while((siCTemp != NULL) && (siCTemp != siComponents));
06075 
06076   MessageBox(hWndMain, szBuf, NULL, MB_ICONEXCLAMATION);
06077 }
06078 #endif /* SSU_DEBUG */
06079 
06080 void DeInitSiCDependencies(siCD *siCDDependencies)
06081 {
06082   siCD   *siCDepTemp;
06083   
06084   if(siCDDependencies == NULL)
06085   {
06086     return;
06087   }
06088   else if((siCDDependencies->Prev == NULL) || (siCDDependencies->Prev == siCDDependencies))
06089   {
06090     SiCDepNodeDelete(siCDDependencies);
06091     return;
06092   }
06093   else
06094   {
06095     siCDepTemp = siCDDependencies->Prev;
06096   }
06097 
06098   while(siCDepTemp != siCDDependencies)
06099   {
06100     SiCDepNodeDelete(siCDepTemp);
06101     siCDepTemp = siCDDependencies->Prev;
06102   }
06103   SiCDepNodeDelete(siCDepTemp);
06104 }
06105 
06106 void DeInitSiComponents(siC **siCHeadNode)
06107 {
06108   siC   *siCTemp;
06109   
06110   if((*siCHeadNode) == NULL)
06111   {
06112     return;
06113   }
06114   else if(((*siCHeadNode)->Prev == NULL) || ((*siCHeadNode)->Prev == (*siCHeadNode)))
06115   {
06116     SiCNodeDelete((*siCHeadNode));
06117     return;
06118   }
06119   else
06120   {
06121     siCTemp = (*siCHeadNode)->Prev;
06122   }
06123 
06124   while(siCTemp != (*siCHeadNode))
06125   {
06126     SiCNodeDelete(siCTemp);
06127     siCTemp = (*siCHeadNode)->Prev;
06128   }
06129   SiCNodeDelete(siCTemp);
06130 }
06131 
06132 void DeInitDSNode(dsN **dsnComponentDSRequirement)
06133 {
06134   dsN *dsNTemp;
06135   
06136   if(*dsnComponentDSRequirement == NULL)
06137   {
06138     return;
06139   }
06140   else if(((*dsnComponentDSRequirement)->Prev == NULL) || ((*dsnComponentDSRequirement)->Prev == *dsnComponentDSRequirement))
06141   {
06142     DsNodeDelete(dsnComponentDSRequirement);
06143     return;
06144   }
06145   else
06146   {
06147     dsNTemp = (*dsnComponentDSRequirement)->Prev;
06148   }
06149 
06150   while(dsNTemp != *dsnComponentDSRequirement)
06151   {
06152     DsNodeDelete(&dsNTemp);
06153     dsNTemp = (*dsnComponentDSRequirement)->Prev;
06154   }
06155   DsNodeDelete(dsnComponentDSRequirement);
06156 }
06157 
06158 BOOL ResolveComponentDependency(siCD *siCDInDependency, HWND hwndListBox)
06159 {
06160   int     dwIndex;
06161   siCD    *siCDepTemp = siCDInDependency;
06162   BOOL    bMoreToResolve = FALSE;
06163   DWORD   dwAttrib;
06164 
06165   if(siCDepTemp != NULL)
06166   {
06167     if((dwIndex = SiCNodeGetIndexRN(siCDepTemp->szReferenceName)) != -1)
06168     {
06169       dwAttrib = SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL);
06170       if(!(dwAttrib & SIC_SELECTED) && !(dwAttrib & SIC_DISABLED))
06171       {
06172         bMoreToResolve = TRUE;
06173         SiCNodeSetAttributes(dwIndex, SIC_SELECTED, TRUE, TRUE, AC_ALL, hwndListBox);
06174       }
06175     }
06176 
06177     siCDepTemp = siCDepTemp->Next;
06178     while((siCDepTemp != NULL) && (siCDepTemp != siCDInDependency))
06179     {
06180       if((dwIndex = SiCNodeGetIndexRN(siCDepTemp->szReferenceName)) != -1)
06181       {
06182         dwAttrib = SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL);
06183         if(!(dwAttrib & SIC_SELECTED) && !(dwAttrib & SIC_DISABLED))
06184         {
06185           bMoreToResolve = TRUE;
06186           SiCNodeSetAttributes(dwIndex, SIC_SELECTED, TRUE, TRUE, AC_ALL, hwndListBox);
06187         }
06188       }
06189 
06190       siCDepTemp = siCDepTemp->Next;
06191     }
06192   }
06193   return(bMoreToResolve);
06194 }
06195 
06196 BOOL ResolveDependencies(DWORD dwIndex, HWND hwndListBox)
06197 {
06198   BOOL  bMoreToResolve  = FALSE;
06199   DWORD dwCount         = 0;
06200   siC   *siCTemp        = siComponents;
06201 
06202   if(siCTemp != NULL)
06203   {
06204     /* can resolve specific component or all components (-1) */
06205     if((dwIndex == dwCount) || (dwIndex == -1))
06206     {
06207       if(SiCNodeGetAttributes(dwCount, TRUE, AC_ALL) & SIC_SELECTED)
06208       {
06209          bMoreToResolve = ResolveComponentDependency(siCTemp->siCDDependencies, hwndListBox);
06210          if(dwIndex == dwCount)
06211          {
06212            return(bMoreToResolve);
06213          }
06214       }
06215     }
06216 
06217     ++dwCount;
06218     siCTemp = siCTemp->Next;
06219     while((siCTemp != NULL) && (siCTemp != siComponents))
06220     {
06221       /* can resolve specific component or all components (-1) */
06222       if((dwIndex == dwCount) || (dwIndex == -1))
06223       {
06224         if(SiCNodeGetAttributes(dwCount, TRUE, AC_ALL) & SIC_SELECTED)
06225         {
06226            bMoreToResolve = ResolveComponentDependency(siCTemp->siCDDependencies, hwndListBox);
06227            if(dwIndex == dwCount)
06228            {
06229              return(bMoreToResolve);
06230            }
06231         }
06232       }
06233 
06234       ++dwCount;
06235       siCTemp = siCTemp->Next;
06236     }
06237   }
06238   return(bMoreToResolve);
06239 }
06240 
06241 BOOL ResolveComponentDependee(siCD *siCDInDependee)
06242 {
06243   int     dwIndex;
06244   siCD    *siCDDependeeTemp   = siCDInDependee;
06245   BOOL    bAtLeastOneSelected = FALSE;
06246 
06247   if(siCDDependeeTemp != NULL)
06248   {
06249     if((dwIndex = SiCNodeGetIndexRN(siCDDependeeTemp->szReferenceName)) != -1)
06250     {
06251       if((SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL) & SIC_SELECTED) == TRUE)
06252       {
06253         bAtLeastOneSelected = TRUE;
06254       }
06255     }
06256 
06257     siCDDependeeTemp = siCDDependeeTemp->Next;
06258     while((siCDDependeeTemp != NULL) && (siCDDependeeTemp != siCDInDependee))
06259     {
06260       if((dwIndex = SiCNodeGetIndexRN(siCDDependeeTemp->szReferenceName)) != -1)
06261       {
06262         if((SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL) & SIC_SELECTED) == TRUE)
06263         {
06264           bAtLeastOneSelected = TRUE;
06265         }
06266       }
06267 
06268       siCDDependeeTemp = siCDDependeeTemp->Next;
06269     }
06270   }
06271   return(bAtLeastOneSelected);
06272 }
06273 
06274 ssi* SsiGetNode(LPSTR szDescription)
06275 {
06276   ssi *ssiSiteSelectorTemp = ssiSiteSelector;
06277 
06278   do
06279   {
06280     if(ssiSiteSelectorTemp == NULL)
06281       break;
06282 
06283     if(lstrcmpi(ssiSiteSelectorTemp->szDescription, szDescription) == 0)
06284       return(ssiSiteSelectorTemp);
06285 
06286     ssiSiteSelectorTemp = ssiSiteSelectorTemp->Next;
06287   } while((ssiSiteSelectorTemp != NULL) && (ssiSiteSelectorTemp != ssiSiteSelector));
06288 
06289   return(NULL);
06290 }
06291 
06292 void ResolveDependees(LPSTR szToggledReferenceName, HWND hwndListBox)
06293 {
06294   BOOL  bAtLeastOneSelected;
06295   BOOL  bMoreToResolve  = FALSE;
06296   siC   *siCTemp        = siComponents;
06297   DWORD dwIndex;
06298   DWORD dwAttrib;
06299 
06300   do
06301   {
06302     if(siCTemp == NULL)
06303       break;
06304 
06305     if((siCTemp->siCDDependees != NULL) &&
06306        (lstrcmpi(siCTemp->szReferenceName, szToggledReferenceName) != 0))
06307     {
06308       bAtLeastOneSelected = ResolveComponentDependee(siCTemp->siCDDependees);
06309       if(bAtLeastOneSelected == FALSE)
06310       {
06311         if((dwIndex = SiCNodeGetIndexRN(siCTemp->szReferenceName)) != -1)
06312         {
06313           dwAttrib = SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL);
06314           if((dwAttrib & SIC_SELECTED) && !(dwAttrib & SIC_DISABLED))
06315           {
06316             SiCNodeSetAttributes(dwIndex, SIC_SELECTED, FALSE, TRUE, AC_ALL, hwndListBox);
06317             bMoreToResolve = TRUE;
06318           }
06319         }
06320       }
06321       else
06322       {
06323         if((dwIndex = SiCNodeGetIndexRN(siCTemp->szReferenceName)) != -1)
06324         {
06325           dwAttrib = SiCNodeGetAttributes(dwIndex, TRUE, AC_ALL);
06326           if(!(dwAttrib & SIC_SELECTED) && !(dwAttrib & SIC_DISABLED))
06327           {
06328             SiCNodeSetAttributes(dwIndex, SIC_SELECTED, TRUE, TRUE, AC_ALL, hwndListBox);
06329             bMoreToResolve = TRUE;
06330           }
06331         }
06332       }
06333     }
06334 
06335     siCTemp = siCTemp->Next;
06336   } while((siCTemp != NULL) && (siCTemp != siComponents));
06337 
06338   if(bMoreToResolve == TRUE)
06339     ResolveDependees(szToggledReferenceName, hwndListBox);
06340 }
06341 
06342 /* Function: ReplacePrivateProfileStrCR()
06343  *
06344  *       in: LPSTR aInputOutputStr: In/out string to containing "\\n" to replace.
06345  *           
06346  *  purpose: To parse for and replace "\\n" string with "\n".  Strings stored
06347  *           in .ini files cannot contain "\n" because it's a key delimiter.
06348  *           To work around this limination, "\\n" chars can be used to
06349  *           represent '\n'.  This function will look for "\\n" and replace
06350  *           them with a true "\n".
06351  *           If it encounters a string of "\\\\n" (which looks like '\\n'),
06352  *           then this function will strip out the extra '\\' and just show
06353  *           "\\n";
06354  */
06355 void ReplacePrivateProfileStrCR(LPSTR aInputOutputStr)
06356 {
06357   LPSTR pSearch          = aInputOutputStr;
06358   LPSTR pSearchEnd       = aInputOutputStr + lstrlen(aInputOutputStr);
06359   LPSTR pPreviousSearch  = NULL;
06360 
06361   while (pSearch < pSearchEnd)
06362   {
06363     if (('\\' == *pSearch) || ('n' == *pSearch))
06364     {
06365       // found a '\\' or 'n'.  check to see if  the prefivous char is also a '\\'.
06366       if (pPreviousSearch && ('\\' == *pPreviousSearch))
06367       {
06368         if ('n' == *pSearch)
06369           *pSearch = '\n';
06370 
06371         memmove(pPreviousSearch, pSearch, pSearchEnd-pSearch+1);
06372 
06373         // our string is shorter now ...
06374         pSearchEnd -= pSearch - pPreviousSearch;
06375       }
06376     }
06377 
06378     pPreviousSearch = pSearch;
06379     pSearch = CharNext(pSearch);
06380   }
06381 }
06382 
06383 void PrintUsage(void)
06384 {
06385   char szBuf[MAX_BUF];
06386   char szUsageMsg[MAX_BUF];
06387   char szProcessFilename[MAX_BUF];
06388 
06389   /* -h: this help
06390    * -a [path]: Alternate archive search path
06391    * -app: ID of application which is launching the installer  (Shared installs)
06392    * -app_path: Points to representative file of app (Shared installs)
06393    * -dd [path]: Suggested install destination directory. (Shared installs)
06394    * -greLocal: Forces GRE to be installed into the application dir.
06395    * -greShared: Forces GRE to be installed into a global, shared dir (normally
06396    *    c:\program files\common files\mozilla.org\GRE
06397    * -reg_path [path]: Where to make entries in the Windows registry. (Shared installs)
06398    * -f: Force install of GRE installer (Shared installs), though it'll work
06399    *    for non GRE installers too.
06400    * -greForce: Force 'Component GRE' to be downloaded, run, and installed.  This
06401    *    bypasses GRE's logic of determining when to install by running its
06402    *    installer with a '-f' flag.
06403    * -n [filename]: setup's parent's process filename
06404    * -ma: run setup in Auto mode
06405    * -mmi: Allow multiple installer instances. (Shared installs)
06406    * -showBanner: Show the banner in the download and install process dialogs.
06407    *              This will override config.ini
06408    * -hideBanner: Hides the banner in the download and install process dialogs.
06409    *              This will override config.ini
06410    * -ms: run setup in Silent mode
06411    * -ira: ignore the [RunAppX] sections
06412    * -ispf: ignore the [Program FolderX] sections that show
06413    *        the Start Menu shortcut folder at the end of installation.
06414    */
06415 
06416   if(sgProduct.szParentProcessFilename && *sgProduct.szParentProcessFilename != '\0')
06417     ParsePath(sgProduct.szParentProcessFilename, szProcessFilename, sizeof(szProcessFilename), FALSE, PP_FILENAME_ONLY);
06418   else
06419   {
06420     GetModuleFileName(NULL, szBuf, sizeof(szBuf));
06421     ParsePath(szBuf, szProcessFilename, sizeof(szProcessFilename), FALSE, PP_FILENAME_ONLY);
06422   }
06423 
06424   GetConfigIniProfileString("Strings", "UsageMsg Usage", "", szBuf, sizeof(szBuf));
06425   if (lstrlen(szBuf) > 0)
06426   {
06427     char strUsage[MAX_BUF];
06428 
06429     ReplacePrivateProfileStrCR(szBuf);
06430     _snprintf(szUsageMsg, sizeof(szUsageMsg), szBuf, szProcessFilename);
06431     szUsageMsg[sizeof(szUsageMsg) - 1] = '\0';
06432     GetPrivateProfileString("Messages", "DLG_USAGE_TITLE", "", strUsage, sizeof(strUsage), szFileIniInstall);
06433     MessageBox(hWndMain, szUsageMsg, strUsage, MB_ICONEXCLAMATION);
06434   }
06435 }
06436 
06437 /* Function: ParseForStartupOptions()
06438  *       in: aCmdLine
06439  *  purpose: Parses for options that affect the initialization of setup.exe,
06440  *           such as -ms, -ma, -mmi.
06441  *           This is required to be parsed this early because setup needs to
06442  *           know if dialogs need to be shown (-ms, -ma) and also where to
06443  *           create the temp directory for temporary items to be placed at
06444  *           (-mmi).
06445  */
06446 DWORD ParseForStartupOptions(LPSTR aCmdLine)
06447 {
06448   char  szArgVBuf[MAX_BUF];
06449   int   i;
06450   int   iArgC;
06451 
06452 #ifdef XXX_DEBUG
06453   char  szBuf[MAX_BUF];
06454   char  szOutputStr[MAX_BUF];
06455 #endif
06456 
06457   iArgC = GetArgC(aCmdLine);
06458 
06459 #ifdef XXX_DEBUG
06460   wsprintf(szOutputStr, "ArgC: %d\n", iArgC);
06461 #endif
06462 
06463   i = 0;
06464   while(i < iArgC)
06465   {
06466     GetArgV(aCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06467 
06468     if(!lstrcmpi(szArgVBuf, "-mmi") || !lstrcmpi(szArgVBuf, "/mmi"))
06469     {
06470       gbAllowMultipleInstalls = TRUE;    
06471     }
06472     else if(!lstrcmpi(szArgVBuf, "-ma") || !lstrcmpi(szArgVBuf, "/ma"))
06473       SetSetupRunMode("AUTO");
06474     else if(!lstrcmpi(szArgVBuf, "-ms") || !lstrcmpi(szArgVBuf, "/ms"))
06475       SetSetupRunMode("SILENT");
06476 
06477 #ifdef XXX_DEBUG
06478     itoa(i, szBuf, 10);
06479     lstrcat(szOutputStr, "    ");
06480     lstrcat(szOutputStr, szBuf);
06481     lstrcat(szOutputStr, ": ");
06482     lstrcat(szOutputStr, szArgVBuf);
06483     lstrcat(szOutputStr, "\n");
06484 #endif
06485 
06486     ++i;
06487   }
06488 
06489 #ifdef XXX_DEBUG
06490   MessageBox(NULL, szOutputStr, "Output", MB_OK);
06491 #endif
06492   return(WIZ_OK);
06493 }
06494 
06495 DWORD ParseCommandLine(LPSTR aMessageToClose, LPSTR lpszCmdLine)
06496 {
06497   char  szArgVBuf[MAX_BUF];
06498   int   i;
06499   int   iArgC;
06500 
06501 #ifdef XXX_DEBUG
06502   char  szBuf[MAX_BUF];
06503   char  szOutputStr[MAX_BUF];
06504 #endif
06505 
06506   iArgC = GetArgC(lpszCmdLine);
06507 
06508 #ifdef XXX_DEBUG
06509   wsprintf(szOutputStr, "ArgC: %d\n", iArgC);
06510 #endif
06511 
06512   i = 0;
06513   while(i < iArgC)
06514   {
06515     GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06516 
06517     if(!lstrcmpi(szArgVBuf, "-h") || !lstrcmpi(szArgVBuf, "/h"))
06518     {
06519       ShowMessage(aMessageToClose, FALSE);
06520       PrintUsage();
06521       return(WIZ_ERROR_UNDEFINED);
06522     }
06523     else if(!lstrcmpi(szArgVBuf, "-a") || !lstrcmpi(szArgVBuf, "/a"))
06524     {
06525       ++i;
06526       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06527       lstrcpy(sgProduct.szAlternateArchiveSearchPath, szArgVBuf);
06528     }
06529     else if(!lstrcmpi(szArgVBuf, "-greForce") || !lstrcmpi(szArgVBuf, "/greForce"))
06530     {
06531       gbForceInstallGre = TRUE;
06532     }
06533     else if(!lstrcmpi(szArgVBuf, "-greLocal") || !lstrcmpi(szArgVBuf, "/greLocal"))
06534     {
06535       sgProduct.greType = GRE_LOCAL;
06536     }
06537     else if(!lstrcmpi(szArgVBuf, "-greShared") || !lstrcmpi(szArgVBuf, "/greShared"))
06538     {
06539       sgProduct.greType = GRE_SHARED;
06540     }
06541     else if(!lstrcmpi(szArgVBuf, "-f") || !lstrcmpi(szArgVBuf, "/f"))
06542     {
06543       gbForceInstall = TRUE;
06544     }
06545     else if(!lstrcmpi(szArgVBuf, "-n") || !lstrcmpi(szArgVBuf, "/n"))
06546     {
06547       ++i;
06548       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06549       lstrcpy(sgProduct.szParentProcessFilename, szArgVBuf);
06550     }
06551     else if(!lstrcmpi(szArgVBuf, "-ira") || !lstrcmpi(szArgVBuf, "/ira"))
06552       /* ignore [RunAppX] sections */
06553       gbIgnoreRunAppX = TRUE;
06554     else if(!lstrcmpi(szArgVBuf, "-ispf") || !lstrcmpi(szArgVBuf, "/ispf"))
06555       /* ignore [Program FolderX] sections */
06556       gbIgnoreProgramFolderX = TRUE;
06557     else if(!lstrcmpi(szArgVBuf, "-dd") || !lstrcmpi(szArgVBuf, "/dd"))
06558     {
06559       ++i;
06560       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06561       lstrcpy(sgProduct.szPath, szArgVBuf);
06562     }
06563     // identifies the app which is installing for shared installs
06564     else if(!lstrcmpi(szArgVBuf, "-app") || !lstrcmpi(szArgVBuf, "/app"))
06565     {
06566       ++i;
06567       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06568       lstrcpy(sgProduct.szAppID, szArgVBuf);
06569     }
06570     // points to a file belonging to the app which can be searched to determine
06571     //    if the app is installed
06572     else if(!lstrcmpi(szArgVBuf, "-app_path") || !lstrcmpi(szArgVBuf, "/app_path"))
06573     {
06574       ++i;
06575       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06576       lstrcpy(sgProduct.szAppPath, szArgVBuf);
06577     }
06578     // alternative path in Windows registry, for private sharable installations
06579     else if(!lstrcmpi(szArgVBuf, "-reg_path") || !lstrcmpi(szArgVBuf, "/reg_path"))
06580     {
06581       ++i;
06582       GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
06583       lstrcpy(sgProduct.szRegPath, szArgVBuf);
06584     }
06585     else if(!lstrcmpi(szArgVBuf, "-showBanner") || !lstrcmpi(szArgVBuf, "/showBanner"))
06586       gShowBannerImage = TRUE;
06587     else if(!lstrcmpi(szArgVBuf, "-hideBanner") || !lstrcmpi(szArgVBuf, "/hideBanner"))
06588       gShowBannerImage = FALSE;
06589     else if(!lstrcmpi(szArgVBuf, "-cleanupOnUpgrade") || !lstrcmpi(szArgVBuf, "/cleanupOnUpgrade"))
06590       sgProduct.checkCleanupOnUpgrade = TRUE;
06591     else if(!lstrcmpi(szArgVBuf, "-noCleanupOnUpgrade") || !lstrcmpi(szArgVBuf, "/noCleanupOnUpgrade"))
06592       sgProduct.checkCleanupOnUpgrade = FALSE;
06593     else if(!lstrcmpi(szArgVBuf, "-greCleanupOrphans") || !lstrcmpi(szArgVBuf, "/greCleanupOrphans"))
06594       sgProduct.greCleanupOrphans = TRUE;
06595     else if(!lstrcmpi(szArgVBuf, "-greNoCleanupOrphans") || !lstrcmpi(szArgVBuf, "/greNoCleanupOrphans"))
06596       sgProduct.greCleanupOrphans = FALSE;
06597 
06598 #ifdef XXX_DEBUG
06599     itoa(i, szBuf, 10);
06600     lstrcat(szOutputStr, "    ");
06601     lstrcat(szOutputStr, szBuf);
06602     lstrcat(szOutputStr, ": ");
06603     lstrcat(szOutputStr, szArgVBuf);
06604     lstrcat(szOutputStr, "\n");
06605 #endif
06606 
06607     ++i;
06608   }
06609 
06610 #ifdef XXX_DEBUG
06611   MessageBox(NULL, szOutputStr, "Output", MB_OK);
06612 #endif
06613   return(WIZ_OK);
06614 }
06615 
06616 void GetAlternateArchiveSearchPath(LPSTR lpszCmdLine)
06617 {
06618   char  szBuf[MAX_PATH];
06619   LPSTR lpszAASPath;
06620   LPSTR lpszEndPath;
06621   LPSTR lpszEndQuote;
06622 
06623   if(lstrcpy(szBuf, lpszCmdLine))
06624   {
06625     if((lpszAASPath = strstr(szBuf, "-a")) == NULL)
06626       return;
06627     else
06628       lpszAASPath += 2;
06629 
06630     if(*lpszAASPath == '\"')
06631     {
06632       lpszAASPath = lpszAASPath + 1;
06633       if((lpszEndQuote = strstr(lpszAASPath, "\"")) != NULL)
06634       {
06635         *lpszEndQuote = '\0';
06636       }
06637     }
06638     else if((lpszEndPath = strstr(lpszAASPath, " ")) != NULL)
06639     {
06640       *lpszEndPath = '\0';
06641     }
06642 
06643     lstrcpy(sgProduct.szAlternateArchiveSearchPath, lpszAASPath);
06644   }
06645 }
06646 
06647 int PreCheckInstance(char *szSection)
06648 {
06649   char  szBuf[MAX_BUF];
06650   char  szKey[MAX_BUF];
06651   char  szName[MAX_BUF];
06652   char  szParameter[MAX_BUF];
06653   char  szPath[MAX_BUF];
06654   char  szFile[MAX_BUF];
06655   char  *ptrName = NULL;
06656   HKEY  hkeyRoot;
06657   int   iRv = WIZ_OK;
06658   DWORD dwCounter = 0;
06659   BOOL  bContinue = TRUE;
06660   char  szExtraCmd[] = "Extra Cmd";
06661   char  szExtraCmdKey[MAX_BUF];
06662 
06663   do
06664   {
06665     /* Read the win reg key path */
06666     wsprintf(szExtraCmdKey, "%s%d Reg Key", szExtraCmd, dwCounter);
06667     GetConfigIniProfileString(szSection, szExtraCmdKey, "",
06668                               szKey, sizeof(szKey));
06669     if(*szKey == '\0')
06670     {
06671       bContinue = FALSE;
06672       continue;
06673     }
06674 
06675     /* Read the win reg root key */
06676     wsprintf(szExtraCmdKey, "%s%d Reg Key Root", szExtraCmd, dwCounter);
06677     GetConfigIniProfileString(szSection, szExtraCmdKey, "",
06678                               szBuf, sizeof(szBuf));
06679     if(*szBuf == '\0')
06680     {
06681       bContinue = FALSE;
06682       continue;
06683     }
06684     hkeyRoot = ParseRootKey(szBuf);
06685 
06686     /* Read the win reg name value */
06687     wsprintf(szExtraCmdKey, "%s%d Reg Name", szExtraCmd, dwCounter);
06688     GetConfigIniProfileString(szSection, szExtraCmdKey, "",
06689                               szName, sizeof(szName));
06690     if(*szName == '\0')
06691       ptrName = NULL;
06692     else
06693       ptrName = szName;
06694 
06695     /* Read the parameter to use for quitting the browser's turbo mode */
06696     wsprintf(szExtraCmdKey, "%s%d Parameter", szExtraCmd, dwCounter);
06697     GetConfigIniProfileString(szSection, szExtraCmdKey, "",
06698                               szParameter, sizeof(szParameter));
06699 
06700     /* Read the win reg key that contains the path to the browser */
06701     GetWinReg(hkeyRoot, szKey, ptrName, szFile, sizeof(szFile));
06702     ParsePath(szFile, szPath, sizeof(szPath), FALSE, PP_PATH_ONLY);
06703 
06704     /* Make sure the file exists */
06705     if(FileExists(szFile))
06706     {
06707       // we've found a file, so let's execute it and stop.  No need to look
06708       // for other keys to parse.  We only want to do that if the file is
06709       // _not_ found.  This is for when we change the name of the browser
06710       // app file and still need to deal with locating it and calling
06711       // -kill on it. ie.
06712       //   previous name: netscp6.exe
06713       //   new name: netscp.exe
06714       // We only need to call one of them, not both.
06715       bContinue = FALSE;
06716 
06717       /* Run the file */
06718       WinSpawn(szFile, szParameter, szPath, SW_HIDE, WS_WAIT);
06719 
06720       /* Even though WinSpawn is suppose to wait for the app to finish, this
06721        * does not really work that way for trying to quit the browser when
06722        * it's in turbo mode, so we wait 2 secs for it to complete. */
06723       Delay(2);
06724     }
06725 
06726     ++dwCounter;
06727   } while(bContinue);
06728 
06729   return(iRv);
06730 }
06731 
06732 HRESULT GetCheckInstanceQuitMessage(char *aSection, char *aMessage, DWORD aMessageBufSize)
06733 {
06734   char messageFullInstaller[MAX_BUF];
06735 
06736   *aMessage = '\0';
06737   *messageFullInstaller = '\0';
06738 
06739   GetConfigIniProfileString(aSection, "Message", "", aMessage, aMessageBufSize);
06740   GetConfigIniProfileString(aSection, "Message Full Installer", "", messageFullInstaller, sizeof(messageFullInstaller));
06741   if(!gbDownloadTriggered && !gbPreviousUnfinishedDownload && (*messageFullInstaller != '\0'))
06742     MozCopyStr(messageFullInstaller, aMessage, aMessageBufSize);
06743 
06744   return(WIZ_OK);
06745 }
06746 
06747 HRESULT ShowMessageAndQuitProcess(HWND aHwndFW, char *aMsgQuitProcess, char *aMsgWait, BOOL aCloseAllWindows, char *aProcessName, BOOL aForceQuit)
06748 {
06749   switch(sgProduct.mode)
06750   {
06751     case NORMAL:
06752     {
06753       char msgTitleStr[MAX_BUF];
06754       GetPrivateProfileString("Messages", "MB_ATTENTION_STR", "", msgTitleStr, sizeof(msgTitleStr), szFileIniInstall);
06755       MessageBox(hWndMain, aMsgQuitProcess, msgTitleStr, MB_ICONEXCLAMATION | MB_SETFOREGROUND);
06756       break;
06757     }
06758 
06759     case AUTO:
06760     {
06761       /* Setup mode is AUTO.  Show message, timeout, then auto close
06762        * all the windows associated with the process */
06763       ShowMessage(aMsgQuitProcess, TRUE);
06764       Delay(5);
06765       ShowMessage(aMsgQuitProcess, FALSE);
06766       break;
06767     }
06768 
06769     case SILENT:
06770       break;
06771   }
06772 
06773   if(aForceQuit)
06774   {
06775     assert(aProcessName);
06776     FindAndKillProcess(aProcessName, KP_KILL_PROCESS);
06777   }
06778   else
06779   {
06780     assert(aHwndFW);
06781     /* First try sending a WM_QUIT message to the window because this is the
06782      * preferred way to quit a process.  If it works, then we're good and
06783      * CloseAllWindowsOfWindowHandle() will have nothing to do.
06784      * If it doesn't work, then CloseAllWindowsOfWindowHandle will try to
06785      * quit the process. */
06786     SendMessageTimeout(aHwndFW, WM_QUIT, (WPARAM)1, (LPARAM)0, SMTO_NORMAL, WM_CLOSE_TIMEOUT_VALUE, NULL);
06787     if(aCloseAllWindows)
06788       CloseAllWindowsOfWindowHandle(aHwndFW, aMsgWait);
06789   }
06790   Delay(2);
06791   return(WIZ_OK);
06792 }
06793 
06794 HRESULT CheckInstances()
06795 {
06796   char  section[MAX_BUF];
06797   char  processName[MAX_BUF];
06798   char  className[MAX_BUF];
06799   char  windowName[MAX_BUF];
06800   char  closeAllWindows[MAX_BUF];
06801   char  message[MAX_BUF];
06802   char  msgTitleStr[MAX_BUF];
06803   char  prettyName[MAX_BUF];
06804   char  buf[MAX_BUF];
06805   char  msgWait[MAX_BUF];
06806   int   index;
06807   int   killProcessTries = 0;
06808   int   instanceOfFoundProcess = 0;
06809   BOOL  bContinue;
06810   BOOL  bCloseAllWindows;
06811   HWND  hwndFW;
06812   LPSTR szWN;
06813   LPSTR szCN;
06814   DWORD dwRv0;
06815   DWORD dwRv1;
06816 
06817   GetPrivateProfileString("Messages", "MB_ATTENTION_STR", "", msgTitleStr, sizeof(msgTitleStr), szFileIniInstall);
06818   bContinue = TRUE;
06819   index    = -1;
06820   while(bContinue)
06821   {
06822     *className  = '\0';
06823     *windowName = '\0';
06824     *message    = '\0';
06825 
06826     wsprintf(section, "Check Instance%d", ++index);
06827     GetConfigIniProfileString(section, "Process Name", "", processName, sizeof(processName));
06828     GetConfigIniProfileString(section, "Pretty Name", "", prettyName, sizeof(prettyName));
06829     GetConfigIniProfileString(section, "Message Wait", "", msgWait, sizeof(msgWait));
06830     GetConfigIniProfileString(section, "Close All Process Windows", "", closeAllWindows, sizeof(closeAllWindows));
06831     if(lstrcmpi(closeAllWindows, "TRUE") == 0)
06832       bCloseAllWindows = TRUE;
06833     else
06834       bCloseAllWindows = FALSE;
06835 
06836     if(instanceOfFoundProcess != index)
06837     {
06838       killProcessTries = 0;
06839       instanceOfFoundProcess = index;
06840     }
06841 
06842     if((killProcessTries == 1) && (*processName != '\0'))
06843     {
06844       if(FindAndKillProcess(processName, KP_DO_NOT_KILL_PROCESS))
06845       {
06846         /* found process, display warning message, then kill process */
06847         GetPrivateProfileString("Messages", "MSG_FORCE_QUIT_PROCESS", "", message, sizeof(message), szFileIniInstall);
06848         if(*message != '\0')
06849         {
06850           wsprintf(buf, message, prettyName, processName, prettyName, prettyName);
06851           ShowMessageAndQuitProcess(NULL, buf, msgWait, bCloseAllWindows, processName, CI_FORCE_QUIT_PROCESS);
06852           ++killProcessTries;
06853           instanceOfFoundProcess = index--;
06854         }
06855       }
06856       continue;
06857     }
06858     else if(killProcessTries == MAX_KILL_PROCESS_RETRIES)
06859     {
06860       GetPrivateProfileString("Messages", "MSG_FORCE_QUIT_PROCESS_FAILED", "", message, sizeof(message), szFileIniInstall);
06861       if(*message != '\0')
06862       {
06863         wsprintf(buf, message, prettyName, processName, prettyName);
06864         switch(sgProduct.mode)
06865         {
06866           case NORMAL:
06867             MessageBox(hWndMain, buf, msgTitleStr, MB_ICONEXCLAMATION | MB_SETFOREGROUND);
06868             break;
06869 
06870           case AUTO:
06871             /* Setup mode is AUTO.  Show message, timeout, then auto close
06872              * all the windows associated with the process */
06873             ShowMessage(buf, TRUE);
06874             Delay(5);
06875             ShowMessage(buf, FALSE);
06876             break;
06877 
06878           default:
06879             break;
06880         }
06881       }
06882 
06883       /* can't kill the process for some unknown reason.  Stop the installation. */
06884       return(TRUE);
06885     }
06886     else if((killProcessTries > 1) &&
06887             (killProcessTries < MAX_KILL_PROCESS_RETRIES) &&
06888             (*processName != '\0'))
06889     {
06890       if(FindAndKillProcess(processName, KP_KILL_PROCESS))
06891       {
06892         ++killProcessTries;
06893         instanceOfFoundProcess = index--;
06894       }
06895       continue;
06896     }
06897 
06898     dwRv0 = GetConfigIniProfileString(section, "Class Name",  "", className,  sizeof(className));
06899     dwRv1 = GetConfigIniProfileString(section, "Window Name", "", windowName, sizeof(windowName));
06900     if((dwRv0 == 0L) && (dwRv1 == 0L) && (*processName == '\0'))
06901     {
06902       bContinue = FALSE;
06903     }
06904     else if((*className != '\0') || (*windowName != '\0'))
06905     {
06906       if(*className == '\0')
06907         szCN = NULL;
06908       else
06909         szCN = className;
06910 
06911       if(*windowName == '\0')
06912         szWN = NULL;
06913       else
06914         szWN = windowName;
06915 
06916       /* If an instance is found, call PreCheckInstance first.
06917        * PreCheckInstance will try to disable the browser's
06918        * QuickLaunch feature. If the browser was in QuickLaunch
06919        * mode without any windows open, PreCheckInstance would
06920        * shutdown the browser, thus a second call to FindAndKillProcess
06921        * is required to see if the process is still around. */
06922       if((hwndFW = FindWindow(szCN, szWN)) != NULL)
06923         PreCheckInstance(section);
06924 
06925       if((hwndFW = FindWindow(szCN, szWN)) != NULL)
06926       {
06927         GetCheckInstanceQuitMessage(section, message, sizeof(message));
06928         if(*message != '\0')
06929         {
06930           ShowMessageAndQuitProcess(hwndFW, message, msgWait, bCloseAllWindows, processName, CI_CLOSE_PROCESS);
06931           ++killProcessTries;
06932           instanceOfFoundProcess = index--;
06933         }
06934         else
06935         {
06936           /* No message to display.  Assume cancel because we can't allow user to continue */
06937           return(TRUE);
06938         }
06939       }
06940     }
06941 
06942     if((killProcessTries == 0) && (*processName != '\0'))
06943     {
06944       /* The first attempt used FindWindow(), but sometimes the browser can be
06945        * in a state where there's no window open and still not fully shutdown.
06946        * In this case, we need to check for the process itself and kill it. */
06947       if(FindAndKillProcess(processName, KP_DO_NOT_KILL_PROCESS))
06948       {
06949         GetCheckInstanceQuitMessage(section, message, sizeof(message));
06950         if(*message != '\0')
06951         {
06952           ShowMessageAndQuitProcess(hwndFW, message, msgWait, bCloseAllWindows, processName, CI_FORCE_QUIT_PROCESS);
06953           ++killProcessTries;
06954           instanceOfFoundProcess = index--;
06955         }
06956         else
06957         {
06958           /* No message to display.  Assume cancel because we can't allow user to continue */
06959           return(TRUE);
06960         }
06961       }
06962     }
06963   }
06964 
06965   return(FALSE);
06966 }
06967 
06968 void RefreshIcons()
06969 {
06970   char subKey[MAX_BUF];
06971   char iconConstraint[MAX_BUF];
06972   BYTE iconConstraintNew[MAX_BUF];
06973   HKEY hkResult;
06974   DWORD dwValueType;
06975   long iconConstraintSize;
06976   long rv;
06977 
06978   // Get the size of the icon from the windows registry.
06979   // When this registry value is changed, the OS can flush the
06980   // icon cache and thus update the icons.
06981   iconConstraintSize = sizeof(iconConstraint);
06982   strcpy(subKey, "Control Panel\\Desktop\\WindowMetrics");
06983   RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_ALL_ACCESS, &hkResult);
06984   rv = RegQueryValueEx(hkResult, "Shell Icon Size", 0, &dwValueType, iconConstraint, &iconConstraintSize);
06985   if(rv != ERROR_SUCCESS || iconConstraintSize == 0)
06986   {
06987     // Key not found or value not found, so use default OS value.
06988     int iIconSize = GetSystemMetrics(SM_CXICON);
06989     if(iIconSize == 0)
06990       // Getting default OS value failed, use hard coded value
06991       iIconSize = DEFAULT_ICON_SIZE;
06992 
06993     sprintf(iconConstraint, "%d", iIconSize);
06994   }
06995 
06996   // decrease the size of the icon by 1
06997   // and tell the system to refresh the icons
06998   sprintf(iconConstraintNew, "%d", atoi(iconConstraint) - 1);
06999   iconConstraintSize = lstrlen(iconConstraintNew);
07000   RegSetValueEx(hkResult, "Shell Icon Size", 0, dwValueType, iconConstraintNew, iconConstraintSize);
07001   SendMessageTimeout(HWND_BROADCAST,
07002                      WM_SETTINGCHANGE,
07003                      SPI_SETNONCLIENTMETRICS,
07004                      (LPARAM)"WindowMetrics",
07005                      SMTO_NORMAL|SMTO_ABORTIFHUNG, 
07006                      10000, NULL); 
07007 
07008   // reset the original size of the icon
07009   // and tell the system to refresh the icons
07010   iconConstraintSize = lstrlen(iconConstraint);
07011   RegSetValueEx(hkResult, "Shell Icon Size", 0, dwValueType, iconConstraint, iconConstraintSize);
07012   SendMessageTimeout(HWND_BROADCAST,
07013                      WM_SETTINGCHANGE,
07014                      SPI_SETNONCLIENTMETRICS,
07015                      (LPARAM)"WindowMetrics",
07016                      SMTO_NORMAL|SMTO_ABORTIFHUNG, 
07017                      10000, NULL); 
07018 }
07019 
07020 int CRCCheckArchivesStartup(char *szCorruptedArchiveList, DWORD dwCorruptedArchiveListSize, BOOL bIncludeTempPath)
07021 {
07022   DWORD dwIndex0;
07023   DWORD dwFileCounter;
07024   siC   *siCObject = NULL;
07025   char  szArchivePathWithFilename[MAX_BUF];
07026   char  szArchivePath[MAX_BUF];
07027   char  szMsgCRCCheck[MAX_BUF];
07028   char  szPartiallyDownloadedFilename[MAX_BUF];
07029   int   iRv;
07030   int   iResult;
07031 
07032   if(szCorruptedArchiveList != NULL)
07033     ZeroMemory(szCorruptedArchiveList, dwCorruptedArchiveListSize);
07034 
07035   GetSetupCurrentDownloadFile(szPartiallyDownloadedFilename,
07036                               sizeof(szPartiallyDownloadedFilename));
07037   GetConfigIniProfileString("Strings", "Message Verifying Archives", "", szMsgCRCCheck, sizeof(szMsgCRCCheck));
07038   ShowMessage(szMsgCRCCheck, TRUE);
07039   
07040   iResult           = WIZ_CRC_PASS;
07041   dwIndex0          = 0;
07042   dwFileCounter     = 0;
07043   siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
07044   while(siCObject)
07045   {
07046     /* only download jars if not already in the local machine */
07047     iRv = LocateJar(siCObject, szArchivePath, sizeof(szArchivePath), bIncludeTempPath);
07048     if((iRv != AP_NOT_FOUND) &&
07049        (lstrcmpi(szPartiallyDownloadedFilename,
07050                  siCObject->szArchiveName) != 0))
07051     {
07052       if(lstrlen(szArchivePath) < sizeof(szArchivePathWithFilename))
07053         lstrcpy(szArchivePathWithFilename, szArchivePath);
07054 
07055       AppendBackSlash(szArchivePathWithFilename, sizeof(szArchivePathWithFilename));
07056       if((lstrlen(szArchivePathWithFilename) + lstrlen(siCObject->szArchiveName)) < sizeof(szArchivePathWithFilename))
07057         lstrcat(szArchivePathWithFilename, siCObject->szArchiveName);
07058 
07059       if(CheckForArchiveExtension(szArchivePathWithFilename))
07060       {
07061         /* Make sure that the Archive that failed is located in the TEMP
07062          * folder.  This means that it was downloaded at one point and not
07063          * simply uncompressed from the self-extracting exe file. */
07064         if(VerifyArchive(szArchivePathWithFilename) != ZIP_OK)
07065         {
07066           if(iRv == AP_TEMP_PATH)
07067             DeleteFile(szArchivePathWithFilename);
07068           else if(szCorruptedArchiveList != NULL)
07069           {
07070             iResult = WIZ_CRC_FAIL;
07071             if((DWORD)(lstrlen(szCorruptedArchiveList) + lstrlen(siCObject->szArchiveName + 1)) < dwCorruptedArchiveListSize)
07072             {
07073               lstrcat(szCorruptedArchiveList, "        ");
07074               lstrcat(szCorruptedArchiveList, siCObject->szArchiveName);
07075               lstrcat(szCorruptedArchiveList, "\n");
07076             }
07077             else
07078             {
07079               iResult = WIZ_OUT_OF_MEMORY;
07080               break;
07081             }
07082           }
07083         }
07084       }
07085     }
07086 
07087     ++dwIndex0;
07088     siCObject = SiCNodeGetObject(dwIndex0, TRUE, AC_ALL);
07089   }
07090   ShowMessage(szMsgCRCCheck, FALSE);
07091   return(iResult);
07092 }
07093 
07094 int StartupCheckArchives(void)
07095 {
07096   int  iRv;
07097   char szBuf[MAX_BUF_SMALL];
07098   char szCorruptedArchiveList[MAX_BUF];
07099 
07100   iRv = CRCCheckArchivesStartup(szCorruptedArchiveList, sizeof(szCorruptedArchiveList), gbPreviousUnfinishedDownload);
07101   switch(iRv)
07102   {
07103     char szMsg[MAX_BUF];
07104     char szBuf2[MAX_BUF];
07105     char szTitle[MAX_BUF_TINY];
07106 
07107     case WIZ_CRC_FAIL:
07108       switch(sgProduct.mode)
07109       {
07110         case NORMAL:
07111           if(GetPrivateProfileString("Messages", "STR_MESSAGEBOX_TITLE", "", szBuf, sizeof(szBuf), szFileIniInstall))
07112             lstrcpy(szTitle, "Setup");
07113           else
07114             wsprintf(szTitle, szBuf, sgProduct.szProductName);
07115 
07116           GetConfigIniProfileString("Strings", "Error Corrupted Archives Detected", "", szBuf, sizeof(szBuf));
07117           if(*szBuf != '\0')
07118           {
07119             lstrcpy(szBuf2, "\n\n");
07120             lstrcat(szBuf2, szCorruptedArchiveList);
07121             lstrcat(szBuf2, "\n");
07122             wsprintf(szMsg, szBuf, szBuf2);
07123           }
07124           MessageBox(hWndMain, szMsg, szTitle, MB_OK | MB_ICONSTOP);
07125           break;
07126 
07127         case AUTO:
07128           GetConfigIniProfileString("Strings", "Error Corrupted Archives Detected AUTO mode", "", szBuf, sizeof(szBuf));
07129           ShowMessage(szBuf, TRUE);
07130           Delay(5);
07131           ShowMessage(szBuf, FALSE);
07132           break;
07133       }
07134 
07135       LogISComponentsFailedCRC(szCorruptedArchiveList, W_STARTUP);
07136       return(WIZ_CRC_FAIL);
07137 
07138     case WIZ_CRC_PASS:
07139       break;
07140 
07141     default:
07142       break;
07143   }
07144   LogISComponentsFailedCRC(NULL, W_STARTUP);
07145   return(iRv);
07146 }
07147 
07148 HRESULT ParseConfigIni(LPSTR lpszCmdLine)
07149 {
07150   int  iRv;
07151   char szBuf[MAX_BUF];
07152   char szMsgInitSetup[MAX_BUF];
07153   char szPreviousPath[MAX_BUF];
07154   char szShowDialog[MAX_BUF];
07155   DWORD dwPreviousUnfinishedState;
07156 
07157   if(InitDlgWelcome(&diWelcome))
07158     return(1);
07159   if(InitDlgLicense(&diLicense))
07160     return(1);
07161   if(InitDlgSetupType(&diSetupType))
07162     return(1);
07163   if(InitDlgSelectComponents(&diSelectComponents, SM_SINGLE))
07164     return(1);
07165   if(InitDlgSelectInstallPath(&diSelectInstallPath))
07166     return(1);
07167   if(InitDlgUpgrade(&diUpgrade))
07168     return(1);
07169   if(InitDlgSelectComponents(&diSelectAdditionalComponents, SM_SINGLE))
07170     return(1);
07171   if(InitDlgWindowsIntegration(&diWindowsIntegration))
07172     return(1);
07173   if(InitDlgProgramFolder(&diProgramFolder))
07174     return(1);
07175   if(InitDlgAdditionalOptions(&diAdditionalOptions))
07176     return(1);
07177   if(InitDlgAdvancedSettings(&diAdvancedSettings))
07178     return(1);
07179   if(InitDlgQuickLaunch(&diQuickLaunch))
07180     return(1);
07181   if(InitDlgStartInstall(&diStartInstall))
07182     return(1);
07183   if(InitDlgDownloading(&diDownloading))
07184     return(1);
07185   if(InitDlgInstalling(&diInstalling))
07186     return(1);
07187   if(InitDlgInstallSuccessful(&diInstallSuccessful))
07188     return(1);
07189   if(InitDlgDownload(&diDownload))
07190     return(1);
07191   if(InitDlgReboot(&diReboot))
07192     return(1);
07193   if(InitSDObject())
07194     return(1);
07195   if(InitSXpcomFile())
07196     return(1);
07197   if(InitGre(&gGre))
07198     return(WIZ_ERROR_INIT);
07199  
07200   /* get install Mode information */
07201   GetConfigIniProfileString("General", "Run Mode", "", szBuf, sizeof(szBuf));
07202   SetSetupRunMode(szBuf);
07203 
07204   /* find out if we are doing a shared install */
07205   GetConfigIniProfileString("General", "Shared Install", "", szBuf, sizeof(szBuf));
07206   if(lstrcmpi(szBuf, "TRUE") == 0)
07207     sgProduct.bSharedInst = TRUE;
07208 
07209   /* find out if we need to cleanup previous installation on upgrade
07210    * (installing ontop of - not related to cleaning up olde GRE's
07211    *  installed elsewhere) */
07212   GetConfigIniProfileString("Cleanup On Upgrade", "Cleanup", "", szBuf, sizeof(szBuf));
07213   if(lstrcmpi(szBuf, "TRUE") == 0)
07214     sgProduct.