Back to index

lightning-sunbird  0.9+nobinonly
nsztool.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 <windows.h>
00041 #include <stdio.h>
00042 #include <io.h>
00043 #include <stdlib.h>
00044 #include <ctype.h>
00045 #include "nsztool.h"
00046 #include "zlib.h"
00047 #include "math.h"
00048 
00049 #define DEFAULT_SEA_FILE "nsinstall.exe"
00050 
00051 /* Function to show the usage for this application */
00052 void ShowUsage(char *name)
00053 {
00054     char szBuf[MAX_BUF];
00055 
00056     wsprintf(szBuf, "Usage: %s <output sea name> <files [file1] [file2]...>\n", name);
00057     lstrcat(szBuf, "\n");
00058     lstrcat(szBuf, "    output sea name: name to use for the self-extracting executable\n");
00059     lstrcat(szBuf, "    files: one or more files to add to the self-extracing executable\n");
00060     MessageBox(NULL, szBuf, "Usage", MB_OK);
00061 }
00062 
00063 /* Function to print error message with/without error code */
00064 void PrintError(LPSTR szMsg, DWORD dwErrorCodeSH)
00065 {
00066   DWORD dwErr;
00067   char  szErrorString[MAX_BUF];
00068 
00069   if(dwErrorCodeSH == ERROR_CODE_SHOW)
00070   {
00071     dwErr = GetLastError();
00072     wsprintf(szErrorString, "%d : %s", dwErr, szMsg);
00073   }
00074   else
00075     wsprintf(szErrorString, "%s", szMsg);
00076 
00077   MessageBox(NULL, szErrorString, NULL, MB_ICONEXCLAMATION);
00078 }
00079 
00080 /* Function to remove quotes from a string */
00081 void RemoveQuotes(LPSTR lpszSrc, LPSTR lpszDest, int iDestSize)
00082 {
00083   char *lpszBegin;
00084 
00085   if(lstrlen(lpszSrc) > iDestSize)
00086     return;
00087 
00088   if(*lpszSrc == '\"')
00089     lpszBegin = &lpszSrc[1];
00090   else
00091     lpszBegin = lpszSrc;
00092 
00093   lstrcpy(lpszDest, lpszBegin);
00094 
00095   if(lpszDest[lstrlen(lpszDest) - 1] == '\"')
00096     lpszDest[lstrlen(lpszDest) - 1] = '\0';
00097 }
00098 
00099 /* Function to remove the last backslash from a path string */
00100 void RemoveBackSlash(LPSTR szInput)
00101 {
00102   int   iCounter;
00103   DWORD dwInputLen;
00104 
00105   if(szInput != NULL)
00106   {
00107     dwInputLen = lstrlen(szInput);
00108 
00109     for(iCounter = dwInputLen -1; iCounter >= 0 ; iCounter--)
00110     {
00111       if(szInput[iCounter] == '\\')
00112         szInput[iCounter] = '\0';
00113       else
00114         break;
00115     }
00116   }
00117 }
00118 
00119 /* Function to append a backslash to a path string */
00120 void AppendBackSlash(LPSTR szInput, DWORD dwInputSize)
00121 {
00122   if(szInput != NULL)
00123   {
00124     if(szInput[strlen(szInput) - 1] != '\\')
00125     {
00126       if(((DWORD)lstrlen(szInput) + 1) < dwInputSize)
00127       {
00128         lstrcat(szInput, "\\");
00129       }
00130     }
00131   }
00132 }
00133 
00134 /* Function to parse a path string for one of three parts of a path:
00135  *   Filename only
00136  *   Path only
00137  *   drive only */
00138 void ParsePath(LPSTR szInput, LPSTR szOutput, DWORD dwOutputSize, DWORD dwType)
00139 {
00140   int   iCounter;
00141   DWORD dwCounter;
00142   DWORD dwInputLen;
00143   BOOL  bFound;
00144 
00145   if((szInput != NULL) && (szOutput != NULL))
00146   {
00147     bFound        = FALSE;
00148     dwInputLen    = lstrlen(szInput);
00149     ZeroMemory(szOutput, dwOutputSize);
00150 
00151     if(dwInputLen < dwOutputSize)
00152     {
00153       switch(dwType)
00154       {
00155         case PP_FILENAME_ONLY:
00156           for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
00157           {
00158             if(szInput[iCounter] == '\\')
00159             {
00160               lstrcpy(szOutput, &szInput[iCounter + 1]);
00161               bFound = TRUE;
00162               break;
00163             }
00164           }
00165           if(bFound == FALSE)
00166             lstrcpy(szOutput, szInput);
00167 
00168           break;
00169 
00170         case PP_PATH_ONLY:
00171           for(iCounter = dwInputLen - 1; iCounter >= 0; iCounter--)
00172           {
00173             if(szInput[iCounter] == '\\')
00174             {
00175               lstrcpy(szOutput, szInput);
00176               szOutput[iCounter + 1] = '\0';
00177               bFound = TRUE;
00178               break;
00179             }
00180           }
00181           if(bFound == FALSE)
00182             lstrcpy(szOutput, szInput);
00183 
00184           break;
00185 
00186         case PP_ROOT_ONLY:
00187           if(szInput[1] == ':')
00188           {
00189             szOutput[0] = szInput[0];
00190             szOutput[1] = szInput[1];
00191             AppendBackSlash(szOutput, dwOutputSize);
00192           }
00193           else if(szInput[1] == '\\')
00194           {
00195             int iFoundBackSlash = 0;
00196             for(dwCounter = 0; dwCounter < dwInputLen; dwCounter++)
00197             {
00198               if(szInput[dwCounter] == '\\')
00199               {
00200                 szOutput[dwCounter] = szInput[dwCounter];
00201                 ++iFoundBackSlash;
00202               }
00203 
00204               if(iFoundBackSlash == 3)
00205                 break;
00206             }
00207 
00208             if(iFoundBackSlash != 0)
00209               AppendBackSlash(szOutput, dwOutputSize);
00210           }
00211           break;
00212       }
00213     }
00214   }
00215 }
00216 
00217 /* Function to check to see if a file exists.
00218  * If it does, return it's attributes */
00219 long FileExists(LPSTR szFile)
00220 {
00221   DWORD rv;
00222 
00223   if((rv = GetFileAttributes(szFile)) == -1)
00224   {
00225     return(FALSE);
00226   }
00227   else
00228   {
00229     return(rv);
00230   }
00231 }
00232 
00233 /* Function to locate the first non space character in a string,
00234  * and return a pointer to it. */
00235 LPSTR GetFirstNonSpace(LPSTR lpszString)
00236 {
00237   int   i;
00238   int   iStrLength;
00239 
00240   iStrLength = lstrlen(lpszString);
00241 
00242   for(i = 0; i < iStrLength; i++)
00243   {
00244     if(!isspace(lpszString[i]))
00245       return(&lpszString[i]);
00246   }
00247 
00248   return(NULL);
00249 }
00250 
00251 /* Function to return the argument count given a command line input
00252  * format string */
00253 int GetArgC(LPSTR lpszCommandLine)
00254 {
00255   int   i;
00256   int   iArgCount;
00257   int   iStrLength;
00258   LPSTR lpszBeginStr;
00259   BOOL  bFoundQuote;
00260   BOOL  bFoundSpace;
00261 
00262   iArgCount    = 0;
00263   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00264 
00265   if(lpszBeginStr == NULL)
00266     return(iArgCount);
00267 
00268   iStrLength   = lstrlen(lpszBeginStr);
00269   bFoundQuote  = FALSE;
00270   bFoundSpace  = TRUE;
00271 
00272   for(i = 0; i < iStrLength; i++)
00273   {
00274     if(lpszCommandLine[i] == '\"')
00275     {
00276       if(bFoundQuote == FALSE)
00277       {
00278         ++iArgCount;
00279         bFoundQuote = TRUE;
00280       }
00281       else
00282       {
00283         bFoundQuote = FALSE;
00284       }
00285     }
00286     else if(bFoundQuote == FALSE)
00287     {
00288       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
00289       {
00290         ++iArgCount;
00291         bFoundSpace = FALSE;
00292       }
00293       else if(isspace(lpszCommandLine[i]))
00294       {
00295         bFoundSpace = TRUE;
00296       }
00297     }
00298   }
00299 
00300   return(iArgCount);
00301 }
00302 
00303 /* Function to return a specific argument parameter from a given command line input
00304  * format string. */
00305 LPSTR GetArgV(LPSTR lpszCommandLine, int iIndex, LPSTR lpszDest, int iDestSize)
00306 {
00307   int   i;
00308   int   j;
00309   int   iArgCount;
00310   int   iStrLength;
00311   LPSTR lpszBeginStr;
00312   LPSTR lpszDestTemp;
00313   BOOL  bFoundQuote;
00314   BOOL  bFoundSpace;
00315 
00316   iArgCount    = 0;
00317   lpszBeginStr = GetFirstNonSpace(lpszCommandLine);
00318 
00319   if(lpszBeginStr == NULL)
00320     return(NULL);
00321 
00322   lpszDestTemp = (char *)calloc(iDestSize, sizeof(char));
00323   if(lpszDestTemp == NULL)
00324   {
00325     PrintError("Out of memory", ERROR_CODE_HIDE);
00326     exit(1);
00327   }
00328 
00329   ZeroMemory(lpszDest, iDestSize);
00330   iStrLength    = lstrlen(lpszBeginStr);
00331   bFoundQuote   = FALSE;
00332   bFoundSpace   = TRUE;
00333   j             = 0;
00334 
00335   for(i = 0; i < iStrLength; i++)
00336   {
00337     if(lpszCommandLine[i] == '\"')
00338     {
00339       if(bFoundQuote == FALSE)
00340       {
00341         ++iArgCount;
00342         bFoundQuote = TRUE;
00343       }
00344       else
00345       {
00346         bFoundQuote = FALSE;
00347       }
00348     }
00349     else if(bFoundQuote == FALSE)
00350     {
00351       if(!isspace(lpszCommandLine[i]) && (bFoundSpace == TRUE))
00352       {
00353         ++iArgCount;
00354         bFoundSpace = FALSE;
00355       }
00356       else if(isspace(lpszCommandLine[i]))
00357       {
00358         bFoundSpace = TRUE;
00359       }
00360     }
00361 
00362     if((iIndex == (iArgCount - 1)) &&
00363       ((bFoundQuote == TRUE) || (bFoundSpace == FALSE) ||
00364       ((bFoundQuote == FALSE) && (lpszCommandLine[i] == '\"'))))
00365     {
00366       if(j < iDestSize)
00367       {
00368         lpszDestTemp[j] = lpszCommandLine[i];
00369         ++j;
00370       }
00371       else
00372       {
00373         lpszDestTemp[j] = '\0';
00374       }
00375     }
00376   }
00377 
00378   RemoveQuotes(lpszDestTemp, lpszDest, iDestSize);
00379   free(lpszDestTemp);
00380   return(lpszDest);
00381 }
00382 
00383 /* Function to add a file to a self-extracting .exe file.
00384  * It compresses the file, then adds it as a resource type "FILE". */
00385 void AddFile(HANDLE hExe, LPSTR lpszFile)
00386 {
00387   char        szBuf[MAX_BUF];
00388   char        szResourceName[MAX_BUF];
00389   HANDLE      hInputFile;
00390   DWORD       dwBytesRead;
00391   DWORD       dwFileSize;
00392   DWORD       dwFileSizeCmp;
00393   LPBYTE      lpBuf;
00394   LPBYTE      lpBufCmp;
00395 
00396   if(!hExe)
00397     exit(1);
00398 
00399   ParsePath(lpszFile, szResourceName, sizeof(szResourceName), PP_FILENAME_ONLY);
00400   strupr(szResourceName);
00401   hInputFile = CreateFile(lpszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00402 
00403   if(hInputFile == INVALID_HANDLE_VALUE)
00404   {
00405     PrintError("CreateFile() failed", ERROR_CODE_SHOW);
00406     exit(1);
00407   }
00408 
00409   dwFileSize    = GetFileSize(hInputFile, NULL);
00410   dwFileSizeCmp = ((long)ceil(dwFileSize * 0.001)) + dwFileSize + 12;
00411   lpBuf         = (LPBYTE)malloc(dwFileSize);
00412   lpBufCmp      = (LPBYTE)malloc(dwFileSizeCmp + (sizeof(DWORD) * 2));
00413   if((lpBuf == NULL) || (lpBufCmp == NULL))
00414   {
00415     PrintError("Out of memory", ERROR_CODE_HIDE);
00416     exit(1);
00417   }
00418 
00419   ReadFile(hInputFile, lpBuf, dwFileSize, &dwBytesRead, NULL);
00420   if(dwBytesRead != dwFileSize)
00421   {
00422     wsprintf(szBuf, "Error reading file: %s", lpszFile);
00423     PrintError(szBuf, ERROR_CODE_HIDE);
00424     exit(1);
00425   }
00426 
00427   if(compress((lpBufCmp + (sizeof(DWORD) * 2)), &dwFileSizeCmp, (const Bytef*)lpBuf, dwFileSize) != Z_OK)
00428   {
00429     PrintError("Error occurred during compression of archives!", ERROR_CODE_HIDE);
00430     exit(1);
00431   }
00432 
00433   *(LPDWORD)lpBufCmp = dwFileSizeCmp;
00434   *(LPDWORD)(lpBufCmp + sizeof(DWORD)) = dwFileSize;
00435 
00436   if(!UpdateResource(hExe, "FILE", szResourceName, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
00437                      lpBufCmp, dwFileSizeCmp + (sizeof(DWORD) * 2)))
00438   {
00439     PrintError("UpdateResource() failed", ERROR_CODE_SHOW);
00440     exit(1);
00441   }
00442 
00443   free(lpBuf);
00444   if(!CloseHandle(hInputFile))
00445   {
00446     PrintError("CloseHandle() failed", ERROR_CODE_SHOW);
00447     exit(1);
00448   }
00449 }
00450 
00451 /* Function to extract a resourced file from a .exe file.
00452  * It also uncompresss the file after extracting it. */
00453 BOOL APIENTRY ExtractFilesProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
00454 {
00455   char    szBuf[MAX_BUF];
00456   HRSRC   hResInfo;
00457   LPSTR   lpszSeaExe = (LPSTR)lParam;
00458   HANDLE  hFile;
00459   LPBYTE  lpBytes;
00460   LPBYTE  lpBytesUnCmp;
00461   HGLOBAL hGlobal;
00462 
00463   // Extract the file
00464   hResInfo = FindResource((HINSTANCE)hModule, lpszName, lpszType);
00465   hGlobal  = LoadResource((HINSTANCE)hModule, hResInfo);
00466   lpBytes  = (LPBYTE)LockResource(hGlobal);
00467 
00468   // Create the file
00469   hFile = CreateFile(lpszSeaExe, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
00470                      FILE_ATTRIBUTE_TEMPORARY, NULL);
00471 
00472   if(hFile != INVALID_HANDLE_VALUE)
00473   {
00474     DWORD dwSize;
00475     DWORD dwSizeUnCmp;
00476 
00477     lpBytesUnCmp = (LPBYTE)malloc((*(LPDWORD)(lpBytes + sizeof(DWORD))) + 1);
00478     dwSizeUnCmp  = *(LPDWORD)(lpBytes + sizeof(DWORD));
00479 
00480     // Copy the file. The first DWORD specifies the size of the file
00481     dwSize = *(LPDWORD)lpBytes;
00482     lpBytes += (sizeof(DWORD) * 2);
00483 
00484     if(uncompress(lpBytesUnCmp, &dwSizeUnCmp, lpBytes, dwSize) != Z_OK)
00485     {
00486       wsprintf(szBuf, "Error occurred during uncompression of %s: ", lpszSeaExe);
00487       PrintError(szBuf, ERROR_CODE_HIDE);
00488       CloseHandle(hFile);
00489       FreeResource(hResInfo);
00490       return FALSE;
00491     }
00492 
00493     while(dwSizeUnCmp > 0)
00494     {
00495       DWORD dwBytesToWrite;
00496       DWORD dwBytesWritten;
00497 
00498       dwBytesToWrite = dwSizeUnCmp > 4096 ? 4096 : dwSizeUnCmp;
00499       if(!WriteFile(hFile, lpBytesUnCmp, dwBytesToWrite, &dwBytesWritten, NULL))
00500       {
00501         wsprintf(szBuf, "%s: write error", lpszSeaExe);
00502         MessageBox(NULL, szBuf, "Error", MB_OK | MB_ICONEXCLAMATION);
00503         CloseHandle(hFile);
00504         FreeResource(hResInfo);
00505         return FALSE;
00506       }
00507 
00508       dwSizeUnCmp -= dwBytesWritten;
00509       lpBytesUnCmp += dwBytesWritten;
00510     }
00511 
00512     CloseHandle(hFile);
00513   }
00514 
00515   // Release the resource
00516   FreeResource(hResInfo);
00517 
00518   return TRUE;  // keep enumerating
00519 }
00520 
00521 HANDLE InitResource(LPSTR lpszSeaExe)
00522 {
00523   HANDLE hExe;
00524 
00525   if((hExe = BeginUpdateResource(lpszSeaExe, FALSE)) == NULL)
00526   {
00527     DWORD dwErr;
00528 
00529     dwErr = GetLastError();
00530     if(dwErr == ERROR_CALL_NOT_IMPLEMENTED)
00531     {
00532       MessageBox(NULL, "This application does not run under this OS", NULL, MB_ICONEXCLAMATION);
00533       exit(0);
00534     }
00535     else
00536     {
00537       PrintError("BeginUpdateResource() error", ERROR_CODE_SHOW);
00538       exit(1);
00539     }
00540   }
00541   return(hExe);
00542 }
00543 
00544 void DeInitResource(HANDLE hExe)
00545 {
00546   if(!EndUpdateResource(hExe, FALSE))
00547   {
00548     PrintError("EndUpdateResource() failed", ERROR_CODE_SHOW);
00549     exit(1);
00550   }
00551 }
00552 
00553 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
00554 {
00555   int               i;
00556   int               iArgC;
00557   char              szBuf[MAX_BUF];
00558   char              szArgVBuf[MAX_BUF];
00559   char              szFileFullPath[MAX_BUF];
00560   char              szSeaExe[MAX_BUF];
00561   char              szNsZipName[MAX_BUF];
00562   char              szAppName[MAX_BUF];
00563   char              szAppPath[MAX_BUF];
00564 
00565 #ifdef SSU_DEBUG
00566   char              szOutputStr[MAX_BUF];
00567 #endif
00568 
00569   WIN32_FIND_DATA   findFileData;
00570   HANDLE            hExe;
00571   HANDLE            hFindFile;
00572   BOOL              bSelfUpdate;
00573 
00574   if(GetModuleFileName(NULL, szAppName, sizeof(szAppName)) == 0L)
00575   {
00576     PrintError("GetModuleFileName() failed", ERROR_CODE_SHOW);
00577     exit(1);
00578   }
00579   ParsePath(szAppName, szBuf, sizeof(szBuf), PP_FILENAME_ONLY);
00580   ParsePath(szAppPath, szBuf, sizeof(szBuf), PP_PATH_ONLY);
00581 
00582   if(*lpszCmdLine == '\0')
00583   {
00584     ShowUsage(szBuf);
00585     exit(1);
00586   }
00587 
00588   iArgC = GetArgC(lpszCmdLine);
00589   bSelfUpdate = FALSE;
00590 
00591 #ifdef SSU_DEBUG
00592   wsprintf(szOutputStr, "ArgC: %d\n", iArgC);
00593   for(i = 0; i < iArgC; i++)
00594   {
00595     GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
00596     itoa(i, szBuf, 10);
00597     lstrcat(szOutputStr, "    ");
00598     lstrcat(szOutputStr, szBuf);
00599     lstrcat(szOutputStr, ": ");
00600     lstrcat(szOutputStr, szArgVBuf);
00601     lstrcat(szOutputStr, "\n");
00602   }
00603   MessageBox(NULL, szOutputStr, "Output", MB_OK);
00604 #endif
00605 
00606   /* Get the first parameter */
00607   GetArgV(lpszCmdLine, 0, szSeaExe, sizeof(szSeaExe));
00608   if(lstrcmpi(szSeaExe, "-g") == 0)
00609   {
00610     /* The first parameter is "-g".
00611      * Create a new nszip that contains nsinstall.exe in itself */
00612 
00613     GetArgV(lpszCmdLine, 1, szNsZipName, sizeof(szNsZipName));
00614     GetArgV(lpszCmdLine, 2, szSeaExe, sizeof(szSeaExe));
00615     if(!FileExists(szSeaExe))
00616     {
00617       wsprintf(szBuf, "file not found: %s", szSeaExe);
00618       PrintError(szBuf, ERROR_CODE_HIDE);
00619       exit(1);
00620     }
00621 
00622     if(GetModuleFileName(NULL, szAppName, sizeof(szAppName)) == 0L)
00623     {
00624       PrintError("GetModuleFileName() failed", ERROR_CODE_SHOW);
00625       exit(1);
00626     }
00627     if(!FileExists(szAppName))
00628     {
00629       wsprintf(szBuf, "File not found: %s", szAppName);
00630       PrintError(szBuf, ERROR_CODE_HIDE);
00631       exit(1);
00632     }
00633 
00634     if(CopyFile(szAppName, szNsZipName, FALSE) == FALSE)
00635     {
00636       wsprintf(szBuf, "Error creating %s", szNsZipName);
00637       PrintError(szBuf, ERROR_CODE_SHOW);
00638       exit(1);
00639     }
00640 
00641     hExe = InitResource(szNsZipName);
00642     AddFile(hExe, szSeaExe);
00643     DeInitResource(hExe);
00644     return(0);
00645   }
00646   else
00647   {
00648     /* The first parameter is not "-g".  Assume that it's the name of the
00649      * self-extracting .exe to be saved as.  So lets create it only if it does not exist. */
00650 
00651     if(!FileExists(szSeaExe))
00652     {
00653       EnumResourceNames(NULL, "FILE", (ENUMRESNAMEPROC)ExtractFilesProc, (LONG)szSeaExe);
00654 
00655       // if still does not exist, copy nsinstall.exe to szSeaExe
00656       if(!FileExists(szSeaExe))
00657       {
00658         if(FileExists(DEFAULT_SEA_FILE))
00659           CopyFile(DEFAULT_SEA_FILE, szSeaExe, FALSE);
00660         else
00661         {
00662           wsprintf(szBuf, "file not found: %s", DEFAULT_SEA_FILE);
00663           PrintError(szBuf, ERROR_CODE_HIDE);
00664           exit(1);
00665         }
00666       }
00667     }
00668 
00669     if(!FileExists(szSeaExe))
00670     {
00671       wsprintf(szBuf, "file not found: %s", szSeaExe);
00672       PrintError(szBuf, ERROR_CODE_HIDE);
00673       exit(1);
00674     }
00675   }
00676 
00677   hExe = InitResource(szSeaExe);
00678   for(i = 1; i < iArgC; i++)
00679   {
00680     GetArgV(lpszCmdLine, i, szArgVBuf, sizeof(szArgVBuf));
00681     GetFullPathName(szArgVBuf, sizeof(szFileFullPath), szFileFullPath, NULL);
00682     hFindFile = FindFirstFile(szFileFullPath, &findFileData);
00683 
00684     if(hFindFile == INVALID_HANDLE_VALUE)
00685     {
00686       wsprintf(szBuf, "file not found: %s", szArgVBuf);
00687       PrintError(szBuf, ERROR_CODE_HIDE);
00688       exit(1);
00689     }
00690 
00691     do
00692     {
00693       char szFile[MAX_BUF];
00694 
00695       if(!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
00696       {
00697         // We need to pass to AddFile() whatever kind of path we were passed,
00698         // e.g. simple, relative, full
00699         strcpy(szFile, szFileFullPath);
00700         strcpy(strrchr(szFile, '\\') + 1, findFileData.cFileName);
00701         AddFile(hExe, szFile);
00702       }
00703     } while(FindNextFile(hFindFile, &findFileData));
00704 
00705     FindClose(hFindFile);
00706   }
00707 
00708   DeInitResource(hExe);
00709   return(0);
00710 }
00711