diff --git a/xpinstall/wizard/windows/nsztool/makefile.win b/xpinstall/wizard/windows/nsztool/makefile.win new file mode 100644 index 00000000000..93a7c4c85d5 --- /dev/null +++ b/xpinstall/wizard/windows/nsztool/makefile.win @@ -0,0 +1,51 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 Communicator client code, +# released March 31, 1998. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1999 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH=..\..\..\.. + +MAKE_OBJ_TYPE = EXE +USE_STATIC_LIBS = 1 + +MODULE = nsztool +PROGRAM = .\$(OBJDIR)\$(MODULE).exe +#RESFILE = $(MODULE).res + +OBJS = \ + .\$(OBJDIR)\nsztool.obj \ + $(NULL) + +LLIBS= \ + $(DIST)\lib\zlib_s.lib \ + $(NULL) + +LLFLAGS= \ + /subsystem:windows \ + /machine:i386 \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(PROGRAM) + $(MAKE_INSTALL) $(PROGRAM) $(DIST)\install + +clobber_all:: + $(RM) $(DIST)\install\$(MODULE).exe + diff --git a/xpinstall/wizard/windows/nsztool/nsztool.c b/xpinstall/wizard/windows/nsztool/nsztool.c new file mode 100644 index 00000000000..b306c601e39 --- /dev/null +++ b/xpinstall/wizard/windows/nsztool/nsztool.c @@ -0,0 +1,631 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 Communicator client code, + * released March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Sean Su + */ + +#include +#include +#include +#include +#include +#include "nsztool.h" +#include "zlib.h" + +//#define SSU_DEBUG + +#define APP_NAME "nsz.exe" + +char *GetSubString(char *Strings) +{ + return(strchr(Strings,0)+1); +} + +void ShowUsage(char *name) +{ + char szBuf[MAX_BUF]; + + wsprintf(szBuf, "Usage: %s \n", name); + lstrcat(szBuf, "\n"); + lstrcat(szBuf, " output sea name: name to use for the self-extracting executable\n"); + lstrcat(szBuf, " files: one or more files to add to the self-extracing executable\n"); + MessageBox(NULL, szBuf, "Usage", MB_OK); +} + +void PrintError(LPSTR szMsg, DWORD dwErrorCodeSH) +{ + DWORD dwErr; + char szErrorString[MAX_BUF]; + + if(dwErrorCodeSH == ERROR_CODE_SHOW) + { + dwErr = GetLastError(); + wsprintf(szErrorString, "%d : %s", dwErr, szMsg); + } + else + wsprintf(szErrorString, "%s", szMsg); + + MessageBox(NULL, szErrorString, NULL, MB_ICONEXCLAMATION); +} + +void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize) +{ + char *lpszBegin; + + if(lstrlen(lpszSrc) > iDestSize) + return; + + if(*lpszSrc == '\"') + lpszBegin = &lpszSrc[1]; + else + lpszBegin = lpszSrc; + + lstrcpy(lpszDest, lpszBegin); + + if(lpszDest[lstrlen(lpszDest) - 1] == '\"') + lpszDest[lstrlen(lpszDest) - 1] = '\0'; +} + +void RemoveBackSlash(LPSTR szInput) +{ + int iCounter; + DWORD dwInputLen; + + if(szInput != NULL) + { + dwInputLen = lstrlen(szInput); + + for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--) + { + if(szInput[iCounter] == '\\') + szInput[iCounter] = '\0'; + else + break; + } + } +} + +void AppendBackSlash(LPSTR szInput, DWORD dwInputSize) +{ + if(szInput != NULL) + { + if(szInput[strlen(szInput) - 1] != '\\') + { + if(((DWORD)lstrlen(szInput) + 1) < dwInputSize) + { + lstrcat(szInput, "\\"); + } + } + } +} + +void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType) +{ + int iCounter; + DWORD dwCounter; + DWORD dwInputLen; + BOOL bFound; + + if((szInput != NULL) && (szOutput != NULL)) + { + bFound = FALSE; + dwInputLen = lstrlen(szInput); + ZeroMemory(szOutput, dwOutputSize); + + if(dwInputLen < dwOutputSize) + { + switch(dwType) + { + case PP_FILENAME_ONLY: + for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--) + { + if(szInput[iCounter] == '\\') + { + lstrcpy(szOutput, &szInput[iCounter + 1]); + bFound = TRUE; + break; + } + } + if(bFound == FALSE) + lstrcpy(szOutput, szInput); + + break; + + case PP_PATH_ONLY: + for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--) + { + if(szInput[iCounter] == '\\') + { + lstrcpy(szOutput, szInput); + szOutput[iCounter + 1] = '\0'; + bFound = TRUE; + break; + } + } + if(bFound == FALSE) + lstrcpy(szOutput, szInput); + + break; + + case PP_ROOT_ONLY: + if(szInput[1] == ':') + { + szOutput[0] = szInput[0]; + szOutput[1] = szInput[1]; + AppendBackSlash(szOutput, dwOutputSize); + } + else if(szInput[1] == '\\') + { + int iFoundBackSlash = 0; + for(dwCounter = 0; dwCounter < dwInputLen; dwCounter++) + { + if(szInput[dwCounter] == '\\') + { + szOutput[dwCounter] = szInput[dwCounter]; + ++iFoundBackSlash; + } + + if(iFoundBackSlash == 3) + break; + } + + if(iFoundBackSlash != 0) + AppendBackSlash(szOutput, dwOutputSize); + } + break; + } + } + } +} + +long FileExists(LPSTR szFile) +{ + DWORD rv; + + if((rv = GetFileAttributes(szFile)) == -1) + { + return(FALSE); + } + else + { + return(rv); + } +} + +LPSTR GetFirstNonSpace(LPSTR lpszString) +{ + int i; + int iStrLength; + + iStrLength = lstrlen(lpszString); + + for(i = 0; i < iStrLength; i++) + { + if(!isspace(lpszString[i])) + return(&lpszString[i]); + } + + return(NULL); +} + +int GetArgC(LPSTR lpszCommandLine) +{ + int i; + int iArgCount; + int iStrLength; + LPSTR lpszBeginStr; + BOOL bFoundQuote; + BOOL bFoundSpace; + + iArgCount = 0; + lpszBeginStr = GetFirstNonSpace(lpszCommandLine); + + if(lpszBeginStr == NULL) + return(iArgCount); + + iStrLength = lstrlen(lpszBeginStr); + bFoundQuote = FALSE; + bFoundSpace = TRUE; + + for(i = 0; i < iStrLength; i++) + { + if(lpszCommandLine[i] == '\"') + { + if(bFoundQuote == FALSE) + { + ++iArgCount; + bFoundQuote = TRUE; + } + else + { + bFoundQuote = FALSE; + } + } + else if(bFoundQuote == FALSE) + { + if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE)) + { + ++iArgCount; + bFoundSpace = FALSE; + } + else if(isspace(lpszCommandLine[i])) + { + bFoundSpace = TRUE; + } + } + } + + return(iArgCount); +} + +LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize) +{ + int i; + int j; + int iArgCount; + int iStrLength; + LPSTR lpszBeginStr; + LPSTR lpszDestTemp; + BOOL bFoundQuote; + BOOL bFoundSpace; + + iArgCount = 0; + lpszBeginStr = GetFirstNonSpace(lpszCommandLine); + + if(lpszBeginStr == NULL) + return(NULL); + + lpszDestTemp = (char *)calloc(iDestSize, sizeof(char)); + if(lpszDestTemp == NULL) + { + PrintError("Out of memory", ERROR_CODE_HIDE); + exit(1); + } + + ZeroMemory(lpszDest, iDestSize); + iStrLength = lstrlen(lpszBeginStr); + bFoundQuote = FALSE; + bFoundSpace = TRUE; + j = 0; + + for(i = 0; i < iStrLength; i++) + { + if(lpszCommandLine[i] == '\"') + { + if(bFoundQuote == FALSE) + { + ++iArgCount; + bFoundQuote = TRUE; + } + else + { + bFoundQuote = FALSE; + } + } + else if(bFoundQuote == FALSE) + { + if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE)) + { + ++iArgCount; + bFoundSpace = FALSE; + } + else if(isspace(lpszCommandLine[i])) + { + bFoundSpace = TRUE; + } + } + + if((iIndex == (iArgCount - 1)) && + ((bFoundQuote == TRUE) || (bFoundSpace == FALSE) || + ((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"')))) + { + if(j < iDestSize) + { + lpszDestTemp[j] = lpszCommandLine[i]; + ++j; + } + else + { + lpszDestTemp[j] = '\0'; + } + } + } + + RemoveQuotes(lpszDestTemp, lpszDest, iDestSize); + free(lpszDestTemp); + return(lpszDest); +} + +void AddFile(LPSTR lpszSeaExe, LPSTR lpszFile) +{ + char szBuf[MAX_BUF]; + char szResourceName[MAX_BUF]; + HANDLE hSeaExe; + HANDLE hInputFile; + DWORD dwBytesRead; + DWORD dwFileSize; + DWORD dwFileSizeCmp; + LPBYTE lpBuf; + LPBYTE lpBufCmp; + + ParsePath(lpszFile, szResourceName, sizeof(szResourceName), PP_FILENAME_ONLY); + strupr(szResourceName); + hInputFile = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if(hInputFile == INVALID_HANDLE_VALUE) + { + PrintError("CreateFile() failed", ERROR_CODE_SHOW); + exit(1); + } + + dwFileSize = GetFileSize(hInputFile, NULL); + lpBuf = (LPBYTE)malloc(dwFileSize); + lpBufCmp = (LPBYTE)malloc(dwFileSize + (sizeof(DWORD) * 2)); + if((lpBuf == NULL) || (lpBufCmp == NULL)) + { + PrintError("Out of memory", ERROR_CODE_HIDE); + exit(1); + } + + ReadFile(hInputFile, lpBuf, dwFileSize, &dwBytesRead, NULL); + if(dwBytesRead != dwFileSize) + { + wsprintf(szBuf, "Error reading file: %s", lpszFile); + PrintError(szBuf, ERROR_CODE_HIDE); + exit(1); + } + + if(compress((lpBufCmp + (sizeof(DWORD) * 2)), &dwFileSizeCmp, (const Bytef*)lpBuf, dwFileSize) != Z_OK) + { + PrintError("Error occurred during compression of archives!", ERROR_CODE_HIDE); + exit(1); + } + + *(LPDWORD)lpBufCmp = dwFileSizeCmp; + *(LPDWORD)(lpBufCmp + sizeof(DWORD)) = dwFileSize; + + if((hSeaExe = BeginUpdateResource(lpszSeaExe, FALSE)) == NULL) + { + PrintError("BeginUpdateResource() error", ERROR_CODE_SHOW); + exit(1); + } + if(!UpdateResource(hSeaExe, "FILE", szResourceName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + lpBufCmp, dwFileSizeCmp + (sizeof(DWORD) * 2))) + { + PrintError("UpdateResource() failed", ERROR_CODE_SHOW); + exit(1); + } + if(!EndUpdateResource(hSeaExe, FALSE)) + { + PrintError("EndUpdateResource() failed", ERROR_CODE_SHOW); + exit(1); + } + + free(lpBuf); + if(!CloseHandle(hInputFile)) + { + PrintError("CloseHandle() failed", ERROR_CODE_SHOW); + exit(1); + } +} + +BOOL APIENTRY ExtractFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam) +{ + char szBuf[MAX_BUF]; + HRSRC hResInfo; + LPSTR lpszSeaExe = (LPSTR)lParam; + HANDLE hFile; + LPBYTE lpBytes; + LPBYTE lpBytesUnCmp; + HGLOBAL hGlobal; + + // Extract the file + hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType); + hGlobal = LoadResource((HINSTANCE)hModule, hResInfo); + lpBytes = (LPBYTE)LockResource(hGlobal); + + // Create the file + hFile = CreateFile(lpszSeaExe, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY, NULL); + + if(hFile != INVALID_HANDLE_VALUE) + { + DWORD dwSize; + DWORD dwSizeUnCmp; + + lpBytesUnCmp = (LPBYTE)malloc((*(LPDWORD)(lpBytes + sizeof(DWORD))) + 1); + dwSizeUnCmp = *(LPDWORD)(lpBytes + sizeof(DWORD)); + + // Copy the file. The first DWORD specifies the size of the file + dwSize = *(LPDWORD)lpBytes; + lpBytes += (sizeof(DWORD) * 2); + + if(uncompress(lpBytesUnCmp, &dwSizeUnCmp, lpBytes, dwSize) != Z_OK) + { + wsprintf(szBuf, "Error occurred during uncompression of %s: ", lpszSeaExe); + PrintError(szBuf, ERROR_CODE_HIDE); + CloseHandle(hFile); + FreeResource(hResInfo); + return FALSE; + } + + while(dwSizeUnCmp > 0) + { + DWORD dwBytesToWrite; + DWORD dwBytesWritten; + + dwBytesToWrite = dwSizeUnCmp > 4096 ? 4096 : dwSizeUnCmp; + if(!WriteFile(hFile, lpBytesUnCmp, dwBytesToWrite, &dwBytesWritten, NULL)) + { + wsprintf(szBuf, "%s: write error", lpszSeaExe); + MessageBox(NULL, szBuf, "Error", MB_OK | MB_ICONEXCLAMATION); + CloseHandle(hFile); + FreeResource(hResInfo); + return FALSE; + } + + dwSizeUnCmp -= dwBytesWritten; + lpBytesUnCmp += dwBytesWritten; + } + + CloseHandle(hFile); + } + + // Release the resource + FreeResource(hResInfo); + + return TRUE; // keep enumerating +} + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + int i; + int iArgC; + char szBuf[MAX_BUF]; + char szArgVBuf[MAX_BUF]; + char szFileFullPath[MAX_BUF]; + char szSeaExe[MAX_BUF]; + char szNsZipName[MAX_BUF]; + char szAppName[MAX_BUF]; + +#ifdef SSU_DEBUG + char szOutputStr[MAX_BUF]; +#endif + + WIN32_FIND_DATA findFileData; + HANDLE hFindFile; + BOOL bSelfUpdate; + + if(*lpszCmdLine == '\0') + { + if(GetModuleFileName(NULL, szAppName, sizeof(szAppName)) == 0L) + { + PrintError("GetModuleFileName() failed", ERROR_CODE_SHOW); + exit(1); + } + ParsePath(szAppName, szBuf, sizeof(szBuf), PP_FILENAME_ONLY); + ShowUsage(szBuf); + exit(1); + } + + iArgC = GetArgC(lpszCmdLine); + bSelfUpdate = FALSE; + +#ifdef SSU_DEBUG + wsprintf(szOutputStr, "ArgC: %d\n", iArgC); + for(i = 0; i < iArgC; i++) + { + GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf)); + itoa(i, szBuf, 10); + lstrcat(szOutputStr, " "); + lstrcat(szOutputStr, szBuf); + lstrcat(szOutputStr, ": "); + lstrcat(szOutputStr, szArgVBuf); + lstrcat(szOutputStr, "\n"); + } + MessageBox(NULL, szOutputStr, "Output", MB_OK); +#endif + + /* Get the first parameter */ + GetArgV(lpszCmdLine, 0, szSeaExe, sizeof(szSeaExe)); + if(lstrcmpi(szSeaExe, "-g") == 0) + { + /* The first parameter is "-g". + * Create a new nszip that contains nsinstall.exe in itself */ + + GetArgV(lpszCmdLine, 1, szNsZipName, sizeof(szNsZipName)); + GetArgV(lpszCmdLine, 2, szSeaExe, sizeof(szSeaExe)); + if(!FileExists(szSeaExe)) + { + wsprintf(szBuf, "file not found: %s", szSeaExe); + PrintError(szBuf, ERROR_CODE_HIDE); + exit(1); + } + + if(GetModuleFileName(NULL, szAppName, sizeof(szAppName)) == 0L) + { + PrintError("GetModuleFileName() failed", ERROR_CODE_SHOW); + exit(1); + } + if(!FileExists(szAppName)) + { + wsprintf(szBuf, "file not found: %s", szAppName); + PrintError(szBuf, ERROR_CODE_HIDE); + exit(1); + } + + if(CopyFile(szAppName, szNsZipName, FALSE) == FALSE) + { + wsprintf(szBuf, "Error creating %s", szNsZipName); + PrintError(szBuf, ERROR_CODE_SHOW); + exit(1); + } + + AddFile(szNsZipName, szSeaExe); + return(0); + } + else + { + /* The first parameter is not "-g". Assume that it's the name of the + * self-extracting .exe to be saved as. So lets create it. */ + + EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)ExtractFilesProc, (LONG)szSeaExe); + if(!FileExists(szSeaExe)) + { + wsprintf(szBuf, "file not found: %s", szSeaExe); + PrintError(szBuf, ERROR_CODE_HIDE); + exit(1); + } + } + + for(i = 1; i < iArgC; i++) + { + GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf)); + GetFullPathName(szArgVBuf, sizeof(szFileFullPath), szFileFullPath, NULL); + hFindFile = FindFirstFile(szFileFullPath, &findFileData); + + if(hFindFile == INVALID_HANDLE_VALUE) + { + wsprintf(szBuf, "file not found: %s", szArgVBuf); + PrintError(szBuf, ERROR_CODE_HIDE); + exit(1); + } + + do + { + char szFile[MAX_BUF]; + + if(!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // We need to pass to AddFile() whatever kind of path we were passed, + // e.g. simple, relative, full + strcpy(szFile, szFileFullPath); + strcpy(strrchr(szFile, '\\') + 1, findFileData.cFileName); + AddFile(szSeaExe, szFile); + } + } while(FindNextFile(hFindFile, &findFileData)); + + FindClose(hFindFile); + } + + return(0); +} + diff --git a/xpinstall/wizard/windows/nsztool/nsztool.h b/xpinstall/wizard/windows/nsztool/nsztool.h new file mode 100644 index 00000000000..b42615c0aaa --- /dev/null +++ b/xpinstall/wizard/windows/nsztool/nsztool.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 Communicator client code, + * released March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Sean Su + */ + +#ifndef _NSZ_H_ +#define _NSZ_H_ + +#define MAX_BUF 4096 + +#define ERROR_CODE_HIDE 0 +#define ERROR_CODE_SHOW 1 + +/* PP: Parse Path */ +#define PP_FILENAME_ONLY 1 +#define PP_PATH_ONLY 2 +#define PP_ROOT_ONLY 3 + +char *GetSubString(char *Strings); +void PrintError(LPSTR szMsg, DWORD dwErrorCodeSH); +void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int dwDestSize); +void RemoveBackSlash(LPSTR szInput); +void AppendBackSlash(LPSTR szInput, DWORD dwInputSize); +void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType); +long FileExists(LPSTR szFile); +int GetArgC(LPSTR lpszCommandLine); +LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize); +void AddFile(LPSTR lpszSeaExe, LPSTR lpszFile); +BOOL APIENTRY ExtractFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam); + +#endif +