RetroZilla/xpinstall/wizard/os2/nsinstall/stubinstall.cpp
2015-10-20 23:03:22 -04:00

669 lines
18 KiB
C++

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/LGPL 2.1/GPL 2.0
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by IBM are
* Copyright (C) 2002, International Business Machines Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Troy Chevalier <troy@netscape.com>
* Sean Su <ssu@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the LGPL or the GPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#define INCL_PM
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <string.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys\stat.h>
#include "resource.h"
#include "nsINIParser.h"
#define MAX_BUF 4096
#define WIZ_TEMP_DIR "ns_temp"
/* Mode of Setup to run in */
#define NORMAL 0
#define SILENT 1
#define AUTO 2
/* PP: Parse Path */
#define PP_FILENAME_ONLY 1
#define PP_PATH_ONLY 2
#define PP_ROOT_ONLY 3
#define CLASS_NAME_SETUP_DLG "MozillaSetupDlg"
/////////////////////////////////////////////////////////////////////////////
// Global Declarations
char szTitle[MAX_BUF];
char szCmdLineToSetup[MAX_BUF];
BOOL gbUncompressOnly;
ULONG ulMode;
static ULONG nTotalBytes = 0; // sum of all the FILE resources
char szOSTempDir[CCHMAXPATH];
/////////////////////////////////////////////////////////////////////////////
// Utility Functions
BOOL isFAT(char* szPath)
{
APIRET rc;
ULONG ulSize;
PFSQBUFFER2 pfsqbuf2;
CHAR szDrive[3];
ulSize = sizeof(FSQBUFFER2) + 3 * CCHMAXPATH;
pfsqbuf2 = (PFSQBUFFER2)malloc(ulSize);
strncpy(szDrive, szPath, 2);
szDrive[2] = '\0';
DosError(FERR_DISABLEHARDERR);
rc = DosQueryFSAttach(szDrive, 0, FSAIL_QUERYNAME,
pfsqbuf2, &ulSize);
DosError(FERR_ENABLEHARDERR);
if (rc == NO_ERROR) {
if (strcmp((char*)(pfsqbuf2->szFSDName + pfsqbuf2->cbName), "FAT") != 0)
return FALSE;
}
return TRUE;
}
HWND FindWindow(PCSZ pszAtomString)
{
ATOM atom;
HENUM henum;
HWND hwndClient, hwnd = NULLHANDLE;
atom = WinFindAtom(WinQuerySystemAtomTable(), pszAtomString);
if (atom) {
henum = WinBeginEnumWindows(HWND_DESKTOP);
while ((hwnd = WinGetNextWindow(henum)) != NULLHANDLE)
{
ULONG ulWindowWord;
ulWindowWord = WinQueryWindowULong(hwnd, QWL_USER);
if (ulWindowWord == atom) {
break;
}
}
}
WinEndEnumWindows(henum);
return hwnd;
}
// this function appends a backslash at the end of a string,
// if one does not already exists.
static void AppendBackSlash(PSZ szInput, ULONG ulInputSize)
{
if(szInput != NULL)
{
if(szInput[strlen(szInput) - 1] != '\\')
{
if(((ULONG)strlen(szInput) + 1) < ulInputSize)
{
strcat(szInput, "\\");
}
}
}
}
// This function is similar to GetFullPathName except instead of
// using the current drive and directory it uses the path of the
// directory designated for temporary files
// If you don't specify a filename, you just get the temp dir without
// a trailing slash
static BOOL
GetFullTempPathName(PCSZ szFileName, ULONG ulBufferLength, PSZ szBuffer)
{
strcpy(szBuffer, szOSTempDir);
AppendBackSlash(szBuffer, MAX_BUF);
strcat(szBuffer, WIZ_TEMP_DIR);
if (szFileName) {
AppendBackSlash(szBuffer, MAX_BUF);
strcat(szBuffer, szFileName);
}
return TRUE;
}
static void CreateDirectoriesAll(char* szPath)
{
int i;
int iLen = strlen(szPath);
char szCreatePath[CCHMAXPATH];
memset(szCreatePath, 0, CCHMAXPATH);
memcpy(szCreatePath, szPath, iLen);
for(i = 0; i < iLen; i++)
{
if((iLen > 1) &&
((i != 0) && ((szPath[i] == '\\') || (szPath[i] == '/'))) &&
(!((szPath[0] == '\\') && (i == 1)) && !((szPath[1] == ':') && (i == 2))))
{
szCreatePath[i] = '\0';
DosCreateDir(szCreatePath, NULL);
szCreatePath[i] = szPath[i];
}
}
}
// This function removes a directory and its subdirectories
void DirectoryRemove(PSZ szDestination, BOOL bRemoveSubdirs)
{
HDIR hFile;
FILEFINDBUF3 fdFile;
ULONG ulFindCount;
ULONG ulAttrs;
char szDestTemp[MAX_BUF];
BOOL bFound;
if(bRemoveSubdirs == TRUE)
{
strcpy(szDestTemp, szDestination);
AppendBackSlash(szDestTemp, sizeof(szDestTemp));
strcat(szDestTemp, "*");
ulFindCount = 1;
hFile = HDIR_CREATE;
ulAttrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
if((DosFindFirst(szDestTemp, &hFile, ulAttrs, &fdFile, sizeof(fdFile), &ulFindCount, FIL_STANDARD)) != NO_ERROR)
bFound = FALSE;
else
bFound = TRUE;
while(bFound == TRUE)
{
if((stricmp(fdFile.achName, ".") != 0) && (stricmp(fdFile.achName, "..") != 0))
{
/* create full path */
strcpy(szDestTemp, szDestination);
AppendBackSlash(szDestTemp, sizeof(szDestTemp));
strcat(szDestTemp, fdFile.achName);
if(fdFile.attrFile & FILE_DIRECTORY)
{
DirectoryRemove(szDestTemp, bRemoveSubdirs);
}
else
{
DosDelete(szDestTemp);
}
}
ulFindCount = 1;
if (DosFindNext(hFile, &fdFile, sizeof(fdFile), &ulFindCount) != NO_ERROR)
bFound = FALSE;
else
bFound = TRUE;
}
DosFindClose(hFile);
}
DosDeleteDir(szDestination);
}
void RemoveBackSlash(PSZ szInput)
{
int iCounter;
ULONG ulInputLen;
if(szInput != NULL)
{
ulInputLen = strlen(szInput);
for(iCounter = ulInputLen -1; iCounter >= 0 ; iCounter--)
{
if(szInput[iCounter] == '\\')
szInput[iCounter] = '\0';
else
break;
}
}
}
void ParsePath(PSZ szInput, PSZ szOutput, ULONG ulOutputSize, ULONG ulType)
{
int iCounter;
ULONG ulCounter;
ULONG ulInputLen;
BOOL bFound;
if((szInput != NULL) && (szOutput != NULL))
{
bFound = TRUE;
ulInputLen = strlen(szInput);
memset(szOutput, 0, ulOutputSize);
if(ulInputLen < ulOutputSize)
{
switch(ulType)
{
case PP_FILENAME_ONLY:
for(iCounter = ulInputLen - 1; iCounter >= 0; iCounter--)
{
if(szInput[iCounter] == '\\')
{
strcpy(szOutput, &szInput[iCounter + 1]);
bFound = TRUE;
break;
}
}
if(bFound == FALSE)
strcpy(szOutput, szInput);
break;
case PP_PATH_ONLY:
for(iCounter = ulInputLen - 1; iCounter >= 0; iCounter--)
{
if(szInput[iCounter] == '\\')
{
strcpy(szOutput, szInput);
szOutput[iCounter + 1] = '\0';
bFound = TRUE;
break;
}
}
if(bFound == FALSE)
strcpy(szOutput, szInput);
break;
case PP_ROOT_ONLY:
if(szInput[1] == ':')
{
szOutput[0] = szInput[0];
szOutput[1] = szInput[1];
AppendBackSlash(szOutput, ulOutputSize);
}
else if(szInput[1] == '\\')
{
int iFoundBackSlash = 0;
for(ulCounter = 0; ulCounter < ulInputLen; ulCounter++)
{
if(szInput[ulCounter] == '\\')
{
szOutput[ulCounter] = szInput[ulCounter];
++iFoundBackSlash;
}
if(iFoundBackSlash == 3)
break;
}
if(iFoundBackSlash != 0)
AppendBackSlash(szOutput, ulOutputSize);
}
break;
}
}
}
}
void ParseCommandLine(int argc, char *argv[])
{
char szArgVBuf[MAX_BUF];
int i = 1;
memset(szCmdLineToSetup, 0, MAX_BUF);
ulMode = NORMAL;
gbUncompressOnly = FALSE;
strcpy(szCmdLineToSetup, " ");
while(i < argc)
{
if((stricmp(argv[i], "-ms") == 0) || (stricmp(argv[i], "/ms") == 0))
{
ulMode = SILENT;
}
else if((stricmp(argv[i], "-u") == 0) || (stricmp(argv[i], "/u") == 0))
{
gbUncompressOnly = TRUE;
}
strcat(szCmdLineToSetup, argv[i]);
strcat(szCmdLineToSetup, " ");
++i;
}
}
/////////////////////////////////////////////////////////////////////////////
// Extract Files Dialog
// Window proc for dialog
MRESULT EXPENTRY DialogProc(HWND hwndDlg, ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch (msg) {
case WM_INITDLG:
{
SWP swpDlg;
WinQueryWindowPos(hwndDlg, &swpDlg);
WinSetWindowPos(hwndDlg,
HWND_TOP,
(WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)/2)-(swpDlg.cx/2),
(WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)/2)-(swpDlg.cy/2),
0,
0,
SWP_MOVE);
WinSendMsg(WinWindowFromID(hwndDlg, IDC_GAUGE),SLM_SETSLIDERINFO,
MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE),
0);
}
}
return WinDefDlgProc(hwndDlg, msg, mp1, mp2);
}
void DeleteTempFiles(ULONG ulNumFiles)
{
ULONG ulSize;
void* pFileData;
FILE* fhFile;
char szTmpFile[CCHMAXPATH] = "";
char szFileName[CCHMAXPATH] = "";
for (int i=1;i<=ulNumFiles;i++) {
WinLoadString(0, NULLHANDLE, ID_FILE_BASE+i, CCHMAXPATH, szFileName);
GetFullTempPathName(szFileName, sizeof(szTmpFile), szTmpFile);
DosDelete(szTmpFile);
}
}
BOOL
ExtractFiles(ULONG ulNumFiles, HWND hwndDlg)
{
ULONG ulSize;
void* pFileData;
FILE* fhFile;
char szTmpFile[CCHMAXPATH] = "";
char szFileName[CCHMAXPATH] = "";
char szArcLstFile[CCHMAXPATH] = "";
char szStatus[256];
char szText[256];
ULONG nBytesWritten = 0;
WinLoadString(0, NULLHANDLE, IDS_STATUS_EXTRACTING, sizeof(szText), szText);
if(gbUncompressOnly == FALSE) {
// CreateDirectoriesAll takes a fully qualified file, so we create one
GetFullTempPathName("tempfile", sizeof(szTmpFile), szTmpFile);
CreateDirectoriesAll(szTmpFile);
GetFullTempPathName("Archive.lst", sizeof(szArcLstFile), szArcLstFile);
} else {
strcpy(szArcLstFile, "Archive.lst");
}
for (int i=1;i<=ulNumFiles;i++) {
WinLoadString(0, NULLHANDLE, ID_FILE_BASE+i, CCHMAXPATH, szFileName);
// Update the UI
sprintf(szStatus, szText, szFileName);
WinSetWindowText(WinWindowFromID(hwndDlg, IDC_STATUS), szStatus);
if(gbUncompressOnly == FALSE) {
GetFullTempPathName(szFileName, sizeof(szTmpFile), szTmpFile);
} else {
strcpy(szTmpFile, szFileName);
}
DosQueryResourceSize(NULLHANDLE, RT_RCDATA, ID_FILE_BASE+i, &ulSize);
DosGetResource(NULLHANDLE, RT_RCDATA, ID_FILE_BASE+i, &pFileData);
FILE* fhFile = fopen(szTmpFile, "wb+");
fwrite(pFileData, ulSize, 1, fhFile);
fclose(fhFile);
DosFreeResource(pFileData);
nBytesWritten += ulSize;
WinSendMsg(WinWindowFromID(hwndDlg, IDC_GAUGE), SLM_SETSLIDERINFO,
MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE),
MPARAM(nBytesWritten * 100 / nTotalBytes));
WritePrivateProfileString("Archives", szFileName, "TRUE", szArcLstFile);
}
}
BOOL FileExists(PSZ szFile)
{
struct stat st;
int statrv;
statrv = stat(szFile, &st);
if (statrv == 0)
return(TRUE);
else
return (FALSE);
}
void RunInstaller(ULONG ulNumFiles, HWND hwndDlg)
{
char szCmdLine[MAX_BUF];
char szSetupFile[CCHMAXPATH];
char szUninstallFile[CCHMAXPATH];
char szArcLstFile[CCHMAXPATH];
char szText[256];
char szTempPath[CCHMAXPATH];
char szFilename[CCHMAXPATH];
char szBuf[MAX_BUF];
ULONG ulLen;
// Update UI
WinSendMsg(WinWindowFromID(hwndDlg, IDC_GAUGE),SLM_SETSLIDERINFO,
MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_INCREMENTVALUE),
0);
WinLoadString(0, NULLHANDLE, IDS_STATUS_LAUNCHING_SETUP, sizeof(szText), szText);
WinSetWindowText(WinWindowFromID(hwndDlg, IDC_STATUS), szText);
// Setup program is in the directory specified for temporary files
GetFullTempPathName("Archive.lst", sizeof(szArcLstFile), szArcLstFile);
GetFullTempPathName("SETUP.EXE", sizeof(szSetupFile), szSetupFile);
GetFullTempPathName("uninstall.exe", sizeof(szUninstallFile), szUninstallFile);
GetPrivateProfileString("Archives", "uninstall.exe", "", szBuf, sizeof(szBuf), szArcLstFile);
if(FileExists(szUninstallFile) && (*szBuf != '\0'))
{
strcpy(szCmdLine, szUninstallFile);
ulLen = strlen(szUninstallFile);
}
else
{
strcpy(szCmdLine, szSetupFile);
PPIB ppib;
PTIB ptib;
char buffer[CCHMAXPATH];
DosGetInfoBlocks( &ptib, &ppib);
DosQueryModuleName(ppib->pib_hmte, sizeof(szBuf), szBuf);
ParsePath(szBuf, szFilename, sizeof(szFilename), PP_FILENAME_ONLY);
strcat(szCmdLine, " -n ");
strcat(szCmdLine, szFilename);
ulLen = strlen(szSetupFile);
}
strcat(szCmdLine, szCmdLineToSetup);
// Launch the installer
RESULTCODES rcChild;
PID pidChild;
CHAR szLoadError[CCHMAXPATH];
szCmdLine[strlen(szCmdLine)] = '\0';
szCmdLine[strlen(szCmdLine)+1] = '\0';
szCmdLine[ulLen] = '\0';
DosExecPgm(szLoadError,
sizeof(szLoadError),
EXEC_ASYNCRESULT,
szCmdLine,
NULL,
&rcChild,
szCmdLine);
if(ulMode != SILENT)
{
WinDestroyWindow(hwndDlg);
}
DosWaitChild(DCWA_PROCESS,
DCWW_WAIT,
&rcChild,
&pidChild,
rcChild.codeTerminate);
DeleteTempFiles(ulNumFiles);
GetFullTempPathName("Archive.lst", sizeof(szTempPath), szTempPath);
DosDelete(szTempPath);
GetFullTempPathName("xpcom.ns", sizeof(szTempPath), szTempPath);
DirectoryRemove(szTempPath, TRUE);
GetFullTempPathName(NULL, sizeof(szTempPath), szTempPath);
DirectoryRemove(szTempPath, TRUE);
}
int main(int argc, char *argv[], char *envp[])
{
HAB hab;
HMQ hmq;
HWND hwndFW, hwndDlg;
ATOM atom;
hab = WinInitialize(0);
hmq = WinCreateMsgQueue(hab,0);
atom = WinAddAtom(WinQuerySystemAtomTable(), "NSExtracting");
char *tempEnvVar = NULL;
// determine the system's TEMP path
tempEnvVar = getenv("TMP");
if ((tempEnvVar) && (!(isFAT(tempEnvVar)))) {
strcpy(szOSTempDir, tempEnvVar);
}
else
{
tempEnvVar = getenv("TEMP");
if (tempEnvVar)
strcpy(szOSTempDir, tempEnvVar);
}
if ((!tempEnvVar) || (isFAT(tempEnvVar)))
{
ULONG ulBootDrive = 0;
APIRET rc;
char buffer[] = " :\\OS2\\";
DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
&ulBootDrive, sizeof(ulBootDrive));
buffer[0] = 'A' - 1 + ulBootDrive;
if (isFAT(buffer)) {
/* Try current disk if boot drive is FAT */
ULONG ulDriveNum;
ULONG ulDriveMap;
strcpy(buffer, " :\\");
DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
buffer[0] = 'A' - 1 + ulDriveNum;
if (isFAT(buffer)) {
int i;
for (i = 2; i < 26; i++) {
if ((ulDriveMap<<(31-i)) >> 31) {
buffer[0] = 'A' + i;
if (!(isFAT(buffer))) {
break;
}
}
}
if (i == 26) {
char szBuf[MAX_BUF];
WinLoadString(0, NULLHANDLE, IDS_ERROR_NO_LONG_FILENAMES, sizeof(szBuf), szBuf);
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szBuf, NULL, 0, MB_ICONEXCLAMATION);
return(1);
}
}
}
strcpy(szOSTempDir, buffer);
strcat(szOSTempDir, "TEMP");
}
WinLoadString(0, NULLHANDLE, IDS_TITLE, MAX_BUF, szTitle);
/* Allow only one instance of stubnsinstall to run.
* Detect a previous instance of stubnsinstall, bring it to the
* foreground, and quit current instance */
if(FindWindow("NSExtracting") != NULL)
return(1);
/* Allow only one instance of Setup to run.
* Detect a previous instance of Setup, and quit */
if((hwndFW = FindWindow(CLASS_NAME_SETUP_DLG)) != NULL)
{
WinSetActiveWindow(HWND_DESKTOP, hwndFW);
return(1);
}
// Parse the command line
ParseCommandLine(argc, argv);
ULONG ulSize;
ULONG ulNumFiles = 0;
INT i = 1;
APIRET rc = NO_ERROR;
while(rc == NO_ERROR) {
rc = DosQueryResourceSize(NULLHANDLE, RT_RCDATA, ID_FILE_BASE+i, &ulSize);
if (rc == NO_ERROR) {
nTotalBytes += ulSize;
ulNumFiles++;
}
i++;
}
if(ulMode != SILENT)
{
hwndDlg = WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP, DialogProc, NULLHANDLE, IDD_EXTRACTING, NULL);
WinSetWindowULong(hwndDlg, QWL_USER, atom);
WinSetWindowPos(hwndDlg, 0, 0, 0, 0, 0, SWP_SHOW | SWP_ACTIVATE);
}
// Extract the files
ExtractFiles(ulNumFiles, hwndDlg);
if (gbUncompressOnly == FALSE) {
// Launch the install program and wait for it to finish
RunInstaller(ulNumFiles, hwndDlg);
}
WinDeleteAtom(WinQuerySystemAtomTable(), atom);
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
}