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  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "extern.h"
00041 #include "extra.h"
00042 #include "parser.h"
00043 #include "dialogs.h"
00044 #include "ifuncns.h"
00045 #include "process.h"
00046 #include <winver.h>
00047 
00048 // shellapi.h is needed to build with WIN32_LEAN_AND_MEAN
00049 #include <shellapi.h>
00050 
00051 #define HIDWORD(l)   ((DWORD) (((ULONG) (l) >> 32) & 0xFFFF))
00052 #define LODWORD(l)   ((DWORD) (l))
00053 
00054 #define INDEX_STR_LEN       10
00055 #define PN_PROCESS          TEXT("Process")
00056 #define PN_THREAD           TEXT("Thread")
00057 
00058 ULONG  (PASCAL *NS_GetDiskFreeSpace)(LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
00059 ULONG  (PASCAL *NS_GetDiskFreeSpaceEx)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
00060 
00061 BOOL InitApplication(HINSTANCE hInstance)
00062 {
00063   WNDCLASS wc;
00064 
00065   wc.style         = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
00066   wc.lpfnWndProc   = DefDlgProc;
00067   wc.cbClsExtra    = 0;
00068   wc.cbWndExtra    = DLGWINDOWEXTRA;
00069   wc.hInstance     = hInstance;
00070   wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UNINSTALL));
00071   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
00072   wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
00073   wc.lpszMenuName  = NULL;
00074   wc.lpszClassName = szClassName;
00075 
00076   dwScreenX = GetSystemMetrics(SM_CXSCREEN);
00077   dwScreenY = GetSystemMetrics(SM_CYSCREEN);
00078 
00079   return(RegisterClass(&wc));
00080 }
00081 
00082 void PrintError(LPSTR szMsg, DWORD dwErrorCodeSH)
00083 {
00084   DWORD dwErr;
00085   char  szErrorString[MAX_BUF];
00086 
00087   if(dwErrorCodeSH == ERROR_CODE_SHOW)
00088   {
00089     dwErr = GetLastError();
00090     wsprintf(szErrorString, "%d : %s", dwErr, szMsg);
00091   }
00092   else
00093     wsprintf(szErrorString, "%s", szMsg);
00094 
00095   if((ugUninstall.mode != SILENT) && (ugUninstall.mode != AUTO))
00096   {
00097     MessageBox(hWndMain, szErrorString, NULL, MB_ICONEXCLAMATION);
00098   }
00099   else if(ugUninstall.mode == AUTO)
00100   {
00101     ShowMessage(szErrorString, TRUE);
00102     Delay(5);
00103     ShowMessage(szErrorString, FALSE);
00104   }
00105 }
00106 
00107 void *NS_GlobalAlloc(DWORD dwMaxBuf)
00108 {
00109   LPSTR szBuf = NULL;
00110 
00111   if((szBuf = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, dwMaxBuf)) == NULL)
00112   {     
00113     if((szEGlobalAlloc == NULL) || (*szEGlobalAlloc == '\0'))
00114       PrintError(TEXT("Memory allocation error."), ERROR_CODE_HIDE);
00115     else
00116       PrintError(szEGlobalAlloc, ERROR_CODE_SHOW);
00117 
00118     return(NULL);
00119   }
00120   else
00121     return(szBuf);
00122 }
00123 
00124 void FreeMemory(void **vPointer)
00125 {
00126   if(*vPointer != NULL)
00127     *vPointer = GlobalFree(*vPointer);
00128 }
00129 
00130 HRESULT NS_LoadStringAlloc(HANDLE hInstance, DWORD dwID, LPSTR *szStringBuf, DWORD dwStringBuf)
00131 {
00132   char szBuf[MAX_BUF];
00133 
00134   if((*szStringBuf = NS_GlobalAlloc(MAX_BUF)) == NULL)
00135     exit(1);
00136   
00137   if(!LoadString(hInstance, dwID, *szStringBuf, dwStringBuf))
00138   {
00139     if((szEStringLoad == NULL) ||(*szEStringLoad == '\0'))
00140       wsprintf(szBuf, "Could not load string resource ID %d", dwID);
00141     else
00142       wsprintf(szBuf, szEStringLoad, dwID);
00143 
00144     PrintError(szBuf, ERROR_CODE_SHOW);
00145     return(1);
00146   }
00147   return(0);
00148 }
00149 
00150 HRESULT NS_LoadString(HANDLE hInstance, DWORD dwID, LPSTR szStringBuf, DWORD dwStringBuf)
00151 {
00152   char szBuf[MAX_BUF];
00153 
00154   if(!LoadString(hInstance, dwID, szStringBuf, dwStringBuf))
00155   {
00156     if((szEStringLoad == NULL) ||(*szEStringLoad == '\0'))
00157       wsprintf(szBuf, "Could not load string resource ID %d", dwID);
00158     else
00159       wsprintf(szBuf, szEStringLoad, dwID);
00160 
00161     PrintError(szBuf, ERROR_CODE_SHOW);
00162     return(1);
00163   }
00164   return(WIZ_OK);
00165 }
00166 
00167 void Delay(DWORD dwSeconds)
00168 {
00169   SleepEx(dwSeconds * 1000, FALSE);
00170 }
00171 
00172 HRESULT Initialize(HINSTANCE hInstance)
00173 {
00174   char szBuf[MAX_BUF];
00175 
00176   hDlgMessage = NULL;
00177   DetermineOSVersion();
00178   gdwWhatToDo = WTD_ASK;
00179 
00180   /* load strings from setup.exe */
00181   if(NS_LoadStringAlloc(hInst, IDS_ERROR_GLOBALALLOC, &szEGlobalAlloc, MAX_BUF))
00182     return(1);
00183   if(NS_LoadStringAlloc(hInst, IDS_ERROR_STRING_LOAD, &szEStringLoad,  MAX_BUF))
00184     return(1);
00185   if(NS_LoadStringAlloc(hInst, IDS_ERROR_DLL_LOAD,    &szEDllLoad,     MAX_BUF))
00186     return(1);
00187   if(NS_LoadStringAlloc(hInst, IDS_ERROR_STRING_NULL, &szEStringNull,  MAX_BUF))
00188     return(1);
00189 
00190   ZeroMemory(szBuf, sizeof(MAX_BUF));
00191   if((szClassName = NS_GlobalAlloc(MAX_BUF)) == NULL)
00192     return(1);
00193 
00194   lstrcpy(szClassName, CLASS_NAME_UNINSTALL_DLG);
00195   hAccelTable = LoadAccelerators(hInst, szClassName);
00196   if((szUninstallDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00197     return(1);
00198 
00199   GetModuleFileName(NULL, szBuf, sizeof(szBuf));
00200   ParsePath(szBuf, szUninstallDir, MAX_BUF, PP_PATH_ONLY);
00201 
00202   if((szTempDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00203     return(1);
00204 
00205   if((szOSTempDir = NS_GlobalAlloc(MAX_BUF)) == NULL)
00206     return(1);
00207 
00208   if((szFileIniUninstall = NS_GlobalAlloc(MAX_BUF)) == NULL)
00209     return(1);
00210 
00211   lstrcpy(szFileIniUninstall, szUninstallDir);
00212   AppendBackSlash(szFileIniUninstall, MAX_BUF);
00213   lstrcat(szFileIniUninstall, FILE_INI_UNINSTALL);
00214 
00215   if((szFileIniDefaultsInfo = NS_GlobalAlloc(MAX_BUF)) == NULL)
00216     return(1);
00217 
00218   lstrcpy(szFileIniDefaultsInfo, szUninstallDir);
00219   AppendBackSlash(szFileIniDefaultsInfo, MAX_BUF);
00220   GetPrivateProfileString("General", "Defaults Info Filename", "", szBuf, MAX_BUF, szFileIniUninstall);
00221   lstrcat(szFileIniDefaultsInfo, szBuf);
00222 
00223   // determine the system's TEMP path
00224   if(GetTempPath(MAX_BUF, szTempDir) == 0)
00225   {
00226     if(GetWindowsDirectory(szTempDir, MAX_BUF) == 0)
00227     {
00228       char szEGetWinDirFailed[MAX_BUF];
00229 
00230       if(GetPrivateProfileString("Messages", "ERROR_GET_WINDOWS_DIRECTORY_FAILED", "", 
00231                                  szEGetWinDirFailed, sizeof(szEGetWinDirFailed),
00232                                  szFileIniUninstall))
00233         PrintError(szEGetWinDirFailed, ERROR_CODE_SHOW);
00234 
00235       return(1);
00236     }
00237 
00238     AppendBackSlash(szTempDir, MAX_BUF);
00239     lstrcat(szTempDir, "TEMP");
00240   }
00241   lstrcpy(szOSTempDir, szTempDir);
00242   AppendBackSlash(szTempDir, MAX_BUF);
00243   lstrcat(szTempDir, WIZ_TEMP_DIR);
00244 
00245   /*  if multiple installer instances are allowed; 
00246       each instance requires a unique temp directory
00247    */
00248   if(gbAllowMultipleInstalls)
00249   {
00250     DWORD dwLen = lstrlen(szTempDir);
00251 
00252     if (strncmp(szUninstallDir, szTempDir, dwLen) == 0)
00253     {
00254       lstrcpy(szTempDir, szUninstallDir);
00255     }
00256     else
00257     {
00258       int i;
00259       for(i = 1; i <= 100 && (FileExists(szTempDir) != FALSE); i++)
00260       {
00261         itoa(i, (szTempDir + dwLen), 10);
00262       }
00263     
00264       if (FileExists(szTempDir) != FALSE)
00265       {
00266         MessageBox(hWndMain, "Cannot create temp directory", NULL, MB_OK | MB_ICONEXCLAMATION);
00267         exit(1);
00268       }
00269     }
00270   }
00271   else
00272   {
00273     // we're not running in mmi mode (allow multiple instances of installer
00274     // to run at the same time), we should look for and remove the dirs
00275     // that are created in the mmi mode.
00276     DWORD dwLen;
00277     char tempDirToCleanup[MAX_BUF];
00278     int i = 1;
00279 
00280     lstrcpy(tempDirToCleanup, szTempDir);
00281     dwLen = lstrlen(tempDirToCleanup);
00282     itoa(i, (tempDirToCleanup + dwLen), 10);
00283     for(i = 2; i <= 100 && (FileExists(tempDirToCleanup)); i++)
00284     {
00285       DirectoryRemove(tempDirToCleanup, TRUE);
00286       itoa(i, (tempDirToCleanup + dwLen), 10);
00287     }
00288   }
00289 
00290   if(!FileExists(szTempDir))
00291   {
00292     AppendBackSlash(szTempDir, MAX_BUF);
00293     CreateDirectoriesAll(szTempDir);
00294     if(!FileExists(szTempDir))
00295     {
00296       char szECreateTempDir[MAX_BUF];
00297 
00298       if(GetPrivateProfileString("Messages", "ERROR_CREATE_TEMP_DIR", "",
00299                                  szECreateTempDir, sizeof(szECreateTempDir), 
00300                                  szFileIniUninstall))
00301       {
00302         wsprintf(szBuf, szECreateTempDir, szTempDir);
00303         PrintError(szBuf, ERROR_CODE_HIDE);
00304       }
00305       return(1);
00306     }
00307     RemoveBackSlash(szTempDir);
00308   }
00309 
00310   ugUninstall.bVerbose = FALSE;
00311   ugUninstall.bUninstallFiles = TRUE;
00312   ugUninstall.bSharedInst = FALSE;
00313 
00314   return(0);
00315 }
00316 
00317 /* Function to remove quotes from a string */
00318 void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize)
00319 {
00320   char *lpszBegin;
00321 
00322   if(lstrlen(lpszSrc) > iDestSize)
00323     return;
00324 
00325   if(*lpszSrc == '\"')
00326     lpszBegin = &lpszSrc[1];
00327   else
00328     lpszBegin = lpszSrc;
00329 
00330   lstrcpy(lpszDest, lpszBegin);
00331 
00332   if(lpszDest[lstrlen(lpszDest) - 1] == '\"')
00333     lpszDest[lstrlen(lpszDest) - 1] = '\0';
00334 }
00335 
00336 /* Function to copy strings safely.
00337  *   returns the amount of memory required (including NULL byte) if there's not enough
00338  *   else, it returns 0 for success.
00339  */
00340 int MozCopyStr(LPSTR szSrc, LPSTR szDest, DWORD dwDestBufSize)
00341 {
00342   DWORD length = lstrlen(szSrc) + 1;
00343   strncpy(szDest, szSrc, dwDestBufSize);
00344   if(length > dwDestBufSize)
00345   {
00346     szDest[dwDestBufSize - 1] = '\0';
00347     return(length);
00348   }
00349   return(0);
00350 }
00351 
00352 /* Function to locate the first non space character in a string,
00353  * and return a pointer to it. */
00354 LPSTR GetFirstNonSpace(LPSTR lpszString)
00355 {
00356   char* p = lpszString;
00357   while (*p && isspace(*p))
00358     p = CharNext(p);
00359 
00360   if(*p == '\0')  // null means end of string
00361     return NULL;
00362 
00363   return p;
00364 }
00365 
00366 /* Function to locate the first space character in a string,
00367  * and return a pointer to it. */
00368 LPSTR GetFirstSpace(LPSTR lpszString)
00369 {
00370   char* p = lpszString;
00371   while (*p && !isspace(*p))
00372     p = CharNext(p);
00373 
00374   if (*p == '\0')  // null means end of string
00375     return NULL;
00376 
00377   return p;
00378 }
00379 
00380 /* Function to locate the first character c in lpszString,
00381  * and return a pointer to it. */
00382 LPSTR MozStrChar(LPSTR lpszString, char c)
00383 {
00384   char* p = lpszString;
00385   while (*p && (*p != c))
00386     p = CharNext(p);
00387 
00388   if (*p == '\0')  // null means end of string
00389     return NULL;
00390 
00391   return p;
00392 }
00393 
00394 /* Function to return the argument count given a command line input
00395  * format string */
00396 int GetArgC(LPSTR lpszCommandLine)
00397 {
00398   int   i;
00399   int   iArgCount;
00400   int   iStrLength;
00401   LPSTR lpszBeginStr;
00402   BOOL  bFoundQuote;
00403   BOOL  bFoundSpace;
00404 
00405   iArgCount    = 0;
00406   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00407 
00408   if(lpszBeginStr == NULL)
00409     return(iArgCount);
00410 
00411   iStrLength   = lstrlen(lpszBeginStr);
00412   bFoundQuote  = FALSE;
00413   bFoundSpace  = TRUE;
00414 
00415   for(i = 0; i < iStrLength; i++)
00416   {
00417     if(lpszCommandLine[i] == '\"')
00418     {
00419       if(bFoundQuote == FALSE)
00420       {
00421         ++iArgCount;
00422         bFoundQuote = TRUE;
00423       }
00424       else
00425       {
00426         bFoundQuote = FALSE;
00427       }
00428     }
00429     else if(bFoundQuote == FALSE)
00430     {
00431       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
00432       {
00433         ++iArgCount;
00434         bFoundSpace = FALSE;
00435       }
00436       else if(isspace(lpszCommandLine[i]))
00437       {
00438         bFoundSpace = TRUE;
00439       }
00440     }
00441   }
00442 
00443   return(iArgCount);
00444 }
00445 
00446 /* Function to return a specific argument parameter from a given command line input
00447  * format string. */
00448 LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize)
00449 {
00450   int   i;
00451   int   j;
00452   int   iArgCount;
00453   int   iStrLength;
00454   LPSTR lpszBeginStr;
00455   LPSTR lpszDestTemp;
00456   BOOL  bFoundQuote;
00457   BOOL  bFoundSpace;
00458 
00459   iArgCount    = 0;
00460   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00461 
00462   if(lpszBeginStr == NULL)
00463     return(NULL);
00464 
00465   lpszDestTemp = (char *)calloc(iDestSize, sizeof(char));
00466   if(lpszDestTemp == NULL)
00467   {
00468     PrintError("Out of memory", ERROR_CODE_HIDE);
00469     exit(1);
00470   }
00471 
00472   ZeroMemory(lpszDest, iDestSize);
00473   iStrLength    = lstrlen(lpszBeginStr);
00474   bFoundQuote   = FALSE;
00475   bFoundSpace   = TRUE;
00476   j             = 0;
00477 
00478   for(i = 0; i < iStrLength; i++)
00479   {
00480     if(lpszCommandLine[i] == '\"')
00481     {
00482       if(bFoundQuote == FALSE)
00483       {
00484         ++iArgCount;
00485         bFoundQuote = TRUE;
00486       }
00487       else
00488       {
00489         bFoundQuote = FALSE;
00490       }
00491     }
00492     else if(bFoundQuote == FALSE)
00493     {
00494       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
00495       {
00496         ++iArgCount;
00497         bFoundSpace = FALSE;
00498       }
00499       else if(isspace(lpszCommandLine[i]))
00500       {
00501         bFoundSpace = TRUE;
00502       }
00503     }
00504 
00505     if((iIndex == (iArgCount - 1)) &&
00506       ((bFoundQuote == TRUE) || (bFoundSpace == FALSE) ||
00507       ((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"'))))
00508     {
00509       if(j < iDestSize)
00510       {
00511         lpszDestTemp[j] = lpszCommandLine[i];
00512         ++j;
00513       }
00514       else
00515       {
00516         lpszDestTemp[j] = '\0';
00517       }
00518     }
00519   }
00520 
00521   RemoveQuotes(lpszDestTemp, lpszDest, iDestSize);
00522   free(lpszDestTemp);
00523   return(lpszDest);
00524 }
00525 
00526 void SetUninstallRunMode(LPSTR szMode)
00527 {
00528   /* Check to see if mode has already been set.  If so,
00529    * then do not override it.
00530    */
00531   if(ugUninstall.mode != NOT_SET)
00532     return;
00533 
00534   if(lstrcmpi(szMode, "NORMAL") == 0)
00535     ugUninstall.mode = NORMAL;
00536   if(lstrcmpi(szMode, "AUTO") == 0)
00537     ugUninstall.mode = AUTO;
00538   if(lstrcmpi(szMode, "SILENT") == 0)
00539     ugUninstall.mode = SILENT;
00540   if(lstrcmpi(szMode, "SHOWICONS") == 0)
00541     ugUninstall.mode = SHOWICONS;
00542   if(lstrcmpi(szMode, "HIDEICONS") == 0)
00543     ugUninstall.mode = HIDEICONS;
00544   if(lstrcmpi(szMode, "SETDEFAULT") == 0)
00545     ugUninstall.mode = SETDEFAULT;
00546 }
00547 
00548 void RemoveBackSlash(LPSTR szInput)
00549 {
00550   int   iCounter;
00551   DWORD dwInputLen;
00552 
00553   if(szInput != NULL)
00554   {
00555     dwInputLen = lstrlen(szInput);
00556 
00557     for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--)
00558     {
00559       if(szInput[iCounter] == '\\')
00560         szInput[iCounter] = '\0';
00561       else
00562         break;
00563     }
00564   }
00565 }
00566 
00567 void AppendBackSlash(LPSTR szInput, DWORD dwInputSize)
00568 {
00569   if(szInput != NULL)
00570   {
00571     if(*szInput == '\0')
00572     {
00573       if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
00574       {
00575         lstrcat(szInput, "\\");
00576       }
00577     }
00578     else if(szInput[strlen(szInput) - 1] != '\\')
00579     {
00580       if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
00581       {
00582         lstrcat(szInput, "\\");
00583       }
00584     }
00585   }
00586 }
00587 
00588 void RemoveSlash(LPSTR szInput)
00589 {
00590   int   iCounter;
00591   DWORD dwInputLen;
00592 
00593   if(szInput != NULL)
00594   {
00595     dwInputLen = lstrlen(szInput);
00596 
00597     for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--)
00598     {
00599       if(szInput[iCounter] == '/')
00600         szInput[iCounter] = '\0';
00601       else
00602         break;
00603     }
00604   }
00605 }
00606 
00607 void AppendSlash(LPSTR szInput, DWORD dwInputSize)
00608 {
00609   if(szInput != NULL)
00610   {
00611     if(*szInput == '\0')
00612     {
00613       if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
00614       {
00615         lstrcat(szInput, "/");
00616       }
00617     }
00618     else if(szInput[strlen(szInput) - 1] != '/')
00619     {
00620       if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
00621       {
00622         lstrcat(szInput, "/");
00623       }
00624     }
00625   }
00626 }
00627 
00628 void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType)
00629 {
00630   int   iCounter;
00631   DWORD dwCounter;
00632   DWORD dwInputLen;
00633   BOOL  bFound;
00634 
00635   if((szInput != NULL) && (szOutput != NULL))
00636   {
00637     bFound        = FALSE;
00638     dwInputLen    = lstrlen(szInput);
00639     ZeroMemory(szOutput, dwOutputSize);
00640 
00641     if(dwInputLen < dwOutputSize)
00642     {
00643       switch(dwType)
00644       {
00645         case PP_FILENAME_ONLY:
00646           for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
00647           {
00648             if(szInput[iCounter] == '\\')
00649             {
00650               lstrcpy(szOutput, &szInput[iCounter + 1]);
00651               bFound = TRUE;
00652               break;
00653             }
00654           }
00655           if(bFound == FALSE)
00656             lstrcpy(szOutput, szInput);
00657 
00658           break;
00659 
00660         case PP_PATH_ONLY:
00661           for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
00662           {
00663             if(szInput[iCounter] == '\\')
00664             {
00665               lstrcpy(szOutput, szInput);
00666               szOutput[iCounter + 1] = '\0';
00667               bFound = TRUE;
00668               break;
00669             }
00670           }
00671           if(bFound == FALSE)
00672             lstrcpy(szOutput, szInput);
00673 
00674           break;
00675 
00676         case PP_ROOT_ONLY:
00677           if(szInput[1] == ':')
00678           {
00679             szOutput[0] = szInput[0];
00680             szOutput[1] = szInput[1];
00681             AppendBackSlash(szOutput, dwOutputSize);
00682           }
00683           else if(szInput[1] == '\\')
00684           {
00685             int iFoundBackSlash = 0;
00686             for(dwCounter = 0; dwCounter < dwInputLen; dwCounter++)
00687             {
00688               if(szInput[dwCounter] == '\\')
00689               {
00690                 szOutput[dwCounter] = szInput[dwCounter];
00691                 ++iFoundBackSlash;
00692               }
00693 
00694               if(iFoundBackSlash == 3)
00695                 break;
00696             }
00697 
00698             if(iFoundBackSlash != 0)
00699               AppendBackSlash(szOutput, dwOutputSize);
00700           }
00701           break;
00702       }
00703     }
00704   }
00705 }
00706 
00707 void DetermineOSVersion()
00708 {
00709   BOOL          bIsWin95Debute;
00710   char          szEMsg[MAX_BUF];
00711   OSVERSIONINFO osVersionInfo;
00712 
00713   ulOSType = 0;
00714   osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00715   if(!GetVersionEx(&osVersionInfo))
00716   {
00717     /* GetVersionEx() failed for some reason.  It's not fatal, but could cause
00718      * some complications during installation */
00719     if(GetPrivateProfileString("Messages", "ERROR_GETVERSION", "", szEMsg, sizeof(szEMsg), szFileIniUninstall))
00720       PrintError(szEMsg, ERROR_CODE_SHOW);
00721   }
00722 
00723   bIsWin95Debute  = IsWin95Debute();
00724   switch(osVersionInfo.dwPlatformId)
00725   {
00726     case VER_PLATFORM_WIN32_WINDOWS:
00727       ulOSType |= OS_WIN9x;
00728       if(osVersionInfo.dwMinorVersion == 0)
00729       {
00730         ulOSType |= OS_WIN95;
00731         if(bIsWin95Debute)
00732           ulOSType |= OS_WIN95_DEBUTE;
00733       }
00734       else
00735         ulOSType |= OS_WIN98;
00736       break;
00737 
00738     case VER_PLATFORM_WIN32_NT:
00739       ulOSType |= OS_NT;
00740       switch(osVersionInfo.dwMajorVersion)
00741       {
00742         case 3:
00743           ulOSType |= OS_NT3;
00744           break;
00745 
00746         case 4:
00747           ulOSType |= OS_NT4;
00748           break;
00749 
00750         default:
00751           ulOSType |= OS_NT5;
00752           switch(osVersionInfo.dwMinorVersion)
00753           {
00754             case 0:
00755               /* a minor version of 0 (major.minor.build) indicates Win2000 */
00756               ulOSType |= OS_NT50;
00757               break;
00758 
00759             case 1:
00760               /* a minor version of 1 (major.minor.build) indicates WinXP */
00761               ulOSType |= OS_NT51;
00762           break;
00763           }
00764         break;
00765       }
00766       break;
00767 
00768     default:
00769       if(GetPrivateProfileString("Messages", "ERROR_SETUP_REQUIREMENT", "", szEMsg, sizeof(szEMsg), szFileIniUninstall))
00770         PrintError(szEMsg, ERROR_CODE_HIDE);
00771 
00772       exit(1);
00773       break;
00774   }
00775 }
00776 
00777 HRESULT WinSpawn(LPSTR szClientName, LPSTR szParameters, LPSTR szCurrentDir, int iShowCmd, BOOL bWait)
00778 {
00779   SHELLEXECUTEINFO seInfo;
00780 
00781   seInfo.cbSize       = sizeof(SHELLEXECUTEINFO);
00782   seInfo.fMask        = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOCLOSEPROCESS;
00783   seInfo.hwnd         = hWndMain;
00784   seInfo.lpVerb       = NULL;
00785   seInfo.lpFile       = szClientName;
00786   seInfo.lpParameters = szParameters;
00787   seInfo.lpDirectory  = szCurrentDir;
00788   seInfo.nShow        = SW_SHOWNORMAL;
00789   seInfo.hInstApp     = 0;
00790   seInfo.lpIDList     = NULL;
00791   seInfo.lpClass      = NULL;
00792   seInfo.hkeyClass    = 0;
00793   seInfo.dwHotKey     = 0;
00794   seInfo.hIcon        = 0;
00795   seInfo.hProcess     = 0;
00796 
00797   if((ShellExecuteEx(&seInfo) != 0) && (seInfo.hProcess != NULL))
00798   {
00799     if(bWait)
00800     {
00801       for(;;)
00802       {
00803         if(WaitForSingleObject(seInfo.hProcess, 200) == WAIT_OBJECT_0)
00804           break;
00805 
00806         ProcessWindowsMessages();
00807       }
00808     }
00809     return(TRUE);
00810   }
00811   return(FALSE);
00812 }
00813 
00814 HRESULT InitDlgUninstall(diU *diDialog)
00815 {
00816   diDialog->bShowDialog = FALSE;
00817   if((diDialog->szTitle = NS_GlobalAlloc(MAX_BUF)) == NULL)
00818     return(1);
00819   if((diDialog->szMessage0 = NS_GlobalAlloc(MAX_BUF)) == NULL)
00820     return(1);
00821 
00822   return(0);
00823 }
00824 
00825 void DeInitDlgUninstall(diU *diDialog)
00826 {
00827   FreeMemory(&(diDialog->szTitle));
00828   FreeMemory(&(diDialog->szMessage0));
00829 }
00830 
00831 HRESULT InitUninstallGeneral()
00832 {
00833   ugUninstall.mode = NOT_SET;
00834 
00835   if((ugUninstall.szAppPath                 = NS_GlobalAlloc(MAX_BUF)) == NULL)
00836     return(1);
00837   if((ugUninstall.szLogPath                 = NS_GlobalAlloc(MAX_BUF)) == NULL)
00838     return(1);
00839   if((ugUninstall.szLogFilename             = NS_GlobalAlloc(MAX_BUF)) == NULL)
00840     return(1);
00841   if((ugUninstall.szCompanyName             = NS_GlobalAlloc(MAX_BUF)) == NULL)
00842     return(1);
00843   if((ugUninstall.szProductName             = NS_GlobalAlloc(MAX_BUF)) == NULL)
00844     return(1);
00845   if((ugUninstall.szWrKey                   = NS_GlobalAlloc(MAX_BUF)) == NULL)
00846     return(1);
00847   if((ugUninstall.szUserAgent               = NS_GlobalAlloc(MAX_BUF)) == NULL)
00848     return(1);
00849   if((ugUninstall.szDefaultComponent        = NS_GlobalAlloc(MAX_BUF)) == NULL)
00850     return(1);
00851   if((ugUninstall.szWrMainKey               = NS_GlobalAlloc(MAX_BUF)) == NULL)
00852     return(1);
00853   if((ugUninstall.szDescription             = NS_GlobalAlloc(MAX_BUF)) == NULL)
00854     return(1);
00855   if((ugUninstall.szUninstallKeyDescription = NS_GlobalAlloc(MAX_BUF)) == NULL)
00856     return(1);
00857   if((ugUninstall.szUninstallFilename       = NS_GlobalAlloc(MAX_BUF)) == NULL)
00858     return(1);
00859   if((ugUninstall.szClientAppID             = NS_GlobalAlloc(MAX_BUF)) == NULL)
00860     return(1);
00861   if((ugUninstall.szClientAppPath           = NS_GlobalAlloc(MAX_BUF)) == NULL)
00862     return(1);
00863 
00864   return(0);
00865 }
00866 
00867 void DeInitUninstallGeneral()
00868 {
00869   FreeMemory(&(ugUninstall.szAppPath));
00870   FreeMemory(&(ugUninstall.szLogPath));
00871   FreeMemory(&(ugUninstall.szLogFilename));
00872   FreeMemory(&(ugUninstall.szDescription));
00873   FreeMemory(&(ugUninstall.szUninstallKeyDescription));
00874   FreeMemory(&(ugUninstall.szUninstallFilename));
00875   FreeMemory(&(ugUninstall.szUserAgent));
00876   FreeMemory(&(ugUninstall.szDefaultComponent));
00877   FreeMemory(&(ugUninstall.szWrKey));
00878   FreeMemory(&(ugUninstall.szCompanyName));
00879   FreeMemory(&(ugUninstall.szProductName));
00880   FreeMemory(&(ugUninstall.szWrMainKey));
00881   FreeMemory(&(ugUninstall.szClientAppID));
00882   FreeMemory(&(ugUninstall.szClientAppPath));
00883   DeleteObject(ugUninstall.definedFont);
00884 }
00885 
00886 sil *CreateSilNode()
00887 {
00888   sil *silNode;
00889 
00890   if((silNode = NS_GlobalAlloc(sizeof(struct sInfoLine))) == NULL)
00891     exit(1);
00892 
00893   if((silNode->szLine = NS_GlobalAlloc(MAX_BUF)) == NULL)
00894     exit(1);
00895 
00896   silNode->ullLineNumber = 0;
00897   silNode->Next          = silNode;
00898   silNode->Prev          = silNode;
00899 
00900   return(silNode);
00901 }
00902 
00903 void SilNodeInsert(sil *silHead, sil *silTemp)
00904 {
00905   if(silHead == NULL)
00906   {
00907     silHead          = silTemp;
00908     silHead->Next    = silHead;
00909     silHead->Prev    = silHead;
00910   }
00911   else
00912   {
00913     silTemp->Next           = silHead;
00914     silTemp->Prev           = silHead->Prev;
00915     silHead->Prev->Next     = silTemp;
00916     silHead->Prev           = silTemp;
00917   }
00918 }
00919 
00920 void SilNodeDelete(sil *silTemp)
00921 {
00922   if(silTemp != NULL)
00923   {
00924     silTemp->Next->Prev = silTemp->Prev;
00925     silTemp->Prev->Next = silTemp->Next;
00926     silTemp->Next       = NULL;
00927     silTemp->Prev       = NULL;
00928 
00929     FreeMemory(&(silTemp->szLine));
00930     FreeMemory(&silTemp);
00931   }
00932 }
00933 
00934 BOOL IsWin95Debute()
00935 {
00936   HINSTANCE hLib;
00937   BOOL      bIsWin95Debute;
00938 
00939   bIsWin95Debute = FALSE;
00940   if((hLib = LoadLibraryEx("kernel32.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) != NULL)
00941   {
00942     if(((FARPROC)NS_GetDiskFreeSpaceEx = GetProcAddress(hLib, "GetDiskFreeSpaceExA")) == NULL)
00943     {
00944       (FARPROC)NS_GetDiskFreeSpace = GetProcAddress(hLib, "GetDiskFreeSpaceA");
00945       bIsWin95Debute = TRUE;
00946     }
00947 
00948     FreeLibrary(hLib);
00949   }
00950   return(bIsWin95Debute);
00951 }
00952 
00953 DWORD ParseCommandLine(LPSTR lpszCmdLine)
00954 {
00955   char  szArgVBuf[MAX_BUF];
00956   int   i;
00957   int   iArgC;
00958 
00959   i     = 0;
00960   iArgC = GetArgC(lpszCmdLine);
00961   while(i < iArgC)
00962   {
00963     GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
00964 
00965     if((lstrcmpi(szArgVBuf, "-ma") == 0) || (lstrcmpi(szArgVBuf, "/ma") == 0))
00966     {
00967       SetUninstallRunMode("AUTO");
00968     }
00969     else if((lstrcmpi(szArgVBuf, "-ms") == 0) || (lstrcmpi(szArgVBuf, "/ms") == 0))
00970     {
00971       SetUninstallRunMode("SILENT");
00972     }
00973     else if((lstrcmpi(szArgVBuf, "-ua") == 0) || (lstrcmpi(szArgVBuf, "/ua") == 0))
00974     {
00975       if((i + 1) < iArgC)
00976         GetArgV(lpszCmdLine, ++i, ugUninstall.szUserAgent, MAX_BUF);
00977     }
00978     else if((lstrcmpi(szArgVBuf, "-ss") == 0) || (lstrcmpi(szArgVBuf, "/ss") == 0))
00979     // Show Shortcuts
00980     {
00981       SetUninstallRunMode("SHOWICONS");
00982       if((i + 1) < iArgC)
00983         GetArgV(lpszCmdLine, ++i, ugUninstall.szDefaultComponent, MAX_BUF);
00984     }
00985     else if((lstrcmpi(szArgVBuf, "-hs") == 0) || (lstrcmpi(szArgVBuf, "/hs") == 0))
00986     // Hide Shortcuts
00987     {
00988       SetUninstallRunMode("HIDEICONS");
00989       if((i + 1) < iArgC)
00990         GetArgV(lpszCmdLine, ++i, ugUninstall.szDefaultComponent, MAX_BUF);
00991     }
00992     else if((lstrcmpi(szArgVBuf, "-sd") == 0) || (lstrcmpi(szArgVBuf, "/sd") == 0))
00993     // SetDefault
00994     {
00995       SetUninstallRunMode("SETDEFAULT");
00996       if((i + 1) < iArgC)
00997         GetArgV(lpszCmdLine, ++i, ugUninstall.szDefaultComponent, MAX_BUF);
00998     }
00999     else if((lstrcmpi(szArgVBuf, "-app") == 0) || (lstrcmpi(szArgVBuf, "/app") == 0))
01000     // Set the App ID
01001     {
01002       if((i + 1) < iArgC)
01003         GetArgV(lpszCmdLine, ++i, ugUninstall.szClientAppID, MAX_BUF);
01004     }
01005     else if((lstrcmpi(szArgVBuf, "-app_path") == 0) || (lstrcmpi(szArgVBuf, "/app_path") == 0))
01006     // Set the App Path
01007     {
01008       if((i + 1) < iArgC)
01009         GetArgV(lpszCmdLine, ++i, ugUninstall.szClientAppPath, MAX_BUF);
01010     }
01011     else if((lstrcmpi(szArgVBuf, "-reg_path") == 0) || (lstrcmpi(szArgVBuf, "/reg_path") == 0))
01012     // Set the alternative Windows registry path
01013     {
01014       if((i + 1) < iArgC)
01015         GetArgV(lpszCmdLine, ++i, ugUninstall.szWrMainKey, MAX_BUF);
01016     }
01017     else if((lstrcmpi(szArgVBuf, "-v") == 0) || (lstrcmpi(szArgVBuf, "/v") == 0))
01018     // Set Verbose
01019     {
01020       ugUninstall.bVerbose = TRUE;
01021     }
01022     else if(!lstrcmpi(szArgVBuf, "-mmi") || !lstrcmpi(szArgVBuf, "/mmi"))
01023     {
01024       gbAllowMultipleInstalls = TRUE;    
01025     }
01026 
01027     ++i;
01028   }
01029   return(WIZ_OK);
01030 }
01031 
01032 int PreCheckInstance(char *szSection, char *szIniFile)
01033 {
01034   char  szBuf[MAX_BUF];
01035   char  szKey[MAX_BUF];
01036   char  szName[MAX_BUF];
01037   char  szParameter[MAX_BUF];
01038   char  szPath[MAX_BUF];
01039   char  szFile[MAX_BUF];
01040   char  *ptrName = NULL;
01041   HKEY  hkeyRoot;
01042   int   iRv = WIZ_OK;
01043   DWORD dwCounter = 0;
01044   BOOL  bContinue = TRUE;
01045   char  szExtraCmd[] = "Extra Cmd";
01046   char  szExtraCmdKey[MAX_BUF];
01047 
01048   do
01049   {
01050     /* Read the win reg key path */
01051     wsprintf(szExtraCmdKey, "%s%d Reg Key", szExtraCmd, dwCounter);
01052     GetPrivateProfileString(szSection,
01053                             szExtraCmdKey,
01054                             "",
01055                             szKey,
01056                             sizeof(szKey),
01057                             szIniFile);
01058     if(*szKey == '\0')
01059     {
01060       bContinue = FALSE;
01061       continue;
01062     }
01063 
01064     /* Read the win reg root key */
01065     wsprintf(szExtraCmdKey, "%s%d Reg Key Root", szExtraCmd, dwCounter);
01066     GetPrivateProfileString(szSection,
01067                             szExtraCmdKey,
01068                             "",
01069                             szBuf,
01070                             sizeof(szBuf),
01071                             szIniFile);
01072     if(*szBuf == '\0')
01073     {
01074       bContinue = FALSE;
01075       continue;
01076     }
01077     hkeyRoot = ParseRootKey(szBuf);
01078 
01079     /* Read the win reg name value */
01080     wsprintf(szExtraCmdKey, "%s%d Reg Name", szExtraCmd, dwCounter);
01081     GetPrivateProfileString(szSection,
01082                             szExtraCmdKey,
01083                             "",
01084                             szName,
01085                             sizeof(szName),
01086                             szIniFile);
01087     if(*szName == '\0')
01088       ptrName = NULL;
01089     else
01090       ptrName = szName;
01091 
01092     /* Read the parameter to use for quitting the browser's turbo mode */
01093     wsprintf(szExtraCmdKey, "%s%d Parameter", szExtraCmd, dwCounter);
01094     GetPrivateProfileString(szSection,
01095                             szExtraCmdKey,
01096                             "",
01097                             szParameter,
01098                             sizeof(szParameter),
01099                             szIniFile);
01100 
01101     /* Read the win reg key that contains the path to the browser */
01102     GetWinReg(hkeyRoot, szKey, ptrName, szFile, sizeof(szFile));
01103     ParsePath(szFile, szPath, sizeof(szPath), PP_PATH_ONLY);
01104 
01105     /* Make sure the file exists */
01106     if(FileExists(szFile))
01107     {
01108       // we've found a file, so let's execute it and stop.  No need to look
01109       // for other keys to parse.  We only want to do that if the file is
01110       // _not_ found.  This is for when we change the name of the browser
01111       // app file and still need to deal with locating it and calling
01112       // -kill on it. ie.
01113       //   previous name: netscp6.exe
01114       //   new name: netscp.exe
01115       // We only need to call one of them, not both.
01116       bContinue = FALSE;
01117 
01118       /* Run the file */
01119       WinSpawn(szFile, szParameter, szPath, SW_HIDE, WS_WAIT);
01120 
01121       /* Even though WinSpawn is suppose to wait for the app to finish, this
01122        * does not really work that way for trying to quit the browser when
01123        * it's in turbo mode, so we wait 2 secs for it to complete. */
01124       Delay(2);
01125     }
01126 
01127     ++dwCounter;
01128   } while(bContinue);
01129 
01130   return(iRv);
01131 }
01132 
01133 HRESULT GetCheckInstanceQuitMessage(char *aSection, char *aMessage, DWORD aMessageBufSize)
01134 {
01135   *aMessage = '\0';
01136   GetPrivateProfileString(aSection, "Message", "", aMessage, aMessageBufSize, szFileIniUninstall);
01137   return(WIZ_OK);
01138 }
01139 
01140 HRESULT ShowMessageAndQuitProcess(HWND aHwndFW, char *aMsgQuitProcess, char *aMsgWait, BOOL aCloseAllWindows, char *aProcessName, BOOL aForceQuit)
01141 {
01142   switch(ugUninstall.mode)
01143   {
01144     case NORMAL:
01145     {
01146       char msgTitleStr[MAX_BUF];
01147       GetPrivateProfileString("Messages", "MB_ATTENTION_STR", "", msgTitleStr, sizeof(msgTitleStr), szFileIniUninstall);
01148       MessageBox(hWndMain, aMsgQuitProcess, msgTitleStr, MB_ICONEXCLAMATION | MB_SETFOREGROUND);
01149       break;
01150     }
01151 
01152     case AUTO:
01153     {
01154       /* Setup mode is AUTO.  Show message, timeout, then auto close
01155        * all the windows associated with the process */
01156       ShowMessage(aMsgQuitProcess, TRUE);
01157       Delay(5);
01158       ShowMessage(aMsgQuitProcess, FALSE);
01159       break;
01160     }
01161 
01162     case SILENT:
01163       break;
01164   }
01165 
01166   if(aForceQuit)
01167   {
01168     assert(aProcessName);
01169     FindAndKillProcess(aProcessName, KP_KILL_PROCESS);
01170   }
01171   else
01172   {
01173     assert(aHwndFW);
01174     /* First try sending a WM_QUIT message to the window because this is the
01175      * preferred way to quit a process.  If it works, then we're good and
01176      * CloseAllWindowsOfWindowHandle() will have nothing to do.
01177      * If it doesn't work, then CloseAllWindowsOfWindowHandle will try to
01178      * quit the process. */
01179     SendMessageTimeout(aHwndFW, WM_QUIT, (WPARAM)1, (LPARAM)0, SMTO_NORMAL, WM_CLOSE_TIMEOUT_VALUE, NULL);
01180     if(aCloseAllWindows)
01181       CloseAllWindowsOfWindowHandle(aHwndFW, aMsgWait);
01182   }
01183   Delay(2);
01184   return(WIZ_OK);
01185 }
01186 
01187 HRESULT CheckInstances()
01188 {
01189   char  section[MAX_BUF];
01190   char  processName[MAX_BUF];
01191   char  className[MAX_BUF];
01192   char  windowName[MAX_BUF];
01193   char  closeAllWindows[MAX_BUF];
01194   char  message[MAX_BUF];
01195   char  msgTitleStr[MAX_BUF];
01196   char  prettyName[MAX_BUF];
01197   char  buf[MAX_BUF];
01198   char  msgWait[MAX_BUF];
01199   int   index;
01200   int   killProcessTries = 0;
01201   int   instanceOfFoundProcess = 0;
01202   BOOL  bContinue;
01203   BOOL  bCloseAllWindows;
01204   HWND  hwndFW;
01205   LPSTR szWN;
01206   LPSTR szCN;
01207   DWORD dwRv0;
01208   DWORD dwRv1;
01209 
01210   GetPrivateProfileString("Messages", "MB_ATTENTION_STR", "", msgTitleStr, sizeof(msgTitleStr), szFileIniUninstall);
01211   bContinue = TRUE;
01212   index    = -1;
01213   while(bContinue)
01214   {
01215     *className  = '\0';
01216     *windowName = '\0';
01217     *message    = '\0';
01218 
01219     wsprintf(section, "Check Instance%d", ++index);
01220     GetPrivateProfileString(section, "Process Name", "", processName, sizeof(processName), szFileIniUninstall);
01221     GetPrivateProfileString(section, "Pretty Name", "", prettyName, sizeof(prettyName), szFileIniUninstall);
01222     GetPrivateProfileString(section, "Message Wait", "", msgWait, sizeof(msgWait), szFileIniUninstall);
01223     GetPrivateProfileString(section, "Close All Process Windows", "", closeAllWindows, sizeof(closeAllWindows), szFileIniUninstall);
01224     if(lstrcmpi(closeAllWindows, "TRUE") == 0)
01225       bCloseAllWindows = TRUE;
01226     else
01227       bCloseAllWindows = FALSE;
01228 
01229     if(instanceOfFoundProcess != index)
01230     {
01231       killProcessTries = 0;
01232       instanceOfFoundProcess = index;
01233     }
01234 
01235     if((killProcessTries == 1) && (*processName != '\0'))
01236     {
01237       if(FindAndKillProcess(processName, KP_DO_NOT_KILL_PROCESS))
01238       {
01239         /* found process, display warning message, then kill process */
01240         GetPrivateProfileString("Messages", "MSG_FORCE_QUIT_PROCESS", "", message, sizeof(message), szFileIniUninstall);
01241         if(*message != '\0')
01242         {
01243           wsprintf(buf, message, prettyName, processName, prettyName, prettyName);
01244           ShowMessageAndQuitProcess(NULL, buf, msgWait, bCloseAllWindows, processName, CI_FORCE_QUIT_PROCESS);
01245           ++killProcessTries;
01246           instanceOfFoundProcess = index--;
01247         }
01248       }
01249       continue;
01250     }
01251     else if(killProcessTries == MAX_KILL_PROCESS_RETRIES)
01252     {
01253       GetPrivateProfileString("Messages", "MSG_FORCE_QUIT_PROCESS_FAILED", "", message, sizeof(message), szFileIniUninstall);
01254       if(*message != '\0')
01255       {
01256         wsprintf(buf, message, prettyName, processName, prettyName);
01257         switch(ugUninstall.mode)
01258         {
01259           case NORMAL:
01260             MessageBox(hWndMain, buf, msgTitleStr, MB_ICONEXCLAMATION | MB_SETFOREGROUND);
01261             break;
01262 
01263           case AUTO:
01264             /* Setup mode is AUTO.  Show message, timeout, then auto close
01265              * all the windows associated with the process */
01266             ShowMessage(buf, TRUE);
01267             Delay(5);
01268             ShowMessage(buf, FALSE);
01269             break;
01270 
01271           default:
01272             break;
01273         }
01274       }
01275 
01276       /* can't kill the process for some unknown reason.  Stop the installation. */
01277       return(TRUE);
01278     }
01279     else if((killProcessTries > 1) &&
01280             (killProcessTries < MAX_KILL_PROCESS_RETRIES) &&
01281             (*processName != '\0'))
01282     {
01283       if(FindAndKillProcess(processName, KP_KILL_PROCESS))
01284       {
01285         ++killProcessTries;
01286         instanceOfFoundProcess = index--;
01287       }
01288       continue;
01289     }
01290 
01291     dwRv0 = GetPrivateProfileString(section, "Class Name",  "", className,  sizeof(className), szFileIniUninstall);
01292     dwRv1 = GetPrivateProfileString(section, "Window Name", "", windowName, sizeof(windowName), szFileIniUninstall);
01293     if((dwRv0 == 0L) && (dwRv1 == 0L) && (*processName == '\0'))
01294     {
01295       bContinue = FALSE;
01296     }
01297     else if((*className != '\0') || (*windowName != '\0'))
01298     {
01299       if(*className == '\0')
01300         szCN = NULL;
01301       else
01302         szCN = className;
01303 
01304       if(*windowName == '\0')
01305         szWN = NULL;
01306       else
01307         szWN = windowName;
01308 
01309       /* If an instance is found, call PreCheckInstance first.
01310        * PreCheckInstance will try to disable the browser's
01311        * QuickLaunch feature. If the browser was in QuickLaunch
01312        * mode without any windows open, PreCheckInstance would
01313        * shutdown the browser, thus a second call to FindAndKillProcess
01314        * is required to see if the process is still around. */
01315       if((hwndFW = FindWindow(szCN, szWN)) != NULL)
01316         PreCheckInstance(section, szFileIniUninstall);
01317 
01318       if((hwndFW = FindWindow(szCN, szWN)) != NULL)
01319       {
01320         GetCheckInstanceQuitMessage(section, message, sizeof(message));
01321         if(*message != '\0')
01322         {
01323           ShowMessageAndQuitProcess(hwndFW, message, msgWait, bCloseAllWindows, processName, CI_CLOSE_PROCESS);
01324           ++killProcessTries;
01325           instanceOfFoundProcess = index--;
01326         }
01327         else
01328         {
01329           /* No message to display.  Assume cancel because we can't allow user to continue */
01330           return(TRUE);
01331         }
01332       }
01333     }
01334 
01335     if((killProcessTries == 0) && (*processName != '\0'))
01336     {
01337       /* The first attempt used FindWindow(), but sometimes the browser can be
01338        * in a state where there's no window open and still not fully shutdown.
01339        * In this case, we need to check for the process itself and kill it. */
01340       if(FindAndKillProcess(processName, KP_DO_NOT_KILL_PROCESS))
01341       {
01342         GetCheckInstanceQuitMessage(section, message, sizeof(message));
01343         if(*message != '\0')
01344         {
01345           ShowMessageAndQuitProcess(hwndFW, message, msgWait, bCloseAllWindows, processName, CI_FORCE_QUIT_PROCESS);
01346           ++killProcessTries;
01347           instanceOfFoundProcess = index--;
01348         }
01349         else
01350         {
01351           /* No message to display.  Assume cancel because we can't allow user to continue */
01352           return(TRUE);
01353         }
01354       }
01355     }
01356   }
01357 
01358   return(FALSE);
01359 }
01360 
01361 BOOL GetFileVersion(LPSTR szFile, verBlock *vbVersion)
01362 {
01363   UINT              uLen;
01364   UINT              dwLen;
01365   BOOL              bRv;
01366   DWORD             dwHandle;
01367   LPVOID            lpData;
01368   LPVOID            lpBuffer;
01369   VS_FIXEDFILEINFO  *lpBuffer2;
01370 
01371   vbVersion->ullMajor   = 0;
01372   vbVersion->ullMinor   = 0;
01373   vbVersion->ullRelease = 0;
01374   vbVersion->ullBuild   = 0;
01375   if(FileExists(szFile))
01376   {
01377     bRv    = TRUE;
01378     dwLen  = GetFileVersionInfoSize(szFile, &dwHandle);
01379     lpData = (LPVOID)malloc(sizeof(long)*dwLen);
01380     uLen   = 0;
01381 
01382     if(GetFileVersionInfo(szFile, dwHandle, dwLen, lpData) != 0)
01383     {
01384       if(VerQueryValue(lpData, "\\", &lpBuffer, &uLen) != 0)
01385       {
01386         lpBuffer2             = (VS_FIXEDFILEINFO *)lpBuffer;
01387         vbVersion->ullMajor   = HIWORD(lpBuffer2->dwFileVersionMS);
01388         vbVersion->ullMinor   = LOWORD(lpBuffer2->dwFileVersionMS);
01389         vbVersion->ullRelease = HIWORD(lpBuffer2->dwFileVersionLS);
01390         vbVersion->ullBuild   = LOWORD(lpBuffer2->dwFileVersionLS);
01391       }
01392     }
01393     free(lpData);
01394   }
01395   else
01396     /* File does not exist */
01397     bRv = FALSE;
01398 
01399   return(bRv);
01400 }
01401 
01402 void TranslateVersionStr(LPSTR szVersion, verBlock *vbVersion)
01403 {
01404   LPSTR szNum1 = NULL;
01405   LPSTR szNum2 = NULL;
01406   LPSTR szNum3 = NULL;
01407   LPSTR szNum4 = NULL;
01408 
01409   szNum1 = strtok(szVersion, ".");
01410   szNum2 = strtok(NULL,      ".");
01411   szNum3 = strtok(NULL,      ".");
01412   szNum4 = strtok(NULL,      ".");
01413 
01414   vbVersion->ullMajor   = _atoi64(szNum1);
01415   vbVersion->ullMinor   = _atoi64(szNum2);
01416   vbVersion->ullRelease = _atoi64(szNum3);
01417   vbVersion->ullBuild   = _atoi64(szNum4);
01418 }
01419 
01420 int CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
01421 {
01422   if(vbVersionOld.ullMajor > vbVersionNew.ullMajor)
01423     return(4);
01424   else if(vbVersionOld.ullMajor < vbVersionNew.ullMajor)
01425     return(-4);
01426 
01427   if(vbVersionOld.ullMinor > vbVersionNew.ullMinor)
01428     return(3);
01429   else if(vbVersionOld.ullMinor < vbVersionNew.ullMinor)
01430     return(-3);
01431 
01432   if(vbVersionOld.ullRelease > vbVersionNew.ullRelease)
01433     return(2);
01434   else if(vbVersionOld.ullRelease < vbVersionNew.ullRelease)
01435     return(-2);
01436 
01437   if(vbVersionOld.ullBuild > vbVersionNew.ullBuild)
01438     return(1);
01439   else if(vbVersionOld.ullBuild < vbVersionNew.ullBuild)
01440     return(-1);
01441 
01442   /* the versions are all the same */
01443   return(0);
01444 }
01445 
01446 BOOL VerifyRestrictedAccess(void)
01447 {
01448   char  szSubKey[MAX_BUF];
01449   char  szSubKeyToTest[] = "Software\\%s - Test Key";
01450   BOOL  bRv;
01451   DWORD dwDisp = 0;
01452   DWORD dwErr;
01453   HKEY  hkRv;
01454 
01455   wsprintf(szSubKey, szSubKeyToTest, ugUninstall.szCompanyName);
01456   dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
01457                          szSubKey,
01458                          0,
01459                          NULL,
01460                          REG_OPTION_NON_VOLATILE,
01461                          KEY_WRITE,
01462                          NULL,
01463                          &hkRv,
01464                          &dwDisp);
01465   if(dwErr == ERROR_SUCCESS)
01466   {
01467     RegCloseKey(hkRv);
01468     switch(dwDisp)
01469     {
01470       case REG_CREATED_NEW_KEY:
01471         RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);
01472         break;
01473 
01474       case REG_OPENED_EXISTING_KEY:
01475         break;
01476     }
01477     bRv = FALSE;
01478   }
01479   else
01480     bRv = TRUE;
01481 
01482   return(bRv);
01483 }
01484 
01485 BOOL CheckLegacy(HWND hDlg)
01486 {
01487   char      szSection[MAX_BUF];
01488   char      szFilename[MAX_BUF];
01489   char      szMessage[MAX_BUF];
01490   char      szIndex[MAX_BUF];
01491   char      szVersionNew[MAX_BUF];
01492   char      szDecryptedFilePath[MAX_BUF];
01493   int       iIndex;
01494   BOOL      bContinue;
01495   DWORD     dwRv0;
01496   DWORD     dwRv1;
01497   verBlock  vbVersionNew;
01498   verBlock  vbVersionOld;
01499 
01500   bContinue = TRUE;
01501   iIndex    = -1;
01502   while(bContinue)
01503   {
01504     ZeroMemory(szFilename,      sizeof(szFilename));
01505     ZeroMemory(szVersionNew,    sizeof(szVersionNew));
01506     ZeroMemory(szMessage,       sizeof(szMessage));
01507 
01508     ++iIndex;
01509     itoa(iIndex, szIndex, 10);
01510     lstrcpy(szSection, "Legacy Check");
01511     lstrcat(szSection, szIndex);
01512 
01513     dwRv0 = GetPrivateProfileString(szSection, "Filename", "", szFilename, MAX_BUF, szFileIniUninstall);
01514     dwRv1 = GetPrivateProfileString(szSection, "Version", "", szVersionNew, MAX_BUF, szFileIniUninstall);
01515     if(dwRv0 == 0L)
01516     {
01517       bContinue = FALSE;
01518     }
01519     else if(*szFilename != '\0')
01520     {
01521       GetPrivateProfileString(szSection, "Message", "", szMessage, MAX_BUF, szFileIniUninstall);
01522       if(*szMessage == '\0')
01523         /* no message string input. so just continue with the next check */
01524         continue;
01525 
01526       DecryptString(szDecryptedFilePath, szFilename);
01527       if((dwRv1 == 0L) || (*szVersionNew == '\0'))
01528       {
01529         if(FileExists(szDecryptedFilePath))
01530         {
01531           char szMBWarningStr[MAX_BUF];
01532 
01533           if(!GetPrivateProfileString("Messages", "MB_WARNING_STR", "",
01534                                       szMBWarningStr, sizeof(szMBWarningStr), 
01535                                       szFileIniUninstall))
01536             lstrcpy(szMBWarningStr, "Warning");
01537 
01538           if(MessageBox(hDlg, szMessage, szMBWarningStr, MB_ICONWARNING | MB_YESNO) == IDYES)
01539             return(TRUE);
01540         }
01541         /* file does not exist, so it's okay.  Continue with the next check */
01542         continue;
01543       }
01544 
01545       if(GetFileVersion(szDecryptedFilePath, &vbVersionOld))
01546       {
01547         TranslateVersionStr(szVersionNew, &vbVersionNew);
01548         if(CompareVersion(vbVersionOld, vbVersionNew) < 0)
01549         {
01550           char szMBWarningStr[MAX_BUF];
01551 
01552           if(!GetPrivateProfileString("Messages", "MB_WARNING_STR", "",
01553                                       szMBWarningStr, sizeof(szMBWarningStr), 
01554                                       szFileIniUninstall))
01555             lstrcpy(szMBWarningStr, "Warning");
01556 
01557           if(MessageBox(hDlg, szMessage, szMBWarningStr, MB_ICONWARNING | MB_YESNO) == IDYES)
01558             return(TRUE);
01559         }
01560       }
01561     }
01562   }
01563   /* returning TRUE means the user wants to go back and choose a different destination path
01564    * returning FALSE means the user is ignoring the warning
01565    */
01566   return(FALSE);
01567 }
01568 
01569 // This function looks up the path for the application being uninstalled, NOT the client
01570 //   app in a shared install environment.
01571 HRESULT GetAppPath()
01572 {
01573   char szTmpAppPath[MAX_BUF];
01574   char szKey[MAX_BUF];
01575   BOOL bRestrictedAccess;
01576   HKEY hkRoot;
01577 
01578   if(*ugUninstall.szUserAgent != '\0')
01579   {
01580     hkRoot = ugUninstall.hWrMainRoot;
01581     wsprintf(szKey, "%s\\%s\\Main", ugUninstall.szWrMainKey, ugUninstall.szUserAgent);
01582   }
01583   else
01584   {
01585     hkRoot = ugUninstall.hWrRoot;
01586     strcpy(szKey, ugUninstall.szWrKey);
01587   }
01588 
01589   bRestrictedAccess = VerifyRestrictedAccess();
01590   if(bRestrictedAccess)
01591     hkRoot = HKEY_CURRENT_USER;
01592 
01593   GetWinReg(hkRoot, szKey, "PathToExe", szTmpAppPath, sizeof(szTmpAppPath));
01594   if(FileExists(szTmpAppPath))
01595     lstrcpy(ugUninstall.szAppPath, szTmpAppPath);
01596 
01597   GetWinReg(hkRoot, szKey, "Install Directory", ugUninstall.szInstallPath, sizeof(ugUninstall.szInstallPath));
01598 
01599   return(0);
01600 }
01601 
01602 // For shared installs we maintain an app list, which is a glorified
01603 //   refcount of the apps which are using this version of the 
01604 //   shared app.  Processing the app list does two things:
01605 //
01606 //   1) Cleans up any registry entries for apps which are no longer
01607 //      installed.  The app list includes a representative file for
01608 //      each app.  If that file is not installed than the app is 
01609 //      assumed to have been removed from the system.
01610 //   2) Returns a count of the installed apps which depend upon this
01611 //      shared app.  If this app is not shared, there will be no app
01612 //      list so this will always return 0.
01613 DWORD CleanupAppList()
01614 {
01615   typedef struct siAppListStruct siAppList;
01616   struct siAppListStruct
01617   {
01618     char szAppID[MAX_BUF];
01619     siAppList *Next;
01620   };
01621 
01622   siAppList *siALHead;
01623   siAppList *siALPrev;
01624   siAppList *siALTmp;
01625 
01626   char      *szRv = NULL;
01627   char      szKey[MAX_BUF];
01628   char      szBuf[MAX_BUF];
01629   char      szDefaultApp[MAX_BUF_TINY];
01630   BOOL      bFoundDefaultApp;
01631   HKEY      hkResult;
01632   DWORD     dwIndex;
01633   DWORD     dwBufSize;
01634   DWORD     dwTotalSubKeys;
01635   DWORD     dwTotalValues;
01636   DWORD     dwAppCount;
01637   FILETIME  ftLastWriteFileTime;
01638 
01639   GetPrivateProfileString("General", "Default AppID", "", szDefaultApp, MAX_BUF_TINY, szFileIniUninstall);
01640   wsprintf(szKey, "%s\\%s\\AppList", ugUninstall.szWrMainKey, ugUninstall.szUserAgent);
01641   if(RegOpenKeyEx(ugUninstall.hWrMainRoot, szKey, 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
01642   {
01643     return(0);
01644   }
01645 
01646   siALHead = NULL;
01647   dwAppCount = 0;
01648   dwTotalSubKeys = 0;
01649   dwTotalValues  = 0;
01650   RegQueryInfoKey(hkResult, NULL, NULL, NULL, &dwTotalSubKeys, NULL, NULL, &dwTotalValues, NULL, NULL, NULL, NULL);
01651 
01652   for(dwIndex = 0; dwIndex < dwTotalSubKeys; dwIndex++)
01653   {
01654     dwBufSize = sizeof(szBuf);
01655     if(RegEnumKeyEx(hkResult, dwIndex, szBuf, &dwBufSize, NULL, NULL, NULL, &ftLastWriteFileTime) == ERROR_SUCCESS)
01656     {
01657       if((siALTmp = NS_GlobalAlloc(sizeof(struct siAppListStruct))) == NULL)
01658         exit(1);
01659       lstrcpy(siALTmp->szAppID, szBuf);
01660       siALTmp->Next = NULL;
01661 
01662       if(siALHead == NULL)
01663         siALHead = siALTmp; //New list, point the head at it.
01664       else
01665         siALPrev->Next = siALTmp;
01666 
01667       siALPrev = siALTmp;
01668     }
01669   }
01670   RegCloseKey(hkResult);
01671 
01672   siALTmp = siALHead;
01673   while(siALTmp != NULL)
01674   {
01675     if(lstrcmpi(siALTmp->szAppID, szDefaultApp) == 0)
01676       bFoundDefaultApp = TRUE;
01677 
01678     // ProcessAppItem returns the # of installations of the App
01679     dwAppCount = dwAppCount + ProcessAppItem(ugUninstall.hWrMainRoot, szKey, siALTmp->szAppID);
01680 
01681     siALPrev = siALTmp;
01682     siALTmp = siALTmp->Next;
01683     FreeMemory(&siALPrev);
01684   }
01685 
01686   if(dwAppCount == 0)
01687     RegDeleteKey(ugUninstall.hWrMainRoot, szKey);
01688 
01689   // If the Default App is not listed in AppList, then the shared app should not be in the 
01690   //   Windows Add/Remove Programs list either.
01691   if(!bFoundDefaultApp)
01692   {
01693     wsprintf(szKey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s (%s)",ugUninstall.szProductName, ugUninstall.szUserAgent);
01694     RegDeleteKey(ugUninstall.hWrMainRoot, szKey);
01695   }
01696 
01697   return(dwAppCount);
01698 }
01699 
01700 
01701 // Removes the app item if it is the app identified with the /app command-line option
01702 // If an app item is not installed this removes it from the app list.
01703 // Returns the # of installations of the app item found in the AppList.
01704 DWORD ProcessAppItem(HKEY hkRootKey, LPSTR szKeyAppList, LPSTR szAppID)
01705 {
01706   DWORD dwIndex = 1;
01707   const DWORD dwUpperLimit = 100;
01708   BOOL  bDefaultApp;
01709   char szBuf[MAX_BUF];
01710   char szKey[MAX_BUF];
01711   char szName[MAX_BUF];
01712   char szUninstKey[MAX_BUF];
01713 
01714   GetPrivateProfileString("General", "Default AppID", "", szBuf, sizeof(szBuf), szFileIniUninstall);
01715   bDefaultApp = (lstrcmpi(szAppID, szBuf) == 0);
01716 
01717   wsprintf(szKey, "%s\\%s", szKeyAppList, szAppID);
01718 
01719   if(lstrcmpi(szAppID, ugUninstall.szClientAppID) == 0) // This is the app that the user said 
01720   {                                                     // on the command-line to uninstall.
01721     if((ugUninstall.szClientAppPath[0] == '\0') || (bDefaultApp)) // If we didn't get an /app_path or this
01722     {                                                             // is the default app, just remove it.
01723       RegDeleteKey(hkRootKey, szKey);
01724       if(bDefaultApp)
01725       {
01726         wsprintf(szKey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\GRE (%s)", ugUninstall.szUserAgent);
01727         RegDeleteKey(hkRootKey, szKey);
01728       }
01729 
01730       return 0;
01731     }
01732 
01733     wsprintf(szName, "PathToExe%02d", dwIndex);
01734     while(WinRegNameExists(hkRootKey, szKey, szName) && // Since we got an /app_path we need to cycle
01735          (dwIndex < dwUpperLimit))                      // through the list looking for that instance.
01736     {
01737       GetWinReg(hkRootKey, szKey, szName, szBuf, sizeof(szBuf));
01738       if((lstrcmpi(szBuf, ugUninstall.szClientAppPath) == 0) || (!FileExists(szBuf)))
01739       {
01740         // RemovePathToExeXX() will delete the dwIndex Name and reorder
01741         // PathToExeXX so there are no gaps.
01742         RemovePathToExeXX(hkRootKey, szKey, dwIndex, dwUpperLimit);
01743       }
01744       else
01745         wsprintf(szName, "PathToExe%02d", ++dwIndex);
01746     }
01747 
01748     if(--dwIndex == 0)
01749       RegDeleteKey(hkRootKey, szKey);
01750 
01751     return dwIndex;
01752   }
01753 
01754   if(bDefaultApp) // The Default App does not have an installed file registered.  However, an entry in 
01755   {               // the Windows Add/Remove products list indicates that the Default App is installed
01756                   // and needs to be counted.
01757     wsprintf(szUninstKey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s (%s)",ugUninstall.szProductName, ugUninstall.szUserAgent);
01758     GetWinReg(hkRootKey, szUninstKey, "UninstallString", szBuf, sizeof(szBuf));
01759 
01760     if(szBuf[0] != '\0')
01761       return 1;
01762   }
01763 
01764   dwIndex = 1;
01765   wsprintf(szName, "PathToExe%02d", dwIndex);
01766   while(WinRegNameExists(hkRootKey, szKey, szName) && // Count the entries which can be verified by the
01767        (dwIndex < dwUpperLimit))                      // existence of the file pointed to by PathToExeXX
01768   {
01769     GetWinReg(hkRootKey, szKey, szName, szBuf, sizeof(szBuf));
01770     if(!FileExists(szBuf))    
01771     {
01772       // RemovePathToExeXX() will delete the dwIndex Name and reorder
01773       // PathToExeXX so there are no gaps.
01774       RemovePathToExeXX(hkRootKey, szKey, dwIndex, dwUpperLimit);
01775     }
01776     else
01777       wsprintf(szName, "PathToExe%02d", ++dwIndex);
01778   }
01779 
01780   if(--dwIndex == 0)
01781     RegDeleteKey(hkRootKey, szKey);
01782 
01783   return dwIndex;
01784 }
01785 
01786 void RemovePathToExeXX(HKEY hkRootKey, LPSTR szKey, DWORD dwIndex, const DWORD dwUpperLimit)
01787 {
01788   char szBuf[MAX_BUF_TINY];
01789   char szName[MAX_BUF_TINY];
01790   char szNextName[MAX_BUF_TINY];
01791 
01792   wsprintf(szName,     "PathToExe%02d", dwIndex++);
01793   wsprintf(szNextName, "PathToExe%02d", dwIndex);
01794   while(WinRegNameExists(hkRootKey, szKey, szNextName) && (dwIndex < dwUpperLimit))
01795   {
01796     GetWinReg(hkRootKey, szKey, szNextName, szBuf, sizeof(szBuf));
01797     SetWinReg(hkRootKey, szKey, szName, REG_SZ, szBuf, lstrlen(szBuf));
01798     lstrcpy(szName, szNextName);
01799     wsprintf(szNextName, "PathToExe%02d", ++dwIndex);
01800   }        
01801 
01802   DeleteWinRegValue(hkRootKey, szKey, szName);
01803 }
01804 
01805 /* Function: ReplacePrivateProfileStrCR()
01806  *
01807  *       in: LPSTR aInputOutputStr: In/out string to containing "\\n" to replace.
01808  *           
01809  *  purpose: To parse for and replace "\\n" string with "\n".  Strings stored
01810  *           in .ini files cannot contain "\n" because it's a key delimiter.
01811  *           To work around this limination, "\\n" chars can be used to
01812  *           represent '\n'.  This function will look for "\\n" and replace
01813  *           them with a true "\n".
01814  *           If it encounters a string of "\\\\n" (which looks like '\\n'),
01815  *           then this function will strip out the extra '\\' and just show
01816  *           "\\n";
01817  */
01818 void ReplacePrivateProfileStrCR(LPSTR aInputOutputStr)
01819 {
01820   LPSTR pSearch          = aInputOutputStr;
01821   LPSTR pSearchEnd       = aInputOutputStr + lstrlen(aInputOutputStr);
01822   LPSTR pPreviousSearch  = NULL;
01823 
01824   while (pSearch < pSearchEnd)
01825   {
01826     if (('\\' == *pSearch) || ('n' == *pSearch))
01827     {
01828       // found a '\\' or 'n'.  check to see if  the prefivous char is also a '\\'.
01829       if (pPreviousSearch && ('\\' == *pPreviousSearch))
01830       {
01831         if ('n' == *pSearch)
01832           *pSearch = '\n';
01833 
01834         memmove(pPreviousSearch, pSearch, pSearchEnd-pSearch+1);
01835 
01836         // our string is shorter now ...
01837         pSearchEnd -= pSearch - pPreviousSearch;
01838       }
01839     }
01840 
01841     pPreviousSearch = pSearch;
01842     pSearch = CharNext(pSearch);
01843   }
01844 }
01845 
01846 /* Function: IsPathWithinWindir()
01847  *       in: char *aTargetPath
01848  *      out: returns a BOOL type indicating whether the install path chosen
01849  *           by the user is within the %windir% or not.
01850  *  purpose: To see if aTargetPath is within the %windir% path.
01851  */
01852 BOOL IsPathWithinWindir(char *aTargetPath)
01853 {
01854   char    windir[MAX_PATH];
01855   char    targetPath[MAX_PATH];
01856   HRESULT rv;
01857 
01858   assert(aTargetPath);
01859 
01860   rv = GetWindowsDirectory(windir, sizeof(windir));
01861   assert(rv);
01862   MozCopyStr(aTargetPath, targetPath, sizeof(targetPath));
01863   RemoveBackSlash(targetPath);
01864   CharUpperBuff(targetPath, sizeof(targetPath));
01865   RemoveBackSlash(windir);
01866   CharUpperBuff(windir, sizeof(windir));
01867 
01868   if(strstr(targetPath, windir))
01869     return(TRUE);
01870 
01871   return(FALSE);
01872 }
01873 
01874 /* Function: VerifyAndDeleteInstallationFolder()
01875  *       in: none
01876  *      out: none
01877  *  purpose: To verify that the installation folder has been completely
01878  *           deleted, else prompt the user if they would like to delete
01879  *           the folder and it's left over contents.
01880  *           It will also check to make sure that the installation
01881  *           folder is not within the %windir% folder.  If it is,
01882  *           it will warn the user and not perform the deletion of the
01883  *           installation folder.
01884  */
01885 void VerifyAndDeleteInstallationFolder()
01886 {
01887   if(FileExists(ugUninstall.szInstallPath))
01888   {
01889     char buf[MAX_BUF];
01890     char msg[MAX_BUF];
01891     char msgBoxTitle[MAX_BUF];
01892     char installationPath[MAX_BUF];
01893 
01894     MozCopyStr(ugUninstall.szInstallPath, installationPath, sizeof(installationPath));
01895     RemoveBackSlash(installationPath);
01896 
01897     if(ugUninstall.mode == NORMAL)
01898     {
01899       GetPrivateProfileString("Messages", "MB_ATTENTION_STR", "", msgBoxTitle, sizeof(msgBoxTitle), szFileIniUninstall);
01900       GetPrivateProfileString("Messages", "MSG_DELETE_INSTALLATION_PATH", "", buf, sizeof(buf), szFileIniUninstall);
01901       ReplacePrivateProfileStrCR(buf);
01902       _snprintf(msg, sizeof(msg), buf, installationPath);
01903       msg[sizeof(msg) - 1] = '\0';
01904 
01905       /* Prompt user on if they want the completely remove the
01906        * installation folder */
01907       if(MessageBox(hWndMain, msg, msgBoxTitle, MB_ICONQUESTION | MB_YESNO) == IDYES)
01908       {
01909         if(IsPathWithinWindir(installationPath))
01910         {
01911           GetPrivateProfileString("Messages", "MSG_INSTALLATION_PATH_WITHIN_WINDIR",
01912               "", msg, sizeof(msg), szFileIniUninstall);
01913           MessageBox(hWndMain, msg, NULL, MB_ICONEXCLAMATION);
01914           return;
01915         }
01916 
01917         /* Remove the installation folder here */
01918         AppendBackSlash(installationPath, sizeof(installationPath));
01919         DirectoryRemove(installationPath, TRUE);
01920       }
01921     }
01922     else
01923     {
01924       /* If uninstall is running in !NORMAL mode, assume user wants to
01925        * completely delete the installation folder */
01926       AppendBackSlash(installationPath, sizeof(installationPath));
01927       DirectoryRemove(installationPath, TRUE);
01928     }
01929   }
01930 }
01931 
01932 HRESULT GetUninstallLogPath()
01933 {
01934   char szBuf[MAX_BUF];
01935   char szLogFolder[MAX_BUF];
01936   char szKey[MAX_BUF];
01937   char szWindowsUninstallKey[MAX_BUF];
01938   char szErrorMsg[MAX_BUF];
01939   char szEUninstallLogFolder[MAX_BUF];
01940   char szRootKey[MAX_BUF];
01941   BOOL bRestrictedAccess;
01942   HKEY hkRoot;
01943 
01944   if(*ugUninstall.szUserAgent != '\0')
01945   {
01946     hkRoot = ugUninstall.hWrMainRoot;
01947     lstrcpy(szKey, ugUninstall.szWrMainKey);
01948     AppendBackSlash(szKey, sizeof(szKey));
01949     lstrcat(szKey, ugUninstall.szUserAgent);
01950     AppendBackSlash(szKey, sizeof(szKey));
01951     lstrcat(szKey, "Uninstall");
01952   }
01953   else
01954   {
01955     hkRoot = ugUninstall.hWrRoot;
01956     strcpy(szKey, ugUninstall.szWrKey);
01957   }
01958 
01959   bRestrictedAccess = VerifyRestrictedAccess();
01960   if(bRestrictedAccess)
01961     hkRoot = HKEY_CURRENT_USER;
01962 
01963   GetWinReg(hkRoot, szKey, "Uninstall Log Folder",   szLogFolder, sizeof(szLogFolder));
01964   GetWinReg(hkRoot, szKey, "Description",            ugUninstall.szUninstallKeyDescription, MAX_BUF);
01965 
01966   if(!bRestrictedAccess)
01967   {
01968     lstrcpy(szWindowsUninstallKey, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
01969     lstrcat(szWindowsUninstallKey, ugUninstall.szUninstallKeyDescription);
01970     GetWinReg(HKEY_LOCAL_MACHINE, szWindowsUninstallKey, "DisplayName", ugUninstall.szDescription, MAX_BUF);
01971   }
01972 
01973   /* if the DisplayName was not found in the windows registry,
01974    * use the description read in from config.ini file */
01975   if(*ugUninstall.szDescription == '\0')
01976     lstrcpy(ugUninstall.szDescription, ugUninstall.szUninstallKeyDescription);
01977 
01978   if(FileExists(szLogFolder) == FALSE)
01979   {
01980     if(GetPrivateProfileString("Messages", "ERROR_UNINSTALL_LOG_FOLDER", "",
01981                                szEUninstallLogFolder, sizeof(szEUninstallLogFolder), 
01982                                szFileIniUninstall))
01983     {
01984       lstrcpy(szBuf, "\n\n    ");
01985 
01986       if(*szLogFolder == '\0')
01987       {
01988         GetStringRootKey(hkRoot, szRootKey, sizeof(szRootKey));
01989         lstrcat(szBuf, szRootKey);
01990         lstrcat(szBuf, "\\");
01991         lstrcat(szBuf, szKey);
01992         lstrcat(szBuf, "\\Uninstall Log Folder");
01993       }
01994       else
01995         lstrcat(szBuf, szLogFolder);
01996 
01997       lstrcat(szBuf, "\n");
01998       wsprintf(szErrorMsg, szEUninstallLogFolder, szBuf);
01999       PrintError(szErrorMsg, ERROR_CODE_SHOW);
02000     }
02001 
02002     return(1);
02003   }
02004   lstrcpy(ugUninstall.szLogPath, szLogFolder);
02005 
02006   return(0);
02007 }
02008 
02009 HRESULT ParseUninstallIni()
02010 {
02011   char szBuf[MAX_BUF];
02012   char szKeyCrypted[MAX_BUF];
02013   char szShowDialog[MAX_BUF];
02014   LOGFONT lf;
02015   char fontName[MAX_BUF];
02016   char fontSize[MAX_BUF];
02017   char charSet[MAX_BUF];
02018 
02019   lstrcpy(ugUninstall.szLogFilename, FILE_LOG_INSTALL);
02020 
02021   GetPrivateProfileString("General", "Shared Install", "", szBuf, MAX_BUF, szFileIniUninstall);
02022   ugUninstall.bSharedInst = (lstrcmpi(szBuf, "TRUE") == 0);
02023 
02024   /* get install Mode information */
02025   GetPrivateProfileString("General", "Run Mode", "", szBuf, MAX_BUF, szFileIniUninstall);
02026   SetUninstallRunMode(szBuf);
02027 
02028   if((ugUninstall.mode != SHOWICONS) && (ugUninstall.mode != HIDEICONS) && (ugUninstall.mode != SETDEFAULT))
02029     if(CheckInstances())
02030       return(1);
02031   if(InitDlgUninstall(&diUninstall))
02032     return(1);
02033  
02034   /* get product name description */
02035   GetPrivateProfileString("General", "Company Name", "", ugUninstall.szCompanyName, MAX_BUF, szFileIniUninstall);
02036   GetPrivateProfileString("General", "Product Name", "", ugUninstall.szProductName, MAX_BUF, szFileIniUninstall);
02037   GetPrivateProfileString("General", "Root Key",     "", szBuf, MAX_BUF, szFileIniUninstall);
02038   ugUninstall.hWrRoot = ParseRootKey(szBuf);
02039 
02040   GetPrivateProfileString("General", "Key",          "", szKeyCrypted, MAX_BUF, szFileIniUninstall);
02041   GetPrivateProfileString("General", "Decrypt Key",  "", szBuf, MAX_BUF, szFileIniUninstall);
02042   if(lstrcmpi(szBuf, "TRUE") == 0)
02043   {
02044     DecryptString(ugUninstall.szWrKey, szKeyCrypted);
02045   }
02046   else
02047     strcpy(ugUninstall.szWrKey, szKeyCrypted);
02048 
02049   RemoveBackSlash(ugUninstall.szWrKey);
02050 
02051   GetPrivateProfileString("General", "Main Root Key",    "", szBuf, MAX_BUF, szFileIniUninstall);
02052   ugUninstall.hWrMainRoot = ParseRootKey(szBuf);
02053 
02054   GetPrivateProfileString("General", "Main Key",         "", szKeyCrypted, MAX_BUF, szFileIniUninstall);
02055   GetPrivateProfileString("General", "Decrypt Main Key", "", szBuf, MAX_BUF, szFileIniUninstall);
02056 
02057   // If szWrMainKey is not null then it was set on the command-line and that is
02058   //    what we want to use.
02059   if(*ugUninstall.szWrMainKey == '\0') 
02060   {
02061     if(lstrcmpi(szBuf, "TRUE") == 0)
02062     {
02063       DecryptString(ugUninstall.szWrMainKey, szKeyCrypted);
02064     }
02065     else
02066       strcpy(ugUninstall.szWrMainKey, szKeyCrypted);
02067   }
02068 
02069   RemoveBackSlash(ugUninstall.szWrMainKey);
02070 
02071   GetPrivateProfileString("General", "Uninstall Filename", "", ugUninstall.szUninstallFilename, MAX_BUF, szFileIniUninstall);
02072 
02073 
02074   /* Uninstall dialog */
02075   GetPrivateProfileString("Dialog Uninstall",       "Show Dialog",  "", szShowDialog,                 MAX_BUF, szFileIniUninstall);
02076   GetPrivateProfileString("Dialog Uninstall",       "Title",        "", diUninstall.szTitle,          MAX_BUF, szFileIniUninstall);
02077   GetPrivateProfileString("Dialog Uninstall",       "Message0",     "", diUninstall.szMessage0,       MAX_BUF, szFileIniUninstall);
02078   if(lstrcmpi(szShowDialog, "TRUE") == 0)
02079     diUninstall.bShowDialog = TRUE;
02080 
02081   switch(ugUninstall.mode)
02082   {
02083     case AUTO:
02084     case SILENT:
02085     case SHOWICONS:
02086     case HIDEICONS:
02087     case SETDEFAULT:
02088       gdwWhatToDo             = WTD_NO_TO_ALL;
02089       diUninstall.bShowDialog = FALSE;
02090       break;
02091   }
02092 
02093   /* get defined font */
02094   GetPrivateProfileString("Dialog Uninstall", "FONTNAME", "", fontName, MAX_BUF, szFileIniUninstall);
02095   GetPrivateProfileString("Dialog Uninstall", "FONTSIZE", "", fontSize, MAX_BUF, szFileIniUninstall);
02096   GetPrivateProfileString("Dialog Uninstall", "CHARSET", "", charSet, MAX_BUF, szFileIniUninstall);
02097   memset(&lf, 0, sizeof(lf));
02098   strcpy(lf.lfFaceName, fontName);
02099   lf.lfHeight = -MulDiv(atoi(fontSize), GetDeviceCaps(GetDC(NULL), LOGPIXELSY), 72);
02100   lf.lfCharSet = atoi(charSet);
02101   ugUninstall.definedFont = CreateFontIndirect( &lf ); 
02102 
02103   GetAppPath();
02104 
02105 
02106   if(ugUninstall.bSharedInst)
02107   {
02108     // Shared installations require a user agent.  Without one there is no way to know 
02109     //   what version of GRE to clean up so we can't do anything--including CleanupAppList()
02110     //   so don't change the order of the if statement.  
02111     //   (We should add UI warning the user when a required UserAgent is not supplied.)
02112     // CleanupAppList() returns the number of installations of apps dependant on this shared app.
02113     if((ugUninstall.szUserAgent[0] == '\0') || (CleanupAppList() != 0))
02114       ugUninstall.bUninstallFiles = FALSE;
02115   }
02116 
02117   return(GetUninstallLogPath());
02118 }
02119 
02120 void GetWinReg(HKEY hkRootKey, LPSTR szKey, LPSTR szName, LPSTR szReturnValue, DWORD dwReturnValueSize)
02121 {
02122   HKEY  hkResult;
02123   DWORD dwErr;
02124   DWORD dwSize;
02125   char  szBuf[MAX_BUF];
02126 
02127   ZeroMemory(szBuf, sizeof(szBuf));
02128   ZeroMemory(szReturnValue, dwReturnValueSize);
02129 
02130   if((dwErr = RegOpenKeyEx(hkRootKey, szKey, 0, KEY_READ, &hkResult)) == ERROR_SUCCESS)
02131   {
02132     dwSize = sizeof(szBuf);
02133     dwErr = RegQueryValueEx(hkResult, szName, 0, NULL, szBuf, &dwSize);
02134 
02135     if((*szBuf != '\0') && (dwErr == ERROR_SUCCESS))
02136       ExpandEnvironmentStrings(szBuf, szReturnValue, dwReturnValueSize);
02137     else
02138       *szReturnValue = '\0';
02139 
02140     RegCloseKey(hkResult);
02141   }
02142 }
02143 
02144 void SetWinReg(HKEY hkRootKey, LPSTR szKey, LPSTR szName, DWORD dwType, LPSTR szData, DWORD dwSize)
02145 {
02146   HKEY    hkResult;
02147   DWORD   dwErr;
02148   DWORD   dwDisp;
02149   char    szBuf[MAX_BUF];
02150 
02151   memset(szBuf, '\0', MAX_BUF);
02152 
02153   dwErr = RegOpenKeyEx(hkRootKey, szKey, 0, KEY_WRITE, &hkResult);
02154   if(dwErr != ERROR_SUCCESS)
02155     dwErr = RegCreateKeyEx(hkRootKey, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkResult, &dwDisp);
02156 
02157   if(dwErr == ERROR_SUCCESS)
02158   {
02159     dwErr = RegSetValueEx(hkResult, szName, 0, dwType, szData, dwSize);
02160 
02161     RegCloseKey(hkResult);
02162   }
02163 }
02164 
02165 void SetWinRegNumValue(HKEY hkRootKey, LPSTR szKey, LPSTR szName, DWORD dwData)
02166 {
02167   HKEY    hkResult;
02168   DWORD   dwErr;
02169   DWORD   dwDisp;
02170   DWORD   dwVal;
02171   DWORD   dwValSize;
02172 
02173   dwVal = dwData;
02174   dwValSize = sizeof(DWORD);
02175 
02176   dwErr = RegOpenKeyEx(hkRootKey, szKey, 0, KEY_WRITE, &hkResult);
02177   if(dwErr != ERROR_SUCCESS)
02178     dwErr = RegCreateKeyEx(hkRootKey, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkResult, &dwDisp);
02179 
02180   if(dwErr == ERROR_SUCCESS)
02181   {
02182     dwErr = RegSetValueEx(hkResult, szName, 0, REG_DWORD, (LPBYTE)&dwVal, dwValSize);
02183 
02184     RegCloseKey(hkResult);
02185   }
02186 }
02187 
02188 HRESULT DecryptVariable(LPSTR szVariable, DWORD dwVariableSize)
02189 {
02190   char szBuf[MAX_BUF];
02191   char szKey[MAX_BUF];
02192   char szName[MAX_BUF];
02193   char szValue[MAX_BUF];
02194 
02195   /* zero out the memory allocations */
02196   ZeroMemory(szBuf,       sizeof(szBuf));
02197   ZeroMemory(szKey,       sizeof(szKey));
02198   ZeroMemory(szName,      sizeof(szName));
02199   ZeroMemory(szValue,     sizeof(szValue));
02200 
02201   if(lstrcmpi(szVariable, "PROGRAMFILESDIR") == 0)
02202   {
02203     /* parse for the "c:\Program Files" directory */
02204     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "ProgramFilesDir", szVariable, dwVariableSize);
02205     /* see if that failed */
02206     if (*szVariable == 0)
02207     {
02208       char* backslash;
02209       /* Use the parent of the windows directory */
02210       GetWindowsDirectory(szVariable, dwVariableSize);
02211       backslash = strrchr(szVariable, '\\');
02212       if (backslash)
02213         *backslash = 0;
02214     }
02215   }
02216   else if(lstrcmpi(szVariable, "COMMONFILESDIR") == 0)
02217   {
02218     /* parse for the "c:\Program Files\Common Files" directory */
02219     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "CommonFilesDir", szVariable, dwVariableSize);
02220   }
02221   else if(lstrcmpi(szVariable, "MEDIAPATH") == 0)
02222   {
02223     /* parse for the "c:\Winnt40\Media" directory */
02224     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "MediaPath", szVariable, dwVariableSize);
02225   }
02226   else if(lstrcmpi(szVariable, "CONFIGPATH") == 0)
02227   {
02228     /* parse for the "c:\Windows\Config" directory */
02229     if(ulOSType & OS_WIN9x)
02230     {
02231       GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "ConfigPath", szVariable, dwVariableSize);
02232     }
02233   }
02234   else if(lstrcmpi(szVariable, "DEVICEPATH") == 0)
02235   {
02236     /* parse for the "c:\Winnt40\INF" directory */
02237     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", "DevicePath", szVariable, dwVariableSize);
02238   }
02239   else if(lstrcmpi(szVariable, "COMMON_STARTUP") == 0)
02240   {
02241     /* parse for the "C:\WINNT40\Profiles\All Users\Start Menu\\Programs\\Startup" directory */
02242     if(ulOSType & OS_WIN9x)
02243     {
02244       GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Startup", szVariable, dwVariableSize);
02245     }
02246     else
02247     {
02248       GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Startup", szVariable, dwVariableSize);
02249     }
02250   }
02251   else if(lstrcmpi(szVariable, "COMMON_PROGRAMS") == 0)
02252   {
02253     /* parse for the "C:\WINNT40\Profiles\All Users\Start Menu\\Programs" directory */
02254     if(ulOSType & OS_WIN9x)
02255     {
02256       GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Programs", szVariable, dwVariableSize);
02257     }
02258     else
02259     {
02260       GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Programs", szVariable, dwVariableSize);
02261     }
02262   }
02263   else if(lstrcmpi(szVariable, "COMMON_STARTMENU") == 0)
02264   {
02265     /* parse for the "C:\WINNT40\Profiles\All Users\Start Menu" directory */
02266     if(ulOSType & OS_WIN9x)
02267     {
02268       GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Start Menu", szVariable, dwVariableSize);
02269     }
02270     else
02271     {
02272       GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Start Menu", szVariable, dwVariableSize);
02273     }
02274   }
02275   else if(lstrcmpi(szVariable, "COMMON_DESKTOP") == 0)
02276   {
02277     /* parse for the "C:\WINNT40\Profiles\All Users\Desktop" directory */
02278     if(ulOSType & OS_WIN9x)
02279     {
02280       GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Desktop", szVariable, dwVariableSize);
02281     }
02282     else
02283     {
02284       GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Common Desktop", szVariable, dwVariableSize);
02285     }
02286   }
02287   else if(lstrcmpi(szVariable, "PERSONAL_STARTUP") == 0)
02288   {
02289     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Start Menu\Programs\Startup" directory */
02290     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Startup", szVariable, dwVariableSize);
02291   }
02292   else if(lstrcmpi(szVariable, "PERSONAL_PROGRAMS") == 0)
02293   {
02294     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Start Menu\Programs" directory */
02295     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Programs", szVariable, dwVariableSize);
02296   }
02297   else if(lstrcmpi(szVariable, "PERSONAL_STARTMENU") == 0)
02298   {
02299     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Start Menu" directory */
02300     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Start Menu", szVariable, dwVariableSize);
02301   }
02302   else if(lstrcmpi(szVariable, "PERSONAL_DESKTOP") == 0)
02303   {
02304     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Desktop" directory */
02305     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Desktop", szVariable, dwVariableSize);
02306   }
02307   else if(lstrcmpi(szVariable, "PERSONAL_APPDATA") == 0)
02308   {
02309     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Application Data" directory */
02310     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "AppData", szVariable, dwVariableSize);
02311   }
02312   else if(lstrcmpi(szVariable, "PERSONAL_CACHE") == 0)
02313   {
02314     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Temporary Internet Files" directory */
02315     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Cache", szVariable, dwVariableSize);
02316   }
02317   else if(lstrcmpi(szVariable, "PERSONAL_COOKIES") == 0)
02318   {
02319     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Cookies" directory */
02320     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Cookies", szVariable, dwVariableSize);
02321   }
02322   else if(lstrcmpi(szVariable, "PERSONAL_FAVORITES") == 0)
02323   {
02324     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Favorites" directory */
02325     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Favorites", szVariable, dwVariableSize);
02326   }
02327   else if(lstrcmpi(szVariable, "PERSONAL_FONTS") == 0)
02328   {
02329     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Fonts" directory */
02330     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Fonts", szVariable, dwVariableSize);
02331   }
02332   else if(lstrcmpi(szVariable, "PERSONAL_HISTORY") == 0)
02333   {
02334     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\History" directory */
02335     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "History", szVariable, dwVariableSize);
02336   }
02337   else if(lstrcmpi(szVariable, "PERSONAL_NETHOOD") == 0)
02338   {
02339     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\NetHood" directory */
02340     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "NetHood", szVariable, dwVariableSize);
02341   }
02342   else if(lstrcmpi(szVariable, "PERSONAL_PERSONAL") == 0)
02343   {
02344     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Personal" directory */
02345     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Personal", szVariable, dwVariableSize);
02346   }
02347   else if(lstrcmpi(szVariable, "PERSONAL_PRINTHOOD") == 0)
02348   {
02349     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\PrintHood" directory */
02350     if(ulOSType & OS_NT)
02351     {
02352       GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "PrintHood", szVariable, dwVariableSize);
02353     }
02354   }
02355   else if(lstrcmpi(szVariable, "PERSONAL_RECENT") == 0)
02356   {
02357     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\Recent" directory */
02358     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Recent", szVariable, dwVariableSize);
02359   }
02360   else if(lstrcmpi(szVariable, "PERSONAL_SENDTO") == 0)
02361   {
02362     /* parse for the "C:\WINNT40\Profiles\%USERNAME%\SendTo" directory */
02363     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "SendTo", szVariable, dwVariableSize);
02364   }
02365   else if(lstrcmpi(szVariable, "PERSONAL_TEMPLATES") == 0)
02366   {
02367     /* parse for the "C:\WINNT40\ShellNew" directory */
02368     GetWinReg(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Templates", szVariable, dwVariableSize);
02369   }
02370   else if(lstrcmpi(szVariable, "WIZTEMP") == 0)
02371   {
02372     /* parse for the "c:\Temp" path */
02373     lstrcpy(szVariable, szTempDir);
02374     if(szVariable[strlen(szVariable) - 1] == '\\')
02375       szVariable[strlen(szVariable) - 1] = '\0';
02376   }
02377   else if(lstrcmpi(szVariable, "TEMP") == 0)
02378   {
02379     /* parse for the "c:\Temp" path */
02380     lstrcpy(szVariable, szOSTempDir);
02381     if(szVariable[strlen(szVariable) - 1] == '\\')
02382       szVariable[strlen(szVariable) - 1] = '\0';
02383   }
02384   else if(lstrcmpi(szVariable, "WINDISK") == 0)
02385   {
02386     /* Locate the drive that Windows is installed on, and only use the drive letter and the ':' character (C:). */
02387     if(GetWindowsDirectory(szBuf, MAX_BUF) == 0)
02388     {
02389       char szEGetWinDirFailed[MAX_BUF];
02390 
02391       if(GetPrivateProfileString("Messages", "ERROR_GET_WINDOWS_DIRECTORY_FAILED", "",
02392                                  szEGetWinDirFailed, sizeof(szEGetWinDirFailed), 
02393                                  szFileIniUninstall))
02394         PrintError(szEGetWinDirFailed, ERROR_CODE_SHOW);
02395 
02396       exit(1);
02397     }
02398     else
02399     {
02400       /* Copy the first 2 characters from the path..        */
02401       /* This is the drive letter and the ':' character for */
02402       /* where Windows is installed at.                     */
02403       memset(szVariable, '\0', MAX_BUF);
02404       szVariable[0] = szBuf[0];
02405       szVariable[1] = szBuf[1];
02406     }
02407   }
02408   else if(lstrcmpi(szVariable, "WINDIR") == 0)
02409   {
02410     /* Locate the "c:\Windows" directory */
02411     if(GetWindowsDirectory(szVariable, dwVariableSize) == 0)
02412     {
02413       char szEGetWinDirFailed[MAX_BUF];
02414 
02415       if(GetPrivateProfileString("Messages", "ERROR_GET_WINDOWS_DIRECTORY_FAILED", "",
02416                                  szEGetWinDirFailed, sizeof(szEGetWinDirFailed), 
02417                                  szFileIniUninstall))
02418         PrintError(szEGetWinDirFailed, ERROR_CODE_SHOW);
02419       exit(1);
02420     }
02421   }
02422   else if(lstrcmpi(szVariable, "WINSYSDIR") == 0)
02423   {
02424     /* Locate the "c:\Windows\System" (for Win95/Win98) or "c:\Windows\System32" (for NT) directory */
02425     if(GetSystemDirectory(szVariable, dwVariableSize) == 0)
02426     {
02427       char szEGetSysDirFailed[MAX_BUF];
02428 
02429       if(GetPrivateProfileString("Messages", "ERROR_GET_SYSTEM_DIRECTORY_FAILED", "",
02430                                  szEGetSysDirFailed, sizeof(szEGetSysDirFailed), 
02431                                  szFileIniUninstall))
02432         PrintError(szEGetSysDirFailed, ERROR_CODE_SHOW);
02433 
02434       exit(1);
02435     }
02436   }
02437   else if(lstrcmpi(szVariable, "JRE BIN PATH") == 0)
02438   {
02439     /* Locate the "c:\Program Files\JavaSoft\JRE\1.3\Bin" directory */
02440     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\javaw.Exe", NULL, szVariable, dwVariableSize);
02441     if(*szVariable == '\0')
02442       return(FALSE);
02443     else
02444     {
02445       ParsePath(szVariable, szBuf, MAX_BUF, PP_PATH_ONLY);
02446       lstrcpy(szVariable, szBuf);
02447     }
02448   }
02449   else if(lstrcmpi(szVariable, "JRE PATH") == 0)
02450   {
02451     /* Locate the "c:\Program Files\JavaSoft\JRE\1.3" directory */
02452     GetWinReg(HKEY_LOCAL_MACHINE, "Software\\JavaSoft\\Java Plug-in\\1.3", "JavaHome", szVariable, dwVariableSize);
02453     if(*szVariable == '\0')
02454       return(FALSE);
02455   }
02456   else if(lstrcmpi(szVariable, "UNINSTALL STARTUP PATH") == 0)
02457   {
02458     lstrcpy(szVariable, szUninstallDir);
02459   }
02460   else if(lstrcmpi(szVariable, "Product CurrentVersion") == 0)
02461   {
02462     char szKey[MAX_BUF];
02463 
02464     lstrcpy(szKey, "Software\\");
02465     lstrcat(szKey, ugUninstall.szCompanyName);
02466     lstrcat(szKey, "\\");
02467     lstrcat(szKey, ugUninstall.szProductName);
02468 
02469     /* parse for the current Netscape WinReg key */
02470     GetWinReg(HKEY_LOCAL_MACHINE, szKey, "CurrentVersion", szBuf, sizeof(szBuf));
02471 
02472     if(*szBuf == '\0')
02473       return(FALSE);
02474 
02475     wsprintf(szVariable, "Software\\%s\\%s\\%s", ugUninstall.szCompanyName, ugUninstall.szProductName, szBuf);
02476   }
02477   else if(lstrcmpi(szVariable, "Product WinRegKey") == 0)
02478   {
02479     char szKey[MAX_BUF];
02480 
02481     lstrcpy(szKey, "Software\\");
02482     lstrcat(szKey, ugUninstall.szCompanyName);
02483     lstrcat(szKey, "\\");
02484     lstrcat(szKey, ugUninstall.szProductName);
02485 
02486     wsprintf(szVariable, "Software\\%s\\%s", ugUninstall.szCompanyName, ugUninstall.szProductName);
02487   }
02488   else
02489     return(FALSE);
02490 
02491   return(TRUE);
02492 }
02493 
02494 HRESULT DecryptString(LPSTR szOutputStr, LPSTR szInputStr)
02495 {
02496   DWORD dwLenInputStr;
02497   DWORD dwCounter;
02498   DWORD dwVar;
02499   DWORD dwPrepend;
02500   char  szBuf[MAX_BUF];
02501   char  szVariable[MAX_BUF];
02502   char  szPrepend[MAX_BUF];
02503   char  szAppend[MAX_BUF];
02504   char  szResultStr[MAX_BUF];
02505   BOOL  bFoundVar;
02506   BOOL  bBeginParse;
02507   BOOL  bDecrypted;
02508 
02509   /* zero out the memory addresses */
02510   memset(szBuf,       '\0', MAX_BUF);
02511   memset(szVariable,  '\0', MAX_BUF);
02512   memset(szPrepend,   '\0', MAX_BUF);
02513   memset(szAppend,    '\0', MAX_BUF);
02514   memset(szResultStr, '\0', MAX_BUF);
02515 
02516   lstrcpy(szPrepend, szInputStr);
02517   dwLenInputStr = lstrlen(szInputStr);
02518   bBeginParse   = FALSE;
02519   bFoundVar     = FALSE;
02520 
02521   for(dwCounter = 0; dwCounter < dwLenInputStr; dwCounter++)
02522   {
02523     if((szInputStr[dwCounter] == ']') && bBeginParse)
02524       break;
02525 
02526     if(bBeginParse)
02527       szVariable[dwVar++] = szInputStr[dwCounter];
02528 
02529     if((szInputStr[dwCounter] == '[') && !bBeginParse)
02530     {
02531       dwVar        = 0;
02532       dwPrepend    = dwCounter;
02533       bBeginParse  = TRUE;
02534     }
02535   }
02536 
02537   if(dwCounter == dwLenInputStr)
02538     /* did not find anything to expand. */
02539     dwCounter = 0;
02540   else
02541   {
02542     bFoundVar = TRUE;
02543     ++dwCounter;
02544   }
02545 
02546   if(bFoundVar)
02547   {
02548     lstrcpy(szAppend, &szInputStr[dwCounter]);
02549 
02550     szPrepend[dwPrepend] = '\0';
02551 
02552     bDecrypted = DecryptVariable(szVariable, MAX_BUF);
02553     if(!bDecrypted)
02554     {
02555       /* Variable was not able to be decrypted. */
02556       /* Leave the variable as it was read in by adding the '[' and ']' */
02557       /* characters back to the variable. */
02558       lstrcpy(szBuf, "[");
02559       lstrcat(szBuf, szVariable);
02560       lstrcat(szBuf, "]");
02561       lstrcpy(szVariable, szBuf);
02562     }
02563 
02564     lstrcpy(szOutputStr, szPrepend);
02565     lstrcat(szOutputStr, szVariable);
02566     lstrcat(szOutputStr, szAppend);
02567 
02568     if(bDecrypted)
02569     {
02570       DecryptString(szResultStr, szOutputStr);
02571       lstrcpy(szOutputStr, szResultStr);
02572     }
02573   }
02574   else
02575     lstrcpy(szOutputStr, szInputStr);
02576 
02577   return(TRUE);
02578 }
02579 
02580 HRESULT FileExists(LPSTR szFile)
02581 {
02582   DWORD rv;
02583 
02584   if((rv = GetFileAttributes(szFile)) == -1)
02585   {
02586     return(FALSE);
02587   }
02588   else
02589   {
02590     return(rv);
02591   }
02592 }
02593 
02594 BOOL WinRegNameExists(HKEY hkRootKey, LPSTR szKey, LPSTR szName)
02595 {
02596   HKEY  hkResult;
02597   DWORD dwErr;
02598   DWORD dwSize;
02599   char  szBuf[MAX_BUF];
02600   BOOL  bNameExists = FALSE;
02601 
02602   szBuf[0] = '\0';
02603   if((dwErr = RegOpenKeyEx(hkRootKey, szKey, 0, KEY_READ, &hkResult)) == ERROR_SUCCESS)
02604   {
02605     dwSize = sizeof(szBuf);
02606     dwErr  = RegQueryValueEx(hkResult, szName, 0, NULL, szBuf, &dwSize);
02607 
02608     if((*szBuf != '\0') && (dwErr == ERROR_SUCCESS))
02609       bNameExists = TRUE;
02610 
02611     RegCloseKey(hkResult);
02612   }
02613 
02614   return(bNameExists);
02615 }
02616 
02617 void DeleteWinRegValue(HKEY hkRootKey, LPSTR szKey, LPSTR szName)
02618 {
02619   HKEY    hkResult;
02620   DWORD   dwErr;
02621 
02622   dwErr = RegOpenKeyEx(hkRootKey, szKey, 0, KEY_WRITE, &hkResult);
02623   if(dwErr == ERROR_SUCCESS)
02624   {
02625     if(*szName == '\0')
02626       dwErr = RegDeleteValue(hkResult, NULL);
02627     else
02628       dwErr = RegDeleteValue(hkResult, szName);
02629 
02630     RegCloseKey(hkResult);
02631   }
02632 }
02633 
02634 void DeInitialize()
02635 {
02636   DeInitDlgUninstall(&diUninstall);
02637 
02638   FreeMemory(&szTempDir);
02639   FreeMemory(&szOSTempDir);
02640   FreeMemory(&szUninstallDir);
02641   FreeMemory(&szEGlobalAlloc);
02642   FreeMemory(&szEDllLoad);
02643   FreeMemory(&szEStringLoad);
02644   FreeMemory(&szEStringNull);
02645   FreeMemory(&szFileIniUninstall);
02646   FreeMemory(&szFileIniDefaultsInfo);
02647 }
02648