diff --git a/Contrib/ExDLL/exdll.c b/Contrib/ExDLL/exdll.c new file mode 100644 index 00000000..7c2ea1c3 --- /dev/null +++ b/Contrib/ExDLL/exdll.c @@ -0,0 +1,102 @@ +#include + +typedef struct _stack_t { + struct _stack_t *next; + char text[1]; // this should be the length of string_size +} stack_t; + +int popstring(char *str); // 0 on success, 1 on empty stack +void pushstring(char *str); + +enum +{ +INST_0, // $0 +INST_1, // $1 +INST_2, // $2 +INST_3, // $3 +INST_4, // $4 +INST_5, // $5 +INST_6, // $6 +INST_7, // $7 +INST_8, // $8 +INST_9, // $9 +INST_R0, // $R0 +INST_R1, // $R1 +INST_R2, // $R2 +INST_R3, // $R3 +INST_R4, // $R4 +INST_R5, // $R5 +INST_R6, // $R6 +INST_R7, // $R7 +INST_R8, // $R8 +INST_R9, // $R9 +INST_CMDLINE, // $CMDLINE +INST_INSTDIR, // $INSTDIR +INST_OUTDIR, // $OUTDIR +INST_EXEDIR, // $EXEDIR +__INST_LAST +}; + +char *getuservariable(int varnum); + + +HINSTANCE g_hInstance; +HWND g_hwndParent; +int g_stringsize; +stack_t **g_stacktop; +char *g_variables; + +void __declspec(dllexport) myFunction(HWND hwndParent, int string_size, + char *variables, stack_t **stacktop) +{ + g_hwndParent=hwndParent; + g_stringsize=string_size; + g_stacktop=stacktop; + g_variables=variables; + + // do your stuff here + { + char buf[1024]; + wsprintf(buf,"$0=%s\n",getuservariable(INST_0)); + MessageBox(g_hwndParent,buf,0,MB_OK); + } +} + + + +BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + g_hInstance=hInst; + return TRUE; +} + + +// utility functions (not required but often useful) +int popstring(char *str) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + lstrcpy(str,th->text); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +void pushstring(char *str) +{ + stack_t *th; + if (!g_stacktop) return; + th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize); + lstrcpyn(th->text,str,g_stringsize); + th->next=*g_stacktop; + *g_stacktop=th; +} + +char *getuservariable(int varnum) +{ + if (varnum < 0 || varnum >= __INST_LAST) return NULL; + return g_variables+varnum*g_stringsize; +} + + diff --git a/Contrib/ExDLL/exdll.dpr b/Contrib/ExDLL/exdll.dpr new file mode 100644 index 00000000..ff1f613f --- /dev/null +++ b/Contrib/ExDLL/exdll.dpr @@ -0,0 +1,122 @@ +{ + NSIS ExDLL example + (C) 2001 - Peter Windridge + + Fixed and formatted by Alexander Tereschenko + http://futuris.plastiqueweb.com/ + + Tested in Delphi 6.01 +} + +library exdll; + +uses Windows; + +type + VarConstants = ( + INST_0, + INST_1, // $1 + INST_2, // $2 + INST_3, // $3 + INST_4, // $4 + INST_5, // $5 + INST_6, // $6 + INST_7, // $7 + INST_8, // $8 + INST_9, // $9 + INST_R0, // $R0 + INST_R1, // $R1 + INST_R2, // $R2 + INST_R3, // $R3 + INST_R4, // $R4 + INST_R5, // $R5 + INST_R6, // $R6 + INST_R7, // $R7 + INST_R8, // $R8 + INST_R9, // $R9 + INST_CMDLINE, // $CMDLINE + INST_INSTDIR, // $INSTDIR + INST_OUTDIR, // $OUTDIR + INST_EXEDIR, // $EXEDIR + __INST_LAST + ); + TVariableList = INST_0..__INST_LAST; + pstack_t = ^stack_t; + stack_t = record + next: pstack_t; + text: PChar; + end; + +var + g_stringsize: integer; + g_stacktop: ^pstack_t; + g_variables: PChar; + g_hwndParent: HWND; + +function PopString(str: PChar):integer; +var + th: pstack_t; +begin + if integer(g_stacktop^) = 0 then + begin + Result:=1; + Exit; + end; + th:=g_stacktop^; + lstrcpy(str,@th.text); + g_stacktop^ := th.next; + GlobalFree(HGLOBAL(th)); + Result:=0; +end; + +function PushString(str: PChar):integer; +var + th: pstack_t; +begin + if integer(g_stacktop) = 0 then + begin + Result:=1; + Exit; + end; + th:=pstack_t(GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize)); + lstrcpyn(@th.text,str,g_stringsize); + th.next:=g_stacktop^; + g_stacktop^:=th; + Result:=0; +end; + +function GetUserVariable(varnum: TVariableList):PChar; +begin + if (integer(varnum) < 0) or (integer(varnum) >= integer(__INST_LAST)) then + begin + Result:=''; + Exit; + end; + Result:=g_variables+integer(varnum)*g_stringsize; +end; + +function ex_dll(hwndParent: HWND; string_size: integer; variables: PChar; stacktop: pointer):integer; cdecl; +var + c: PChar; + buf: array[0..1024] of char; +begin + // set up global variables + g_stringsize:=string_size; + g_hwndParent:=hwndParent; + g_stringsize:=string_size; + g_stacktop:=stacktop; + g_variables:=variables; + + c:=GetUserVariable(INST_0); + MessageBox(g_hwndParent,c,'The value of $0',MB_OK); + PopString(@buf); + MessageBox(g_hwndParent,@buf,'pop',MB_OK); + PushString(PChar('Hello, this is a push')); + + Result:=1; +end; + +exports ex_dll; + +begin +end. diff --git a/Contrib/ExDLL/exdll.dsp b/Contrib/ExDLL/exdll.dsp new file mode 100644 index 00000000..af6c95c6 --- /dev/null +++ b/Contrib/ExDLL/exdll.dsp @@ -0,0 +1,107 @@ +# Microsoft Developer Studio Project File - Name="exdll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=exdll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "exdll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "exdll.mak" CFG="exdll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "exdll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "exdll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "exdll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXDLL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXDLL_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"../../exdll.dll" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "exdll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXDLL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXDLL_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "exdll - Win32 Release" +# Name "exdll - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\exdll.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/Contrib/ExDLL/exdll.dsw b/Contrib/ExDLL/exdll.dsw new file mode 100644 index 00000000..e8a07c1a --- /dev/null +++ b/Contrib/ExDLL/exdll.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "exdll"=.\exdll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/Icons/checks1.bmp b/Contrib/Icons/checks1.bmp new file mode 100644 index 00000000..81597154 Binary files /dev/null and b/Contrib/Icons/checks1.bmp differ diff --git a/Contrib/Icons/checks2.bmp b/Contrib/Icons/checks2.bmp new file mode 100644 index 00000000..e88402aa Binary files /dev/null and b/Contrib/Icons/checks2.bmp differ diff --git a/Contrib/Icons/checks4.bmp b/Contrib/Icons/checks4.bmp new file mode 100644 index 00000000..9ec0527c Binary files /dev/null and b/Contrib/Icons/checks4.bmp differ diff --git a/Contrib/Icons/checksX.bmp b/Contrib/Icons/checksX.bmp new file mode 100644 index 00000000..43d5dd65 Binary files /dev/null and b/Contrib/Icons/checksX.bmp differ diff --git a/Contrib/Icons/checksX2.bmp b/Contrib/Icons/checksX2.bmp new file mode 100644 index 00000000..ede88a0f Binary files /dev/null and b/Contrib/Icons/checksX2.bmp differ diff --git a/Contrib/Icons/jarsonic-checks.bmp b/Contrib/Icons/jarsonic-checks.bmp new file mode 100644 index 00000000..d5766d0e Binary files /dev/null and b/Contrib/Icons/jarsonic-checks.bmp differ diff --git a/Contrib/Icons/lucas-checks.bmp b/Contrib/Icons/lucas-checks.bmp new file mode 100644 index 00000000..733f8de1 Binary files /dev/null and b/Contrib/Icons/lucas-checks.bmp differ diff --git a/Contrib/Icons/normal-install.ico b/Contrib/Icons/normal-install.ico new file mode 100644 index 00000000..55c32414 Binary files /dev/null and b/Contrib/Icons/normal-install.ico differ diff --git a/Contrib/Icons/normal-uninstall.ico b/Contrib/Icons/normal-uninstall.ico new file mode 100644 index 00000000..9b336f06 Binary files /dev/null and b/Contrib/Icons/normal-uninstall.ico differ diff --git a/Contrib/Icons/setup.ico b/Contrib/Icons/setup.ico new file mode 100644 index 00000000..28339848 Binary files /dev/null and b/Contrib/Icons/setup.ico differ diff --git a/Contrib/InstallOptions/Install Options.html b/Contrib/InstallOptions/Install Options.html new file mode 100644 index 00000000..e70efde2 --- /dev/null +++ b/Contrib/InstallOptions/Install Options.html @@ -0,0 +1,363 @@ +Install Options/DLL Documentation + +
Install +Options (/DLL)
Copyright © 2001 Michael +Bishop (original version) and Nullsoft, Inc. (DLL conversion and integration) +
+ +
+Introduction:
Installer Options was a quick +application Michael Bishop threw together so he could prompt the user for some information +during the install process. This version is a highly modified version of it that is designed +as a NSIS extension DLL for the
NSIS installer. Installer Options will create a +dialog box which will be displayed inside of the NSIS window. The dialog box is +defined by an INI file, which allows you to define the layout of controls by +changing the INI file. +

To use the DLL, you should include it as part of your installation. +Extract it to known location (probably $TEMP), and then load it using CallInstDLL, passing one parameter on the stack. +The one parameter is a name of an .ini file that defines the window. +Example:

+	SetOutPath $TEMP
+	File inst.ini
+	File InstallOptions.dll
+	Push $TEMP\inst.ini
+ 	CallInstDLL $TEMP\InstallOptions.dll dialog
+        Pop $0 
+        ;  ($0 would be "success" "cancel" "back" or some other value on error.
+
+	ReadINIStr $1 $TEMP\inst.ini "Field 1" State ; $1 = field #1's state
+
+	Delete $TEMP\inst.nsi
+	Delete $TEMP\InstallOptions.dll
+
+It is often very useful to call InstallOptions from the NSIS callback functions .onNextPage and .onPrevPage. +

The INI file has one required section. This section includes the number of controls to be created as well as general window attributes. The INI file also +includes a variable number of Field sections which are used to create the +controls to be displayed. +

The required section is named "Settings". It will contain the +following values: +

+

Each field section has the heading "Field #" where # must be sequential +numbers from 1 to NumFields. Each Field section contains the following values: +

+
+History: +

+

+
+
  Copyright © 2001 Michael Bishop
+  Portions Copyright © 2001 Nullsoft, Inc.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp new file mode 100644 index 00000000..0dea3606 --- /dev/null +++ b/Contrib/InstallOptions/InstallerOptions.cpp @@ -0,0 +1,1074 @@ +/********************************************************************************* + * + * InstallerOptions by Michael Bishop: + * InstallerOptions/DLL Version 1.2 beta + * + * highly modified by justin frankel to go in as dll, subclass, be sexy, and whatnot. + * + * key changes + * - no longer need parentwnd ini writing shit + * - to call now, use: + * Push $TEMP\inst.ini + * CallInstDLL $TEMP\mydll.dll dialog + * Pop $0 + * ($0 would be "success" "cancel" "back" or some other value on error. + * - new INI entries: [settings]\cancelconfirm (text to confirm cancel on cancel button click) + * - fixed some flag related bugs (multiple of them at 0x100 etc) + * - made it so you can specify positions in negative, for distance from the right/bottom edges. + * - made it so that the file/dir requests automatically size the browse button in + * - removed a lot of code for the old style integration + * - removed support for silent installers (it seems the old version would bring up it's own dialog) + * + * - keyboard integration fixed + * - fixed issues with file open dialog too + * + * - added BackEnabled, fixed more (getting it ready to use with closer integration to nsis 1.90) + * + * - results are now read differently from the .ini file. Instead of [Results]\, + * use [Field ]\State + * + * - The state of checkboxes and radioboxes is now defined by State=. State=1 is checked, + * State=0 (or no State=) is unchecked. + * + * - The initial contents of edit controls and file/dir request controls is now defined by + * State= instead of Text=. + * + * - Font is now taken from the main NSIS window (by Amir Szekely 22nd July 2002) + * + * - Added CancelEnabled (by ORTIM) + * + * - Added CancelConfirmCaption and CancelConfirmIcon (by Amir Szekely) + * + * Copyright (C) 2001 Michael Bishop + * Portions Copyright (C) 2001 Nullsoft, Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + **********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "resource.h" + +typedef struct _stack_t { + struct _stack_t *next; + char text[1]; // this should be the length of string_size +} stack_t; + +int popstring(char *str); // 0 on success, 1 on empty stack +void pushstring(char *str); + +enum +{ +INST_0, // $0 +INST_1, // $1 +INST_2, // $2 +INST_3, // $3 +INST_4, // $4 +INST_5, // $5 +INST_6, // $6 +INST_7, // $7 +INST_8, // $8 +INST_9, // $9 +INST_R0, // $R0 +INST_R1, // $R1 +INST_R2, // $R2 +INST_R3, // $R3 +INST_R4, // $R4 +INST_R5, // $R5 +INST_R6, // $R6 +INST_R7, // $R7 +INST_R8, // $R8 +INST_R9, // $R9 +INST_CMDLINE, // $CMDLINE +INST_INSTDIR, // $INSTDIR +INST_OUTDIR, // $OUTDIR +INST_EXEDIR, // $EXEDIR +__INST_LAST +}; + +char *getuservariable(int varnum); + + +int g_stringsize; +stack_t **g_stacktop; +char *g_variables; + +#define strcpy(x,y) lstrcpy(x,y) +#define strncpy(x,y,z) lstrcpyn(x,y,z) +#define strdup(x) STRDUP(x) +#define stricmp(x,y) lstrcmpi(x,y) +//#define abs(x) ((x) < 0 ? -(x) : (x)) + +void *MALLOC(int len) { return (void*)GlobalAlloc(GPTR,len); } +void FREE(void *d) { if (d) GlobalFree((HGLOBAL)d); } + +char *STRDUP(const char *c) +{ + char *t=(char*)MALLOC(lstrlen(c)+1); + lstrcpy(t,c); + return t; +} + +#define FIELD_BROWSEBUTTON (1) +#define FIELD_LABEL (2) +#define FIELD_TEXT (3) +#define FIELD_COMBOBOX (4) +#define FIELD_FILEREQUEST (5) +#define FIELD_DIRREQUEST (6) +#define FIELD_CHECKBOX (7) +#define FIELD_RADIOBUTTON (8) +#define FIELD_LISTBOX (9) + +// general flags +#define FLAG_BOLD (0x1) +#define FLAG_RIGHT (0x2) + +// text box flags +#define FLAG_PASSWORD (0x100) + +// listbox flags +#define FLAG_MULTISELECT (0x200) + +// combobox flags +#define FLAG_DROPLIST (0x400) + +struct TableEntry { + char *pszName; + int nBitsToSet; +}; + +struct FieldType { + char *pszText; + char *pszState; + char *pszRoot; + + char *pszListItems; + char *pszFilter; + + int nType; + RECT rect; + + int nMinLength; + int nMaxLength; + char *pszValidateText; + + int nFlags; + bool bSaveDlg; + + HWND hwnd; + UINT nControlID; + + int nParentIdx; // this is used by the filerequest and dirrequest controls +}; + +// initial buffer size. buffers will grow as required. +// use a value larger than MAX_PATH to prevent need for excessive growing. +#define MAX_BUFFER_LENGTH (300) + +char szBrowseButtonCaption[] = "..."; + +HWND hConfigWindow = NULL; +HWND hMainWindow = NULL; +HINSTANCE m_hInstance = NULL; + +char *pszTitle = NULL; +char *pszCancelQuestion = NULL; +char *pszCancelQuestionCaption = NULL; +char *pszCancelButtonText = NULL; +char *pszNextButtonText = NULL; +char *pszBackButtonText = NULL; +char *pszOldTitle = NULL; +unsigned int nCancelQuestionIcon = 0; +BOOL bBackEnabled=FALSE; +BOOL bCancelEnabled=TRUE; // by ORTIM + +FieldType *pFields = NULL; +int nNumFields = 0; +int g_done; + +// will contain a count of the number of controls on the main NSIS window. +unsigned int nNSISControlCount = 0; + +struct WindowEntry { + HWND hwnd; + long nOldStyle; +}; + + +// array of HWNDs and window styles used to make the main NSIS controls invisible while this program runs. + +bool BrowseForFile(int nControlIdx) { + OPENFILENAME ofn={0,}; + HWND hControl; + BOOL bResult; + FieldType *pThisField = &pFields[nControlIdx]; + + hControl = pThisField->hwnd; + + ofn.Flags = pThisField->nFlags; + +// ofn.hInstance = m_hInstance; // no templates so we can leave this at NULL; + ofn.hwndOwner = hConfigWindow; +// ofn.lCustData = NULL; +// ofn.lpfnHook = NULL; +// ofn.lpstrCustomFilter = NULL; +// ofn.lpstrDefExt = NULL; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFile = (char*)MALLOC(ofn.nMaxFile); + +// ofn.nMaxFileTitle = MAX_PATH; // we ignore this for simplicity, leave lpstrFileTitle at NULL +// ofn.lpstrFileTitle = new char [ofn.nMaxFileTitle]; + + ofn.lpstrFilter = pThisField->pszFilter; // TODO: implement this +// ofn.lpstrInitialDir = NULL; // for now, just use the default initial directory. +// ofn.lpstrTitle = NULL; // TODO: implement this +// ofn.lpTemplateName = NULL; + ofn.lStructSize = sizeof(ofn); +// ofn.nFileExtension // this is output variable, leave it to 0 for now. +// ofn.nFileOffset // this is output variable, leave it to 0 for now. +// ofn.nFilterIndex = 1; // since we use no custom filters, leaving it at 0 means use the first. +// ofn.nMaxCustFilter = 0; + + GetWindowText(hControl, ofn.lpstrFile, ofn.nMaxFile); + + for(;;) { + if (pThisField->bSaveDlg) { + bResult = GetSaveFileName(&ofn); + } else { + bResult = GetOpenFileName(&ofn); + } + if (bResult) { + SetWindowText(hControl, ofn.lpstrFile); + return true; + } + // check this because the dialog will sometimes return this error just because a directory is specified + // instead of a filename. in this case, try it without the initial filename and see if that works. +// if (*(ofn.lpstrFile)) { //&& (CommDlgExtendedError() == FNERR_INVALIDFILENAME)) { + // *(ofn.lpstrFile) = '\0'; + // } else { + break; + // } + } + + return false; +} + + +int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData) { + TCHAR szDir[MAX_PATH]; + + if (uMsg == BFFM_INITIALIZED) { + if (GetWindowText(pFields[(int)pData].hwnd, szDir, MAX_PATH) > 0) { + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szDir); + } + } + return 0; +} + + +bool BrowseForFolder(int nControlIdx) { + BROWSEINFO bi={0,}; + HWND hControl; + + hControl = pFields[nControlIdx].hwnd; + + bi.hwndOwner = hConfigWindow; + // bi.pidlRoot = NULL; + bi.pszDisplayName = (char*)MALLOC(MAX_PATH); + //LPCTSTR lpszTitle = NULL; + bi.ulFlags = BIF_STATUSTEXT; + bi.lpfn = BrowseCallbackProc; + bi.lParam = nControlIdx; + //bi.iImage = 0; + + if (pFields[nControlIdx].pszRoot) { + LPSHELLFOLDER sf; + ULONG eaten; + LPITEMIDLIST root; +#define _alloca MALLOC + USES_CONVERSION; + LPOLESTR s = A2OLE(pFields[nControlIdx].pszRoot); +#undef _alloca + SHGetDesktopFolder(&sf); + sf->ParseDisplayName(hConfigWindow, NULL, (unsigned short *)s, &eaten, &root, NULL); + bi.pidlRoot = root; + sf->Release(); + FREE(s); + } +// CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + LPITEMIDLIST pResult = SHBrowseForFolder(&bi); + if (!pResult) { + FREE(bi.pszDisplayName); + return false; + } + + char *pszFolder = (char*)MALLOC(MAX_PATH); + if (SHGetPathFromIDList(pResult, pszFolder)) { + SetWindowText(hControl, pszFolder); + } + + LPMALLOC pMalloc; + if (!SHGetMalloc(&pMalloc)) { + pMalloc->Free(pResult); + } + + FREE(bi.pszDisplayName); + FREE(pszFolder); + + return true; +} + +bool ValidateFields() { + int nIdx; + int nLength; + + // In the unlikely event we can't allocate memory, go ahead and return true so we can get out of here. + // May cause problems for the install script, but no memory is problems for us. + for (nIdx = 0; nIdx < nNumFields; nIdx++) { + // this if statement prevents a stupid bug where a min/max length is assigned to a label control + // where the user obviously has no way of changing what is displayed. (can you say, "infinite loop"?) + if (pFields[nIdx].nType > FIELD_LABEL) { + nLength = GetWindowTextLength(pFields[nIdx].hwnd); + + if (((pFields[nIdx].nMaxLength > 0) && (nLength > pFields[nIdx].nMaxLength)) || + ((pFields[nIdx].nMinLength > 0) && (nLength < pFields[nIdx].nMinLength))) { + if (pFields[nIdx].pszValidateText) { + MessageBox(hConfigWindow, pFields[nIdx].pszValidateText, NULL, MB_OK); + } + SetFocus(pFields[nIdx].hwnd); + return false; + } + + } + } + return true; +} + +bool SaveSettings(LPSTR pszFilename) { + char szField[25]; + int nIdx; + HWND hwnd; + int nBufLen = MAX_BUFFER_LENGTH; + char *pszBuffer = (char*)MALLOC(nBufLen); + + if (!pszBuffer) return false; + for(nIdx = 0; nIdx < nNumFields; nIdx++) { + hwnd = pFields[nIdx].hwnd; + wsprintf(szField, "Field %d", nIdx + 1); + switch(pFields[nIdx].nType) { + case FIELD_CHECKBOX: + case FIELD_RADIOBUTTON: + { + wsprintf(pszBuffer, "%d", !!SendMessage(hwnd, BM_GETCHECK, 0, 0)); + break; + } + case FIELD_LISTBOX: + { + // Ok, this one requires a bit of work. + // First, we allocate a buffer long enough to hold every item. + // Then, we loop through every item and if it's selected we add it to our buffer. + // If there is already an item in the list, then we prepend a | character before the new item. + // We could simplify for single-select boxes, but using one piece of code saves some space. + int nLength = lstrlen(pFields[nIdx].pszListItems) + 10; + if (nLength > nBufLen) { + FREE(pszBuffer); + nBufLen = nLength; + pszBuffer = (char*)MALLOC(nBufLen); + if (!pszBuffer) return false; + } + char *pszItem = (char*)MALLOC(nBufLen); + + *pszBuffer = '\0'; + int nNumItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + for(int nIdx2 = 0; nIdx2 < nNumItems; nIdx2++) { + if (SendMessage(hwnd, LB_GETSEL, nIdx2, 0) > 0) { + if (*pszBuffer) lstrcat(pszBuffer, "|"); + SendMessage(hwnd, LB_GETTEXT, (WPARAM)nIdx2, (LPARAM)pszItem); + lstrcat(pszBuffer, pszItem); + } + } + + FREE(pszItem); + break; + } + default: + { + int nLength = GetWindowTextLength(pFields[nIdx].hwnd); + if (nLength > nBufLen) { + FREE(pszBuffer); + // add a bit extra so we do this less often + nBufLen = nLength + 20; + pszBuffer = (char*)MALLOC(nBufLen); + if (!pszBuffer) return false; + } + GetWindowText(hwnd, pszBuffer, nBufLen); + break; + } + } + WritePrivateProfileString(szField, "STATE", pszBuffer, pszFilename); + } + + FREE(pszBuffer); + + return true; +} + +void AddBrowseButtons() { + // this function loops through all the controls and if a filerequest or dirrequest + // control is found, then it adds the corresponding browse button. + // NOTE: this also resizes the text box created to make room for the button. + int nIdx; + int nWidth = 22; + FieldType *pNewField; + + for (nIdx = nNumFields - 1; nIdx >= 0; nIdx--) { + // we loop down so we don't run into the newly added fields. + switch (pFields[nIdx].nType) { + case FIELD_FILEREQUEST: + case FIELD_DIRREQUEST: + pNewField = &pFields[nNumFields]; + // nNumFields functions as the index of the new control, increment at *end* of loop + pNewField->nControlID = 1200 + nNumFields; + pNewField->nParentIdx = nIdx; + pNewField->nType = FIELD_BROWSEBUTTON; + //pNewField->pszListItems = NULL; + //pNewField->nMaxLength = 0; + //pNewField->nMinLength = 0; + pNewField->pszText = szBrowseButtonCaption; //STRDUP("..."); + //pNewField->pszValidateText = NULL; + + pNewField->rect.right = pFields[nIdx].rect.right; + pNewField->rect.left = pNewField->rect.right - nWidth; + pNewField->rect.bottom = pFields[nIdx].rect.bottom; + pNewField->rect.top = pFields[nIdx].rect.top; + + pFields[nIdx].rect.right = pNewField->rect.right - 3 - nWidth; + + pNewField->rect.right-=nWidth; + pNewField->rect.left-=nWidth; + + + + nNumFields++; + break; + } + } +} + +bool ReadSettings(LPSTR pszFilename) { + int nResult; + char *pszResult; + char pszField[25]; + int nSize; + int nIdx; + + nSize = 1000; + pszResult = (char*)MALLOC(nSize); // buffer to read from the file + if (!pszResult) return false; + + nResult = GetPrivateProfileString("Settings", "Title", "", pszResult, nSize, pszFilename); + pszTitle = (nResult > 0) ? strdup(pszResult) : NULL; + + nResult = GetPrivateProfileString("Settings", "CancelConfirm", "", pszResult, nSize, pszFilename); + pszCancelQuestion = (nResult > 0) ? strdup(pszResult) : NULL; + nResult = GetPrivateProfileString("Settings", "CancelConfirmCaption", "", pszResult, nSize, pszFilename); + pszCancelQuestionCaption = (nResult > 0) ? strdup(pszResult) : NULL; + nResult = GetPrivateProfileString("Settings", "CancelConfirmIcon", "", pszResult, nSize, pszFilename); + if (!lstrcmpi(pszResult, "MB_ICONEXCLAMATION")) + nCancelQuestionIcon = MB_ICONEXCLAMATION; + else if (!lstrcmpi(pszResult, "MB_ICONWARNING")) + nCancelQuestionIcon = MB_ICONWARNING; + else if (!lstrcmpi(pszResult, "MB_ICONINFORMATION")) + nCancelQuestionIcon = MB_ICONINFORMATION; + else if (!lstrcmpi(pszResult, "MB_ICONASTERISK")) + nCancelQuestionIcon = MB_ICONASTERISK; + else if (!lstrcmpi(pszResult, "MB_ICONQUESTION")) + nCancelQuestionIcon = MB_ICONQUESTION; + else if (!lstrcmpi(pszResult, "MB_ICONSTOP")) + nCancelQuestionIcon = MB_ICONSTOP; + else if (!lstrcmpi(pszResult, "MB_ICONERROR")) + nCancelQuestionIcon = MB_ICONERROR; + else if (!lstrcmpi(pszResult, "MB_ICONHAND")) + nCancelQuestionIcon = MB_ICONHAND; + + nResult = GetPrivateProfileString("Settings", "CancelButtonText", "", pszResult, nSize, pszFilename); + pszCancelButtonText = (nResult > 0) ? strdup(pszResult) : NULL; + nResult = GetPrivateProfileString("Settings", "NextButtonText", "", pszResult, nSize, pszFilename); + pszNextButtonText = (nResult > 0) ? strdup(pszResult) : NULL; + nResult = GetPrivateProfileString("Settings", "BackButtonText", "", pszResult, nSize, pszFilename); + pszBackButtonText = (nResult > 0) ? strdup(pszResult) : NULL; + + nNumFields = GetPrivateProfileInt("Settings", "NumFields", 0, pszFilename); + bBackEnabled = GetPrivateProfileInt("Settings", "BackEnabled", 0, pszFilename); + bCancelEnabled = GetPrivateProfileInt("Settings", "CancelEnabled", 1, pszFilename); // by ORTIM + + if (nNumFields > 0) { + // make this twice as large for the worst case that every control is a browse button. + // the structure is small enough that this won't waste much memory. + // if the structure gets much larger, we should switch to a linked list. + pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields); + } + + for(nIdx = 0; nIdx < nNumFields; nIdx++) { + wsprintf(pszField, "field %d", nIdx + 1); + + *pszResult = '\0'; + nResult = GetPrivateProfileString(pszField, "TYPE", "", pszResult, nSize, pszFilename); + if (!stricmp(pszResult, "LABEL")) { + pFields[nIdx].nType = FIELD_LABEL; + } else if (!stricmp(pszResult, "TEXT")) { + pFields[nIdx].nType = FIELD_TEXT; + } else if (!stricmp(pszResult, "PASSWORD")) { + pFields[nIdx].nType = FIELD_TEXT; + pFields[nIdx].nFlags |= FLAG_PASSWORD; + } else if (!stricmp(pszResult, "LISTBOX")) { + pFields[nIdx].nType = FIELD_LISTBOX; + } else if (!stricmp(pszResult, "COMBOBOX")) { + pFields[nIdx].nType = FIELD_COMBOBOX; + } else if (!stricmp(pszResult, "DROPLIST")) { + pFields[nIdx].nType = FIELD_COMBOBOX; + pFields[nIdx].nFlags |= FLAG_DROPLIST; + } else if (!stricmp(pszResult, "FILEREQUEST")) { + pFields[nIdx].nType = FIELD_FILEREQUEST; + } else if (!stricmp(pszResult, "DIRREQUEST")) { + pFields[nIdx].nType = FIELD_DIRREQUEST; + } else if (!stricmp(pszResult, "CHECKBOX")) { + pFields[nIdx].nType = FIELD_CHECKBOX; + } else if (!stricmp(pszResult, "RADIOBUTTON")) { + pFields[nIdx].nType = FIELD_RADIOBUTTON; + } else { + continue; + } + + nResult = GetPrivateProfileString(pszField, "TEXT", "", pszResult, nSize, pszFilename); + if (nResult) { + pFields[nIdx].pszText = STRDUP(pszResult); + } + nResult = GetPrivateProfileString(pszField, "STATE", "", pszResult, nSize, pszFilename); + pFields[nIdx].pszState = STRDUP(pszResult); + + nResult = GetPrivateProfileString(pszField, "ROOT", "", pszResult, nSize, pszFilename); + if (nResult) { + pFields[nIdx].pszRoot = STRDUP(pszResult); + } + + nResult = GetPrivateProfileString(pszField, "ListItems", "", pszResult, nSize, pszFilename); + if (nResult) { + // add an extra | character to the end to simplify the loop where we add the items. + pFields[nIdx].pszListItems = (char*)MALLOC(nResult + 2); + wsprintf(pFields[nIdx].pszListItems, "%s|", pszResult); + } + pFields[nIdx].nMaxLength = GetPrivateProfileInt(pszField, "MaxLen", 0, pszFilename); + pFields[nIdx].nMinLength = GetPrivateProfileInt(pszField, "MinLen", 0, pszFilename); + + nResult = GetPrivateProfileString(pszField, "ValidateText", "", pszResult, nSize, pszFilename); + if (nResult) { + pFields[nIdx].pszValidateText = STRDUP(pszResult); + // translate backslash-n in the input into actual carriage-return/line-feed characters. + for (char *pPos = pFields[nIdx].pszValidateText; *pPos; pPos++) { + if (*pPos == '\\') { + if ((*(pPos + 1) == 'n') || (*(pPos + 1) == 'N')) { + *pPos = '\r'; + *(pPos + 1) = '\n'; +/* + } else if (*(pPos + 1) == '\\') { + // if it's 2 backslash in a row, then skip the second. + pPos++; +*/ + } + } + } + } + + nResult = GetPrivateProfileString(pszField, "Filter", "All Files|*.*", pszResult, nSize, pszFilename); + if (nResult) { + // add an extra | character to the end to simplify the loop where we add the items. + pFields[nIdx].pszFilter = (char*)MALLOC(nResult + 2); + strcpy(pFields[nIdx].pszFilter, pszResult); + char *pszPos = pFields[nIdx].pszFilter; + while (*pszPos) { + if (*pszPos == '|') *pszPos = '\0'; + pszPos++; + } + } + + pFields[nIdx].rect.left = GetPrivateProfileInt(pszField, "LEFT", 0, pszFilename); + pFields[nIdx].rect.right = GetPrivateProfileInt(pszField, "RIGHT", 0, pszFilename); + pFields[nIdx].rect.top = GetPrivateProfileInt(pszField, "TOP", 0, pszFilename); + pFields[nIdx].rect.bottom = GetPrivateProfileInt(pszField, "BOTTOM", 0, pszFilename); + + TableEntry FlagTable[] = { + { "FILE_MUST_EXIST", OFN_FILEMUSTEXIST }, + { "PATH_MUST_EXIST", OFN_PATHMUSTEXIST }, + { "WARN_IF_EXIST", OFN_OVERWRITEPROMPT }, + { "PROMPT_CREATE", OFN_CREATEPROMPT }, + + { "RIGHT" , FLAG_RIGHT }, + + { "PASSWORD" , FLAG_PASSWORD }, + { "DROPLIST" , FLAG_DROPLIST }, + + { "MULTISELECT" , FLAG_MULTISELECT }, + { "FILE_EXPLORER", OFN_EXPLORER }, + { "FILE_HIDEREADONLY", OFN_HIDEREADONLY }, + +/* + { "NO_ALPHA", 0 }, + { "NO_NUMBERS", 0 }, + { "NO_SYMBOLS", 0 }, + { "BOLD", FLAG_BOLD }, +*/ + { NULL, 0 } + }; + + nResult = GetPrivateProfileString(pszField, "flags", "", pszResult, nSize, pszFilename); + if (nResult > 0) { + // append the | to make parsing a bit easier + if (lstrlen(pszResult) pszStart) { + if (!stricmp("REQ_SAVE", pszStart)) { + pFields[nIdx].bSaveDlg = true; + } else { + // v1.3 converted this to a table lookup. + // I think it's a bit larger now, but we can + // add new flags with very little overhead. + int nFlagIdx = 0; + while (FlagTable[nFlagIdx].pszName != NULL) { + if (!stricmp(FlagTable[nFlagIdx].pszName, pszStart)) { + pFields[nIdx].nFlags |= FlagTable[nFlagIdx].nBitsToSet; + break; + } + nFlagIdx++; + } + } + } + // jump to the next item, skip any redundant | characters + do { pszEnd++; } while (*pszEnd == '|'); + pszStart = pszEnd; + } + pszEnd++; + } + } + + pFields[nIdx].nControlID = 1200 + nIdx; + } + + FREE(pszResult); + + AddBrowseButtons(); + + return true; +} + + +LRESULT WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) { + switch (codeNotify) { + case BN_CLICKED: + { + for (int nIdx = 0; nIdx < nNumFields; nIdx++) { + if (pFields[nIdx].nType == FIELD_BROWSEBUTTON) { + if (id == pFields[nIdx].nControlID) { + int nParentIdx = pFields[nIdx].nParentIdx; + + switch(pFields[nParentIdx].nType) { + case FIELD_FILEREQUEST: + BrowseForFile(nParentIdx); + break; + case FIELD_DIRREQUEST: + BrowseForFolder(nParentIdx); + break; + } + break; + } + } + } + } + break; + } + return 0; +} + + +static void *lpWndProcOld; + +static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_COMMAND && (LOWORD(wParam) == IDCANCEL || LOWORD(wParam) == IDOK || LOWORD(wParam) == 3)) + { + PostMessage(hConfigWindow,WM_USER+666,0,LOWORD(wParam)); + return 0; + } + return CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); +} + +int g_is_cancel,g_is_back; + + +BOOL CALLBACK cfgDlgProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hwndDlg, WM_COMMAND, WMCommandProc); + return 0; + case WM_USER+666: + if (lParam != IDCANCEL || !pszCancelQuestion || MessageBox(hwndDlg,pszCancelQuestion,pszCancelQuestionCaption?pszCancelQuestionCaption:"Question",MB_YESNO|nCancelQuestionIcon)==IDYES) + { + if (lParam == IDCANCEL || lParam == 3 || ValidateFields()) { + if (lParam == 3) g_is_back++; + if (lParam == IDCANCEL) g_is_cancel++; + g_done++; + PostMessage(hwndDlg,WM_CLOSE,0,0); + } + } + break; + case WM_CLOSE: break; + } + return 0; +} + + + + +extern "C" void __declspec(dllexport) dialog(HWND hwndParent, int string_size, + char *variables, stack_t **stacktop) +{ + hMainWindow=hwndParent; + g_stringsize=string_size; + g_stacktop=stacktop; + g_variables=variables; + + int nIdx; + UINT nAddMsg; + + if (!hMainWindow) + { + popstring(NULL); + pushstring("error finding mainwnd"); + return; // cannot be used in silent mode unfortunately. + } + HWND childwnd=FindWindowEx(hMainWindow,NULL,"#32770",NULL); // find window to replace + if (!childwnd) childwnd=GetDlgItem(hMainWindow,1018); + if (!childwnd) + { + popstring(NULL); + pushstring("error finding childwnd"); + return; + } + + if (!*stacktop || !(*stacktop)->text[0] || !ReadSettings((*stacktop)->text)) + { + popstring(NULL); + pushstring("error finding config"); + return; + } + int cw_vis=IsWindowVisible(childwnd); + if (cw_vis) ShowWindow(childwnd,SW_HIDE); + + int was_cancel_enabled=EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),1); + int was_ok_enabled=EnableWindow(GetDlgItem(hMainWindow,IDOK),1); + static char old_cancel[256]; + GetDlgItemText(hMainWindow,IDCANCEL,old_cancel,sizeof(old_cancel)); + if (pszCancelButtonText) SetDlgItemText(hMainWindow,IDCANCEL,pszCancelButtonText); + static char old_ok[256]; + GetDlgItemText(hMainWindow,IDOK,old_ok,sizeof(old_ok)); + if (pszNextButtonText) SetDlgItemText(hMainWindow,IDOK,pszNextButtonText); + static char old_back[256]; + GetDlgItemText(hMainWindow,3,old_back,sizeof(old_back)); + if (pszBackButtonText) SetDlgItemText(hMainWindow,3,pszBackButtonText); + + + int old_back_enabled=!EnableWindow(GetDlgItem(hMainWindow,3),bBackEnabled); + int old_back_visible=IsWindowVisible(GetDlgItem(hMainWindow,3)); + ShowWindow(GetDlgItem(hMainWindow,3),bBackEnabled?SW_SHOWNA:SW_HIDE); + + int old_cancel_enabled=!EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelEnabled); // by ORTIM + int old_cancel_visible=IsWindowVisible(GetDlgItem(hMainWindow,IDCANCEL)); // by ORTIM + ShowWindow(GetDlgItem(hMainWindow,IDCANCEL),bCancelEnabled?SW_SHOWNA:SW_HIDE); // by ORTIM + + lpWndProcOld = (void *) GetWindowLong(hMainWindow,GWL_WNDPROC); + SetWindowLong(hMainWindow,GWL_WNDPROC,(long)ParentWndProc); + + // Added by Amir Szekely 22nd July 2002 + HFONT hFont = (HFONT)SendMessage(hMainWindow, WM_GETFONT, 0, 0); + + RECT dialog_r; + hConfigWindow=CreateDialog(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG1),hMainWindow,cfgDlgProc); + if (hConfigWindow) + { + GetWindowRect(childwnd,&dialog_r); + ScreenToClient(hMainWindow,(LPPOINT)&dialog_r); + ScreenToClient(hMainWindow,((LPPOINT)&dialog_r)+1); + SetWindowPos(hConfigWindow,0,dialog_r.left,dialog_r.top,dialog_r.right-dialog_r.left,dialog_r.bottom-dialog_r.top,SWP_NOZORDER|SWP_NOACTIVATE); + // Added by Amir Szekely 22nd July 2002 + // Sets the font of IO window to be the same as the main window + SendMessage(hConfigWindow, WM_SETFONT, (WPARAM)hFont, TRUE); + } + else + { + popstring(NULL); + pushstring("error creating dialog"); + return; + } + + + + for (nIdx = 0; nIdx < nNumFields; nIdx++) { + char szFieldClass[20]; + + if (pFields[nIdx].rect.left<0) pFields[nIdx].rect.left+=dialog_r.right; + if (pFields[nIdx].rect.right<0) pFields[nIdx].rect.right+=dialog_r.right; + if (pFields[nIdx].rect.top<0) pFields[nIdx].rect.top+=dialog_r.bottom; + if (pFields[nIdx].rect.bottom<0) pFields[nIdx].rect.bottom+=dialog_r.bottom; + + DWORD dwExStyle = 0; + DWORD dwStyle=0; + char *title=pFields[nIdx].pszText; + switch (pFields[nIdx].nType) { + case FIELD_LABEL: + dwStyle = WS_GROUP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP; + dwExStyle = WS_EX_TRANSPARENT; + strcpy(szFieldClass, "STATIC"); + break; + case FIELD_FILEREQUEST: + case FIELD_DIRREQUEST: + pFields[nIdx].rect.right-=25; + case FIELD_TEXT: + if (pFields[nIdx].nFlags & FLAG_PASSWORD) { + dwStyle = WS_VISIBLE | WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS | WS_TABSTOP | ES_AUTOHSCROLL | ES_PASSWORD; + } else { + dwStyle = WS_VISIBLE | WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS | WS_TABSTOP | ES_AUTOHSCROLL; + } + dwExStyle = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE; + strcpy(szFieldClass, "EDIT"); + title=pFields[nIdx].pszState; + break; + case FIELD_COMBOBOX: + if (pFields[nIdx].nFlags & FLAG_DROPLIST) { + dwStyle = CBS_DROPDOWNLIST | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBS_AUTOHSCROLL | CBS_HASSTRINGS; + } else { + dwStyle = CBS_DROPDOWN | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBS_AUTOHSCROLL | CBS_HASSTRINGS; + } + dwExStyle = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE; + title=pFields[nIdx].pszState; + strcpy(szFieldClass, "COMBOBOX"); + break; + case FIELD_BROWSEBUTTON: + dwStyle = WS_GROUP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP; + strcpy(szFieldClass, "BUTTON"); + break; + case FIELD_LISTBOX: + if (pFields[nIdx].nFlags & FLAG_MULTISELECT) { + dwStyle = WS_GROUP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL; + } else { + dwStyle = WS_GROUP | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | LBS_DISABLENOSCROLL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT; + } + dwExStyle = WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE; + strcpy(szFieldClass, "LISTBOX"); + break; + case FIELD_CHECKBOX: + if (pFields[nIdx].nFlags & FLAG_RIGHT) { + dwStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX | BS_RIGHTBUTTON; + } else { + dwStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | BS_TEXT | BS_VCENTER | BS_AUTOCHECKBOX; + } + strcpy(szFieldClass, "BUTTON"); + break; + case FIELD_RADIOBUTTON: + if (pFields[nIdx].nFlags & FLAG_RIGHT) { + dwStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON | BS_RIGHTBUTTON; + } else { + dwStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_CLIPSIBLINGS | BS_TEXT | BS_VCENTER | BS_AUTORADIOBUTTON; + } + strcpy(szFieldClass, "BUTTON"); + break; + default: + continue; + } + + pFields[nIdx].hwnd = CreateWindowEx( + dwExStyle, + szFieldClass, + title, + dwStyle, + pFields[nIdx].rect.left, + pFields[nIdx].rect.top, + pFields[nIdx].rect.right-pFields[nIdx].rect.left, + pFields[nIdx].rect.bottom-pFields[nIdx].rect.top, + hConfigWindow, + (HMENU)pFields[nIdx].nControlID, + m_hInstance, + NULL); + + if (pFields[nIdx].hwnd) { + // Changed by Amir Szekely 22nd July 2002 + // Sets the font of IO window to be the same as the main window + SendMessage(pFields[nIdx].hwnd, WM_SETFONT, (WPARAM)hFont, TRUE); + // make sure we created the window, then set additional attributes + if (pFields[nIdx].nMaxLength > 0) { + switch (pFields[nIdx].nType) { + case FIELD_TEXT: + case FIELD_DIRREQUEST: + case FIELD_FILEREQUEST: + SendMessage(pFields[nIdx].hwnd, EM_LIMITTEXT, (WPARAM)pFields[nIdx].nMaxLength, (LPARAM)0); + break; + } + } + if ((pFields[nIdx].nType == FIELD_CHECKBOX) || (pFields[nIdx].nType == FIELD_RADIOBUTTON)) { + if (pFields[nIdx].pszState[0] == '1') + { + SendMessage(pFields[nIdx].hwnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); + } + } else if ( + ((pFields[nIdx].nType == FIELD_COMBOBOX) && (nAddMsg = CB_ADDSTRING)) || + ((pFields[nIdx].nType == FIELD_LISTBOX ) && (nAddMsg = LB_ADDSTRING)) + ) { + // if this is a listbox or combobox, we need to add the list items. + char *pszStart, *pszEnd; + pszStart = pszEnd = pFields[nIdx].pszListItems; + while ((*pszEnd) && (*pszStart)) { + if (*pszEnd == '|') { + *pszEnd = '\0'; + if (pszEnd > pszStart) { + SendMessage(pFields[nIdx].hwnd, nAddMsg, 0, (LPARAM)pszStart); + } + // jump to the next item, skip any redundant | characters + do { pszEnd++; } while (*pszEnd == '|'); + pszStart = pszEnd; + } + pszEnd++; + } + if (pFields[nIdx].pszState) { + int nItem = SendMessage(pFields[nIdx].hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)pFields[nIdx].pszState); + if (nItem != CB_ERR) { + SendMessage(pFields[nIdx].hwnd, CB_SETCURSEL, nItem, 0); + } + } + } + } + } + + static char old_title[1024]; + if (pszTitle) + { + GetWindowText(hMainWindow,old_title,sizeof(old_title)); + SetWindowText(hMainWindow,pszTitle); + } + + ShowWindow(hConfigWindow, SW_SHOWNA); + SetFocus(GetDlgItem(hMainWindow,IDOK)); + + while (!g_done) { + MSG msg; + int nResult = GetMessage(&msg, NULL, 0, 0); + if (!IsDialogMessage(hConfigWindow,&msg) && !IsDialogMessage(hMainWindow,&msg) && !TranslateMessage(&msg)) + DispatchMessage(&msg); + } + + // we don't save settings on cancel since that means your installer will likely + // quit soon, which means the ini might get flushed late and cause crap. :) anwyay. + if (!g_is_cancel) SaveSettings((*stacktop)->text); + popstring(NULL); + + pushstring(g_is_cancel?"cancel":g_is_back?"back":"success"); + + if (lpWndProcOld) + SetWindowLong(hMainWindow,GWL_WNDPROC,(long)lpWndProcOld); + DestroyWindow(hConfigWindow); + if (was_cancel_enabled) EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),0); + if (was_ok_enabled) EnableWindow(GetDlgItem(hMainWindow,IDOK),0); + SetDlgItemText(hMainWindow,IDCANCEL,old_cancel); + SetDlgItemText(hMainWindow,IDOK,old_ok); + SetDlgItemText(hMainWindow,3,old_back); + + EnableWindow(GetDlgItem(hMainWindow,3),old_back_enabled); + + EnableWindow(GetDlgItem(hMainWindow,IDCANCEL),old_cancel_enabled); // by ORTIM + ShowWindow(GetDlgItem(hMainWindow,IDCANCEL),old_cancel_visible?SW_SHOWNA:SW_HIDE); // by ORTIM + + ShowWindow(GetDlgItem(hMainWindow,3),old_back_visible?SW_SHOWNA:SW_HIDE); + if (pszTitle) SetWindowText(hMainWindow,old_title); + + if (cw_vis) ShowWindow(childwnd,SW_SHOWNA); + + FREE(pszTitle); + FREE(pszCancelQuestion); + FREE(pszCancelQuestionCaption); + FREE(pszCancelButtonText); + FREE(pszNextButtonText); + FREE(pszBackButtonText); + for (nIdx = 0; nIdx < nNumFields; nIdx++) { + FREE(pFields[nIdx].pszText); + FREE(pFields[nIdx].pszState); + FREE(pFields[nIdx].pszListItems); + FREE(pFields[nIdx].pszFilter); + FREE(pFields[nIdx].pszRoot); + } + FREE(pFields); +} + + + +extern "C" BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + m_hInstance=(HINSTANCE) hInst; + return TRUE; +} + + +// utility functions (not required but often useful) +int popstring(char *str) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + if (str) lstrcpy(str,th->text); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +void pushstring(char *str) +{ + stack_t *th; + if (!g_stacktop) return; + th=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)+g_stringsize); + lstrcpyn(th->text,str,g_stringsize); + th->next=*g_stacktop; + *g_stacktop=th; +} + +char *getuservariable(int varnum) +{ + if (varnum < 0 || varnum >= __INST_LAST) return NULL; + return g_variables+varnum*g_stringsize; +} + + diff --git a/Contrib/InstallOptions/io.dsp b/Contrib/InstallOptions/io.dsp new file mode 100644 index 00000000..ec4b52f2 --- /dev/null +++ b/Contrib/InstallOptions/io.dsp @@ -0,0 +1,115 @@ +# Microsoft Developer Studio Project File - Name="io" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=io - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "io.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "io.mak" CFG="io - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "io - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "io - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "io - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /D "WIN32_LEAN_AND_MEAN" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib /out:"../../Bin/InstallOptions.dll" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "io - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTOPTDLL_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "io - Win32 Release" +# Name "io - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\InstallerOptions.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\ioptdll.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/Contrib/InstallOptions/io.dsw b/Contrib/InstallOptions/io.dsw new file mode 100644 index 00000000..73449211 --- /dev/null +++ b/Contrib/InstallOptions/io.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "io"=.\io.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/InstallOptions/ioptdll.rc b/Contrib/InstallOptions/ioptdll.rc new file mode 100644 index 00000000..63cf1344 --- /dev/null +++ b/Contrib/InstallOptions/ioptdll.rc @@ -0,0 +1,94 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 57, 41 +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 50 + TOPMARGIN, 7 + BOTTOMMARGIN, 34 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Contrib/InstallOptions/resource.h b/Contrib/InstallOptions/resource.h new file mode 100644 index 00000000..6984d551 --- /dev/null +++ b/Contrib/InstallOptions/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ioptdll.rc +// +#define IDD_DIALOG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Contrib/InstallOptions/test.ini b/Contrib/InstallOptions/test.ini new file mode 100644 index 00000000..c6389898 --- /dev/null +++ b/Contrib/InstallOptions/test.ini @@ -0,0 +1,67 @@ +[Settings] +NumFields=6 + +Title=Test Install Setup: Testing Installer Options + +; uncomment this to confirm on exit. +; CancelConfirm=Are you sure you want to cancel the install? + +; comment this out to hide the back button +BackEnabled=1 + +; you can override the defaults here +CancelButtonText=Cancel +NextButtonText=Next > +BackButtonText=< Back + +[Field 1] +Type=checkbox +text=Install support for X +left=0 +right=300 +top=0 +bottom=15 +state=0 + +[Field 2] +Type=checkbox +text=Install support for Y +left=0 +right=300 +top=15 +bottom=30 +state=1 + +[Field 3] +Type=checkbox +text=Install support for Z +left=0 +right=300 +top=30 +bottom=45 +state=0 + +[Field 4] +Type=FileRequest +State=C:\poop.poop +Left=0 +Right=-1 +Top=45 +Bottom=64 +Filter=Poop Files|*.poop|All files|*.* +Flags=FILE_MUST_EXIST|OFN_EXPLORER|OFN_HIDEREADONLY + +[Field 5] +Type=DirRequest +Left=0 +Right=-1 +Top=65 +Bottom=84 + +[Field 6] +Type=Label +Left=0 +Right=-1 +Top=85 +Bottom=104 +Text=This is a label... diff --git a/Contrib/InstallOptions/test.nsi b/Contrib/InstallOptions/test.nsi new file mode 100644 index 00000000..c1b37da9 --- /dev/null +++ b/Contrib/InstallOptions/test.nsi @@ -0,0 +1,128 @@ +; Copyright (C) 2001 Michael Bishop +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software. +; 3. This notice may not be removed or altered from any source distribution. +; + +; Test installation script + +; The name of the installer +Name "Test Install" + +; The file to write +OutFile "test-setup.exe" +ShowInstDetails show + +; The default installation directory +InstallDir $PROGRAMFILES\Test + +DirText "Choose dir" +LicenseText "You are about to install test install and it owns, you will love it, we think." +LicenseData "..\..\license.txt" +ComponentText "Choose components" + +; Do not automatically close the installation window +AutoCloseWindow false + +; Define some installation templates +InstType "Typical" ; 1 + +Section "Required Components" +ReadINIStr $R0 $7 "Field 1" State +DetailPrint "Install X=$R0" +ReadINIStr $R0 $7 "Field 2" State +DetailPrint "Install Y=$R0" +ReadINIStr $R0 $7 "Field 3" State +DetailPrint "Install Z=$R0" +ReadINIStr $R0 $7 "Field 4" State +DetailPrint "File=$R0" +ReadINIStr $R0 $7 "Field 5" State +DetailPrint "Dir=$R0" + +SectionEnd + +Section "more components" +Nop +SectionEnd + + +; $9 = counter +; $8 = DLL +; $7 = ini +Function .onInit + StrCpy $9 0 + GetTempFileName $8 + GetTempFileName $7 + File /oname=$8 ..\..\Bin\InstallOptions.dll + File /oname=$7 "test.ini" +FunctionEnd + +; cleanup on exit. +Function .onInstSuccess +Call Cleanup +FunctionEnd + +Function .onInstFailed +Call Cleanup +FunctionEnd + +Function .onUserAbort +Call Cleanup +FunctionEnd + +Function Cleanup + Delete $8 + Delete $7 +FunctionEnd + +Function .onNextPage + StrCmp $9 1 good + IntOp $9 $9 + 1 + Return + good: + Call RunConfigure + Pop $0 + StrCmp $0 "cancel" "" nocancel + Call Cleanup + Quit + nocancel: + StrCmp $0 "back" "" noback + Abort + noback: + IntOp $9 $9 + 1 +FunctionEnd + +Function .onPrevPage + StrCmp $9 2 good + IntOp $9 $9 - 1 + Return + good: + Call RunConfigure + Pop $0 + StrCmp $0 "cancel" "" nocancel + Call Cleanup + Quit + nocancel: + StrCmp $0 "back" back + Abort + back: + IntOp $9 $9 - 1 +FunctionEnd + +Function RunConfigure + Push $7 + CallInstDLL $8 dialog +FunctionEnd \ No newline at end of file diff --git a/Contrib/Makensisw/License.txt b/Contrib/Makensisw/License.txt new file mode 100644 index 00000000..06b9427a --- /dev/null +++ b/Contrib/Makensisw/License.txt @@ -0,0 +1,18 @@ +Copyright (c) 2002 Robert Rainwter +-- this version was slightly modified by Justin Frankel -- + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/Contrib/Makensisw/Readme.txt b/Contrib/Makensisw/Readme.txt new file mode 100644 index 00000000..f44fb030 --- /dev/null +++ b/Contrib/Makensisw/Readme.txt @@ -0,0 +1,152 @@ +---------------------------------------------------- +MakeNSISW - MakeNSIS Windows Wrapper +---------------------------------------------------- + + +About MakeNSISW +--------------- +MakeNSISW is a wrapper for the MakeNSIS that is distributed with +NSIS (http://www.nullsoft.com/free/nsis/). MakeNSISW allows you +to compile NSIS scripts using a Windows GUI interface. To install +MakeNSISW, compile the source using Visual C++ or Mingw. + + +Requirements +------------ +MakeNSISW requires NSIS be installed on your system. The default +directory for this installation is $PROGRAMFILES\NSIS\Contrib\MakeNSISW. + + +Usage: +------ +If you installed the Shell Extensions option during the installation, then +all that is required is that you choose 'Compile NSI' from the right- +click menu on a NSIS script. This will invoke MakeNSISW. + +The format of the parameters when calling MakeNSISW from the commandline is: + makensisw full_path_of_makensis.exe [options] [script.nsi | - [...]] + +Where full_path_of_makensis.exe is the full name including the path of the +compiler. For the options, please see the MakeNSIS documentation. + + +Shortcut Keys +------------- +Ctrl+R: Recompiles the script +Ctrl+X: Exits the application +Ctrl+T: Tests the installer +Ctrl+E: Edits the script + + +Version History +--------------- +0.1 + - Initial Release + +0.2 + - Added ability to save output and copy output + +0.3 + - Added option to recompile script (F2 or File|Recompile) + - Added Help Menu + - Return code is now always set + - Added Accelerator key support for Exit and Recompile + - No longer uses NSIS's version string + - Made clearer status message in title bar + - Disabled menu/accelerator functions during compile + +0.4 + - Fixed Copy Selected bug + +0.5 + - Minor Makefile changes (mingw) + - Moved strings into global strings to make editing easier + - Added Clear Log Command under Edit menu + - Recompile no longer clears the log window (use F5) + - Close is now the default button when you hit enter + - added VC++ project, updated resources to work with VC++ + - rearranged directory structure + - makefiles now target ../../makensisw.exe + - removed makensisw home link in help menu (hope this is ok, + doesn't really seem needed to me) + - made display use a fixed width font (Some people may not like + this, but I do) + - added 'test' button (peeks output for 'Output' line) + - made it so that the log shows the most recent 32k. + - made it so that the log always clears on a recompile. + - compiled with VC++ so no longer needs msvcrt.dll + - made the compiler name be a full path (for more flexibility) + +0.6 + - print correct usage if unable to execute compiler + - removed mingw warnings + - set title/branding before errors + - some docs changes + - Added Edit|Edit Script function + +0.7 + - Edit Script should now work for output>32k + - Added resize support (thanks to felfert) + - Added window position saving (thanks to felfert) + - Disable some items when exec of makensis failed + +0.8 + - Added window size constraints (thanks to bcheck) + - Cleaned up the resource file + +0.9 + - Removed global strings (moved into #defines) + - Some GUI changes + - No longer focused Close button (its default anyways) + - Fixed resize bug on minimize/restore (thanks to felfert) + - Made window placement stored in HKLM instead of HKCU, cause + I hate things that get littered in HKCU. + +1.0 + - Fixed bug with large output causing crash + +1.1 + - Crash may actually be fixed + +1.2 + - XP visual style support + +1.3 + - Added Documentation menu item + - Fix GUI problem with About dialog + +1.4 + - Edit Script command will now work with or without file associations + - Added default filename for save dialog + - Use standard fonts + - Documentation menuitem caused recompile + +1.5 + - Fixed Copy All function + +1.6 + - Reduced size from 44k to 12k (kickik) + - Editbox not limited to 32k (now using richedit control) + - Made the log window font-size smaller. + + +Copyright Information +--------------------- +Copyright (c) 2002 Robert Rainwater +Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/Contrib/Makensisw/afxres.h b/Contrib/Makensisw/afxres.h new file mode 100644 index 00000000..b3cc0671 --- /dev/null +++ b/Contrib/Makensisw/afxres.h @@ -0,0 +1,5 @@ +#include + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/Contrib/Makensisw/makensisw.cpp b/Contrib/Makensisw/makensisw.cpp new file mode 100644 index 00000000..0ada29fa --- /dev/null +++ b/Contrib/Makensisw/makensisw.cpp @@ -0,0 +1,363 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +#include +#include + +#include "makensisw.h" +#include "resource.h" +#include "noclib.h" + +char *g_script; +int g_retcode; + +static RECT resizeRect; +static int dx; +static int dy; + +HINSTANCE g_hInstance; +HWND g_hwnd; +HANDLE g_hThread; + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char *cmdParam, int cmdShow) { + HACCEL haccel; + g_hInstance=GetModuleHandle(0); + g_script=GetCommandLine(); // set commandline global string + if (*g_script++=='"') while (*g_script++!='"'); + else while (*g_script++!=' '); + while (*g_script==' ') g_script++; + g_retcode = -1; // return code is always false unless set to true by GetExitCodeProcess + HWND hDialog = CreateDialog(g_hInstance,MAKEINTRESOURCE(DLG_MAIN),0,DialogProc); + if (!hDialog) { + char buf [MAX_STRING]; + wsprintf(buf, "Error creating dialog box.\n\nError: %x", GetLastError ()); + MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_OK); + return 1; + } + haccel = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDK_ACCEL)); + MSG msg; + int status; + while ((status=GetMessage(&msg,0,0,0))!=0) { + if (status==-1) return -1; + if (!TranslateAccelerator(hDialog,haccel,&msg)) { + if (!IsDialogMessage(hDialog,&msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + ExitProcess(msg.wParam); + return msg.wParam; +} + +BOOL CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + static HINSTANCE hRichEditDLL = 0; + if (!hRichEditDLL) hRichEditDLL= LoadLibrary("RichEd32.dll"); + switch (msg) { + case WM_INITDIALOG: + { + g_hwnd=hwndDlg; + HICON hIcon = LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_ICON)); + SetClassLong(hwndDlg,GCL_HICON,(long)hIcon); + HFONT hFont = CreateFont(14,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_CHARACTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_DONTCARE,"Courier New"); + SendDlgItemMessage(hwndDlg,IDC_LOGWIN,WM_SETFONT,(WPARAM)hFont,0); + SendDlgItemMessage(hwndDlg,IDC_LOGWIN,EM_SETBKGNDCOLOR,0,GetSysColor(COLOR_BTNFACE)); + RestoreWindowPos(g_hwnd); + CompileNSISScript(); + return TRUE; + } + case WM_DESTROY: + { + SaveWindowPos(g_hwnd); + PostQuitMessage(0); + return TRUE; + } + case WM_CLOSE: + { + if (!g_hThread) { + DestroyWindow(hwndDlg); + FreeLibrary(hRichEditDLL); + } + return TRUE; + } + case WM_GETMINMAXINFO: + { + ((MINMAXINFO*)lParam)->ptMinTrackSize.x=MINWIDTH; + ((MINMAXINFO*)lParam)->ptMinTrackSize.y=MINHEIGHT; + } + case WM_ENTERSIZEMOVE: + { + + GetClientRect(g_hwnd, &resizeRect); + return TRUE; + } + case WM_SIZE: + { + if ((wParam == SIZE_MAXHIDE)||(wParam == SIZE_MAXSHOW)) return TRUE; + } + case WM_SIZING: + { + RECT rSize; + if (hwndDlg == g_hwnd) { + GetClientRect(g_hwnd, &rSize); + if (((rSize.right==0)&&(rSize.bottom==0))||((resizeRect.right==0)&&(resizeRect.bottom==0))) + return TRUE; + dx = rSize.right - resizeRect.right; + dy = rSize.bottom - resizeRect.bottom; + EnumChildWindows(g_hwnd, DialogResize, (LPARAM)0); + resizeRect = rSize; + } + return TRUE; + } + case WM_MAKENSIS_PROCESSCOMPLETE: + { + if (g_hThread) { + CloseHandle(g_hThread); + g_hThread=0; + } + if (g_retcode==0) SetTitle(g_hwnd,"Finished Sucessfully"); + else SetTitle(g_hwnd,"Compile Error: See Log for Details"); + EnableItems(g_hwnd); + return TRUE; + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) { + case IDM_ABOUT: + { + DialogBox(g_hInstance,MAKEINTRESOURCE(DLG_ABOUT),g_hwnd,(DLGPROC)AboutProc); + return TRUE; + } + case IDM_NSISHOME: + { + ShellExecute(g_hwnd,"open",NSIS_URL,NULL,NULL,SW_SHOWNORMAL); + return TRUE; + } + case IDM_DOCS: + { + char pathf[MAX_PATH],*path; + GetModuleFileName(NULL,pathf,sizeof(pathf)); + path=my_strrchr(pathf,'\\'); + if(path!=NULL) *path=0; + lstrcat(pathf,"\\makensis.htm"); + if ((int)ShellExecute(g_hwnd,"open",pathf,NULL,NULL,SW_SHOWNORMAL)<=32) + ShellExecute(g_hwnd,"open",DOCPATH,NULL,NULL,SW_SHOWNORMAL); + return TRUE; + } + case IDM_RECOMPILE: + { + CompileNSISScript(); + return TRUE; + } + case IDM_TEST: + case IDC_TEST: + { + if (g_output_exe[0]) { + ShellExecute(g_hwnd,"open",g_output_exe,NULL,NULL,SW_SHOWNORMAL); + } + return TRUE; + } + case IDM_EDITSCRIPT: + { + if (g_input_script[0]) { + if ((int)ShellExecute(g_hwnd,"open",g_input_script,NULL,NULL,SW_SHOWNORMAL)<=32) { + char path[MAX_PATH]; + if (GetWindowsDirectory(path,sizeof(path))) { + lstrcat(path,"\\notepad.exe"); + ShellExecute(g_hwnd,"open",path,g_input_script,NULL,SW_SHOWNORMAL); + } + } + } + return TRUE; + } + case IDC_CLOSE: + case IDM_EXIT: + { + if (!g_hThread) { + DestroyWindow(hwndDlg); + } + return TRUE; + } + case IDM_COPY: + { + CopyToClipboard(g_hwnd); + return TRUE; + } + case IDM_COPYSELECTED: + { + SendMessage(GetDlgItem(g_hwnd,IDC_LOGWIN), WM_COPY, 0, 0); + return TRUE; + } + case IDM_SAVE: + { + OPENFILENAME l={sizeof(l),}; + char buf[MAX_STRING]; + l.hwndOwner = hwndDlg; + l.lpstrFilter = "Log Files (*.log)\0Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; + l.lpstrFile = buf; + l.nMaxFile = 1023; + l.lpstrTitle = "Save Output"; + l.lpstrDefExt = "log"; + l.lpstrInitialDir = NULL; + l.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_PATHMUSTEXIST; + lstrcpy(buf,"output.log"); + if (GetSaveFileName(&l)) { + HANDLE hFile = CreateFile(buf,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0); + if (hFile) { + int len=SendDlgItemMessage(g_hwnd,IDC_LOGWIN,WM_GETTEXTLENGTH,0,0); + char *existing_text=(char*)GlobalAlloc(GPTR,len); + existing_text[0]=0; + GetDlgItemText(g_hwnd, IDC_LOGWIN, existing_text, len); + DWORD dwWritten = 0; + WriteFile(hFile,existing_text,len,&dwWritten,0); + CloseHandle(hFile); + GlobalFree(existing_text); + } + } + return TRUE; + } + } + } + } + return 0; +} + +DWORD WINAPI MakeNSISProc(LPVOID p) { + char buf[1024]; + STARTUPINFO si={sizeof(si),}; + SECURITY_ATTRIBUTES sa={sizeof(sa),}; + SECURITY_DESCRIPTOR sd={0,}; + PROCESS_INFORMATION pi={0,}; + HANDLE newstdout=0,read_stdout=0; + + OSVERSIONINFO osv={sizeof(osv)}; + GetVersionEx(&osv); + if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) { + InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd,true,NULL,false); + sa.lpSecurityDescriptor = &sd; + } + else sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = true; + if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) { + ErrorMessage(g_hwnd,"There was an error creating the pipe."); + PostMessage(g_hwnd,WM_MAKENSIS_PROCESSCOMPLETE,0,0); + return 1; + } + GetStartupInfo(&si); + si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.hStdOutput = newstdout; + si.hStdError = newstdout; + if (!CreateProcess(NULL,g_script,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) { + char buf[MAX_STRING]; + wsprintf(buf,"Could not execute:\r\n %s.",g_script); + ErrorMessage(g_hwnd,buf); + CloseHandle(newstdout); + CloseHandle(read_stdout); + PostMessage(g_hwnd,WM_MAKENSIS_PROCESSCOMPLETE,0,0); + return 1; + } + unsigned long exit=0,read,avail; + my_memset(buf,0,sizeof(buf)); + while(1) { + PeekNamedPipe(read_stdout,buf,sizeof(buf)-1,&read,&avail,NULL); + if (read != 0) { + my_memset(buf,0,sizeof(buf)); + if (avail > sizeof(buf)-1) { + while (read >= sizeof(buf)-1) { + ReadFile(read_stdout,buf,sizeof(buf)-1,&read,NULL); + LogMessage(g_hwnd,buf); + my_memset(buf,0,sizeof(buf)); + } + } + else { + ReadFile(read_stdout,buf,sizeof(buf),&read,NULL); + LogMessage(g_hwnd,buf); + } + } + GetExitCodeProcess(pi.hProcess,&exit); + if (exit != STILL_ACTIVE) break; + Sleep(TIMEOUT); + } + g_retcode = exit; + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + CloseHandle(newstdout); + CloseHandle(read_stdout); + PostMessage(g_hwnd,WM_MAKENSIS_PROCESSCOMPLETE,0,0); + return 0; +} + +BOOL CALLBACK DialogResize(HWND hWnd, LPARAM /* unused */) +{ + RECT r; + GetWindowRect(hWnd, &r); + ScreenToClient(g_hwnd, (LPPOINT)&r); + ScreenToClient(g_hwnd, ((LPPOINT)&r)+1); + switch (GetDlgCtrlID(hWnd)) { + case IDC_LOGWIN: + SetWindowPos(hWnd, 0, r.left, r.top,r.right - r.left + dx, r.bottom - r.top + dy, SWP_NOZORDER|SWP_NOMOVE); + break; + case IDC_TEST: + case IDC_CLOSE: + SetWindowPos(hWnd, 0, r.left + dx, r.top + dy, 0, 0, SWP_NOZORDER|SWP_NOSIZE); + break; + default: + SetWindowPos(hWnd, 0, r.left, r.top + dy, r.right - r.left + dx, r.bottom - r.top, SWP_NOZORDER); + break; + } + RedrawWindow(hWnd,NULL,NULL,RDW_INVALIDATE); + return TRUE; +} + +BOOL CALLBACK AboutProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch(msg) { + case WM_INITDIALOG: + { + HFONT bfont = CreateFont(14,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + FIXED_PITCH|FF_DONTCARE, "MS Shell Dlg"); + HFONT rfont = CreateFont(12,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + FIXED_PITCH|FF_DONTCARE, "MS Shell Dlg"); + if (bfont) SendDlgItemMessage(hwndDlg, IDC_ABOUTVERSION, WM_SETFONT, (WPARAM)bfont, FALSE); + if (rfont) { + SendDlgItemMessage(hwndDlg, IDC_ABOUTCOPY, WM_SETFONT, (WPARAM)rfont, FALSE); + SendDlgItemMessage(hwndDlg, IDC_ABOUTPORTIONS, WM_SETFONT, (WPARAM)rfont, FALSE); + } + char buf[MAX_STRING]; + wsprintf(buf,"MakeNSISW %s",NSISW_VERSION); + SetDlgItemText(hwndDlg,IDC_ABOUTVERSION,buf); + SetDlgItemText(hwndDlg,IDC_ABOUTCOPY,COPYRIGHT); + SetDlgItemText(hwndDlg,IDC_ABOUTPORTIONS,CONTRIBUTOR); + } + case WM_COMMAND: + { + switch (LOWORD(wParam)) { + case IDOK: { + EndDialog(hwndDlg, TRUE); + } + } + } + } + return FALSE; +} diff --git a/Contrib/Makensisw/makensisw.dsp b/Contrib/Makensisw/makensisw.dsp new file mode 100644 index 00000000..f193fdb2 --- /dev/null +++ b/Contrib/Makensisw/makensisw.dsp @@ -0,0 +1,160 @@ +# Microsoft Developer Studio Project File - Name="makensisw" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=makensisw - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "makensisw.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "makensisw.mak" CFG="makensisw - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "makensisw - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "makensisw - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "makensisw - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D RELEASE=1.6 /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"WinMain" /subsystem:windows /machine:I386 /nodefaultlib /out:"../../makensisw.exe" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "makensisw - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "makensisw - Win32 Release" +# Name "makensisw - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\makensisw.cpp +# End Source File +# Begin Source File + +SOURCE=.\noclib.cpp +# End Source File +# Begin Source File + +SOURCE=.\utils.cpp +# End Source File +# Begin Source File + +SOURCE=.\version.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\afxres.h +# End Source File +# Begin Source File + +SOURCE=.\makensisw.h +# End Source File +# Begin Source File + +SOURCE=.\noclib.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=..\..\Source\default1.bin +# End Source File +# Begin Source File + +SOURCE=..\..\source\icon.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=..\..\Source\rt_manif.bin +# End Source File +# End Group +# Begin Group "Documentation" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Readme.txt +# End Source File +# End Group +# Begin Source File + +SOURCE=.\makensisw.xml +# End Source File +# End Target +# End Project diff --git a/Contrib/Makensisw/makensisw.dsw b/Contrib/Makensisw/makensisw.dsw new file mode 100644 index 00000000..653335be --- /dev/null +++ b/Contrib/Makensisw/makensisw.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "makensisw"=.\makensisw.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/Makensisw/makensisw.h b/Contrib/Makensisw/makensisw.h new file mode 100644 index 00000000..2d89f897 --- /dev/null +++ b/Contrib/Makensisw/makensisw.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +#ifndef MAKENSIS_H +#define MAKENSIS_H + +#include + +#define _RICHEDIT_VER 0x0200 +#include +#undef _RICHEDIT_VER + +// Defines +#define NSIS_URL "http://www.nullsoft.com/free/nsis/" +#define USAGE "Usage:\r\n makensisw full_path_of_makensis.exe [options] [script.nsi | - [...]]\r\n" +#define COPYRIGHT "Copyright (c) 2002 Robert Rainwater" +#define CONTRIBUTOR "Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert" +#define DOCPATH "http://firehose.net/free/nsis/makensis.htm" +#define REGSEC HKEY_LOCAL_MACHINE +#define REGKEY "Software\\NSIS" +#define REGLOC "MakeNSISWPlacement" +#define MAX_STRING 256 +#define TIMEOUT 200 +#define MINWIDTH 350 +#define MINHEIGHT 180 + +#define WM_MAKENSIS_PROCESSCOMPLETE (WM_USER+1001) + +// Extern Variables +extern const char *NSISW_VERSION; +extern char *g_script; +extern HWND g_hwnd; +extern HANDLE g_hThread; +extern char g_output_exe[1024]; +extern char g_input_script[1024]; + +// makensisw +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, char *cmdParam, int cmdShow); +static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +DWORD WINAPI MakeNSISProc(LPVOID p); +BOOL CALLBACK DialogResize(HWND hWnd, LPARAM /* unused*/); +BOOL CALLBACK AboutProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +void CompileNSISScript(); + +// utils +void SetTitle(HWND hwnd,char *substr); +void SetBranding(HWND hwnd); +void CopyToClipboard(HWND hwnd); +void ClearLog(HWND hwnd); +void LogMessage(HWND hwnd,const char *str); +void ErrorMessage(HWND hwnd,const char *str); +void DisableItems(HWND hwnd); +void EnableItems(HWND hwnd); +void RestoreWindowPos(HWND hwnd); +void SaveWindowPos(HWND hwnd); +#endif \ No newline at end of file diff --git a/Contrib/Makensisw/makensisw.xml b/Contrib/Makensisw/makensisw.xml new file mode 100644 index 00000000..244fba0b --- /dev/null +++ b/Contrib/Makensisw/makensisw.xml @@ -0,0 +1,10 @@ + + + +MakeNSIS Wrapper + + + + + + diff --git a/Contrib/Makensisw/noclib.cpp b/Contrib/Makensisw/noclib.cpp new file mode 100644 index 00000000..b650f84a --- /dev/null +++ b/Contrib/Makensisw/noclib.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +/* +Contribution by kickik +*/ +#include +#include "noclib.h" + +char *my_strrchr(const char *string, int c) { + for (int i = lstrlen(string); i >= 0; i--) + if (string[i] == c) + return (char*)&string[i]; + return 0; +} + +void *my_memset(void *dest, int c, size_t count) { + for (size_t i = 0; i < count; i++) ((char*)dest)[i]=c; + return dest; +} + +char *my_strstr(const char *string, const char *strCharSet) { + if (!*strCharSet) return (char*)string; + size_t chklen=lstrlen(string)-lstrlen(strCharSet); + char *s1, *s2; + for (size_t i = 0; i < chklen; i++) { + s1=&((char*)string)[i]; + s2=(char*)strCharSet; + while (*s1++ == *s2++) + if (!*s2) + return &((char*)string)[i]; + } + return 0; +} \ No newline at end of file diff --git a/Contrib/Makensisw/noclib.h b/Contrib/Makensisw/noclib.h new file mode 100644 index 00000000..7928393f --- /dev/null +++ b/Contrib/Makensisw/noclib.h @@ -0,0 +1,32 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +/* +Contribution by kickik +*/ +#ifndef NOCLIB_H +#define NOCLIB_H + +char *my_strrchr(const char *string, int c); +void *my_memset(void *dest, int c, size_t count); +char *my_strstr(const char *string, const char *strCharSet); + +#endif \ No newline at end of file diff --git a/Contrib/Makensisw/resource.h b/Contrib/Makensisw/resource.h new file mode 100644 index 00000000..be5db97c --- /dev/null +++ b/Contrib/Makensisw/resource.h @@ -0,0 +1,38 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define DLG_MAIN 101 +#define IDI_ICON 102 +#define DLG_ABOUT 103 +#define IDM_MENU 104 +#define IDK_ACCEL 105 +#define IDR_DEFAULT1 108 +#define IDC_LOGWIN 402 +#define IDC_VERSION 405 +#define IDC_CLOSE 406 +#define IDM_ABOUT 501 +#define IDM_EXIT 502 +#define IDM_SAVE 503 +#define IDM_COPY 504 +#define IDM_COPYSELECTED 505 +#define IDM_RECOMPILE 506 +#define IDM_NSISHOME 507 +#define IDC_TEST 1000 +#define IDC_ABOUTVERSION 1001 +#define IDC_ABOUTCOPY 1003 +#define IDC_ABOUTPORTIONS 1005 +#define IDM_TEST 40002 +#define IDM_EDITSCRIPT 40003 +#define IDM_DOCS 40004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40005 +#define _APS_NEXT_CONTROL_VALUE 1009 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Contrib/Makensisw/resource.rc b/Contrib/Makensisw/resource.rc new file mode 100644 index 00000000..7f936225 --- /dev/null +++ b/Contrib/Makensisw/resource.rc @@ -0,0 +1,179 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON DISCARDABLE "..\\..\\source\\icon.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDM_MENU MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Recompile\tCtrl+R", IDM_RECOMPILE + MENUITEM "&Test\tCtrl+T", IDM_TEST + MENUITEM "&Save Output...", IDM_SAVE + MENUITEM SEPARATOR + MENUITEM "E&xit\tCtrl+X", IDM_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "Edit Script\tCtrl+E", IDM_EDITSCRIPT + MENUITEM SEPARATOR + MENUITEM "Copy &All", IDM_COPY + MENUITEM "Copy &Selected", IDM_COPYSELECTED + END + POPUP "&Help" + BEGIN + MENUITEM "NSIS Home", IDM_NSISHOME + MENUITEM "Documentation", IDM_DOCS + MENUITEM SEPARATOR + MENUITEM "&About", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDK_ACCEL ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + "E", IDM_EDITSCRIPT, VIRTKEY, CONTROL, NOINVERT + "R", IDM_RECOMPILE, VIRTKEY, CONTROL, NOINVERT + "T", IDM_TEST, VIRTKEY, CONTROL, NOINVERT + "X", IDM_EXIT, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +DLG_MAIN DIALOG DISCARDABLE 0, 0, 361, 228 +STYLE DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "MakeNSIS" +MENU IDM_MENU +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_LOGWIN,"RICHEDIT",ES_MULTILINE | ES_AUTOVSCROLL | + ES_READONLY | WS_BORDER | WS_VSCROLL,7,4,345,186 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,202,346,1 + LTEXT "",IDC_VERSION,7,212,200,12,WS_DISABLED + DEFPUSHBUTTON "Clo&se",IDC_CLOSE,303,209,49,14 + PUSHBUTTON "&Test",IDC_TEST,247,209,50,14,WS_DISABLED +END + +DLG_ABOUT DIALOG DISCARDABLE 0, 0, 235, 86 +STYLE DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "About MakeNSISW" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_ICON,IDC_STATIC,7,4,20,20 + DEFPUSHBUTTON "Clo&se",IDOK,185,64,43,15 + LTEXT "MakeNSISW",IDC_ABOUTVERSION,44,4,184,8 + LTEXT "Copyright",IDC_ABOUTCOPY,44,18,184,8 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,45,55,183,1 + LTEXT "Portions Copyright",IDC_ABOUTPORTIONS,44,30,184,20 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + DLG_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 4 + BOTTOMMARGIN, 79 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// 24 +// + +1 24 MOVEABLE PURE "makensisw.xml" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Contrib/Makensisw/utils.cpp b/Contrib/Makensisw/utils.cpp new file mode 100644 index 00000000..386974ef --- /dev/null +++ b/Contrib/Makensisw/utils.cpp @@ -0,0 +1,185 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +#include +#include "resource.h" +#include "makensisw.h" +#include "noclib.h" + +void SetTitle(HWND hwnd,char *substr) { + char title[64]; + if (substr==NULL) wsprintf(title,"MakeNSISW"); + else wsprintf(title,"MakeNSISW - %s",substr); + SetWindowText(hwnd,title); +} + +void SetBranding(HWND hwnd) { + char title[64]; + wsprintf(title,"MakeNSISW %s",NSISW_VERSION); + SetDlgItemText(hwnd, IDC_VERSION, title); +} + +void CopyToClipboard(HWND hwnd) { + int len=SendDlgItemMessage(hwnd,IDC_LOGWIN,WM_GETTEXTLENGTH,0,0); + char *existing_text=(char*)GlobalAlloc(GPTR,len); + if (!hwnd||!OpenClipboard(hwnd)||!existing_text) return; + EmptyClipboard(); + existing_text[0]=0; + GetDlgItemText(hwnd, IDC_LOGWIN, existing_text, len); + SetClipboardData(CF_TEXT,existing_text); + CloseClipboard(); +} + + +void ClearLog(HWND hwnd) { + SetDlgItemText(hwnd, IDC_LOGWIN, ""); +} + +char g_output_exe[1024]; +char g_input_script[1024]; +BOOL g_input_found; +void LogMessage(HWND hwnd,const char *str) { + if (!str || !*str) return; + int len=SendDlgItemMessage(hwnd,IDC_LOGWIN,WM_GETTEXTLENGTH,0,0); + char *existing_text=(char*)GlobalAlloc(GPTR,len+lstrlen(str)+3);//3=\r\n\0 + if (!existing_text) return; + existing_text[0]=0; + GETTEXTEX gt={0}; + gt.cb = len; + gt.codepage = CP_ACP; + gt.flags = GT_DEFAULT; + SendDlgItemMessage(hwnd,IDC_LOGWIN,EM_GETTEXTEX,(WPARAM)>,(LPARAM)existing_text); + lstrcat(existing_text,str); + if (!g_input_found) { + char *p1=my_strstr(existing_text,"\r\nProcessing script file: \""); + if (p1) { + while (*p1++ != '"'); + char *p2=my_strstr(p1,"\r\n"); + lstrcpyn(g_input_script,p1,p2-p1); + g_input_found=TRUE; + } + } + SetDlgItemText(hwnd, IDC_LOGWIN, existing_text); + SendDlgItemMessage(hwnd, IDC_LOGWIN,EM_SETSEL,lstrlen(existing_text),lstrlen(existing_text)); + SendDlgItemMessage(hwnd, IDC_LOGWIN,EM_SCROLLCARET,0,0); + GlobalFree(existing_text); +} + + + +void ErrorMessage(HWND hwnd,const char *str) { + if (!str) return; + char buf[1028]; + wsprintf(buf,"Error - %s\r\n",str); + LogMessage(hwnd,buf); +} + +void DisableItems(HWND hwnd) { + g_output_exe[0]=0; + g_input_script[0]=0; + g_input_found=FALSE; + EnableWindow(GetDlgItem(hwnd,IDC_CLOSE),0); + EnableWindow(GetDlgItem(hwnd,IDC_TEST),0); + HMENU m = GetMenu(hwnd); + EnableMenuItem(m,IDM_SAVE,MF_GRAYED); + EnableMenuItem(m,IDM_TEST,MF_GRAYED); + EnableMenuItem(m,IDM_EXIT,MF_GRAYED); + EnableMenuItem(m,IDM_RECOMPILE,MF_GRAYED); + EnableMenuItem(m,IDM_COPY,MF_GRAYED); + EnableMenuItem(m,IDM_COPYSELECTED,MF_GRAYED); + EnableMenuItem(m,IDM_EDITSCRIPT,MF_GRAYED); +} + +void EnableItems(HWND hwnd) { + int len=SendDlgItemMessage(hwnd,IDC_LOGWIN,WM_GETTEXTLENGTH,0,0); + char *existing_text=(char*)GlobalAlloc(GPTR,len); + if (!existing_text) return; + existing_text[0]=0; + GetDlgItemText(hwnd, IDC_LOGWIN, existing_text, len); + char *p=existing_text; + char *p2; + char *p3; + if ((p2=my_strstr(p,"\r\nOutput: \""))) { + while (*p2 != '\"') p2++; + p2++; + if ((p3=my_strstr(p2,"\"\r\n")) && p3 < my_strstr(p2,"\r\n")) { + *p3=0; + lstrcpy(g_output_exe,p2); + } + } + + HMENU m = GetMenu(hwnd); + if (g_output_exe[0]) { + EnableWindow(GetDlgItem(hwnd,IDC_TEST),1); + EnableMenuItem(m,IDM_TEST,MF_ENABLED); + } + EnableWindow(GetDlgItem(hwnd,IDC_CLOSE),1); + EnableMenuItem(m,IDM_SAVE,MF_ENABLED); + EnableMenuItem(m,IDM_EXIT,MF_ENABLED); + EnableMenuItem(m,IDM_RECOMPILE,MF_ENABLED); + EnableMenuItem(m,IDM_COPY,MF_ENABLED); + EnableMenuItem(m,IDM_COPYSELECTED,MF_ENABLED); + EnableMenuItem(m,IDM_EDITSCRIPT,MF_ENABLED); +} + +void CompileNSISScript() { + ClearLog(g_hwnd); + SetTitle(g_hwnd,NULL); + SetBranding(g_hwnd); + if (lstrlen(g_script)==0) { + HMENU m = GetMenu(g_hwnd); + LogMessage(g_hwnd,USAGE); + EnableMenuItem(m,IDM_RECOMPILE,MF_GRAYED); + EnableMenuItem(m,IDM_EDITSCRIPT,MF_GRAYED); + EnableMenuItem(m,IDM_TEST,MF_GRAYED); + EnableWindow(GetDlgItem(g_hwnd,IDC_TEST),0); + return; + } + // Disable buttons during compile + DisableItems(g_hwnd); + DWORD id; + g_hThread=CreateThread(NULL,0,MakeNSISProc,0,0,&id); +} + +void RestoreWindowPos(HWND hwnd) { + HKEY hKey; + WINDOWPLACEMENT p; + if (RegOpenKeyEx(REGSEC,REGKEY,0,KEY_READ,&hKey) == ERROR_SUCCESS) { + DWORD l = sizeof(p); + DWORD t; + if ((RegQueryValueEx(hKey,REGLOC,NULL,&t,(unsigned char*)&p,&l)==ERROR_SUCCESS)&&(t == REG_BINARY)&&(l==sizeof(p))) { + p.length = sizeof(p); + SetWindowPlacement(hwnd, &p); + } + RegCloseKey(hKey); + } +} + +void SaveWindowPos(HWND hwnd) { + HKEY hKey; + WINDOWPLACEMENT p; + p.length = sizeof(p); + GetWindowPlacement(hwnd, &p); + if (RegCreateKey(REGSEC,REGKEY,&hKey) == ERROR_SUCCESS) { + RegSetValueEx(hKey,REGLOC,0,REG_BINARY,(unsigned char*)&p,sizeof(p)); + RegCloseKey(hKey); + } +} diff --git a/Contrib/Makensisw/utils.h b/Contrib/Makensisw/utils.h new file mode 100644 index 00000000..7e69c4b7 --- /dev/null +++ b/Contrib/Makensisw/utils.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +#ifndef UTILS_H +#define UTILS_H + +#define REGSEC HKEY_LOCAL_MACHINE // JF> modified this to HKLM so that + // nsis uninstaller would remove. this means + // window placement is shared across users, but + // bfd. +#define REGKEY "Software\\NSIS" +#define REGLOC "MakeNSISWPlacement" + +extern const char *NSISW_VERSION; + +// Methods +void SetTitle(HWND hwnd,char *substr); +void SetBranding(HWND hwnd); +void CopyToClipboard(HWND hwnd); +void ClearLog(HWND hwnd); +void LogMessage(HWND hwnd,const char *str); +void ErrorMessage(HWND hwnd,const char *str); +void DisableItems(HWND hwnd); +void EnableItems(HWND hwnd); +void RestoreWindowPos(HWND hwnd); +void SaveWindowPos(HWND hwnd); + +#endif \ No newline at end of file diff --git a/Contrib/Makensisw/version.cpp b/Contrib/Makensisw/version.cpp new file mode 100644 index 00000000..19517630 --- /dev/null +++ b/Contrib/Makensisw/version.cpp @@ -0,0 +1,30 @@ +/* + Copyright (c) 2002 Robert Rainwater + Portions Copyright (c) 2002 Justin Frankel and Fritz Elfert + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ +// Turns a define into a string +#define REALSTR(x) #x +#define STR(x) REALSTR(x) + +#ifdef RELEASE +const char *NSISW_VERSION = STR(RELEASE); +#else +const char *NSISW_VERSION = "Local Build: " __DATE__; +#endif \ No newline at end of file diff --git a/Contrib/NSISdl/ReadMe.txt b/Contrib/NSISdl/ReadMe.txt new file mode 100644 index 00000000..35bcaac9 --- /dev/null +++ b/Contrib/NSISdl/ReadMe.txt @@ -0,0 +1,59 @@ + NSIS-DL 1.1 - http downloading DLL for NSIS + Copyright (C) 2001 Yaroslav Faybishenko & Justin Frankel + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + + + +This dll can be used from NSIS to download files via http. + +How to use (for another example, see waplugin.nsi in the nsis directory): + + Pass the url and filename on the stack + Result is returned in $0 + "cancel" if cancelled + "success" if success + otherwise, an error string describing the error + +Example: + ; pack the dll in the install file + File /oname=$TEMP\nsdtmp09.dll nsisdl.dll + + ; make the call to download + Push "http://www.xcf.berkeley.edu/~yaroslav/photos/mike/mike1-full.jpg" + Push "$INSTDIR\test.jpg" + CallInstDLL $TEMP\nsdtmp09.dll download ; for a quiet install, use download_quiet + + ; delete DLL from temporary directory + Delete $TEMP\nsdtmp09.dll + + ; check if download succeeded + StrCmp $0 "success" successful + StrCmp $0 "cancel" cancelled + + ; we failed + DetailPrint "Download failed: $0" + goto done + + cancelled: + DetailPrint "Download cancelled" + goto done + successful: + DetailPrint "Download successful" + ExecShell $INSTDIR\test.jpg + goto done diff --git a/Contrib/NSISdl/Script1.rc b/Contrib/NSISdl/Script1.rc new file mode 100644 index 00000000..1d43d167 --- /dev/null +++ b/Contrib/NSISdl/Script1.rc @@ -0,0 +1,78 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 265, 104 +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",WS_BORDER, + 0,36,265,11 + CTEXT "",IDC_STATIC2,0,25,263,8 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Contrib/NSISdl/asyncdns.cpp b/Contrib/NSISdl/asyncdns.cpp new file mode 100644 index 00000000..cf8b7c27 --- /dev/null +++ b/Contrib/NSISdl/asyncdns.cpp @@ -0,0 +1,78 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: asyncdns.cpp - JNL portable asynchronous DNS implementation +** License: see jnetlib.h +*/ + + +#include "netinc.h" +#include "util.h" +#include "asyncdns.h" + +JNL_AsyncDNS::JNL_AsyncDNS(int max_cache_entries) +{ + m_thread_kill=1; + m_thread=0; + m_addr=0; + m_hostname[0]=0; +} + +JNL_AsyncDNS::~JNL_AsyncDNS() +{ + m_thread_kill=1; + + if (m_thread) + { + WaitForSingleObject(m_thread,INFINITE); + CloseHandle(m_thread); + } +} + +unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d) +{ + JNL_AsyncDNS *_this=(JNL_AsyncDNS*)_d; + int nowinsock=JNL::open_socketlib(); + struct hostent *hostentry; + hostentry=::gethostbyname(_this->m_hostname); + if (hostentry) + { + _this->m_addr=*((int*)hostentry->h_addr); + } + else + _this->m_addr=INADDR_NONE; + if (!nowinsock) JNL::close_socketlib(); + _this->m_thread_kill=1; + return 0; +} + +int JNL_AsyncDNS::resolve(char *hostname, unsigned long *addr) +{ + // return 0 on success, 1 on wait, -1 on unresolvable + unsigned long ip=inet_addr(hostname); + if (ip != INADDR_NONE) + { + *addr=ip; + return 0; + } + + if (lstrcmpi(m_hostname,hostname)) m_addr=0; + else if (m_addr == INADDR_NONE) return -1; + else if (m_addr) + { + *addr=m_addr; + return 0; + } + lstrcpy(m_hostname,hostname); + + if (m_thread_kill) + { + DWORD id; + if (m_thread) return -1; + m_thread_kill=0; + m_thread=CreateThread(NULL,0,_threadfunc,(LPVOID)this,0,&id); + if (!m_thread) return -1; + } + return 1; +} diff --git a/Contrib/NSISdl/asyncdns.h b/Contrib/NSISdl/asyncdns.h new file mode 100644 index 00000000..5aa16271 --- /dev/null +++ b/Contrib/NSISdl/asyncdns.h @@ -0,0 +1,38 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: asyncdns.h - JNL portable asynchronous DNS interface +** License: see jnetlib.h +** +** Usage: +** 1. Create JNL_AsyncDNS object, optionally with the number of cache entries. +** 2. call resolve() to resolve a hostname into an address. The return value of +** resolve is 0 on success (host successfully resolved), 1 on wait (meaning +** try calling resolve() with the same hostname in a few hundred milliseconds +** or so), or -1 on error (i.e. the host can't resolve). +** 4. enjoy. +*/ + +#ifndef _ASYNCDNS_H_ +#define _ASYNCDNS_H_ + +class JNL_AsyncDNS +{ +public: + JNL_AsyncDNS(int max_cache_entries=64); + ~JNL_AsyncDNS(); + + int resolve(char *hostname, unsigned long *addr); // return 0 on success, 1 on wait, -1 on unresolvable + +private: + char m_hostname[256]; + unsigned long m_addr; + + volatile int m_thread_kill; + HANDLE m_thread; + static unsigned long WINAPI _threadfunc(LPVOID _d); + +}; + +#endif //_ASYNCDNS_H_ diff --git a/Contrib/NSISdl/connection.cpp b/Contrib/NSISdl/connection.cpp new file mode 100644 index 00000000..9bee6223 --- /dev/null +++ b/Contrib/NSISdl/connection.cpp @@ -0,0 +1,447 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: connection.cpp - JNL TCP connection implementation +** License: see jnetlib.h +*/ + +#include "netinc.h" +#include "util.h" +#include "connection.h" + + +JNL_Connection::JNL_Connection(JNL_AsyncDNS *dns, int sendbufsize, int recvbufsize) +{ + m_errorstr=""; + if (dns == JNL_CONNECTION_AUTODNS) + { + m_dns=new JNL_AsyncDNS(); + m_dns_owned=1; + } + else + { + m_dns=dns; + m_dns_owned=0; + } + m_recv_buffer_len=recvbufsize; + m_send_buffer_len=sendbufsize; + m_recv_buffer=(char*)malloc(m_recv_buffer_len); + m_send_buffer=(char*)malloc(m_send_buffer_len); + m_socket=-1; + memset(m_recv_buffer,0,recvbufsize); + memset(m_send_buffer,0,sendbufsize); + m_remote_port=0; + m_state=STATE_NOCONNECTION; + m_recv_len=m_recv_pos=0; + m_send_len=m_send_pos=0; + m_host[0]=0; + memset(&m_saddr,0,sizeof(m_saddr)); +} + +void JNL_Connection::connect(int s, struct sockaddr_in *loc) +{ + close(1); + m_socket=s; + m_remote_port=0; + m_dns=NULL; + if (loc) m_saddr=*loc; + else memset(&m_saddr,0,sizeof(m_saddr)); + if (m_socket != -1) + { + SET_SOCK_BLOCK(m_socket,0); + m_state=STATE_CONNECTED; + } + else + { + m_errorstr="invalid socket passed to connect"; + m_state=STATE_ERROR; + } +} + +void JNL_Connection::connect(char *hostname, int port) +{ + close(1); + m_remote_port=(short)port; + m_socket=::socket(AF_INET,SOCK_STREAM,0); + if (m_socket==-1) + { + m_errorstr="creating socket"; + m_state=STATE_ERROR; + } + else + { + SET_SOCK_BLOCK(m_socket,0); + strncpy(m_host,hostname,sizeof(m_host)-1); + m_host[sizeof(m_host)-1]=0; + memset(&m_saddr,0,sizeof(m_saddr)); + if (!m_host[0]) + { + m_errorstr="empty hostname"; + m_state=STATE_ERROR; + } + else + { + m_state=STATE_RESOLVING; + m_saddr.sin_family=AF_INET; + m_saddr.sin_port=htons((unsigned short)port); + m_saddr.sin_addr.s_addr=inet_addr(hostname); + } + } +} + +JNL_Connection::~JNL_Connection() +{ + if (m_socket >= 0) + { + ::shutdown(m_socket, SHUT_RDWR); + ::closesocket(m_socket); + m_socket=-1; + } + free(m_recv_buffer); + free(m_send_buffer); + if (m_dns_owned) + { + delete m_dns; + } +} + +void JNL_Connection::run(int max_send_bytes, int max_recv_bytes, int *bytes_sent, int *bytes_rcvd) +{ + int bytes_allowed_to_send=(max_send_bytes<0)?m_send_buffer_len:max_send_bytes; + int bytes_allowed_to_recv=(max_recv_bytes<0)?m_recv_buffer_len:max_recv_bytes; + + if (bytes_sent) *bytes_sent=0; + if (bytes_rcvd) *bytes_rcvd=0; + + switch (m_state) + { + case STATE_RESOLVING: + if (m_saddr.sin_addr.s_addr == INADDR_NONE) + { + int a=m_dns?m_dns->resolve(m_host,(unsigned long int *)&m_saddr.sin_addr.s_addr):-1; + if (!a) { m_state=STATE_CONNECTING; } + else if (a == 1) + { + m_state=STATE_RESOLVING; + break; + } + else + { + m_errorstr="resolving hostname"; + m_state=STATE_ERROR; + return; + } + } + if (!::connect(m_socket,(struct sockaddr *)&m_saddr,16)) + { + m_state=STATE_CONNECTED; + } + else if (ERRNO!=EINPROGRESS) + { + m_errorstr="connecting to host"; + m_state=STATE_ERROR; + } + else { m_state=STATE_CONNECTING; } + break; + case STATE_CONNECTING: + { + fd_set f[3]; + FD_ZERO(&f[0]); + FD_ZERO(&f[1]); + FD_ZERO(&f[2]); + FD_SET(m_socket,&f[0]); + FD_SET(m_socket,&f[1]); + FD_SET(m_socket,&f[2]); + struct timeval tv; + memset(&tv,0,sizeof(tv)); + if (select(m_socket+1,&f[0],&f[1],&f[2],&tv)==-1) + { + m_errorstr="connecting to host (calling select())"; + m_state=STATE_ERROR; + } + else if (FD_ISSET(m_socket,&f[1])) + { + m_state=STATE_CONNECTED; + } + else if (FD_ISSET(m_socket,&f[2])) + { + m_errorstr="connecting to host"; + m_state=STATE_ERROR; + } + } + break; + case STATE_CONNECTED: + case STATE_CLOSING: + if (m_send_len>0 && bytes_allowed_to_send>0) + { + int len=m_send_buffer_len-m_send_pos; + if (len > m_send_len) len=m_send_len; + if (len > bytes_allowed_to_send) len=bytes_allowed_to_send; + if (len > 0) + { + int res=::send(m_socket,m_send_buffer+m_send_pos,len,0); + if (res==-1 && ERRNO != EWOULDBLOCK) + { +// m_state=STATE_CLOSED; +// return; + } + if (res>0) + { + bytes_allowed_to_send-=res; + if (bytes_sent) *bytes_sent+=res; + m_send_pos+=res; + m_send_len-=res; + } + } + if (m_send_pos>=m_send_buffer_len) + { + m_send_pos=0; + if (m_send_len>0) + { + len=m_send_buffer_len-m_send_pos; + if (len > m_send_len) len=m_send_len; + if (len > bytes_allowed_to_send) len=bytes_allowed_to_send; + int res=::send(m_socket,m_send_buffer+m_send_pos,len,0); + if (res==-1 && ERRNO != EWOULDBLOCK) + { +// m_state=STATE_CLOSED; + } + if (res>0) + { + bytes_allowed_to_send-=res; + if (bytes_sent) *bytes_sent+=res; + m_send_pos+=res; + m_send_len-=res; + } + } + } + } + if (m_recv_len m_recv_buffer_len-m_recv_len) len=m_recv_buffer_len-m_recv_len; + if (len > bytes_allowed_to_recv) len=bytes_allowed_to_recv; + if (len>0) + { + int res=::recv(m_socket,m_recv_buffer+m_recv_pos,len,0); + if (res == 0 || (res < 0 && ERRNO != EWOULDBLOCK)) + { + m_state=STATE_CLOSED; + break; + } + if (res > 0) + { + bytes_allowed_to_recv-=res; + if (bytes_rcvd) *bytes_rcvd+=res; + m_recv_pos+=res; + m_recv_len+=res; + } + } + if (m_recv_pos >= m_recv_buffer_len) + { + m_recv_pos=0; + if (m_recv_len < m_recv_buffer_len) + { + len=m_recv_buffer_len-m_recv_len; + if (len > bytes_allowed_to_recv) len=bytes_allowed_to_recv; + if (len > 0) + { + int res=::recv(m_socket,m_recv_buffer+m_recv_pos,len,0); + if (res == 0 || (res < 0 && ERRNO != EWOULDBLOCK)) + { + m_state=STATE_CLOSED; + break; + } + if (res > 0) + { + bytes_allowed_to_recv-=res; + if (bytes_rcvd) *bytes_rcvd+=res; + m_recv_pos+=res; + m_recv_len+=res; + } + } + } + } + } + if (m_state == STATE_CLOSING) + { + if (m_send_len < 1) m_state = STATE_CLOSED; + } + break; + default: break; + } +} + +void JNL_Connection::close(int quick) +{ + if (quick || m_state == STATE_RESOLVING || m_state == STATE_CONNECTING) + { + m_state=STATE_CLOSED; + if (m_socket >= 0) + { + ::shutdown(m_socket, SHUT_RDWR); + ::closesocket(m_socket); + } + m_socket=-1; + memset(m_recv_buffer,0,m_recv_buffer_len); + memset(m_send_buffer,0,m_send_buffer_len); + m_remote_port=0; + m_recv_len=m_recv_pos=0; + m_send_len=m_send_pos=0; + m_host[0]=0; + memset(&m_saddr,0,sizeof(m_saddr)); + } + else + { + if (m_state == STATE_CONNECTED) m_state=STATE_CLOSING; + } +} + +int JNL_Connection::send_bytes_in_queue(void) +{ + return m_send_len; +} + +int JNL_Connection::send_bytes_available(void) +{ + return m_send_buffer_len-m_send_len; +} + +int JNL_Connection::send(char *data, int length) +{ + if (length > send_bytes_available()) + { + return -1; + } + + int write_pos=m_send_pos+m_send_len; + if (write_pos >= m_send_buffer_len) + { + write_pos-=m_send_buffer_len; + } + + int len=m_send_buffer_len-write_pos; + if (len > length) + { + len=length; + } + + memcpy(m_send_buffer+write_pos,data,len); + if (length > len) + { + memcpy(m_send_buffer,data+len,length-len); + } + m_send_len+=length; + return 0; +} + +int JNL_Connection::send_string(char *line) +{ + return send(line,strlen(line)); +} + +int JNL_Connection::recv_bytes_available(void) +{ + return m_recv_len; +} + +int JNL_Connection::peek_bytes(char *data, int maxlength) +{ + if (maxlength > m_recv_len) + { + maxlength=m_recv_len; + } + int read_pos=m_recv_pos-m_recv_len; + if (read_pos < 0) + { + read_pos += m_recv_buffer_len; + } + int len=m_recv_buffer_len-read_pos; + if (len > maxlength) + { + len=maxlength; + } + memcpy(data,m_recv_buffer+read_pos,len); + if (len < maxlength) + { + memcpy(data+len,m_recv_buffer,maxlength-len); + } + + return maxlength; +} + +int JNL_Connection::recv_bytes(char *data, int maxlength) +{ + + int ml=peek_bytes(data,maxlength); + m_recv_len-=ml; + return ml; +} + +int JNL_Connection::getbfromrecv(int pos, int remove) +{ + int read_pos=m_recv_pos-m_recv_len + pos; + if (pos < 0 || pos > m_recv_len) return -1; + if (read_pos < 0) + { + read_pos += m_recv_buffer_len; + } + if (read_pos >= m_recv_buffer_len) + { + read_pos-=m_recv_buffer_len; + } + if (remove) m_recv_len--; + return m_recv_buffer[read_pos]; +} + +int JNL_Connection::recv_lines_available(void) +{ + int l=recv_bytes_available(); + int lcount=0; + int lastch=0; + int pos; + for (pos=0; pos < l; pos ++) + { + int t=getbfromrecv(pos,0); + if (t == -1) return lcount; + if ((t=='\r' || t=='\n') &&( + (lastch != '\r' && lastch != '\n') || lastch==t + )) lcount++; + lastch=t; + } + return lcount; +} + +int JNL_Connection::recv_line(char *line, int maxlength) +{ + if (maxlength > m_recv_len) maxlength=m_recv_len; + while (maxlength--) + { + int t=getbfromrecv(0,1); + if (t == -1) + { + *line=0; + return 0; + } + if (t == '\r' || t == '\n') + { + int r=getbfromrecv(0,0); + if ((r == '\r' || r == '\n') && r != t) getbfromrecv(0,1); + *line=0; + return 0; + } + *line++=(char)t; + } + return 1; +} + +unsigned long JNL_Connection::get_interface(void) +{ + if (m_socket==-1) return 0; + struct sockaddr_in sin; + memset(&sin,0,sizeof(sin)); + socklen_t len=16; + if (::getsockname(m_socket,(struct sockaddr *)&sin,&len)) return 0; + return (unsigned long) sin.sin_addr.s_addr; +} diff --git a/Contrib/NSISdl/connection.h b/Contrib/NSISdl/connection.h new file mode 100644 index 00000000..dfa52639 --- /dev/null +++ b/Contrib/NSISdl/connection.h @@ -0,0 +1,135 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: connection.h - JNL TCP connection interface +** License: see jnetlib.h +** +** Usage: +** 1. Create a JNL_Connection object, optionally specifying a JNL_AsyncDNS +** object to use (or NULL for none, or JNL_CONNECTION_AUTODNS for auto), +** and the send and receive buffer sizes. +** 2. Call connect() to have it connect to a host/port (the hostname will be +** resolved if possible). +** 3. call run() with the maximum send/recv amounts, and optionally parameters +** so you can tell how much has been send/received. You want to do this a lot, while: +** 4. check get_state() to check the state of the connection. The states are: +** JNL_Connection::STATE_ERROR +** - an error has occured on the connection. the connection has closed, +** and you can no longer write to the socket (there still might be +** data in the receive buffer - use recv_bytes_available()). +** JNL_Connection::STATE_NOCONNECTION +** - no connection has been made yet. call connect() already! :) +** JNL_Connection::STATE_RESOLVING +** - the connection is still waiting for a JNL_AsycnDNS to resolve the +** host. +** JNL_Connection::STATE_CONNECTING +** - the asynchronous call to connect() is still running. +** JNL_Connection::STATE_CONNECTED +** - the connection has connected, all is well. +** JNL_Connection::STATE_CLOSING +** - the connection is closing. This happens after a call to close, +** without the quick parameter set. This means that the connection +** will close once the data in the send buffer is sent (data could +** still be being received when it would be closed). After it is +** closed, the state will transition to: +** JNL_Connection::STATE_CLOSED +** - the connection has closed, generally without error. There still +** might be data in the receieve buffer, use recv_bytes_available(). +** 5. Use send() and send_string() to send data. You can use +** send_bytes_in_queue() to see how much has yet to go out, or +** send_bytes_available() to see how much you can write. If you use send() +** or send_string() and not enough room is available, both functions will +** return error ( < 0) +** 6. Use recv() and recv_line() to get data. If you want to see how much data +** there is, use recv_bytes_available() and recv_lines_available(). If you +** call recv() and not enough data is available, recv() will return how much +** data was actually read. See comments at the function defs. +** +** 7. To close, call close(1) for a quick close, or close() for a close that will +** make the socket close after sending all the data sent. +** +** 8. delete ye' ol' object. +*/ + +#ifndef _CONNECTION_H_ +#define _CONNECTION_H_ + +#include "asyncdns.h" + +#define JNL_CONNECTION_AUTODNS ((JNL_AsyncDNS*)-1) + +class JNL_Connection +{ + public: + typedef enum + { + STATE_ERROR, + STATE_NOCONNECTION, + STATE_RESOLVING, + STATE_CONNECTING, + STATE_CONNECTED, + STATE_CLOSING, + STATE_CLOSED + } state; + + JNL_Connection(JNL_AsyncDNS *dns=JNL_CONNECTION_AUTODNS, int sendbufsize=8192, int recvbufsize=8192); + ~JNL_Connection(); + + void connect(char *hostname, int port); + void connect(int sock, struct sockaddr_in *loc=NULL); // used by the listen object, usually not needed by users. + + void run(int max_send_bytes=-1, int max_recv_bytes=-1, int *bytes_sent=NULL, int *bytes_rcvd=NULL); + int get_state() { return m_state; } + char *get_errstr() { return m_errorstr; } + + void close(int quick=0); + void flush_send(void) { m_send_len=m_send_pos=0; } + + int send_bytes_in_queue(void); + int send_bytes_available(void); + int send(char *data, int length); // returns -1 if not enough room + int send_string(char *line); // returns -1 if not enough room + + + int recv_bytes_available(void); + int recv_bytes(char *data, int maxlength); // returns actual bytes read + unsigned int recv_int(void); + int recv_lines_available(void); + int recv_line(char *line, int maxlength); // returns 0 if the line was terminated with a \r or \n, 1 if not. + // (i.e. if you specify maxlength=10, and the line is 12 bytes long + // it will return 1. or if there is no \r or \n and that's all the data + // the connection has.) + int peek_bytes(char *data, int maxlength); // returns bytes peeked + + unsigned long get_interface(void); // this returns the interface the connection is on + unsigned long get_remote(void) { return m_saddr.sin_addr.s_addr; } // remote host ip. + short get_remote_port(void) { return m_remote_port; } // this returns the remote port of connection + + protected: + int m_socket; + short m_remote_port; + char *m_recv_buffer; + char *m_send_buffer; + int m_recv_buffer_len; + int m_send_buffer_len; + + int m_recv_pos; + int m_recv_len; + int m_send_pos; + int m_send_len; + + struct sockaddr_in m_saddr; + char m_host[256]; + + JNL_AsyncDNS *m_dns; + int m_dns_owned; + + state m_state; + char *m_errorstr; + + int getbfromrecv(int pos, int remove); // used by recv_line* + +}; + +#endif // _Connection_H_ diff --git a/Contrib/NSISdl/httpget.cpp b/Contrib/NSISdl/httpget.cpp new file mode 100644 index 00000000..9cb8b35a --- /dev/null +++ b/Contrib/NSISdl/httpget.cpp @@ -0,0 +1,471 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: httpget.cpp - JNL HTTP GET implementation +** License: see jnetlib.h +*/ + +#include "netinc.h" +#include "util.h" +#include "httpget.h" + + +JNL_HTTPGet::JNL_HTTPGet(JNL_AsyncDNS *dns, int recvbufsize, char *proxy) +{ + m_recvbufsize=recvbufsize; + m_dns=dns; + m_con=NULL; + m_http_proxylpinfo=0; + m_http_proxyhost=0; + m_http_proxyport=0; + if (proxy && *proxy) + { + char *p=(char*)malloc(strlen(proxy)+1); + if (p) + { + char *r=NULL; + strcpy(p,proxy); + do_parse_url(p,&m_http_proxyhost,&m_http_proxyport,&r,&m_http_proxylpinfo); + free(r); + free(p); + } + } + m_sendheaders=NULL; + reinit(); +} + +void JNL_HTTPGet::reinit() +{ + m_errstr=0; + m_recvheaders=NULL; + m_recvheaders_size=0; + m_http_state=0; + m_http_port=0; + m_http_url=0; + m_reply=0; + m_http_host=m_http_lpinfo=m_http_request=NULL; +} + +void JNL_HTTPGet::deinit() +{ + delete m_con; + free(m_recvheaders); + + free(m_http_url); + free(m_http_host); + free(m_http_lpinfo); + free(m_http_request); + free(m_errstr); + free(m_reply); + reinit(); +} + +JNL_HTTPGet::~JNL_HTTPGet() +{ + deinit(); + free(m_sendheaders); + free(m_http_proxylpinfo); + free(m_http_proxyhost); + +} + + +void JNL_HTTPGet::addheader(char *header) +{ + //if (strstr(header,"\r") || strstr(header,"\n")) return; + if (!m_sendheaders) + { + m_sendheaders=(char*)malloc(strlen(header)+3); + if (m_sendheaders) + { + strcpy(m_sendheaders,header); + strcat(m_sendheaders,"\r\n"); + } + } + else + { + char *t=(char*)malloc(strlen(header)+strlen(m_sendheaders)+1+2); + if (t) + { + strcpy(t,m_sendheaders); + strcat(t,header); + strcat(t,"\r\n"); + free(m_sendheaders); + m_sendheaders=t; + } + } +} + +void JNL_HTTPGet::do_encode_mimestr(char *in, char *out) +{ + char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int shift = 0; + int accum = 0; + + while (*in) + { + if (*in) + { + accum <<= 8; + shift += 8; + accum |= *in++; + } + while ( shift >= 6 ) + { + shift -= 6; + *out++ = alphabet[(accum >> shift) & 0x3F]; + } + } + if (shift == 4) + { + *out++ = alphabet[(accum & 0xF)<<2]; + *out++='='; + } + else if (shift == 2) + { + *out++ = alphabet[(accum & 0x3)<<4]; + *out++='='; + *out++='='; + } + + *out++=0; +} + + +void JNL_HTTPGet::connect(char *url) +{ + deinit(); + m_http_url=(char*)malloc(strlen(url)+1); + strcpy(m_http_url,url); + do_parse_url(m_http_url,&m_http_host,&m_http_port,&m_http_request, &m_http_lpinfo); + strcpy(m_http_url,url); + if (!m_http_host || !m_http_host[0] || !m_http_port) + { + m_http_state=-1; + seterrstr("invalid URL"); + return; + } + + int sendbufferlen=0; + + if (!m_http_proxyhost || !m_http_proxyhost[0]) + { + sendbufferlen += 4 /* GET */ + strlen(m_http_request) + 9 /* HTTP/1.0 */ + 2; + } + else + { + sendbufferlen += 4 /* GET */ + strlen(m_http_url) + 9 /* HTTP/1.0 */ + 2; + if (m_http_proxylpinfo&&m_http_proxylpinfo[0]) + { + sendbufferlen+=58+strlen(m_http_proxylpinfo)*2; // being safe here + } + } + sendbufferlen += 5 /* Host: */ + strlen(m_http_host) + 2; + + if (m_http_lpinfo&&m_http_lpinfo[0]) + { + sendbufferlen+=46+strlen(m_http_lpinfo)*2; // being safe here + } + + if (m_sendheaders) sendbufferlen+=strlen(m_sendheaders); + + char *str=(char*)malloc(sendbufferlen+1024); + if (!str) + { + seterrstr("error allocating memory"); + m_http_state=-1; + } + + if (!m_http_proxyhost || !m_http_proxyhost[0]) + { + wsprintf(str,"GET %s HTTP/1.0\r\n",m_http_request); + } + else + { + wsprintf(str,"GET %s HTTP/1.0\r\n",m_http_url); + } + + wsprintf(str+strlen(str),"Host:%s\r\n",m_http_host); + + if (m_http_lpinfo&&m_http_lpinfo[0]) + { + strcat(str,"Authorization: Basic "); + do_encode_mimestr(m_http_lpinfo,str+strlen(str)); + strcat(str,"\r\n"); + } + if (m_http_proxylpinfo&&m_http_proxylpinfo[0]) + { + strcat(str,"Proxy-Authorization: Basic "); + do_encode_mimestr(m_http_proxylpinfo,str+strlen(str)); + strcat(str,"\r\n"); + } + + if (m_sendheaders) strcat(str,m_sendheaders); + strcat(str,"\r\n"); + + int a=m_recvbufsize; + if (a < 4096) a=4096; + m_con=new JNL_Connection(m_dns,strlen(str)+4,a); + if (m_con) + { + if (!m_http_proxyhost || !m_http_proxyhost[0]) + { + m_con->connect(m_http_host,m_http_port); + } + else + { + m_con->connect(m_http_proxyhost,m_http_proxyport); + } + m_con->send_string(str); + } + else + { + m_http_state=-1; + seterrstr("could not create connection object"); + } + free(str); + +} + +static int _strnicmp(char *b1, char *b2, int l) +{ + while (l-- && *b1 && *b2) + { + char bb1=*b1++; + char bb2=*b2++; + if (bb1>='a' && bb1 <= 'z') bb1+='A'-'a'; + if (bb2>='a' && bb2 <= 'z') bb2+='A'-'a'; + if (bb1 != bb2) return bb1-bb2; + } + return 0; +} + +char *_strstr(char *i, char *s) +{ + if (strlen(i)>=strlen(s)) while (i[strlen(s)-1]) + { + int l=strlen(s)+1; + char *ii=i; + char *is=s; + while (--l>0) + { + if (*ii != *is) break; + ii++; + is++; + } + if (l==0) return i; + i++; + } + return NULL; +} + +#define strstr _strstr + +void JNL_HTTPGet::do_parse_url(char *url, char **host, int *port, char **req, char **lp) +{ + char *p,*np; + free(*host); *host=0; + free(*req); *req=0; + free(*lp); *lp=0; + + if (strstr(url,"://")) np=p=strstr(url,"://")+3; + else np=p=url; + while (*np != '/' && *np) np++; + if (*np) + { + *req=(char*)malloc(strlen(np)+1); + if (*req) strcpy(*req,np); + *np++=0; + } + else + { + *req=(char*)malloc(2); + if (*req) strcpy(*req,"/"); + } + + np=p; + while (*np != '@' && *np) np++; + if (*np) + { + *np++=0; + *lp=(char*)malloc(strlen(p)+1); + if (*lp) strcpy(*lp,p); + p=np; + } + else + { + *lp=(char*)malloc(1); + if (*lp) strcpy(*lp,""); + } + np=p; + while (*np != ':' && *np) np++; + if (*np) + { + *np++=0; + *port=my_atoi(np); + } else *port=80; + *host=(char*)malloc(strlen(p)+1); + if (*host) strcpy(*host,p); +} + + +char *JNL_HTTPGet::getallheaders() +{ // double null terminated, null delimited list + if (m_recvheaders) return m_recvheaders; + else return "\0\0"; +} + +char *JNL_HTTPGet::getheader(char *headername) +{ + char *ret=NULL; + if (strlen(headername)<1||!m_recvheaders) return NULL; + char *p=m_recvheaders; + while (*p) + { + if (!_strnicmp(headername,p,strlen(headername))) + { + ret=p+strlen(headername); + while (*ret == ' ') ret++; + break; + } + p+=strlen(p)+1; + } + return ret; +} + +int JNL_HTTPGet::run() +{ + int cnt=0; + if (m_http_state==-1||!m_con) return -1; // error + + +run_again: + static char buf[4096]; + m_con->run(); + + if (m_con->get_state()==JNL_Connection::STATE_ERROR) + { + seterrstr(m_con->get_errstr()); + return -1; + } + if (m_con->get_state()==JNL_Connection::STATE_CLOSED) return 1; + + if (m_http_state==0) // connected, waiting for reply + { + if (m_con->recv_lines_available()>0) + { + m_con->recv_line(buf,4095); + buf[4095]=0; + m_reply=(char*)malloc(strlen(buf)+1); + strcpy(m_reply,buf); + + if (strstr(buf,"200")) m_http_state=2; // proceed to read headers normally + else if (strstr(buf,"301") || strstr(buf,"302")) + { + m_http_state=1; // redirect city + } + else + { + seterrstr(buf); + m_http_state=-1; + return -1; + } + cnt=0; + } + else if (!cnt++) goto run_again; + } + if (m_http_state == 1) // redirect + { + while (m_con->recv_lines_available() > 0) + { + m_con->recv_line(buf,4096); + if (!buf[0]) + { + m_http_state=-1; + return -1; + } + if (!_strnicmp(buf,"Location:",9)) + { + char *p=buf+9; while (*p== ' ') p++; + if (*p) + { + connect(p); + return 0; + } + } + } + } + if (m_http_state==2) + { + if (!cnt++ && m_con->recv_lines_available() < 1) goto run_again; + while (m_con->recv_lines_available() > 0) + { + m_con->recv_line(buf,4096); + if (!buf[0]) { m_http_state=3; break; } + if (!m_recvheaders) + { + m_recvheaders_size=strlen(buf)+1; + m_recvheaders=(char*)malloc(m_recvheaders_size+1); + if (m_recvheaders) + { + strcpy(m_recvheaders,buf); + m_recvheaders[m_recvheaders_size]=0; + } + } + else + { + int oldsize=m_recvheaders_size; + m_recvheaders_size+=strlen(buf)+1; + char *n=(char*)malloc(m_recvheaders_size+1); + if (n) + { + memcpy(n,m_recvheaders,oldsize); + strcpy(n+oldsize,buf); + n[m_recvheaders_size]=0; + free(m_recvheaders); + m_recvheaders=n; + } + } + } + } + if (m_http_state==3) + { + } + return 0; +} + +int JNL_HTTPGet::get_status() // returns 0 if connecting, 1 if reading headers, + // 2 if reading content, -1 if error. +{ + if (m_http_state < 0) return -1; + if (m_http_state < 2) return 0; + if (m_http_state == 2) return 1; + if (m_http_state == 3) return 2; + return -1; +} + +int JNL_HTTPGet::getreplycode()// returns 0 if none yet, otherwise returns http reply code. +{ + if (!m_reply) return 0; + char *p=m_reply; + while (*p && *p != ' ') p++; // skip over HTTP/x.x + if (!*p) return 0; + return my_atoi(++p); +} + +int JNL_HTTPGet::bytes_available() +{ + if (m_con && m_http_state==3) return m_con->recv_bytes_available(); + return 0; +} +int JNL_HTTPGet::get_bytes(char *buf, int len) +{ + if (m_con && m_http_state==3) return m_con->recv_bytes(buf,len); + return 0; +} +int JNL_HTTPGet::peek_bytes(char *buf, int len) +{ + if (m_con && m_http_state==3) return m_con->peek_bytes(buf,len); + return 0; +} diff --git a/Contrib/NSISdl/httpget.h b/Contrib/NSISdl/httpget.h new file mode 100644 index 00000000..88dc5f4b --- /dev/null +++ b/Contrib/NSISdl/httpget.h @@ -0,0 +1,109 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: httpget.h - JNL interface for doing HTTP GETs. +** License: see jnetlib.h +** +** Usage: +** 1. Create a JNL_HTTPGet object, optionally specifying a JNL_AsyncDNS +** object to use (or NULL for none, or JNL_CONNECTION_AUTODNS for auto), +** and the receive buffer size, and a string specifying proxy (or NULL +** for none). See note on proxy string below. +** 2. call addheader() to add whatever headers you want. It is recommended to +** add at least the following two: +** addheader("User-Agent:MyApp (Mozilla)"); +*/// addheader("Accept:*/*"); +/* ( the comment weirdness is there so I Can do the star-slash :) +** 3. Call connect() with the URL you wish to GET (see URL string note below) +** 4. Call run() once in a while, checking to see if it returns -1 +** (if it does return -1, call geterrorstr() to see what the error is). +** (if it returns 1, no big deal, the connection has closed). +** 5. While you're at it, you can call bytes_available() to see if any data +** from the http stream is available, or getheader() to see if any headers +** are available, or getreply() to see the HTTP reply, or getallheaders() +** to get a double null terminated, null delimited list of headers returned. +** 6. If you want to read from the stream, call get_bytes (which returns how much +** was actually read). +** 7. content_length() is a helper function that uses getheader() to check the +** content-length header. +** 8. Delete ye' ol' object when done. +** +** Proxy String: +** should be in the format of host:port, or user@host:port, or +** user:password@host:port. if port is not specified, 80 is assumed. +** URL String: +** should be in the format of http://user:pass@host:port/requestwhatever +** note that user, pass, port, and /requestwhatever are all optional :) +** note that also, http:// is really not important. if you do poo:// +** or even leave out the http:// altogether, it will still work. +*/ + +#ifndef _HTTPGET_H_ +#define _HTTPGET_H_ + +#include "connection.h" + +class JNL_HTTPGet +{ + public: + JNL_HTTPGet(JNL_AsyncDNS *dns=JNL_CONNECTION_AUTODNS, int recvbufsize=16384, char *proxy=NULL); + ~JNL_HTTPGet(); + + void addheader(char *header); + + void connect(char *url); + + int run(); // returns: 0 if all is OK. -1 if error (call geterrorstr()). 1 if connection closed. + + int get_status(); // returns 0 if connecting, 1 if reading headers, + // 2 if reading content, -1 if error. + + char *getallheaders(); // double null terminated, null delimited list + char *getheader(char *headername); + char *getreply() { return m_reply; } + int getreplycode(); // returns 0 if none yet, otherwise returns http reply code. + + char *geterrorstr() { return m_errstr;} + + int bytes_available(); + int get_bytes(char *buf, int len); + int peek_bytes(char *buf, int len); + + int content_length() { char *p=getheader("content-length:"); if (p) return my_atoi(p); return 0; } + + JNL_Connection *get_con() { return m_con; } + + public: + void reinit(); + void deinit(); + void seterrstr(char *str) { if (m_errstr) free(m_errstr); m_errstr=(char*)malloc(strlen(str)+1); strcpy(m_errstr,str); } + + void do_parse_url(char *url, char **host, int *port, char **req, char **lp); + void do_encode_mimestr(char *in, char *out); + + JNL_AsyncDNS *m_dns; + JNL_Connection *m_con; + int m_recvbufsize; + + int m_http_state; + + int m_http_port; + char *m_http_url; + char *m_http_host; + char *m_http_lpinfo; + char *m_http_request; + + char *m_http_proxylpinfo; + char *m_http_proxyhost; + int m_http_proxyport; + + char *m_sendheaders; + char *m_recvheaders; + int m_recvheaders_size; + char *m_reply; + + char *m_errstr; +}; + +#endif // _HTTPGET_H_ diff --git a/Contrib/NSISdl/netinc.h b/Contrib/NSISdl/netinc.h new file mode 100644 index 00000000..b4d96fda --- /dev/null +++ b/Contrib/NSISdl/netinc.h @@ -0,0 +1,82 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: netinc.h - network includes and portability defines (used internally) +** License: see jnetlib.h +*/ + +#ifndef _NETINC_H_ +#define _NETINC_H_ + +#ifdef _WIN32 + +#include +#include +#include +#define strcasecmp(x,y) stricmp(x,y) +#define ERRNO (WSAGetLastError()) +#define SET_SOCK_BLOCK(s,block) { unsigned long __i=block?0:1; ioctlsocket(s,FIONBIO,&__i); } +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EINPROGRESS WSAEWOULDBLOCK +typedef int socklen_t; + +#else + +#ifndef THREAD_SAFE +#define THREAD_SAFE +#endif +#ifndef _REENTRANT +#define _REENTRANT +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERRNO errno +#define closesocket(s) close(s) +#define SET_SOCK_BLOCK(s,block) { int __flags; if ((__flags = fcntl(s, F_GETFL, 0)) != -1) { if (!block) __flags |= O_NONBLOCK; else __flags &= ~O_NONBLOCK; fcntl(s, F_SETFL, __flags); } } + +#define stricmp(x,y) strcasecmp(x,y) +#define strnicmp(x,y,z) strncasecmp(x,y,z) +#define wsprintf sprintf + +#endif // !_WIN32 + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#ifndef INADDR_ANY +#define INADDR_ANY 0 +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + +extern void mini_memset(void *,char,int); +extern void mini_memcpy(void *,void*,int); +#define memset mini_memset +#define memcpy mini_memcpy +#define strcpy lstrcpy +#define strncpy lstrcpyn +#define strcat lstrcat +#define strlen lstrlen +#define malloc(x) GlobalAlloc(GPTR,(x)) +#define free(x) { if (x) GlobalFree(x); } + +#endif //_NETINC_H_ diff --git a/Contrib/NSISdl/nsisdl.cpp b/Contrib/NSISdl/nsisdl.cpp new file mode 100644 index 00000000..af30f253 --- /dev/null +++ b/Contrib/NSISdl/nsisdl.cpp @@ -0,0 +1,448 @@ +/* + NSIS-DL 1.1 - http downloading DLL for NSIS + Copyright (C) 2001 Yaroslav Faybishenko & Justin Frankel + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + + + Note: this source code is pretty hacked together right now, improvements + and cleanups will come later. + + */ + +#include +#include +#include + +#include "netinc.h" +#include "util.h" +#include "resource.h" +#include "httpget.h" + + +void *operator new( unsigned int num_bytes ) +{ + return GlobalAlloc(GPTR,num_bytes); +} +void operator delete( void *p ) { if (p) GlobalFree(p); } + +typedef struct _stack_t { + struct _stack_t *next; + char text[1]; // this should be the length of string_size +} stack_t; + +static int popstring(char *str); // 0 on success, 1 on empty stack +static void setuservariable(int varnum, char *var); + +enum +{ +INST_0, // $0 +INST_1, // $1 +INST_2, // $2 +INST_3, // $3 +INST_4, // $4 +INST_5, // $5 +INST_6, // $6 +INST_7, // $7 +INST_8, // $8 +INST_9, // $9 +INST_R0, // $R0 +INST_R1, // $R1 +INST_R2, // $R2 +INST_R3, // $R3 +INST_R4, // $R4 +INST_R5, // $R5 +INST_R6, // $R6 +INST_R7, // $R7 +INST_R8, // $R8 +INST_R9, // $R9 +INST_CMDLINE, // $CMDLINE +INST_INSTDIR, // $INSTDIR +INST_OUTDIR, // $OUTDIR +INST_EXEDIR, // $EXEDIR +__INST_LAST +}; + + +HANDLE hModule; +HWND g_parent; +HWND g_dialog; +HWND g_childwnd; +int g_stringsize; +stack_t **g_stacktop; +char *g_variables; +static int g_cancelled; + +BOOL CALLBACK DownloadDialogProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + return 0; +} + + +static void *lpWndProcOld; + +static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_COMMAND && LOWORD(wParam) == IDCANCEL) + { + g_cancelled = 1; + return 0; + } + return CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); +} + + +BOOL APIENTRY DllMain( HANDLE _hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + hModule = _hModule; + JNL::open_socketlib (); + break; + + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + JNL::close_socketlib (); + break; + + } + + return TRUE; +} + + +static int g_file_size; + +static void progress_callback(char *msg, int read_bytes) +{ + if (g_dialog) + { + HWND hwndProgressBar = GetDlgItem (g_dialog, IDC_PROGRESS1); + + SetDlgItemText (g_dialog, IDC_STATIC2, msg); + if (g_file_size) SendMessage(hwndProgressBar, PBM_SETPOS, (WPARAM)MulDiv(read_bytes,30000,g_file_size), 0); + } +} + +static int getProxyInfo(char *out) +{ + DWORD v=0; + HKEY hKey; + if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",0,KEY_READ,&hKey) == ERROR_SUCCESS) + { + DWORD l = 4; + DWORD t; + if (RegQueryValueEx(hKey,"ProxyEnable",NULL,&t,(unsigned char *)&v,&l) == ERROR_SUCCESS && t == REG_DWORD) + { + l=8192; + if (RegQueryValueEx(hKey,"ProxyServer",NULL,&t,(unsigned char *)out,&l ) != ERROR_SUCCESS || t != REG_SZ) + { + v=0; + *out=0; + } + } + else v=0; + out[8192-1]=0; + RegCloseKey(hKey); + } + return v; +} + + +extern char *_strstr(char *i, char *s); + +static +void downloadFile(char *url, + HANDLE hFile, + char **error) +{ + static char buf[8192]; + char *p=NULL; + if (getProxyInfo(buf)) + { + p=_strstr(buf,"http="); + if (!p) p=buf; + else + { + p+=5; + char *tp=_strstr(p,";"); + if (tp) *tp=0; + } + } + DWORD start_time=GetTickCount(); + JNL_HTTPGet *get=new JNL_HTTPGet(JNL_CONNECTION_AUTODNS,16384,(p&&p[0])?p:NULL); + int st; + int has_printed_headers = 0; + int cl; + int len; + int sofar = 0; + + get->addheader ("User-Agent: NSISDL/1.1 (Mozilla)"); + get->addheader ("Accept: */*"); + + get->connect (url); + + while (1) { + if (g_dialog) + { + MSG msg; + while (PeekMessage(&msg,g_dialog,0,0,PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + Sleep(25); + + if (g_cancelled) break; + + st = get->run (); + + if (st == -1) { + *error=get->geterrorstr(); + break; + } else if (st == 1) { + if (sofar < cl) + *error="download incomplete"; + break; + } else { + + if (get->get_status () == 0) { + // progressFunc ("Connecting ...", 0); + + } else if (get->get_status () == 1) { + + progress_callback("Reading headers", 0); + + } else if (get->get_status () == 2) { + + if (! has_printed_headers) { + has_printed_headers = 1; + + cl = get->content_length (); + if (cl == 0) { + *error = "Server did not specify content length."; + break; + } else if (g_dialog) { + HWND hwndProgressBar = GetDlgItem (g_dialog, IDC_PROGRESS1); + SendMessage(hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,30000)); + g_file_size=cl; + } + } + + while ((len = get->bytes_available ()) > 0) { + if (len > 8192) + len = 8192; + len = get->get_bytes (buf, len); + if (len > 0) { + DWORD dw; + WriteFile(hFile,buf,len,&dw,NULL); + sofar += len; + int time_sofar=(GetTickCount()-start_time)/1000; + int bps=sofar/(time_sofar?time_sofar:1); + int remain=MulDiv(time_sofar,cl,sofar) - time_sofar; + char *rtext="second"; + if (remain >= 60) + { + remain/=60; + rtext="minute"; + if (remain >= 60) + { + remain/=60; + rtext="hour"; + } + } + wsprintf (buf, + "%dkB (%d%%) of %dkB @ %d.%01dkB/s", + sofar/1024, + MulDiv(100,sofar,cl), + cl/1024, + bps/1024,((bps*10)/1024)%10 + ); + if (remain) wsprintf(buf+lstrlen(buf)," (%d %s%s remaining)", + remain, + rtext, + remain==1?"":"s" + ); + progress_callback(buf, sofar); + } else { + if (sofar < cl) + *error = "Server aborted."; + + break; + } + } + + } else { + *error = "Bad response status."; + break; + } + } + + } + + if (*error) + { + char *t=*error; + *error = (char *)GlobalAlloc(GPTR,strlen(t)+1); + lstrcpy(*error,t); + } + delete get; +} + +extern "C" +{ + +__declspec(dllexport) void download (HWND parent, + int stringsize, + char *variables, + stack_t **stacktop) +{ + static char buf[1024]; + static char url[1024]; + static char filename[1024]; + int wasen=0; + HWND hwndL=0; + HWND hwndB=0; + + g_parent = parent; + g_stringsize = stringsize; + g_variables = variables; + g_stacktop = stacktop; + + popstring (filename); + popstring (url); + + HANDLE hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + wsprintf (buf, "Unable to open %s", filename); + setuservariable(INST_0, buf); + } else { + if (g_parent) + { + g_childwnd=FindWindowEx(g_parent,NULL,"#32770",NULL); + hwndL=GetDlgItem(g_childwnd,1016); + hwndB=GetDlgItem(g_childwnd,1027); + if (hwndL && IsWindowVisible(hwndL)) ShowWindow(hwndL,SW_HIDE); + else hwndL=NULL; + if (hwndB && IsWindowVisible(hwndB)) ShowWindow(hwndB,SW_HIDE); + else hwndB=NULL; + + wasen=EnableWindow(GetDlgItem(g_parent,IDCANCEL),1); + lpWndProcOld = (void *) GetWindowLong(g_parent,GWL_WNDPROC); + SetWindowLong(g_parent,GWL_WNDPROC,(long)ParentWndProc); + + g_dialog = CreateDialog((HINSTANCE)hModule, + MAKEINTRESOURCE(IDD_DIALOG1), + g_childwnd, + DownloadDialogProc); + if (g_dialog) + { + RECT r; + GetWindowRect(GetDlgItem(g_childwnd,1016),&r); + ScreenToClient(g_childwnd,(LPPOINT)&r); + SetWindowPos(g_dialog,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); + ShowWindow(g_dialog,SW_SHOWNA); + char *p=filename; + while (*p) p++; + while (*p != '\\' && p != filename) p=CharPrev(filename,p); + wsprintf(buf,"Downloading %s", p+1); + SetDlgItemText(g_childwnd,1006,buf); + + wsprintf(buf,"Connecting ..."); + SetDlgItemText (g_dialog, IDC_STATIC2, buf); + } + } + + + char *error=NULL; + + downloadFile(url, hFile, &error); + + CloseHandle(hFile); + if (g_parent) + { + if (g_dialog) DestroyWindow(g_dialog); + if (lpWndProcOld) + SetWindowLong(g_parent,GWL_WNDPROC,(long)lpWndProcOld); + if (g_childwnd) + { + if (hwndB) ShowWindow(hwndB,SW_SHOWNA); + if (hwndL) ShowWindow(hwndL,SW_SHOWNA); + } + if (wasen) EnableWindow(GetDlgItem(g_parent,IDCANCEL),0); + } + + + + if (g_cancelled) { + setuservariable(INST_0, "cancel"); + DeleteFile(filename); + } else if (error == NULL) { + setuservariable(INST_0, "success"); + } else { + DeleteFile(filename); + setuservariable(INST_0, error); + } + if (error) GlobalFree(error); + } +} + + +__declspec(dllexport) void download_quiet(HWND parent, + int stringsize, + char *variables, + stack_t **stacktop) +{ + download(NULL,stringsize,variables,stacktop); +} + +} + +// utility functions (not required but often useful) +static +int popstring(char *str) +{ + stack_t *th; + if (!g_stacktop || !*g_stacktop) return 1; + th=(*g_stacktop); + lstrcpy(str,th->text); + *g_stacktop = th->next; + GlobalFree((HGLOBAL)th); + return 0; +} + +static +void setuservariable(int varnum, char *var) +{ + if (var != NULL && varnum >= 0 && varnum < __INST_LAST) { + lstrcpy (g_variables + varnum*g_stringsize, var); + + } +} diff --git a/Contrib/NSISdl/nsisdl.dsp b/Contrib/NSISdl/nsisdl.dsp new file mode 100644 index 00000000..a905672f --- /dev/null +++ b/Contrib/NSISdl/nsisdl.dsp @@ -0,0 +1,152 @@ +# Microsoft Developer Studio Project File - Name="nsisdl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=nsisdl - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "nsisdl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nsisdl.mak" CFG="nsisdl - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nsisdl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "nsisdl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "nsisdl - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSISDL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSISDL_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /entry:"DllMain" /dll /machine:I386 /nodefaultlib /out:"../../nsisdl.dll" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "nsisdl - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSISDL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSISDL_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "nsisdl - Win32 Release" +# Name "nsisdl - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\asyncdns.cpp +# End Source File +# Begin Source File + +SOURCE=.\connection.cpp +# End Source File +# Begin Source File + +SOURCE=.\httpget.cpp +# End Source File +# Begin Source File + +SOURCE=.\nsisdl.cpp +# End Source File +# Begin Source File + +SOURCE=.\Script1.rc +# End Source File +# Begin Source File + +SOURCE=.\util.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\asyncdns.h +# End Source File +# Begin Source File + +SOURCE=.\connection.h +# End Source File +# Begin Source File + +SOURCE=.\httpget.h +# End Source File +# Begin Source File + +SOURCE=.\netinc.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/Contrib/NSISdl/nsisdl.dsw b/Contrib/NSISdl/nsisdl.dsw new file mode 100644 index 00000000..fdfdbcd3 --- /dev/null +++ b/Contrib/NSISdl/nsisdl.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "nsisdl"=.\nsisdl.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/NSISdl/resource.h b/Contrib/NSISdl/resource.h new file mode 100644 index 00000000..a4e827f2 --- /dev/null +++ b/Contrib/NSISdl/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#define IDD_DIALOG1 101 +#define IDC_PROGRESS1 1001 +#define IDC_STATIC1 1002 +#define IDC_STATIC2 1003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Contrib/NSISdl/util.cpp b/Contrib/NSISdl/util.cpp new file mode 100644 index 00000000..dd80613f --- /dev/null +++ b/Contrib/NSISdl/util.cpp @@ -0,0 +1,64 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: util.cpp - JNL implementation of basic network utilities +** License: see jnetlib.h +*/ + +#include "netinc.h" + +#include "util.h" + +int JNL::open_socketlib() +{ +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(1, 1), &wsaData)) return 1; +#endif + return 0; +} +void JNL::close_socketlib() +{ +#ifdef _WIN32 + WSACleanup(); +#endif +} +unsigned long JNL::ipstr_to_addr(const char *cp) +{ + return ::inet_addr(cp); +} + +void JNL::addr_to_ipstr(unsigned long addr, char *host, int maxhostlen) +{ + struct in_addr a; a.s_addr=addr; + char *p=::inet_ntoa(a); strncpy(host,p?p:"",maxhostlen); +} + +int my_atoi(char *s) +{ + int sign=0; + int v=0; + if (*s == '-') { s++; sign++; } + for (;;) + { + int c=*s++ - '0'; + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) return -(int) v; + return (int)v; +} + +void mini_memset(void *o,char i,int l) +{ + char *oo=(char*)o; + while (l-- > 0) *oo++=i; +} +void mini_memcpy(void *o,void*i,int l) +{ + char *oo=(char*)o; + char *ii=(char*)i; + while (l-- > 0) *oo++=*ii++; +} \ No newline at end of file diff --git a/Contrib/NSISdl/util.h b/Contrib/NSISdl/util.h new file mode 100644 index 00000000..d271fd6c --- /dev/null +++ b/Contrib/NSISdl/util.h @@ -0,0 +1,41 @@ +/* +** JNetLib +** Copyright (C) 2000-2001 Nullsoft, Inc. +** Author: Justin Frankel +** File: util.h - JNL interface for basic network utilities +** License: see jnetlib.h +** +** routines you may be interested in: +** JNL::open_socketlib(); +** opens the socket library. Call this once before using any network +** code. If you create a new thread, call this again. Only really an +** issue for Win32 support, but use it anyway for portability/ +** +** JNL::close_Socketlib(); +** closes the socketlib. Call this when you're done with the network, +** after all your JNetLib objects have been destroyed. +** +** unsigned long JNL::ipstr_to_addr(const char *cp); +** gives you the integer representation of a ip address in dotted +** decimal form. +** +** JNL::addr_to_ipstr(unsigned long addr, char *host, int maxhostlen); +** gives you the dotted decimal notation of an integer ip address. +** +*/ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +class JNL +{ + public: + static int open_socketlib(); + static void close_socketlib(); + static unsigned long ipstr_to_addr(const char *cp); + static void addr_to_ipstr(unsigned long addr, char *host, int maxhostlen); +}; + +int my_atoi(char *p); + +#endif //_UTIL_H_ diff --git a/Contrib/Splash/splash.c b/Contrib/Splash/splash.c new file mode 100644 index 00000000..44c2d878 --- /dev/null +++ b/Contrib/Splash/splash.c @@ -0,0 +1,137 @@ +#include + +HBITMAP g_hbm; +int sleep_val; +int g_rv; + +static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CREATE) + { + BITMAP bm; + RECT vp; + GetObject(g_hbm, sizeof(bm), (LPSTR)&bm); + SystemParametersInfo(SPI_GETWORKAREA, 0, &vp, 0); + SetWindowLong(hwnd,GWL_STYLE,0); + SetWindowPos(hwnd,NULL, + vp.left+(vp.right-vp.left-bm.bmWidth)/2, + vp.top+(vp.bottom-vp.top-bm.bmHeight)/2, + bm.bmWidth,bm.bmHeight, + SWP_NOZORDER); + ShowWindow(hwnd,SW_SHOW); + SetTimer(hwnd,1,sleep_val,NULL); + return 0; + } + if (uMsg == WM_PAINT) + { + PAINTSTRUCT ps; + RECT r; + HDC curdc=BeginPaint(hwnd,&ps); + HDC hdc=CreateCompatibleDC(curdc); + HBITMAP oldbm; + GetClientRect(hwnd,&r); + oldbm=(HBITMAP)SelectObject(hdc,g_hbm); + BitBlt(curdc,r.left,r.top,r.right-r.left,r.bottom-r.top,hdc,0,0,SRCCOPY); + SelectObject(hdc,oldbm); + DeleteDC(hdc); + EndPaint(hwnd,&ps); + return 0; + } + if (uMsg == WM_CLOSE) return 0; + if (uMsg == WM_DESTROY) + { + PostQuitMessage(0); + return 0; + } + if (uMsg == WM_TIMER || uMsg == WM_LBUTTONDOWN) + { + g_rv=(uMsg == WM_LBUTTONDOWN); + DestroyWindow(hwnd); + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow) +{ + char fn[MAX_PATH]; + int hwndParent; + char *o=fn; + + hInstance=GetModuleHandle(NULL); + lpszCmdParam=GetCommandLine(); + if (*lpszCmdParam == '\"') + { + do + { + lpszCmdParam++; + } while (*lpszCmdParam != '\"' && *lpszCmdParam); + if (*lpszCmdParam) lpszCmdParam++; + } + else + { + do + { + lpszCmdParam++; + } while (*lpszCmdParam != ' ' && *lpszCmdParam); + } + while (*lpszCmdParam == ' ') lpszCmdParam++; + sleep_val=0; + while (*lpszCmdParam >= '0' && *lpszCmdParam <= '9') + { + sleep_val*=10; + sleep_val += *lpszCmdParam++-'0'; + } + + while (*lpszCmdParam == ' ') lpszCmdParam++; + hwndParent=0; + while (*lpszCmdParam >= '0' && *lpszCmdParam <= '9') + { + hwndParent*=10; + hwndParent += *lpszCmdParam++-'0'; + } + + while (*lpszCmdParam == ' ') lpszCmdParam++; + while (*lpszCmdParam) + { + *o++=*lpszCmdParam++; + } + *o=0; + + if (fn[0] && sleep_val>0) + { + MSG msg; + char classname[4]="_sp"; + static WNDCLASS wc; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.lpszClassName = classname; + if (RegisterClass(&wc)) + { + char fn2[MAX_PATH]; + lstrcpy(fn2,fn); + lstrcat(fn,".bmp"); + lstrcat(fn2,".wav"); + g_hbm=LoadImage(NULL,fn,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_LOADFROMFILE); + if (g_hbm) + { + BOOL s=0; + HANDLE f=CreateFile(fn2,0,0,NULL,OPEN_EXISTING,0,NULL); + if (f != INVALID_HANDLE_VALUE) { CloseHandle(f); s=PlaySound(fn2,NULL,SND_ASYNC|SND_FILENAME); } + + CreateWindowEx(WS_EX_TOOLWINDOW,classname,classname, + 0,0,0,0,0,(HWND)hwndParent,NULL,hInstance,NULL); + + while (GetMessage(&msg,NULL,0,0)) + { + DispatchMessage(&msg); + } + + if (s) PlaySound(NULL,0,0); + + DeleteObject(g_hbm); + } + } + } + ExitProcess(g_rv); +} \ No newline at end of file diff --git a/Contrib/Splash/splash.dsp b/Contrib/Splash/splash.dsp new file mode 100644 index 00000000..38a68efc --- /dev/null +++ b/Contrib/Splash/splash.dsp @@ -0,0 +1,108 @@ +# Microsoft Developer Studio Project File - Name="splash" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=splash - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "splash.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "splash.mak" CFG="splash - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "splash - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "splash - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "splash - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Og /Os /Oy /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /Ox /Ow /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /entry:"WinMain" /subsystem:windows /machine:I386 /nodefaultlib /out:"../../splash.exe" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "splash - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "splash - Win32 Release" +# Name "splash - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\splash.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/Contrib/Splash/splash.dsw b/Contrib/Splash/splash.dsw new file mode 100644 index 00000000..80fb0049 --- /dev/null +++ b/Contrib/Splash/splash.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "splash"=.\splash.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/Splash/splash.txt b/Contrib/Splash/splash.txt new file mode 100644 index 00000000..d460b3c2 --- /dev/null +++ b/Contrib/Splash/splash.txt @@ -0,0 +1,38 @@ +Splash.exe - small (3.5k), simple (one file) program that lets you throw +up a splash screen in NSIS installers. + +--- UPDATED in 1.50 - will break old scripts --- + +To use: + +Create a .BMP file of your splash screen. +(optional) Create a .WAV file to play while your splash screen shows. + +Add the following lines to your .NSI file: + +Function .onInit + SetOutPath $TEMP + File /oname=spltmp.bmp "my_splash.bmp" + +; optional +; File /oname=spltmp.wav "my_splashshit.wav" + + File /oname=spltmp.exe "C:\program files\nsis\splash.exe" + ExecWait '"$TEMP\spltmp.exe" 1000 $HWNDPARENT $TEMP\spltmp' + Delete $TEMP\spltmp.exe + Delete $TEMP\spltmp.bmp +; Delete $TEMP\spltmp.wav +FunctionEnd + +Note that the first parameter to splash.exe is the length to show the +screen for (in milliseconds), the second is the parent window (in decimal), +and the last is the splash bitmap filename (without the .bmp). The BMP file +used will be this parameter.bmp, and the wave file used (if present) will be +this parameter.wav. + +(If you already have an .onInit function, put that in it) + +Note: the return value of splash.exe is 1 if the user closed the splash +screen early (you can check it using ClearErrors/IfErrors) + +-Justin diff --git a/Contrib/UIs/default.exe b/Contrib/UIs/default.exe new file mode 100755 index 00000000..11e6832f Binary files /dev/null and b/Contrib/UIs/default.exe differ diff --git a/Contrib/UIs/mlbl.exe b/Contrib/UIs/mlbl.exe new file mode 100755 index 00000000..b0e50308 Binary files /dev/null and b/Contrib/UIs/mlbl.exe differ diff --git a/Contrib/UIs/mlbl2.exe b/Contrib/UIs/mlbl2.exe new file mode 100755 index 00000000..0eb79d43 Binary files /dev/null and b/Contrib/UIs/mlbl2.exe differ diff --git a/Contrib/zip2exe/icon.ico b/Contrib/zip2exe/icon.ico new file mode 100644 index 00000000..b755e000 Binary files /dev/null and b/Contrib/zip2exe/icon.ico differ diff --git a/Contrib/zip2exe/main.cpp b/Contrib/zip2exe/main.cpp new file mode 100644 index 00000000..db6ad810 --- /dev/null +++ b/Contrib/zip2exe/main.cpp @@ -0,0 +1,715 @@ +#include +#include + +// portions Copyright © 1999-2001 Miguel Garrido (mgarrido01@hotmail.com) + +extern "C" +{ +#include "zlib/unzip.h" +}; +#include "resource.h" + +const char *g_errcaption="ZIP2EXE Error"; + +HINSTANCE g_hInstance; +HWND g_hwnd; +HANDLE g_hThread; +char g_cmdline[1024]; +char g_makensis_path[MAX_PATH]; +int g_extracting; +int g_zipfile_size; + +char *g_options="";//"/V3"; + +static BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, + LPSTR lpszCmdParam, int nCmdShow) +{ + g_hInstance=hInstance; + + + return DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),GetDesktopWindow(),DlgProc); +} +char tempzip_path[1024]; + + +int made; + +static void doRMDir(char *buf) +{ + HANDLE h; + WIN32_FIND_DATA fd; + char *p=buf; + while (*p) p++; + lstrcpy(p,"\\*.*"); + h = FindFirstFile(buf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (fd.cFileName[0] != '.' || + (fd.cFileName[1] != '.' && fd.cFileName[1])) + { + lstrcpy(p+1,fd.cFileName); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + SetFileAttributes(buf,fd.dwFileAttributes^FILE_ATTRIBUTE_READONLY); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) doRMDir(buf); + else + { + DeleteFile(buf); + } + } + } while (FindNextFile(h,&fd)); + FindClose(h); + } + p[0]=0; // fix buffer + RemoveDirectory(buf); +} + +static void doMKDir(char *directory) +{ + char *p, *p2; + char buf[MAX_PATH]; + if (!*directory) return; + lstrcpy(buf,directory); + p=buf; while (*p) p++; + while (p >= buf && *p != '\\') p--; + p2 = buf; + if (p2[1] == ':') p2+=4; + else if (p2[0] == '\\' && p2[1] == '\\') + { + p2+=2; + while (*p2 && *p2 != '\\') p2++; + if (*p2) p2++; + while (*p2 && *p2 != '\\') p2++; + if (*p2) p2++; + } + if (p >= p2) + { + *p=0; + doMKDir(buf); + } + CreateDirectory(directory,NULL); +} + + + +void tempzip_cleanup(HWND hwndDlg, int err) +{ + if (tempzip_path[0]) doRMDir(tempzip_path); + tempzip_path[0]=0; + if (err) + { + SendDlgItemMessage(hwndDlg,IDC_ZIPINFO_FILES,LB_RESETCONTENT,0,0); + EnableWindow(GetDlgItem(hwndDlg,IDOK),0); + SetDlgItemText(hwndDlg,IDC_ZIPINFO_SUMMARY,""); + SetDlgItemText(hwndDlg,IDC_ZIPFILE,""); + SetDlgItemText(hwndDlg,IDC_OUTFILE,""); + } +} + +int tempzip_make(HWND hwndDlg, char *fn) +{ + char buf[MAX_PATH]; + GetTempPath(MAX_PATH,buf); + GetTempFileName(buf,"z2e",GetTickCount(),tempzip_path); + if (!CreateDirectory(tempzip_path,NULL)) + { + GetTempPath(MAX_PATH,tempzip_path); + strcat(tempzip_path,"\\nsi"); + if (!CreateDirectory(tempzip_path,NULL)) + { + tempzip_path[0]=0; + MessageBox(hwndDlg,"Error creating temporary directory",g_errcaption,MB_OK|MB_ICONSTOP); + return 1; + } + } + FILE *fp=fopen(fn,"rb"); + if (fp) + { + fseek(fp,0,SEEK_END); + g_zipfile_size=ftell(fp); + fclose(fp); + } + else g_zipfile_size=0; + unzFile f; + f = unzOpen(fn); + if (!f || unzGoToFirstFile(f) != UNZ_OK) + { + if (f) unzClose(f); + MessageBox(hwndDlg,"Error opening ZIP file",g_errcaption,MB_OK|MB_ICONSTOP); + return 1; + } + + int nf=0, nkb=0; + g_extracting=1; + do { + char filename[MAX_PATH]; + unzGetCurrentFileInfo(f,NULL,filename,sizeof(filename),NULL,0,NULL,0); + if (filename[0] && + filename[strlen(filename)-1] != '\\' && + filename[strlen(filename)-1] != '/') + { + char *pfn=filename; + while (*pfn) + { + if (*pfn == '/') *pfn='\\'; + pfn++; + } + pfn=filename; + if (pfn[1] == ':' && pfn[2] == '\\') pfn+=3; + while (*pfn == '\\') pfn++; + + char out_filename[1024]; + lstrcpy(out_filename,tempzip_path); + lstrcat(out_filename,"\\"); + lstrcat(out_filename,pfn); + if (strstr(pfn,"\\")) + { + char buf[1024]; + lstrcpy(buf,out_filename); + char *p=buf+strlen(buf); + while (p > buf && *p != '\\') p--; + *p=0; + if (buf[0]) doMKDir(buf); + } + + if (unzOpenCurrentFile(f) == UNZ_OK) + { + SendDlgItemMessage(hwndDlg,IDC_ZIPINFO_FILES,LB_ADDSTRING,0,(LPARAM)pfn); + FILE *fp; + int l; + fp = fopen(out_filename,"wb"); + if (fp) + { + do + { + char buf[1024]; + l=unzReadCurrentFile(f,buf,sizeof(buf)); + if (l > 0) + { + if (fwrite(buf,1,l,fp) != (unsigned int)l) + { + unzClose(f); + fclose(fp); + MessageBox(hwndDlg,"Error writing output file(s)",g_errcaption,MB_OK|MB_ICONSTOP); + g_extracting=0; + return 1; + } + nkb++; + } + } while (l > 0); + + fclose(fp); + } + else + { + unzClose(f); + MessageBox(hwndDlg,"Error opening output file(s)",g_errcaption,MB_OK|MB_ICONSTOP); + g_extracting=0; + return 1; + } + nf++; + wsprintf(buf,"Extracting: %d files, %dKB",nf,nkb); + SetDlgItemText(hwndDlg,IDC_ZIPINFO_SUMMARY,buf); + MSG msg; + int quit=0; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) + { + if (msg.message == WM_DESTROY && msg.hwnd == g_hwnd) + { + quit++; + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + unzCloseCurrentFile(f); + if (quit) break; + } + else + { + unzClose(f); + MessageBox(hwndDlg,"Error extracting from ZIP file",g_errcaption,MB_OK|MB_ICONSTOP); + g_extracting=0; + return 1; + } + } + } while (unzGoToNextFile(f) == UNZ_OK); + + g_extracting=0; + wsprintf(buf,"Extracted: %d files, %dKB",nf,nkb); + SetDlgItemText(hwndDlg,IDC_ZIPINFO_SUMMARY,buf); + unzClose(f); + return 0; +} + +char *gp_winamp = "(WINAMP DIRECTORY)"; +char *gp_winamp_plugins = "(WINAMP PLUG-INS DIRECTORY)"; +char *gp_winamp_vis = "(WINAMP VIS PLUG-INS DIRECTORY)"; +char *gp_winamp_dsp = "(WINAMP DSP PLUG-INS DIRECTORY)"; +char *gp_winamp_skins = "(WINAMP SKINS DIRECTORY)"; +char *gp_poi = "(PATH OF INSTALLER)"; + + +void wnd_printf(const char *str) +{ + if (!*str) return; + char existing_text[32000]; + existing_text[0]=0; + UINT l=GetDlgItemText(g_hwnd, IDC_OUTPUTTEXT, existing_text, 32000); + l+=strlen(str); + + char *p=existing_text; + existing_text[31000]=0; + while (l > 31000 && *p) + { + while (*p != '\r' && *p != '\n' && *p) + { + p++; + l--; + } + while (*p == '\r' || *p == '\n') + { + p++; + l--; + } + } + + char buf[31000]; + lstrcpy(buf,p); + lstrcpy(existing_text,buf); + lstrcat(existing_text,str); + + SetDlgItemText(g_hwnd, IDC_OUTPUTTEXT, existing_text); + SendDlgItemMessage(g_hwnd, IDC_OUTPUTTEXT, EM_LINESCROLL, 0, SendDlgItemMessage(g_hwnd, IDC_OUTPUTTEXT, EM_GETLINECOUNT, 0, 0)); // scroll to the last line of the textbox + +} + +void ErrorMessage(char *str) //display detailed error info +{ + LPVOID msg; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &msg, + 0, + NULL + ); + wnd_printf(str); + wnd_printf(": "); + wnd_printf((char*)msg); + LocalFree(msg); +} + +DWORD WINAPI ThreadProc(LPVOID p) // thread that will start & monitor wwwinamp +{ + char buf[1024]; //i/o buffer + STARTUPINFO si={sizeof(si),}; + SECURITY_ATTRIBUTES sa={sizeof(sa),}; + SECURITY_DESCRIPTOR sd={0,}; //security information for pipes + PROCESS_INFORMATION pi={0,}; + HANDLE newstdout=0,read_stdout=0; //pipe handles + + OSVERSIONINFO osv={sizeof(osv)}; + GetVersionEx(&osv); + if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) //initialize security descriptor (Windows NT) + { + InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd, true, NULL, false); + sa.lpSecurityDescriptor = &sd; + } + else sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = true; //allow inheritable handles + + if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //create stdout pipe + { + ErrorMessage("CreatePipe"); + PostMessage(g_hwnd,WM_USER+1203,0,1); + return 1; + } + + GetStartupInfo(&si); //set startupinfo for the spawned process + /* + The dwFlags member tells CreateProcess how to make the process. + STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW + validates the wShowWindow member. + */ + si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.hStdOutput = newstdout; + si.hStdError = newstdout; //set the new handles for the child process + + // ******************************************************************* + // If there is a command line in the config file, use it for create process + + //spawn the child process + if (!CreateProcess(NULL,g_cmdline,NULL,NULL,TRUE,CREATE_NEW_CONSOLE, + NULL,tempzip_path,&si,&pi)) + { + ErrorMessage("CreateProcess"); + wnd_printf("\r\nPlease make sure the path to makensis.exe is correct."); + CloseHandle(newstdout); + CloseHandle(read_stdout); + PostMessage(g_hwnd,WM_USER+1203,0,1); + return 1; + } + + unsigned long exit=0; //process exit code + unsigned long bread; //bytes read + unsigned long avail; //bytes available + + memset(buf,0,sizeof(buf)); + while (1) //main program loop + { + PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL); + //check to see if there is any data to read from stdout + if (bread != 0) + { + memset(buf,0,sizeof(buf)); + if (avail > 1023) + { + while (bread >= 1023) + { + ReadFile(read_stdout,buf,1023,&bread,NULL); //read the stdout pipe + wnd_printf(buf); + memset(buf,0,sizeof(buf)); + } + } + else + { + ReadFile(read_stdout,buf,1023,&bread,NULL); + wnd_printf(buf); + } + } + + GetExitCodeProcess(pi.hProcess,&exit); //while the process is running + if (exit != STILL_ACTIVE) + break; + + Sleep(100); + } + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + CloseHandle(newstdout); + CloseHandle(read_stdout); + + + wsprintf(buf,"(source ZIP size was %d bytes)\r\n",g_zipfile_size); + wnd_printf(buf); + + PostMessage(g_hwnd,WM_USER+1203,0,0); + return 0; +} + + +char nsifilename[MAX_PATH]; + + + +void makeEXE(HWND hwndDlg) +{ + char buf[2048]; + GetTempPath(MAX_PATH,buf); + GetTempFileName(buf,"zne",0,nsifilename); + FILE *fp=fopen(nsifilename,"w"); + if (!fp) + { + MessageBox(hwndDlg,"Error writing .NSI file",g_errcaption,MB_OK|MB_ICONSTOP); + return; + } + GetDlgItemText(hwndDlg,IDC_INSTNAME,buf,sizeof(buf)); + fprintf(fp,"Name `%s`\n",buf); + fprintf(fp,"Caption `%s Self Extractor`\n",buf); + GetDlgItemText(hwndDlg,IDC_OUTFILE,buf,sizeof(buf)); + fprintf(fp,"OutFile `%s`\n",buf); + GetDlgItemText(hwndDlg,IDC_INSTPATH,buf,sizeof(buf)); + char *outpath = "$INSTDIR"; + int iswinamp=0; + char *iswinampmode=NULL; + if (!strcmp(buf,gp_poi)) lstrcpy(buf,"$EXEDIR"); + + if (!strcmp(buf,gp_winamp)) + { + iswinamp=1; + fprintf(fp,"Function SetMyOutPath\n" + " SetOutPath $INSTDIR\n" + "FunctionEnd\n"); + } + if (!strcmp(buf,gp_winamp_plugins)) + { + iswinamp=1; + fprintf(fp,"Function SetMyOutPath\n" + " SetOutPath $INSTDIR\\Plugins\n" + "FunctionEnd\n"); + } + if (!strcmp(buf,gp_winamp_vis)) + { + iswinamp=1; + iswinampmode="VisDir"; + } + if (!strcmp(buf,gp_winamp_dsp)) + { + iswinamp=1; + iswinampmode="DSPDir"; + } + if (!strcmp(buf,gp_winamp_skins)) + { + iswinamp=1; + iswinampmode="SkinDir"; + } + + if (iswinamp) + { + fprintf(fp,"InstallDir `$PROGRAMFILES\\Winamp`\n"); + fprintf(fp,"InstallDirRegKey HKEY_LOCAL_MACHINE `Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Winamp` `UninstallString`\n"); + + fprintf(fp,"Function .onVerifyInstDir\n" + " IfFileExists $INSTDIR\\winamp.exe WinampInstalled\n" + " Abort\n" + " WinampInstalled:\n" + "FunctionEnd\n"); + + if (iswinampmode) + { + fprintf(fp,"Function SetMyOutPath\n" + " StrCpy $1 $INSTDIR\\Plugins\n" + " ReadINIStr $9 $INSTDIR\\winamp.ini Winamp %s\n" + " StrCmp $9 '' End\n" + " IfFileExists $9 0 End\n" + " StrCpy $1 $9\n" + " End:\n" + " SetOutPath $1\n" + "FunctionEnd\n",iswinampmode); + } + } + else // set out path to $INSTDIR + { + fprintf(fp,"InstallDir `%s`\n",buf); + fprintf(fp,"Function SetMyOutPath\n" + " SetOutPath $INSTDIR\n" + "FunctionEnd\n"); + } + + GetDlgItemText(hwndDlg,IDC_DESCTEXT,buf,sizeof(buf)); + fprintf(fp,"DirText `%s`\n",buf); + + fprintf(fp,"Section\n"); + fprintf(fp,"Call SetMyOutPath\n"); + fprintf(fp,"File /r `%s\\*.*`\n",tempzip_path); + fprintf(fp,"SectionEnd\n"); + fclose(fp); + + wsprintf(g_cmdline,"\"%s\" %s \"%s\"",g_makensis_path,g_options,nsifilename); + + + DWORD id; + g_hThread=CreateThread(NULL,0,ThreadProc,0,0,&id); + +} + + +BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static int ids[]={IDC_SZIPFRAME,IDC_BROWSE,IDC_ZIPFILE,IDC_ZIPINFO_SUMMARY,IDC_ZIPINFO_FILES,IDC_OFRAME,IDC_INAMEST, + IDC_INSTNAME,IDC_DTEXTST,IDC_DESCTEXT,IDC_DEPST,IDC_INSTPATH,IDC_OEFST,IDC_OUTFILE,IDC_BROWSE2,IDC_BROWSE3,IDC_COMPILER}; + static HICON hIcon; + static HFONT hFont; + if (uMsg == WM_DESTROY) { if (hIcon) DeleteObject(hIcon); hIcon=0; if (hFont) DeleteObject(hFont); hFont=0; } + switch (uMsg) + { + case WM_INITDIALOG: + g_hwnd=hwndDlg; + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_poi); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$TEMP"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$SYSDIR"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$WINDIR"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$DESKTOP"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$DESKTOP\\Poop"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$PROGRAMFILES\\Poop"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$STARTMENU"); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)"$SMPROGRAMS"); + + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_winamp); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_winamp_plugins); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_winamp_vis); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_winamp_dsp); + SendDlgItemMessage(hwndDlg,IDC_INSTPATH,CB_ADDSTRING,0,(LPARAM)gp_winamp_skins); + + SetDlgItemText(hwndDlg,IDC_INSTPATH,gp_poi); + SetDlgItemText(hwndDlg,IDC_DESCTEXT,"Select the folder where you would like to extract the files to:"); + hIcon=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_ICON1)); + SetClassLong(hwndDlg,GCL_HICON,(long)hIcon); + + hFont=CreateFont(15,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET, + OUT_CHARACTER_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY,FIXED_PITCH|FF_DONTCARE,"Courier New"); + SendDlgItemMessage(hwndDlg,IDC_OUTPUTTEXT,WM_SETFONT,(WPARAM)hFont,0); + { + char *p=g_makensis_path; + GetModuleFileName(g_hInstance,g_makensis_path,sizeof(g_makensis_path)); + while (*p) p++; + while (p >= g_makensis_path && *p != '\\') p--; + strcpy(++p,"makensis.exe"); + } + SetDlgItemText(hwndDlg,IDC_COMPILER,g_makensis_path); + return 1; + case WM_CLOSE: + if (!g_hThread) + { + tempzip_cleanup(hwndDlg,0); + EndDialog(hwndDlg,1); + } + break; + case WM_USER+1203: + + if (g_hThread) + { + if (!lParam) + { + ShowWindow(GetDlgItem(hwndDlg,IDC_TEST),SW_SHOWNA); + } + made=1; + ShowWindow(GetDlgItem(hwndDlg,IDC_BACK),SW_SHOWNA); + EnableWindow(GetDlgItem(hwndDlg,IDOK),1); + CloseHandle(g_hThread); + g_hThread=0; + if (nsifilename[0]) DeleteFile(nsifilename); + nsifilename[0]=0; + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_BROWSE: + if (!g_extracting) { + OPENFILENAME l={sizeof(l),}; + char buf[1024]; + l.hwndOwner = hwndDlg; + l.lpstrFilter = "ZIP files\0*.zip\0All files\0*.*\0"; + l.lpstrFile = buf; + l.nMaxFile = 1023; + l.lpstrTitle = "Open ZIP file"; + l.lpstrDefExt = "zip"; + l.lpstrInitialDir = NULL; + l.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_PATHMUSTEXIST; + buf[0]=0; + if (GetOpenFileName(&l)) + { + char buf2[1024]; + lstrcpy(buf2,buf); + tempzip_cleanup(hwndDlg,1); + SetDlgItemText(hwndDlg,IDC_ZIPFILE,buf); + char *t=buf+strlen(buf); + while (t > buf && *t != '\\' && *t != '.') t--; + { + char *p=t; + while (p >= buf && *p != '\\') p--; + p++; + *t=0; + SetDlgItemText(hwndDlg,IDC_INSTNAME,p[0]?p:"Stuff"); + } + strcpy(t,".exe"); + SetDlgItemText(hwndDlg,IDC_OUTFILE,buf); + if (tempzip_make(hwndDlg,buf2)) tempzip_cleanup(hwndDlg,1); + else + { + EnableWindow(GetDlgItem(hwndDlg,IDOK),1); + } + } + } + break; + case IDC_BROWSE2: + { + OPENFILENAME l={sizeof(l),}; + char buf[1024]; + l.hwndOwner = hwndDlg; + l.lpstrFilter = "EXE files\0*.exe\0All files\0*.*\0"; + l.lpstrFile = buf; + l.nMaxFile = 1023; + l.lpstrTitle = "Select output EXE file"; + l.lpstrDefExt = "exe"; + l.lpstrInitialDir = NULL; + l.Flags = OFN_HIDEREADONLY|OFN_EXPLORER; + GetDlgItemText(hwndDlg,IDC_OUTFILE,buf,sizeof(buf)); + if (GetSaveFileName(&l)) + { + SetDlgItemText(hwndDlg,IDC_OUTFILE,buf); + } + } + break; + case IDC_BROWSE3: + { + OPENFILENAME l={sizeof(l),}; + char buf[1024]; + l.hwndOwner = hwndDlg; + l.lpstrFilter = "Makensis EXE files (Makensis*.exe)\0Makensis*.exe\0All files\0*.*\0"; + l.lpstrFile = buf; + l.nMaxFile = 1023; + l.lpstrTitle = "Select compiler EXE file"; + l.lpstrDefExt = "exe"; + l.lpstrInitialDir = NULL; + l.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_PATHMUSTEXIST; + GetDlgItemText(hwndDlg,IDC_COMPILER,buf,sizeof(buf)); + if (GetOpenFileName(&l)) + { + SetDlgItemText(hwndDlg,IDC_COMPILER,buf); + } + } + break; + case IDC_BACK: + if (!g_hThread) + { + made=0; + ShowWindow(GetDlgItem(hwndDlg,IDC_BACK),SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_TEST),SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_OUTPUTTEXT),SW_HIDE); + { + int x; + for (x = 0; x < sizeof(ids)/sizeof(ids[0]); x ++) + ShowWindow(GetDlgItem(hwndDlg,ids[x]),SW_SHOWNA); + SetDlgItemText(hwndDlg,IDOK,"Convert"); + EnableWindow(GetDlgItem(hwndDlg,IDOK),1); + } + } + break; + case IDC_TEST: + if (!g_hThread) { + char buf[1024]; + GetDlgItemText(hwndDlg,IDC_OUTFILE,buf,sizeof(buf)); + ShellExecute(hwndDlg,"open",buf,"","",SW_SHOW); + } + break; + case IDOK: + if (!g_hThread) + { + if (!made) + { + GetDlgItemText(hwndDlg,IDC_COMPILER,g_makensis_path,sizeof(g_makensis_path)); + SetDlgItemText(g_hwnd, IDC_OUTPUTTEXT, ""); + int x; + for (x = 0; x < sizeof(ids)/sizeof(ids[0]); x ++) + ShowWindow(GetDlgItem(hwndDlg,ids[x]),SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_OUTPUTTEXT),SW_SHOWNA); + SetDlgItemText(hwndDlg,IDOK,"Close"); + EnableWindow(GetDlgItem(hwndDlg,IDOK),0); + + makeEXE(hwndDlg); + } + else + { + tempzip_cleanup(hwndDlg,0); + EndDialog(hwndDlg,0); + } + } + break; + } + break; + } + return 0; +} \ No newline at end of file diff --git a/Contrib/zip2exe/res.rc b/Contrib/zip2exe/res.rc new file mode 100644 index 00000000..29d38512 --- /dev/null +++ b/Contrib/zip2exe/res.rc @@ -0,0 +1,132 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 361, 234 +STYLE DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Nullsoft ZIP2EXE v0.16" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Open &ZIP",IDC_BROWSE,13,17,49,14 + EDITTEXT IDC_ZIPFILE,66,18,284,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + LISTBOX IDC_ZIPINFO_FILES,13,45,335,56,LBS_NOINTEGRALHEIGHT | + LBS_NOSEL | WS_VSCROLL + EDITTEXT IDC_INSTNAME,81,113,267,12,ES_AUTOHSCROLL + EDITTEXT IDC_DESCTEXT,81,129,267,12,ES_AUTOHSCROLL + COMBOBOX IDC_INSTPATH,81,144,268,126,CBS_DROPDOWN | WS_VSCROLL | + WS_TABSTOP + EDITTEXT IDC_OUTFILE,13,169,292,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_BROWSE2,307,168,41,14 + DEFPUSHBUTTON "Convert",IDOK,304,213,50,14,WS_DISABLED + GROUPBOX "Source ZIP file",IDC_SZIPFRAME,7,7,347,180 + LTEXT "",IDC_ZIPINFO_SUMMARY,13,33,245,8 + GROUPBOX "Output",IDC_OFRAME,7,102,347,85 + LTEXT "Default extract path:",IDC_DEPST,13,145,66,8 + LTEXT "Description text:",IDC_DTEXTST,13,131,66,8 + LTEXT "Output EXE file:",IDC_OEFST,14,157,51,8 + LTEXT "Installer name",IDC_INAMEST,13,116,66,8 + PUSHBUTTON "Test",IDC_TEST,251,213,50,14,NOT WS_VISIBLE + PUSHBUTTON "< Back",IDC_BACK,7,213,50,14,NOT WS_VISIBLE + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,210,347,1 + PUSHBUTTON "Change Compiler",IDC_BROWSE3,7,190,62,14 + EDITTEXT IDC_COMPILER,74,191,280,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + EDITTEXT IDC_OUTPUTTEXT,7,7,347,202,ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | + WS_VSCROLL | WS_HSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 354 + TOPMARGIN, 7 + BOTTOMMARGIN, 227 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Contrib/zip2exe/resource.h b/Contrib/zip2exe/resource.h new file mode 100644 index 00000000..c0c653b5 --- /dev/null +++ b/Contrib/zip2exe/resource.h @@ -0,0 +1,37 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by res.rc +// +#define IDD_DIALOG1 101 +#define IDI_ICON1 102 +#define IDC_ZIPFILE 1000 +#define IDC_BROWSE 1001 +#define IDC_ZIPINFO_SUMMARY 1002 +#define IDC_BROWSE3 1003 +#define IDC_ZIPINFO_FILES 1004 +#define IDC_INSTPATH 1005 +#define IDC_DESCTEXT 1006 +#define IDC_OUTFILE 1007 +#define IDC_BROWSE2 1008 +#define IDC_INSTNAME 1009 +#define IDC_SZIPFRAME 1010 +#define IDC_OFRAME 1011 +#define IDC_INAMEST 1012 +#define IDC_DTEXTST 1013 +#define IDC_DEPST 1014 +#define IDC_OEFST 1015 +#define IDC_OUTPUTTEXT 1016 +#define IDC_TEST 1017 +#define IDC_BACK 1018 +#define IDC_COMPILER 1019 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1020 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Contrib/zip2exe/zip2exe.dsp b/Contrib/zip2exe/zip2exe.dsp new file mode 100644 index 00000000..1bc1b30b --- /dev/null +++ b/Contrib/zip2exe/zip2exe.dsp @@ -0,0 +1,160 @@ +# Microsoft Developer Studio Project File - Name="zip2exe" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=zip2exe - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zip2exe.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zip2exe.mak" CFG="zip2exe - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zip2exe - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "zip2exe - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "zip2exe - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX- /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"../../zip2exe.exe" /opt:nowin98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zip2exe - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "zip2exe - Win32 Release" +# Name "zip2exe - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\zlib\Adler32.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Crc32.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infblock.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infcodes.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Inffast.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Inflate.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Inftrees.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infutil.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Unzip.c +# End Source File +# Begin Source File + +SOURCE=.\zlib\Zutil.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon.ico +# End Source File +# Begin Source File + +SOURCE=.\res.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/Contrib/zip2exe/zip2exe.dsw b/Contrib/zip2exe/zip2exe.dsw new file mode 100644 index 00000000..59a7a925 --- /dev/null +++ b/Contrib/zip2exe/zip2exe.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "zip2exe"=.\zip2exe.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Contrib/zip2exe/zlib/ADLER32.C b/Contrib/zip2exe/zlib/ADLER32.C new file mode 100644 index 00000000..16cf9a70 --- /dev/null +++ b/Contrib/zip2exe/zlib/ADLER32.C @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/Contrib/zip2exe/zlib/CRC32.C b/Contrib/zip2exe/zlib/CRC32.C new file mode 100644 index 00000000..a91101a8 --- /dev/null +++ b/Contrib/zip2exe/zlib/CRC32.C @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/Contrib/zip2exe/zlib/INFBLOCK.C b/Contrib/zip2exe/zlib/INFBLOCK.C new file mode 100644 index 00000000..f4920faa --- /dev/null +++ b/Contrib/zip2exe/zlib/INFBLOCK.C @@ -0,0 +1,398 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + ZFREE(z, s->sub.trees.blens); + r = t; + if (r == Z_DATA_ERROR) + s->mode = BAD; + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + ZFREE(z, s->sub.trees.blens); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + s->mode = BAD; + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/Contrib/zip2exe/zlib/INFBLOCK.H b/Contrib/zip2exe/zlib/INFBLOCK.H new file mode 100644 index 00000000..bd25c807 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFBLOCK.H @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/Contrib/zip2exe/zlib/INFCODES.C b/Contrib/zip2exe/zlib/INFCODES.C new file mode 100644 index 00000000..d4e5ee9a --- /dev/null +++ b/Contrib/zip2exe/zlib/INFCODES.C @@ -0,0 +1,257 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ +#ifndef __TURBOC__ /* Turbo C bug for following expression */ + f = (uInt)(q - s->window) < c->sub.copy.dist ? + s->end - (c->sub.copy.dist - (q - s->window)) : + q - c->sub.copy.dist; +#else + f = q - c->sub.copy.dist; + if ((uInt)(q - s->window) < c->sub.copy.dist) + f = s->end - (c->sub.copy.dist - (uInt)(q - s->window)); +#endif + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/Contrib/zip2exe/zlib/INFCODES.H b/Contrib/zip2exe/zlib/INFCODES.H new file mode 100644 index 00000000..6c750d89 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFCODES.H @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/Contrib/zip2exe/zlib/INFFAST.C b/Contrib/zip2exe/zlib/INFFAST.C new file mode 100644 index 00000000..61a78ee9 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFFAST.C @@ -0,0 +1,170 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + if ((uInt)(q - s->window) >= d) /* offset before dest */ + { /* just copy */ + r = q - d; + *q++ = *r++; c--; /* minimum count is three, */ + *q++ = *r++; c--; /* so unroll loop a little */ + } + else /* else offset after destination */ + { + e = d - (uInt)(q - s->window); /* bytes from offset to end */ + r = s->end - e; /* pointer to offset */ + if (c > e) /* if source crosses, */ + { + c -= e; /* copy to end of window */ + do { + *q++ = *r++; + } while (--e); + r = s->window; /* copy rest from start of window */ + } + } + do { /* copy all or what's left */ + *q++ = *r++; + } while (--c); + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/Contrib/zip2exe/zlib/INFFAST.H b/Contrib/zip2exe/zlib/INFFAST.H new file mode 100644 index 00000000..8facec55 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFFAST.H @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/Contrib/zip2exe/zlib/INFFIXED.H b/Contrib/zip2exe/zlib/INFFIXED.H new file mode 100644 index 00000000..77f7e763 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFFIXED.H @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/Contrib/zip2exe/zlib/INFLATE.C b/Contrib/zip2exe/zlib/INFLATE.C new file mode 100644 index 00000000..32e9b8de --- /dev/null +++ b/Contrib/zip2exe/zlib/INFLATE.C @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/Contrib/zip2exe/zlib/INFTREES.C b/Contrib/zip2exe/zlib/INFTREES.C new file mode 100644 index 00000000..ef1e0b6b --- /dev/null +++ b/Contrib/zip2exe/zlib/INFTREES.C @@ -0,0 +1,455 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + lengths), or Z_MEM_ERROR if not enough memory. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_MEM_ERROR; /* not enough memory */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/Contrib/zip2exe/zlib/INFTREES.H b/Contrib/zip2exe/zlib/INFTREES.H new file mode 100644 index 00000000..85853e09 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFTREES.H @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/Contrib/zip2exe/zlib/INFUTIL.C b/Contrib/zip2exe/zlib/INFUTIL.C new file mode 100644 index 00000000..824dab57 --- /dev/null +++ b/Contrib/zip2exe/zlib/INFUTIL.C @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/Contrib/zip2exe/zlib/INFUTIL.H b/Contrib/zip2exe/zlib/INFUTIL.H new file mode 100644 index 00000000..99d1135d --- /dev/null +++ b/Contrib/zip2exe/zlib/INFUTIL.H @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/Contrib/zip2exe/zlib/UNZIP.H b/Contrib/zip2exe/zlib/UNZIP.H new file mode 100644 index 00000000..76692cb7 --- /dev/null +++ b/Contrib/zip2exe/zlib/UNZIP.H @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/Contrib/zip2exe/zlib/Unzip.c b/Contrib/zip2exe/zlib/Unzip.c new file mode 100644 index 00000000..dab22d71 --- /dev/null +++ b/Contrib/zip2exe/zlib/Unzip.c @@ -0,0 +1,1295 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ +#include + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (GlobalAlloc(GMEM_FIXED,size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) GlobalFree(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char unz_copyright[] = + " unzip 0.15 Copyright 1998 Gilles Vollant "; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + FILE* file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + FILE* file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ +} unz_s; + + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte(fin,pi) + FILE *fin; + int *pi; +{ + unsigned char c; + int err = fread(&c, 1, 1, fin); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ferror(fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir(fin) + FILE *fin; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (fseek(fin,0,SEEK_END) != 0) + return 0; + + + uSizeFile = ftell( fin ); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (fseek(fin,uReadPos,SEEK_SET)!=0) + break; + + if (fread(buf,(uInt)uReadSize,1,fin)!=1) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer + "zlib/zlib109.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen (path) + const char *path; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + FILE * fin ; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + fin=fopen(path,"rb"); + if (fin==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(fin); + if (central_pos==0) + err=UNZ_ERRNO; + + if (fseek(fin,central_pos,SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(fin,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + fclose(s->file); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + return err; +} + + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek(s->file,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + Store = s->cur_file_info.compression_method==0; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file=s->file; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if (!Store) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (len>pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, + pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if (pfile_in_zip_read_info->compression_method==0) + { + uInt uDoCopy,i ; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} diff --git a/Contrib/zip2exe/zlib/ZCONF.H b/Contrib/zip2exe/zlib/ZCONF.H new file mode 100644 index 00000000..6d450fc7 --- /dev/null +++ b/Contrib/zip2exe/zlib/ZCONF.H @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/Contrib/zip2exe/zlib/ZLIB.H b/Contrib/zip2exe/zlib/ZLIB.H new file mode 100644 index 00000000..49f56b43 --- /dev/null +++ b/Contrib/zip2exe/zlib/ZLIB.H @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.3" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/Contrib/zip2exe/zlib/ZUTIL.H b/Contrib/zip2exe/zlib/ZUTIL.H new file mode 100644 index 00000000..6f2cb97c --- /dev/null +++ b/Contrib/zip2exe/zlib/ZUTIL.H @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/Contrib/zip2exe/zlib/Zutil.c b/Contrib/zip2exe/zlib/Zutil.c new file mode 100644 index 00000000..b805a548 --- /dev/null +++ b/Contrib/zip2exe/zlib/Zutil.c @@ -0,0 +1,226 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ +#include + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)GlobalAlloc(GPTR,items*size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + if (ptr) GlobalFree(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Examples/WinMessages.NSH b/Examples/WinMessages.NSH new file mode 100644 index 00000000..0c5d3766 --- /dev/null +++ b/Examples/WinMessages.NSH @@ -0,0 +1,164 @@ +; KiCHiK put together this list of WM_ messages. + +!define WM_NULL 0x0 +!define WM_CREATE 0x1 +!define WM_DESTROY 0x2 +!define WM_MOVE 0x3 +!define WM_SIZE 0x5 +!define WM_SETFOCUS 0x7 +!define WM_KILLFOCUS 0x8 +!define WM_ENABLE 0xA +!define WM_SETREDRAW 0xB +!define WM_SETTEXT 0xC +!define WM_GETTEXT 0xD +!define WM_GETTEXTLENGTH 0xE +!define WM_PAINT 0xF +!define WM_CLOSE 0x10 +!define WM_QUERYENDSESSION 0x11 +!define WM_QUIT 0x12 +!define WM_QUERYOPEN 0x13 +!define WM_ERASEBKGND 0x14 +!define WM_SYSCOLORCHANGE 0x15 +!define WM_ENDSESSION 0x16 +!define WM_SHOWWINDOW 0x18 +!define WM_WININICHANGE 0x1A +!define WM_DEVMODECHANGE 0x1B +!define WM_ACTIVATEAPP 0x1C +!define WM_FONTCHANGE 0x1D +!define WM_TIMECHANGE 0x1E +!define WM_CANCELMODE 0x1F +!define WM_SETCURSOR 0x20 +!define WM_MOUSEACTIVATE 0x21 +!define WM_CHILDACTIVATE 0x22 +!define WM_QUEUESYNC 0x23 +!define WM_GETMINMAXINFO 0x24 +!define WM_PAINTICON 0x26 +!define WM_ICONERASEBKGND 0x27 +!define WM_NEXTDLGCTL 0x28 +!define WM_SPOOLERSTATUS 0x2A +!define WM_DRAWITEM 0x2B +!define WM_MEASUREITEM 0x2C +!define WM_DELETEITEM 0x2D +!define WM_VKEYTOITEM 0x2E +!define WM_CHARTOITEM 0x2F +!define WM_SETFONT 0x30 +!define WM_GETFONT 0x31 +!define WM_SETHOTKEY 0x32 +!define WM_GETHOTKEY 0x33 +!define WM_QUERYDRAGICON 0x37 +!define WM_COMPAREITEM 0x39 +!define WM_COMPACTING 0x41 +!define WM_WINDOWPOSCHANGING 0x46 +!define WM_WINDOWPOSCHANGED 0x47 +!define WM_POWER 0x48 +!define WM_COPYDATA 0x4A +!define WM_CANCELJOURNAL 0x4B +!define WM_NCCREATE 0x81 +!define WM_NCDESTROY 0x82 +!define WM_NCCALCSIZE 0x83 +!define WM_NCHITTEST 0x84 +!define WM_NCPAINT 0x85 +!define WM_NCACTIVATE 0x86 +!define WM_GETDLGCODE 0x87 +!define WM_NCMOUSEMOVE 0xA0 +!define WM_NCLBUTTONDOWN 0xA1 +!define WM_NCLBUTTONUP 0xA2 +!define WM_NCLBUTTONDBLCLK 0xA3 +!define WM_NCRBUTTONDOWN 0xA4 +!define WM_NCRBUTTONUP 0xA5 +!define WM_NCRBUTTONDBLCLK 0xA6 +!define WM_NCMBUTTONDOWN 0xA7 +!define WM_NCMBUTTONUP 0xA8 +!define WM_NCMBUTTONDBLCLK 0xA9 +!define WM_KEYFIRST 0x100 +!define WM_KEYDOWN 0x100 +!define WM_KEYUP 0x101 +!define WM_CHAR 0x102 +!define WM_DEADCHAR 0x103 +!define WM_SYSKEYDOWN 0x104 +!define WM_SYSKEYUP 0x105 +!define WM_SYSCHAR 0x106 +!define WM_SYSDEADCHAR 0x107 +!define WM_KEYLAST 0x108 +!define WM_INITDIALOG 0x110 +!define WM_COMMAND 0x111 +!define WM_SYSCOMMAND 0x112 +!define WM_TIMER 0x113 +!define WM_HSCROLL 0x114 +!define WM_VSCROLL 0x115 +!define WM_INITMENU 0x116 +!define WM_INITMENUPOPUP 0x117 +!define WM_MENUSELECT 0x11F +!define WM_MENUCHAR 0x120 +!define WM_ENTERIDLE 0x121 +!define WM_CTLCOLORMSGBOX 0x132 +!define WM_CTLCOLOREDIT 0x133 +!define WM_CTLCOLORLISTBOX 0x134 +!define WM_CTLCOLORBTN 0x135 +!define WM_CTLCOLORDLG 0x136 +!define WM_CTLCOLORSCROLLBAR 0x137 +!define WM_CTLCOLORSTATIC 0x138 +!define WM_MOUSEFIRST 0x200 +!define WM_MOUSEMOVE 0x200 +!define WM_LBUTTONDOWN 0x201 +!define WM_LBUTTONUP 0x202 +!define WM_LBUTTONDBLCLK 0x203 +!define WM_RBUTTONDOWN 0x204 +!define WM_RBUTTONUP 0x205 +!define WM_RBUTTONDBLCLK 0x206 +!define WM_MBUTTONDOWN 0x207 +!define WM_MBUTTONUP 0x208 +!define WM_MBUTTONDBLCLK 0x209 +!define WM_MOUSELAST 0x209 +!define WM_PARENTNOTIFY 0x210 +!define WM_ENTERMENULOOP 0x211 +!define WM_EXITMENULOOP 0x212 +!define WM_MDICREATE 0x220 +!define WM_MDIDESTROY 0x221 +!define WM_MDIACTIVATE 0x222 +!define WM_MDIRESTORE 0x223 +!define WM_MDINEXT 0x224 +!define WM_MDIMAXIMIZE 0x225 +!define WM_MDITILE 0x226 +!define WM_MDICASCADE 0x227 +!define WM_MDIICONARRANGE 0x228 +!define WM_MDIGETACTIVE 0x229 +!define WM_MDISETMENU 0x230 +!define WM_DROPFILES 0x233 +!define WM_MDIREFRESHMENU 0x234 +!define WM_CUT 0x300 +!define WM_COPY 0x301 +!define WM_PASTE 0x302 +!define WM_CLEAR 0x303 +!define WM_UNDO 0x304 +!define WM_RENDERFORMAT 0x305 +!define WM_RENDERALLFORMATS 0x306 +!define WM_DESTROYCLIPBOARD 0x307 +!define WM_DRAWCLIPBOARD 0x308 +!define WM_PAINTCLIPBOARD 0x309 +!define WM_VSCROLLCLIPBOARD 0x30A +!define WM_SIZECLIPBOARD 0x30B +!define WM_ASKCBFORMATNAME 0x30C +!define WM_CHANGECBCHAIN 0x30D +!define WM_HSCROLLCLIPBOARD 0x30E +!define WM_QUERYNEWPALETTE 0x30F +!define WM_PALETTEISCHANGING 0x310 +!define WM_PALETTECHANGED 0x311 +!define WM_HOTKEY 0x312 +!define WM_PENWINFIRST 0x380 +!define WM_PENWINLAST 0x38F +!define WM_USER 0x400 +!define WM_DDE_FIRST 0x3E0 +!define WM_CONVERTREQUESTEX 0x108 +!define WM_IME_STARTCOMPOSITION 0x10D +!define WM_IME_ENDCOMPOSITION 0x10E +!define WM_IME_COMPOSITION 0x10F +!define WM_IME_KEYLAST 0x10F +!define WM_IME_SETCONTEXT 0x281 +!define WM_IME_NOTIFY 0x282 +!define WM_IME_CONTROL 0x283 +!define WM_IME_COMPOSITIONFULL 0x284 +!define WM_IME_SELECT 0x285 +!define WM_IME_CHAR 0x286 +!define WM_IME_KEYDOWN 0x290 +!define WM_IME_KEYUP 0x291 diff --git a/Examples/bigtest.nsi b/Examples/bigtest.nsi new file mode 100644 index 00000000..52ff0896 --- /dev/null +++ b/Examples/bigtest.nsi @@ -0,0 +1,239 @@ +; bigtest.nsi +; +; This script attempts to test most of the functionality of NSIS. +; +!ifdef HAVE_UPX +!packhdr tmp.dat "upx\upx -9 tmp.dat" +!endif + +!ifdef NOCOMPRESS +SetCompress off +!endif + +SetDateSave on +SetDatablockOptimize on +CRCCheck on +SilentInstall normal +BGGradient 000000 800000 FFFFFF +InstallColors FF8080 000030 + + +Name "BigNSISTest" +Caption "NSIS Big Test" +Icon "..\contrib\Icons\normal-install.ico" +OutFile "bigtest.exe" + +LicenseText "make sure this license text is all there (it's about 28k last I checked). The last line is a simple '}'." +LicenseData "..\source\exehead\main.c" + +InstallDir "$PROGRAMFILES\NSISCrap\BigNSISTest" +InstallDirRegKey HKLM SOFTWARE\NSISCrap\BigNSISTest "Install_Dir" +DirText "Choose a directory to install in to:" + +; uninstall stuff +UninstallText "This will uninstall example2. Hit next to continue." +UninstallIcon "..\contrib\Icons\normal-uninstall.ico" + +ComponentText "This will install the test on your computer. Select which optional things you want installed." +CheckBitmap ..\contrib\Icons\checksX.bmp +!ifndef NOINSTTYPES ; only if not defined +InstType "Most" +InstType "Full" +InstType "More" +InstType "Base" +;InstType /NOCUSTOM +;InstType /COMPONENTSONLYONCUSTOM +!endif + +AutoCloseWindow false +ShowInstDetails show + + +Section "" ; empty string makes it hidden, so would starting with - +; write reg crap +StrCpy $1 "POOOOOOOOOOOP" +DetailPrint "I like to f*ck sheep $1" +WriteRegStr HKLM SOFTWARE\NSISCrap\BigNSISTest "Install_Dir" "$INSTDIR" +; write uninstall strings +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\BigNSISTest" "DisplayName" "BigNSISTest (remove only)" +WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\BigNSISTest" "UninstallString" '"$INSTDIR\bt-uninst.exe"' +#File /oname=poop.exe makensisw.exe + +SetOutPath $INSTDIR +File /a "..\source\exehead\bin2h.exe" +CreateDirectory "$INSTDIR\shiz\crap" ; 2 recursively create a directory for fun. +WriteUninstaller "bt-uninst.exe" +Nop ; for fun +SectionEnd + + +Section "TempTest" +SectionIn 1 2 3 + Start: MessageBox MB_OK "Start:" + + MessageBox MB_YESNO "Goto Poop" IDYES Poop + + MessageBox MB_OK "Right before Poop:" + + Poop: MessageBox MB_OK "Poop:" + + MessageBox MB_OK "Right after Poop:" + + MessageBox MB_YESNO "Goto Start:?" IDYES Start + +SectionEnd + + +Function poopTest +ReadINIStr $1 "$INSTDIR\test.ini" "MySectionShit" "Value1" +StrCmp $1 $8 NoFailedMsg + MessageBox MB_OK "WriteINIStr failed" +NoFailedMsg: FunctionEnd + + +SubSection /e SubSection1 +Section "Test Registry/INI functions" +SectionIn 1 4 3 +WriteRegStr HKLM SOFTWARE\NSISCrap\BigNSISTest "StrTest_INSTDIR" "$INSTDIR" +WriteRegDword HKLM SOFTWARE\NSISCrap\BigNSISTest "DwordTest_0xDEADBEEF" 0xdeadbeef +WriteRegDword HKLM SOFTWARE\NSISCrap\BigNSISTest "DwordTest_123456" 123456 +WriteRegDword HKLM SOFTWARE\NSISCrap\BigNSISTest "DwordTest_0123" 0123 +WriteRegBin HKLM SOFTWARE\NSISCrap\BigNSISTest "BinTest_deadbeef01f00dbeef" "DEADBEEF01F00DBEEF" +StrCpy $8 "$SYSDIR\Poop" +WriteINIStr "$INSTDIR\test.ini" "MySection" "Value1" $8 +WriteINIStr "$INSTDIR\test.ini" "MySectionShit" "Value1" $8 +WriteINIStr "$INSTDIR\test.ini" "MySectionShit" "Value2" $8 +WriteINIStr "$INSTDIR\test.ini" "POOPon" "Value1" $8 +Call poopTest + +DeleteINIStr "$INSTDIR\test.ini" "POOPon" "Value1" +DeleteINISec "$INSTDIR\test.ini" "MySectionShit" + +ReadINIStr $1 "$INSTDIR\test.ini" "MySectionShit" "Value1" +StrCmp $1 "" INIDelSuccess + MessageBox MB_OK "DeleteINISec failed" +INIDelSuccess: + +ClearErrors +ReadRegStr $1 HKCR "software\microsoft" shit +IfErrors 0 NoError + MessageBox MB_OK "could not read from HKCR\software\microsoft\shit" + Goto ErrorYay +NoError: + MessageBox MB_OK "read '$1' from HKCR\software\microsoft\shit" +ErrorYay: +SectionEnd + + +Function "CSCTest" +CreateDirectory "$SMPROGRAMS\Big NSIS Test" +SetOutPath $INSTDIR ; for working directory +CreateShortCut "$SMPROGRAMS\Big NSIS Test\Uninstall BIG NSIS Test.lnk" "$INSTDIR\bt-uninst.exe" ; use defaults for parameters, icon, etc. +; this one will use notepad's icon, start it minimized, and give it a hotkey (of Ctrl+Shift+Q) +CreateShortCut "$SMPROGRAMS\Big NSIS Test\bin2h.exe.lnk" "$INSTDIR\bin2h.exe" "" "$WINDIR\notepad.exe" 0 SW_SHOWMINIMIZED CONTROL|SHIFT|Q +CreateShortCut "$SMPROGRAMS\Big NSIS Test\TheDir.lnk" "$INSTDIR\" "" "" 0 SW_SHOWMAXIMIZED CONTROL|SHIFT|Z +FunctionEnd + + +Section "Test CreateShortCut" +SectionIn 1 2 3 +Call CSCTest +SectionEnd +SubSection Sub2 + +Function myfunc +StrCpy $2 "poop=$1" +MessageBox MB_OK "myfunc: $2" +FunctionEnd + +Section "Test Branching" +BeginTestSection: +SectionIn 1 2 3 +SetOutPath $INSTDIR +IfFileExists "$INSTDIR\bin2h.c" 0 BranchTest69 + MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to overwrite $INSTDIR\bin2h.c?" IDNO NoOverwrite ; skipped if file doesn't exist +BranchTest69: + SetOverwrite ifnewer ; NOT AN INSTRUCTION, NOT COUNTED IN SKIPPINGS +NoOverwrite: +File "..\source\exehead\bin2h.c" ; skipped if answered no +SetOverwrite try ; NOT AN INSTRUCTION, NOT COUNTED IN SKIPPINGS +MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to skip the rest of this section?" IDYES EndTestBranch +MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to go back to the beginning of this section?" IDYES BeginTestSection +MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to hide the installer and wait five seconds?" IDNO NoHide +HideWindow +Sleep 5000 +BringToFront +NoHide: +MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to call the function 5 times?" IDNO NoRecurse +StrCpy $1 "x" +LoopPoop: + Call myfunc + StrCpy $1 "x$1" + StrCmp $1 "xxxxxx" 0 LoopPoop +NoRecurse: + +EndTestBranch: + +SectionEnd + +SubSectionEnd + +Section "Test CopyFiles" +SectionIn 1 2 3 +SetOutPath $INSTDIR\cpdest +CopyFiles "$WINDIR\*.ini" "$INSTDIR\cpdest" 0 +SectionEnd + +SubSectionEnd +Section "Test Exec functions" CRAPIDX +SectionIn 1 2 3 +SearchPath $1 notepad.exe +MessageBox MB_OK "notepad.exe=$1" +Exec '"$1"' +ExecShell "open" '"$INSTDIR"' +Sleep 500 +BringToFront +SectionEnd + +Section "Test ActiveX control registration" +SectionIn 2 +UnRegDLL "$SYSDIR\spin32.ocx" +Sleep 1000 +RegDLL "$SYSDIR\spin32.ocx" +Sleep 1000 +SectionEnd + +; special uninstall section. +Section "Uninstall" +DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\BigNSISTest" +DeleteRegKey HKLM "SOFTWARE\NSISCrap\BigNSISTest" +Delete "$INSTDIR\bin2h.exe" +Delete "$INSTDIR\bin2h.c" +Delete "$INSTDIR\bt-uninst.exe" +Delete "$INSTDIR\test.ini" +Delete "$SMPROGRAMS\Big NSIS Test\*.*" +RMDir "$SMPROGRAMS\BiG NSIS Test" +MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to remove the directory $INSTDIR\cpdest?" IDNO NoDelete +Delete "$INSTDIR\cpdest\*.*" +RMDir "$INSTDIR\cpdest" ; skipped if no +NoDelete: +RMDir "$INSTDIR\shiz\crap" +RMDir "$INSTDIR\shiz" +RMDir "$INSTDIR" +IfFileExists "$INSTDIR" 0 NoErrorMsg +MessageBox MB_OK "Note: $INSTDIR could not be removed!" IDOK 0 ; skipped if file doesn't exist +NoErrorMsg: +SectionEnd + +; eof + +Function .onSelChange + SectionGetText ${CRAPIDX} $0 + StrCmp $0 "" e + SectionSetText ${CRAPIDX} "" + Goto e2 +e: + SectionSetText ${CRAPIDX} "Doop" +e2: + +FunctionEnd diff --git a/Examples/branding.nsh b/Examples/branding.nsh new file mode 100644 index 00000000..7174602e --- /dev/null +++ b/Examples/branding.nsh @@ -0,0 +1,104 @@ +; Written by Amir Szekely 24th July 2002 +; Please see gfx.nsi for example of usage + +!verbose 3 + +; If we haven't included this as install macros yet +!ifndef BI_MACROS_USED +; If this isn't supposed to be uninstall macros +!ifndef BI_UNINSTALL +!define BI_MACROS_USED +; Undefine BI_FUNC if already defined by uninstaller macros +!ifdef BI_FUNC +!undef BI_FUNC +!endif +; Define BI_FUNC +!define BI_FUNC "BIChange" +; If BI_VAR or BI_TEMPFILE was already defined undefine it so BI_INIT can redefine it +!ifdef BI_VAR +!undef BI_VAR +!endif +!ifdef BI_TEMPFILE +!undef BI_TEMPFILE +!endif +; If macros aren't defined yet, define them +!ifndef UBI_MACROS_USED +!define BI_OK +!endif +; Done +!endif +!endif + +; If we haven't included this as uninstall macros yet +!ifndef UBI_MACROS_USED +; If this is supposed to be uninstall macros +!ifdef BI_UNINSTALL +!define UBI_MACROS_USED +; Undefine BI_FUNC if already defined by installer macros +!ifdef BI_FUNC +!undef BI_FUNC +!endif +; Define BI_FUNC +!define BI_FUNC "un.BIChange" +; If BI_VAR or BI_TEMPFILE was already defined undefine it so BI_INIT can redefine it +!ifdef BI_VAR +!undef BI_VAR +!endif +!ifdef BI_TEMPFILE +!undef BI_TEMPFILE +!endif +; If macros aren't defined yet, define them +!ifndef BI_MACROS_USED +!define BI_OK +!endif +; Done +!endif +!endif + +!ifdef BI_OK + +!macro BI_INIT VAR +!define BI_VAR ${VAR} +StrCpy ${BI_VAR} 0 +!macroend + +!macro BI_NEXT +IntOp ${BI_VAR} ${BI_VAR} + 1 +Call ${BI_FUNC} +!macroend + +!macro BI_PREV +IntOp ${BI_VAR} ${BI_VAR} - 1 +Call ${BI_FUNC} +!macroend + +!macro BI_LIST +Function ${BI_FUNC} +Push $0 +Push $1 +StrCpy $0 0 +GetTempFileName $1 +!macroend + +!macro BI_LIST_ADD IMAGE PARMS +IntOp $0 $0 + 1 +StrCmp ${BI_VAR} $0 0 +4 + File /oname=$1 "${IMAGE}" + SetBrandingImage ${PARMS} $1 + Goto BI_done +!macroend + +!macro BI_LIST_END +BI_done: + Delete $1 + Pop $1 + Pop $0 +FunctionEnd +!macroend + +!undef BI_OK +!endif ; ifdef BI_OK + +!verbose 4 + +!echo "Branding macros defined successfully!" \ No newline at end of file diff --git a/Examples/example1.nsi b/Examples/example1.nsi new file mode 100644 index 00000000..476248ca --- /dev/null +++ b/Examples/example1.nsi @@ -0,0 +1,29 @@ +; example1.nsi +; +; This script is perhaps one of the simplest NSIs you can make. All of the +; optional settings are left to their default settings. The instalelr simply +; prompts the user asking them where to install, and drops of makensisw.exe +; there. +; + +; The name of the installer +Name "Example1" + +; The file to write +OutFile "example1.exe" + +; The default installation directory +InstallDir $PROGRAMFILES\Example1 + +; The text to prompt the user to enter a directory +DirText "This will install the very simple example1 on your computer. Choose a directory" + +; The stuff to install +Section "ThisNameIsIgnoredSoWhyBother?" + ; Set output path to the installation directory. + SetOutPath $INSTDIR + ; Put file there + File ..\makensisw.exe +SectionEnd ; end the section + +; eof diff --git a/Examples/example2.nsi b/Examples/example2.nsi new file mode 100644 index 00000000..f2d2950e --- /dev/null +++ b/Examples/example2.nsi @@ -0,0 +1,67 @@ +; example2.nsi +; +; This script is based on example1.nsi, but adds uninstall support +; and (optionally) start menu shortcuts. +; +; It will install notepad.exe into a directory that the user selects, +; + +; The name of the installer +Name "Example2" + +; The file to write +OutFile "example2.exe" + +; The default installation directory +InstallDir $PROGRAMFILES\Example2 +; Registry key to check for directory (so if you install again, it will +; overwrite the old one automatically) +InstallDirRegKey HKLM SOFTWARE\NSIS_Example2 "Install_Dir" + +; The text to prompt the user to enter a directory +ComponentText "This will install the less simple example2 on your computer. Select which optional things you want installed." +; The text to prompt the user to enter a directory +DirText "Choose a directory to install in to:" + +; The stuff to install +Section "Example2 (required)" + ; Set output path to the installation directory. + SetOutPath $INSTDIR + ; Put file there + File "..\makensisw.exe" + ; Write the installation path into the registry + WriteRegStr HKLM SOFTWARE\NSIS_Example2 "Install_Dir" "$INSTDIR" + ; Write the uninstall keys for Windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Example2" "DisplayName" "NSIS Example2 (remove only)" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Example2" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteUninstaller "uninstall.exe" +SectionEnd + +; optional section +Section "Start Menu Shortcuts" + CreateDirectory "$SMPROGRAMS\Example2" + CreateShortCut "$SMPROGRAMS\Example2\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\Example2\Example2 (notepad).lnk" "$INSTDIR\notepad.exe" "" "$INSTDIR\makensisw.exe" 0 +SectionEnd + +; uninstall stuff + +UninstallText "This will uninstall example2. Hit next to continue." + +; special uninstall section. +Section "Uninstall" + ; remove registry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Example2" + DeleteRegKey HKLM SOFTWARE\NSIS_Example2 + ; remove files + Delete $INSTDIR\makensisw.exe + ; MUST REMOVE UNINSTALLER, too + Delete $INSTDIR\uninstall.exe + ; remove shortcuts, if any. + Delete "$SMPROGRAMS\Example2\*.*" + ; remove directories used. + RMDir "$SMPROGRAMS\Example2" + RMDir "$INSTDIR" +SectionEnd + +; eof diff --git a/Examples/functions.htm b/Examples/functions.htm new file mode 100644 index 00000000..69560840 --- /dev/null +++ b/Examples/functions.htm @@ -0,0 +1,614 @@ +NSIS utility functions + +

NSIS utility functions

+

Contents:

+ + +
+General utility:
+;------------------------------------------------------------------------------
+; GetParent
+; input, top of stack  (i.e. C:\Program Files\Poop)
+; output, top of stack (replaces, with i.e. C:\Program Files)
+; modifies no other variables.
+;
+; Usage:
+;   Push "C:\Program Files\Directory\Whatever"
+;   Call GetParent
+;   Pop $0
+;   ; at this point $0 will equal "C:\Program Files\Directory"
+
+
+Function GetParent 
+  Exch $0 ; old $0 is on top of stack
+  Push $1
+  Push $2
+  StrCpy $1 -1
+  loop:
+    StrCpy $2 $0 1 $1
+    StrCmp $2 "" exit
+    StrCmp $2 "\" exit
+    IntOp $1 $1 - 1
+  Goto loop
+  exit:
+    StrCpy $0 $0 $1
+    Pop $2
+    Pop $1
+    Exch $0 ; put $0 on top of stack, restore $0 to original value
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; TrimNewlines
+; input, top of stack  (i.e. whatever$\r$\n)
+; output, top of stack (replaces, with i.e. whatever)
+; modifies no other variables.
+;
+Function TrimNewlines
+  Exch $0
+  Push $1
+  Push $2
+    StrCpy $1 0
+    loop:
+      IntOp $1 $1 - 1
+      StrCpy $2 $0 1 $1
+      StrCmp $2 "$\r" loop
+      StrCmp $2 "$\n" loop
+  IntOp $1 $1 + 1
+    
+  StrCpy $0 $0 $1
+  Pop $2
+  Pop $1
+  Exch $0
+FunctionEnd
+
+
+
+;------------------------------------------------------------------------------
+; GetParameters
+; input, none
+; output, top of stack (replaces, with i.e. whatever)
+; modifies no other variables.
+
+Function GetParameters
+  Push $0
+  Push $1
+  Push $2
+  StrCpy $0 $CMDLINE 1
+  StrCpy $1 '"'
+  StrCpy $2 1
+  StrCmp $0 '"' loop
+    StrCpy $1 ' ' ; we're scanning for a space instead of a quote
+  loop:
+    StrCpy $0 $CMDLINE 1 $2
+    StrCmp $0 $1 loop2
+    StrCmp $0 "" loop2
+    IntOp $2 $2 + 1
+    Goto loop
+  loop2:
+    IntOp $2 $2 + 1
+    StrCpy $0 $CMDLINE 1 $2
+    StrCmp $0 " " loop2
+  StrCpy $0 $CMDLINE "" $2
+  Pop $2
+  Pop $1
+  Exch $0
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; StrStr
+; input, top of stack = string to search for
+;        top of stack-1 = string to search in
+; output, top of stack (replaces with the portion of the string remaining)
+; modifies no other variables.
+;
+; Usage:
+;   Push "this is a long ass string"
+;   Push "ass"
+;   Call StrStr
+;   Pop $0
+;  ($0 at this point is "ass string")
+
+Function StrStr
+  Exch $1 ; st=haystack,old$1, $1=needle
+  Exch    ; st=old$1,haystack
+  Exch $2 ; st=old$1,old$2, $2=haystack
+  Push $3
+  Push $4
+  Push $5
+  StrLen $3 $1
+  StrCpy $4 0
+  ; $1=needle
+  ; $2=haystack
+  ; $3=len(needle)
+  ; $4=cnt
+  ; $5=tmp
+  loop:
+    StrCpy $5 $2 $3 $4
+    StrCmp $5 $1 done
+    StrCmp $5 "" done
+    IntOp $4 $4 + 1
+    Goto loop
+  done:
+  StrCpy $1 $2 "" $4
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Exch $1
+FunctionEnd
+
+
+
+
System version checking:
+;------------------------------------------------------------------------------
+; GetWindowsVersion
+;
+; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/
+; Returns on top of stack
+;
+; Windows Version (95, 98, ME, NT x.x, 2000)
+; or
+; '' (Unknown Windows Version)
+;
+; Usage:
+;   Call GetWindowsVersion
+;   Pop $0
+;   ; at this point $0 is "NT 4.0" or whatnot
+
+Function GetWindowsVersion
+  Push $0
+  Push $9
+  ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
+  StrCmp $0 "" 0 lbl_winnt
+  ; we are not NT.
+  ReadRegStr $0 HKLM SOFTWARE\Microsoft\Windows\CurrentVersion VersionNumber
+ 
+  StrCpy $9 $0 1
+  StrCmp $9 '4' 0 lbl_error
+
+  StrCpy $9 $0 3
+
+  StrCmp $9 '4.0' lbl_win32_95
+  StrCmp $9 '4.9' lbl_win32_ME lbl_win32_98
+
+  lbl_win32_95:
+    StrCpy $0 '95'
+  Goto lbl_done
+
+  lbl_win32_98:
+    StrCpy $0 '98'
+  Goto lbl_done
+
+  lbl_win32_ME:
+    StrCpy $0 'ME'
+  Goto lbl_done
+
+  lbl_winnt: 
+
+    StrCpy $9 $0 1
+    StrCmp $9 '3' lbl_winnt_x
+    StrCmp $9 '4' lbl_winnt_x
+    StrCmp $9 '5' lbl_winnt_5 lbl_error
+
+    lbl_winnt_x:
+      StrCpy $0 "NT $0" 6
+    Goto lbl_done
+
+    lbl_winnt_5:
+      Strcpy $0 '2000'
+    Goto lbl_done
+
+  lbl_error:
+    Strcpy $0 ''
+  lbl_done:
+  Pop $9
+  Exch $0
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; GetIEVersion
+;
+; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/
+; Returns on top of stack
+; 1-6 (Installed IE Version)
+; or 
+; '' (IE is not installed)
+;
+; Usage:
+;   Call GetIEVersion
+;   Pop $0
+;   ; at this point $0 is "5" or whatnot
+
+Function GetIEVersion
+  Push $0
+  ClearErrors
+  ReadRegStr $0 HKLM "Software\Microsoft\Internet Explorer" "Version"
+  IfErrors lbl_123 lbl_456
+
+  lbl_456: ; ie 4+
+    Strcpy $0 $0 1
+  Goto lbl_done
+
+  lbl_123: ; older ie version
+    ClearErrors
+    ReadRegStr $0 HKLM "Software\Microsoft\Internet Explorer" "IVer"
+    IfErrors lbl_error
+
+      StrCpy $0 $0 3
+      StrCmp $0 '100' lbl_ie1
+      StrCmp $0 '101' lbl_ie2
+      StrCmp $0 '102' lbl_ie2
+
+      StrCpy $0 '3' ; default to ie3 if not 100, 101, or 102.
+      Goto lbl_done
+        lbl_ie1: 
+          StrCpy $0 '1'
+        Goto lbl_done
+        lbl_ie2:
+          StrCpy $0 '2'
+        Goto lbl_done
+    lbl_error:
+      StrCpy $0 ''
+  lbl_done:
+  Exch $0
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; IsFlashInstalled
+;
+; By Yazno, http://yazno.tripod.com/powerpimpit/
+; Returns on top of stack
+; 0 (Flash is not installed)
+; or
+; 1 (Flash is installed)
+;
+; Usage:
+;   Call IsFlashInstalled
+;   Pop $0
+;   ; $0 at this point is "1" or "0"
+
+Function IsFlashInstalled
+ Push $0
+ ClearErrors
+ ReadRegStr $0 HKCR "CLSID\{D27CDB6E-AE6D-11cf-96B8-444553540000}" ""
+ IfErrors lbl_na 
+   StrCpy $0 1
+ Goto lbl_end
+ lbl_na:
+   StrCpy $0 0
+ lbl_end:
+ Exch $0
+FunctionEnd
+
+
+
+
+
Shared DLL functions: +
;------------------------------------------------------------------------------
+; un.RemoveSharedDLL
+;
+; Decrements a shared DLLs reference count, and removes if necessary.
+; Use by passing one item on the stack (the full path of the DLL).
+; Note: for use in the main installer (not the uninstaller), rename the
+; function to RemoveSharedDLL.
+; 
+; Usage:
+;   Push $SYSDIR\myDll.dll
+;   Call un.RemoveShareDLL
+;
+
+Function un.RemoveSharedDLL
+  Exch $9
+  Push $0
+  ReadRegDword $0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $9
+  StrCmp $0 "" remove
+    IntOp $0 $0 - 1
+    IntCmp $0 0 rk rk uk
+    rk:
+      DeleteRegValue HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $9
+    goto Remove
+    uk:
+      WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $9 $0
+    Goto noremove
+  remove:
+    Delete /REBOOTOK $9
+  noremove:
+  Pop $0
+  Pop $9
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; AddSharedDLL
+;
+; Increments a shared DLLs reference count.
+; Use by passing one item on the stack (the full path of the DLL).
+;
+; Usage: 
+;   Push $SYSDIR\myDll.dll
+;   Call AddSharedDLL
+;
+
+Function AddSharedDLL
+  Exch $9
+  Push $0
+  ReadRegDword $0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $9
+  IntOp $0 $0 + 1
+  WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $9 $0
+  Pop $0
+  Pop $9
+FunctionEnd  
+
+
+;------------------------------------------------------------------------------
+; UpgradeDLL (macro)
+;
+; Updates a DLL (or executable) based on version resource information.
+;
+; Input: param = input source file.
+;        top of stack = full path on system to install file to.
+;
+; Output: none (removes full path from stack)
+;
+; Usage:
+;
+;  Push "$SYSDIR\atl.dll"
+;  !insertmacro UpgradeDLL "atl.dll"
+;
+
+!macro UpgradeDLL DLL_NAME
+  Exch $0
+  Push $1
+  Push $2
+  Push $3
+  Push $4
+  ClearErrors
+  GetDLLVersionLocal ${DLL_NAME} $1 $2
+  GetDLLVersion $0 $3 $4
+  IfErrors upgrade_${DLL_NAME}
+    IntCmpU $1 $3 "" noupgrade_${DLL_NAME} upgrade_${DLL_NAME}
+    IntCmpU $2 $4 noupgrade_${DLL_NAME} noupgrade_${DLL_NAME}
+  upgrade_${DLL_NAME}:
+    UnRegDLL $0
+    File /oname=$0 ${DLL_NAME}
+    RegDLL $0
+  noupgrade_${DLL_NAME}:
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Pop $0
+!macroend
+
+
+
+
Winamp functions:
;------------------------------------------------------------------------------
+; GetWinampInstPath
+; 
+; takes no parameters
+; returns with the winamp install directory on the stack (it will be
+; an empty string if winamp is not detected).
+;
+; modifies no other variables
+;
+; Usage:
+;   Call GetWinampInstPath
+;   Pop $0
+;   MessageBox MB_OK "Winamp installed at: $0"
+
+Function GetWinampInstPath
+  Push $0
+  Push $1
+  Push $2
+  ReadRegStr $0 HKLM \
+     "Software\Microsoft\Windows\CurrentVersion\Uninstall\Winamp" \ 
+     "UninstallString"
+  StrCmp $0 "" fin
+
+    StrCpy $1 $0 1 0 ; get firstchar
+    StrCmp $1 '"' "" getparent 
+      ; if first char is ", let's remove "'s first.
+      StrCpy $0 $0 "" 1
+      StrCpy $1 0
+      rqloop:
+        StrCpy $2 $0 1 $1
+        StrCmp $2 '"' rqdone
+        StrCmp $2 "" rqdone
+        IntOp $1 $1 + 1
+        Goto rqloop
+      rqdone:
+      StrCpy $0 $0 $1
+    getparent:
+    ; the uninstall string goes to an EXE, let's get the directory.
+    StrCpy $1 -1
+    gploop:
+      StrCpy $2 $0 1 $1
+      StrCmp $2 "" gpexit
+      StrCmp $2 "\" gpexit
+      IntOp $1 $1 - 1
+      Goto gploop
+    gpexit:
+    StrCpy $0 $0 $1
+
+    StrCmp $0 "" fin
+    IfFileExists $0\winamp.exe fin
+      StrCpy $0 ""
+  fin:
+  Pop $2
+  Pop $1
+  Exch $0
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; GetWinampVisPath
+; 
+; requires $INSTDIR to point to the Winamp directory.
+; sets $OUTDIR with vis plug-in path
+;
+; modifies no other variables
+
+Function GetWinampVisPath 
+  ReadINIStr $OUTDIR $INSTDIR\winamp.ini Winamp VisDir 
+  StrCmp $OUTDIR "" NoINISetting
+    IfFileExists $OUTDIR Good
+  NoINISetting:
+    StrCpy $OUTDIR $INSTDIR\Plugins
+  Good:
+FunctionEnd 
+
+
+;------------------------------------------------------------------------------
+; GetWinampDSPPath
+; 
+; requires $INSTDIR to point to the Winamp directory.
+; sets $OUTDIR with dsp plug-in path
+;
+; modifies no other variables
+
+Function GetWinampDSPPath 
+  ReadINIStr $OUTDIR $INSTDIR\winamp.ini Winamp DSPDir 
+  StrCmp $OUTDIR "" NoINISetting
+    IfFileExists $OUTDIR Good
+  NoINISetting:
+    StrCpy $OUTDIR $INSTDIR\Plugins
+  Good:
+FunctionEnd 
+
+;------------------------------------------------------------------------------
+; GetWinampSkinPath
+; 
+; requires $INSTDIR to point to the Winamp directory.
+; sets $OUTDIR with skin plug-in path
+;
+; modifies no other variables
+
+Function GetWinampSkinPath 
+  ReadINIStr $OUTDIR $INSTDIR\winamp.ini Winamp SkinDir 
+  StrCmp $OUTDIR "" NoINISetting
+    IfFileExists $OUTDIR Good
+  NoINISetting:
+    StrCpy $OUTDIR $INSTDIR\Skins
+  Good:
+FunctionEnd 
+
+;------------------------------------------------------------------------------
+; CloseWinamp
+; 
+; Closes all running instances of Winamp 1.x/2.x
+;
+; modifies no other variables
+Function CloseWinamp
+  Push $0
+  loop:
+    FindWindow $0 "Winamp v1.x"
+    IntCmp $0 0 done
+     SendMessage $0 16 0 0
+     Sleep 100
+     Goto loop
+  done:
+  Pop $0
+FunctionEnd
+
+
+
+
+
Netscape functions:
+;------------------------------------------------------------------------------
+; InstallNetscapePlugin
+;
+; Replace 'mynetscapeplugin.dll' with the name of your DLL to extract.
+;
+; (pretty much untested, but should work)
+;
+; you may want to add is-netscape-running and error checking (if the file isn't writable)
+
+Function InstallNetscapePlugin
+  Push $OUTDIR
+  Push $0
+  Push $1
+  StrCpy $0 0
+  outer_loop:
+    EnumRegKey $1 HKLM "Software\Netscape\Netscape Navigator" $0
+    StrCmp $1 "" abort
+    ReadRegStr $1 HKLM "Software\Netscape\Netscape Navigator\$1\Main" "Plugins Directory"    
+    StrCmp $1 "" abort
+    SetOutPath $1
+    File mynetscapeplugin.dll
+    IntOp $0 $0 + 1
+  Goto outer_loop
+  abort:
+  Pop $1
+  Pop $0
+  Pop $OUTDIR
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; un.RemoveNetscapePlugin
+;
+; input: top of stack = dll name of plugin to remove
+; output: none
+; 
+; Usage:
+;   Push mynetscapepluging.dll
+;   Call un.RemoveNetscapePlugin
+;
+; you may want to add is-netscape-running and error checking (if the delete doesn't work).
+
+
+Function un.RemoveNetscapePlugin
+  Exch $2
+  Push $0
+  Push $1
+  StrCpy $0 0
+  outer_loop:
+    EnumRegKey $1 HKLM "Software\Netscape\Netscape Navigator" $0
+    StrCmp $1 "" abort
+    ReadRegStr $1 HKLM "Software\Netscape\Netscape Navigator\$1\Main" "Plugins Directory"    
+    StrCmp $1 "" abort
+    Delete /REBOOTOK $1\$2
+    IntOp $0 $0 + 1
+  Goto outer_loop
+  abort:
+  Pop $1
+  Pop $0
+  Pop $2
+FunctionEnd
+
+
+
diff --git a/Examples/gfx.nsi b/Examples/gfx.nsi new file mode 100644 index 00000000..aa92f7c4 --- /dev/null +++ b/Examples/gfx.nsi @@ -0,0 +1,86 @@ +; gfx.nsi +; +; This script shows some examples of using all of the new +; graphic related additions made in NSIS 1.99 +; +; Written by Amir Szkeley 22nd July 2002 +; + +Name "Graphical effects" + +OutFile "gfx.exe" + +; Adds an XP manifest to the installer +XPStyle on + +; Add branding image to the installer (an image on the side) +AddBrandingImage left 100 + +; Sets the font of the installer +SetFont "Comic Sans MS" 8 + +; Just to make it three pages... +SubCaption 0 ": Yet another page..." +SubCaption 2 ": Yet another page..." +LicenseText "Second page" +LicenseData "gfx.nsi" +DirText "Lets make a third page!" + +; Install dir +InstallDir "${NSISDIR}\Examples" + +; Branding helper functions +!include "branding.nsh" + +Function .onInit + !insertmacro BI_INIT $R0 +FunctionEnd + +Function .onNextPage + !insertmacro BI_NEXT +FunctionEnd + +Function .onPrevPage + !insertmacro BI_PREV +FunctionEnd + +!insertmacro BI_LIST +!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks1.bmp" /RESIZETOFIT +!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks2.bmp" /RESIZETOFIT +!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checks4.bmp" /RESIZETOFIT +!insertmacro BI_LIST_END + +Section + ; You can also use the BI_NEXT macro here... + MessageBox MB_YESNO "We can change the branding image from within a section too!$\nDo you want me to change it?" IDNO done + GetTempFileName $1 + File /oname=$1 "${NSISDIR}\Contrib\Icons\checksX2.bmp" + SetBrandingImage $1 + Delete $1 + done: + WriteUninstaller uninst.exe +SectionEnd + +; Another page for uninstaller +UninstallText "Another page..." + +; Uninstall branding helper functions +!define BI_UNINSTALL +!include "branding.nsh" + +Function un.onInit + !insertmacro BI_INIT $R0 +FunctionEnd + +Function un.onNextPage + !insertmacro BI_NEXT +FunctionEnd + +!insertmacro BI_LIST +!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\checksX.bmp" /RESIZETOFIT +!insertmacro BI_LIST_ADD "${NSISDIR}\Contrib\Icons\jarsonic-checks.bmp" /RESIZETOFIT +!insertmacro BI_LIST_END + +Section uninstall + MessageBox MB_OK "Bla" +SectionEnd \ No newline at end of file diff --git a/Examples/makensis.nsi b/Examples/makensis.nsi new file mode 100644 index 00000000..4975c0c8 --- /dev/null +++ b/Examples/makensis.nsi @@ -0,0 +1,420 @@ +!define VER_MAJOR 2 +!define VER_MINOR 0a2 + +!ifdef NO_COMPRESSION +SetCompress off +SetDatablockOptimize off +!endif + +!ifdef NO_CRC +CRCCheck off +!endif + +Name "NSIS" +Caption "Nullsoft Install System - Setup" +OutFile nsis${VER_MAJOR}${VER_MINOR}.exe + +SetCompressor bzip2 + +!ifdef uglyinstaller +BGGradient 000000 308030 FFFFFF +InstallColors FF8080 000000 +InstProgressFlags smooth colored +XPStyle on +!else +WindowIcon off +!endif + +!ifdef NSIS_CONFIG_LICENSEPAGE +LicenseText "You must read the following license before installing:" +LicenseData ..\license.txt +!endif +!ifdef NSIS_CONFIG_COMPONENTPAGE +ComponentText "This will install the Nullsoft Install System v${VER_MAJOR}.${VER_MINOR} on your computer:" +InstType "Full (w/ Source and Contrib)" +InstType "Normal (w/ Contrib, w/o Source)" +InstType "Lite (w/o Source or Contrib)" +!endif + +AutoCloseWindow false +ShowInstDetails show +ShowUninstDetails show +DirText "Please select a location to install NSIS (or use the default):" +SetOverwrite on +SetDateSave on +!ifdef HAVE_UPX + !packhdr tmp.dat "upx\upx --best --compress-icons=1 tmp.dat" +!endif + +InstallDir $PROGRAMFILES\NSIS +InstallDirRegKey HKLM SOFTWARE\NSIS "" + +Section "NSIS development system (required)" + SectionIn 1 2 3 RO + SetOutPath $INSTDIR + SetOverwrite try + File ..\makensis.exe + File ..\makensisw.exe + File ..\makensis.htm + File ..\license.txt + SetOverwrite off + File ..\nsisconf.nsi +SectionEnd + +Section "NSIS Examples (recommended)" + SectionIn 1 2 3 + SetOutPath $INSTDIR\Examples + SetOverwrite try + Delete $INSTDIR\*.nsh + Delete $INSTDIR\viewhtml.nsi + Delete $INSTDIR\waplugin.nsi + Delete $INSTDIR\example*.nsi + Delete $INSTDIR\*test.nsi + Delete $INSTDIR\primes.nsi + Delete $INSTDIR\functions.htm + File ..\Examples\makensis.nsi + File ..\Examples\example1.nsi + File ..\Examples\example2.nsi + File ..\Examples\viewhtml.nsi + File ..\Examples\waplugin.nsi + File ..\Examples\bigtest.nsi + File ..\Examples\primes.nsi + File ..\Examples\rtest.nsi + File ..\Examples\gfx.nsi + File ..\Examples\WinMessages.nsh + File ..\Examples\branding.nsh + File ..\Examples\functions.htm +SectionEnd + +Section "NSI Development Shell Extensions" + SectionIn 1 2 3 + ; back up old value of .nsi + ReadRegStr $1 HKCR ".nsi" "" + StrCmp $1 "" Label1 + StrCmp $1 "NSISFile" Label1 + WriteRegStr HKCR ".nsi" "backup_val" $1 + Label1: + WriteRegStr HKCR ".nsi" "" "NSISFile" + WriteRegStr HKCR "NSISFile" "" "NSI Script File" + WriteRegStr HKCR "NSISFile\shell" "" "open" + WriteRegStr HKCR "NSISFile\DefaultIcon" "" $INSTDIR\makensis.exe,0 + WriteRegStr HKCR "NSISFile\shell\open\command" "" 'notepad.exe "%1"' + WriteRegStr HKCR "NSISFile\shell\compile" "" "Compile NSI" + WriteRegStr HKCR "NSISFile\shell\compile\command" "" '"$INSTDIR\makensisw.exe" "$INSTDIR\makensis.exe" /CD "%1"' + WriteRegStr HKCR "NSISFile\shell\compile-bz2" "" "Compile NSI (with bz2)" + WriteRegStr HKCR "NSISFile\shell\compile-bz2\command" "" '"$INSTDIR\makensisw.exe" "$INSTDIR\makensis.exe" /CD /X"SetCompressor bzip2" "%1"' +SectionEnd + +Section "Start Menu + Desktop Icons" + SectionIn 1 2 3 + SetOutPath $SMPROGRAMS\NSIS + Delete "$SMPROGRAMS\NSIS\NSIS Home Page.lnk" + WriteINIStr "$SMPROGRAMS\NSIS\NSIS Home Page.url" "InternetShortcut" "URL" "http://www.nullsoft.com/free/nsis/" + CreateShortCut "$SMPROGRAMS\NSIS\Uninstall NSIS.lnk" "$INSTDIR\uninst-nsis.exe" + CreateShortCut "$SMPROGRAMS\NSIS\NSIS Documentation.lnk" "$INSTDIR\makensis.htm" + CreateShortCut "$SMPROGRAMS\NSIS\NSIS Program Directory.lnk" "$INSTDIR" + Delete "$SMPROGRAMS\NSIS\NSI Online Template Generator.lnk" + WriteINIStr "$SMPROGRAMS\NSIS\NSI Online Template Generator.url" "InternetShortcut" "URL" "http://www.firehose.net/free/nsis/makensitemplate.phtml" + SetOutPath $INSTDIR + CreateShortCut "$DESKTOP\MakeNSIS.lnk" "$INSTDIR\Makensisw.exe" '"$INSTDIR\makensis.exe" /CD' +SectionEnd + +!ifndef NO_CONTRIB + +SubSection "Additional utilities" + +SubSection "Contrib" + +Section "Extra Icons" + SectionIn 1 2 + SetOutPath $INSTDIR\Contrib\Icons + SetOverwrite try + Delete $INSTDIR\Contrib\*.ico + Delete $INSTDIR\Contrib\*.bmp + File ..\Contrib\Icons\*.ico + File ..\Contrib\Icons\*.bmp + SetOutPath $INSTDIR +SectionEnd + +Section "Extra UIs" + SectionIn 1 2 + SetOutPath $INSTDIR\Contrib\UIs + SetOverwrite try + File ..\Contrib\UIs\*.exe + SetOutPath $INSTDIR +SectionEnd + +Section "Splash" + SectionIn 1 2 + SetOutPath $INSTDIR\Contrib\Splash + SetOverwrite try + File ..\Contrib\Splash\splash.c + File ..\Contrib\Splash\splash.dsp + File ..\Contrib\Splash\splash.dsw + File ..\Contrib\splash\splash.txt + SetOutPath $INSTDIR\Bin + File ..\Bin\splash.exe + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\Splash Screen Help.lnk" "$INSTDIR\contrib\splash\splash.txt" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\Splash project workspace.lnk" "$INSTDIR\source\splash\splash.dsw" + NoShortCuts: +SectionEnd + +Section "Zip2Exe" + SectionIn 1 2 + DetailPrint "Extracting zip2exe source" + SetDetailsPrint textonly + RMDir /r $INSTDIR\Source\Zip2Exe + SetOutPath $INSTDIR\Contrib\zip2exe + SetOverwrite try + File ..\Contrib\zip2exe\*.cpp + File ..\Contrib\zip2exe\*.ico + File ..\Contrib\zip2exe\*.h + File ..\Contrib\zip2exe\*.rc + File ..\Contrib\zip2exe\*.dsw + File ..\Contrib\zip2exe\*.dsp + SetOutPath $INSTDIR\Contrib\zip2exe\zlib + File ..\Contrib\zip2exe\zlib\*.* + SetOutPath $INSTDIR\Bin + File ..\Bin\zip2exe.exe + SetDetailsPrint both + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + Delete "$SMPROGRAMS\Bin\NSIS\ZIP2EXE converter.lnk" + Delete "$SMPROGRAMS\NSIS\ZIP2EXE project workspace.lnk" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\ZIP2EXE converter.lnk" "$INSTDIR\Bin\zip2exe.exe" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\ZIP2EXE project workspace.lnk" "$INSTDIR\source\zip2exe\zip2exe.dsw" + NoShortCuts: +SectionEnd + +Section "InstallOptions" + SectionIn 1 2 + SetOutPath $INSTDIR\Contrib\InstallOptions + SetOverwrite try + File ..\contrib\installoptions\io.dsp + File ..\contrib\installoptions\io.dsw + File ..\contrib\installoptions\test.ini + File ..\contrib\installoptions\test.nsi + File ..\contrib\installoptions\InstallerOptions.cpp + File ..\contrib\installoptions\*.rc + File ..\contrib\installoptions\*.h + File "..\contrib\installoptions\Install Options.html" + SetOutPath $INSTDIR\Bin + File ..\Bin\InstallOptions.dll + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\InstallOptions Readme.lnk" "$INSTDIR\contrib\InstallOptions\install options.html" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\InstallOptions project workspace.lnk" "$INSTDIR\contrib\InstallOptions\io.dsw" + NoShortCuts: +SectionEnd + +Section "NSIS-DL" + SectionIn 1 2 + SetOutPath $INSTDIR\Contrib\NSISdl + SetOverwrite try + File ..\contrib\NSISdl\nsisdl.dsw + File ..\contrib\NSISdl\nsisdl.dsp + File ..\contrib\NSISdl\*.cpp + File ..\contrib\NSISdl\*.h + File ..\contrib\NSISdl\*.rc + File ..\contrib\NSISdl\ReadMe.txt + SetOutPath $INSTDIR\Bin + File ..\Bin\nsisdl.dll + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\NSIS-DL Readme.lnk" "$INSTDIR\contrib\NSISDL\ReadMe.txt" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\NSIS-DL project workspace.lnk" "$INSTDIR\contrib\NSISDL\nsisdl.dsw" + NoShortCuts: +SectionEnd + +SubSectionEnd + +SubSectionEnd + +!endif + + +!ifndef NO_SOURCE + +SubSection "Source code" + +Section "NSIS Source Code" + SectionIn 1 + DetailPrint "Extracting source code...." + SetDetailsPrint textonly + SetOutPath $INSTDIR\Source + SetOverwrite try + File ..\Source\*.cpp + File ..\Source\*.c + File ..\Source\*.h + File ..\Source\script1.rc + File ..\Source\Makefile + File ..\Source\makenssi.dsp + File ..\Source\makenssi.dsw + File ..\Source\icon.ico + SetOutPath $INSTDIR\Source\zlib + File ..\Source\zlib\*.* + SetOutPath $INSTDIR\Source\bzip2 + File ..\Source\bzip2\*.* + SetOutPath $INSTDIR\Source\exehead + File ..\Source\exehead\*.c + File ..\Source\exehead\*.h + File ..\Source\exehead\exehead.xml + File ..\Source\exehead\resource.rc + File ..\Source\exehead\*.dsp + File ..\Source\exehead\Makefile + File ..\Source\exehead\nsis.ico + File ..\Source\exehead\uninst.ico + File ..\Source\exehead\bitmap1.bmp + File ..\Source\exehead\bin2h.exe + IfFileExists $SMPROGRAMS\NSIS 0 NoSourceShortCuts + CreateShortCut "$SMPROGRAMS\NSIS\MakeNSIS project workspace.lnk" "$INSTDIR\source\makenssi.dsw" + NoSourceShortCuts: + SetDetailsPrint both +SectionEnd + +SubSection "Contrib" + +Section "ExDLL Source" + SectionIn 1 + SetOutPath $INSTDIR\Contrib\ExDLL + SetOverwrite try + File ..\contrib\exdll\exdll.c + File ..\contrib\exdll\exdll.dpr + File ..\contrib\exdll\exdll.dsp + File ..\contrib\exdll\exdll.dsw + SetOutPath $INSTDIR + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\ExDLL project workspace.lnk" "$INSTDIR\contrib\ExDLL\exdll.dsw" + NoShortCuts: +SectionEnd + +Section "MakeNSISW Source" + SectionIn 1 + SetOutPath $INSTDIR\Contrib\Makensisw + SetOverwrite try + File ..\contrib\makensisw\*.cpp + File ..\contrib\makensisw\*.xml + File ..\contrib\makensisw\*.h + File ..\contrib\makensisw\*.ds? + File ..\contrib\makensisw\*.rc + File ..\contrib\makensisw\*.txt + #File ..\contrib\makensisw\Makefile + IfFileExists $SMPROGRAMS\NSIS 0 NoShortCuts + CreateDirectory $SMPROGRAMS\NSIS\Contrib + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\MakeNSISW project workspace.lnk" "$INSTDIR\contrib\MakeNsisw\makensisw.dsw" + CreateShortCut "$SMPROGRAMS\NSIS\Contrib\MakeNSISW readme.lnk" "$INSTDIR\contrib\MakeNsisw\readme.txt" + NoShortCuts: +SectionEnd + +SubSectionEnd + +SubSectionEnd + +!endif + +Section -post + WriteRegStr HKLM SOFTWARE\NSIS "" $INSTDIR + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" "DisplayName" "NSIS Development Kit (remove only)" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" "UninstallString" '"$INSTDIR\uninst-nsis.exe"' + SetOutPath $INSTDIR + IfFileExists $SMPROGRAMS\NSIS "" nofunshit + ExecShell open '$SMPROGRAMS\NSIS' + Sleep 500 + BringToFront + nofunshit: + ; since the installer is now created last (in 1.2+), this makes sure + ; that any old installer that is readonly is overwritten. + Delete $INSTDIR\uninst-nsis.exe + WriteUninstaller $INSTDIR\uninst-nsis.exe +SectionEnd + +Function .onInstSuccess + MessageBox MB_YESNO|MB_ICONQUESTION "Setup has completed. View readme file now?" IDNO NoReadme + ExecShell open '$INSTDIR\makensis.htm' + NoReadme: +FunctionEnd + +!ifndef NO_UNINST + +UninstallText "This will uninstall NSIS from your system:" + +Section Uninstall + IfFileExists $INSTDIR\makensis.exe skip_confirmation + MessageBox MB_YESNO "It does not appear that NSIS is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)" IDYES skip_confirmation + Abort "Uninstall aborted by user" + skip_confirmation: + ReadRegStr $1 HKCR ".nsi" "" + StrCmp $1 "NSISFile" 0 NoOwn ; only do this if we own it + ReadRegStr $1 HKCR ".nsi" "backup_val" + StrCmp $1 "" 0 RestoreBackup ; if backup == "" then delete the whole key + DeleteRegKey HKCR ".nsi" + Goto NoOwn + RestoreBackup: + WriteRegStr HKCR ".nsi" "" $1 + DeleteRegValue HKCR ".nsi" "backup_val" + NoOwn: + + DeleteRegKey HKCR "NSISFile" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" + DeleteRegKey HKLM SOFTWARE\NSIS + + Delete $SMPROGRAMS\NSIS\Contrib\*.lnk + Delete $SMPROGRAMS\NSIS\Contrib\*.url + RMDir $SMPROGRAMS\NSIS\Contrib + RMDir /r $INSTDIR\Contrib + + Delete $SMPROGRAMS\NSIS\*.lnk + Delete $SMPROGRAMS\NSIS\*.url + RMDir $SMPROGRAMS\NSIS + Delete $DESKTOP\MakeNSIS.lnk + Delete $INSTDIR\makensis*.exe + Delete $INSTDIR\Bin\zip2exe.exe + Delete $INSTDIR\Bin\installoptions.exe + Delete $INSTDIR\Bin\installoptions.dll + Delete $INSTDIR\Bin\splash.txt + Delete $INSTDIR\Bin\splash.exe + Delete $INSTDIR\Bin\nsisdl.dll + Delete $INSTDIR\makensis.htm + Delete $INSTDIR\Examples\functions.htm + Delete $INSTDIR\makensis.rtf + Delete $INSTDIR\uninst-nsis.exe + Delete $INSTDIR\nsisconf.nsi + Delete $INSTDIR\Examples\makensis.nsi + Delete $INSTDIR\Examples\example1.nsi + Delete $INSTDIR\Examples\example2.nsi + Delete $INSTDIR\Examples\waplugin.nsi + Delete $INSTDIR\Examples\viewhtml.nsi + Delete $INSTDIR\Examples\bigtest.nsi + Delete $INSTDIR\Examples\primes.nsi + Delete $INSTDIR\Examples\rtest.nsi + Delete $INSTDIR\Examples\uglytest.nsi + Delete $INSTDIR\Examples\spin.nsi + Delete $INSTDIR\Examples\wafull.nsi + Delete $INSTDIR\Examples\upgradedll.nsh + Delete $INSTDIR\Examples\WinMessages.nsh + Delete $INSTDIR\main.ico + Delete $INSTDIR\makensis-license.txt + Delete $INSTDIR\license.txt + Delete $INSTDIR\uninst.ico + Delete $INSTDIR\bitmap1.bmp + Delete $INSTDIR\bitmap2.bmp + RMDir /r $INSTDIR\Source + RMDir /r $INSTDIR\Bin + RMDir /r $INSTDIR\Examples + RMDir $INSTDIR + + ; if $INSTDIR was removed, skip these next ones + IfFileExists $INSTDIR 0 Removed + MessageBox MB_YESNO|MB_ICONQUESTION \ + "Remove all files in your NSIS directory? (If you have anything you created that you want to keep, click No)" IDNO Removed + Delete $INSTDIR\*.* ; this would be skipped if the user hits no + RMDir /r $INSTDIR + IfFileExists $INSTDIR 0 Removed + MessageBox MB_OK|MB_ICONEXCLAMATION "Note: $INSTDIR could not be removed." + Removed: +SectionEnd + +!endif diff --git a/Examples/primes.nsi b/Examples/primes.nsi new file mode 100644 index 00000000..8d2acfdc --- /dev/null +++ b/Examples/primes.nsi @@ -0,0 +1,48 @@ +Name "primes" +AllowRootDirInstall true +OutFile "primes.exe" +Caption "Prime number generator" +ShowInstDetails show +AllowRootDirInstall true +InstallDir "$EXEDIR" +DirText "Select directory to write primes.txt" + +Section "crap" + SetOutPath $INSTDIR + Call DoPrimes +SectionEnd + +Function DoPrimes +; we put this in here so it doesn't update the progress bar (faster) +!define PPOS $0 ; position in prime searching +!define PDIV $1 ; divisor +!define PMOD $2 ; the result of the modulus +!define PCNT $3 ; count of how many we've printed + FileOpen $9 $INSTDIR\primes.txt w + + DetailPrint "2 is prime!" + FileWrite $9 "2 is prime!$\r$\n" + DetailPrint "3 is prime!" + FileWrite $9 "3 is prime!$\r$\n" + Strcpy ${PPOS} 3 + Strcpy ${PCNT} 2 +outerloop: + StrCpy ${PDIV} 3 + innerloop: + IntOp ${PMOD} ${PPOS} % ${PDIV} + IntCmp ${PMOD} 0 notprime + IntOp ${PDIV} ${PDIV} + 2 + IntCmp ${PDIV} ${PPOS} 0 innerloop 0 + DetailPrint "${PPOS} is prime!" + FileWrite $9 "${PPOS} is prime!$\r$\n" + IntOp ${PCNT} ${PCNT} + 1 + IntCmp ${PCNT} 100 0 innerloop + StrCpy ${PCNT} 0 + MessageBox MB_YESNO "Process more?" IDNO stop + notprime: + IntOp ${PPOS} ${PPOS} + 2 + Goto outerloop + stop: + FileClose $9 +FunctionEnd + diff --git a/Examples/rtest.nsi b/Examples/rtest.nsi new file mode 100644 index 00000000..b8b3b42b --- /dev/null +++ b/Examples/rtest.nsi @@ -0,0 +1,56 @@ +Name "rtest" +OutFile "rtest.exe" + +InstallDir $TEMP +BGGradient 0 FFFF00 00FFFF +DirShow hide +ComponentText "select tests." + +Section "test 1" +StrCpy $0 "a" +Call test1 +StrCmp $0 "a182345678" success +DetailPrint "Test 1 failed (output: $0)" +Goto end +success: +DetailPrint "Test 1 succeded (output: $0)" +end: +SectionEnd + +Function test1 +GetLabelAddress $9 skip8 +IntOp $9 $9 - 1 +StrCpy $0 $01 +Call $9 +StrCpy $0 $02 +StrCpy $0 $03 +StrCpy $0 $04 +StrCpy $0 $05 +StrCpy $0 $06 +StrCpy $0 $07 +StrCpy $0 $08 +skip8: +FunctionEnd + +Section "test 2" +StrCpy $0 "0" +StrCpy $1 "11" +GetFunctionAddress $9 test2 +Call $9 +StrCmp $1 "11,10,9,8,7,6,5,4,3,2,1" success + DetailPrint "Test 2 failed (output: $1)" +Goto end +success: + DetailPrint "Test 2 succeded (output: $1)" +end: +SectionEnd + +Function test2 +IntOp $0 $0 + 1 +IntCmp $0 10 done +Push $0 +Call test2 +Pop $0 +done: + StrCpy $1 "$1,$0" +FunctionEnd diff --git a/Examples/viewhtml.nsi b/Examples/viewhtml.nsi new file mode 100644 index 00000000..9bea08ec --- /dev/null +++ b/Examples/viewhtml.nsi @@ -0,0 +1,43 @@ +; viewhtml.nsi +; +; This script creates a silent installer which extracts one (or more) HTML +; files to a temporary directory, opens Internet Explorer to view the file(s), +; and when Internet Explorer has quit, deletes the file(s). +; + +; The name of the installer (not really used in a silent install) +Name "ViewHTML" + +; Set to silent mode +SilentInstall silent + +; The file to write +OutFile "viewhtml.exe" + +; The installation directory (the user never gets to change this) +InstallDir "$TEMP\ViewHTML" + +; The stuff to install +Section "" + ; Set output path to the installation directory. + SetOutPath $INSTDIR + ; Extract file + File "..\makensis.htm" + ; View file + ExecWait '"$PROGRAMFILES\Internet Explorer\iexplore.exe" "$INSTDIR\makensis.htm"' + ; Delete the files + Delete $INSTDIR\Makensis.htm + RMDir $INSTDIR +SectionEnd + +; Note: another way of doing this would be to use ExecShell, but then you +; really couldn't get away with deleting the files. Here is the ExecShell +; line that you would want to use: +; +; ExecShell "open" '"$INSTDIR\makensis.htm"' +; +; The advantage of this way is that it would use the default browser to +; open the HTML. +; + +; eof diff --git a/Examples/waplugin.nsi b/Examples/waplugin.nsi new file mode 100644 index 00000000..9a47701c --- /dev/null +++ b/Examples/waplugin.nsi @@ -0,0 +1,153 @@ +; waplugin.nsi +; +; This script will generate an installer that installs a Winamp plug-in. +; It also puts a license page on, for shits and giggles. +; +; This installer will automatically alert the user that installation was +; successful, and ask them whether or not they would like to make the +; plug-in the default and run Winamp. +; + +; The name of the installer +Name "TinyVis Plug-in" + +; The file to write +OutFile "waplugin.exe" + +; License page +; LicenseText "This installer will install the Nullsoft Tiny Visualization 2000 Plug-in for Winamp. Please read the license below." +; use the default makensis license :) +; LicenseData license.txt + +; The default installation directory +InstallDir $PROGRAMFILES\Winamp +; detect winamp path from uninstall string if available +InstallDirRegKey HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\Winamp" \ + "UninstallString" + +; The text to prompt the user to enter a directory +DirText "Please select your Winamp path below (you will be able to proceed when Winamp is detected):" +DirShow hide + +; automatically close the installer when done. +AutoCloseWindow true +; hide the "show details" box +ShowInstDetails nevershow + +Function .onVerifyInstDir +!ifndef WINAMP_AUTOINSTALL + IfFileExists $INSTDIR\Winamp.exe Good + Abort + Good: +!endif ; WINAMP_AUTOINSTALL +FunctionEnd + +Function QueryWinampVisPath ; sets $1 with vis path + StrCpy $1 $INSTDIR\Plugins + ; use DSPDir instead of VISDir to get DSP plugins directory + ReadINIStr $9 $INSTDIR\winamp.ini Winamp VisDir + StrCmp $9 "" End + IfFileExists $9 0 End + StrCpy $1 $9 ; update dir + End: +FunctionEnd + + +!ifdef WINAMP_AUTOINSTALL +Function GetWinampInstPath + Push $0 + Push $1 + Push $2 + ReadRegStr $0 HKLM \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\Winamp" \ + "UninstallString" + StrCmp $0 "" fin + + StrCpy $1 $0 1 0 ; get firstchar + StrCmp $1 '"' "" getparent + ; if first char is ", let's remove "'s first. + StrCpy $0 $0 "" 1 + StrCpy $1 0 + rqloop: + StrCpy $2 $0 1 $1 + StrCmp $2 '"' rqdone + StrCmp $2 "" rqdone + IntOp $1 $1 + 1 + Goto rqloop + rqdone: + StrCpy $0 $0 $1 + getparent: + ; the uninstall string goes to an EXE, let's get the directory. + StrCpy $1 -1 + gploop: + StrCpy $2 $0 1 $1 + StrCmp $2 "" gpexit + StrCmp $2 "\" gpexit + IntOp $1 $1 - 1 + Goto gploop + gpexit: + StrCpy $0 $0 $1 + + StrCmp $0 "" fin + IfFileExists $0\winamp.exe fin + StrCpy $0 "" + fin: + Pop $2 + Pop $1 + Exch $0 +FunctionEnd + + + +Function MakeSureIGotWinamp + Call GetWinampInstPath + Pop $0 + StrCmp $0 "" getwinamp + Return + getwinamp: + StrCpy $1 $TEMP\porearre1.dll + StrCpy $2 "$TEMP\Winamp Installer.exe" + File /oname=$1 nsisdl.dll + Push http://download.nullsoft.com/winamp/client/winamp277_lite.exe + Push $2 + CallInstDLL $1 download + Delete $1 + StrCmp $0 success success + SetDetailsView show + DetailPrint "download failed: $0" + Abort + success: + ExecWait '"$2" /S' + Delete $2 + Call GetWinampInstPath + Pop $0 + StrCmp $0 "" skip + StrCpy $INSTDIR $0 + skip: +FunctionEnd + +!endif ; WINAMP_AUTOINSTALL +; The stuff to install +Section "ThisNameIsIgnoredSoWhyBother?" +!ifdef WINAMP_AUTOINSTALL + Call MakeSureIGotWinamp +!endif + + Call QueryWinampVisPath + SetOutPath $1 + + ; File to extract + File "C:\program files\winamp\plugins\vis_nsfs.dll" + + ; prompt user, and if they select no, skip the following 3 instructions. + MessageBox MB_YESNO|MB_ICONQUESTION \ + "The plug-in was installed. Would you like to run Winamp now with TinyVis as the default plug-in?" \ + IDNO NoWinamp + WriteINIStr "$INSTDIR\Winamp.ini" "Winamp" "visplugin_name" "vis_nsfs.dll" + WriteINIStr "$INSTDIR\Winamp.ini" "Winamp" "visplugin_num" "0" + Exec '"$INSTDIR\Winamp.exe"' + NoWinamp: +SectionEnd + +; eof diff --git a/Source/DialogTemplate.cpp b/Source/DialogTemplate.cpp new file mode 100644 index 00000000..a4d7722d --- /dev/null +++ b/Source/DialogTemplate.cpp @@ -0,0 +1,463 @@ +/* + Copyright (C) 2002 Amir Szekely + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "DialogTemplate.h" + +////////////////////////////////////////////////////////////////////// +// Utilities +////////////////////////////////////////////////////////////////////// + +#define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn + +// returns the number of WCHARs in str including null charcter +inline DWORD WCStrLen(WCHAR* szwStr) { + int i; + for (i = 0; szwStr[i]; i++); + return i+1; +} + +// Reads a variany length array from seeker into readInto and advances seeker +void ReadVarLenArr(BYTE* &seeker, char* &readInto) { + WORD* arr = (WORD*)seeker; + switch (arr[0]) { + case 0x0000: + readInto = 0; + seeker += sizeof(WORD); + break; + case 0xFFFF: + readInto = MAKEINTRESOURCE(arr[1]); + seeker += 2*sizeof(WORD); + break; + default: + { + DWORD dwStrLen = WCStrLen((WCHAR*)arr); + readInto = new char[dwStrLen]; + WideCharToMultiByte(CP_ACP, 0, (WCHAR*)arr, dwStrLen, readInto, dwStrLen, 0, 0); + seeker += (dwStrLen)*sizeof(WORD); + } + break; + } +} + +// A macro that writes a given string (that can be a number too) into the buffer +#define WriteStringOrId(x) \ + if (x) \ + if (IS_INTRESOURCE(x)) { \ + *(WORD*)seeker = 0xFFFF; \ + seeker += sizeof(WORD); \ + *(WORD*)seeker = WORD(x); \ + seeker += sizeof(WORD); \ + } \ + else { \ + MultiByteToWideChar(CP_ACP, 0, x, -1, (WCHAR*)seeker, dwSize); \ + seeker += (lstrlen(x)+1)*sizeof(WCHAR); \ + } \ + else \ + seeker += sizeof(WORD); + +// A macro that adds the size of x (which can be a string a number, or nothing) to dwSize +#define AddStringOrIdSize(x) dwSize += x ? (IS_INTRESOURCE(x) ? sizeof(DWORD) : (lstrlen(x)+1)*sizeof(WCHAR)) : sizeof(WORD) + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CDialogTemplate::CDialogTemplate(BYTE* pbData) { + m_szClass = 0; + m_szFont = 0; + m_szMenu = 0; + m_szTitle = 0; + + WORD wItems = 0; + + if (*(DWORD*)pbData == 0xFFFF0001) { // Extended dialog template signature + m_bExtended = true; + + DLGTEMPLATEEX* dTemplateEx = (DLGTEMPLATEEX*)pbData; + + m_dwHelpId = dTemplateEx->helpID; + m_dwStyle = dTemplateEx->style; + m_dwExtStyle = dTemplateEx->exStyle; + m_sX = dTemplateEx->x; + m_sY = dTemplateEx->y; + m_sWidth = dTemplateEx->cx; + m_sHeight = dTemplateEx->cy; + + wItems = dTemplateEx->cDlgItems; + } + else { + m_bExtended = false; + DLGTEMPLATE* dTemplate = (DLGTEMPLATE*)pbData; + + m_dwStyle = dTemplate->style; + m_dwExtStyle = dTemplate->dwExtendedStyle; + m_sX = dTemplate->x; + m_sY = dTemplate->y; + m_sWidth = dTemplate->cx; + m_sHeight = dTemplate->cy; + + wItems = dTemplate->cdit; + } + + BYTE* seeker = pbData + (m_bExtended ? sizeof(DLGTEMPLATEEX) : sizeof(DLGTEMPLATE)); + + // Read menu variant length array + ReadVarLenArr(seeker, m_szMenu); + // Read class variant length array + ReadVarLenArr(seeker, m_szClass); + // Read title variant length array + ReadVarLenArr(seeker, m_szTitle); + // Read font size and variant length array (only if style DS_SETFONT is used!) + if (m_dwStyle & DS_SETFONT) { + m_sFontSize = *(short*)seeker; + seeker += sizeof(short); + ReadVarLenArr(seeker, m_szFont); + } + + // Read items + for (int i = 0; i < wItems; i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundry + if (DWORD(seeker - pbData) % sizeof(DWORD)) + seeker += sizeof(WORD); + + DialogItemTemplate* item = new DialogItemTemplate; + ZeroMemory(item, sizeof(DialogItemTemplate)); + + if (m_bExtended) { + DLGITEMTEMPLATEEX* rawItem = (DLGITEMTEMPLATEEX*)seeker; + + item->dwHelpId = rawItem->helpID; + item->dwStyle = rawItem->style; + item->dwExtStyle = rawItem->exStyle; + item->sX = rawItem->x; + item->sY = rawItem->y; + item->sWidth = rawItem->cx; + item->sHeight = rawItem->cy; + item->wId = rawItem->id; + + seeker += sizeof(DLGITEMTEMPLATEEX); + } + else { + DLGITEMTEMPLATE* rawItem = (DLGITEMTEMPLATE*)seeker; + + item->dwStyle = rawItem->style; + item->dwExtStyle = rawItem->dwExtendedStyle; + item->sX = rawItem->x; + item->sY = rawItem->y; + item->sWidth = rawItem->cx; + item->sHeight = rawItem->cy; + item->wId = rawItem->id; + + seeker += sizeof(DLGITEMTEMPLATE); + } + + // Read class variant length array + ReadVarLenArr(seeker, item->szClass); + // Read title variant length array + ReadVarLenArr(seeker, item->szTitle); + + // Read creation data variant length array + // First read the size of the array (no null termination) + item->wCreateDataSize = *(WORD*)seeker; + seeker += sizeof(WORD); + // Then read the array it self (if size is not 0) + if (item->wCreateDataSize) { + item->wCreateDataSize -= sizeof(WORD); // Size includes size field itself... + item->szCreationData = new char[item->wCreateDataSize]; + CopyMemory(item->szCreationData, seeker, item->wCreateDataSize); + seeker += item->wCreateDataSize; + } + + // Add the item to the vector + m_vItems.push_back(item); + } +} + +CDialogTemplate::~CDialogTemplate() { + if (m_szMenu && !IS_INTRESOURCE(m_szMenu)) + delete [] m_szMenu; + if (m_szClass && !IS_INTRESOURCE(m_szClass)) + delete [] m_szClass; + if (m_szTitle) + delete [] m_szTitle; + if (m_szFont) + delete [] m_szTitle; + + for (int i = 0; i < m_vItems.size(); i++) { + if (m_vItems[i]->szClass && !IS_INTRESOURCE(m_vItems[i]->szClass)) + delete [] m_vItems[i]->szClass; + if (m_vItems[i]->szTitle && !IS_INTRESOURCE(m_vItems[i]->szTitle)) + delete [] m_vItems[i]->szTitle; + if (m_vItems[i]->szCreationData) + delete [] m_vItems[i]->szCreationData; + } +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +// Returns info about the item with the id wId +DialogItemTemplate* CDialogTemplate::GetItem(WORD wId) { + for (int i = 0; i < m_vItems.size(); i++) + if (m_vItems[i]->wId == wId) + return m_vItems[i]; + return 0; +} + +// Returns info about the item with the indexed i +DialogItemTemplate* CDialogTemplate::GetItemByIdx(DWORD i) { + if (i > m_vItems.size()) return 0; + return m_vItems[i]; +} + +// Removes an item +void CDialogTemplate::RemoveItem(WORD wId) { + for (int i = 0; i < m_vItems.size(); i++) + if (m_vItems[i]->wId == wId) + m_vItems.erase(m_vItems.begin() + i); +} + +// Sets the font of the dialog +void CDialogTemplate::SetFont(char* szFaceName, WORD wFontSize) { + m_dwStyle |= DS_SETFONT; + if (m_szFont) delete [] m_szFont; + m_szFont = new char[lstrlen(szFaceName)]; + lstrcpy(m_szFont, szFaceName); + m_sFontSize = wFontSize; +} + +// Adds an item to the dialog +void CDialogTemplate::AddItem(DialogItemTemplate item) { + DialogItemTemplate* newItem = new DialogItemTemplate; + CopyMemory(newItem, &item, sizeof(DialogItemTemplate)); + + if (item.szClass && !IS_INTRESOURCE(item.szClass)) { + newItem->szClass = new char[lstrlen(item.szClass)+1]; + lstrcpy(newItem->szClass, item.szClass); + } + if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) { + newItem->szTitle = new char[lstrlen(item.szTitle)+1]; + lstrcpy(newItem->szTitle, item.szTitle); + } + if (item.wCreateDataSize) { + newItem->szCreationData = new char[item.wCreateDataSize]; + memcpy(newItem->szCreationData, item.szCreationData, item.wCreateDataSize); + } + m_vItems.push_back(newItem); +} + +// Moves all of the items in the dialog by (x,y) and resizes the dialog by (x,y) +void CDialogTemplate::MoveAllAndResize(short x, short y) { + // Move all items + for (int i = 0; i < m_vItems.size(); i++) { + m_vItems[i]->sX += x; + m_vItems[i]->sY += y; + } + // Resize + m_sWidth += x; + m_sHeight += y; +} + +// Converts pixels to this dialog's units +void CDialogTemplate::PixelsToDlgUnits(short& x, short& y) { + DWORD dwTemp; + BYTE* pbDlg = Save(dwTemp); + HWND hDlg = CreateDialogIndirect(GetModuleHandle(0), (DLGTEMPLATE*)pbDlg, 0, 0); + delete [] pbDlg; + if (!hDlg) + throw runtime_error("Can't create dialog from template!"); + RECT r = {0, 0, 1024, 1024}; + MapDialogRect(hDlg, &r); + DestroyWindow(hDlg); + + x = float(x) / (float(r.right)/1024); + y = float(y) / (float(r.bottom)/1024); +} + +// Converts pixels to this dialog's units +void CDialogTemplate::DlgUnitsToPixels(short& x, short& y) { + DWORD dwTemp; + BYTE* pbDlg = Save(dwTemp); + HWND hDlg = CreateDialogIndirect(GetModuleHandle(0), (DLGTEMPLATE*)pbDlg, 0, 0); + delete [] pbDlg; + if (!hDlg) + throw runtime_error("Can't create dialog from template!"); + RECT r = {0, 0, 1024, 1024}; + MapDialogRect(hDlg, &r); + DestroyWindow(hDlg); + + x = float(x) * (float(r.right)/1024); + y = float(y) * (float(r.bottom)/1024); +} + +// Saves the dialog in the form of DLGTEMPLATE[EX] +BYTE* CDialogTemplate::Save(DWORD& dwSize) { + // We need the size first to know how much memory to allocate + dwSize = GetSize(); + BYTE* pbDlg = new BYTE[dwSize]; + ZeroMemory(pbDlg, dwSize); + BYTE* seeker = pbDlg; + + if (m_bExtended) { + DLGTEMPLATEEX dh = { + 0x0001, + 0xFFFF, + m_dwHelpId, + m_dwExtStyle, + m_dwStyle, + m_vItems.size(), + m_sX, + m_sY, + m_sWidth, + m_sHeight + }; + + CopyMemory(seeker, &dh, sizeof(DLGTEMPLATEEX)); + seeker += sizeof(DLGTEMPLATEEX); + } + else { + DLGTEMPLATE dh = { + m_dwStyle, + m_dwExtStyle, + m_vItems.size(), + m_sX, + m_sY, + m_sWidth, + m_sHeight + }; + + CopyMemory(seeker, &dh, sizeof(DLGTEMPLATE)); + seeker += sizeof(DLGTEMPLATE); + } + + // Write menu variant length array + WriteStringOrId(m_szMenu); + // Write class variant length array + WriteStringOrId(m_szClass); + // Write title variant length array + WriteStringOrId(m_szTitle); + + // Write font variant length array, size, and extended info (if needed) + if (m_dwStyle & DS_SETFONT) { + *(short*)seeker = m_sFontSize; + seeker += sizeof(short); + if (m_bExtended) { + *(short*)seeker = m_sFontWeight; + seeker += sizeof(short); + *(short*)seeker = m_bItalic ? TRUE : FALSE; + seeker += sizeof(short); + } + WriteStringOrId(m_szFont); + } + + // Write all of the items + for (int i = 0; i < m_vItems.size(); i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundry + if (DWORD(seeker - pbDlg) % sizeof(DWORD)) + seeker += sizeof(WORD); + + if (m_bExtended) { + DLGITEMTEMPLATEEX dih = { + m_vItems[i]->dwHelpId, + m_vItems[i]->dwExtStyle, + m_vItems[i]->dwStyle, + m_vItems[i]->sX, + m_vItems[i]->sY, + m_vItems[i]->sWidth, + m_vItems[i]->sHeight, + m_vItems[i]->wId + }; + + CopyMemory(seeker, &dih, sizeof(DLGITEMTEMPLATEEX)); + seeker += sizeof(DLGITEMTEMPLATEEX); + } + else { + DLGITEMTEMPLATE dih = { + m_vItems[i]->dwStyle, + m_vItems[i]->dwExtStyle, + m_vItems[i]->sX, + m_vItems[i]->sY, + m_vItems[i]->sWidth, + m_vItems[i]->sHeight, + m_vItems[i]->wId + }; + + CopyMemory(seeker, &dih, sizeof(DLGITEMTEMPLATE)); + seeker += sizeof(DLGITEMTEMPLATE); + } + + // Write class variant length array + WriteStringOrId(m_vItems[i]->szClass); + // Write title variant length array + WriteStringOrId(m_vItems[i]->szTitle); + + // Write creation data variant length array + // First write its size + if (m_vItems[i]->wCreateDataSize) m_vItems[i]->wCreateDataSize += sizeof(WORD); + *(WORD*)seeker = m_vItems[i]->wCreateDataSize; + seeker += sizeof(WORD); + // If size is nonzero write the data too + if (m_vItems[i]->wCreateDataSize) { + CopyMemory(seeker, m_vItems[i]->szCreationData, m_vItems[i]->wCreateDataSize); + seeker += m_vItems[i]->wCreateDataSize; + } + } + + // DONE! + return pbDlg; +} + +// Returns the size that the DLGTEMPLATE[EX] will take when saved +DWORD CDialogTemplate::GetSize() { + DWORD dwSize = m_bExtended ? sizeof(DLGTEMPLATEEX) : sizeof(DLGTEMPLATE); + + // Menu + AddStringOrIdSize(m_szMenu); + // Class + AddStringOrIdSize(m_szClass); + // Title + AddStringOrIdSize(m_szTitle); + + // Font + if (m_dwStyle & DS_SETFONT) { + dwSize += sizeof(WORD) + (m_bExtended ? 2*sizeof(short) : 0); + AddStringOrIdSize(m_szFont); + } + + for (int i = 0; i < m_vItems.size(); i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundry + ALIGN(dwSize, sizeof(DWORD)); + + dwSize += m_bExtended ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE); + + // Class + AddStringOrIdSize(m_vItems[i]->szClass); + // Title + AddStringOrIdSize(m_vItems[i]->szTitle); + + dwSize += sizeof(WORD) + m_vItems[i]->wCreateDataSize; + } + + return dwSize; +} diff --git a/Source/DialogTemplate.h b/Source/DialogTemplate.h new file mode 100644 index 00000000..81bc5f02 --- /dev/null +++ b/Source/DialogTemplate.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2002 Amir Szekely + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_) +#define AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include + +#include +using namespace std; + +struct DialogItemTemplate { + DWORD dwHelpId; // Extended only + + short sX; + short sY; + short sWidth; + short sHeight; + DWORD dwExtStyle; + DWORD dwStyle; + WORD wId; + + char *szClass; + char *szTitle; + char *szCreationData; + + WORD wCreateDataSize; +}; + +typedef struct { + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x; + short y; + short cx; + short cy; +} DLGTEMPLATEEX; + +typedef struct { + DWORD helpID; + DWORD exStyle; + DWORD style; + short x; + short y; + short cx; + short cy; + WORD id; +} DLGITEMTEMPLATEEX; + + +class CDialogTemplate { +public: + CDialogTemplate(BYTE* pbData); + virtual ~CDialogTemplate(); + + DialogItemTemplate* GetItem(WORD wId); + DialogItemTemplate* GetItemByIdx(DWORD i); + void RemoveItem(WORD wId); + void SetFont(char* szFaceName, WORD wFontSize); + void AddItem(DialogItemTemplate item); + void MoveAllAndResize(short x, short y); + void PixelsToDlgUnits(short& x, short& y); + void DlgUnitsToPixels(short& x, short& y); + BYTE* Save(DWORD& dwSize); + DWORD GetSize(); + +private: + bool m_bExtended; + + DWORD m_dwHelpId; // Extended only + + short m_sX; + short m_sY; + short m_sWidth; + short m_sHeight; + DWORD m_dwExtStyle; + DWORD m_dwStyle; + + char* m_szMenu; + char* m_szClass; + char* m_szTitle; + + // Only if DS_FONT style is set + short m_sFontSize; + short m_sFontWeight; // Extended only + bool m_bItalic; // Extended only + char* m_szFont; + + // Items vector + vector m_vItems; +}; + +#endif // !defined(AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_) diff --git a/Source/Makefile b/Source/Makefile new file mode 100644 index 00000000..ca54a4d4 --- /dev/null +++ b/Source/Makefile @@ -0,0 +1,74 @@ +# +# This makefile for mingw32 by Nels. Thanks, Nels +# +# +# -- Subdirs -- +SUBDIRS = exehead + +# -- Objects and source files -- +SRCS = crc32.c build.cpp exedata.cpp makenssi.cpp script.cpp tokens.cpp util.cpp ResourceEditor.cpp DialogTemplate.cpp ./zlib/deflate.c ./zlib/trees.c ./bzip2/blocksort.c ./bzip2/bzlib.c ./bzip2/compress.c ./bzip2/huffman.c +OBJS = build.o exedata.o makenssi.o script.o tokens.o util.o script1.res crc32.o ResourceEditor.o DialogTemplate.o deflate.o trees.o blocksort.o bzlib.o compress.o huffman.o +LIBS = -lgdi32 -lversion + +# -- Programs -- +MAKE = make +CC = gcc +RC = windres +RM = del + +# -- Compilers and linker flags -- +DEFINES = -DWIN32 -D_WINDOWS_ +CFLAGS = -O2 $(DEFINES) +CPPFLAGS = -O2 -fvtable-thunks $(DEFINES) +LFLAGS = -s +RCFLAGS = --input-format rc --output-format coff + +all : subdirs makensis + +subdirs: $(SUBDIRS) + +$(SUBDIRS):: + $(MAKE) -C $@ all + +makensis : $(OBJS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LFLAGS) -o makensis.exe $(OBJS) $(LIBS) + +# -- Dependencies -- +build.o : build.cpp ./zlib/zlib.h ./exehead/config.h ./exehead/fileform.h ./exehead/resource.h exedata.h build.h util.h strlist.h lineparse.h ResourceEditor.h Makefile +exedata.o : exedata.cpp exedata.h ./exehead/Release/bitmap1.h ./exehead/Release/bitmap2.h ./exehead/Release/icon.h ./exehead/Release/unicon.h ./exehead/Release/exehead.h Makefile +makenssi.o : makenssi.cpp build.h util.h exedata.h strlist.h lineparse.h ./exehead/fileform.h ./exehead/config.h Makefile +script.o : script.cpp tokens.h build.h util.h exedata.h strlist.h lineparse.h ResourceEditor.h DialogTemplate.h ./exehead/resource.h ./exehead/fileform.h ./exehead/config.h Makefile +tokens.o : tokens.cpp build.h tokens.h Makefile +util.o : util.cpp ./exehead/fileform.h util.h strlist.h ResourceEditor.h Makefile +crc32.o : crc32.c ./exehead/config.h Makefile +ResourceEditor.o : ResourceEditor.cpp +DialogTemplate.o : DialogTemplate.cpp + +# -- Special command line for the resource file -- +script1.res : script1.rc resource.h Makefile + $(RC) $(RCFLAGS) -o script1.res -i script1.rc + +# -- Special command lines for zlib -- +deflate.o : ./zlib/deflate.c ./zlib/deflate.h ./zlib/zutil.h ./zlib/zlib.h ./zlib/zconf.h Makefile ./exehead/config.h + $(CC) $(CFLAGS) -c ./zlib/deflate.c -o deflate.o + +trees.o : ./zlib/trees.c ./zlib/deflate.h ./zlib/zutil.h ./zlib/zlib.h ./zlib/zconf.h Makefile ./exehead/config.h + $(CC) $(CFLAGS) -c ./zlib/trees.c -o trees.o + +# -- Special command lines for bzip2 -- +blocksort.o : ./bzip2/blocksort.c ./bzip2/bzlib.h ./bzip2/bzlib_private.h ./exehead/config.h + $(CC) $(CFLAGS) -c ./bzip2/blocksort.c -o blocksort.o +bzlib.o : ./bzip2/bzlib.c ./bzip2/bzlib.h ./bzip2/bzlib_private.h ./exehead/config.h + $(CC) $(CFLAGS) -c ./bzip2/bzlib.c -o bzlib.o +compress.o : ./bzip2/compress.c ./bzip2/bzlib.h ./bzip2/bzlib_private.h ./exehead/config.h + $(CC) $(CFLAGS) -c ./bzip2/compress.c -o compress.o +huffman.o : ./bzip2/huffman.c ./bzip2/bzlib.h ./bzip2/bzlib_private.h ./exehead/config.h + $(CC) $(CFLAGS) -c ./bzip2/huffman.c -o huffman.o + + +# -- Clean script -- +clean :: + $(MAKE) -C exehead clean + $(RM) *.o + $(RM) script1.res + $(RM) makensis.exe diff --git a/Source/Release/Script1.res b/Source/Release/Script1.res new file mode 100644 index 00000000..59f1e0a5 Binary files /dev/null and b/Source/Release/Script1.res differ diff --git a/Source/Release/vc60.idb b/Source/Release/vc60.idb new file mode 100644 index 00000000..954d0534 --- /dev/null +++ b/Source/Release/vc60.idb @@ -0,0 +1 @@ +Microsoft C/C++ program database 2.00 diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp new file mode 100644 index 00000000..3aa0852a --- /dev/null +++ b/Source/ResourceEditor.cpp @@ -0,0 +1,780 @@ +/* + Copyright (C) 2002 Amir Szekely + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#define RESOURCE_EDITOR_NO_API +#include "ResourceEditor.h" + +////////////////////////////////////////////////////////////////////// +// Utilities +////////////////////////////////////////////////////////////////////// + +#define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn +#define RALIGN(dwToAlign, dwAlignOn) ((dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn) + +void *operator new(size_t size) { + void *p = malloc(size); + if (!p) + throw bad_alloc(); + return p; +} +void operator delete(void *p) { + if (p) free(p); +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// CResourceEditor +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize) { + // Copy the data + m_iSize = iSize; + m_pbPE = new BYTE[iSize]; + CopyMemory(m_pbPE, pbPE, iSize); + + // Get dos header + m_dosHeader = (PIMAGE_DOS_HEADER)m_pbPE; + if (m_dosHeader->e_magic != IMAGE_DOS_SIGNATURE) + throw runtime_error("PE file contains invalid DOS header"); + + // Get NT headers + m_ntHeaders = (PIMAGE_NT_HEADERS)(m_pbPE + m_dosHeader->e_lfanew); + if (m_ntHeaders->Signature != IMAGE_NT_SIGNATURE) + throw runtime_error("PE file missing NT signature"); + + // No check sum support yet... + if (m_ntHeaders->OptionalHeader.CheckSum) + throw runtime_error("CResourceEditor doesn't yet support check sum"); + + // Get resource section virtual address + m_dwResourceSectionVA = m_ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + // Pointer to the sections headers array + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders); + + // Find resource section index in the array + for (m_dwResourceSectionIndex = 0; m_dwResourceSectionIndex < m_ntHeaders->FileHeader.NumberOfSections; m_dwResourceSectionIndex++) + if (m_dwResourceSectionVA == sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) + break; + + // No resource section... + if (m_dwResourceSectionIndex == m_ntHeaders->FileHeader.NumberOfSections) + throw runtime_error("PE file doesn't contain any resource section"); + + // Pointer to section data, the first resource directory + PRESOURCE_DIRECTORY rdRoot = PRESOURCE_DIRECTORY(m_pbPE + sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData); + + // Scan the resource directory + m_cResDir = ScanDirectory(rdRoot, rdRoot); +} + +CResourceEditor::~CResourceEditor() { + if (m_pbPE) + delete [] m_pbPE; + if (m_cResDir) { + m_cResDir->Destroy(); + delete m_cResDir; + } +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +// Adds/Replaces/Removes a resource. +// If lpData is 0 UpdateResource removes the resource. +void CResourceEditor::UpdateResource(char* szType, char* szName, WORD wLanguage, BYTE* lpData, DWORD dwSize) { + CResourceDirectory* nameDir = 0; + CResourceDirectory* langDir = 0; + CResourceDataEntry* data = 0; + IMAGE_RESOURCE_DIRECTORY rd = {0, time(0),}; + int iTypeIdx, iNameIdx, iLangIdx; + + iTypeIdx = m_cResDir->Find(szType); + if (iTypeIdx > -1) { + nameDir = m_cResDir->GetEntry(iTypeIdx)->GetSubDirectory(); + iNameIdx = nameDir->Find(szName); + if (iNameIdx > -1) { + langDir = nameDir->GetEntry(iNameIdx)->GetSubDirectory(); + iLangIdx = langDir->Find(wLanguage); + if (iLangIdx > -1) { + data = langDir->GetEntry(iLangIdx)->GetDataEntry(); + } + } + } + + if (lpData) { + // Replace/Add the resource + if (data) { + data->SetData(lpData, dwSize); + return; + } + + if (!nameDir) { + // Type doesn't yet exist + nameDir = new CResourceDirectory(&rd); + m_cResDir->AddEntry(new CResourceDirectoryEntry(szType, nameDir)); + } + if (!langDir) { + // Name doesn't yet exist + langDir = new CResourceDirectory(&rd); + nameDir->AddEntry(new CResourceDirectoryEntry(szName, langDir)); + } + if (!data) { + // Language doesn't yet exist, hence data nither + data = new CResourceDataEntry(lpData, dwSize); + langDir->AddEntry(new CResourceDirectoryEntry(MAKEINTRESOURCE(wLanguage), data)); + } + } + else if (data) { + // Delete the resource + delete data; + delete langDir->GetEntry(iLangIdx); + langDir->RemoveEntry(iLangIdx); + // Delete directories holding the resource if empty + if (!langDir->CountEntries()) { + delete langDir; + delete nameDir->GetEntry(iNameIdx); + nameDir->RemoveEntry(iNameIdx); + if (!nameDir->CountEntries()) { + delete nameDir; + delete m_cResDir->GetEntry(iTypeIdx); + m_cResDir->RemoveEntry(iTypeIdx); + } + } + } +} + +void CResourceEditor::UpdateResource(WORD szType, char* szName, WORD wLanguage, BYTE* lpData, DWORD dwSize) { + UpdateResource(MAKEINTRESOURCE(szType), szName, wLanguage, lpData, dwSize); +} + +void CResourceEditor::UpdateResource(char* szType, WORD szName, WORD wLanguage, BYTE* lpData, DWORD dwSize) { + UpdateResource(szType, MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize); +} + +void CResourceEditor::UpdateResource(WORD szType, WORD szName, WORD wLanguage, BYTE* lpData, DWORD dwSize) { + UpdateResource(MAKEINTRESOURCE(szType), MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize); +} + +// Returns a copy of the resource requested +// Returns 0 if resource can't be found +BYTE* CResourceEditor::GetResource(char* szType, char* szName, WORD wLanguage) { + CResourceDirectory* nameDir = 0; + CResourceDirectory* langDir = 0; + CResourceDataEntry* data = 0; + + int i = m_cResDir->Find(szType); + if (i > -1) { + nameDir = m_cResDir->GetEntry(i)->GetSubDirectory(); + i = nameDir->Find(szName); + if (i > -1) { + langDir = nameDir->GetEntry(i)->GetSubDirectory(); + i = langDir->Find(wLanguage); + if (i > -1) { + data = langDir->GetEntry(i)->GetDataEntry(); + } + } + } + + if (data) { + BYTE* toReturn = new BYTE[data->GetSize()]; + CopyMemory(toReturn, data->GetData(), data->GetSize()); + return toReturn; + } + else + return 0; +} + +// Saves the edited PE into a buffer and returns it. +BYTE* CResourceEditor::Save(DWORD &dwSize) { + int i; + + DWORD dwRsrcSize = m_cResDir->GetSize(); // Size of new resource section + DWORD dwRsrcSizeAligned = RALIGN(dwRsrcSize, m_ntHeaders->OptionalHeader.FileAlignment); // Align it to FileAlignment + + // Calculate the total new PE size + dwSize = m_iSize - IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData + dwRsrcSizeAligned; + + // Allocate memory for the new PE + BYTE* pbNewPE = new BYTE[dwSize]; + // Fill it with zeros + ZeroMemory(pbNewPE, dwSize); + + BYTE* seeker = pbNewPE; + BYTE* oldSeeker = m_pbPE; + + // Copy old headers + CopyMemory(seeker, oldSeeker, m_ntHeaders->OptionalHeader.SizeOfHeaders); + + // Get new nt headers pointer + PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(pbNewPE + PIMAGE_DOS_HEADER(pbNewPE)->e_lfanew); + // Get a pointer to the new section headers + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); + + // Copy everything between the headers and the sections (Borland stuff...) + CopyMemory(seeker, oldSeeker, sectionHeadersArray[0].PointerToRawData-ntHeaders->OptionalHeader.SizeOfHeaders); + + // Skip some stuff between the headers and the sections (which is??? ask Borland...) + seeker += sectionHeadersArray[0].PointerToRawData-ntHeaders->OptionalHeader.SizeOfHeaders; + oldSeeker += sectionHeadersArray[0].PointerToRawData-ntHeaders->OptionalHeader.SizeOfHeaders; + + // Skip the headers + seeker += ntHeaders->OptionalHeader.SizeOfHeaders; + oldSeeker += m_ntHeaders->OptionalHeader.SizeOfHeaders; + + // Copy all of the section up until the resource section + DWORD dwSectionsSize = 0; + for (i = 0; i < m_dwResourceSectionIndex; i++) + dwSectionsSize += sectionHeadersArray[i].SizeOfRawData; + + CopyMemory(seeker, oldSeeker, dwSectionsSize); + seeker += dwSectionsSize; + oldSeeker += dwSectionsSize; + + // Skip the resource section in the old PE seeker. + oldSeeker += sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData; + + // Save the old virtual size of the resource section + DWORD dwOldVirtualSize = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize; + + // Set the new size of the resource section (size aligned to FileAlignment) + sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = dwRsrcSizeAligned; + // Set the virtual size as well (in memory) + sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = RALIGN(dwRsrcSize, ntHeaders->OptionalHeader.SectionAlignment); + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize; + + // Set the new virtual size of the image + DWORD old = ntHeaders->OptionalHeader.SizeOfImage; + ntHeaders->OptionalHeader.SizeOfImage = RALIGN(ntHeaders->OptionalHeader.SizeOfHeaders, ntHeaders->OptionalHeader.SectionAlignment); + for (int j = 0; j < ntHeaders->FileHeader.NumberOfSections; j++) + ntHeaders->OptionalHeader.SizeOfImage += RALIGN(sectionHeadersArray[j].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment); + + // Set the new AddressOfEntryPoint if needed + if (ntHeaders->OptionalHeader.AddressOfEntryPoint > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) + ntHeaders->OptionalHeader.AddressOfEntryPoint += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; + + // Set the new BaseOfCode if needed + if (ntHeaders->OptionalHeader.BaseOfCode > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) + ntHeaders->OptionalHeader.BaseOfCode += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; + + // Set the new BaseOfData if needed + if (ntHeaders->OptionalHeader.BaseOfData > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) + ntHeaders->OptionalHeader.BaseOfData += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; + + // Refresh the headers of the sections that come after the resource section, and the data directory + for (i++; i < ntHeaders->FileHeader.NumberOfSections; i++) { + sectionHeadersArray[i].PointerToRawData -= IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData; + sectionHeadersArray[i].PointerToRawData += dwRsrcSizeAligned; + int secInDataDir = 0; + for (int j = 0; j < ntHeaders->OptionalHeader.NumberOfRvaAndSizes; j++) + if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) + secInDataDir = j; + sectionHeadersArray[i].VirtualAddress -= RALIGN(dwOldVirtualSize, ntHeaders->OptionalHeader.SectionAlignment); + sectionHeadersArray[i].VirtualAddress += RALIGN(sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment); + if (secInDataDir) + ntHeaders->OptionalHeader.DataDirectory[secInDataDir].VirtualAddress = sectionHeadersArray[i].VirtualAddress; + } + + // Write the resource section + WriteRsrcSec(seeker); + // Advance the pointer + seeker += dwRsrcSizeAligned; + + // Write all the sections that come after the resource section + dwSectionsSize = 0; + for (i = m_dwResourceSectionIndex + 1; i < m_ntHeaders->FileHeader.NumberOfSections; i++) + dwSectionsSize += sectionHeadersArray[i].SizeOfRawData; + + CopyMemory(seeker, oldSeeker, dwSectionsSize); + + /********************************************************** + * To add checksum to the header use MapFileAndCheckSum + **********************************************************/ + + return pbNewPE; +} + +////////////////////////////////////////////////////////////////////// +// Private Methods +////////////////////////////////////////////////////////////////////// + +// This function scans a give resource directory and return a CResourceDirectory object +// rdRoot must point to the root directory of the resource section +CResourceDirectory* CResourceEditor::ScanDirectory(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan) { + // Create CResourceDirectory from rdToScan + CResourceDirectory* rdc = new CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY(rdToScan)); + char* szName; + PIMAGE_RESOURCE_DATA_ENTRY rde; + + // Go through all entries of this resource directory + for (int i = 0; i < rdToScan->Header.NumberOfNamedEntries + rdToScan->Header.NumberOfIdEntries; i++) { + // If this entry points to data entry get a pointer to it + if (!rdToScan->Entries[i].DataIsDirectory) + rde = PIMAGE_RESOURCE_DATA_ENTRY(rdToScan->Entries[i].OffsetToData + (BYTE*)rdRoot); + + // If this entry has a name, translate it from Unicode + if (rdToScan->Entries[i].NameIsString) { + PIMAGE_RESOURCE_DIR_STRING_U rds = PIMAGE_RESOURCE_DIR_STRING_U(rdToScan->Entries[i].NameOffset + (char*)rdRoot); + + szName = new char[rds->Length+1]; + WideCharToMultiByte(CP_ACP, 0, rds->NameString, rds->Length, szName, rds->Length, 0, 0); + szName[rds->Length] = 0; + } + // Else, set the name to this entry's id + else + szName = MAKEINTRESOURCE(rdToScan->Entries[i].Id); + + if (rdToScan->Entries[i].DataIsDirectory) + rdc->AddEntry( + new CResourceDirectoryEntry( + szName, + ScanDirectory( + rdRoot, + PRESOURCE_DIRECTORY(rdToScan->Entries[i].OffsetToDirectory + (BYTE*)rdRoot) + ) + ) + ); + else + rdc->AddEntry( + new CResourceDirectoryEntry( + szName, + new CResourceDataEntry( + (BYTE*)rdRoot + rde->OffsetToData - m_dwResourceSectionVA, + rde->Size, + rde->CodePage + ) + ) + ); + + // Delete the dynamicly allocated name if it is a name and not an id + if (!IS_INTRESOURCE(szName)) + delete [] szName; + } + + return rdc; +} + +// This function writes into a given place in memory (pbRsrcSec) the edited resource section +void CResourceEditor::WriteRsrcSec(BYTE* pbRsrcSec) { + BYTE* seeker = pbRsrcSec; + + queue qDirs; // Used to scan the tree by level + queue qDataEntries; // Used for writing the data entries + queue qDataEntries2; // Used for writing raw resources data + queue qStrings; // Used for writing resources' names + + qDirs.push(m_cResDir); + + while (!qDirs.empty()) { + CResourceDirectory* crd = qDirs.front(); + + CopyMemory(seeker, &crd->GetInfo(), sizeof(IMAGE_RESOURCE_DIRECTORY)); + crd->m_dwWrittenAt = DWORD(seeker); + seeker += sizeof(IMAGE_RESOURCE_DIRECTORY); + + for (int i = 0; i < crd->CountEntries(); i++) { + if (crd->GetEntry(i)->HasName()) + qStrings.push(crd->GetEntry(i)); + if (crd->GetEntry(i)->IsDataDirectory()) + qDirs.push(crd->GetEntry(i)->GetSubDirectory()); + else { + qDataEntries.push(crd->GetEntry(i)->GetDataEntry()); + qDataEntries2.push(crd->GetEntry(i)->GetDataEntry()); + } + + IMAGE_RESOURCE_DIRECTORY_ENTRY rDirE = {0,}; + rDirE.DataIsDirectory = crd->GetEntry(i)->IsDataDirectory(); + rDirE.Id = (crd->GetEntry(i)->HasName()) ? 0 : crd->GetEntry(i)->GetId(); + rDirE.NameIsString = (crd->GetEntry(i)->HasName()) ? 1 : 0; + + CopyMemory(seeker, &rDirE, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); + crd->GetEntry(i)->m_dwWrittenAt = DWORD(seeker); + seeker += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); + } + qDirs.pop(); + } + + /* + * Write IMAGE_RESOURCE_DATA_ENTRYs. + */ + while (!qDataEntries.empty()) { + CResourceDataEntry* cRDataE = qDataEntries.front(); + IMAGE_RESOURCE_DATA_ENTRY rDataE = {0,}; + rDataE.CodePage = cRDataE->GetCodePage(); + rDataE.Size = cRDataE->GetSize(); + + CopyMemory(seeker, &rDataE, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); + cRDataE->m_dwWrittenAt = DWORD(seeker); + seeker += sizeof(IMAGE_RESOURCE_DATA_ENTRY); + + qDataEntries.pop(); + } + + /* + * Write strings + */ + while (!qStrings.empty()) { + CResourceDirectoryEntry* cRDirE = qStrings.front(); + + PIMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->NameOffset = DWORD(seeker) - DWORD(pbRsrcSec); + + char* szName = cRDirE->GetName(); + WORD iLen = lstrlen(szName); + WCHAR* szwName = new WCHAR[iLen]; + MultiByteToWideChar(CP_ACP, 0, szName, iLen, szwName, iLen); + CopyMemory(seeker, &iLen, sizeof(WORD)); + seeker += sizeof(WORD); + CopyMemory(seeker, szwName, iLen*sizeof(WCHAR)); + seeker += iLen*sizeof(WCHAR); + + // Even though the number of chars is predefined a null termination is required + *(WORD*)seeker = 0; + seeker += sizeof(WORD); + + delete [] szName; + delete [] szwName; + + qStrings.pop(); + } + + /* + * Write raw resource data and set offsets in IMAGE_RESOURCE_DATA_ENTRYs. + */ + while (!qDataEntries2.empty()) { + CResourceDataEntry* cRDataE = qDataEntries2.front(); + CopyMemory(seeker, cRDataE->GetData(), cRDataE->GetSize()); + PIMAGE_RESOURCE_DATA_ENTRY(cRDataE->m_dwWrittenAt)->OffsetToData = seeker - pbRsrcSec + m_dwResourceSectionVA; + + seeker += RALIGN(cRDataE->GetSize(), 8); + + qDataEntries2.pop(); + } + + /* + * Set all of the directory entries offsets. + */ + SetOffsets(m_cResDir, DWORD(pbRsrcSec)); +} + +// Sets the offsets in directory entries +void CResourceEditor::SetOffsets(CResourceDirectory* resDir, DWORD newResDirAt) { + for (int i = 0; i < resDir->CountEntries(); i++) { + if (resDir->GetEntry(i)->IsDataDirectory()) { + PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->DataIsDirectory = 1; + PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->OffsetToDirectory = resDir->GetEntry(i)->GetSubDirectory()->m_dwWrittenAt - newResDirAt; + SetOffsets(resDir->GetEntry(i)->GetSubDirectory(), newResDirAt); + } + else { + PIMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt)->OffsetToData = resDir->GetEntry(i)->GetDataEntry()->m_dwWrittenAt - newResDirAt; + } + } +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// CResourceDirectory +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResourceDirectory::CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY prd) { + m_rdDir = *prd; + m_rdDir.NumberOfIdEntries = 0; + m_rdDir.NumberOfNamedEntries = 0; +} + +CResourceDirectory::~CResourceDirectory() { +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +IMAGE_RESOURCE_DIRECTORY CResourceDirectory::GetInfo() { + return m_rdDir; +} + +CResourceDirectoryEntry* CResourceDirectory::GetEntry(int i) { + if (m_vEntries.size() < i || i < 0) + return 0; + return m_vEntries[i]; +} + +// This function inserts a new directory entry +// It also keeps the directory entries sorted +void CResourceDirectory::AddEntry(CResourceDirectoryEntry* entry) { + int i = 0; + if (entry->HasName()) { + char* szEntName = entry->GetName(); + for (i = 0; i < m_rdDir.NumberOfIdEntries; i++) { + char* szName = m_vEntries[i]->GetName(); + int cmp = lstrcmp(szName, szEntName); + delete [] szName; + if (cmp == 0) { + delete [] szEntName; + return; + } + if (cmp > 0) + break; + } + delete [] szEntName; + m_rdDir.NumberOfNamedEntries++; + } + else { + for (i = m_rdDir.NumberOfNamedEntries; i < m_rdDir.NumberOfNamedEntries+m_rdDir.NumberOfIdEntries; i++) { + if (m_vEntries[i]->GetId() == entry->GetId()) + return; + if (m_vEntries[i]->GetId() > entry->GetId()) + break; + } + m_rdDir.NumberOfIdEntries++; + } + m_vEntries.insert(m_vEntries.begin() + i, entry); +} + +void CResourceDirectory::RemoveEntry(int i) { + if (m_vEntries[i]->HasName()) + m_rdDir.NumberOfNamedEntries--; + else + m_rdDir.NumberOfIdEntries--; + m_vEntries.erase(m_vEntries.begin() + i); +} + +int CResourceDirectory::CountEntries() { + return m_vEntries.size(); +} + +// Returns the index of a directory entry with the specified name +// Name can be a string or an id +// Returns -1 if can not be found +int CResourceDirectory::Find(char* szName) { + if (IS_INTRESOURCE(szName)) + return Find(WORD(szName)); + else + if (szName[0] == '#') + return Find(atol(szName+1)); + + for (int i = 0; i < m_vEntries.size(); i++) { + if (!m_vEntries[i]->HasName()) + continue; + + char* szEntName = m_vEntries[i]->GetName(); + int cmp = lstrcmp(szName, szEntName); + delete [] szEntName; + + if (!cmp) + return i; + } + + return -1; +} + +// Returns the index of a directory entry with the specified id +// Returns -1 if can not be found +int CResourceDirectory::Find(WORD wId) { + for (int i = 0; i < m_vEntries.size(); i++) { + if (m_vEntries[i]->HasName()) + continue; + + if (wId == m_vEntries[i]->GetId()) + return i; + } + + return -1; +} + +// Get the size of this resource directory (including all of its children) +DWORD CResourceDirectory::GetSize() { + DWORD dwSize = sizeof(IMAGE_RESOURCE_DIRECTORY); + for (int i = 0; i < m_vEntries.size(); i++) { + dwSize += sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); + if (m_vEntries[i]->HasName()) + dwSize += sizeof(IMAGE_RESOURCE_DIR_STRING_U) + m_vEntries[i]->GetNameLength()*sizeof(WCHAR); + if (m_vEntries[i]->IsDataDirectory()) + dwSize += m_vEntries[i]->GetSubDirectory()->GetSize(); + else { + DWORD dwAligned = m_vEntries[i]->GetDataEntry()->GetSize(); + ALIGN(dwAligned, 8); + dwSize += sizeof(IMAGE_RESOURCE_DATA_ENTRY) + dwAligned; + } + } + return dwSize; +} + +// Destroys this directory and all of its children +void CResourceDirectory::Destroy() { + for (int i = 0; i < m_vEntries.size(); i++) { + if (m_vEntries[i]->IsDataDirectory()) { + m_vEntries[i]->GetSubDirectory()->Destroy(); + delete m_vEntries[i]->GetSubDirectory(); + } + else + delete m_vEntries[i]->GetDataEntry(); + } +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// CResourceDirectoryEntry +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDirectory* rdSubDir) { + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; + m_wId = WORD(szName); + } + else { + m_bHasName = true; + m_szName = new char[lstrlen(szName)]; + lstrcpy(m_szName, szName); + } + m_bIsDataDirectory = true; + m_rdSubDir = rdSubDir; +} + +CResourceDirectoryEntry::CResourceDirectoryEntry(char* szName, CResourceDataEntry* rdeData) { + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; + m_wId = WORD(szName); + } + else { + m_bHasName = true; + m_szName = new char[lstrlen(szName)]; + lstrcpy(m_szName, szName); + } + m_bIsDataDirectory = false; + m_rdeData = rdeData; +} + +CResourceDirectoryEntry::~CResourceDirectoryEntry() { + if (m_szName && m_bHasName) + delete [] m_szName; +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +bool CResourceDirectoryEntry::HasName() { + return m_bHasName; +} + +// Don't forget to free the memory used by the string after usage! +char* CResourceDirectoryEntry::GetName() { + if (!m_bHasName) + return 0; + char* szName = 0; + szName = new char[lstrlen(m_szName)]; + lstrcpy(szName, m_szName); + return szName; +} + +int CResourceDirectoryEntry::GetNameLength() { + return lstrlen(m_szName); +} + +WORD CResourceDirectoryEntry::GetId() { + if (m_bHasName) + return 0; + return m_wId; +} + +bool CResourceDirectoryEntry::IsDataDirectory() { + return m_bIsDataDirectory; +} + +CResourceDirectory* CResourceDirectoryEntry::GetSubDirectory() { + if (!m_bIsDataDirectory) + return NULL; + return m_rdSubDir; +} + +CResourceDataEntry* CResourceDirectoryEntry::GetDataEntry() { + if (m_bIsDataDirectory) + return NULL; + return m_rdeData; +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// CResourceDataEntry +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResourceDataEntry::CResourceDataEntry(BYTE* pbData, DWORD dwSize, DWORD dwCodePage) { + m_pbData = 0; + SetData(pbData, dwSize, dwCodePage); +} + +CResourceDataEntry::~CResourceDataEntry() { + if (m_pbData) + delete [] m_pbData; +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +// To save memory this function doesn't give you a copy of the data +// Don't mess with the data returned from this function! +BYTE* CResourceDataEntry::GetData() { + return m_pbData; +} + +void CResourceDataEntry::SetData(BYTE* pbData, DWORD dwSize) { + SetData(pbData, dwSize, m_dwCodePage); +} + +void CResourceDataEntry::SetData(BYTE* pbData, DWORD dwSize, DWORD dwCodePage) { + if (m_pbData) delete [] m_pbData; + m_pbData = new BYTE[dwSize]; + CopyMemory(m_pbData, pbData, dwSize); + m_dwSize = dwSize; + m_dwCodePage = dwCodePage; +} + +DWORD CResourceDataEntry::GetSize() { + return m_dwSize; +} + +DWORD CResourceDataEntry::GetCodePage() { + return m_dwCodePage; +} \ No newline at end of file diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h new file mode 100644 index 00000000..3233180e --- /dev/null +++ b/Source/ResourceEditor.h @@ -0,0 +1,167 @@ +/* + Copyright (C) 2002 Amir Szekely + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_) +#define AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifdef RESOURCE_EDITOR_NO_API + +#include +#include +#include +#include +#include + +#endif // #ifdef RESOURCE_EDITOR_NO_API + +#include +using namespace std; + +class CResourceDirectory; +class CResourceDirectoryEntry; +class CResourceDataEntry; + +// Resource directory with entries +typedef struct RESOURCE_DIRECTORY { + IMAGE_RESOURCE_DIRECTORY Header; + IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1]; +} *PRESOURCE_DIRECTORY; + +class CResourceEditor { +public: + CResourceEditor(BYTE* pbPE, int iSize); + virtual ~CResourceEditor(); + + void UpdateResource(char* szType, char* szName, WORD wLanguage, BYTE* lpData, DWORD dwSize); + void UpdateResource(WORD szType, char* szName, WORD wLanguage, BYTE* lpData, DWORD dwSize); + void UpdateResource(char* szType, WORD szName, WORD wLanguage, BYTE* lpData, DWORD dwSize); + void UpdateResource(WORD szType, WORD szName, WORD wLanguage, BYTE* lpData, DWORD dwSize); + BYTE* GetResource(char* szType, char* szName, WORD wLanguage); + + BYTE* Save(DWORD &dwSize); + +private: + BYTE* m_pbPE; + int m_iSize; + + PIMAGE_DOS_HEADER m_dosHeader; + PIMAGE_NT_HEADERS m_ntHeaders; + + DWORD m_dwResourceSectionIndex; + DWORD m_dwResourceSectionVA; + + CResourceDirectory* m_cResDir; + + CResourceDirectory* ScanDirectory(PRESOURCE_DIRECTORY rdRoot, PRESOURCE_DIRECTORY rdToScan); + + void WriteRsrcSec(BYTE* pbRsrcSec); + void SetOffsets(CResourceDirectory* resDir, DWORD newResDirAt); +}; + +#ifdef RESOURCE_EDITOR_NO_API + +class CResourceDirectory { +public: + CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY prd); + virtual ~CResourceDirectory(); + + IMAGE_RESOURCE_DIRECTORY GetInfo(); + + CResourceDirectoryEntry* GetEntry(int i); + void AddEntry(CResourceDirectoryEntry* entry); + void RemoveEntry(int i); + int CountEntries(); + int Find(char* szName); + int Find(WORD wId); + + DWORD GetSize(); + + void Destroy(); + + DWORD m_dwWrittenAt; + +private: + IMAGE_RESOURCE_DIRECTORY m_rdDir; + vector m_vEntries; +}; + +class CResourceDirectoryEntry { +public: + CResourceDirectoryEntry(char* szName, CResourceDirectory* rdSubDir); + CResourceDirectoryEntry(char* szName, CResourceDataEntry* rdeData); + virtual ~CResourceDirectoryEntry(); + + bool HasName(); + char* GetName(); + int GetNameLength(); + + WORD GetId(); + + bool IsDataDirectory(); + CResourceDirectory* GetSubDirectory(); + + CResourceDataEntry* GetDataEntry(); + + DWORD m_dwWrittenAt; + +private: + bool m_bHasName; + union { + char* m_szName; + WORD m_wId; + }; + + bool m_bIsDataDirectory; + union { + CResourceDirectory* m_rdSubDir; + CResourceDataEntry* m_rdeData; + }; +}; + +class CResourceDataEntry { +public: + CResourceDataEntry(BYTE* pbData, DWORD dwSize, DWORD dwCodePage = 0); + ~CResourceDataEntry(); + + BYTE* GetData(); + + void SetData(BYTE* pbData, DWORD dwSize); + void SetData(BYTE* pbData, DWORD dwSize, DWORD dwCodePage); + + DWORD GetSize(); + DWORD GetCodePage(); + + DWORD m_dwWrittenAt; + +private: + BYTE* m_pbData; + DWORD m_dwSize; + DWORD m_dwCodePage; +}; + +#endif // #ifdef RESOURCE_EDITOR_NO_API + +#endif // !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_) diff --git a/Source/Script1.rc b/Source/Script1.rc new file mode 100644 index 00000000..6e7f7b13 --- /dev/null +++ b/Source/Script1.rc @@ -0,0 +1,72 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Source/afxres.h b/Source/afxres.h new file mode 100644 index 00000000..b3cc0671 --- /dev/null +++ b/Source/afxres.h @@ -0,0 +1,5 @@ +#include + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/Source/build.cpp b/Source/build.cpp new file mode 100644 index 00000000..9ce37b4f --- /dev/null +++ b/Source/build.cpp @@ -0,0 +1,1971 @@ +#include +#include +#include "exehead/config.h" +#include "exehead/fileform.h" + +#include "exedata.h" + +#include "build.h" +#include "util.h" + +#include "ResourceEditor.h" +#include "exehead/resource.h" + +extern const char *NSIS_VERSION; + +void CEXEBuild::define(const char *p, const char *v) +{ + definedlist.add(p,v); +} + + +CEXEBuild::~CEXEBuild() +{ + free(header_data_new); + free(m_unicon_data); +} + +CEXEBuild::CEXEBuild() +{ + display_info=1; + display_script=1; + display_errors=1; + display_warnings=1; + + has_called_write_output=0; + + ns_func.add("",0); // make sure offset 0 is special on these (i.e. never used by a label) + ns_label.add("",0); + + header_data_new=(unsigned char*)malloc(zlib_exeheader_size); + exeheader_size_new=zlib_exeheader_size; + exeheader_size=zlib_exeheader_size; + + if (!header_data_new) + { + ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n",exeheader_size_new); + extern void quit(); quit(); + } + + // Changed by Amir Szekely 31st July 2002 + memcpy(header_data_new,zlib_header_data,zlib_exeheader_size); + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + // Changed by Amir Szekely 11th July 2002 + // No need to check for uninstaller icon if uninstall support is disabled. + if (unicondata_size != icondata_size) + { + ERROR_MSG("Internal compiler error #12345: installer,uninstaller icon size mismatch (%d,%d)\n",icondata_size,unicondata_size); + extern void quit(); quit(); + } +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT + + strcpy(cur_out_path,"$INSTDIR"); + +#ifdef NSIS_CONFIG_LOG + definedlist.add("NSIS_CONFIG_LOG"); +#endif +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + definedlist.add("NSIS_CONFIG_UNINSTALL_SUPPORT"); +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE + definedlist.add("NSIS_CONFIG_LICENSEPAGE"); +#endif +#ifdef NSIS_CONFIG_SILENT_SUPPORT + definedlist.add("NSIS_CONFIG_SILENT_SUPPORT"); +#endif +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + definedlist.add("NSIS_CONFIG_COMPRESSION_SUPPORT"); +#endif +#ifdef NSIS_ZLIP_COMPRESS_WHOLE + definedlist.add("NSIS_ZLIP_COMPRESS_WHOLE"); +#endif +#ifdef NSIS_BZIP2_COMPRESS_WHOLE + definedlist.add("NSIS_BZIP2_COMPRESS_WHOLE"); +#endif + { + char b[123]; + wsprintf(b,"%d",NSIS_COMPRESS_BZIP2_LEVEL); + definedlist.add("NSIS_COMPRESS_BZIP2_LEVEL",b); + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + definedlist.add("NSIS_CONFIG_CRC_SUPPORT"); +#endif +#ifdef NSIS_CONFIG_CRC_ANAL + definedlist.add("NSIS_CONFIG_CRC_ANAL"); +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + definedlist.add("NSIS_CONFIG_COMPONENTPAGE"); +#endif +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + definedlist.add("NSIS_CONFIG_VISIBLE_SUPPORT"); +#endif +#ifdef NSIS_CONFIG_XPSTYLE_SUPPORT + definedlist.add("NSIS_CONFIG_XPSTYLE_SUPPORT"); +#endif +#ifdef NSIS_SUPPORT_BGBG + definedlist.add("NSIS_SUPPORT_BGBG"); +#endif +#ifdef NSIS_SUPPORT_ACTIVEXREG + definedlist.add("NSIS_SUPPORT_ACTIVEXREG"); +#endif +#ifdef NSIS_SUPPORT_INTOPTS + definedlist.add("NSIS_SUPPORT_INTOPTS"); +#endif +#ifdef NSIS_SUPPORT_STROPTS + definedlist.add("NSIS_SUPPORT_STROPTS"); +#endif +#ifdef NSIS_SUPPORT_STACK + definedlist.add("NSIS_SUPPORT_STACK"); +#endif +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + definedlist.add("NSIS_SUPPORT_FILEFUNCTIONS"); +#endif +#ifdef NSIS_SUPPORT_FINDFIRST + definedlist.add("NSIS_SUPPORT_FINDFIRST"); +#endif +#ifdef NSIS_SUPPORT_CREATESHORTCUT + definedlist.add("NSIS_SUPPORT_CREATESHORTCUT"); +#endif +#ifdef NSIS_SUPPORT_INIFILES + definedlist.add("NSIS_SUPPORT_INIFILES"); +#endif +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + definedlist.add("NSIS_SUPPORT_REGISTRYFUNCTIONS"); +#endif +#ifdef NSIS_SUPPORT_COPYFILES + definedlist.add("NSIS_SUPPORT_COPYFILES"); +#endif +#ifdef NSIS_SUPPORT_EXECUTE + definedlist.add("NSIS_SUPPORT_EXECUTE"); +#endif +#ifdef NSIS_SUPPORT_SHELLEXECUTE + definedlist.add("NSIS_SUPPORT_SHELLEXECUTE"); +#endif +#ifdef NSIS_SUPPORT_GETDLLVERSION + definedlist.add("NSIS_SUPPORT_GETDLLVERSION"); +#endif +#ifdef NSIS_SUPPORT_GETFILETIME + definedlist.add("NSIS_SUPPORT_GETFILETIME"); +#endif +#ifdef NSIS_SUPPORT_HWNDS + definedlist.add("NSIS_SUPPORT_HWNDS"); +#endif +#ifdef NSIS_SUPPORT_ENVIRONMENT + definedlist.add("NSIS_SUPPORT_ENVIRONMENT"); +#endif +#ifdef NSIS_SUPPORT_RMDIR + definedlist.add("NSIS_SUPPORT_RMDIR"); +#endif +#ifdef NSIS_SUPPORT_FILE + definedlist.add("NSIS_SUPPORT_FILE"); +#endif +#ifdef NSIS_SUPPORT_DELETE + definedlist.add("NSIS_SUPPORT_DELETE"); +#endif +#ifdef NSIS_SUPPORT_RENAME + definedlist.add("NSIS_SUPPORT_RENAME"); +#endif +#ifdef NSIS_SUPPORT_MESSAGEBOX + definedlist.add("NSIS_SUPPORT_MESSAGEBOX"); +#endif +#ifdef NSIS_SUPPORT_CODECALLBACKS + definedlist.add("NSIS_SUPPORT_CODECALLBACKS"); +#endif +#ifdef NSIS_SUPPORT_MOVEONREBOOT + definedlist.add("NSIS_SUPPORT_MOVEONREBOOT"); +#endif + + { + char b[123]; + wsprintf(b,"%d",NSIS_MAX_STRLEN); + definedlist.add("NSIS_MAX_STRLEN",b); + wsprintf(b,"%d",NSIS_MAX_INST_TYPES); + definedlist.add("NSIS_MAX_INST_TYPES",b); + } + + // Added by Amir Szekely 11th July 2002 + // Coded by Robert Rainwater + { + char szNSISDir[NSIS_MAX_STRLEN],*fn2; + GetModuleFileName(NULL,szNSISDir,sizeof(szNSISDir)); + fn2=strrchr(szNSISDir,'\\'); + if(fn2!=NULL) *fn2=0; + definedlist.add("NSISDIR",(char*)szNSISDir); + } + + db_opt_save=db_comp_save=db_full_size=db_opt_save_u=db_comp_save_u=db_full_size_u=0; + + // Added by Amir Szekely 31st July 2002 + compressor = &zlib_comressor; + build_compressor_set = false; +#ifdef NSIS_ZLIB_COMPRESS_WHOLE + build_compress_whole = true; +#else + build_compress_whole = false; +#endif + + cur_entries=&build_entries; + cur_datablock=&build_datablock; + cur_functions=&build_functions; + cur_labels=&build_labels; + + subsection_open_cnt=0; + build_cursection_isfunc=0; + build_cursection=NULL; + // init public data. + build_packname[0]=build_packcmd[0]=build_output_filename[0]=0; + + build_overwrite=0; + build_compress=1; + build_crcchk=1; + build_datesave=1; + build_optimize_datablock=1; + + memset(&build_header,-1,sizeof(build_header)); + + build_header.install_reg_rootkey=0; +#ifdef NSIS_CONFIG_COMPONENTPAGE + build_header.no_custom_instmode_flag=0; +#endif + build_header.num_sections=0; + build_header.common.num_entries=0; +#ifdef NSIS_CONFIG_SILENT_SUPPORT + build_header.common.silent_install=0; +#endif + build_header.common.misc_flags=8; + build_header.common.show_details=0; + build_header.common.lb_bg=RGB(0,0,0); + build_header.common.lb_fg=RGB(0,255,0); + build_header.common.progress_flags=0; + + uninstall_mode=0; + uninstall_size_full=0; + uninstall_size=-1; + + memset(&build_uninst,-1,sizeof(build_uninst)); + build_uninst.common.lb_bg=RGB(0,0,0); + build_uninst.common.lb_fg=RGB(0,255,0); + build_uninst.common.num_entries=0; +#ifdef NSIS_CONFIG_SILENT_SUPPORT + build_uninst.common.silent_install=0; +#endif + build_uninst.code=0; + build_uninst.code_size=-1; + build_uninst.common.show_details=0; + build_uninst.common.misc_flags=0; + + uninstaller_writes_used=0; + + // Changed by Amir Szekely 11th July 2002 + // Changed to fit the new format in which uninstaller icons are saved + m_unicon_data=(unsigned char *)malloc(unicondata_size+3*sizeof(DWORD)); + memcpy(m_unicon_data+3*sizeof(DWORD),unicon_data+22,unicondata_size); + *(DWORD*)m_unicon_data = 1; + *(DWORD*)(DWORD(m_unicon_data) + sizeof(DWORD)) = unicondata_size; + *(DWORD*)(DWORD(m_unicon_data) + 2*sizeof(DWORD)) = 0; + unicondata_size += 3*sizeof(DWORD); + + m_inst_fileused=0; + m_uninst_fileused=0; + + branding_image_found=false; // Added by Amir Szekely 22nd July 2002 +} + +int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); } + +int CEXEBuild::add_string(const char *string) // returns offset in stringblock +{ + if (uninstall_mode) return add_string_uninst(string,1); + return add_string_main(string,1); +} + +// based on Dave Laundon's code +int CEXEBuild::preprocess_string(char *out, const char *in) +{ + static const char VarNames[] = + "HWNDPARENT\0" // 0 + "0\0" // 1 + "1\0" // 2 + "2\0" // 3 + "3\0" // 4 + "4\0" // 5 + "5\0" // 6 + "6\0" // 7 + "7\0" // 8 + "8\0" // 9 + "9\0" // 10 + "R0\0" // 11 + "R1\0" // 12 + "R2\0" // 13 + "R3\0" // 14 + "R4\0" // 15 + "R5\0" // 16 + "R6\0" // 17 + "R7\0" // 18 + "R8\0" // 19 + "R9\0" // 20 + "CMDLINE\0" // 21 everything before here doesn't have trailing slash removal + + "INSTDIR\0" // 22 + "OUTDIR\0" // 23 + "EXEDIR\0" // 24 + "PROGRAMFILES\0" // 25 + "SMPROGRAMS\0" // 26 + "SMSTARTUP\0" // 27 + "DESKTOP\0" // 28 + "STARTMENU\0" // 29 + "QUICKLAUNCH\0" // 30 + "TEMP\0" // 31 + "WINDIR\0" // 32 + "SYSDIR\0" // 33 + ; + + const char *p=in; + while (*p) + { + const char *np=CharNext(p); + + if (np-p > 1) // multibyte char + { + int l=np-p; + while (l--) + { + int i = (unsigned char)*p++; + if (i >= VAR_CODES_START) { + *out++ = (char)255; + } + *out++=i; + } + continue; + } + + int i = (unsigned char)*p; + + p=np; + + // Test for characters extending into the variable codes + if (i >= VAR_CODES_START) { + *out++ = (char)255; + } + else if (i == '$') + { + if (*p == '$') + { + i='$'; + p++; // Can simply convert $$ to $ now + } + else + { + const char *pVarName; + for ( + pVarName = VarNames, i = VAR_CODES_START; + strncmp(pVarName, p, strlen(pVarName)); + pVarName += strlen(pVarName) + 1, i++ + ); + // Found? + if (*pVarName) p += strlen(pVarName); + else // warning should go here + { + char tbuf[64]; + strncpy(tbuf,p,63); + tbuf[63]=0; + if (strstr(tbuf," ")) strstr(tbuf," ")[0]=0; + warning("unknown variable \"%s\" detected, ignoring\n",tbuf); + i = '$'; + } + } + } + *out++=i; + } + *out=0; + return 0; +} + +int CEXEBuild::add_string_main(const char *string, int process) // returns offset (in string block) +{ + if (!*string) return -1; + if (!process) return build_strlist.add(string,2); + + char buf[4096]; + preprocess_string(buf,string); + return build_strlist.add(buf,2); +} + +int CEXEBuild::add_string_uninst(const char *string, int process) // returns offset (in string block) +{ + if (!*string) return -1; + if (!process) return ubuild_strlist.add(string,2); + + char buf[4096]; + preprocess_string(buf,string); + return ubuild_strlist.add(buf,2); +} + +// what it does is, when you pass it the offset of the last item added, it will determine if +// that data is already present in the datablock, and if so, reference it instead (and shorten +// the datablock as necessary). Reduces overhead if you want to add files to a couple places. +// Woo, an optimizing installer generator, now we're styling. + +int CEXEBuild::datablock_optimize(int start_offset) +{ + int this_len = cur_datablock->getlen()-start_offset; + int pos=0; + + if (!build_optimize_datablock) return start_offset; + + char *db=(char*)cur_datablock->get(); + int first_int=*(int*)(db+start_offset); + if (this_len >= 4) while (pos < start_offset) + { + int this_int = *(int*)(db+pos); + if (this_int == first_int && !memcmp(db+pos,db+start_offset,this_len)) + { + db_opt_save+=this_len; + cur_datablock->resize(max(start_offset,pos+this_len)); + return pos; + } + pos += 4 + (this_int&0x7fffffff); + } + + return start_offset; +} + +int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // returns offset +{ + // Changed by Amir Szekely 31st July 2002 + // Ability to change compression methods from within the script + build_compressor_set=true; + + int done=0; + + if (length < 0) + { + ERROR_MSG("Error: add_data() called with length=%d\n",length); + return -1; + } + + if (!dblock) dblock=cur_datablock; + + int st=dblock->getlen(); + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (!build_compress_whole && build_compress) + { + // grow datablock so that there is room to compress into + int bufferlen=length+1024+length/4; // give a nice 25% extra space + dblock->resize(st+bufferlen+sizeof(int)); + + int n; + if ((n=compressor->Init(9)) != C_OK) + { + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%d).\n",n); + extern void quit(); quit(); + } + + compressor->SetNextIn((char*)data, length); + compressor->SetNextOut((char*)dblock->get() + st + sizeof(int), bufferlen); + + compressor->Compress(C_FINISH); + + int used=bufferlen-compressor->GetAvailOut(); + + // never store compressed if output buffer is full + if (compressor->GetAvailOut() && (build_compress == 2 || used < length)) + { + done=1; + dblock->resize(st+used+sizeof(int)); + + *((int*)((char *)dblock->get()+st)) = used|0x80000000; + if (dblock == cur_datablock) + { + int nst=datablock_optimize(st); + if (nst == st) db_comp_save+=length-used; + else st=nst; + } + } + compressor->End(); + } +#endif // NSIS_CONFIG_COMPRESSION_SUPPORT + + if (!done) + { + dblock->resize(st); + dblock->add(&length,sizeof(int)); + dblock->add(data,length); + if (dblock == cur_datablock) + { + st=datablock_optimize(st); + } + } + + if (dblock == cur_datablock) + { + db_full_size += length + sizeof(int); + } + + return st; +} + +int CEXEBuild::add_label(const char *name) +{ + if (!build_cursection && !uninstall_mode) + { + ERROR_MSG("Error: Label declaration not valid outside of function/section\n"); + return PS_ERROR; + } + if ((name[0] >= '0' && name[0] <= '9') || name[0] == '-' || name[0] == ' ' || name[0] == ':') + { + ERROR_MSG("Error: labels must not begin with 0-9, -, :, or a space.\n"); + return PS_ERROR; + } + int cs; + int ce; + if (build_cursection) + { + cs=build_cursection->code; + ce=cs+build_cursection->code_size; + } + else + { + cs=build_uninst.code; + ce=cs+build_uninst.code_size; + } + + char *p=strdup(name); + if (p[strlen(p)-1] == ':') p[strlen(p)-1]=0; + int offs=ns_label.add(p,0); + free(p); + + int n=cur_labels->getlen()/sizeof(section); + if (n) + { + section *t=(section*)cur_labels->get(); + while (n--) + { + if ((*name == '.' || (t->code >= cs && t->code <= ce)) && + t->name_ptr==offs) + { + if (*name == '.') ERROR_MSG("Error: global label \"%s\" already declared\n",name); + else ERROR_MSG("Error: label \"%s\" already declared in section/function\n",name); + return PS_ERROR; + } + t++; + } + } + + section s={0,}; + s.name_ptr = offs; + s.code = ce; + cur_labels->add(&s,sizeof(s)); + + return PS_OK; +} + +int CEXEBuild::add_function(const char *funname) +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Function open when creating function (use FunctionEnd first)\n"); + return PS_ERROR; + } + if (build_cursection) + { + ERROR_MSG("Error: Section open when creating function (use SectionEnd first)\n"); + return PS_ERROR; + } + if (!funname[0]) + { + ERROR_MSG("Error: Function must have a name\n"); + return PS_ERROR; + } + + if (!strnicmp(funname,"un.",3)) + { + set_uninstall_mode(1); + } + + int addr=ns_func.add(funname,0); + int x; + int n=cur_functions->getlen()/sizeof(section); + section *tmp=(section*)cur_functions->get(); + for (x = 0; x < n; x ++) + { + if (tmp[x].name_ptr == addr) + { + ERROR_MSG("Error: Function named \"%s\" already exists.\n",funname); + return PS_ERROR; + } + } + + cur_functions->resize((n+1)*sizeof(section)); + build_cursection=((section*)cur_functions->get())+n; + build_cursection_isfunc=1; + build_cursection->name_ptr=addr; + build_cursection->code=cur_entries->getlen()/sizeof(entry); + build_cursection->code_size=0; + build_cursection->default_state=0; + build_cursection->size_kb=0; + return PS_OK; +} + +int CEXEBuild::function_end() +{ + if (!build_cursection_isfunc) + { + ERROR_MSG("Error: No function open, FunctionEnd called\n"); + return PS_ERROR; + } + build_cursection_isfunc=0; + build_cursection=NULL; + + // add ret. + entry ent={EW_RET,}; + cur_entries->add(&ent,sizeof(entry)); + if (!uninstall_mode) build_header.common.num_entries++; + else build_uninst.common.num_entries++; + + set_uninstall_mode(0); + return PS_OK; +} + + +int CEXEBuild::section_add_flags(int flags) +{ + if (uninstall_mode) + { + ERROR_MSG("Error: can't modify flags of uninstall section\n"); + return PS_ERROR; + } + if (!build_cursection || build_cursection_isfunc) + { + ERROR_MSG("Error: can't modify flags when no section is open\n"); + return PS_ERROR; + } + build_cursection->default_state|=flags; + return PS_OK; +} + +void CEXEBuild::section_add_size_kb(int kb) +{ + if (build_cursection) + { + build_cursection->size_kb+=kb; + } +} + +int CEXEBuild::section_end() +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: SectionEnd specified in function (not section)\n"); + return PS_ERROR; + } + else if (uninstall_mode) + { + entry ent={EW_RET,}; + cur_entries->add(&ent,sizeof(entry)); + build_uninst.common.num_entries++; + set_uninstall_mode(0); + } + else if (!build_cursection) + { + ERROR_MSG("Error: SectionEnd specified and no sections open\n"); + return PS_ERROR; + } + else + { + entry ent={EW_RET,}; + cur_entries->add(&ent,sizeof(entry)); + build_header.common.num_entries++; + } + build_cursection=NULL; + return PS_OK; +} + +int CEXEBuild::add_section(const char *secname, const char *file, int line, const char *defname, int expand=0) +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Section can't create section (already in function, use FunctionEnd first)\n"); + return PS_ERROR; + } + if (build_cursection || uninstall_mode) + { + ERROR_MSG("Error: Section already open, call SectionEnd first\n"); + return PS_ERROR; + } + if (!stricmp(secname,"uninstall")) + { + if (defname[0]) + { + ERROR_MSG("Error: Uninstall section cannot have index output define\n"); + return PS_ERROR; + } + if (build_uninst.code_size >= 0) + { + ERROR_MSG("Error: Uninstall section already specified\n"); + return PS_ERROR; + } + if (subsection_open_cnt) + { + ERROR_MSG("Error: Uninstall section specified inside SubSection\n"); + return PS_ERROR; + } + build_uninst.code=ubuild_entries.getlen()/sizeof(entry); + build_uninst.code_size=0; + set_uninstall_mode(1); + build_cursection=NULL; + return PS_OK; + } + + int n=(build_sections.getlen()/sizeof(section)); + build_sections.resize(build_sections.getlen()+sizeof(section)); + build_cursection=((section*)build_sections.get()) + n; + build_cursection->default_state=DFS_SET; + build_cursection->name_ptr=add_string(secname); + build_cursection->code=cur_entries->getlen()/sizeof(entry); + build_cursection->code_size=0; + build_cursection->size_kb=0; + build_cursection->expand=expand; + + if (secname[0]=='-') + { + build_cursection=NULL; + entry ent={EW_RET,}; + cur_entries->add(&ent,sizeof(entry)); + build_header.common.num_entries++; + } + + if (defname[0]) + { + char buf[32]; + wsprintf(buf,"%d",build_header.num_sections); + if (definedlist.add(defname,buf)) + { + ERROR_MSG("Error: \"%s\" already defined, can't assign section index!\n",defname); + return PS_ERROR; + } + } + + build_header.num_sections++; + + return PS_OK; +} + +int CEXEBuild::make_sure_not_in_secorfunc(const char *str) +{ + if (build_cursection || uninstall_mode) + { + ERROR_MSG("Error: command %s not valid in %s\n",str,build_cursection_isfunc?"function":"section"); + return PS_ERROR; + } + return PS_OK; +} + +int CEXEBuild::add_entry(const entry *ent) +{ + if (!build_cursection && !uninstall_mode) + { + ERROR_MSG("Error: Can't add entry, no section or function is open!\n"); + return PS_ERROR; + } + + cur_entries->add(ent,sizeof(entry)); + + if (!uninstall_mode) + { + if (!build_cursection_isfunc && build_cursection->name_ptr >=0 && build_strlist.get()[build_cursection->name_ptr] == '-') + { + ERROR_MSG("Error: cannot add entry to divider section\n"); + return PS_ERROR; + } + build_cursection->code_size++; + build_header.common.num_entries++; + } + else + { + build_uninst.common.num_entries++; + if (build_cursection) build_cursection->code_size++; + else build_uninst.code_size++; + } + + return PS_OK; +} + +int CEXEBuild::resolve_jump_int(const char *fn, int *a, int offs, int start, int end) +{ + if (*a > 0) + { + char *lname=(char*)ns_label.get()+*a; + if (lname[0] == '-' || lname[0]=='+') + { + *a=offs+atoi(lname)+1; + } + else + { + section *s = (section*)cur_labels->get(); + int n=cur_labels->getlen()/sizeof(section); + while (n-->0) + { + if ((*lname == '.' || (s->code >= start && s->code <= end)) && s->name_ptr == *a) + { + *a = s->code+1; // jumps are to the absolute position, +1 (to differentiate between no jump, and jumping to offset 0) + s->default_state++; + return 0; + } + s++; + } + + ERROR_MSG("Error: could not resolve label \"%s\" in %s\n",lname,fn); + return 1; + } + } + else if (*a < 0) // to jump to a user variable target, -variable_index-1 is already stored. + { + } + // otherwise, *a is 0, which means no jump and we also leave it intact + return 0; +} + +int CEXEBuild::resolve_call_int(const char *fn, const char *str, int fptr, int *ofs) +{ + if (fptr < 0) return 0; + int nf=cur_functions->getlen()/sizeof(section); + section *sec=(section *)cur_functions->get(); + while (nf-- > 0) + { + if (sec->name_ptr>0 && sec->name_ptr == fptr) + { + ofs[0]=sec->code; + sec->default_state++; + return 0; + } + sec++; + } + ERROR_MSG("Error: resolving %s function \"%s\" in %s\n",str,(char*)ns_func.get()+fptr,fn); + ERROR_MSG("Note: uninstall functions must begin with \"un.\", and install functions must not\n"); + return 1; +} + + + +int CEXEBuild::resolve_instruction(const char *fn, const char *str, entry *w, int offs, int start, int end) +{ + if (w->which == EW_NOP) + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + } + else if (w->which == EW_MESSAGEBOX) + { + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[4],offs,start,end)) return 1; + } + else if (w->which == EW_IFFILEEXISTS) + { + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + } + else if (w->which == EW_IFERRORS) + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + } + else if (w->which == EW_IFREBOOTFLAG) + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + } + else if (w->which == EW_STRCMP) + { + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + } + else if (w->which == EW_INTCMP || w->which == EW_INTCMPU) + { + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[4],offs,start,end)) return 1; + } + else if (w->which == EW_ISWINDOW) + { + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + } + else if (w->which == EW_CALL) + { + if (w->offsets[0] >= 0 && w->offsets[1]) // get as jump + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + } + else + { + if (w->offsets[0] >= 0 && resolve_call_int(fn,str,w->offsets[0],w->offsets)) return 1; + // if w->offsets[0] >= 0, EW_CALL requires that it 1-based. + // otherwise, if < 0, it needs an increment anyway (since it + // was encoded with a -2 base, to prevent it looking like an + // empty string "") + w->offsets[0]++; + } + } + else if (w->which == EW_GETFUNCTIONADDR) + { + char buf[32]; + if (w->offsets[1] < 0) + { + ERROR_MSG("Error: GetFunctionAddress requires a real function to get address of.\n"); + return 1; + } + + if (resolve_call_int(fn,str,w->offsets[1],&w->offsets[1])) return 1; + + w->which=EW_ASSIGNVAR; + wsprintf(buf,"%d",w->offsets[1]+1); // +1 here to make 1-based. + w->offsets[1]=add_string(buf); + } + else if (w->which == EW_GETLABELADDR) + { + char buf[32]; + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + w->which=EW_ASSIGNVAR; + wsprintf(buf,"%d",w->offsets[1]); + w->offsets[1]=add_string(buf); + } + return 0; +} + +int CEXEBuild::resolve_coderefs(const char *str) +{ + // resolve jumps&calls + { + section *sec=(section *)cur_functions->get(); + int l=cur_functions->getlen()/sizeof(section); + entry *w=(entry*)cur_entries->get(); + while (l-- > 0) + { + int x; + for (x = sec->code; x < sec->code+sec->code_size; x ++) + { + char fname[1024]; + wsprintf(fname,"function \"%s\"",ns_func.get()+sec->name_ptr); + if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) return 1; + } + sec++; + } + if (uninstall_mode) + { + int x; + for (x = build_uninst.code; x < build_uninst.code+build_uninst.code_size; x ++) + if (resolve_instruction("\"uninstall section\"",str,w+x,x,build_uninst.code,build_uninst.code+build_uninst.code_size)) return 1; + } + else + { + int cnt=0; + sec=(section *)build_sections.get(); + l=build_sections.getlen()/sizeof(section); + while (l-- > 0) + { + int x; + for (x = sec->code; x < sec->code+sec->code_size; x ++) + { + char fname[1024]; + if (sec->name_ptr>=0) wsprintf(fname,"section \"%s\" (%d)",build_strlist.get()+sec->name_ptr,cnt); + else wsprintf(fname,"unnamed section (%d)",cnt); + if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) return 1; + } + sec++; + cnt++; + } + } + } + + // optimize unused functions + { + section *sec=(section *)cur_functions->get(); + int l=cur_functions->getlen()/sizeof(section); + entry *w=(entry*)cur_entries->get(); + while (l-- > 0) + { + if (sec->name_ptr) + { + if (!sec->default_state) + { + if (sec->code_size>0) + { + warning("%s function \"%s\" not referenced - zeroing code (%d-%d) out\n",str, + ns_func.get()+sec->name_ptr, + sec->code,sec->code+sec->code_size); + memset(w+sec->code,0,sec->code_size*sizeof(entry)); + } + } + } + sec++; + } + } + + // give warnings on unused labels + { + section *t=(section*)cur_labels->get(); + int n=cur_labels->getlen()/sizeof(section); + while (n-->0) + { + if (!t->default_state) + { + char *n=(char*)ns_label.get()+t->name_ptr; + if (*n == '.') warning("global label \"%s\" not used",n); + else warning("label \"%s\" not used",n); + } + t++; + } + } + + return 0; +} + +int CEXEBuild::write_output(void) +{ +#ifndef NSIS_CONFIG_CRC_SUPPORT + build_crcchk=0; +#endif + if (has_called_write_output) + { + ERROR_MSG("Error (write_output): write_output already called, can't continue\n"); + return PS_ERROR; + } + has_called_write_output++; + if (!build_output_filename[0]) + { + ERROR_MSG("Error: invalid script: never had OutFile command\n"); + return PS_ERROR; + } + + { + int ns=build_sections.getlen()/sizeof(section); + if (!ns) + { + ERROR_MSG("Error: invalid script: no sections specified\n"); + return PS_ERROR; + } + +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (build_header.componenttext_ptr < 0 && + ns > 1 +#ifdef NSIS_CONFIG_SILENT_SUPPORT + && !build_header.common.silent_install +#endif + ) + { + build_header.componenttext_ptr=-1; + } +#endif + } + +#ifdef NSIS_CONFIG_COMPONENTPAGE + // if component page, do component strings: + if (build_header.componenttext_ptr>=0) + { + int x; + int iscp=0; + for (x = 1; x < build_header.num_sections&&!iscp; x ++) + { + char c=build_strlist.get()[((section*)build_sections.get())[x].name_ptr]; + if (c && c != '-') iscp++; + } + if (iscp) + { + if (build_header.custom_ptr<0) build_header.custom_ptr=add_string_main("Custom",0); + if (build_header.common.subcaption_ptrs[1]<0) + build_header.common.subcaption_ptrs[1]=add_string_main(": Installation Options",0); + + if (build_header.install_types_ptr[0] < 0) + { + if (build_header.componentsubtext_ptr[1]<0) + build_header.componentsubtext_ptr[1]=add_string_main("Select components to install:",0); + } + else + { + if (build_header.componentsubtext_ptr[0]<0) + build_header.componentsubtext_ptr[0]=add_string_main("Select the type of install:",0); + if (build_header.no_custom_instmode_flag!=1 && build_header.componentsubtext_ptr[1]<0) + build_header.componentsubtext_ptr[1]=add_string_main("Or, select the optional components you wish to install:",0); + } + } + else build_header.componenttext_ptr=-1; + } +#endif + + + if (!build_entries.getlen()) + { + ERROR_MSG("Error: invalid script: no entries specified\n"); + return PS_ERROR; + } + + if (build_header.common.name_ptr < 0) + { + warning("Name command not specified. Assuming default."); + build_header.common.name_ptr=add_string_main("Name",0); + build_uninst.common.name_ptr=add_string_uninst("Name",0); + } + + if (build_cursection || uninstall_mode) + { + ERROR_MSG("Error: Section left open at EOF\n"); + return PS_ERROR; + } + + if (subsection_open_cnt) + { + ERROR_MSG("Error: SubSection left open at EOF\n"); + return PS_ERROR; + } + + // deal with functions, for both install and uninstall modes. + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Function still open at EOF, cannot proceed\n"); + return 1; + } + +#ifdef NSIS_CONFIG_LICENSEPAGE + if (build_header.licensedata_ptr<0 || build_header.licensetext_ptr<0) + { + build_header.licensedata_ptr=-1; + build_header.licensetext_ptr=-1; + } + + if (build_header.licensedata_ptr>=0) + { + if (build_header.common.subcaption_ptrs[0]<0) + build_header.common.subcaption_ptrs[0]=add_string_main(": License Agreement",0); + if (build_header.licensebutton_ptr<0) + build_header.licensebutton_ptr=add_string_main("I Agree",0); + } + + if (build_header.license_bg<0) + build_header.license_bg=GetSysColor(COLOR_BTNFACE); +#endif + + if (build_header.text_ptr >= 0) + { + if (build_header.dirsubtext_ptr<0) + { + char buf[2048]; + wsprintf(buf,"Select the directory to install %s in:",build_strlist.get()+build_header.common.name_ptr); + build_header.dirsubtext_ptr=add_string_main(buf,0); + } + if (build_header.common.subcaption_ptrs[2]<0) + build_header.common.subcaption_ptrs[2]=add_string_main(": Installation Directory",0); + if (build_header.browse_ptr<0) build_header.browse_ptr=add_string_main("Browse...",0); + if (build_header.spaceavailable_ptr<0) build_header.spaceavailable_ptr=add_string_main("Space available: ",0); + } + + if (build_header.text_ptr >= 0 +#ifdef NSIS_CONFIG_COMPONENTPAGE + || build_header.componenttext_ptr>=0 +#endif + ) + { + // Changed by Amir Szekely 22nd July 2002 + // Adds the ability to disable space texts + if (build_header.spacerequired_ptr==-1) build_header.spacerequired_ptr=add_string_main("Space required: ",0); + if (build_header.nextbutton_ptr<0) build_header.nextbutton_ptr=add_string_main("Next >",0); + if (build_header.installbutton_ptr<0) build_header.installbutton_ptr=add_string_main("Install",0); + } + + if (build_header.common.subcaption_ptrs[3]<0) + build_header.common.subcaption_ptrs[3]=add_string_main(": Installing Files",0); + if (build_header.common.subcaption_ptrs[4]<0) + build_header.common.subcaption_ptrs[4]=add_string_main(": Completed",0); + + if (build_header.common.branding_ptr<0) + { + char buf[256]; + wsprintf(buf,"Nullsoft Install System %s",NSIS_VERSION); + build_header.common.branding_ptr=add_string_main(buf,0); + } + if (build_header.backbutton_ptr<0) build_header.backbutton_ptr=add_string_main("< Back",0); + if (build_header.common.cancelbutton_ptr<0) build_header.common.cancelbutton_ptr=add_string_main("Cancel",0); + if (build_header.common.showdetailsbutton_ptr<0) build_header.common.showdetailsbutton_ptr=add_string_main("Show details",0); + + if (build_header.common.closebutton_ptr<0) build_header.common.closebutton_ptr=add_string_main("Close",0); + if (build_header.common.completed_ptr<0) build_header.common.completed_ptr=add_string_main("Completed",0); +#ifdef NSIS_SUPPORT_FILE + if (m_inst_fileused && build_header.common.fileerrtext_ptr<0) + { + build_header.common.fileerrtext_ptr=add_string_main( + "Error opening file for writing: \r\n\t\"$0\"\r\n" + "Hit abort to abort installation,\r\n" + "retry to retry writing the file, or\r\n" + "ignore to skip this file"); + } +#endif + + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (ubuild_entries.getlen()) + { + if (!uninstaller_writes_used) + { + warning("Uninstall turned on but WriteUninstaller never used. No uninstaller will be created."); + } + else + { + if (build_uninst.uninstalltext2_ptr<0) + build_uninst.uninstalltext2_ptr=add_string_uninst("Uninstalling from:",0); + if (build_uninst.common.subcaption_ptrs[0]<0) + build_uninst.common.subcaption_ptrs[0]=add_string_uninst(": Confirmation",0); + if (build_uninst.common.subcaption_ptrs[1]<0) + build_uninst.common.subcaption_ptrs[1]=add_string_uninst(": Uninstalling Files",0); + if (build_uninst.common.subcaption_ptrs[2]<0) + build_uninst.common.subcaption_ptrs[2]=add_string_uninst(": Completed",0); + if (build_uninst.common.caption_ptr < 0) + { + char buf[1024]; + wsprintf(buf,"%s Uninstall",ubuild_strlist.get()+build_uninst.common.name_ptr); + build_uninst.common.caption_ptr=add_string_uninst(buf,0); + } + build_uninst.common.branding_ptr=add_string_uninst(build_strlist.get() + build_header.common.branding_ptr,0); + build_uninst.common.cancelbutton_ptr=add_string_uninst(build_strlist.get() + build_header.common.cancelbutton_ptr,0); + build_uninst.common.showdetailsbutton_ptr=add_string_uninst(build_strlist.get() + build_header.common.showdetailsbutton_ptr,0); + build_uninst.common.closebutton_ptr=add_string_uninst(build_strlist.get() + build_header.common.closebutton_ptr,0); + build_uninst.common.completed_ptr=add_string_uninst(build_strlist.get() + build_header.common.completed_ptr,0); + + build_uninst.common.progress_flags=build_header.common.progress_flags; + build_uninst.common.misc_flags|=build_header.common.misc_flags&(4|8); + + if (build_uninst.uninstbutton_ptr<0) build_uninst.uninstbutton_ptr=add_string_uninst("Uninstall",0); + + set_uninstall_mode(1); + #ifdef NSIS_SUPPORT_CODECALLBACKS + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onInit",0),&build_uninst.common.code_onInit)) return PS_ERROR; + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUninstSuccess",0),&build_uninst.common.code_onInstSuccess)) return PS_ERROR; + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUninstFailed",0),&build_uninst.common.code_onInstFailed)) return PS_ERROR; + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onUserAbort",0),&build_uninst.common.code_onUserAbort)) return PS_ERROR; + if (resolve_call_int("uninstall callback","un.callbacks",ns_func.find("un.onNextPage",0),&build_uninst.common.code_onNextPage)) return PS_ERROR; + #endif//NSIS_SUPPORT_CODECALLBACKS + if (resolve_coderefs("uninstall")) return PS_ERROR; + set_uninstall_mode(0); + } + } + else if (uninstaller_writes_used) + { + ERROR_MSG("Error: no Uninstall section specified, but WriteUninstaller used %d time(s)\n",uninstaller_writes_used); + return PS_ERROR; + } + +#ifdef NSIS_SUPPORT_FILE + if (m_uninst_fileused && build_uninst.common.fileerrtext_ptr<0) + { + build_uninst.common.fileerrtext_ptr=add_string_uninst(build_strlist.get() + build_header.common.fileerrtext_ptr,0); + } +#endif + +#endif + + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onInit",0),&build_header.common.code_onInit)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onInstSuccess",0),&build_header.common.code_onInstSuccess)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onInstFailed",0),&build_header.common.code_onInstFailed)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onUserAbort",0),&build_header.common.code_onUserAbort)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onVerifyInstDir",0),&build_header.code_onVerifyInstDir)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onNextPage",0),&build_header.common.code_onNextPage)) return PS_ERROR; + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onPrevPage",0),&build_header.code_onPrevPage)) return PS_ERROR; +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (resolve_call_int("install callback",".callbacks",ns_func.find(".onSelChange",0),&build_header.code_onSelChange)) return PS_ERROR; +#endif//NSIS_CONFIG_COMPONENTPAGE +#endif//NSIS_SUPPORT_CODECALLBACKS + + if (resolve_coderefs("install")) return PS_ERROR; + + // Added by Amir Szekely 8th July 2002 + // Removes any unused resources +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + try { + SCRIPT_MSG("Removing unused resources... "); + CResourceEditor re(header_data_new, exeheader_size_new); +#ifdef NSIS_CONFIG_LICENSEPAGE + if (build_header.licensedata_ptr < 0 +#ifdef NSIS_CONFIG_SILENT_SUPPORT + || build_header.common.silent_install +#endif // NSIS_CONFIG_SILENT_SUPPORT + ) + { + re.UpdateResource(RT_DIALOG, IDD_LICENSE, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } +#endif // NSIS_CONFIG_LICENSEPAGE +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (build_header.componenttext_ptr < 0 +#ifdef NSIS_CONFIG_SILENT_SUPPORT + || build_header.common.silent_install +#endif // NSIS_CONFIG_SILENT_SUPPORT + ) + { + re.UpdateResource(RT_DIALOG, IDD_SELCOM, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + re.UpdateResource(RT_BITMAP, IDB_BITMAP1, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } +#endif // NSIS_CONFIG_COMPONENTPAGE + if (build_header.text_ptr < 0 +#ifdef NSIS_CONFIG_SILENT_SUPPORT + || build_header.common.silent_install +#endif // NSIS_CONFIG_SILENT_SUPPORT + ) + { + re.UpdateResource(RT_DIALOG, IDD_DIR, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!uninstaller_writes_used +#ifdef NSIS_CONFIG_SILENT_SUPPORT + || build_uninst.common.silent_install +#endif // NSIS_CONFIG_SILENT_SUPPORT + ) + { + re.UpdateResource(RT_DIALOG, IDD_UNINST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + } +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_header.common.silent_install +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + && (build_uninst.common.silent_install || !uninstaller_writes_used) +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT + ) + { + re.UpdateResource(RT_DIALOG, IDD_INST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); + re.UpdateResource(RT_DIALOG, IDD_INSTFILES, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); +#ifdef NSIS_CONFIG_CRC_SUPPORT + re.UpdateResource(RT_DIALOG, IDD_VERIFY, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 0, 0); +#endif // NSIS_CONFIG_CRC_SUPPORT + } +#endif // NSIS_CONFIG_SILENT_SUPPORT + + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + + SCRIPT_MSG("Done!\n"); + } + catch (exception& err) { + ERROR_MSG("\nError: %s\n", err.what()); + return PS_ERROR; + } +#endif // NSIS_CONFIG_VISIBLE_SUPPORT + + // Pack exe header if asked for + if (build_header.common.caption_ptr < 0) + { + char buf[1024]; + wsprintf(buf,"%s Setup",build_strlist.get()+build_header.common.name_ptr); + build_header.common.caption_ptr=add_string_main(buf,0); + } + + if (build_packname[0] && build_packcmd[0]) + { + FILE *tmpfile=fopen(build_packname,"wb"); + if (!tmpfile) + { + ERROR_MSG("Error: writing temporary file \"%s\" for pack\n",build_packname); + return PS_ERROR; + } + fwrite(header_data_new,1,exeheader_size_new,tmpfile); + fclose(tmpfile); + if (system(build_packcmd) == -1) + { + remove(build_packname); + ERROR_MSG("Error: calling packer on \"%s\"\n",build_packname); + return PS_ERROR; + } + tmpfile=fopen(build_packname,"rb"); + if (!tmpfile) + { + remove(build_packname); + ERROR_MSG("Error: reading temporary file \"%s\" after pack\n",build_packname); + return PS_ERROR; + } + fseek(tmpfile,0,SEEK_END); + exeheader_size_new=ftell(tmpfile); + exeheader_size_new+=511; + exeheader_size_new&=~511; // align to 512. + fseek(tmpfile,0,SEEK_SET); + unsigned char *header_data_older=header_data_new; + header_data_new=(unsigned char *)malloc(exeheader_size_new); + if (!header_data_new) + { + free(header_data_older); + fclose(tmpfile); + ERROR_MSG("Error: malloc(%d) failed (exepack)\n",exeheader_size_new); + return PS_ERROR; + } + memset(header_data_new,0,exeheader_size_new); + fread(header_data_new,1,exeheader_size_new,tmpfile); + fclose(tmpfile); + remove(build_packname); + + // write out exe header, pack, read back in, align to 512, and + // update the header info + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + // Get offsets of icons to replace for uninstall + // Also makes sure that the icons are there and in the right size. + if (uninstaller_writes_used) { + SCRIPT_MSG("Finding icons offsets for uninstaller... "); + icon_offset = generate_unicons_offsets(header_data_new, m_unicon_data); + if (icon_offset == 0) + return PS_ERROR; + SCRIPT_MSG("Done!\n"); + } +#endif //NSIS_CONFIG_UNINSTALL_SUPPORT + + build_optimize_datablock=0; + + if (uninstall_generate() != PS_OK) + { + return PS_ERROR; + } + + int crc=0; + + { + char buffer[1024],*p; + GetFullPathName(build_output_filename,1024,buffer,&p); + INFO_MSG("\nOutput: \"%s\"\n",buffer); + } + FILE *fp = fopen(build_output_filename,"w+b"); + if (!fp) + { + ERROR_MSG("Can't open output file\n"); + return PS_ERROR; + } + + if ((int)fwrite(header_data_new,1,exeheader_size_new,fp) != exeheader_size_new) + { + ERROR_MSG("Error: can't write %d bytes to output\n",exeheader_size_new); + fclose(fp); + return PS_ERROR; + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + #ifdef NSIS_CONFIG_CRC_ANAL + crc=CRC32(crc,header_data_new,exeheader_size_new); + #else + crc=CRC32(crc,header_data_new+512,exeheader_size_new-512); + #endif +#endif + + firstheader fh={0,}; + fh.nsinst[0]=FH_INT1; + fh.nsinst[1]=FH_INT2; + fh.nsinst[2]=FH_INT3; + + fh.flags=(build_crcchk?FH_FLAGS_CRC:0); + fh.flags|=(build_crcchk==2?FH_FLAGS_FORCE_CRC:0); +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_header.common.silent_install) fh.flags |= FH_FLAGS_SILENT; +#endif + fh.siginfo=FH_SIG; + + int installinfo_compressed; + int fd_start; + if (build_compress_whole) + { + if ((compressor->Init(9)) != C_OK) + { + ERROR_MSG("Error: deflateInit() returned < 0\n"); + return PS_ERROR; + } + } + { + GrowBuf ihd; + { + GrowBuf hdrcomp; + hdrcomp.add(&build_header,sizeof(build_header)); + hdrcomp.add(build_sections.get(),build_sections.getlen()); + hdrcomp.add(build_entries.get(),build_entries.getlen()); + hdrcomp.add(build_strlist.get(),build_strlist.getlen()); + + if (add_data((char*)hdrcomp.get(),hdrcomp.getlen(),&ihd) < 0) return PS_ERROR; + + installinfo_compressed=ihd.getlen(); + fh.length_of_header=hdrcomp.getlen(); + } + + + if (!build_compress_whole) + fh.length_of_all_following_data=ihd.getlen()+build_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(int):0); + else + fd_start=ftell(fp); + + if (fwrite(&fh,1,sizeof(fh),fp) != sizeof(fh)) + { + ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(fh)); + fclose(fp); + return PS_ERROR; + } + + if (build_compress_whole) { + if (deflateToFile(fp,(char*)ihd.get(),ihd.getlen())) + { + fclose(fp); + return PS_ERROR; + } + } + else { + if (fwrite(ihd.get(),1,ihd.getlen(),fp) != (unsigned int)ihd.getlen()) + { + ERROR_MSG("Error: can't write %d bytes to output\n",ihd.getlen()); + fclose(fp); + return PS_ERROR; + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + crc=CRC32(crc,(unsigned char*)&fh,sizeof(fh)); + crc=CRC32(crc,(unsigned char*)ihd.get(),ihd.getlen()); +#endif + } + } + + { + int ns=build_sections.getlen()/sizeof(section); + section *s=(section*)build_sections.get(); + int x; + int req=1; + int div=0; + int divptr=build_strlist.find("-",2); + for (x = 1; x < ns; x ++) + { + if (s[x].name_ptr == divptr) div++; + if (s[x].name_ptr == -1) req++; + } + INFO_MSG("Install: %d section%s",ns,ns==1?"":"s"); + if (req||div) + { + INFO_MSG(" ("); + if (req) + { + INFO_MSG("%d required",req); + if (div) INFO_MSG(", "); + } + if (div) INFO_MSG("%d divider%s",div,div==1?"":"s"); + INFO_MSG(")"); + } + INFO_MSG(".\n"); + } + int ne=build_entries.getlen()/sizeof(entry); + INFO_MSG("Install: %d instruction%s (%d bytes), ",ne,ne==1?"":"s",ne*sizeof(entry)); + INFO_MSG("%d byte string table.\n",build_strlist.getlen()); + if (ubuild_entries.getlen()) + { + int tmp=ubuild_entries.getlen()/sizeof(entry); + INFO_MSG("Uninstall: "); + INFO_MSG("%d instruction%s (%d bytes), ",tmp,tmp==1?"":"s",tmp*sizeof(entry)); + INFO_MSG("%d byte string table.\n",ubuild_strlist.getlen()); + } + + + if (db_opt_save) + { + int total_out_size_estimate= + exeheader_size_new+sizeof(fh)+build_datablock.getlen()+(build_crcchk?4:0); + int pc=MulDiv(db_opt_save,1000,db_opt_save+total_out_size_estimate); + INFO_MSG("Datablock optimizer saved %d bytes (~%d.%d%%).\n",db_opt_save, + pc/10,pc%10); + } + + INFO_MSG("\n"); + int total_usize=exeheader_size; + + INFO_MSG("EXE header size: %10d / %d bytes\n",exeheader_size_new,exeheader_size); + + if (build_compress_whole) { + INFO_MSG("Install code+strings: (%d bytes)\n", + sizeof(fh)+fh.length_of_header+sizeof(int)); + } + else { + INFO_MSG("Install code+strings: %10d / %d bytes\n", + sizeof(fh)+installinfo_compressed, + sizeof(fh)+fh.length_of_header+sizeof(int)); + } + + total_usize+=sizeof(fh)+fh.length_of_header+sizeof(int); + + { + int dbsize, dbsizeu; + dbsize = build_datablock.getlen(); + if (uninstall_size>0) dbsize-=uninstall_size; + + if (build_compress_whole) { + dbsizeu=dbsize; + INFO_MSG("Install data: (%d bytes)\n",dbsizeu); + } + else { + dbsizeu = db_full_size - uninstall_size_full; + INFO_MSG("Install data: %10d / %d bytes\n",dbsize,dbsizeu); + } + total_usize+=dbsizeu; + } + + if (uninstall_size>=0) + { + if (build_compress_whole) + INFO_MSG("Uninstall code+data+strings: (%d bytes)\n",uninstall_size_full); + else + INFO_MSG("Uninstall code+data+strings: %6d / %d bytes\n",uninstall_size,uninstall_size_full); + total_usize+=uninstall_size_full; + } + + if (build_datablock.getlen()) + { + char *dbptr=(char *)build_datablock.get(); + int dbl=build_datablock.getlen(); + if (build_compress_whole) { + INFO_MSG("Compressed data: "); +// INFO_MSG("[compress]"); + } + while (dbl > 0) + { + int l=dbl; + if (l > 32768) l=32768; + if (build_compress_whole) { + if (deflateToFile(fp,dbptr,l)) + { + fclose(fp); + return PS_ERROR; + } + } + else { +#ifdef NSIS_CONFIG_CRC_SUPPORT + crc=CRC32(crc,(unsigned char *)dbptr,l); +#endif + if ((int)fwrite(dbptr,1,l,fp) != l) + { + ERROR_MSG("Error: can't write %d bytes to output\n",l); + fclose(fp); + return PS_ERROR; + } + } + dbptr+=l; + dbl-=l; + } + } + if (build_compress_whole) { + if (deflateToFile(fp,NULL,0)) + { + fclose(fp); + return PS_ERROR; + } + compressor->End(); + + fh.length_of_all_following_data=(ftell(fp)-fd_start)+(build_crcchk?sizeof(int):0); + INFO_MSG("%10d / %d bytes\n",(ftell(fp)-fd_start),build_datablock.getlen()); + + fseek(fp,fd_start,SEEK_SET); + fwrite(&fh,sizeof(fh),1,fp); + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (build_crcchk) + { + // check rest of CRC + fseek(fp,fd_start,SEEK_SET); + for (;;) + { + char buf[32768]; + int l=fread(buf,1,sizeof(buf),fp); + if (!l) break; + crc=CRC32(crc,(unsigned char *)buf,l); + } + } +#endif + fseek(fp,0,SEEK_END); // reset eof flag + } + + if (build_crcchk) + { + total_usize+=sizeof(int); + if (fwrite(&crc,1,sizeof(int),fp) != sizeof(int)) + { + ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(int)); + fclose(fp); + return PS_ERROR; + } + INFO_MSG("CRC (0x%08X): 4 / 4 bytes\n",crc); + } + INFO_MSG("\n"); + { + int pc=MulDiv(ftell(fp),1000,total_usize); + INFO_MSG("Total size: %10d / %d bytes (%d.%d%%)\n", + ftell(fp),total_usize,pc/10,pc%10); + } + fclose(fp); + print_warnings(); + return PS_OK; +} + +int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush +{ + // Changed by Amir Szekely 31st July 2002 + // Ability to change compression methods from within the script + build_compressor_set=true; + + char obuf[32768]; + int flush=0; + compressor->SetNextIn(buf,len); + if (!buf||!len) + { + char a; + compressor->SetNextIn(&a,0); + flush=C_FINISH; + } + for (;;) + { + compressor->SetNextOut(obuf,sizeof(obuf)); + int ret=compressor->Compress(flush); + if (ret<0 && (ret!=-1 || !flush)) + { + ERROR_MSG("Error: deflateToFile: deflate()=%d\n",ret); + return 1; + } + int l=compressor->GetNextOut()-obuf; + if (l) + { + if (fwrite(obuf,1,l,fp) != (unsigned)l) + { + ERROR_MSG("Error: deflateToFile fwrite(%d) failed\n",l); + return 1; + } + } + if (!compressor->GetAvailIn() && (!flush || !l)) break; + } + return 0; +} + +int CEXEBuild::uninstall_generate() +{ +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (ubuild_entries.getlen() && uninstaller_writes_used) + { + firstheader fh={0,}; + + GrowBuf uhd; + // add one more bit (the code+strtabs) to the uninstall datablock + { + GrowBuf udata; + + udata.add(&build_uninst,sizeof(build_uninst)); + udata.add(ubuild_entries.get(),ubuild_entries.getlen()); + udata.add(ubuild_strlist.get(),ubuild_strlist.getlen()); + + set_uninstall_mode(1); + fh.length_of_header=udata.getlen(); + int err=add_data((char*)udata.get(),udata.getlen(),&uhd); + set_uninstall_mode(0); + if (err < 0) return PS_ERROR; + } + + int crc=0; + + build_header.uninstdata_offset=build_datablock.getlen(); + build_header.uninsticon_size=unicondata_size; + + if (add_data((char *)m_unicon_data,unicondata_size) < 0) + return PS_ERROR; +#ifdef NSIS_CONFIG_CRC_SUPPORT + #ifdef NSIS_CONFIG_CRC_ANAL + crc=CRC32(crc,header_data_new,icon_offset); + #else + crc=CRC32(crc,header_data_new+512,icon_offset-512); + #endif + // Changed by Amir Szekely 11th July 2002 + // This bunch of lines do CRC for the uninstaller icon data + unsigned char* seeker = m_unicon_data + sizeof(DWORD); + DWORD dwEndOfIcons = 0; + for (DWORD i = 0; i < *(DWORD*)m_unicon_data; i++) { + DWORD dwSize = *(DWORD*)seeker; + seeker += sizeof(DWORD); + DWORD dwOffset = *(DWORD*)seeker; + seeker += sizeof(DWORD); + // Do CRC for icon data + crc=CRC32(crc,seeker,dwSize); + seeker += dwSize; + if (i < (*(DWORD*)m_unicon_data) - 1) { + // Do CRC for data between icons + crc=CRC32(crc,header_data_new+dwOffset+dwSize,(*(DWORD*)(seeker+sizeof(DWORD)))-dwOffset-dwSize); + } + else { + dwEndOfIcons = dwOffset+dwSize; + } + } + // Done with icons, carry on + crc=CRC32(crc,header_data_new+dwEndOfIcons,exeheader_size_new-dwEndOfIcons); +#endif + fh.nsinst[0]=FH_INT1; + fh.nsinst[1]=FH_INT2; + fh.nsinst[2]=FH_INT3; + fh.flags = FH_FLAGS_UNINSTALL | (build_crcchk?FH_FLAGS_CRC:0); + fh.flags |= (build_crcchk==2?FH_FLAGS_FORCE_CRC:0); +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_uninst.common.silent_install) fh.flags |= FH_FLAGS_SILENT; +#endif + fh.siginfo=FH_SIG; + fh.length_of_all_following_data= + uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(int):0); + + GrowBuf udata; + + if (build_compress_whole) { + // compress uninstaller too + udata.add(&fh,sizeof(fh)); + { + char obuf[32768]; + if ((compressor->Init(9)) != C_OK) + { + ERROR_MSG("Error: deflateInit() returned < 0\n"); + return PS_ERROR; + } + int x; + for (x = 0; x < 2; x ++) + { + if (!x) + compressor->SetNextIn((char*)uhd.get(),uhd.getlen()); + else + compressor->SetNextIn((char*)ubuild_datablock.get(),ubuild_datablock.getlen()); + while (compressor->GetAvailIn()) + { + compressor->SetNextOut(obuf,sizeof(obuf)); + compressor->Compress(0); + if (compressor->GetNextOut()-obuf > 0) + udata.add(obuf,compressor->GetNextOut()-obuf); + } + } + for (;;) + { + compressor->SetNextOut(obuf,sizeof(obuf)); + compressor->Compress(C_FINISH); + if (compressor->GetNextOut()-obuf > 0) + udata.add(obuf,compressor->GetNextOut()-obuf); + else break; + } + compressor->End(); + } + + firstheader *_fh=(firstheader *)udata.get(); + _fh->length_of_all_following_data=udata.getlen()+(build_crcchk?sizeof(int):0); + } + else { + udata.add(&fh,sizeof(fh)); + udata.add(uhd.get(),uhd.getlen()); + udata.add(ubuild_datablock.get(),ubuild_datablock.getlen()); + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (build_crcchk) + { + int s=CRC32(crc,(unsigned char *)udata.get(),udata.getlen()); + udata.add(&s,sizeof(int)); + } +#endif + + if (add_data((char*)udata.get(),udata.getlen()) < 0) + return PS_ERROR; + + uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int); + + // compressed size + uninstall_size=build_datablock.getlen()-build_header.uninstdata_offset; + } +#endif + return PS_OK; +} + + +#define SWAP(x,y,i) { i _ii; _ii=x; x=y; y=_ii; } + +void CEXEBuild::set_uninstall_mode(int un) +{ + if (un != uninstall_mode) + { + uninstall_mode=un; + if (un) cur_datablock=&ubuild_datablock; + else cur_datablock=&build_datablock; + if (un) cur_entries=&ubuild_entries; + else cur_entries=&build_entries; + if (un) cur_functions=&ubuild_functions; + else cur_functions=&build_functions; + if (un) cur_labels=&ubuild_labels; + else cur_labels=&build_labels; + + SWAP(db_opt_save_u,db_opt_save,int); + SWAP(db_comp_save_u,db_comp_save,int); + SWAP(db_full_size_u,db_full_size,int); + } +} + +extern FILE *g_output; + +void CEXEBuild::warning(const char *s, ...) +{ + char buf[4096]; + va_list val; + va_start(val,s); + vsprintf(buf,s,val); + va_end(val); + m_warnings.add(buf,-1); + if (display_warnings) + { + fprintf(g_output,"warning: %s\n",buf); + fflush(g_output); + } +} + +void CEXEBuild::ERROR_MSG(const char *s, ...) +{ + if (display_errors) + { + char buf[4096]; + va_list val; + va_start(val,s); + vsprintf(buf,s,val); + va_end(val); + fprintf(g_output,"%s",buf); + fflush(g_output); + } +} + +void CEXEBuild::SCRIPT_MSG(const char *s, ...) +{ + if (display_script) + { + char buf[4096]; + va_list val; + va_start(val,s); + vsprintf(buf,s,val); + va_end(val); + fprintf(g_output,"%s",buf); + fflush(g_output); + } +} + +void CEXEBuild::INFO_MSG(const char *s, ...) +{ + if (display_info) + { + char buf[4096]; + va_list val; + va_start(val,s); + vsprintf(buf,s,val); + va_end(val); + fprintf(g_output,"%s",buf); + fflush(g_output); + } +} + +void CEXEBuild::print_warnings() +{ + int nw=0,x=m_warnings.getlen(); + if (!x || !display_warnings) return; + char *p=m_warnings.get(); + while (x>0) if (!p[--x]) nw++; + fprintf(g_output,"\n%d warning%s:\n",nw,nw==1?"":"s"); + for (x = 0; x < nw; x ++) + { + fprintf(g_output," %s\n",p); + p+=strlen(p)+1; + } + fflush(g_output); +} diff --git a/Source/build.h b/Source/build.h new file mode 100644 index 00000000..ff53789e --- /dev/null +++ b/Source/build.h @@ -0,0 +1,169 @@ +#ifndef _BUILD_H_ +#define _BUILD_H_ + +#include "strlist.h" +#include "lineparse.h" + +#include "exehead/fileform.h" +#include "exehead/config.h" + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +// Changed by Amir Szekely 31st July 2002 +#include "compressor.h" +#include "czlib.h" +#include "cbzip2.h" + +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + +#ifdef NSIS_CONFIG_CRC_SUPPORT +extern "C" +{ + unsigned long CRC32(unsigned long crc, const unsigned char *buf, unsigned int len); +}; +#endif + +#define PS_OK 0 +#define PS_EOF 1 +#define PS_ENDIF 2 +#define PS_ELSE 3 +#define PS_ELSE_IF0 4 +#define PS_ELSE_IF1 5 +#define PS_ERROR 50 +#define IS_PS_ELSE(x) (( x ) >= PS_ELSE && ( x ) <= PS_ELSE_IF1) + +class CEXEBuild { + public: + CEXEBuild(); + ~CEXEBuild(); + + // to add a warning to the compiler's warning list. + void warning(const char *s, ...); + + // to add a defined thing. + void define(const char *p, const char *v=""); + + // process a script (you can process as many scripts as you want, + // it is as if they are concatenated) + int process_script(FILE *fp, char *curfilename, int *lineptr); + int process_oneline(char *line, char *curfilename, int lineptr); + + // you only get to call write_output once, so use it wisely. + int write_output(void); + + void print_help(char *commandname=NULL); + + DefineList definedlist; + + int display_errors; + int display_script; + int display_warnings; + int display_info; + + private: + // tokens.cpp + int get_commandtoken(char *s, int *np, int *op); + + // script.cpp + int parseScript(FILE *fp, const char *curfilename, int *lineptr, int ignore); + void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist); + int doParse(const char *str, FILE *fp, const char *curfilename, int *lineptr, int ignore); + int doCommand(int which_token, LineParser &line, FILE *fp, const char *curfilename, int linecnt); + int do_add_file(const char *lgss, int attrib, int recurse, int linecnt, int *total_files, const char *name_override=0); + GrowBuf m_linebuild; // used for concatenating lines + + void ERROR_MSG(const char *s, ...); + void SCRIPT_MSG(const char *s, ...); + void INFO_MSG(const char *s, ...); + + // build.cpp functions used mostly by script.cpp + int getcurdbsize(); + int add_section(const char *secname, const char *file, int line, const char *defname, int expand); + int section_end(); + int add_function(const char *funname); + int function_end(); + void section_add_size_kb(int kb); + int section_add_flags(int flags); + int add_label(const char *name); + int add_entry(const entry *ent); + int add_data(const char *data, int length, IGrowBuf *dblock=NULL); // returns offset + int add_string(const char *string); // returns offset (in string table) + int add_string_main(const char *string, int process=1); // returns offset (in string table) + int add_string_uninst(const char *string, int process=1); // returns offset (in string table) + int preprocess_string(char *out, const char *in); + + int make_sure_not_in_secorfunc(const char *str); + + // build.cpp functions used mostly within build.cpp + int datablock_optimize(int start_offset); + void printline(int l); + int process_jump(LineParser &line, int wt, int *offs); + + int resolve_jump_int(const char *fn, int *a, int offs, int start, int end); + int resolve_call_int(const char *fn, const char *str, int fptr, int *ofs); + int resolve_instruction(const char *fn, const char *str, entry *w, int offs, int start, int end); + + int resolve_coderefs(const char *str); + void print_warnings(); + int uninstall_generate(); + void set_uninstall_mode(int un); + + // a whole bunch O data. + + // Added by Amir Szekely 31st July 2002 + ICompressor *compressor; + CZlib zlib_comressor; + CBzip2 bzip2_compressor; + bool build_compressor_set; + bool build_compress_whole; + + int has_called_write_output; + + char build_packname[1024], build_packcmd[1024]; + int build_overwrite, build_compress, build_crcchk, + build_datesave, build_optimize_datablock; + + header build_header; + int uninstall_mode; + uninstall_header build_uninst; + int uninstall_size,uninstall_size_full; + int uninstaller_writes_used; + + char build_output_filename[1024]; + char cur_out_path[1024]; + + int subsection_open_cnt; + StringList m_warnings; + GrowBuf m_macros; + + StringList m_macro_entry; + + int db_opt_save, db_comp_save, db_full_size, db_opt_save_u, + db_comp_save_u, db_full_size_u; + int build_sections_req,build_sections_div; + + StringList ns_func, ns_label; // function and label namespaces + + int build_cursection_isfunc; + section *build_cursection; + GrowBuf build_sections; + GrowBuf build_entries,ubuild_entries, *cur_entries; + GrowBuf build_functions, ubuild_functions, *cur_functions; + GrowBuf build_labels, ubuild_labels, *cur_labels; + StringList build_strlist,ubuild_strlist; + + MMapBuf build_datablock, ubuild_datablock; // use GrowBuf here instead of MMapBuf if you want + IGrowBuf *cur_datablock; + + unsigned char *header_data_new; + int exeheader_size_new; + int enabled_bitmap_offset; + int icon_offset; + int m_inst_fileused; + int m_uninst_fileused; + bool branding_image_found; // Added by Amir Szekely 29nd July 2002 + WORD branding_image_id; // Added by Amir Szekely 29nd July 2002 + unsigned char *m_unicon_data; + int deflateToFile(FILE *fp, char *buf, int len); // len==0 to flush +}; + +#endif //_BUILD_H_ diff --git a/Source/bzip2/blocksort.c b/Source/bzip2/blocksort.c new file mode 100644 index 00000000..f7269681 --- /dev/null +++ b/Source/bzip2/blocksort.c @@ -0,0 +1,1100 @@ +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. + + To get some idea how the block sorting algorithms in this file + work, read my paper + On the Performance of BWT Sorting Algorithms + in Proceedings of the IEEE Data Compression Conference 2000, + Snowbird, Utah, USA, 27-30 March 2000. The main sort in this + file implements the algorithm called cache in the paper. +--*/ + + +#include "bzlib_private.h" + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +__inline__ +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( copyStart[ss]-1 == copyEnd[ss], 1007 ); + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, &budget ); + if (budget < 0) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/bzlib.c b/Source/bzip2/bzlib.c new file mode 100644 index 00000000..84a94cb9 --- /dev/null +++ b/Source/bzip2/bzlib.c @@ -0,0 +1,790 @@ +#include "../exehead/config.h" +#if (defined(EXEHEAD) && defined(NSIS_COMPRESS_USE_BZIP2)) || !defined(EXEHEAD) +/*-------------------------------------------------------------*/ +/*--- Library top-level functions. ---*/ +/*--- bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * made zero-length BZ_FLUSH work correctly in bzCompress(). + * fixed bzWrite/bzRead to ignore zero-length requests. + * fixed bzread to correctly handle read requests after EOF. + * wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. +--*/ +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Compression stuff ---*/ +/*---------------------------------------------------*/ + + +#ifndef EXEHEAD + +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ + Int32 i; + s->nblock = 0; + s->numZ = 0; + s->state_out_pos = 0; + for (i = 0; i < 256; i++) s->inUse[i] = False; + s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ + s->state_in_ch = 256; + s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ + if (s->state_in_ch < 256 && s->state_in_len > 0) + return False; else + return True; +} + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) + ( bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 n; + EState* s; + + if (strm == NULL || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + + s = BZALLOC( sizeof(EState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + + s->arr1 = NULL; + s->arr2 = NULL; + s->ftab = NULL; + + n = NSIS_COMPRESS_BZIP2_LEVEL*100000; + s->arr1 = BZALLOC( n * sizeof(UInt32) ); + s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); + s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); + + if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { + BZFREE(s->arr1); + BZFREE(s->arr2); + BZFREE(s->ftab); + BZFREE(s); + return BZ_MEM_ERROR; + } + + s->blockNo = 0; + s->state = BZ_S_INPUT; + s->mode = BZ_M_RUNNING; + s->nblockMAX = 100000 * NSIS_COMPRESS_BZIP2_LEVEL - 19; + s->workFactor = workFactor; + + s->block = (UChar*)s->arr2; + s->mtfv = (UInt16*)s->arr1; + s->zbits = NULL; + s->ptr = (UInt32*)s->arr1; + + strm->state = s; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + init_RL ( s ); + prepare_new_block ( s ); + return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ + UChar ch = (UChar)(s->state_in_ch); + s->inUse[s->state_in_ch] = True; + switch (s->state_in_len) { + case 1: + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 2: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 3: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + default: + s->inUse[s->state_in_len-4] = True; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = ((UChar)(s->state_in_len-4)); + s->nblock++; + break; + } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ + if (s->state_in_ch < 256) add_pair_to_block ( s ); + init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ +{ \ + UInt32 zchh = (UInt32)(zchh0); \ + /*-- fast track the common case --*/ \ + if (zchh != zs->state_in_ch && \ + zs->state_in_len == 1) { \ + UChar ch = (UChar)(zs->state_in_ch); \ + zs->inUse[zs->state_in_ch] = True; \ + zs->block[zs->nblock] = (UChar)ch; \ + zs->nblock++; \ + zs->state_in_ch = zchh; \ + } \ + else \ + /*-- general, uncommon cases --*/ \ + if (zchh != zs->state_in_ch || \ + zs->state_in_len == 255) { \ + if (zs->state_in_ch < 256) \ + add_pair_to_block ( zs ); \ + zs->state_in_ch = zchh; \ + zs->state_in_len = 1; \ + } else { \ + zs->state_in_len++; \ + } \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ + Bool progress_in = False; + + if (s->mode == BZ_M_RUNNING) { + + /*-- fast track the common case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + + } else { + + /*-- general, uncommon case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + /*-- flush/finish end? --*/ + if (s->avail_in_expect == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + s->avail_in_expect--; + } + } + return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ + Bool progress_out = False; + + while (True) { + + /*-- no output space? --*/ + if (s->strm->avail_out == 0) break; + + /*-- block done? --*/ + if (s->state_out_pos >= s->numZ) break; + + progress_out = True; + *(s->strm->next_out) = s->zbits[s->state_out_pos]; + s->state_out_pos++; + s->strm->avail_out--; + s->strm->next_out++; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ + Bool progress_in = False; + Bool progress_out = False; + EState* s = strm->state; + + while (True) { + + if (s->state == BZ_S_OUTPUT) { + progress_out |= copy_output_until_stop ( s ); + if (s->state_out_pos < s->numZ) break; + if (s->mode == BZ_M_FINISHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + prepare_new_block ( s ); + s->state = BZ_S_INPUT; + if (s->mode == BZ_M_FLUSHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + } + + if (s->state == BZ_S_INPUT) { + progress_in |= copy_input_until_stop ( s ); + if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { + flush_RL ( s ); + BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); + s->state = BZ_S_OUTPUT; + } + else + if (s->nblock >= s->nblockMAX) { + BZ2_compressBlock ( s, False ); + s->state = BZ_S_OUTPUT; + } + else + if (s->strm->avail_in == 0) { + break; + } + } + + } + + return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ + Bool progress; + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + preswitch: + switch (s->mode) { + + case BZ_M_IDLE: + return BZ_SEQUENCE_ERROR; + + case BZ_M_RUNNING: + if (action == BZ_RUN) { + progress = handle_compress ( strm ); + return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; + } + else + if (action == BZ_FLUSH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FLUSHING; + goto preswitch; + } + else + if (action == BZ_FINISH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FINISHING; + goto preswitch; + } + else + return BZ_PARAM_ERROR; + + case BZ_M_FLUSHING: + if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FLUSH_OK; + s->mode = BZ_M_RUNNING; + return BZ_RUN_OK; + + case BZ_M_FINISHING: + if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (!progress) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FINISH_OK; + s->mode = BZ_M_IDLE; + return BZ_STREAM_END; + } + return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) +{ + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + BZFREE(s->arr1); + BZFREE(s->arr2); + BZFREE(s->ftab); + BZFREE(strm->state); + + strm->state = NULL; + + return BZ_OK; +} +#else // EXEHEAD + +/*---------------------------------------------------*/ +/*--- Decompression stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) + ( bz_stream* strm) +{ + DState* s; + + s = BZALLOC( sizeof(DState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + strm->state = s; + s->state = BZ_X_BLKHDR_1; + // s->bsLive = 0; +// s->bsBuff = 0; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE + s->ll16 = BZALLOC( NSIS_COMPRESS_BZIP2_LEVEL*100000 * sizeof(UInt16) ); + s->ll4 = BZALLOC( + ((1 + NSIS_COMPRESS_BZIP2_LEVEL*100000) >> 1) * sizeof(UChar) + ); + if (s->ll16 == NULL || s->ll4 == NULL) return (BZ_MEM_ERROR); +#else + s->tt = BZALLOC( NSIS_COMPRESS_BZIP2_LEVEL * 100000 * sizeof(Int32) ); + if (s->tt == NULL) return (BZ_MEM_ERROR); +#endif + // s->currBlockNo = 0; + + return BZ_OK; +} + + +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ + Int32 nb, na, mid; + nb = 0; + na = 256; + do { + mid = (nb + na) >> 1; + if (indx >= cftab[mid]) nb = mid; else na = mid; + } + while (na - nb != 1); + return nb; +} + + +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE +/*---------------------------------------------------*/ +static +void unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +} +#else//!small, fast +static +void unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + /* restore */ +// UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; + UChar c_state_out_ch = s->state_out_ch; + Int32 c_state_out_len = s->state_out_len; + Int32 c_nblock_used = s->nblock_used; + Int32 c_k0 = s->k0; + UInt32* c_tt = s->tt; + UInt32 c_tPos = s->tPos; + char* cs_next_out = s->strm->next_out; + unsigned int cs_avail_out = s->strm->avail_out; + /* end restore */ + + UInt32 avail_out_INIT = cs_avail_out; + Int32 s_save_nblockPP = s->save_nblock+1; + unsigned int total_out_lo32_old; + + while (True) { + + /* try to finish existing run */ + if (c_state_out_len > 0) { + while (True) { + if (cs_avail_out == 0) goto return_notr; + if (c_state_out_len == 1) break; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + c_state_out_len--; + cs_next_out++; + cs_avail_out--; + } + s_state_out_len_eq_one: + { + if (cs_avail_out == 0) { + c_state_out_len = 1; goto return_notr; + }; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + cs_next_out++; + cs_avail_out--; + } + } + /* can a new run be started? */ + if (c_nblock_used == s_save_nblockPP) { + c_state_out_len = 0; goto return_notr; + }; + c_state_out_ch = c_k0; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (k1 != c_k0) { + c_k0 = k1; goto s_state_out_len_eq_one; + }; + if (c_nblock_used == s_save_nblockPP) + goto s_state_out_len_eq_one; + + c_state_out_len = 2; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + c_state_out_len = 3; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + BZ_GET_FAST_C(k1); c_nblock_used++; + c_state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST_C(c_k0); c_nblock_used++; + } + + return_notr: + total_out_lo32_old = s->strm->total_out_lo32; + s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); + if (s->strm->total_out_lo32 < total_out_lo32_old) + s->strm->total_out_hi32++; + + /* save */ +// s->calculatedBlockCRC = c_calculatedBlockCRC; + s->state_out_ch = c_state_out_ch; + s->state_out_len = c_state_out_len; + s->nblock_used = c_nblock_used; + s->k0 = c_k0; + s->tt = c_tt; + s->tPos = c_tPos; + s->strm->next_out = cs_next_out; + s->strm->avail_out = cs_avail_out; + /* end save */ + } +} + +#endif + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ + DState* s; + s = strm->state; + + while (True) { + if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; + if (s->state == BZ_X_OUTPUT) { +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE + unRLE_obuf_to_output_SMALL ( s ); +#else + unRLE_obuf_to_output_FAST ( s ); +#endif + if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { + s->state = BZ_X_BLKHDR_1; + } else { + return BZ_OK; + } + } + if (s->state >= BZ_X_BLKHDR_1) { + Int32 r = BZ2_decompress ( s ); + if (r == BZ_STREAM_END) { + return r; + } + if (s->state != BZ_X_OUTPUT) return r; + } + } + + AssertH ( 0, 6001 ); + + return 0; /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) +{ + DState* s; + s = strm->state; + +#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE + BZFREE(s->tt); +#else + BZFREE(s->ll16); + BZFREE(s->ll4); +#endif + BZFREE(strm->state); + strm->state = NULL; + + return BZ_OK; +} + +#endif + +#endif diff --git a/Source/bzip2/bzlib.h b/Source/bzip2/bzlib.h new file mode 100644 index 00000000..cf6f3d1d --- /dev/null +++ b/Source/bzip2/bzlib.h @@ -0,0 +1,174 @@ + +/*-------------------------------------------------------------*/ +/*--- Public header file for the library. ---*/ +/*--- bzlib.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_H +#define _BZLIB_H + +#define BZ_NO_STDIO 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define BZ_RUN 0 +#define BZ_FLUSH 1 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FLUSH_OK 2 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 +#define BZ_SEQUENCE_ERROR (-1) +#define BZ_PARAM_ERROR (-2) +#define BZ_MEM_ERROR (-3) +#define BZ_DATA_ERROR (-4) +#define BZ_DATA_ERROR_MAGIC (-5) +#define BZ_IO_ERROR (-6) +#define BZ_UNEXPECTED_EOF (-7) +#define BZ_OUTBUFF_FULL (-8) +#define BZ_CONFIG_ERROR (-9) + +typedef + struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *opaque; + } + bz_stream; + + +#ifndef BZ_IMPORT +#define BZ_EXPORT +#endif + +#ifdef _WIN32 +# include +# include +# ifdef small + /* windows.h define small to char */ +# undef small +# endif +# ifdef BZ_EXPORT +# define BZ_API(func) WINAPI func +# define BZ_EXTERN extern +# else + /* import windows dll dynamically */ +# define BZ_API(func) (WINAPI * func) +# define BZ_EXTERN +# endif +#else +# define BZ_API(func) func +# define BZ_EXTERN extern +#endif + + +/*-- Core (low-level) library functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompress) ( + bz_stream* strm, + int action + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( + bz_stream *strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( + bz_stream *strm + ); + + + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/bzlib_private.h b/Source/bzip2/bzlib_private.h new file mode 100644 index 00000000..31f0de0c --- /dev/null +++ b/Source/bzip2/bzlib_private.h @@ -0,0 +1,474 @@ + +/*-------------------------------------------------------------*/ +/*--- Private header file for the library. ---*/ +/*--- bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_PRIVATE_H +#define _BZLIB_PRIVATE_H + +#include + + #include "bzlib.h" + + + +/*-- General stuff. --*/ + +#define BZ_VERSION "1.0.1, 23-June-2000" + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#ifndef __GNUC__ +#define __inline__ /* */ +#endif + +#define AssertD(cond,msg) /* */ +#define AssertH(cond,errcode) /* */ +#define AssertD(cond,msg) /* */ +#define VPrintf0(zf) /* */ +#define VPrintf1(zf,za1) /* */ +#define VPrintf2(zf,za1,za2) /* */ +#define VPrintf3(zf,za1,za2,za3) /* */ +#define VPrintf4(zf,za1,za2,za3,za4) /* */ +#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */ + + +#define BZALLOC(items) GlobalAlloc(GPTR,items) +#define BZFREE(addr) { if (addr) GlobalFree(addr); } + + +/*-- Constants for the back end. --*/ + +#define BZ_MAX_ALPHA_SIZE 258 +#define BZ_MAX_CODE_LEN 23 + +#define BZ_RUNA 0 +#define BZ_RUNB 1 + +#define BZ_N_GROUPS 6 +#define BZ_G_SIZE 50 +#define BZ_N_ITERS 4 + +#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) + + + +/*-- Stuff for randomising repetitive blocks. --*/ + +extern Int16 BZ2_rNums[512]; + +#define BZ_RAND_DECLS \ + Int32 rNToGo; \ + Int32 rTPos \ + +#define BZ_RAND_INIT_MASK \ + s->rNToGo = 0; \ + s->rTPos = 0 \ + +#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) + +#define BZ_RAND_UPD_MASK \ + if (s->rNToGo == 0) { \ + s->rNToGo = BZ2_rNums[s->rTPos]; \ + s->rTPos++; \ + if (s->rTPos == 512) s->rTPos = 0; \ + } \ + s->rNToGo--; + + + +/*-- Stuff for doing CRCs. --*/ + +//extern UInt32 BZ2_crc32Table[256]; + +#define BZ_INITIALISE_CRC(crcVar) +/* \ +{ \ + crcVar = 0xffffffffL; \ +} +*/ + +#define BZ_FINALISE_CRC(crcVar) + +/* \ +{ \ + crcVar = ~(crcVar); \ +} +*/ + +#define BZ_UPDATE_CRC(crcVar,cha) +/* + \ +{ \ + crcVar = (crcVar << 8) ^ \ + BZ2_crc32Table[(crcVar >> 24) ^ \ + ((UChar)cha)]; \ +} +*/ + + +/*-- States and modes for compression. --*/ + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + + + + +/*-- Structure holding all the compression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* mode this stream is in, and whether inputting */ + /* or outputting data */ + Int32 mode; + Int32 state; + + /* remembers avail_in when flush/finish requested */ + UInt32 avail_in_expect; + + /* for doing the block sorting */ + UInt32* arr1; + UInt32* arr2; + UInt32* ftab; + Int32 origPtr; + + /* aliases for arr1 and arr2 */ + UInt32* ptr; + UChar* block; + UInt16* mtfv; + UChar* zbits; + + /* for deciding when to use the fallback sorting algorithm */ + Int32 workFactor; + + /* run-length-encoding of the input */ + UInt32 state_in_ch; + Int32 state_in_len; + BZ_RAND_DECLS; + + /* input and output limits and current posns */ + Int32 nblock; + Int32 nblockMAX; + Int32 numZ; + Int32 state_out_pos; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + UChar unseqToSeq[256]; + + /* the buffer for bit stream creation */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 blockNo; + + /* stuff for coding the MTF values */ + Int32 nMTF; + Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + /* second dimension: only 3 needed; 4 makes index calculations faster */ + UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; + + } + EState; + + + +/*-- externs for compression. --*/ + +extern void +BZ2_blockSort ( EState* ); + +extern void +BZ2_compressBlock ( EState*, Bool ); + +extern void +BZ2_bsInitWrite ( EState* ); + +extern void +BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); + +extern void +BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); + + + +/*-- states for decompression. --*/ + +#define BZ_X_IDLE 1 +#define BZ_X_OUTPUT 2 + +#define BZ_X_BLKHDR_1 11 +#define BZ_X_RANDBIT 12 +#define BZ_X_ORIGPTR_1 13 +#define BZ_X_ORIGPTR_2 14 +#define BZ_X_ORIGPTR_3 15 +#define BZ_X_MAPPING_1 16 +#define BZ_X_MAPPING_2 17 +#define BZ_X_SELECTOR_1 18 +#define BZ_X_SELECTOR_2 19 +#define BZ_X_SELECTOR_3 20 +#define BZ_X_CODING_1 21 +#define BZ_X_CODING_2 22 +#define BZ_X_CODING_3 23 +#define BZ_X_MTF_1 24 +#define BZ_X_MTF_2 25 +#define BZ_X_MTF_3 26 +#define BZ_X_MTF_4 27 +#define BZ_X_MTF_5 28 +#define BZ_X_MTF_6 29 + + + +/*-- Constants for the fast MTF decoder. --*/ + +#define MTFA_SIZE 4096 +#define MTFL_SIZE 16 + + + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* state indicator for this stream */ + Int32 state; + + /* for doing the final run-length decoding */ + UChar state_out_ch; + Int32 state_out_len; + Bool blockRandomised; + BZ_RAND_DECLS; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 currBlockNo; + Int32 verbosity; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + UInt32 tPos; + Int32 k0; + Int32 unzftab[256]; + Int32 nblock_used; + Int32 cftab[257]; + Int32 cftabCopy[257]; + +#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 *tt; +#else + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 *ll16; + UChar *ll4; +#endif + + /* stored and calculated CRCs */ +// UInt32 storedBlockCRC; + // UInt32 storedCombinedCRC; + // UInt32 calculatedBlockCRC; + //UInt32 calculatedCombinedCRC; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + Bool inUse16[16]; + UChar seqToUnseq[256]; + + /* for decoding the MTF values */ + UChar mtfa [MTFA_SIZE]; + Int32 mtfbase[256 / MTFL_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + + Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 minLens[BZ_N_GROUPS]; + + /* save area for scalars in the main decompress code */ + Int32 save_i; + Int32 save_j; + Int32 save_t; + Int32 save_alphaSize; + Int32 save_nGroups; + Int32 save_nSelectors; + Int32 save_EOB; + Int32 save_groupNo; + Int32 save_groupPos; + Int32 save_nextSym; + Int32 save_nblockMAX; + Int32 save_nblock; + Int32 save_es; + Int32 save_N; + Int32 save_curr; + Int32 save_zt; + Int32 save_zn; + Int32 save_zvec; + Int32 save_zj; + Int32 save_gSel; + Int32 save_gMinlen; + Int32* save_gLimit; + Int32* save_gBase; + Int32* save_gPerm; + + } + DState; + + + +/*-- Macros for decompression. --*/ + +#define BZ_GET_FAST(cccc) \ + s->tPos = s->tt[s->tPos]; \ + cccc = (UChar)(s->tPos & 0xff); \ + s->tPos >>= 8; + +#define BZ_GET_FAST_C(cccc) \ + c_tPos = c_tt[c_tPos]; \ + cccc = (UChar)(c_tPos & 0xff); \ + c_tPos >>= 8; + +#define SET_LL4(i,n) \ + { if (((i) & 0x1) == 0) \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ + } + +#define GET_LL4(i) \ + ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) + +#define SET_LL(i,n) \ + { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ + SET_LL4(i, n >> 16); \ + } + +#define GET_LL(i) \ + (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) + +#define BZ_GET_SMALL(cccc) \ + cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ + s->tPos = GET_LL(s->tPos); + + +/*-- externs for decompression. --*/ + +extern Int32 +BZ2_indexIntoF ( Int32, Int32* ); + +extern Int32 +BZ2_decompress ( DState* ); + +extern void +BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#endif + + +/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ + +#ifdef BZ_NO_STDIO +#ifndef NULL +#define NULL 0 +#endif +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/compress.c b/Source/bzip2/compress.c new file mode 100644 index 00000000..eba959c8 --- /dev/null +++ b/Source/bzip2/compress.c @@ -0,0 +1,681 @@ +/*-------------------------------------------------------------*/ +/*--- Compression machinery (not incl block sorting) ---*/ +/*--- compress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * changed setting of nGroups in sendMTFValues() so as to + do a bit better on small files +--*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +void BZ2_bsInitWrite ( EState* s ) +{ + s->bsLive = 0; + s->bsBuff = 0; +} + + +/*---------------------------------------------------*/ +static +void bsFinishWrite ( EState* s ) +{ + while (s->bsLive > 0) { + s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } +} + + +/*---------------------------------------------------*/ +#define bsNEEDW(nz) \ +{ \ + while (s->bsLive >= 8) { \ + s->zbits[s->numZ] \ + = (UChar)(s->bsBuff >> 24); \ + s->numZ++; \ + s->bsBuff <<= 8; \ + s->bsLive -= 8; \ + } \ +} + + +/*---------------------------------------------------*/ +static +__inline__ +void bsW ( EState* s, Int32 n, UInt32 v ) +{ + bsNEEDW ( n ); + s->bsBuff |= (v << (32 - s->bsLive - n)); + s->bsLive += n; +} + + +/*---------------------------------------------------*/ +static +void bsPutUInt32 ( EState* s, UInt32 u ) +{ + bsW ( s, 8, (u >> 24) & 0xffL ); + bsW ( s, 8, (u >> 16) & 0xffL ); + bsW ( s, 8, (u >> 8) & 0xffL ); + bsW ( s, 8, u & 0xffL ); +} + + +/*---------------------------------------------------*/ +static +void bsPutUChar ( EState* s, UChar c ) +{ + bsW( s, 8, (UInt32)c ); +} + + +/*---------------------------------------------------*/ +/*--- The back end proper ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +static +void makeMaps_e ( EState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->unseqToSeq[i] = s->nInUse; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +static +void generateMTFValues ( EState* s ) +{ + UChar yy[256]; + Int32 i, j; + Int32 zPend; + Int32 wr; + Int32 EOB; + + /* + After sorting (eg, here), + s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, + and + ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] + holds the original block data. + + The first thing to do is generate the MTF values, + and put them in + ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. + Because there are strictly fewer or equal MTF values + than block values, ptr values in this area are overwritten + with MTF values only when they are no longer needed. + + The final compressed bitstream is generated into the + area starting at + (UChar*) (&((UChar*)s->arr2)[s->nblock]) + + These storage aliases are set up in bzCompressInit(), + except for the last one, which is arranged in + compressBlock(). + */ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt16* mtfv = s->mtfv; + + makeMaps_e ( s ); + EOB = s->nInUse+1; + + for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; + + wr = 0; + zPend = 0; + for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; + + for (i = 0; i < s->nblock; i++) { + UChar ll_i; + AssertD ( wr <= i, "generateMTFValues(1)" ); + j = ptr[i]-1; if (j < 0) j += s->nblock; + ll_i = s->unseqToSeq[block[j]]; + AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); + + if (yy[0] == ll_i) { + zPend++; + } else { + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + { + register UChar rtmp; + register UChar* ryy_j; + register UChar rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while ( rll_i != rtmp ) { + register UChar rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + }; + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; + } + + } + } + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + + mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; + + s->nMTF = wr; +} + + +/*---------------------------------------------------*/ +#define BZ_LESSER_ICOST 0 +#define BZ_GREATER_ICOST 15 + +static +void sendMTFValues ( EState* s ) +{ + Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; + Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; + Int32 nGroups, nBytes; + + /*-- + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + is a global since the decoder also needs it. + + Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + are also globals only used in this proc. + Made global to keep stack frame size small. + --*/ + + + UInt16 cost[BZ_N_GROUPS]; + Int32 fave[BZ_N_GROUPS]; + + UInt16* mtfv = s->mtfv; + + + alphaSize = s->nInUse+2; + for (t = 0; t < BZ_N_GROUPS; t++) + for (v = 0; v < alphaSize; v++) + s->len[t][v] = BZ_GREATER_ICOST; + + /*--- Decide how many coding tables to use ---*/ + AssertH ( s->nMTF > 0, 3001 ); + if (s->nMTF < 200) nGroups = 2; else + if (s->nMTF < 600) nGroups = 3; else + if (s->nMTF < 1200) nGroups = 4; else + if (s->nMTF < 2400) nGroups = 5; else + nGroups = 6; + + /*--- Generate an initial set of coding tables ---*/ + { + Int32 nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = s->nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs-1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize-1) { + ge++; + aFreq += s->mtfFreq[ge]; + } + + if (ge > gs + && nPart != nGroups && nPart != 1 + && ((nGroups-nPart) % 2 == 1)) { + aFreq -= s->mtfFreq[ge]; + ge--; + } + + for (v = 0; v < alphaSize; v++) + if (v >= gs && v <= ge) + s->len[nPart-1][v] = BZ_LESSER_ICOST; else + s->len[nPart-1][v] = BZ_GREATER_ICOST; + + nPart--; + gs = ge+1; + remF -= aFreq; + } + } + + /*--- + Iterate up to BZ_N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZ_N_ITERS; iter++) { + + for (t = 0; t < nGroups; t++) fave[t] = 0; + + for (t = 0; t < nGroups; t++) + for (v = 0; v < alphaSize; v++) + s->rfreq[t][v] = 0; + + /*--- + Set up an auxiliary length table which is used to fast-track + the common case (nGroups == 6). + ---*/ + if (nGroups == 6) { + for (v = 0; v < alphaSize; v++) { + s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; + s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; + s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (True) { + + /*--- Set group start & end marks. --*/ + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (t = 0; t < nGroups; t++) cost[t] = 0; + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + register UInt32 cost01, cost23, cost45; + register UInt16 icv; + cost01 = cost23 = cost45 = 0; + +# define BZ_ITER(nn) \ + icv = mtfv[gs+(nn)]; \ + cost01 += s->len_pack[icv][0]; \ + cost23 += s->len_pack[icv][1]; \ + cost45 += s->len_pack[icv][2]; \ + + BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); + BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); + BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); + BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); + BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); + BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); + BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); + BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); + BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); + BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); + +# undef BZ_ITER + + cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; + cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; + cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + UInt16 icv = mtfv[i]; + for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; bt = -1; + for (t = 0; t < nGroups; t++) + if (cost[t] < bc) { bc = cost[t]; bt = t; }; + totc += bc; + fave[bt]++; + s->selector[nSelectors] = bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + +# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ + + BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); + BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); + BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); + BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); + BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); + BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); + BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); + BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); + BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); + BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); + +# undef BZ_ITUR + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) + s->rfreq[bt][ mtfv[i] ]++; + } + + gs = ge+1; + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (t = 0; t < nGroups; t++) + BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), + alphaSize, 20 ); + } + + + AssertH( nGroups < 8, 3002 ); + AssertH( nSelectors < 32768 && + nSelectors <= (2 + (NSIS_COMPRESS_BZIP2_LEVEL * 100000 / BZ_G_SIZE)), + 3003 ); + + + /*--- Compute MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) pos[i] = i; + for (i = 0; i < nSelectors; i++) { + ll_i = s->selector[i]; + j = 0; + tmp = pos[j]; + while ( ll_i != tmp ) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + }; + pos[0] = tmp; + s->selectorMtf[i] = j; + } + }; + + /*--- Assign actual codes for the tables. --*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + AssertH ( !(maxLen > 20), 3004 ); + AssertH ( !(minLen < 1), 3005 ); + BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), + minLen, maxLen, alphaSize ); + } + + /*--- Transmit the mapping table. ---*/ + { + Bool inUse16[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = False; + for (j = 0; j < 16; j++) + if (s->inUse[i * 16 + j]) inUse16[i] = True; + } + + nBytes = s->numZ; + for (i = 0; i < 16; i++) + if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); + + for (i = 0; i < 16; i++) + if (inUse16[i]) + for (j = 0; j < 16; j++) { + if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); + } + + } + + /*--- Now the selectors. ---*/ + nBytes = s->numZ; + bsW ( s, 3, nGroups ); + bsW ( s, 15, nSelectors ); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); + bsW(s,1,0); + } + + /*--- Now the coding tables. ---*/ + nBytes = s->numZ; + + for (t = 0; t < nGroups; t++) { + Int32 curr = s->len[t][0]; + bsW ( s, 5, curr ); + for (i = 0; i < alphaSize; i++) { + while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; + while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; + bsW ( s, 1, 0 ); + } + } + + + /*--- And finally, the block data proper ---*/ + nBytes = s->numZ; + selCtr = 0; + gs = 0; + while (True) { + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + AssertH ( s->selector[selCtr] < nGroups, 3006 ); + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + UInt16 mtfv_i; + UChar* s_len_sel_selCtr + = &(s->len[s->selector[selCtr]][0]); + Int32* s_code_sel_selCtr + = &(s->code[s->selector[selCtr]][0]); + +# define BZ_ITAH(nn) \ + mtfv_i = mtfv[gs+(nn)]; \ + bsW ( s, \ + s_len_sel_selCtr[mtfv_i], \ + s_code_sel_selCtr[mtfv_i] ) + + BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); + BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); + BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); + BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); + BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); + BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); + BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); + BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); + BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); + BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); + +# undef BZ_ITAH + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + bsW ( s, + s->len [s->selector[selCtr]] [mtfv[i]], + s->code [s->selector[selCtr]] [mtfv[i]] ); + } + } + + + gs = ge+1; + selCtr++; + } + AssertH( selCtr == nSelectors, 3007 ); + +} + + +/*---------------------------------------------------*/ +void BZ2_compressBlock ( EState* s, Bool is_last_block ) +{ + if (s->nblock > 0) { + + if (s->blockNo > 1) s->numZ = 0; + + + BZ2_blockSort ( s ); + } + + s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); + + /*-- If this is the first block, create the stream header. --*/ + if (s->blockNo == 1) { + BZ2_bsInitWrite ( s ); + } + + if (s->nblock > 0) { + + bsPutUChar ( s, 0x31 ); +#if 0 + bsPutUChar ( s, 0x41 ); + bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); + bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); +#endif + + /*-- Now the block's CRC, so it is in a known place. --*/ +// bsPutUInt32 ( s, s->blockCRC ); + + /*-- + Now a single bit indicating (non-)randomisation. + As of version 0.9.5, we use a better sorting algorithm + which makes randomisation unnecessary. So always set + the randomised bit to 'no'. Of course, the decoder + still needs to be able to handle randomised blocks + so as to maintain backwards compatibility with + older versions of bzip2. + --*/ + bsW(s,1,0); + + bsW ( s, 24, s->origPtr ); + generateMTFValues ( s ); + sendMTFValues ( s ); + } + + + /*-- If this is the last block, add the stream trailer. --*/ + if (is_last_block) { + + bsPutUChar ( s, 0x17 ); +#if 0 + bsPutUChar ( s, 0x72 ); + bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); + bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); +#endif +// bsPutUInt32 ( s, s->combinedCRC ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/decompress.c b/Source/bzip2/decompress.c new file mode 100644 index 00000000..4cbc23e8 --- /dev/null +++ b/Source/bzip2/decompress.c @@ -0,0 +1,569 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_BZIP2 + +/*-------------------------------------------------------------*/ +/*--- Decompression machinery ---*/ +/*--- decompress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +static +void makeMaps_d ( DState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->seqToUnseq[s->nInUse] = i; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + + +static int __mygetbits(int *vtmp, int nnn, DState* s) +{ + for (;;) { + if (s->bsLive >= nnn) { + UInt32 v; + v = (s->bsBuff >> + (s->bsLive-nnn)) & ((1 << nnn)-1); + s->bsLive -= nnn; + *vtmp = v; + break; + } + if (s->strm->avail_in == 0) return 1; + s->bsBuff = (s->bsBuff << 8) | ((UInt32) (*((UChar*)(s->strm->next_in)))); + s->bsLive += 8; + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + return 0; +} + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + { int vtmp; if (__mygetbits(&vtmp,nnn,s)) RETURN(BZ_OK) \ + (vvv) = vtmp; } + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (groupPos == 0) { \ + groupNo++; \ + if (groupNo >= nSelectors) \ + RETURN(BZ_DATA_ERROR); \ + groupPos = BZ_G_SIZE; \ + gSel = s->selector[groupNo]; \ + gMinlen = s->minLens[gSel]; \ + gLimit = &(s->limit[gSel][0]); \ + gPerm = &(s->perm[gSel][0]); \ + gBase = &(s->base[gSel][0]); \ + } \ + groupPos--; \ + zn = gMinlen; \ + GET_BITS(label1, zvec, zn); \ + while (1) { \ + if (zn > 20 /* the longest code */) \ + RETURN(BZ_DATA_ERROR); \ + if (zvec <= gLimit[zn]) break; \ + zn++; \ + GET_BIT(label2, zj); \ + zvec = (zvec << 1) | zj; \ + }; \ + if (zvec - gBase[zn] < 0 \ + || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ + RETURN(BZ_DATA_ERROR); \ + lval = gPerm[zvec - gBase[zn]]; \ +} + + +/*---------------------------------------------------*/ +Int32 BZ2_decompress ( DState* s ) +{ + UChar uc; + Int32 retVal; + Int32 minLen, maxLen; + bz_stream* strm = s->strm; + + /* stuff that needs to be saved/restored */ + Int32 i; + Int32 j; + Int32 t; + Int32 alphaSize; + Int32 nGroups; + Int32 nSelectors; + Int32 EOB; + Int32 groupNo; + Int32 groupPos; + Int32 nextSym; + Int32 nblockMAX; + Int32 nblock; + Int32 es; + Int32 N; + Int32 curr; + Int32 zt; + Int32 zn; + Int32 zvec; + Int32 zj; + Int32 gSel; + Int32 gMinlen; + Int32* gLimit; + Int32* gBase; + Int32* gPerm; + + /*restore from the save area*/ + i = s->save_i; + j = s->save_j; + t = s->save_t; + alphaSize = s->save_alphaSize; + nGroups = s->save_nGroups; + nSelectors = s->save_nSelectors; + EOB = s->save_EOB; + groupNo = s->save_groupNo; + groupPos = s->save_groupPos; + nextSym = s->save_nextSym; + nblockMAX = s->save_nblockMAX; + nblock = s->save_nblock; + es = s->save_es; + N = s->save_N; + curr = s->save_curr; + zt = s->save_zt; + zn = s->save_zn; + zvec = s->save_zvec; + zj = s->save_zj; + gSel = s->save_gSel; + gMinlen = s->save_gMinlen; + gLimit = s->save_gLimit; + gBase = s->save_gBase; + gPerm = s->save_gPerm; + + retVal = BZ_OK; + + switch (s->state) { + + + GET_UCHAR(BZ_X_BLKHDR_1, uc); + + if (uc == 0x17) + { + s->state = BZ_X_IDLE; + RETURN(BZ_STREAM_END); + } + if (uc != 0x31) RETURN(BZ_DATA_ERROR); + + s->currBlockNo++; + + GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); + + s->origPtr = 0; + GET_UCHAR(BZ_X_ORIGPTR_1, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_2, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_3, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + + if (s->origPtr < 0) + RETURN(BZ_DATA_ERROR); + if (s->origPtr > 10 + NSIS_COMPRESS_BZIP2_LEVEL*100000) + RETURN(BZ_DATA_ERROR); + + /*--- Receive the mapping table ---*/ + for (i = 0; i < 16; i++) { + GET_BIT(BZ_X_MAPPING_1, uc); + if (uc == 1) + s->inUse16[i] = True; else + s->inUse16[i] = False; + } + + for (i = 0; i < 256; i++) s->inUse[i] = False; + + for (i = 0; i < 16; i++) + if (s->inUse16[i]) + for (j = 0; j < 16; j++) { + GET_BIT(BZ_X_MAPPING_2, uc); + if (uc == 1) s->inUse[i * 16 + j] = True; + } + makeMaps_d ( s ); + if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); + alphaSize = s->nInUse+2; + + /*--- Now the selectors ---*/ + GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); + if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); + if (nSelectors < 1) RETURN(BZ_DATA_ERROR); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (True) { + GET_BIT(BZ_X_SELECTOR_3, uc); + if (uc == 0) break; + j++; + if (j >= nGroups) RETURN(BZ_DATA_ERROR); + } + s->selectorMtf[i] = j; + } + + /*--- Undo the MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], tmp, v; + for (v = 0; v < nGroups; v++) pos[v] = v; + + for (i = 0; i < nSelectors; i++) { + v = s->selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { pos[v] = pos[v-1]; v--; } + pos[0] = tmp; + s->selector[i] = tmp; + } + } + + /*--- Now the coding tables ---*/ + for (t = 0; t < nGroups; t++) { + GET_BITS(BZ_X_CODING_1, curr, 5); + for (i = 0; i < alphaSize; i++) { + while (True) { + if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); + GET_BIT(BZ_X_CODING_2, uc); + if (uc == 0) break; + GET_BIT(BZ_X_CODING_3, uc); + if (uc == 0) curr++; else curr--; + } + s->len[t][i] = curr; + } + } + + /*--- Create the Huffman decoding tables ---*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + BZ2_hbCreateDecodeTables ( + &(s->limit[t][0]), + &(s->base[t][0]), + &(s->perm[t][0]), + &(s->len[t][0]), + minLen, maxLen, alphaSize + ); + s->minLens[t] = minLen; + } + + /*--- Now the MTF values ---*/ + + EOB = s->nInUse+1; + nblockMAX = NSIS_COMPRESS_BZIP2_LEVEL*100000; + groupNo = -1; + groupPos = 0; + + for (i = 0; i <= 255; i++) s->unzftab[i] = 0; + + /*-- MTF init --*/ + { + Int32 ii, jj, kk; + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + /*-- end MTF init --*/ + + nblock = 0; + GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); + + while (True) { + + if (nextSym == EOB) break; + + if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + + es = -1; + N = 1; + do { + if (nextSym == BZ_RUNA) es = es + (0+1) * N; else + if (nextSym == BZ_RUNB) es = es + (1+1) * N; + N = N * 2; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); + + es++; + uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; + s->unzftab[uc] += es; + +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->ll16[nblock] = (UInt16)uc; + nblock++; + es--; + } +#else + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->tt[nblock] = (UInt32)uc; + nblock++; + es--; + } +#endif + continue; + + } else { + + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + + /*-- uc = MTF ( nextSym-1 ) --*/ + { + Int32 ii, jj, kk, pp, lno, off; + UInt32 nn; + nn = (UInt32)(nextSym - 1); + + if (nn < MTFL_SIZE) { + /* avoid general-case expense */ + pp = s->mtfbase[0]; + uc = s->mtfa[pp+nn]; + while (nn > 3) { + Int32 z = pp+nn; + s->mtfa[(z) ] = s->mtfa[(z)-1]; + s->mtfa[(z)-1] = s->mtfa[(z)-2]; + s->mtfa[(z)-2] = s->mtfa[(z)-3]; + s->mtfa[(z)-3] = s->mtfa[(z)-4]; + nn -= 4; + } + while (nn > 0) { + s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; + }; + s->mtfa[pp] = uc; + } else { + /* general case */ + lno = nn / MTFL_SIZE; + off = nn % MTFL_SIZE; + pp = s->mtfbase[lno] + off; + uc = s->mtfa[pp]; + while (pp > s->mtfbase[lno]) { + s->mtfa[pp] = s->mtfa[pp-1]; pp--; + }; + s->mtfbase[lno]++; + while (lno > 0) { + s->mtfbase[lno]--; + s->mtfa[s->mtfbase[lno]] + = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; + lno--; + } + s->mtfbase[0]--; + s->mtfa[s->mtfbase[0]] = uc; + if (s->mtfbase[0] == 0) { + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + } + } + /*-- end uc = MTF ( nextSym-1 ) --*/ + + s->unzftab[s->seqToUnseq[uc]]++; +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE + s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); +#else + s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); +#endif + nblock++; + + GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); + continue; + } + } + + /* Now we know what nblock is, we can do a better sanity + check on s->origPtr. + */ + if (s->origPtr < 0 || s->origPtr >= nblock) + RETURN(BZ_DATA_ERROR); + + s->state_out_len = 0; + s->state_out_ch = 0; + s->state = BZ_X_OUTPUT; + + /*-- Set up cftab to facilitate generation of T^(-1) --*/ + s->cftab[0] = 0; + for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]+s->cftab[i-1]; +// for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE + { + /*-- Make a copy of cftab, used in generation of T --*/ + for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; + + /*-- compute the T vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->ll16[i]); + SET_LL(i, s->cftabCopy[uc]); + s->cftabCopy[uc]++; + } + + /*-- Compute T^(-1) by pointer reversal on T --*/ + i = s->origPtr; + j = GET_LL(i); + do { + Int32 tmp = GET_LL(j); + SET_LL(j, i); + i = j; + j = tmp; + } + while (i != s->origPtr); + + s->tPos = s->origPtr; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_SMALL(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +#else//!small + + /*-- compute the T^(-1) vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->tt[i] & 0xff); + s->tt[s->cftab[uc]] |= (i << 8); + s->cftab[uc]++; + } + + s->tPos = s->tt[s->origPtr] >> 8; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_FAST(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_FAST(s->k0); s->nblock_used++; + } + +#endif + RETURN(BZ_OK); + + default: AssertH ( False, 4001 ); + } + + AssertH ( False, 4002 ); + + save_state_and_return: + + s->save_i = i; + s->save_j = j; + s->save_t = t; + s->save_alphaSize = alphaSize; + s->save_nGroups = nGroups; + s->save_nSelectors = nSelectors; + s->save_EOB = EOB; + s->save_groupNo = groupNo; + s->save_groupPos = groupPos; + s->save_nextSym = nextSym; + s->save_nblockMAX = nblockMAX; + s->save_nblock = nblock; + s->save_es = es; + s->save_N = N; + s->save_curr = curr; + s->save_zt = zt; + s->save_zn = zn; + s->save_zvec = zvec; + s->save_zj = zj; + s->save_gSel = gSel; + s->save_gMinlen = gMinlen; + s->save_gLimit = gLimit; + s->save_gBase = gBase; + s->save_gPerm = gPerm; + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ +#endif \ No newline at end of file diff --git a/Source/bzip2/huffman.c b/Source/bzip2/huffman.c new file mode 100644 index 00000000..4a8b37fa --- /dev/null +++ b/Source/bzip2/huffman.c @@ -0,0 +1,229 @@ +/*-------------------------------------------------------------*/ +/*--- Huffman coding low-level stuff ---*/ +/*--- huffman.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + +#ifndef EXEHEAD +/*---------------------------------------------------*/ +#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) +#define DEPTHOF(zz1) ((zz1) & 0x000000ff) +#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) + +#define ADDWEIGHTS(zw1,zw2) \ + (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ + (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) + +#define UPHEAP(z) \ +{ \ + Int32 zz, tmp; \ + zz = z; tmp = heap[zz]; \ + while (weight[tmp] < weight[heap[zz >> 1]]) { \ + heap[zz] = heap[zz >> 1]; \ + zz >>= 1; \ + } \ + heap[zz] = tmp; \ +} + +#define DOWNHEAP(z) \ +{ \ + Int32 zz, yy, tmp; \ + zz = z; tmp = heap[zz]; \ + while (True) { \ + yy = zz << 1; \ + if (yy > nHeap) break; \ + if (yy < nHeap && \ + weight[heap[yy+1]] < weight[heap[yy]]) \ + yy++; \ + if (weight[tmp] < weight[heap[yy]]) break; \ + heap[zz] = heap[yy]; \ + zz = yy; \ + } \ + heap[zz] = tmp; \ +} + + +/*---------------------------------------------------*/ +void BZ2_hbMakeCodeLengths ( UChar *len, + Int32 *freq, + Int32 alphaSize, + Int32 maxLen ) +{ + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + Int32 nNodes, nHeap, n1, n2, i, j, k; + Bool tooLong; + + static Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; + static Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; + static Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; + + for (i = 0; i < alphaSize; i++) + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + + while (True) { + + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + UPHEAP(nHeap); + } + + AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); + + while (nHeap > 1) { + n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + nNodes++; + parent[n1] = parent[n2] = nNodes; + weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + UPHEAP(nHeap); + } + + AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); + + tooLong = False; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { k = parent[k]; j++; } + len[i-1] = j; + if (j > maxLen) tooLong = True; + } + + if (! tooLong) break; + + for (i = 1; i < alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbAssignCodes ( Int32 *code, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) + if (length[i] == n) { code[i] = vec; vec++; }; + vec <<= 1; + } +} +#endif + + +/*---------------------------------------------------*/ +void BZ2_hbCreateDecodeTables ( Int32 *limit, + Int32 *base, + Int32 *perm, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) + for (j = 0; j < alphaSize; j++) + if (length[j] == i) { perm[pp] = j; pp++; }; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; + for (i = 0; i < alphaSize; i++) base[length[i]+1]++; + + for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (base[i+1] - base[i]); + limit[i] = vec-1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) + base[i] = ((limit[i-1] + 1) << 1) - base[i]; +} + + +/*-------------------------------------------------------------*/ +/*--- end huffman.c ---*/ +/*-------------------------------------------------------------*/ \ No newline at end of file diff --git a/Source/bzip2/randtable.c b/Source/bzip2/randtable.c new file mode 100644 index 00000000..99969350 --- /dev/null +++ b/Source/bzip2/randtable.c @@ -0,0 +1,127 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_BZIP2 + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------*/ +Int16 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ +#endif \ No newline at end of file diff --git a/Source/cbzip2.h b/Source/cbzip2.h new file mode 100644 index 00000000..46fd733c --- /dev/null +++ b/Source/cbzip2.h @@ -0,0 +1,51 @@ +#ifndef __CBZIP2_H__ +#define __CBZIP2_H__ + +#include "compressor.h" +#include "bzip2/bzlib.h" + +class CBzip2 : public ICompressor { + public: + int Init(int level) { + stream = new bz_stream; + if (!stream) return BZ_MEM_ERROR; + return BZ2_bzCompressInit(stream, level, 0, 30); + } + + int End() { + int ret = BZ2_bzCompressEnd(stream); + delete stream; + return ret; + } + + int Compress(BOOL finish) { + return BZ2_bzCompress(stream, finish?BZ_FINISH:0); + } + + void SetNextIn(char *in, unsigned int size) { + stream->next_in = in; + stream->avail_in = size; + } + + void SetNextOut(char *out, unsigned int size) { + stream->next_out = out; + stream->avail_out = size; + } + + virtual char* GetNextOut() { + return stream->next_out; + } + + virtual unsigned int GetAvailIn() { + return stream->avail_in; + } + + virtual unsigned int GetAvailOut() { + return stream->avail_out; + } + + private: + bz_stream *stream; +}; + +#endif \ No newline at end of file diff --git a/Source/compressor.h b/Source/compressor.h new file mode 100644 index 00000000..f7c7aa8a --- /dev/null +++ b/Source/compressor.h @@ -0,0 +1,22 @@ +#ifndef __COMPRESSOR_H__ +#define __COMPRESSOR_H__ + +#define C_OK 0 +#define C_FINISH TRUE + +class ICompressor { + public: + virtual int Init(int level) = 0; + virtual int End() = 0; + virtual int Compress(BOOL finish) = 0; + + virtual void SetNextIn(char *in, unsigned int size) = 0; + virtual void SetNextOut(char *out, unsigned int size) = 0; + + virtual char* GetNextOut() = 0; + + virtual unsigned int GetAvailIn() = 0; + virtual unsigned int GetAvailOut() = 0; +}; + +#endif \ No newline at end of file diff --git a/Source/crc32.c b/Source/crc32.c new file mode 100644 index 00000000..d7feea83 --- /dev/null +++ b/Source/crc32.c @@ -0,0 +1,34 @@ +#include "exehead/config.h" +#ifdef NSIS_CONFIG_CRC_SUPPORT + +// this is based on the (slow,small) CRC32 implementation from zlib. + +static unsigned long crc_table[256]; + +static void make_crc_table() +{ + unsigned long c; + int n, k; + + for (n = 0; n < 256; n++) + { + c = (unsigned long)n; + for (k = 0; k < 8; k++) c = (c >> 1) ^ (c & 1 ? 0xedb88320L : 0); + crc_table[n] = c; + } +} + + +// actually CRC32, but we put it in here so we don't +// have to modify the other code. +unsigned long CRC32(unsigned long crc, const unsigned char *buf, unsigned int len) +{ + if (!crc_table[1]) make_crc_table(); + crc = crc ^ 0xffffffffL; + while (len-- > 0) { + crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8); + } + return crc ^ 0xffffffffL; +} + +#endif \ No newline at end of file diff --git a/Source/czlib.h b/Source/czlib.h new file mode 100644 index 00000000..3b092517 --- /dev/null +++ b/Source/czlib.h @@ -0,0 +1,51 @@ +#ifndef __CZLIB_H__ +#define __CZLIB_H__ + +#include "compressor.h" +#include "zlib/ZLIB.H" + +class CZlib : public ICompressor { + public: + int Init(int level) { + stream = new z_stream; + if (!stream) return Z_MEM_ERROR; + return deflateInit(stream, level); + } + + int End() { + int ret = deflateEnd(stream); + delete stream; + return ret; + } + + int Compress(BOOL finish) { + return deflate(stream, finish?Z_FINISH:0); + } + + void SetNextIn(char *in, unsigned int size) { + stream->next_in = (unsigned char*)in; + stream->avail_in = size; + } + + void SetNextOut(char *out, unsigned int size) { + stream->next_out = (unsigned char*)out; + stream->avail_out = size; + } + + virtual char* GetNextOut() { + return (char*)stream->next_out; + } + + virtual unsigned int GetAvailIn() { + return stream->avail_in; + } + + virtual unsigned int GetAvailOut() { + return stream->avail_out; + } + + private: + z_stream *stream; +}; + +#endif \ No newline at end of file diff --git a/Source/exedata.cpp b/Source/exedata.cpp new file mode 100644 index 00000000..7d2b0933 --- /dev/null +++ b/Source/exedata.cpp @@ -0,0 +1,17 @@ +#include "exedata.h" + +#ifdef NSIS_CONFIG_COMPONENTPAGE +#include "exehead/Release-zlib/bitmap1.h" +#endif +#include "exehead/Release-zlib/icon.h" +#include "exehead/Release-zlib/unicon.h" +#include "exehead/Release-zlib/exehead_zlib.h" +#include "exehead/Release-bzip2/exehead_bzip2.h" +// Changed by Amir Szekely 31st July 2002 +int zlib_exeheader_size=sizeof(zlib_header_data); +int bzip2_exeheader_size=sizeof(bzip2_header_data); +int exeheader_size=0; + +// Changed by Amir Szekely 8th July 2002 +int icondata_size=sizeof(icon_data)-22; +int unicondata_size=sizeof(unicon_data)-22; diff --git a/Source/exedata.h b/Source/exedata.h new file mode 100644 index 00000000..c4ed9db3 --- /dev/null +++ b/Source/exedata.h @@ -0,0 +1,16 @@ +#ifndef _EXEDATA_H_ +#define _EXEDATA_H_ + +extern int zlib_exeheader_size; +extern int bzip2_exeheader_size; +extern int exeheader_size; +extern int icondata_size; +extern int unicondata_size; + +extern unsigned char zlib_header_data[]; +extern unsigned char bzip2_header_data[]; +extern unsigned char icon_data[]; +extern unsigned char unicon_data[]; +extern unsigned char bitmap1_data[630]; + +#endif //_EXEDATA_H_ \ No newline at end of file diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c new file mode 100644 index 00000000..e5b9153f --- /dev/null +++ b/Source/exehead/Main.c @@ -0,0 +1,364 @@ +/* + Nullsoft "SuperPimp" Installation System - main.c - executable header main code + + Copyright (C) 1999-2002 Nullsoft, Inc. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + This source distribution includes portions of zlib. see zlib/zlib.h for + its license and so forth. Note that this license is also borrowed from zlib. +*/ + + +#include +#include +#include "resource.h" +#include "util.h" +#include "fileform.h" +#include "state.h" +#include "ui.h" + +#include "lang.h" + +extern unsigned long CRC32(unsigned long crc, const unsigned char *buf, unsigned int len); + +#if !defined(NSIS_CONFIG_VISIBLE_SUPPORT) && !defined(NSIS_CONFIG_SILENT_SUPPORT) +#error One of NSIS_CONFIG_SILENT_SUPPORT or NSIS_CONFIG_VISIBLE_SUPPORT must be defined. +#endif +#ifdef NSIS_COMPRESS_WHOLE +extern HANDLE dbd_hFile; +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT +static const char *g_crcinvalid=_LANG_INVALIDCRC; +#else +static const char *g_crcinvalid=_LANG_INVALIDINST; +#endif + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +static const char *g_errorcopyinginstall=_LANG_UNINSTINITERROR; +#endif + +char g_caption[NSIS_MAX_STRLEN*2]; +int g_filehdrsize; +HWND g_hwnd; + +static int m_length; +static int m_pos; + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_CRC_SUPPORT +static BOOL CALLBACK verProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_INITDIALOG) + { + SetTimer(hwndDlg,1,250,NULL); + uMsg = WM_TIMER; + } + if (uMsg == WM_TIMER) + { + static char bt[64]; + wsprintf(bt,_LANG_VERIFYINGINST,MulDiv(m_pos,100,m_length)); + + SetWindowText(hwndDlg,bt); + SetDlgItemText(hwndDlg,IDC_STR,bt); + } + return 0; +} +#endif//NSIS_CONFIG_CRC_SUPPORT +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow) +{ + static int ret; + static const char *m_Err; +#ifdef NSIS_CONFIG_CRC_SUPPORT +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + static HWND hwnd; +#endif + static int crc; + static char no_crc; + static char do_crc; +#endif//NSIS_CONFIG_CRC_SUPPORT +#if defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) + static char silent; +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT + int left; + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + unsigned int verify_time=GetTickCount()+1000; +#endif + char *cmdline=state_command_line; + char *realcmds; + char seekchar=' '; + + InitCommonControls(); + lstrcpyn(state_command_line,GetCommandLine(),NSIS_MAX_STRLEN); + + if (*cmdline == '\"') seekchar = *cmdline++; + + while (*cmdline && *cmdline != seekchar) if (*cmdline) cmdline++; + if (*cmdline) cmdline++; + realcmds=cmdline; + + do + { +#ifdef NSIS_CONFIG_CRC_SUPPORT +#endif//NSIS_CONFIG_CRC_SUPPORT + while (*cmdline == ' ') if (*cmdline) cmdline++; + if (cmdline[0] != '/') break; + cmdline++; +#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT) + if (cmdline[0] == 'S' && (cmdline[1] == ' ' || !cmdline[1])) + { + silent++; + cmdline+=2; + } + else +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (cmdline[0] == 'N' && + cmdline[1] == 'C' && + cmdline[2] == 'R' && + cmdline[3] == 'C' && + (cmdline[4] == ' ' || !cmdline[4])) + { + no_crc++; + cmdline+=4; + } + else +#endif//NSIS_CONFIG_CRC_SUPPORT + if (cmdline[0] == 'D' && cmdline[1] == '=') + { + cmdline[-2]=0; // keep this from being passed to uninstaller if necessary + lstrcpy(state_install_directory,cmdline+2); + cmdline+=lstrlen(cmdline); + } + else while (*cmdline && *cmdline != ' ') if (*cmdline) cmdline++; + } + while (*cmdline); + + lstrcpy(g_caption,_LANG_GENERIC_ERROR); + + g_hInstance=GetModuleHandle(NULL); + GetModuleFileName(g_hInstance,state_exe_directory,NSIS_MAX_STRLEN); + + g_db_hFile=myOpenFile(state_exe_directory,GENERIC_READ,OPEN_EXISTING); + if (g_db_hFile==INVALID_HANDLE_VALUE) + { + m_Err = _LANG_CANTOPENSELF; + goto end; + } + + // make state_exe_directory point to dir, not full exe. + + trimslashtoend(state_exe_directory); + + left = m_length = GetFileSize(g_db_hFile,NULL); + while (left > 0) + { + static char temp[512]; + DWORD l=left; + if (l > 512) l=512; + if (!ReadFile(g_db_hFile,temp,l,&l,NULL)) + { + m_Err=g_crcinvalid; +#if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) + if (hwnd) DestroyWindow(hwnd); +#endif//NSIS_CONFIG_CRC_SUPPORT + goto end; + } + + if (!g_filehdrsize) + { + int dbl; + dbl=isheader((firstheader*)temp); + if (dbl) + { + int a=*(int*)temp; + g_filehdrsize=m_pos; + if (dbl > left) + { + m_Err=g_crcinvalid; + goto end; + } +#if defined(NSIS_CONFIG_SILENT_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) + if (a&FH_FLAGS_SILENT) silent++; +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_CRC_SUPPORT + // Changed by Amir Szekely 23rd July 2002 (CRCCheck force) + if ((no_crc && !(a&FH_FLAGS_FORCE_CRC)) || !(a&FH_FLAGS_CRC)) break; // if first bit is not set, then no crc checking. + + do_crc++; + +#ifndef NSIS_CONFIG_CRC_ANAL + left=dbl-4; + // end crc checking at crc :) this means you can tack shit on the end and it'll still work. +#else //!NSIS_CONFIG_CRC_ANAL + left-=4; +#endif//NSIS_CONFIG_CRC_ANAL + // this is in case the end part is < 512 bytes. + if (l > (DWORD)left) l=(DWORD)left; + +#else//!NSIS_CONFIG_CRC_SUPPORT + break; +#endif//!NSIS_CONFIG_CRC_SUPPORT + } + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + else if (!silent) +#endif//NSIS_CONFIG_SILENT_SUPPORT + { + if (hwnd) + { + static MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) DispatchMessage(&msg); + } + else if (GetTickCount() > verify_time) + hwnd=CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_VERIFY),GetDesktopWindow(),verProc); + } +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +#ifndef NSIS_CONFIG_CRC_ANAL + if (left= 31 || NSIS_MAX_INST_TYPES < 1 +#error invalid value for NSIS_MAX_INST_TYPES +#endif + +char g_autoclose; +char g_noicon; +int progress_bar_pos, progress_bar_len; + +HWND g_progresswnd; + +static char g_tmp[4096]; + +// sent to the last child window to tell it that the install thread is done +#define WM_NOTIFY_INSTPROC_DONE (WM_USER+0x4) + +// sent to the outer window to tell it to go to the next inner window +#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8) + +// update message used by DirProc and SelProc for space display +#define WM_IN_UPDATEMSG (WM_USER+0xf) + +#define WM_TREEVIEW_KEYHACK (WM_USER+0x13) + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); +#ifdef NSIS_CONFIG_LICENSEPAGE +static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif +static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +static DWORD WINAPI install_thread(LPVOID p); + +HWND bgWnd_Init(HINSTANCE hInstance, char *title, int color1, int color2, int); + +HWND insthwnd, insthwnd2,insthwndbutton; + +void *g_inst_combinedheader; +section *g_inst_section; +entry *g_inst_entry; +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +int g_is_uninstaller; +static int g_max_page=1; +static int g_page_offs=4; +#else +#define g_max_page 3 +#define g_page_offs 0 +#endif + +static int m_page=-1,m_abort; +static HWND m_curwnd; +static int m_whichcfg; + +#ifdef NSIS_CONFIG_LOG +static void build_g_logfile() +{ + lstrcpy(g_log_file,state_install_directory); + addtrailingslash(g_log_file); + lstrcat(g_log_file,"install.log"); +} +#endif + +#ifdef NSIS_CONFIG_COMPONENTPAGE +static void SetChildrenStates(HWND hWnd, TV_ITEM *pItem, int iState) { + HTREEITEM hItem; + int l=0; + + pItem->mask|=TVIF_PARAM; + + TreeView_GetItem(hWnd, pItem); + if (pItem->state >> 12 == 0) + return; + + if (iState < 3 && (g_inst_section[pItem->lParam].default_state & DFS_RO)) l=3; + + pItem->state = INDEXTOSTATEIMAGEMASK(iState+l); + pItem->stateMask = TVIS_STATEIMAGEMASK; + + if (!(g_inst_section[pItem->lParam].default_state & DFS_RO)) + { + if (iState == 2) g_inst_section[pItem->lParam].default_state |= DFS_SET; + else g_inst_section[pItem->lParam].default_state &= ~DFS_SET; + TreeView_SetItem(hWnd, pItem); + } + + hItem = TreeView_GetChild(hWnd, pItem->hItem); + while (hItem) { + pItem->hItem = hItem; + SetChildrenStates(hWnd, pItem, iState); + hItem = TreeView_GetNextSibling(hWnd, hItem); + } +} + +static void SetParentState(HWND hWnd, TV_ITEM *pItem) { + + HTREEITEM hItem; + int iState = 0, iStatePrev = 0; + + HTREEITEM hParent = TreeView_GetParent(hWnd, pItem->hItem); + if (!hParent) + return; + + hItem = TreeView_GetChild(hWnd, hParent); + + while (hItem) { + + pItem->hItem = hItem; + pItem->mask|=TVIF_PARAM; + TreeView_GetItem(hWnd, pItem); + iState = pItem->state >> 12; + if (iState && !(g_inst_section[pItem->lParam].default_state & DFS_RO)) + { + if (iState==5) iState=2; + else if (iState==4) iState=1; + + if (iStatePrev && (iStatePrev != iState)) { + iState = 3; + break; + } + iStatePrev = iState; + } + hItem = TreeView_GetNextSibling(hWnd, hItem); + } + + pItem->hItem = hParent; + if (iState) { + pItem->state = INDEXTOSTATEIMAGEMASK(iState); + TreeView_SetItem(hWnd, pItem); + } + + SetParentState(hWnd, pItem); + +} + + +static void CheckTreeItem(HWND hWnd, TV_ITEM *pItem, int checked) { + + HTREEITEM hItem = pItem->hItem; + int l=0; + + pItem->mask = TVIF_STATE|TVIF_PARAM; + TreeView_GetItem(hWnd, pItem); + if (pItem->state >> 12 == 0) + return; + + if (g_inst_section[pItem->lParam].default_state & DFS_RO) l=3; + + pItem->state = INDEXTOSTATEIMAGEMASK(checked?2:1+l); + pItem->stateMask = TVIS_STATEIMAGEMASK; + + TreeView_SetItem(hWnd, pItem); + + SetChildrenStates(hWnd, pItem, checked?2:1); + pItem->hItem = hItem; + SetParentState(hWnd, pItem); +} + +#endif//NSIS_CONFIG_COMPONENTPAGE + +int ui_doinstall(void) +{ + g_autoclose=g_inst_cmnheader->misc_flags&1; +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!g_is_uninstaller) + { + g_max_page=3; + g_page_offs=0; +#else + { +#endif + if (!is_valid_instpath(state_install_directory)) + { + if (g_inst_header->install_reg_key_ptr>=0) + { + myRegGetStr((HKEY)g_inst_header->install_reg_rootkey, + GetStringFromStringTab(g_inst_header->install_reg_key_ptr), + GetStringFromStringTab(g_inst_header->install_reg_value_ptr),ps_tmpbuf); + if (ps_tmpbuf[0]) + { + char *p=ps_tmpbuf; + char *e; + if (p[0]=='\"') + { + char *p2=*p?p+1:p; + p=p2; + while (*p2 && *p2 != '\"') if (*p2) p2++; + *p2=0; + } + // p is the path now, check for .exe extension + + e=p+lstrlen(p)-4; + if (e > p) + { + // if filename ends in .exe, and is not a directory, remove the filename + if (!lstrcmpi(e,".exe")) // check extension + { + DWORD d; + d=GetFileAttributes(p); + if (d == (DWORD)-1 || !(d&FILE_ATTRIBUTE_DIRECTORY)) + { + e=scanendslash(p); + if (e>=p) *e=0; + } + } + } + + lstrcpy(state_install_directory,p); + } + } + } + if (!is_valid_instpath(state_install_directory)) + { + process_string_fromtab(state_install_directory,g_inst_header->install_directory_ptr); + } + +#ifdef NSIS_CONFIG_LOG + if (g_inst_cmnheader->silent_install==2) + { + build_g_logfile(); + log_dolog=1; + } +#endif + } + + process_string_fromtab(g_caption,g_inst_cmnheader->caption_ptr); + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (!g_inst_cmnheader->silent_install) +#endif//NSIS_CONFIG_SILENT_SUPPORT + { + HWND h=GetDesktopWindow(); +#ifdef NSIS_SUPPORT_BGBG + if (g_inst_cmnheader->bg_color1 != -1) + { + h=bgWnd_Init(g_hInstance,g_caption,g_inst_cmnheader->bg_color1,g_inst_cmnheader->bg_color2,g_inst_cmnheader->bg_textcolor); + } +#endif//NSIS_SUPPORT_BGBG +#ifdef NSIS_SUPPORT_CODECALLBACKS + g_hwnd=h; + if (ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInit,NULL)) return 1; + g_hwnd=NULL; +#endif//NSIS_SUPPORT_CODECALLBACKS + return DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_INST),h,DialogProc); + } +#endif//NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_SILENT_SUPPORT +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + else +#endif + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInit,NULL)) return 1; +#endif//NSIS_SUPPORT_CODECALLBACKS + if (install_thread(NULL)) + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (!g_quit_flag) ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInstFailed,NULL); +#endif//NSIS_SUPPORT_CODECALLBACKS + return 1; + } +#ifdef NSIS_SUPPORT_CODECALLBACKS + ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInstSuccess,NULL); +#endif//NSIS_SUPPORT_CODECALLBACKS + return 0; + } +#endif//NSIS_CONFIG_SILENT_SUPPORT +} + + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +static int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + if (uMsg==BFFM_INITIALIZED) + { + GetDlgItemText((HWND)lpData,IDC_DIR,g_tmp,sizeof(g_tmp)); + SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,(LPARAM)g_tmp); + } + return 0; +} + + +static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HICON hIcon; + if (uMsg == WM_DESTROY && hIcon) { DeleteObject(hIcon); hIcon=0; } + if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT) + { + int iscp=0,islp=0,isdp=0,ispotentiallydp=0; + int delta=(uMsg == WM_NOTIFY_OUTER_NEXT)?wParam:0; + int prev_page=m_page; + static struct + { + char *id; + DLGPROC proc; + } + windows[]= + { +#ifdef NSIS_CONFIG_LICENSEPAGE + {MAKEINTRESOURCE(IDD_LICENSE),LicenseProc}, +#else + {NULL,NULL}, +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + {MAKEINTRESOURCE(IDD_SELCOM),SelProc}, +#else + {NULL,NULL}, +#endif + {MAKEINTRESOURCE(IDD_DIR),DirProc}, + {MAKEINTRESOURCE(IDD_INSTFILES),InstProc}, +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + {MAKEINTRESOURCE(IDD_UNINST),UninstProc}, + {MAKEINTRESOURCE(IDD_INSTFILES),InstProc}, +#endif + }; + + if (uMsg == WM_INITDIALOG) + { + g_hwnd=hwndDlg; + SetDlgItemText(hwndDlg,IDC_VERSTR,GetStringFromStringTab(g_inst_cmnheader->branding_ptr)); + hIcon=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_ICON2)); + SetClassLong(hwndDlg,GCL_HICON,(long)hIcon); + SetDlgItemText(hwndDlg,IDCANCEL,GetStringFromStringTab(g_inst_cmnheader->cancelbutton_ptr)); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!g_is_uninstaller) +#endif + SetDlgItemText(hwndDlg,IDC_BACK,GetStringFromStringTab(g_inst_header->backbutton_ptr)); + ShowWindow(hwndDlg,SW_SHOW); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (g_is_uninstaller) + { + islp=(g_inst_uninstheader->uninstalltext_ptr>=0); + iscp++; + } + else +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT + { +#ifdef NSIS_CONFIG_LICENSEPAGE + if (g_inst_header->licensedata_ptr>=0) islp++; +#endif//NSIS_CONFIG_LICENSEPAGE +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (g_inst_header->componenttext_ptr>=0) iscp++; +#endif//NSIS_CONFIG_COMPONENTPAGE + if (g_inst_header->text_ptr>=0) ispotentiallydp++; + if (ispotentiallydp && + !((g_inst_cmnheader->misc_flags&2) && + is_valid_instpath(state_install_directory) +#ifdef NSIS_SUPPORT_CODECALLBACKS + && !ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onVerifyInstDir,NULL) +#endif//NSIS_SUPPORT_CODECALLBACKS + )) isdp++; + } + + if (m_page<=0) delta=1; + do + { + int count=1; // Number of pages to move by +#ifdef NSIS_SUPPORT_CODECALLBACKS + // Call onNext|PrevPage for every not-definitely-disabled page + if (ExecuteCodeSegment(g_inst_entry,delta>0?g_inst_cmnheader->code_onNextPage:g_inst_header->code_onPrevPage,NULL)) + { + if (g_quit_flag) // Quit instruction used? + m_page=count=-1; + // Mmm - relies on ps_tmpbuf still being set from the Abort command - safe? + else if ((count = myatoi(ps_tmpbuf)) != 0) + count /= (delta = (count>0?1:-1)); + } +#endif//NSIS_SUPPORT_CODECALLBACKS + // Skip any definitely-disabled pages, then the required number of pages + while ((m_page==0 && !islp) || (m_page==1 && !iscp) || (m_page==2 && !ispotentiallydp) || (--count>=0)) + m_page+=delta; + // Skip any possibly-disabled pages + } while ((m_page >= 0) && (m_page <= g_max_page) && (m_page==2 && !isdp)); + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (m_page>g_max_page) ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInstSuccess,NULL); +#endif//NSIS_SUPPORT_CODECALLBACKS + + if (m_curwnd && (m_page!=prev_page)) + { + DestroyWindow(m_curwnd); + m_curwnd=0; + } + + if (m_page < 0 || m_page > g_max_page) + { + EndDialog(hwndDlg,0); + } + else if (!m_curwnd) + { + HWND hwndtmp; + SetDlgItemText(hwndDlg,IDOK,GetStringFromStringTab( + (m_page == g_max_page) ? g_inst_cmnheader->closebutton_ptr : +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + g_is_uninstaller ? g_inst_uninstheader->uninstbutton_ptr : +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE + (m_page == 0) ? g_inst_header->licensebutton_ptr : +#endif + (m_page == 2 || (m_page == 1 && !isdp)) ? g_inst_header->installbutton_ptr : + g_inst_header->nextbutton_ptr + )); + lstrcpy(g_tmp,g_caption); + process_string_fromtab(g_tmp+lstrlen(g_tmp),g_inst_cmnheader->subcaption_ptrs[m_page]); + + SetWindowText(hwndDlg,g_tmp); + + m_curwnd=CreateDialog(g_hInstance,windows[g_page_offs+m_page].id,hwndDlg,windows[g_page_offs+m_page].proc); + if (m_curwnd) + { + RECT r; + GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r); + ScreenToClient(hwndDlg,(LPPOINT)&r); + SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); + ShowWindow(m_curwnd,SW_SHOWNA); + } + + hwndtmp=GetDlgItem(hwndDlg,IDC_BACK); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + ShowWindow(hwndtmp,(m_page&&!g_is_uninstaller)?SW_SHOWNA:SW_HIDE); + if (!g_is_uninstaller) +#else + ShowWindow(hwndtmp,m_page?SW_SHOWNA:SW_HIDE); +#endif + EnableWindow(hwndtmp, (m_page==1&&islp) || (m_page==2&&(islp||iscp))); + SetFocus(GetDlgItem(hwndDlg,IDOK)); + } + } + if (uMsg == WM_COMMAND) + { + int id=LOWORD(wParam); + + if (id == IDOK && m_curwnd) + { + SendMessage(hwndDlg,WM_NOTIFY_OUTER_NEXT,1,0); + } + if ( +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + !g_is_uninstaller && +#endif + (id == IDC_BACK && m_curwnd && m_page>0)) + { + EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); + SendMessage(hwndDlg,WM_NOTIFY_OUTER_NEXT,-1,0); + } + if (id == IDCANCEL) + { + if (m_abort) + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onInstFailed,NULL); +#endif//NSIS_SUPPORT_CODECALLBACKS + EndDialog(hwndDlg,2); + } + else + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (!ExecuteCodeSegment(g_inst_entry,g_inst_cmnheader->code_onUserAbort,NULL)) +#endif//NSIS_SUPPORT_CODECALLBACKS + { + EndDialog(hwndDlg,1); + } + } + } + } + if (uMsg == WM_CLOSE) + { + if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDCANCEL)) && IsWindowEnabled(GetDlgItem(hwndDlg,IDOK))) + SendMessage(hwndDlg,WM_COMMAND,IDOK,0); + } + return 0; +} + +#ifdef NSIS_CONFIG_LICENSEPAGE +// Changed by Amir Szekely 27th July 2002 +#define _RICHEDIT_VER 0x0200 +#include +#undef _RICHEDIT_VER +static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HWND hwLicense = 0; + static HINSTANCE hRichEditDLL = 0; + if (!hRichEditDLL) hRichEditDLL= LoadLibrary("RichEd32.dll"); + if (uMsg == WM_INITDIALOG) + { + hwLicense=GetDlgItem(hwndDlg,IDC_EDIT1); + SendMessage(hwLicense,EM_AUTOURLDETECT,TRUE,0); + SendMessage(hwLicense,EM_SETBKGNDCOLOR,0,g_inst_header->license_bg); + SendMessage(hwLicense,EM_SETEVENTMASK,0,ENM_LINK); + SetWindowText(hwLicense,GetStringFromStringTab(g_inst_header->licensedata_ptr)); + SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->licensetext_ptr)); + } + else if (uMsg == WM_NOTIFY) { + ENLINK *enlink=(ENLINK *)lParam; + if (enlink->nmhdr.code==EN_LINK) { + if (enlink->msg==WM_LBUTTONDOWN) { + char *szUrl; + SendMessage(hwLicense,EM_SETSEL,enlink->chrg.cpMin,enlink->chrg.cpMax); + szUrl=(char *)GlobalAlloc(GPTR,enlink->chrg.cpMax-enlink->chrg.cpMin+1); + SendMessage(hwLicense,EM_GETSELTEXT,0,(LPARAM)szUrl); + SetCursor(LoadCursor(0,IDC_WAIT)); + ShellExecute(hwndDlg,"open",szUrl,NULL,NULL,SW_SHOWNORMAL); + SetCursor(LoadCursor(0,IDC_ARROW)); + GlobalFree(szUrl); + } + else if (enlink->msg==WM_SETCURSOR) { + SetCursor(LoadCursor(0,IDC_HAND)); + } + } + } + else if (uMsg == WM_CLOSE) { + FreeLibrary(hRichEditDLL); + SendMessage(GetParent(hwndDlg),WM_CLOSE,0,0); + } + return 0; +} +#endif + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_INITDIALOG) + { + SetDlgItemText(hwndDlg,IDC_UNINSTFROM,GetStringFromStringTab(g_inst_uninstheader->uninstalltext2_ptr)); + SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_uninstheader->uninstalltext_ptr)); + SetDlgItemText(hwndDlg,IDC_EDIT1,state_install_directory); + } + return 0; +} +#endif + + +static void inttosizestr(int kb, char *str) +{ + while (*str) str++; + if (kb < 1024) wsprintf(str,"%dKB",kb); + else if (kb < 1024*1024) wsprintf(str,"%d.%dMB",kb>>10,((kb*10)>>10)%10); + else wsprintf(str,"%d.%dGB%s",kb>>20,((kb*10)>>20)%10,(GetVersion()&0x80000000) ? "+":""); +} + +static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_DESTROY) + { + GetDlgItemText(hwndDlg,IDC_DIR,state_install_directory,NSIS_MAX_STRLEN); +#ifdef NSIS_CONFIG_LOG + build_g_logfile(); + log_dolog = !!IsDlgButtonChecked(hwndDlg,IDC_CHECK1); +#endif + } + if (uMsg == WM_INITDIALOG) + { +#ifdef NSIS_CONFIG_LOG + if (GetAsyncKeyState(VK_SHIFT)&0x8000) + { + HWND h=GetDlgItem(hwndDlg,IDC_CHECK1); + SetWindowText(h,"Log install process"); + ShowWindow(h,SW_SHOWNA); + } +#endif + SetDlgItemText(hwndDlg,IDC_DIR,state_install_directory); + SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->text_ptr)); + SetDlgItemText(hwndDlg,IDC_BROWSE,GetStringFromStringTab(g_inst_header->browse_ptr)); + SetDlgItemText(hwndDlg,IDC_SELDIRTEXT,GetStringFromStringTab(g_inst_header->dirsubtext_ptr)); + SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0); + } + if (uMsg == WM_COMMAND) + { + int id=LOWORD(wParam); + if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE) + { + SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0); + } + if (id == IDC_BROWSE) + { + char name[256]; + char str[256]; + BROWSEINFO bi={0,}; + ITEMIDLIST *idlist; + GetDlgItemText(hwndDlg,IDC_DIR,name,256); + GetDlgItemText(hwndDlg,IDC_SELDIRTEXT,str,256); + bi.hwndOwner = hwndDlg; + bi.pszDisplayName = name; + bi.lpfn=BrowseCallbackProc; + bi.lParam=(LPARAM)hwndDlg; + bi.lpszTitle = str; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + idlist = SHBrowseForFolder( &bi ); + if (idlist) + { + const char *post_str; + const char *p; + IMalloc *m; + SHGetPathFromIDList( idlist, name ); + SHGetMalloc(&m); + if (m) + { + m->lpVtbl->Free(m,idlist); + m->lpVtbl->Release(m); + } + post_str=GetStringFromStringTab(g_inst_header->install_directory_ptr); + + p=scanendslash(post_str); + if (p >= post_str && *++p) + { + post_str=p; + p=name+lstrlen(name)-lstrlen(post_str); + if (p <= name || *CharPrev(name,p)!='\\' || lstrcmpi(p,post_str)) + { + addtrailingslash(name); + lstrcat(name,post_str); + } + } + + SetDlgItemText(hwndDlg,IDC_DIR,name); + } + } + } + if (uMsg == WM_IN_UPDATEMSG) + { + static char s[NSIS_MAX_STRLEN]; + int is_valid_path; + int x; + int total=0, available=-1; + DWORD spc,bps,fc,tc; + + GetDlgItemText(hwndDlg,IDC_DIR,state_install_directory,NSIS_MAX_STRLEN); + is_valid_path=is_valid_instpath(state_install_directory); + + mini_memcpy(s,state_install_directory,NSIS_MAX_STRLEN); + s[sizeof(s)-1]=0; + if (s[1] == ':') s[3]=0; + else if (s[0] == '\\' && s[1] == '\\') // \\ path + { + addtrailingslash(s); + } + + if (GetDiskFreeSpace(s,&spc,&bps,&fc,&tc)) + { + DWORD r; + DWORD v=0x7fffffff; + r=bps*spc*(fc>>10); + if (!r) r=(bps*spc*fc)>>10; + if (r > v) r=v; + available=(int)r; + } + for (x = 0; x < g_inst_header->num_sections; x ++) + { +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (g_inst_section[x].default_state&DFS_SET) +#endif + total+=g_inst_section[x].size_kb; + } + + // Added by Amir Szekely 24th July 2002 + // Allows 'SpaceTexts none' + if (g_inst_header->spacerequired_ptr != -2) { + lstrcpy(s,GetStringFromStringTab(g_inst_header->spacerequired_ptr)); + inttosizestr(total,s); + SetDlgItemText(hwndDlg,IDC_SPACEREQUIRED,s); + if (available != -1) + { + lstrcpy(s,GetStringFromStringTab(g_inst_header->spaceavailable_ptr)); + inttosizestr(available,s); + SetDlgItemText(hwndDlg,IDC_SPACEAVAILABLE,s); + } + else + SetDlgItemText(hwndDlg,IDC_SPACEAVAILABLE,""); + } + + EnableWindow(GetDlgItem(GetParent(hwndDlg),IDOK), + is_valid_path && (available >= total || available == -1) +#ifdef NSIS_SUPPORT_CODECALLBACKS + && !ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onVerifyInstDir,NULL) +#endif + ); + } + return 0; +} + +#ifdef NSIS_CONFIG_COMPONENTPAGE + +static LONG oldTreeWndProc; +static DWORD WINAPI newTreeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_KEYDOWN && wParam == VK_SPACE) + { + SendMessage(GetParent(hwnd),WM_TREEVIEW_KEYHACK,0,0); + return 0; + } + return CallWindowProc((WNDPROC)oldTreeWndProc,hwnd,uMsg,wParam,lParam); +} + +int m_num_insttypes; + +static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HTREEITEM *hTreeItems; + static HIMAGELIST hImageList; + HWND hwndCombo1 = GetDlgItem(hwndDlg,IDC_COMBO1); + HWND hwndTree1 = GetDlgItem(hwndDlg,IDC_TREE1); + if (uMsg == WM_INITDIALOG) + { + int doLines=0; + HTREEITEM Par; + HBITMAP hBMcheck1; + int x; + if (hTreeItems) GlobalFree(hTreeItems); + hTreeItems=(HTREEITEM*)GlobalAlloc(GPTR,sizeof(HTREEITEM)*g_inst_header->num_sections); + + hBMcheck1=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); + SetDlgItemText(hwndDlg,IDC_INTROTEXT,GetStringFromStringTab(g_inst_header->componenttext_ptr)); + SetDlgItemText(hwndDlg,IDC_TEXT1,GetStringFromStringTab(g_inst_header->componentsubtext_ptr[0])); + SetDlgItemText(hwndDlg,IDC_TEXT2,GetStringFromStringTab(g_inst_header->componentsubtext_ptr[1])); + + oldTreeWndProc=GetWindowLong(hwndTree1,GWL_WNDPROC); + SetWindowLong(hwndTree1,GWL_WNDPROC,(DWORD)newTreeWndProc); + + if (hImageList) ImageList_Destroy(hImageList); + hImageList = ImageList_Create(16,16, ILC_COLOR32, 4, 4); + ImageList_SetBkColor(hImageList, GetSysColor(COLOR_WINDOW)); + + ImageList_Add(hImageList,hBMcheck1,NULL); + + TreeView_SetImageList(hwndTree1, hImageList, TVSIL_STATE); + + DeleteObject(hBMcheck1); + + if (g_inst_header->install_types_ptr[0]<0) + { + ShowWindow(hwndCombo1,SW_HIDE); + } + else + { + for (m_num_insttypes = 0; m_num_insttypes < NSIS_MAX_INST_TYPES && + g_inst_header->install_types_ptr[m_num_insttypes]>=0; m_num_insttypes ++) + { + SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetStringFromStringTab(g_inst_header->install_types_ptr[m_num_insttypes])); + } + if (g_inst_header->no_custom_instmode_flag!=1) SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetStringFromStringTab(g_inst_header->custom_ptr)); + SendMessage(hwndCombo1,CB_SETCURSEL,m_whichcfg,0); + } + + Par=NULL; + + for (x = 0; x < g_inst_header->num_sections; x ++) + { + if (g_inst_section[x].name_ptr>=0) + { + TVINSERTSTRUCT tv; + process_string_fromtab(ps_tmpbuf,g_inst_section[x].name_ptr); + tv.hParent=Par; + tv.hInsertAfter=TVI_LAST; + tv.item.mask=TVIF_PARAM|TVIF_TEXT|TVIF_STATE; + tv.item.lParam=x; + tv.item.pszText=ps_tmpbuf; + tv.item.stateMask=TVIS_STATEIMAGEMASK; + + if (m_num_insttypes && m_whichcfg != m_num_insttypes && !(g_inst_section[x].default_state&DFS_RO)) + { + if ((g_inst_section[x].default_state>>m_whichcfg) & 1) + g_inst_section[x].default_state|=DFS_SET; + else + g_inst_section[x].default_state&=~DFS_SET; + } + + { + int l=1; + if (g_inst_section[x].default_state & DFS_SET) l++; + if (g_inst_section[x].default_state & DFS_RO) l+=3; + + tv.item.state=INDEXTOSTATEIMAGEMASK(l); + } + + if (ps_tmpbuf[0] == '!' || (ps_tmpbuf[0] == '-' && ps_tmpbuf[1] == '!')) + { + tv.item.pszText++; + tv.item.stateMask|=TVIS_BOLD; + tv.item.state|=TVIS_BOLD; + } + + if (ps_tmpbuf[0] == '-') + { + if (ps_tmpbuf[1]) + { + tv.item.pszText++; + tv.item.mask|=TVIF_CHILDREN; + tv.item.cChildren=1; + Par = hTreeItems[x] = TreeView_InsertItem(hwndTree1,&tv); + doLines=1; + } + else if (Par && x) + { + TV_ITEM it; + it.hItem = hTreeItems[x-1]; + it.mask = TVIF_STATE; + it.stateMask=TVIS_STATEIMAGEMASK; + + SetParentState(hwndTree1,&it); + + Par=TreeView_GetParent(hwndTree1,Par); + } + } + else + { + hTreeItems[x] = TreeView_InsertItem(hwndTree1,&tv); + } + } + } + for (x = 0; x < g_inst_header->num_sections; x ++) + { + if (g_inst_section[x].name_ptr>=0 && g_inst_section[x].expand==1) + { + SendMessage(hwndTree1,TVM_EXPAND,(WPARAM) TVE_TOGGLE,(LPARAM) hTreeItems[x]); + } + } + if (!doLines) + { + SetWindowLong(hwndTree1,GWL_STYLE,GetWindowLong(hwndTree1,GWL_STYLE)&~(TVS_LINESATROOT)); + } + SendMessage(hwndTree1,WM_VSCROLL,SB_TOP,0); + + SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0); + } + if (uMsg == WM_USER+0x17) + { + int x=wParam; + int ns=lParam; + + if (g_inst_section[x].name_ptr>=0 && ns >= 0) + { + TVITEM tv; + process_string_fromtab(ps_tmpbuf,ns); + tv.hItem=hTreeItems[x]; + tv.mask=TVIF_TEXT; + tv.pszText=ps_tmpbuf; + TreeView_SetItem(hwndTree1,&tv); + } + SendMessage(hwndDlg,WM_USER+0x18,x,(LPARAM)!!(g_inst_section[x].default_state&DFS_SET)); + } + if (uMsg == WM_USER+0x18) // select + { + TVITEM hItem; + hItem.mask = TVIF_STATE; + hItem.hItem=hTreeItems[wParam]; + if (hItem.hItem) CheckTreeItem(hwndTree1, &hItem,lParam); + } + if (uMsg == WM_NOTIFY || uMsg == WM_TREEVIEW_KEYHACK) + { + LPNMHDR lpnmh = (LPNMHDR) lParam; + if (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->idFrom == IDC_TREE1) + { + if (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->code == NM_CLICK) + { + TVHITTESTINFO ht = {0}; + if (uMsg != WM_TREEVIEW_KEYHACK) + { + DWORD dwpos = GetMessagePos(); + + ht.pt.x = GET_X_LPARAM(dwpos); + ht.pt.y = GET_Y_LPARAM(dwpos); + MapWindowPoints(HWND_DESKTOP, hwndTree1, &ht.pt, 1); + + TreeView_HitTest(hwndTree1, &ht); + } + else + { + ht.hItem=TreeView_GetSelection(hwndTree1); + if (ht.hItem) ht.flags=TVHT_ONITEMSTATEICON; + } + + if ((TVHT_ONITEMSTATEICON|TVHT_ONITEMLABEL|TVHT_ONITEMRIGHT|TVHT_ONITEM) & ht.flags) + { + TVITEM hItem; + int image,wh; + hItem.hItem = ht.hItem; + + hItem.mask = TVIF_STATE|TVIF_PARAM; + TreeView_GetItem(hwndTree1, &hItem); + + image = hItem.state >> 12; + wh=hItem.lParam; + + if (!(g_inst_section[wh].default_state&DFS_RO)) + { + if (image == 2) // already checked + { + g_inst_section[wh].default_state&=~DFS_SET; + CheckTreeItem(hwndTree1, &hItem,0); + } + else + { + g_inst_section[wh].default_state|=DFS_SET; + CheckTreeItem(hwndTree1, &hItem,1); + } +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_COMPONENTPAGE) + { + extern HWND g_SectionHack; + g_SectionHack=hwndDlg; + ExecuteCodeSegment(g_inst_entry,g_inst_header->code_onSelChange,NULL); + g_SectionHack=0; + } +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_COMPONENTPAGE + { + int r,x; + // check to see which install type we are + for (r = 0; r < m_num_insttypes; r ++) + { + for (x = 0; x < g_inst_header->num_sections; x ++) + { + char c=GetStringFromStringTab(g_inst_section[x].name_ptr)[0]; + if (c && c!='-') + { + TV_ITEM hItem; + hItem.hItem=hTreeItems[x]; + if (g_inst_header->no_custom_instmode_flag==1) + { + int c=(g_inst_section[x].default_state>>m_whichcfg)&1; + CheckTreeItem(hwndTree1, &hItem,c); + } + else if (!(g_inst_section[x].default_state&DFS_RO)) + { + hItem.mask=TVIF_STATE; + TreeView_GetItem(hwndTree1,&hItem); + if (!(g_inst_section[x].default_state&(1<>12)>1 )) break; + } + } + } + if (x == g_inst_header->num_sections) break; + } + + if (!g_inst_header->no_custom_instmode_flag) + { + SendMessage(hwndCombo1,CB_SETCURSEL,r,0); + m_whichcfg=r; + } + } // end of typecheckshit + SendMessage(hwndDlg,WM_IN_UPDATEMSG,0,0); + } // not ro + } // was valid click + } // was click or hack + } + } + if (uMsg == WM_COMMAND) + { + int id=LOWORD(wParam),code=HIWORD(wParam); + if (id == IDC_COMBO1 && code==CBN_SELCHANGE) + { + int t=SendMessage(hwndCombo1,CB_GETCURSEL,0,0); + if (t != CB_ERR) + { + m_whichcfg=t; + if (m_whichcfg != m_num_insttypes) + { + int x; + for (x = 0; x < g_inst_header->num_sections; x ++) + { + if (g_inst_section[x].name_ptr>=0) + { + if (!(g_inst_section[x].default_state & DFS_RO)) + { + TVITEM tv; + int n=(g_inst_section[x].default_state & (1<no_custom_instmode_flag==2) + { + int c=(m_whichcfg == m_num_insttypes && m_num_insttypes)<<3;// SW_SHOWNA=8, SW_HIDE=0 + ShowWindow(hwndTree1,c); + ShowWindow(GetDlgItem(hwndDlg,IDC_TEXT2),c); + } + + if (g_inst_header->spacerequired_ptr > 0) { + int x,total; + char s[128]; + for (total=x=0; x < g_inst_header->num_sections; x ++) + { + if (g_inst_section[x].default_state&DFS_SET) + total+=g_inst_section[x].size_kb; + } + lstrcpy(s,GetStringFromStringTab(g_inst_header->spacerequired_ptr)); + inttosizestr(total,s); + SetDlgItemText(hwndDlg,IDC_SPACEREQUIRED,s); + } + } + return 0; +} +#endif//NSIS_CONFIG_COMPONENTPAGE + +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +int ui_st_updateflag=0x3; + +void update_status_text(const char *text1, const char *text2) +{ + static LVITEM new_item = {LVIF_TEXT,}; + RECT r; + if (insthwnd) + { + if (lstrlen(text1)+lstrlen(text2) >= sizeof(ps_tmpbuf)) return; + + lstrcpy(ps_tmpbuf,text1); + lstrcat(ps_tmpbuf,text2); + if ((ui_st_updateflag&1)) + { + // Changed by Amir Szekely 26th July 2002 + new_item.pszText=ps_tmpbuf; + ListView_InsertItem(insthwnd, &new_item); + ListView_EnsureVisible(insthwnd, new_item.iItem, 0); + new_item.iItem++; + GetClientRect(insthwnd,&r); + ListView_SetColumnWidth(insthwnd, 0, r.right-r.left); + } + if ((ui_st_updateflag&2)) SetWindowText(insthwnd2,ps_tmpbuf); + } +} + + +static DWORD WINAPI install_thread(LPVOID p) +{ + HWND hwndDlg=(HWND)p; +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (g_is_uninstaller) + { + if (ExecuteCodeSegment(g_inst_entry,g_inst_uninstheader->code,g_progresswnd)) m_abort++; + } + else + { +#endif + int m_inst_sec=0; + while (m_inst_secnum_sections && !m_abort) + { +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (g_inst_section[m_inst_sec].default_state&DFS_SET +#ifdef NSIS_CONFIG_SILENT_SUPPORT + || g_inst_cmnheader->silent_install +#endif//NSIS_CONFIG_SILENT_SUPPORT + ) +#endif + { + log_printf2("Section: \"%s\"",GetStringFromStringTab(g_inst_section[m_inst_sec].name_ptr)); + if (ExecuteCodeSegment(g_inst_entry,g_inst_section[m_inst_sec].code,g_progresswnd)) m_abort++; + } +#ifdef NSIS_CONFIG_COMPONENTPAGE + else + { + log_printf2("Skipping section: \"%s\"",GetStringFromStringTab(g_inst_section[m_inst_sec].name_ptr)); + } +#endif + m_inst_sec++; + } +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + } +#endif + if (hwndDlg) SendMessage(hwndDlg,WM_NOTIFY_INSTPROC_DONE,m_abort,0); + return m_abort; +} + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HBRUSH hBrush; + static int lb_bg,lb_fg; + if (uMsg == WM_DESTROY && hBrush) DeleteObject(hBrush); + if (uMsg == WM_INITDIALOG) + { + DWORD id; + HWND hwnd; + int num=0; + int x=0; + LVCOLUMN lvc = {0, 0, -1, 0, 0, -1}; + + insthwndbutton=GetDlgItem(hwndDlg,IDC_SHOWDETAILS); + insthwnd2=GetDlgItem(hwndDlg,IDC_INTROTEXT); + insthwnd=GetDlgItem(hwndDlg,IDC_LIST1); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (g_is_uninstaller) + { + num=g_inst_uninstheader->code_size; + } + else +#endif + { + log_printf3("New install of \"%s\" to \"%s\"",GetStringFromStringTab(g_inst_cmnheader->name_ptr),state_install_directory); + for (; x < g_inst_header->num_sections; x ++) + { +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (g_inst_section[x].default_state&DFS_SET) +#endif + num+=g_inst_section[x].code_size; + } + } + // Changed by Amir Szekely 26th July 2002 + ListView_InsertColumn(insthwnd, 0, &lvc); +#define LVS_EX_LABELTIP 0x00004000 // listview unfolds partly hidden labels if it does not have infotip text + ListView_SetExtendedListViewStyleEx(insthwnd, LVS_EX_LABELTIP, LVS_EX_LABELTIP); + ListView_SetBkColor(insthwnd, g_inst_cmnheader->lb_bg); + ListView_SetTextBkColor(insthwnd, g_inst_cmnheader->lb_bg); + ListView_SetTextColor(insthwnd, g_inst_cmnheader->lb_fg); + SetWindowText(insthwndbutton,GetStringFromStringTab(g_inst_cmnheader->showdetailsbutton_ptr)); + if (g_inst_cmnheader->show_details) + { + ShowWindow(insthwndbutton,SW_HIDE); + if (g_inst_cmnheader->show_details != 2) ShowWindow(insthwnd,SW_SHOWNA); + else insthwndbutton=NULL; + } + progress_bar_len=num; + + g_progresswnd=GetDlgItem(hwndDlg,IDC_PROGRESS1+(g_inst_cmnheader->progress_flags&1)); + ShowWindow(g_progresswnd,SW_SHOWNA); + SendMessage(g_progresswnd,PBM_SETRANGE,0,MAKELPARAM(0,30000)); + SendMessage(g_progresswnd,PBM_SETPOS,0,0); + if (g_inst_cmnheader->progress_flags&2) + { + SendMessage(g_progresswnd,PBM_SETBARCOLOR,0,g_inst_cmnheader->lb_fg); + SendMessage(g_progresswnd,PBM_SETBKCOLOR,0,g_inst_cmnheader->lb_bg); + } + + hwnd=GetParent(hwndDlg); + EnableWindow(GetDlgItem(hwnd,IDOK),0); + EnableWindow(GetDlgItem(hwnd,IDCANCEL),0); + + CloseHandle(CreateThread(NULL,0,install_thread,(LPVOID)hwndDlg,0,&id)); + } + if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_SHOWDETAILS) + { + ShowWindow(GetDlgItem(hwndDlg,IDC_SHOWDETAILS),SW_HIDE); + SendMessage(insthwnd,WM_VSCROLL,SB_BOTTOM,0); + ShowWindow(insthwnd,SW_SHOWNA); + } + if (uMsg == WM_NOTIFY_INSTPROC_DONE) + { + if (g_quit_flag) EndDialog(GetParent(hwndDlg),1); + else if (!wParam) + { + HWND h2=GetParent(hwndDlg); + HWND h=GetDlgItem(h2,IDOK); + EnableWindow(h,1); + if (!g_autoclose) + { + ShowWindow(g_hwnd,SW_SHOWNA); + lstrcpy(g_tmp,g_caption); + process_string_fromtab(g_tmp+lstrlen(g_caption),g_inst_cmnheader->subcaption_ptrs[g_max_page+1]); + update_status_text(GetStringFromStringTab(g_inst_cmnheader->completed_ptr),""); + SetWindowText(h2,g_tmp); + SetFocus(h); + } + else + { + SendMessage(GetParent(hwndDlg),WM_NOTIFY_OUTER_NEXT,1,0); + } + } + else + { + HWND h=GetDlgItem(GetParent(hwndDlg),IDCANCEL); + EnableWindow(h,1); + SetFocus(h); + } + } + return 0; +} +#endif//NSIS_CONFIG_VISIBLE_SUPPORT diff --git a/Source/exehead/afxres.h b/Source/exehead/afxres.h new file mode 100644 index 00000000..b3cc0671 --- /dev/null +++ b/Source/exehead/afxres.h @@ -0,0 +1,5 @@ +#include + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/Source/exehead/bgbg.c b/Source/exehead/bgbg.c new file mode 100644 index 00000000..32b357d3 --- /dev/null +++ b/Source/exehead/bgbg.c @@ -0,0 +1,90 @@ +#include +#include "resource.h" +#include "config.h" + +#ifdef NSIS_SUPPORT_BGBG + +static int m_color1, m_color2, m_textcolor; + +static LRESULT CALLBACK BG_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_PAINT: + { + static PAINTSTRUCT ps; + HFONT newFont, oldFont; + HDC hdc=BeginPaint(hwnd,&ps); + RECT r; + int y; + GetClientRect(hwnd,&r); + // this portion by Drew Davidson, drewdavidson@mindspring.com + + // JF: made slower, reduced to 4 pixels high, because I like how it looks better/ + for (y = r.top; y < r.bottom; y += 4) + { + int rv,gv,bv; + RECT rect; + HBRUSH brush; + rv = GetRValue(m_color2) * y / r.bottom + GetRValue(m_color1) * (r.bottom - y) / r.bottom; + gv = GetGValue(m_color2) * y / r.bottom + GetGValue(m_color1) * (r.bottom - y) / r.bottom; + bv = GetBValue(m_color2) * y / r.bottom + GetBValue(m_color1) * (r.bottom - y) / r.bottom; + brush = CreateSolidBrush(RGB(rv,gv,bv)); + SetRect(&rect, r.left, y, r.right, y+4); + // note that we don't need to do "SelectObject(hdc, brush)" + // because FillRect lets us specify the brush as a parameter. + FillRect(hdc, &rect, brush); + DeleteObject(brush); + } + + if (m_textcolor != -1) + { + newFont = CreateFont(40,0,0,0,FW_BOLD,TRUE,FALSE,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,"Garamond"); + if (newFont) + { + static char buf[256]; + r.left+=16; + r.top+=8; + GetWindowText(hwnd,buf,sizeof(buf)); + SetBkMode(hdc,TRANSPARENT); + SetTextColor(hdc,m_textcolor); + oldFont = SelectObject(hdc,newFont); + DrawText(hdc,buf,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE); + SelectObject(hdc,oldFont); + DeleteObject(newFont); + } + } + EndPaint(hwnd,&ps); + } + return 0; + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + + +HWND bgWnd_Init(HINSTANCE hInstance, char *title, int color1, int color2, int color3) +{ + RECT vp; + char classname[4]="_Nb"; + static WNDCLASS wc; + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.lpfnWndProc = BG_WndProc; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON2)); + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.lpszClassName = classname; + + if (!RegisterClass(&wc)) return 0; + + m_color1=color1; + m_color2=color2; + m_textcolor=color3; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &vp, 0); + + return CreateWindow(classname,title,WS_VISIBLE|WS_OVERLAPPED|WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_MINIMIZEBOX, + vp.left,vp.top,vp.right-vp.left,vp.bottom-vp.top,GetDesktopWindow(),NULL,hInstance,NULL); +} + + +#endif //NSIS_SUPPORT_BGBG \ No newline at end of file diff --git a/Source/exehead/bin2h.c b/Source/exehead/bin2h.c new file mode 100644 index 00000000..994b133c --- /dev/null +++ b/Source/exehead/bin2h.c @@ -0,0 +1,60 @@ +/* Generates a .h file from a binary file. +** v1.2 - 3/8/01 +** Copyright (C) 1996-2001 Justin Frankel +** Public domain. +*/ +#include + +int main(int argc, char *argv[]) { + int length; + FILE *in, *out; + char *outfilename; + char *token; + int total_bytes=0; + + if (argc != 4) { + fprintf(stderr,"Usage: bin2h file.dat outfile.h token_name\n"); + return 1; + } + + in = fopen(argv[1],"rb"); + + if (!in) { + fprintf(stderr,"Error: file not found\n"); + return 1; + } + out = fopen(argv[2],"wt"); + + if (!out) { + fclose(in); + fprintf(stderr,"Error: could not open output file\n"); + return 1; + } + fseek(in,0,SEEK_END); + length=ftell(in); + fseek(in,0,SEEK_SET); + + outfilename = argv[2]; + token = argv[3]; + fprintf(out,"unsigned char %s[%d] = { \n",token,length); + for (;;) { + static int firsttime; + static int linecount; + int c; + if (++linecount > 10) { + linecount = 0; + fprintf(out,",\n "); + } + else if (firsttime) fprintf(out,", "); + firsttime = 1; + c = fgetc(in); + if (feof(in)) break; + total_bytes++; + fprintf(out,"%i",c); + } + fprintf(out,"};\n",token); + fclose(in); + fclose(out); + fprintf(stderr,"%s -> %s (%d bytes)\n\n",argv[1],token,total_bytes); + return 0; +} diff --git a/Source/exehead/bin2h.exe b/Source/exehead/bin2h.exe new file mode 100755 index 00000000..5828c9f1 Binary files /dev/null and b/Source/exehead/bin2h.exe differ diff --git a/Source/exehead/bitmap1.bmp b/Source/exehead/bitmap1.bmp new file mode 100644 index 00000000..9bad965a Binary files /dev/null and b/Source/exehead/bitmap1.bmp differ diff --git a/Source/exehead/config.h b/Source/exehead/config.h new file mode 100644 index 00000000..d1763c7c --- /dev/null +++ b/Source/exehead/config.h @@ -0,0 +1,260 @@ +#ifndef NSIS_CONFIG_H +#define NSIS_CONFIG_H + +#ifndef APSTUDIO_INVOKED // keep msdev's resource editor from mangling the .rc file + +// NSIS_MAX_STRLEN defines the maximum string length for internal variables +// and stack entries. 1024 should be plenty, but if you are doing crazy registry +// shit, you might want to bump it up. Generally it adds about 16-32x the memory, +// so setting this to 4096 from 1024 will add around 64k of memory usage (not +// really a big deal, but not usually needed). +#define NSIS_MAX_STRLEN 1024 + + +// NSIS_MAX_INST_TYPES specified the maximum install types. +// note that this should not exceed 30, ever. +#define NSIS_MAX_INST_TYPES 8 + +// NSIS_CONFIG_UNINSTALL_SUPPORT enables the uninstaller +// support. Comment it out if your installers don't need +// uninstallers +// adds approximately 2kb. +#define NSIS_CONFIG_UNINSTALL_SUPPORT + +// NSIS_CONFIG_LICENSEPAGE enables support for the installer to +// present a license page. +#define NSIS_CONFIG_LICENSEPAGE + +// NSIS_CONFIG_LICENSEPAGE enables support for the installer to +// present a page.where you can select what sections are installed. +// with this disabled, all sections are installed. +#define NSIS_CONFIG_COMPONENTPAGE + +// NSIS_CONFIG_SILENT_SUPPORT enables support for making installers +// that are completely silent. +#define NSIS_CONFIG_SILENT_SUPPORT + +// NSIS_CONFIG_VISIBLE_SUPPORT enables support for making installers +// that are visible. +#define NSIS_CONFIG_VISIBLE_SUPPORT + + +// Changed by Amir Szekely 31st July 2002 +// Now supports runtime choice of compression method + +// NSIS_CONFIG_COMPRESSION_SUPPORT enables support for making installers +// that use compression (recommended). +#define NSIS_CONFIG_COMPRESSION_SUPPORT + // compression specific options + + // NSIS_ZLIB_COMPRESS_WHOLE makes all install data in zlib installers + // compressed together. Runtime requirements are increased, but potential + // for compression is as well. Adds approximately 1kb of disk footprint, + // and requires that the installer create a (potentially large) temporary + // file in the temp directory. + // #define NSIS_ZLIB_COMPRESS_WHOLE + + // NSIS_BZIP2_COMPRESS_WHOLE makes all install data in bzip2 installers + // compressed together. Runtime requirements are increased, but potential + // for compression is as well. Adds approximately 1kb of disk footprint, + // and requires that the installer create a (potentially large) temporary + // file in the temp directory. + #define NSIS_BZIP2_COMPRESS_WHOLE + + // if NSIS_COMPRESS_BZIP2_SMALLMODE is defined, bzip2's decompressor uses + // bzip2's alternative decompression method that uses a lot less memory, at + // the expense of speed. not recommended. + // #define NSIS_COMPRESS_BZIP2_SMALLMODE + + // if NSIS_COMPRESS_BZIP2_LEVEL is defined, it overrides the default bzip2 + // compression window size of 9 (1-9 is valid) + // 9 uses the most memory, but typically compresses best (recommended). + // 1 uses the least memory, but typically compresses the worst. + #define NSIS_COMPRESS_BZIP2_LEVEL 9 + + +// NSIS_CONFIG_CRC_SUPPORT enables support for installer verification. +// HIGHLY recommended. +#define NSIS_CONFIG_CRC_SUPPORT + +// NSIS_CONFIG_CRC_ANAL makes the CRC verification extremely careful, meaning +// extra bytes on the end of file, or the first 512 bytes changing, will give +// error. Enable this if you are paranoid, otherwise leaving it off seems safe +// (and is less prone to reporting virii). If you will be digitally signing your +// installers, leave this off (the default). +// #define NSIS_CONFIG_CRC_ANAL + + +// NSIS_CONFIG_LOG enables the logging facility. +// turning this on (by uncommenting it) adds about +// 3kb, but can be useful in debugging your installers. +// NOT ENABLED BY DEFAULT. +// #define NSIS_CONFIG_LOG + +// NSIS_SUPPORT_BGBG enables support for the blue (well, whatever +// color you want) gradient background window. +#define NSIS_SUPPORT_BGBG + + +// NSIS_SUPPORT_CODECALLBACKS enables support for installer code callbacks. +// recommended, as it uses a minimum of space and allows for neat functionality. +#define NSIS_SUPPORT_CODECALLBACKS + + +// NSIS_SUPPORT_MOVEONREBOOT enables support for uninstallers that automatically +// delete themselves from the temp directory, as well as the reboot moving/deleting +// modes of Delete and Rename. Adds about 512 gay bytes.. +#define NSIS_SUPPORT_MOVEONREBOOT + +/////////////// the following are instruction enabling defines /////////////// + +// NSIS_SUPPORT_ACTIVEXREG enables activeX plug-in registration +// and deregistration, as well as CallInstDLL +#define NSIS_SUPPORT_ACTIVEXREG + +// NSIS_SUPPORT_INTOPTS enables support for IntCmp, IntCmpU, IntOp, and IntFmt. +#define NSIS_SUPPORT_INTOPTS + +// NSIS_SUPPORT_STROPTS enables support for StrCmp, StrCpy, and StrLen, as well as Get*Local. +#define NSIS_SUPPORT_STROPTS + +// NSIS_SUPPORT_STACK enables support for the stack (Push, Pop, Exch) +#define NSIS_SUPPORT_STACK + +// NSIS_SUPPORT_FILEFUNCTIONS enables support for FileOpen,FileClose, FileSeek, FileRead, and FileWrite. +#define NSIS_SUPPORT_FILEFUNCTIONS + +// NSIS_SUPPORT_FINDFIRST enables support for FindFirst, FindNext, and FindClose. +#define NSIS_SUPPORT_FINDFIRST + +// NSIS_SUPPORT_CREATESHORTCUT enables support for CreateShortCut. +#define NSIS_SUPPORT_CREATESHORTCUT + +// NSIS_SUPPORT_INIFILES enables support for ReadINIStr and WriteINIStr. +#define NSIS_SUPPORT_INIFILES + +// NSIS_SUPPORT_REGISTRYFUNCTIONS enables support for ReadRegStr, ReadRegDWORD, WriteRegStr, etc etc etc. +#define NSIS_SUPPORT_REGISTRYFUNCTIONS + +// NSIS_SUPPORT_COPYFILES enables support for CopyFiles +#define NSIS_SUPPORT_COPYFILES + +// NSIS_SUPPORT_REBOOT enables support for Reboot, IfRebootFlag, SetRebootFlag +#define NSIS_SUPPORT_REBOOT + +// NSIS_SUPPORT_FNUTIL enables support for GetFullPathName, GetTempFileName, and SearchPath +#define NSIS_SUPPORT_FNUTIL + +// NSIS_SUPPORT_EXECUTE enables support for Exec and ExecWait +#define NSIS_SUPPORT_EXECUTE + +// NSIS_SUPPORT_SHELLEXECUTE enables support for ExecShell +#define NSIS_SUPPORT_SHELLEXECUTE + +// NSIS_SUPPORT_GETDLLVERSION enables support for GetDLLVersion +#define NSIS_SUPPORT_GETDLLVERSION + +// NSIS_SUPPORT_GETFILETIME enables support for GetFileTime +#define NSIS_SUPPORT_GETFILETIME + +// NSIS_SUPPORT_HWNDS enables support for FindWindow, SendMessage, and IsWindow +#define NSIS_SUPPORT_HWNDS + +// NSIS_SUPPORT_ENVIRONMENT enables support for ReadEnvStr and ExpandEnvStrings +#define NSIS_SUPPORT_ENVIRONMENT + +// NSIS_SUPPORT_RMDIR enables support for RMDir +#define NSIS_SUPPORT_RMDIR + +// NSIS_SUPPORT_FILE enables support for File (extracting files) +#define NSIS_SUPPORT_FILE + +// NSIS_SUPPORT_DELETE enables support for Delete (delete files) +#define NSIS_SUPPORT_DELETE + +// NSIS_SUPPORT_RENAME enables support for Rename (rename files) +#define NSIS_SUPPORT_RENAME + +// NSIS_SUPPORT_MESSAGEBOX enables support for MessageBox +#define NSIS_SUPPORT_MESSAGEBOX + + + +// fixes +#ifndef NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_LICENSEPAGE +#undef NSIS_CONFIG_LICENSEPAGE +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE +#undef NSIS_CONFIG_COMPONENTPAGE +#endif +#ifdef NSIS_SUPPORT_BGBG +#undef NSIS_SUPPORT_BGBG +#endif +#endif + + +#if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#define _NSIS_CONFIG_VERIFYDIALOG +#endif + +#if defined(NSIS_CONFIG_UNINSTALL_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#define _NSIS_CONFIG_UNINSTDLG +#endif + +#if defined(NSIS_CONFIG_UNINSTALL_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#define _NSIS_CONFIG_UNINSTDLG +#endif + +#ifdef EXEHEAD + #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + #ifndef NSIS_COMPRESS_USE_ZLIB + #ifndef NSIS_COMPRESS_USE_BZIP2 + #error compression is enabled but both zlib and bzip2 are disabled. + #endif + #endif + #endif + + #ifdef NSIS_COMPRESS_USE_ZLIB + #ifdef NSIS_COMPRESS_USE_BZIP2 + #error both zlib and bzip2 are enabled. + #endif + #endif + + #ifdef NSIS_COMPRESS_USE_ZLIB + #ifdef NSIS_ZLIB_COMPRESS_WHOLE + #define NSIS_COMPRESS_WHOLE + #endif + #endif + + #ifdef NSIS_COMPRESS_USE_BZIP2 + #ifdef NSIS_BZIP2_COMPRESS_WHOLE + #define NSIS_COMPRESS_WHOLE + #endif + #endif +#endif // EXEHEAD + +#ifdef NSIS_COMPRESS_WHOLE + #ifndef NSIS_CONFIG_COMPRESSION_SUPPORT + #error NSIS_COMPRESS_WHOLE defined, NSIS_CONFIG_COMPRESSION_SUPPORT not + #endif +#endif + +#ifdef NSIS_CONFIG_CRC_ANAL + #ifndef NSIS_CONFIG_CRC_SUPPORT + #error NSIS_CONFIG_CRC_ANAL defined but NSIS_CONFIG_CRC_SUPPORT not + #endif +#endif + + +#ifndef NSIS_COMPRESS_BZIP2_LEVEL + #define NSIS_COMPRESS_BZIP2_LEVEL 9 +#endif + +#if NSIS_MAX_INST_TYPES > 30 + #error NSIS_MAX_INST_TYPES > 30 +#endif + +#endif//!APSTUDIO_INVOKED + +#endif // NSIS_CONFIG_H diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c new file mode 100644 index 00000000..a4b39afc --- /dev/null +++ b/Source/exehead/exec.c @@ -0,0 +1,1423 @@ +#include +#include +#include +#include "fileform.h" +#include "util.h" +#include "state.h" +#include "ui.h" +#include "exec.h" +#include "lang.h" +#include "resource.h" + +#define EXEC_ERROR 0x7FFFFFFF + +#ifdef NSIS_CONFIG_COMPONENTPAGE +HWND g_SectionHack; +#endif + +#ifdef NSIS_SUPPORT_STACK +typedef struct _stack_t { + struct _stack_t *next; + char text[NSIS_MAX_STRLEN]; +} stack_t; + +static stack_t *g_st; +#endif + +static int exec_errorflag; +#ifdef NSIS_SUPPORT_REBOOT +static int exec_rebootflag; +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +HBITMAP g_hBrandingBitmap = 0; +#endif + +static WIN32_FIND_DATA *file_exists(char *buf) +{ + HANDLE h; + static WIN32_FIND_DATA fd; + h = FindFirstFile(buf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + FindClose(h); + return &fd; + } + return NULL; +} + +#ifdef NSIS_SUPPORT_RMDIR +static void doRMDir(char *buf, int recurse) +{ + if (recurse && is_valid_instpath(buf)) + { + int i=lstrlen(buf); + HANDLE h; + WIN32_FIND_DATA fd; + lstrcat(buf,"\\*.*"); + h = FindFirstFile(buf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (fd.cFileName[0] != '.' || + (fd.cFileName[1] != '.' && fd.cFileName[1])) + { + lstrcpy(buf+i+1,fd.cFileName); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) doRMDir(buf,recurse); + else + { + update_status_text(LANG_STR(LANG_DELETEFILE),buf); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + SetFileAttributes(buf,fd.dwFileAttributes^FILE_ATTRIBUTE_READONLY); + DeleteFile(buf); + } + } + } while (FindNextFile(h,&fd)); + FindClose(h); + } + buf[i]=0; // fix buffer + } + log_printf2("RMDir: RemoveDirectory(\"%s\")",buf); + update_status_text(LANG_STR(LANG_REMOVEDIR),buf); + RemoveDirectory(buf); +} +#endif//NSIS_SUPPORT_RMDIR + + + +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS +// based loosely on code from Tim Kosse +// in win9x this isn't necessary (RegDeleteKey() can delete a tree of keys), +// but in win2k you need to do this manually. +static LONG myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey, int onlyifempty) +{ + HKEY key; + int retval=RegOpenKeyEx(thiskey,lpSubKey,0,KEY_ALL_ACCESS,&key); + if (retval==ERROR_SUCCESS) + { + char buffer[MAX_PATH+1]; + while (RegEnumKey(key,0,buffer,MAX_PATH+1)==ERROR_SUCCESS) + { + if (onlyifempty) + { + RegCloseKey(key); + return !ERROR_SUCCESS; + } + if ((retval=myRegDeleteKeyEx(key,buffer,0)) != ERROR_SUCCESS) break; + } + RegCloseKey(key); + retval=RegDeleteKey(thiskey,lpSubKey); + } + return retval; +} +#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS + +extern char g_all_user_var_flag; + +static int ExecuteEntry(entry *entries, int pos); + +static int resolveaddr(int v) +{ + if (v<0) return myatoi(g_usrvars[-(v+1)]); // if <0, that means we + return v; +} + +int ExecuteCodeSegment(entry *entries, int pos, HWND hwndProgress) +{ + while (pos >= 0) + { + int rv; + if (entries[pos].which == EW_RET) return 0; + rv=ExecuteEntry(entries,pos); + if (rv == EXEC_ERROR) return EXEC_ERROR; + + rv=resolveaddr(rv); + + if (!rv) { rv++; pos++; } + else + { + int t=pos; + rv--; // rv is decremented here by 1, since it was +1 on the other end. + pos=rv; // set new position + rv-=t; // set rv to delta for progress adjustment + } + + if (hwndProgress) + { + extern int progress_bar_pos, progress_bar_len; + progress_bar_pos+=rv; + if (!progress_bar_len) progress_bar_len++; + SendMessage(hwndProgress,PBM_SETPOS,MulDiv(progress_bar_pos,30000,progress_bar_len),0); + } + } + return 0; +} + +// returns EXEC_ERROR on error +// returns 0, advance position by 1 +// otherwise, returns new_position+1 +static int ExecuteEntry(entry *entries, int pos) +{ + static char buf[NSIS_MAX_STRLEN],buf2[NSIS_MAX_STRLEN],buf3[NSIS_MAX_STRLEN],buf4[NSIS_MAX_STRLEN]; + int *parms=entries[pos].offsets; + int which=entries[pos].which; + switch (which) + { + case EW_NOP: + log_printf2("Jump: %d",parms[0]); + return parms[0]; + case EW_ABORT: + { + process_string_fromtab(buf,parms[0]); + log_printf2("Aborting: \"%s\"",buf); + update_status_text("",buf); + } + return EXEC_ERROR; + case EW_QUIT: + g_quit_flag++; + if (g_hwnd) PostQuitMessage(0); // make sure we bail out fast. + return EXEC_ERROR; + case EW_CALL: + { + int v=resolveaddr(parms[0])-1; // address is -1, since we encode it as +1 + log_printf2("Call: %d",v); + return ExecuteCodeSegment(entries,v,NULL); + } + case EW_UPDATETEXT: + if (parms[1]) ui_st_updateflag=parms[1]; + else + { + process_string_fromtab(buf4,parms[0]); + log_printf2("detailprint: %s",buf4); + update_status_text(buf4,""); + } + return 0; + case EW_SLEEP: + { + int x=process_string_fromtab_toint(parms[0]); + if (x < 1) x=1; + log_printf2("Sleep(%d)",x); + Sleep(x); + } + return 0; + case EW_SETSFCONTEXT: + g_all_user_var_flag=parms[0]; + return 0; + case EW_HIDEWINDOW: + log_printf("HideWindow"); + ShowWindow(g_hwnd,SW_HIDE); + return 0; + case EW_BRINGTOFRONT: + log_printf("BringToFront"); + ShowWindow(g_hwnd,SW_SHOW); + SetForegroundWindow(g_hwnd); + return 0; + case EW_SETWINDOWCLOSE: + g_autoclose=parms[0]; + return 0; + case EW_CHDETAILSVIEW: + if (insthwndbutton) ShowWindow(insthwndbutton,parms[1]); + if (insthwnd) ShowWindow(insthwnd,parms[0]); + return 0; + case EW_SETFILEATTRIBUTES: + process_string_fromtab(buf,parms[0]); + log_printf3("SetFileAttributes: \"%s\":%08X",buf,parms[1]); + if (!SetFileAttributes(buf,parms[1])) + { + exec_errorflag++; + log_printf("SetFileAttributes failed."); + } + return 0; + case EW_CREATEDIR: + process_string_fromtab(buf2,parms[0]); + log_printf3("CreateDirectory: \"%s\" (%d)",buf2,parms[1]); + if (parms[1]) + { + update_status_text(LANG_STR(LANG_OUTPUTDIR),buf2); + lstrcpy(state_output_directory,buf2); + } + else update_status_text(LANG_STR(LANG_CREATEDIR),buf2); + recursive_create_directory(buf2); + return 0; + case EW_IFFILEEXISTS: + process_string_fromtab(buf,parms[0]); + if (file_exists(buf)) + { + log_printf3("IfFileExists: file \"%s\" exists, jumping %d",buf,parms[1]); + return parms[1]; + } + log_printf3("IfFileExists: file \"%s\" does not exist, jumping %d",buf,parms[2]); + return parms[2]; + case EW_IFERRORS: + { + int f=exec_errorflag; + exec_errorflag=parms[2]; + if (f) + { + return parms[0]; + } + } + return parms[1]; +#ifdef NSIS_SUPPORT_RENAME + case EW_RENAME: + { + process_string_fromtab(buf,parms[0]); + process_string_fromtab(buf2,parms[1]); + lstrcpy(buf4,buf); + if (lstrlen(buf)+lstrlen(buf2) < NSIS_MAX_STRLEN-3) + { + lstrcat(buf4,"->"); + lstrcat(buf4,buf2); + } + log_printf2("Rename: %s",buf4); + if (MoveFile(buf,buf2)) + { + update_status_text(LANG_STR(LANG_RENAME),buf4); + } + else + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (parms[2] && file_exists(buf)) + { +#ifdef NSIS_SUPPORT_REBOOT + exec_rebootflag++; +#endif + MoveFileOnReboot(buf,buf2); + update_status_text(LANG_STR(LANG_RENAMEONREBOOT),buf4); + log_printf2("Rename on reboot: %s",buf4); + } + else +#endif + { + exec_errorflag++; + log_printf2("Rename failed: %s",buf4); + } + } + } + return 0; +#endif//NSIS_SUPPORT_RENAME +#ifdef NSIS_SUPPORT_FNUTIL + case EW_GETFULLPATHNAME: + { + char *p=g_usrvars[parms[0]]; + char *fp; + process_string_fromtab(buf,parms[1]); + if (!GetFullPathName(buf,NSIS_MAX_STRLEN,p,&fp)) + { + exec_errorflag++; + *p=0; + } + else if (fp>buf && *fp) + { + WIN32_FIND_DATA *fd=file_exists(buf); + if (fd) + { + lstrcpy(fp,fd->cFileName); + } + else + { + exec_errorflag++; + *p=0; + } + } + if (!parms[2]) GetShortPathName(p,p,NSIS_MAX_STRLEN); + } + return 0; + case EW_SEARCHPATH: + { + char *fp; + char *p=g_usrvars[parms[0]]; + process_string_fromtab(buf,parms[1]); + if (!SearchPath(NULL,buf,NULL,NSIS_MAX_STRLEN,p,&fp)) + { + p[0]=0; + exec_errorflag++; + } + } + return 0; + case EW_GETTEMPFILENAME: + { + char *textout=g_usrvars[parms[0]]; + if (!GetTempPath(NSIS_MAX_STRLEN,buf) || !GetTempFileName(buf,"nst",0,textout)) + { + *textout=0; + exec_errorflag++; + } + } + return 0; +#endif +#ifdef NSIS_SUPPORT_FILE + case EW_EXTRACTFILE: + { + HANDLE hOut; + int ret; + int overwriteflag=parms[0]; + lstrcpy(buf,state_output_directory); + addtrailingslash(buf); + + process_string_fromtab(buf4,parms[1]); + log_printf3("File: overwriteflag=%d, name=\"%s\"",overwriteflag,buf4); + if (validpathspec(buf4)) + { + lstrcpy(buf,buf4); + } + else lstrcat(buf,buf4); + _tryagain: + if (!overwriteflag) + { + int attr=GetFileAttributes(buf); + if (attr & FILE_ATTRIBUTE_READONLY) + SetFileAttributes(buf,attr^FILE_ATTRIBUTE_READONLY); + } + if (overwriteflag == 3) // check date and time + { + WIN32_FIND_DATA *ffd=file_exists(buf); + overwriteflag=1; // if it doesn't exist, fall back to no overwrites (since it shouldn't matter anyway) + if (ffd) + { + overwriteflag=(CompareFileTime(&ffd->ftLastWriteTime,(FILETIME*)(parms+3)) >= 0); // if first one is newer, then don't overwrite + } + } + hOut=myOpenFile(buf,GENERIC_WRITE,(overwriteflag==1)?CREATE_NEW:CREATE_ALWAYS); + if (hOut == INVALID_HANDLE_VALUE) + { + if (overwriteflag) + { + update_status_text(LANG_STR(LANG_SKIPPED),buf4); + if (overwriteflag==2) exec_errorflag++; + log_printf3("File: skipped: \"%s\" (overwriteflag=%d)",buf,overwriteflag); + return 0; + } + log_printf2("File: error creating \"%s\"",buf); + lstrcpy(buf3,g_usrvars[0]);//save $0 + lstrcpy(g_usrvars[0],buf); + + process_string_fromtab(buf2,g_inst_cmnheader->fileerrtext_ptr); + lstrcpy(g_usrvars[0],buf3); // restore $0 + + switch (MessageBox(g_hwnd,buf2,g_caption,MB_ABORTRETRYIGNORE|MB_ICONSTOP)) + { + case IDRETRY: + log_printf("File: error, user retry"); + goto _tryagain; + case IDIGNORE: + log_printf("File: error, user cancel"); + exec_errorflag++; + return 0; + default: + log_printf("File: error, user abort"); + update_status_text(LANG_STR(LANG_CANTWRITE),buf); + return EXEC_ERROR; + } + } + + update_status_text(LANG_STR(LANG_EXTRACT),buf4); + ret=GetCompressedDataFromDataBlock(parms[2],hOut); + + log_printf3("File: wrote %d to \"%s\"",ret,buf); + + if (parms[3] != 0xffffffff || parms[4] != 0xffffffff) + SetFileTime(hOut,(FILETIME*)(parms+3),NULL,(FILETIME*)(parms+3)); + + CloseHandle(hOut); + + if (ret < 0) + { + if (ret == -2) + { + lstrcpy(buf,LANG_STR(LANG_ERRORWRITING)); + lstrcat(buf,buf4); + } + else + { + lstrcpy(buf,LANG_STR(LANG_ERRORDECOMPRESSING)); + } + log_printf2("%s",buf); + MessageBox(g_hwnd,buf,g_caption,MB_OK|MB_ICONSTOP); + return EXEC_ERROR; + } + } + return 0; +#endif//NSIS_SUPPORT_FILE +#ifdef NSIS_SUPPORT_DELETE + case EW_DELETEFILE: + { + HANDLE h; + WIN32_FIND_DATA fd; + process_string_fromtab(buf2,parms[0]); + lstrcpy(buf,buf2); + log_printf2("Delete: \"%s\"",buf); + trimslashtoend(buf); + h=FindFirstFile(buf2,&fd); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + wsprintf(buf2,"%s\\%s",buf,fd.cFileName); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + SetFileAttributes(buf2,fd.dwFileAttributes^FILE_ATTRIBUTE_READONLY); + if (DeleteFile(buf2)) + { + log_printf2("Delete: DeleteFile(\"%s\")",buf2); + update_status_text(LANG_STR(LANG_DELETEFILE),buf2); + } + else + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (parms[1]) + { +#ifdef NSIS_SUPPORT_REBOOT + exec_rebootflag++; +#endif + log_printf2("Delete: DeleteFile on Reboot(\"%s\")",buf2); + update_status_text(LANG_STR(LANG_DELETEONREBOOT),buf2); + MoveFileOnReboot(buf2,NULL); + } + else +#endif + { + exec_errorflag++; + } + } + } + } while (FindNextFile(h,&fd)); + FindClose(h); + } + } + return 0; +#endif//NSIS_SUPPORT_DELETE +#ifdef NSIS_SUPPORT_MESSAGEBOX + case EW_MESSAGEBOX: // MessageBox + { + int v; + process_string_fromtab(buf4,parms[1]); + log_printf3("MessageBox: %d,\"%s\"",parms[0],buf4); + v=MessageBox(g_hwnd,buf4,g_caption,parms[0]); + if (v) + { + if (v==(parms[2]&0xffff)) + { + return parms[3]; + } + if (v==(parms[2]>>16)) + { + return parms[4]; + } + } + else exec_errorflag++; + } + return 0; +#endif//NSIS_SUPPORT_MESSAGEBOX +#ifdef NSIS_SUPPORT_RMDIR + case EW_RMDIR: + { + process_string_fromtab(buf,parms[0]); + log_printf2("RMDir: \"%s\"",buf); + + if (lastchar(buf)=='\\') trimslashtoend(buf); + + doRMDir(buf,parms[1]); + if (file_exists(buf)) exec_errorflag++; + } + return 0; +#endif//NSIS_SUPPORT_RMDIR +#ifdef NSIS_SUPPORT_STROPTS + case EW_STRLEN: + process_string_fromtab(buf,parms[1]); + myitoa(g_usrvars[parms[0]],lstrlen(buf)); + return 0; + case EW_ASSIGNVAR: + { + int newlen=process_string_fromtab_toint(parms[2]); + int start=process_string_fromtab_toint(parms[3]); + int l; + char *p=g_usrvars[parms[0]]; + process_string_fromtab(buf,parms[1]); + *p=0; + if (parms[2] < 0 || newlen) + { + l=lstrlen(buf); + + if (start<0) start=l+start; + if (start>=0) + { + if (start>l) start=l; + lstrcpy(p,buf+start); + if (newlen) + { + if (newlen<0) newlen=lstrlen(p)+newlen; + if (newlen<0) newlen=0; + if (newlen < NSIS_MAX_STRLEN) p[newlen]=0; + } + } + } + } + return 0; + case EW_STRCMP: + process_string_fromtab(buf3,parms[0]); + process_string_fromtab(buf4,parms[1]); + if (!lstrcmpi(buf3,buf4)) return parms[2]; + return parms[3]; +#endif//NSIS_SUPPORT_STROPTS +#ifdef NSIS_SUPPORT_ENVIRONMENT + case EW_READENVSTR: + { + char *p=g_usrvars[parms[0]]; + process_string_fromtab(buf,parms[1]); + if (parms[2]) + { + if (!GetEnvironmentVariable(buf,p,NSIS_MAX_STRLEN)) + { + *p=0; + exec_errorflag++; + } + } + else + { + ExpandEnvironmentStrings(buf,p,NSIS_MAX_STRLEN); + } + p[NSIS_MAX_STRLEN-1]=0; + } + return 0; +#endif//NSIS_SUPPORT_ENVIRONMENT +#ifdef NSIS_SUPPORT_INTOPTS + case EW_INTCMP: + { + int v,v2; + v=process_string_fromtab_toint(parms[0]); + v2=process_string_fromtab_toint(parms[1]); + if (vv2) return parms[4]; + } + return parms[2]; + case EW_INTCMPU: + { + unsigned int v,v2; + v=(unsigned int)process_string_fromtab_toint(parms[0]); + v2=(unsigned int)process_string_fromtab_toint(parms[1]); + if (vv2) return parms[4]; + } + return parms[2]; + case EW_INTOP: + { + int v,v2; + char *p=g_usrvars[parms[0]]; + v=process_string_fromtab_toint(parms[1]); + v2=process_string_fromtab_toint(parms[2]); + switch (parms[3]) + { + case 0: v+=v2; break; + case 1: v-=v2; break; + case 2: v*=v2; break; + case 3: if (v2) v/=v2; else { v=0; exec_errorflag++; } break; + case 4: v|=v2; break; + case 5: v&=v2; break; + case 6: v^=v2; break; + case 7: v=~v; break; + case 8: v=!v; break; + case 9: v=v||v2; break; + case 10: v=v&&v2; break; + case 11: if (v2) v%=v2; else { v=0; exec_errorflag++; } break; + } + myitoa(p,v); + } + return 0; + case EW_INTFMT: + process_string_fromtab(buf,parms[1]); + wsprintf(g_usrvars[parms[0]], + buf, + process_string_fromtab_toint(parms[2])); + return 0; +#endif//NSIS_SUPPORT_INTOPTS +#ifdef NSIS_SUPPORT_STACK + case EW_PUSHPOP: + { + stack_t *s=g_st; + int cnt=parms[2]; + if (cnt) //Exch contributed by Fritz Elfert + { + while (cnt--&&s) s=s->next; + if (!s) + { + log_printf2("Exch: stack < %d elements",parms[2]); + break; + } + lstrcpy(buf,s->text); + lstrcpy(s->text,g_st->text); + lstrcpy(g_st->text,buf); + } + else if (parms[1]) + { + if (!s) + { + log_printf("Pop: stack empty"); + exec_errorflag++; + return 0; + } + lstrcpy(g_usrvars[parms[0]],s->text); + g_st=s->next; + GlobalFree((HGLOBAL)s); + } + else + { + s=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)); + process_string_fromtab(s->text,parms[0]); + s->next=g_st; + g_st=s; + } + } + return 0; +#endif//NSIS_SUPPORT_STACK +#ifdef NSIS_SUPPORT_HWNDS + case EW_FINDWINDOW: + case EW_SENDMESSAGE: + { + int v; + int b3=process_string_fromtab_toint(parms[3]); + int b4=process_string_fromtab_toint(parms[4]); + + process_string_fromtab(buf,parms[1]); + process_string_fromtab(buf2,parms[2]); + + if (which == EW_SENDMESSAGE) v=SendMessage((HWND)myatoi(buf),myatoi(buf2),b3,b4); + else v=(int)FindWindowEx((HWND)b3,(HWND)b4,buf[0]?buf:NULL,buf2[0]?buf2:NULL); + + if (parms[0]>=0) + myitoa(g_usrvars[parms[0]],v); + } + return 0; + case EW_ISWINDOW: + if (IsWindow((HWND)process_string_fromtab_toint(parms[0]))) return parms[1]; + return parms[2]; + case EW_SETDLGITEMTEXT: + process_string_fromtab(buf,parms[1]); + SetDlgItemText(g_hwnd,parms[0],buf); + return 0; +#endif +#ifdef NSIS_SUPPORT_SHELLEXECUTE + case EW_SHELLEXEC: // this uses improvements of Andras Varga + { + int x; + process_string_fromtab(buf,parms[0]); + process_string_fromtab(buf2,parms[1]); + process_string_fromtab(buf3,parms[2]); + lstrcpy(buf4,buf); + lstrcat(buf4," "); + lstrcat(buf4,buf2); + update_status_text(LANG_STR(LANG_EXECSHELL), buf4); + x=(int)ShellExecute(g_hwnd,buf[0]?buf:NULL,buf2,buf3[0]?buf3:NULL,state_output_directory,parms[3]); + if (x < 33) + { + log_printf5("ExecShell: warning: error (\"%s\": file:\"%s\" params:\"%s\")=%d",buf,buf2,buf3,x); + exec_errorflag++; + } + else + { + log_printf4("ExecShell: success (\"%s\": file:\"%s\" params:\"%s\")",buf,buf2,buf3); + } + } + return 0; +#endif//NSIS_SUPPORT_SHELLEXECUTE +#ifdef NSIS_SUPPORT_EXECUTE + case EW_EXECUTE: + { + HANDLE hProc; + process_string_fromtab(buf,parms[0]); + log_printf2("Exec: command=\"%s\"",buf); + update_status_text(LANG_STR(LANG_EXECUTE),buf); + + hProc=myCreateProcess(buf,*state_output_directory?state_output_directory:NULL); + + if (hProc) + { + log_printf2("Exec: success (\"%s\")",buf); + if (parms[1]) + { + DWORD lExitCode; + while (WaitForSingleObject(hProc,100) == WAIT_TIMEOUT) + { + static MSG msg; + while (PeekMessage(&msg,NULL,WM_PAINT,WM_PAINT,PM_REMOVE)) + DispatchMessage(&msg); + } + GetExitCodeProcess(hProc, &lExitCode); + + if (parms[2]>=0) myitoa(g_usrvars[parms[2]],lExitCode); + else if (lExitCode) exec_errorflag++; + } + CloseHandle( hProc ); + } + else + { + exec_errorflag++; + log_printf2("Exec: failed createprocess (\"%s\")",buf); + } + } + return 0; +#endif//NSIS_SUPPORT_EXECUTE +#ifdef NSIS_SUPPORT_GETFILETIME + case EW_GETFILETIME: + // this new implementation based on one by Dave Bau + // used FindFirstFile instead of GetFileTime to better handle files that are locked. + // also allows GetFileTime to be passed a wildcard. + { + WIN32_FIND_DATA *ffd; + char *highout=g_usrvars[parms[1]]; + char *lowout=g_usrvars[parms[2]]; + process_string_fromtab(buf,parms[0]); + + ffd=file_exists(buf); + if (ffd) + { + myitoa(lowout,ffd->ftLastWriteTime.dwLowDateTime); + myitoa(highout,ffd->ftLastWriteTime.dwHighDateTime); + } + else + { + *lowout=*highout=0; + exec_errorflag++; + } + } + return 0; +#endif//NSIS_SUPPORT_GETFILETIME +#ifdef NSIS_SUPPORT_GETDLLVERSION + case EW_GETDLLVERSION: + { + char *highout=g_usrvars[parms[1]]; + char *lowout=g_usrvars[parms[2]]; + DWORD s1; + DWORD t[4]; // our two members are the 3rd and 4th.. + VS_FIXEDFILEINFO *pvsf1=(VS_FIXEDFILEINFO*)t; + DWORD d; + process_string_fromtab(buf,parms[0]); + s1=GetFileVersionInfoSize(buf,&d); + *lowout=*highout=0; + exec_errorflag++; + if (s1) + { + void *b1; + b1=(void*)GlobalAlloc(GPTR,s1); + if (b1) + { + UINT uLen; + if (GetFileVersionInfo(buf,0,s1,b1) && VerQueryValue(b1,"\\",(void*)&pvsf1,&uLen)) + { + myitoa(highout,pvsf1->dwFileVersionMS); + myitoa(lowout,pvsf1->dwFileVersionLS); + + exec_errorflag--; + } + GlobalFree(b1); + } + } + } + return 0; +#endif//NSIS_SUPPORT_GETDLLVERSION +#ifdef NSIS_SUPPORT_ACTIVEXREG + case EW_REGISTERDLL: + { + HRESULT hres=OleInitialize(NULL); + exec_errorflag++; + if (hres == S_FALSE || hres == S_OK) + { + HANDLE h; + process_string_fromtab(buf,parms[0]); + process_string_fromtab(buf2,parms[1]); + + h=LoadLibrary(buf); + if (h) + { + FARPROC funke = GetProcAddress(h,buf2); + if (funke) + { + exec_errorflag--; + if (parms[2]<0) + { + void (*func)(HWND,int,char*,void*); + func=(void*)funke; + func(g_hwnd,NSIS_MAX_STRLEN,(char*)g_usrvars, +#ifdef NSIS_SUPPORT_STACK + (void*)&g_st); +#else + NULL); +#endif + } + else + { + process_string_fromtab(buf3,parms[2]); + update_status_text(buf3,buf); + funke(); + } + } + else + { + update_status_text(LANG_STR(LANG_CANNOTFINDSYMBOL),buf2); + log_printf3("Error registering DLL: %s not found in %s",buf2,buf); + } + FreeLibrary(h); + } + else + { + update_status_text(LANG_STR(LANG_COULDNOTLOAD),buf); + log_printf2("Error registering DLL: Could not load %s",buf); + } + OleUninitialize(); + } + else + { + update_status_text(LANG_STR(LANG_NOOLE),buf); + log_printf("Error registering DLL: Could not initialize OLE"); + } + } + return 0; +#endif +#ifdef NSIS_SUPPORT_CREATESHORTCUT + case EW_CREATESHORTCUT: + process_string_fromtab(buf3,parms[0]); + process_string_fromtab(buf2,parms[1]); + process_string_fromtab(buf, parms[2]); + process_string_fromtab(buf4,parms[3]); + + log_printf8("CreateShortCut: out: \"%s\", in: \"%s %s\", icon: %s,%d, sw=%d, hk=%d", + buf3,buf2,buf,buf4,parms[4]&0xff,(parms[4]&0xff00)>>8,parms[4]>>16); + + if (CreateShortCut(g_hwnd, buf3, buf4[0]?buf4:NULL, parms[4]&0xff, buf2, buf[0]?buf:NULL, + state_output_directory,(parms[4]&0xff00)>>8,parms[4]>>16)) + { + exec_errorflag++; + update_status_text(LANG_STR(LANG_ERRORCREATINGSHORTCUT),buf3); + } + else + { + update_status_text(LANG_STR(LANG_CREATESHORTCUT),buf3); + } + return 0; +#endif//NSIS_SUPPORT_CREATESHORTCUT +#ifdef NSIS_SUPPORT_COPYFILES + case EW_COPYFILES: // CopyFile (added by NOP) + { + int res; + SHFILEOPSTRUCT op; + process_string_fromtab(buf,parms[0]); + process_string_fromtab(buf2,parms[1]); + log_printf3("CopyFiles \"%s\"->\"%s\"",buf,buf2); + op.hwnd=g_hwnd; + op.wFunc=FO_COPY; + buf[lstrlen(buf)+1]=0; + buf2[lstrlen(buf2)+1]=0; + + lstrcpy(buf3,LANG_STR(LANG_COPYTO)); + lstrcat(buf3,buf2); + + op.pFrom=buf; + op.pTo=buf2; + op.lpszProgressTitle=buf3; + op.fFlags=parms[2]; + update_status_text("",buf3); + res=SHFileOperation(&op); + if (res) + { // some of these changes were from Edgewise (wiked_edge@yahoo.com) + update_status_text(LANG_STR(LANG_COPYFAILED),""); + exec_errorflag++; + } + } + return 0; +#endif//NSIS_SUPPORT_COPYFILES +#ifdef NSIS_SUPPORT_REBOOT + case EW_REBOOT: + exec_errorflag++; + if (parms[0] == 0xbadf00d) + { + HANDLE h=LoadLibrary("advapi32.dll"); + if (h) + { + BOOL (*OPT)(HANDLE, DWORD,PHANDLE); + BOOL (*LPV)(LPCTSTR,LPCTSTR,PLUID); + BOOL (*ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD); + OPT=(void*)GetProcAddress(h,"OpenProcessToken"); + LPV=(void*)GetProcAddress(h,"LookupPrivilegeValueA"); + ATP=(void*)GetProcAddress(h,"AdjustTokenPrivileges"); + if (OPT && LPV && ATP) + { + HANDLE hToken; + TOKEN_PRIVILEGES tkp; + if (OPT(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + LPV(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ATP(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + } + } + } + + if (ExitWindowsEx(EWX_REBOOT|EWX_FORCE,0)) ExitProcess(0); + + FreeLibrary(h); + + return 0; + } + break; + case EW_IFREBOOTFLAG: return parms[!exec_rebootflag]; + case EW_SETREBOOTFLAG: exec_rebootflag=parms[0]; return 0; +#endif//NSIS_SUPPORT_REBOOT +#ifdef NSIS_SUPPORT_INIFILES + case EW_WRITEINI: + { + char *sec, *ent; + sec=ent=0; +#ifdef NSIS_CONFIG_LOG + lstrcpy(buf2,""); + lstrcpy(buf3,buf2); +#endif + process_string_fromtab(buf,parms[0]); + if (parms[1]>=0) + { + process_string_fromtab(buf2,parms[1]); + sec=buf2; + } + if (parms[2]>=0) + { + process_string_fromtab(buf3,parms[2]); + ent=buf3; + } + process_string_fromtab(buf4,parms[3]); + log_printf5("WriteINIStr: wrote [%s] %s=%s in %s",buf,buf2,buf3,buf4); + if (!WritePrivateProfileString(buf,sec,ent,buf4)) exec_errorflag++; + } + return 0; + case EW_READINISTR: + { + static const char *errstr="!N~"; + char *p=g_usrvars[parms[0]]; + process_string_fromtab(buf,parms[1]); + process_string_fromtab(buf2,parms[2]); + process_string_fromtab(buf3,parms[3]); + GetPrivateProfileString(buf,buf2,errstr,p,NSIS_MAX_STRLEN-1,buf3); + if (*((int*)errstr) == *((int*)p)) + { + exec_errorflag++; + p[0]=0; + } + } + return 0; +#endif//NSIS_SUPPORT_INIFILES +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + case EW_DELREG: + { + int rootkey=parms[0]; + exec_errorflag++; + process_string_fromtab(buf4,parms[1]); + if (parms[2] != -1) + { + HKEY hKey; + if (RegOpenKeyEx((HKEY)rootkey,buf4,0,KEY_ALL_ACCESS,&hKey) == ERROR_SUCCESS) + { + process_string_fromtab(buf,parms[2]); + log_printf4("DeleteRegValue: %d\\%s\\%s",rootkey,buf4,buf); + if (RegDeleteValue(hKey,buf) == ERROR_SUCCESS) exec_errorflag--; + RegCloseKey(hKey); + } + } + else + { + log_printf3("DeleteRegKey: %d\\%s",rootkey,buf4); + if (myRegDeleteKeyEx((HKEY)rootkey,buf4,parms[3]) == ERROR_SUCCESS) exec_errorflag--; + } + } + return 0; + case EW_WRITEREG: // write registry value + { + HKEY hKey; + int rootkey=parms[0]; + int type=parms[4]; + exec_errorflag++; + process_string_fromtab(buf2,parms[2]); + process_string_fromtab(buf4,parms[1]); + if (RegCreateKey((HKEY)rootkey,buf4,&hKey) == ERROR_SUCCESS) + { + if (type <= 1) + { + process_string_fromtab(buf3,parms[3]); + if (RegSetValueEx(hKey,buf2,0,type==1?REG_SZ:REG_EXPAND_SZ,buf3,lstrlen(buf3)+1) == ERROR_SUCCESS) exec_errorflag--; + log_printf5("WriteRegStr: set %d\\%s\\%s to %s",rootkey,buf4,buf2,buf3); + } + else if (type == 2) + { + DWORD l; + l=process_string_fromtab_toint(parms[3]); + if (RegSetValueEx(hKey,buf2,0,REG_DWORD,(unsigned char*)&l,4) == ERROR_SUCCESS) exec_errorflag--; + log_printf5("WriteRegDWORD: set %d\\%s\\%s to %d",rootkey,buf4,buf2,l); + } + else if (type == 3) + { + int len=GetCompressedDataFromDataBlockToMemory(parms[3], buf3, NSIS_MAX_STRLEN); + if (len >= 0) + { + if (RegSetValueEx(hKey,buf2,0,REG_BINARY,buf3,len) == ERROR_SUCCESS) exec_errorflag--; + } + log_printf5("WriteRegBin: set %d\\%s\\%s with %d bytes",rootkey,buf4,buf2,len); + + } + RegCloseKey(hKey); + } + else { log_printf3("WriteReg: error creating key %d\\%s",rootkey,buf4); } + } + return 0; + case EW_READREGSTR: // read registry string + { + HKEY hKey; + char *p=g_usrvars[parms[0]]; + int rootkey=parms[1]; + process_string_fromtab(buf,parms[2]); // buf == subkey + process_string_fromtab(buf2,parms[3]); // buf == key name + p[0]=0; + if (RegOpenKeyEx((HKEY)rootkey,buf,0,KEY_READ,&hKey) == ERROR_SUCCESS) + { + DWORD l = NSIS_MAX_STRLEN; + DWORD t; + + if (RegQueryValueEx(hKey,buf2,NULL,&t,p,&l ) != ERROR_SUCCESS || + (t != REG_DWORD && t != REG_SZ && t != REG_EXPAND_SZ)) + { + p[0]=0; + exec_errorflag++; + } + else + { + if (t==REG_DWORD) + { + if (!parms[4]) exec_errorflag++; + myitoa(p,*((DWORD*)p)); + } + else if (parms[4]) exec_errorflag++; + } + RegCloseKey(hKey); + } + else exec_errorflag++; + } + return 0; + case EW_REGENUM: + { + HKEY key; + char *p=g_usrvars[parms[0]]; + int b=process_string_fromtab_toint(parms[3]); + process_string_fromtab(buf2,parms[2]); + p[0]=0; + if (RegOpenKeyEx((HKEY)parms[1],buf2,0,KEY_ALL_ACCESS,&key) == ERROR_SUCCESS) + { + DWORD d=NSIS_MAX_STRLEN-1; + if (parms[4]) RegEnumKey(key,b,p,d); + else RegEnumValue(key,b,p,&d,NULL,NULL,NULL,NULL); + p[NSIS_MAX_STRLEN-1]=0; + RegCloseKey(key); + } + else exec_errorflag++; + } + + return 0; +#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + case EW_FCLOSE: + { + char *t=g_usrvars[parms[0]]; + if (*t) CloseHandle((HANDLE)myatoi(t)); + } + return 0; + case EW_FOPEN: + { + HANDLE h; + char *handleout=g_usrvars[parms[3]]; + process_string_fromtab(buf,parms[0]); + h=myOpenFile(buf,parms[1],parms[2]); + if (h == INVALID_HANDLE_VALUE) + { + *handleout=0; + exec_errorflag++; + } + else + { + myitoa(handleout,(int)h); + } + } + return 0; + case EW_FPUTS: + { + DWORD dw; + int l; + char *t=g_usrvars[parms[0]]; + if (parms[2]) + { + ((unsigned char *)buf2)[0]=process_string_fromtab_toint(parms[1])&0xff; + l=1; + } + else + { + process_string_fromtab(buf2,parms[1]); + l=lstrlen(buf2); + } + if (!*t || !WriteFile((HANDLE)myatoi(t),buf2,l,&dw,NULL)) + { + exec_errorflag++; + } + } + return 0; + case EW_FGETS: + { + char *textout=g_usrvars[parms[1]]; + DWORD dw; + int rpos=0; + char *hptr=g_usrvars[parms[0]]; + int maxlen=process_string_fromtab_toint(parms[2]); + if (maxlen<1) return 0; + if (maxlen > NSIS_MAX_STRLEN-1) maxlen=NSIS_MAX_STRLEN-1; + if (*hptr) + { + char lc=0; + int rcnt=0; + HANDLE h=(HANDLE)myatoi(hptr); + while (rpos=0) + { + myitoa(g_usrvars[parms[3]],v); + } + } + } + return 0; +#endif//NSIS_SUPPORT_FILEFUNCTIONS +#ifdef NSIS_SUPPORT_FINDFIRST + case EW_FINDCLOSE: + { + char *t=g_usrvars[parms[0]]; + if (*t) FindClose((HANDLE)myatoi(t)); + } + return 0; + case EW_FINDNEXT: + { + char *textout=g_usrvars[parms[0]]; + char *t=g_usrvars[parms[1]]; + WIN32_FIND_DATA fd; + if (*t && FindNextFile((HANDLE)myatoi(t),&fd)) + { + lstrcpy(textout,fd.cFileName); + } + else + { + exec_errorflag++; + *textout=0; + } + + } + return 0; + case EW_FINDFIRST: + { + char *textout=g_usrvars[parms[1]]; + char *handleout=g_usrvars[parms[2]]; + HANDLE h; + WIN32_FIND_DATA fd; + process_string_fromtab(buf,parms[0]); + h=FindFirstFile(buf,&fd); + if (h == INVALID_HANDLE_VALUE) + { + *handleout=0; + *textout=0; + exec_errorflag++; + } + else + { + myitoa(handleout,(int)h); + lstrcpy(textout,fd.cFileName); + } + } + return 0; +#endif//NSIS_SUPPORT_FINDFIRST +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + case EW_WRITEUNINSTALLER: + { + int ret=-666; + HANDLE hFile; + process_string_fromtab(buf,parms[0]); + + if (validpathspec(buf)) + { + lstrcpy(buf2,buf); + } + else + { + lstrcpy(buf2,state_install_directory); + addtrailingslash(buf2); + lstrcat(buf2,buf); + } + + + hFile=myOpenFile(buf2,GENERIC_WRITE,CREATE_ALWAYS); + if (hFile != INVALID_HANDLE_VALUE) + { + unsigned char *filebuf; + DWORD l; + filebuf=(unsigned char *)GlobalAlloc(GMEM_FIXED,g_filehdrsize); + if (filebuf) + { + int fixoffs=0; + SetFilePointer(g_db_hFile,0,NULL,FILE_BEGIN); + ReadFile(g_db_hFile,(char*)filebuf,g_filehdrsize,&l,NULL); + if (g_inst_header->uninstdata_offset != -1) + { + // Changed by Amir Szekely 11th July 2002 + unsigned char* unicon_data = (unsigned char*)GlobalAlloc(GMEM_FIXED, g_inst_header->uninsticon_size); + if (unicon_data) { + DWORD i, j; + unsigned char* seeker = unicon_data + sizeof(DWORD); + GetCompressedDataFromDataBlockToMemory(g_inst_header->uninstdata_offset, + unicon_data,g_inst_header->uninsticon_size); + for (i = 0; i < *(DWORD*)unicon_data; i++) { + DWORD dwSize, dwOffset; + dwSize = *(DWORD*)seeker; + seeker += sizeof(DWORD); + dwOffset = *(DWORD*)seeker; + seeker += sizeof(DWORD); + for (j = 0; j < dwSize; j++) + filebuf[dwOffset+j] = seeker[j]; + seeker += dwSize; + } + GlobalFree(unicon_data); + } + } + WriteFile(hFile,(char*)filebuf,g_filehdrsize,&l,NULL); + GlobalFree(filebuf); + ret=GetCompressedDataFromDataBlock(-1,hFile); + } + CloseHandle(hFile); + } + log_printf3("created uninstaller: %d, \"%s\"",ret,buf2); + if (ret < 0) + { + update_status_text(LANG_STR(LANG_ERRORCREATING),buf); + DeleteFile(buf2); + } + else + update_status_text(LANG_STR(LANG_CREATEDUNINST),buf); + } + return 0; +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_CONFIG_LOG + case EW_LOG: + if (parms[0]) + { + log_printf2("settings logging to %d",parms[1]); + log_dolog=parms[1]; + log_printf2("logging set to %d",parms[1]); + } + else + { + process_string_fromtab(buf,parms[1]); + log_printf2("%s",buf); + } + return 0; +#endif//NSIS_CONFIG_LOG +#ifdef NSIS_CONFIG_COMPONENTPAGE + case EW_SECTIONSET: + { + int x=process_string_fromtab_toint(parms[0]); + if (g_inst_section && x >= 0 && x < g_inst_header->num_sections) + { + int z=0; + if (g_SectionHack) + { + int a; + for (a = 0; a < x; a ++) if (g_inst_section[a].name_ptr>=0) z++; + } + + if (parms[1]==0) //set text + { + if (g_SectionHack) + { + SendMessage(g_SectionHack,WM_USER+0x17,x,parms[2]); + } + g_inst_section[x].name_ptr=parms[2]; + } + else if (parms[1]==1) // get text + { + process_string_fromtab(g_usrvars[parms[2]],g_inst_section[x].name_ptr); + } + else if (parms[1]==2) // set flags + { + g_inst_section[x].default_state=process_string_fromtab_toint(parms[2]); + if (g_SectionHack) + { + SendMessage(g_SectionHack,WM_USER+0x18,x,(LPARAM)!!(g_inst_section[x].default_state&DFS_SET)); + } + } + else // get flags + { + myitoa(g_usrvars[parms[2]],g_inst_section[x].default_state); + } + } + else exec_errorflag++; + } + return 0; +#endif//NSIS_CONFIG_COMPONENTPAGE +// Added by Amir Szekely 21st 2002 +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case EW_SETBRANDINGIMAGE: + { + RECT r; + HWND hwImage = GetDlgItem(g_hwnd, parms[1]); + GetWindowRect(hwImage, &r); + process_string_fromtab(buf, parms[0]); + if (g_hBrandingBitmap) DeleteObject(g_hBrandingBitmap); + g_hBrandingBitmap=LoadImage( + 0, + buf, + IMAGE_BITMAP, + parms[2]?r.right-r.left:0, + parms[2]?r.bottom-r.top:0, + LR_LOADFROMFILE + ); + SendMessage( + hwImage, + STM_SETIMAGE, + IMAGE_BITMAP, + (LPARAM)g_hBrandingBitmap + ); + } + return 0; +#endif //NSIS_CONFIG_VISIBLE_SUPPORT + } + MessageBox(g_hwnd,LANG_STR(LANG_INSTCORRUPTED),g_caption,MB_OK|MB_ICONSTOP); + return EXEC_ERROR; +} diff --git a/Source/exehead/exec.h b/Source/exehead/exec.h new file mode 100644 index 00000000..cc4d7234 --- /dev/null +++ b/Source/exehead/exec.h @@ -0,0 +1,7 @@ +#ifndef _EXEC_H_ +#define _EXEC_H_ + +int ExecuteCodeSegment(entry *entries, int pos, HWND hwndProgress); // returns 0 on success + + +#endif//_EXEC_H_ \ No newline at end of file diff --git a/Source/exehead/exehead-bzip2.dsp b/Source/exehead/exehead-bzip2.dsp new file mode 100644 index 00000000..0009ff2f --- /dev/null +++ b/Source/exehead/exehead-bzip2.dsp @@ -0,0 +1,251 @@ +# Microsoft Developer Studio Project File - Name="exehead_bzip2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=exehead_bzip2 - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "exehead-bzip2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "exehead-bzip2.mak" CFG="exehead_bzip2 - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "exehead_bzip2 - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release-bzip2" +# PROP Intermediate_Dir "Release-bzip2" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O1 /Oy /D "_WINDOWS" /D "EXEHEAD" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /D "NSIS_COMPRESS_USE_BZIP2" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib shell32.lib /nologo /entry:"WinMain" /subsystem:windows /pdb:none /machine:I386 /nodefaultlib /out:"Release-bzip2/exehead_bzip2.exe" /opt:nowin98 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=generating include file for makenssi +PostBuild_Cmds=bin2h Release-bzip2\exehead_bzip2.exe Release-bzip2\exehead_bzip2.h bzip2_header_data +# End Special Build Tool +# Begin Target + +# Name "exehead_bzip2 - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Group "headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\zlib\Infblock.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Infcodes.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Inftrees.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Infutil.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Zconf.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Zlib.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\zlib\INFBLOCK.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFCODES.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFLATE.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFTREES.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFUTIL.C +# End Source File +# End Group +# Begin Group "bzip2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\bzip2\bzlib.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\bzlib.h +# End Source File +# Begin Source File + +SOURCE=..\bzip2\bzlib_private.h +# End Source File +# Begin Source File + +SOURCE=..\bzip2\decompress.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\huffman.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\randtable.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\bgbg.c +# End Source File +# Begin Source File + +SOURCE=..\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\exec.c +# End Source File +# Begin Source File + +SOURCE=.\fileform.c +# End Source File +# Begin Source File + +SOURCE=.\Main.c +# End Source File +# Begin Source File + +SOURCE=.\Ui.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\exec.h +# End Source File +# Begin Source File + +SOURCE=.\fileform.h +# End Source File +# Begin Source File + +SOURCE=.\lang.h +# End Source File +# Begin Source File + +SOURCE=.\state.h +# End Source File +# Begin Source File + +SOURCE=.\ui.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap2.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap3.bmp +# End Source File +# Begin Source File + +SOURCE=.\icon3.ico +# End Source File +# Begin Source File + +SOURCE=.\nsis.ico +# End Source File +# Begin Source File + +SOURCE=.\nullsoft.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\uninst.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\exehead.xml +# End Source File +# End Target +# End Project diff --git a/Source/exehead/exehead-zlib.dsp b/Source/exehead/exehead-zlib.dsp new file mode 100644 index 00000000..2dd7e7af --- /dev/null +++ b/Source/exehead/exehead-zlib.dsp @@ -0,0 +1,251 @@ +# Microsoft Developer Studio Project File - Name="exehead_zlib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=exehead_zlib - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "exehead-zlib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "exehead-zlib.mak" CFG="exehead_zlib - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "exehead_zlib - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release-zlib" +# PROP Intermediate_Dir "Release-zlib" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O1 /Oy /D "_WINDOWS" /D "EXEHEAD" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /D "NSIS_COMPRESS_USE_ZLIB" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib shell32.lib /nologo /entry:"WinMain" /subsystem:windows /pdb:none /machine:I386 /nodefaultlib /out:"Release-zlib/exehead_zlib.exe" /opt:nowin98 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=generating include file for makenssi +PostBuild_Cmds=bin2h Release-zlib\exehead_zlib.exe Release-zlib\exehead_zlib.h zlib_header_data bin2h bitmap1.bmp Release-zlib\bitmap1.h bitmap1_data bin2h nsis.ico Release-zlib\icon.h icon_data bin2h uninst.ico Release-zlib\unicon.h unicon_data +# End Special Build Tool +# Begin Target + +# Name "exehead_zlib - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Group "headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\zlib\Infblock.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Infcodes.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Inftrees.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Infutil.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Zconf.h +# End Source File +# Begin Source File + +SOURCE=..\zlib\Zlib.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\zlib\INFBLOCK.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFCODES.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFLATE.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFTREES.C +# End Source File +# Begin Source File + +SOURCE=..\zlib\INFUTIL.C +# End Source File +# End Group +# Begin Group "bzip2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\bzip2\bzlib.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\bzlib.h +# End Source File +# Begin Source File + +SOURCE=..\bzip2\bzlib_private.h +# End Source File +# Begin Source File + +SOURCE=..\bzip2\decompress.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\huffman.c +# End Source File +# Begin Source File + +SOURCE=..\bzip2\randtable.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\bgbg.c +# End Source File +# Begin Source File + +SOURCE=..\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\exec.c +# End Source File +# Begin Source File + +SOURCE=.\fileform.c +# End Source File +# Begin Source File + +SOURCE=.\Main.c +# End Source File +# Begin Source File + +SOURCE=.\Ui.c +# End Source File +# Begin Source File + +SOURCE=.\util.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\exec.h +# End Source File +# Begin Source File + +SOURCE=.\fileform.h +# End Source File +# Begin Source File + +SOURCE=.\lang.h +# End Source File +# Begin Source File + +SOURCE=.\state.h +# End Source File +# Begin Source File + +SOURCE=.\ui.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap2.bmp +# End Source File +# Begin Source File + +SOURCE=.\bitmap3.bmp +# End Source File +# Begin Source File + +SOURCE=.\icon3.ico +# End Source File +# Begin Source File + +SOURCE=.\nsis.ico +# End Source File +# Begin Source File + +SOURCE=.\nullsoft.ico +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\uninst.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\exehead.xml +# End Source File +# End Target +# End Project diff --git a/Source/exehead/exehead.xml b/Source/exehead/exehead.xml new file mode 100644 index 00000000..4f6ca891 --- /dev/null +++ b/Source/exehead/exehead.xml @@ -0,0 +1,10 @@ + + + +Nullsoft Install System. + + + + + + diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c new file mode 100644 index 00000000..5efb7c59 --- /dev/null +++ b/Source/exehead/fileform.c @@ -0,0 +1,323 @@ +#include +#include "fileform.h" +#include "util.h" +#include "state.h" + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +#ifdef NSIS_COMPRESS_USE_ZLIB +#include "../zlib/zlib.h" +#endif + +#ifdef NSIS_COMPRESS_USE_BZIP2 +#include "../bzip2/bzlib.h" +static int bz2_needreinit; +#define z_stream bz_stream +#define inflateInit(x) { if (BZ2_bzDecompressInit(x)<0) return -1; } +#define inflate(x) BZ2_bzDecompress(x) +#define inflateReset(x) { if (bz2_needreinit) { BZ2_bzDecompressEnd(x); inflateInit(x); } bz2_needreinit=1; } +#define Z_OK BZ_OK +#define Z_STREAM_END BZ_STREAM_END +#endif//NSIS_COMPRESS_USE_BZIP2 + +#endif + +#include "ui.h" + +static char *g_db_strtab; + +static int g_db_offset; +HANDLE g_db_hFile; + +#ifdef NSIS_COMPRESS_WHOLE +HANDLE dbd_hFile=INVALID_HANDLE_VALUE; +static int dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen; +#endif//NSIS_COMPRESS_WHOLE + +int isheader(firstheader *h) +{ + if ((h->flags & (~FH_FLAGS_MASK)) || + h->siginfo != FH_SIG || + h->nsinst[2] != FH_INT3 || + h->nsinst[1] != FH_INT2 || + h->nsinst[0] != FH_INT1) return 0; + return h->length_of_all_following_data; +} + + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +static z_stream g_inflate_stream; +#endif + +int loadHeaders(void) +{ + DWORD r; + void *data; + firstheader h; + + if (!ReadFile(g_db_hFile,(LPVOID)&h,sizeof(h),&r,NULL) || r != sizeof(h) || !isheader(&h)) return -1; + + data=(void*)GlobalAlloc(GMEM_FIXED,h.length_of_header); + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + inflateInit(&g_inflate_stream); +#endif + +#ifdef NSIS_COMPRESS_WHOLE + inflateReset(&g_inflate_stream); + + { + char fn[MAX_PATH],fno[MAX_PATH]; + GetTempPath(sizeof(fn),fn); + GetTempFileName(fn,"nsi",0,fno); + dbd_hFile=CreateFile(fno,GENERIC_WRITE|GENERIC_READ,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL); + if (dbd_hFile == INVALID_HANDLE_VALUE) + { + MessageBox(NULL,"Error writing temp file",g_caption,MB_OK); + return -1; + } + } + dbd_srcpos=SetFilePointer(g_db_hFile,0,NULL,FILE_CURRENT); + dbd_fulllen=dbd_srcpos-sizeof(h)+h.length_of_all_following_data-((h.flags&FH_FLAGS_CRC)?4:0); +#endif + + if (GetCompressedDataFromDataBlockToMemory(-1,data,h.length_of_header) != h.length_of_header) + { + MessageBox(NULL,"Error reading installer info block",g_caption,MB_OK); + GlobalFree((HGLOBAL)data); + return -1; + } + +#ifndef NSIS_COMPRESS_WHOLE + g_db_offset=SetFilePointer(g_db_hFile,0,NULL,FILE_CURRENT); +#else + g_db_offset=dbd_pos; +#endif + + g_inst_combinedheader=data; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (h.flags&FH_FLAGS_UNINSTALL) + { + g_is_uninstaller++; + g_inst_entry=(entry *) ((g_inst_uninstheader) + 1); + } + else +#endif + { + g_inst_section=(section *) (g_inst_header + 1); + g_inst_entry=(entry *) (g_inst_section + g_inst_header->num_sections); + } + g_db_strtab = (char *)(g_inst_entry + g_inst_cmnheader->num_entries); + return 0; +} + +const char *GetStringFromStringTab(int offs) +{ + if (offs < 0) return ""; + return g_db_strtab+offs; +} + +#define IBUFSIZE 16384 +#define OBUFSIZE 32768 + +// returns -3 if compression error/eof/etc + +#ifndef NSIS_COMPRESS_WHOLE + +static int _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen) +{ + static char inbuffer[IBUFSIZE+OBUFSIZE]; + char *outbuffer; + int outbuffer_len=outbuf?outbuflen:OBUFSIZE; + int retval=0; + int input_len; + DWORD r; + + outbuffer = outbuf?outbuf:(inbuffer+IBUFSIZE); + + if (offset>=0) + { + /* + int lp=SetFilePointer(g_db_hFile,0,NULL,FILE_CURRENT); + if (lp > g_db_offset+offset) + { + char buf[1023]; + wsprintf(buf,"going from %d to %d",lp,g_db_offset+offset); + MessageBox(NULL,buf,"seeking back",MB_OK); + } + */ + SetFilePointer(g_db_hFile,g_db_offset+offset,NULL,FILE_BEGIN); + } + + if (!ReadFile(g_db_hFile,(LPVOID)&input_len,sizeof(int),&r,NULL)) return -3; + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + else if (input_len & 0x80000000) // compressed + { + inflateReset(&g_inflate_stream); + input_len &= 0x7fffffff; // take off top bit. + + while (input_len > 0) + { + DWORD r; + int err; + + if (!ReadFile(g_db_hFile,(LPVOID)inbuffer,min(input_len,IBUFSIZE),&r,NULL)) return -3; + + g_inflate_stream.next_in = inbuffer; + g_inflate_stream.avail_in = r; + input_len-=r; + + for (;;) + { + int u; + g_inflate_stream.next_out = outbuffer; + g_inflate_stream.avail_out = (unsigned int)outbuffer_len; + + err=inflate(&g_inflate_stream); + + if (err<0) return -4; + + u=(char*)g_inflate_stream.next_out - outbuffer; + + if (!u) break; + + if (!outbuf) + { + if (!WriteFile(hFileOut,outbuffer,u,&r,NULL) || (int)r != u) return -2; + retval+=u; + } + else + { + retval+=u; + outbuffer_len-=u; + outbuffer=g_inflate_stream.next_out; + if (outbuffer_len < 1) return retval; + } + if (err==Z_STREAM_END) return retval; + } + } + } +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + else + { + if (!outbuf) + { + while (input_len > 0) + { + DWORD t; + if (!ReadFile(g_db_hFile,(LPVOID)inbuffer,min(input_len,outbuffer_len),&r,NULL)) return -3; + if (!WriteFile(hFileOut,inbuffer,r,&t,NULL) || r!=t) return -2; + retval+=r; + input_len-=r; + } + } + else + { + if (!ReadFile(g_db_hFile,(LPVOID)outbuf,min(input_len,outbuflen),&r,NULL)) return -3; + retval=r; + } + } + return retval; +} +#else//NSIS_COMPRESS_WHOLE + +static char _inbuffer[IBUFSIZE]; +static char _outbuffer[OBUFSIZE]; +static int __ensuredata(int amount) +{ + int needed=amount-(dbd_size-dbd_pos); + if (needed>0) + { + SetFilePointer(g_db_hFile,dbd_srcpos,NULL,FILE_BEGIN); + SetFilePointer(dbd_hFile,dbd_size,NULL,FILE_BEGIN); + for (;;) + { + int err; + DWORD or; + if (!ReadFile(g_db_hFile,(LPVOID)_inbuffer,min(IBUFSIZE,dbd_fulllen-dbd_srcpos),&or,NULL)) return -1; + dbd_srcpos+=or; + g_inflate_stream.next_in=_inbuffer; + g_inflate_stream.avail_in=or; + do + { + DWORD r,t; + g_inflate_stream.next_out=_outbuffer; + g_inflate_stream.avail_out=OBUFSIZE; + err=inflate(&g_inflate_stream); + if (err<0) + { + return -3; + } + r=g_inflate_stream.next_out-_outbuffer; + if (r) + { + if (!WriteFile(dbd_hFile,_outbuffer,r,&t,NULL) || r != t) + { + return -2; + } + dbd_size+=r; + } + else if (g_inflate_stream.avail_in || !or) return -3; + else break; + } + while (g_inflate_stream.avail_in); + if (amount-(dbd_size-dbd_pos) <= 0) break; + } + SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN); + } + return 0; +} + + +static int _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen) +{ + DWORD r; + int input_len; + int retval; + if (offset>=0) + { + dbd_pos=g_db_offset+offset; + SetFilePointer(dbd_hFile,dbd_pos,NULL,FILE_BEGIN); + } + retval=__ensuredata(sizeof(int)); + if (retval<0) return retval; + + if (!ReadFile(dbd_hFile,(LPVOID)&input_len,sizeof(int),&r,NULL) || r!=sizeof(int)) return -3; + dbd_pos+=sizeof(int); + + retval=__ensuredata(input_len); + if (retval < 0) return retval; + + if (!outbuf) + { + while (input_len > 0) + { + DWORD t; + if (!ReadFile(dbd_hFile,(LPVOID)_inbuffer,min(input_len,IBUFSIZE),&r,NULL)) return -3; + if (!WriteFile(hFileOut,_inbuffer,r,&t,NULL) || r!=t) return -2; + retval+=r; + input_len-=r; + dbd_pos+=r; + } + } + else + { + if (!ReadFile(dbd_hFile,(LPVOID)outbuf,min(input_len,outbuflen),&r,NULL)) return -3; + retval=r; + dbd_pos+=r; + } + return retval; +} +#endif//NSIS_COMPRESS_WHOLE + + +int GetCompressedDataFromDataBlock(int offset, HANDLE hFileOut) +{ + return _dodecomp(offset,hFileOut,NULL,0); +} + +int GetCompressedDataFromDataBlockToMemory(int offset, char *out, int out_len) +{ + return _dodecomp(offset,NULL,out,out_len); +} diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h new file mode 100644 index 00000000..dbbd42ab --- /dev/null +++ b/Source/exehead/fileform.h @@ -0,0 +1,324 @@ +#include "config.h" + +#ifndef _FILEFORM_H_ +#define _FILEFORM_H_ + + +// stored in file: +// exehead (~34k) +// firstheader (~28 bytes) +// hdrinfo (4 bytes describing length/compression):: +// (if install) +// header (~228 bytes) +// sections (20 bytes each) +// (if uninstall) +// uninstall_header (~116 bytes) +// entries (24 bytes each) +// string table +// datablock +// (hdrinfo+datablock is at least 512 bytes if CRC enabled) +// CRC (optional - 4 bytes) + + +#define MAX_ENTRY_OFFSETS 5 + + +// if you want people to not be able to decompile your installers as easily, +// reorder the lines following EW_INVALID_OPCODE randomly. + +enum +{ + EW_INVALID_OPCODE, // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction does nothing, which is + // easily ignored but means something is wrong. + EW_RET, // return from function call + EW_NOP, // Nop/Jump, do nothing: 1, [?new address+1:advance one] + EW_ABORT, // Abort: 1 [status] + EW_QUIT, // Quit: 0 + EW_CALL, // Call: 1 [new address+1] + EW_UPDATETEXT, // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this] + EW_SLEEP, // Sleep: 1 [sleep time in milliseconds] + EW_SETSFCONTEXT, // SetShellVarContext: 1: [isAll] + EW_HIDEWINDOW, // HideWindow: 0 + EW_BRINGTOFRONT, // BringToFront: 0 + EW_SETWINDOWCLOSE, // SetWindowClose: 1 [0: no window close at end, 1: window close at end] + EW_CHDETAILSVIEW, // SetDetailsView: 2 [listaction,buttonaction] + EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes] + EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR] + EW_IFFILEEXISTS, // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists] + EW_IFERRORS, //a IfErrors: 3 [jump if error, jump if not error, new_erflag] + EW_RENAME, // Rename: 3 [old, new, rebootok] + EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn] + EW_SEARCHPATH, // SearchPath: 2 [output, filename] + EW_GETTEMPFILENAME, // GetTempFileName: 1 [output] + EW_EXTRACTFILE, // File to extract: 5,[overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh] + // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer + EW_DELETEFILE, // Delete File: 2, [filename, rebootok] + EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2] + EW_RMDIR, // RMDir: 2 [path, recursiveflag] + EW_STRLEN, // StrLen: 2 [output, input] + EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos] + EW_STRCMP, // StrCmp: 4 [str1, str2, jump_if_equal, jump_if_not_equal] (case-insensitive) + EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead] + EW_INTCMP, // IntCmp: 5 [val1, val2, equal, val1val2] + EW_INTCMPU, // IntCmpU: 5 [val1, val2, equal, val1val2] + EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2 + EW_INTFMT, // IntFmt: [output, format, input] + EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch] + + EW_FINDWINDOW, // FindWindow: 5, [outputvar,window class,window name, window_parent, window_after] + EW_SENDMESSAGE, // SendMessage: 5 [output, hwnd, msg, lparam, wparam] + EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow] + EW_SETDLGITEMTEXT, // SetDlgItemText: 2 [item_id, text] + + EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow] + + EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode] + + EW_GETFILETIME, // GetFileTime; 3 [file highout lowout] + + EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout] + + EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms)] + + EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16] + + EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags] + + EW_REBOOT, // Reboot: 1 [0xbadf00d] + EW_IFREBOOTFLAG, // IfRebootFlag: 2 [if reboot flag set, if not reboot flag] + EW_SETREBOOTFLAG, // SetRebootFlag: 1 [new value] + + EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File] + EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file] + + EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key + EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen] + // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str + EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str] + EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value] + + EW_FCLOSE, // FileClose: 1 [handle] + EW_FOPEN, // FileOpen: 4 [name, openmode, createmode, outputhandle] + EW_FPUTS, // FileWrite: 3 [handle, string, ?int:string] + EW_FGETS, // FileRead: 4 [handle, output, maxlen, ?getchar:gets] + EW_FSEEK, // FileSeek: 4 [handle, offset, mode, >=0?positionoutput] + + EW_FINDCLOSE, // FindClose: 1 [handle] + EW_FINDNEXT, // FindNext: 2 [output, handle] + EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput] + + EW_WRITEUNINSTALLER, // WriteUninstaller: 1 [name] + + EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate] + + EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text] + // SectionGetText: 3: [idx, 1, output] + // SectionSetFlags: 3: [idx, 2, flags] + // SectionGetFlags: 3: [idx, 3, output] + + EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file] + + // instructions not actually implemented in exehead, but used in compiler. + EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR + EW_GETFUNCTIONADDR, + + +}; + + +// used for section->default_state +#define DFS_SET 0x80000000 +#define DFS_RO 0x40000000 + + + +typedef struct +{ + int flags; // &1=CRC, &2=uninstall, &4=silent + int siginfo; // FH_SIG + + int nsinst[3]; // FH_INT1,FH_INT2,FH_INT3 + + // these point to the header+sections+entries+stringtable in the datablock + int length_of_header; + + // this specifies the length of all the data (including the firstheader and CRC) + int length_of_all_following_data; +} firstheader; + +// Settings common to both installers and uninstallers +typedef struct +{ + // unprocessed strings + int branding_ptr; + int cancelbutton_ptr; + int showdetailsbutton_ptr; + int completed_ptr; + int closebutton_ptr; // "Close" + int name_ptr; // name of installer + + // processed strings + int caption_ptr; // name of installer + " Setup" or whatever. + int subcaption_ptrs[5]; + +#ifdef NSIS_SUPPORT_FILE + int fileerrtext_ptr; +#endif + + int num_entries; // total number of entries + +#ifdef NSIS_SUPPORT_BGBG + int bg_color1, bg_color2, bg_textcolor; +#endif + int lb_bg, lb_fg, license_bg; + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // .on* calls + int code_onInit; + int code_onInstSuccess; + int code_onInstFailed; + int code_onUserAbort; + int code_onNextPage; +#endif//NSIS_SUPPORT_CODECALLBACKS + + char show_details; + char progress_flags; +#ifdef NSIS_CONFIG_SILENT_SUPPORT + char silent_install; +#endif//NSIS_CONFIG_SILENT_SUPPORT + // additional flags + char misc_flags; // auto_close=&1, no_show_dirpage=&2, no_show_icon&4, no_rootdir&8; + +} common_header; + +// Settings specific to installers +typedef struct +{ + // common settings + common_header common; + + // these first strings are literals (should not be encoded) + int backbutton_ptr; + int nextbutton_ptr; + int browse_ptr; // "Browse..." + int installbutton_ptr; // "Install" + int spacerequired_ptr; // "Space required: " + int spaceavailable_ptr; // "Space available: " + int custom_ptr; // Custom + int text_ptr; // directory page text + int dirsubtext_ptr; // directory text2 +#ifdef NSIS_CONFIG_COMPONENTPAGE + int componenttext_ptr; // component page text + int componentsubtext_ptr[2]; +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE + int licensetext_ptr; // license page text + int licensedata_ptr; // license text + int licensebutton_ptr; // license button text + int license_bg; // license background color +#endif//NSIS_CONFIG_LICENSEPAGE + + int install_reg_rootkey, install_reg_key_ptr, install_reg_value_ptr; + +#ifdef NSIS_CONFIG_COMPONENTPAGE + int install_types_ptr[NSIS_MAX_INST_TYPES]; // -1 if not used. can describe as lite, normal, full, etc. +#endif + + // below here, the strings are processed (can have variables etc) + int install_directory_ptr; // default install dir. + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + int uninstdata_offset; // -1 if no uninst data. + int uninsticon_size; +#endif + +#ifdef NSIS_CONFIG_COMPONENTPAGE + int no_custom_instmode_flag; +#endif + + int num_sections; // total number of sections + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // .on* calls + int code_onPrevPage; + int code_onVerifyInstDir; +#ifdef NSIS_CONFIG_COMPONENTPAGE + int code_onSelChange; +#endif//NSIS_CONFIG_COMPONENTPAGE +#endif//NSIS_SUPPORT_CODECALLBACKS + +} header; + +// Settings specific to uninstallers +typedef struct +{ + // common settings + common_header common; + + // unprocessed strings + int uninstbutton_ptr; + int uninstalltext_ptr; + int uninstalltext2_ptr; + + int code; + int code_size; + +} uninstall_header; + +typedef struct +{ + int name_ptr; // '' for non-optional components + int default_state; // bits 0-30 set for each of the different install_types, if any. + // DFS_SET and DFS_RO can be set too + int code; + int code_size; + int size_kb; + int expand; +} section; + + +typedef struct +{ + int which; + int offsets[MAX_ENTRY_OFFSETS]; // count and meaning of offsets depend on 'which' +} entry; + + +#define FH_FLAGS_MASK 15 +#define FH_FLAGS_CRC 1 +#define FH_FLAGS_UNINSTALL 2 +#ifdef NSIS_CONFIG_SILENT_SUPPORT +#define FH_FLAGS_SILENT 4 +#endif +// Added by Amir Szekely 23rd July 2002 +#define FH_FLAGS_FORCE_CRC 8 + +#define FH_SIG 0xDEADBEEF + +// neato surprise signature that goes in firstheader. :) +#define FH_INT1 0x6C6C754E +#define FH_INT2 0x74666F73 +#define FH_INT3 0x74736E49 + +// the following are only used/implemented in exehead, not makensis. + +int isheader(firstheader *h); // returns 0 on not header, length_of_datablock on success + +// returns nonzero on error +// returns 0 on success +// on success, m_header will be set to a pointer that should eventually be GlobalFree()'d. +// (or m_uninstheader) +int loadHeaders(void); + +extern HANDLE g_db_hFile; +extern int g_quit_flag; + +const char *GetStringFromStringTab(int offs); +int GetCompressedDataFromDataBlock(int offset, HANDLE hFileOut); +int GetCompressedDataFromDataBlockToMemory(int offset, char *out, int out_len); + +// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value. +#define VAR_CODES_START (256 - 35) + + +#endif //_FILEFORM_H_ diff --git a/Source/exehead/lang.h b/Source/exehead/lang.h new file mode 100644 index 00000000..d17bbce0 --- /dev/null +++ b/Source/exehead/lang.h @@ -0,0 +1,57 @@ +#ifndef _NSIS_LANG_H_ +#define _NSIS_LANG_H_ + +// generic startup strings (these will never be overridable) +#define _LANG_INVALIDCRC "Installer verification failed.\r\n\r\n" \ + "This could be the result of an incomplete download,\r\n" \ + "a failing disk, or (possibly) corruption from a virus." \ + "\r\n\r\nYou can try to force an install using the /NCRC\r\n" \ + "command line switch (but it is NOT recommended)" + +#define _LANG_INVALIDINST "Installer corrupted.\r\n\r\n" \ + "This could be the result of an incomplete download" + + +#define _LANG_UNINSTINITERROR "Error initializing uninstaller" + +#define _LANG_VERIFYINGINST "verifying installer: %d%%" + +#define _LANG_CANTOPENSELF "Can't open self" + +#define _LANG_GENERIC_ERROR "NSIS ERROR" + + +#define LANG_STR(x) (x) + +// instruction strings (these may someday be stored in the datablock or string table, and accessed +// via LANG_STR() +#define LANG_DELETEFILE "Delete file: " +#define LANG_DLLREGERROR "Error registering DLL" +#define LANG_REMOVEDIR "Remove directory: " +#define LANG_OUTPUTDIR "Output directory: " +#define LANG_CREATEDIR "Create directory: " +#define LANG_RENAME "Rename: " +#define LANG_RENAMEONREBOOT "Rename on reboot: " +#define LANG_SKIPPED "Skipped: " +#define LANG_CANTWRITE "Can't write: " +#define LANG_EXTRACT "Extract: " +#define LANG_ERRORWRITING "Extract: error writing to file " +#define LANG_ERRORDECOMPRESSING "Error decompressing data! Corrupted installer?" +#define LANG_DELETEONREBOOT "Delete on reboot: " +#define LANG_EXECSHELL "ExecShell: " +#define LANG_EXECUTE "Execute: " +#define LANG_CANNOTFINDSYMBOL "Could not find symbol: " +#define LANG_COULDNOTLOAD "Could not load: " +#define LANG_NOOLE "No OLE for: " +#define LANG_ERRORCREATINGSHORTCUT "Error creating shortcut: " +#define LANG_CREATESHORTCUT "Create shortcut: " +#define LANG_COPYTO "Copy to " +#define LANG_COPYFAILED "Copy failed" +#define LANG_ERRORCREATING "Error creating: " +#define LANG_CREATEDUNINST "Created uninstaller: " +#define LANG_INSTCORRUPTED "Install corrupted: invalid opcode" + + + + +#endif//_NSIS_LANG_H_ \ No newline at end of file diff --git a/Source/exehead/nsis.ico b/Source/exehead/nsis.ico new file mode 100644 index 00000000..d529d42c Binary files /dev/null and b/Source/exehead/nsis.ico differ diff --git a/Source/exehead/resource.h b/Source/exehead/resource.h new file mode 100644 index 00000000..e7b9d87a --- /dev/null +++ b/Source/exehead/resource.h @@ -0,0 +1,63 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDC_BACK 3 +#define IDD_DIALOG1 101 +#define IDI_ICON1 102 +#define IDD_DIALOG2 102 +#define IDD_LICENSE 102 +#define IDI_ICON2 103 +#define IDD_DIR 103 +#define IDD_SELCOM 104 +#define IDD_INST 105 +#define IDD_INSTFILES 106 +#define IDD_UNINST 107 +#define IDB_BITMAP1 109 +#define IDB_BITMAP2 110 +#define IDI_ICON3 110 +#define IDD_VERIFY 111 +#define IDB_BITMAP3 111 +#define IDC_EDIT1 1000 +#define IDC_BROWSE 1001 +#define IDC_COPYRIGHT 1003 +#define IDC_PROGRESS1 1004 +#define IDC_PROGRESS2 1005 +#define IDC_INTROTEXT 1006 +#define IDC_WMA 1007 +#define IDC_CHECK1 1008 +#define IDC_MJF 1008 +#define IDC_VERSION 1009 +#define IDC_DIRCAPTION 1011 +#define IDC_STATUSTEXT 1014 +#define IDC_LICTEXT 1015 +#define IDC_LIST1 1016 +#define IDC_COMBO1 1017 +#define IDC_CHILDRECT 1018 +#define IDC_DIR 1019 +#define IDC_SELDIRTEXT 1020 +#define IDC_TEXT1 1021 +#define IDC_TEXT2 1022 +#define IDC_SPACEREQUIRED 1023 +#define IDC_SPACEAVAILABLE 1024 +#define IDC_INSTVER 1024 +#define IDC_UNINSTTEXT 1025 +#define IDC_PROGRESSTEXT 1026 +#define IDC_SHOWDETAILS 1027 +#define IDC_VERSTR 1028 +#define IDC_UNINSTFROM 1029 +#define IDC_STR 1030 +#define IDC_ULICON 1031 +#define IDC_TREE1 1032 +#define IDC_BRANDIMAGE 1033 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1034 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/exehead/resource.rc b/Source/exehead/resource.rc new file mode 100644 index 00000000..01d5ec77 --- /dev/null +++ b/Source/exehead/resource.rc @@ -0,0 +1,247 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "config.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE) +#if defined(APSTUDIO_INVOKED) +IDD_LICENSE$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_LICENSE DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + ICON IDI_ICON2,IDC_ULICON,0,0,20,20 + LTEXT "",IDC_INTROTEXT,25,0,241,23 + CONTROL "",IDC_EDIT1,"RICHEDIT",ES_MULTILINE | ES_READONLY | + WS_VSCROLL | WS_BORDER,0,24,266,105 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#if defined(APSTUDIO_INVOKED) +IDD_DIR$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_DIR DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_DIR,11,49,188,12,ES_AUTOHSCROLL + PUSHBUTTON "",IDC_BROWSE,203,48,50,14 + ICON IDI_ICON2,IDC_ULICON,0,0,20,20 + CONTROL "",IDC_SELDIRTEXT,"Static",SS_LEFTNOWORDWRAP | WS_GROUP, + 0,36,265,8 + CONTROL "",IDC_SPACEAVAILABLE,"Static",SS_LEFTNOWORDWRAP | + WS_GROUP,0,122,265,8 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | + WS_TABSTOP,12,65,118,10 + CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP | + WS_GROUP,0,111,265,8 + LTEXT "",IDC_INTROTEXT,25,0,241,34 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE) +#if defined(APSTUDIO_INVOKED) +IDD_SELCOM$(NSIS_CONFIG_COMPONENTPAGE) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_SELCOM DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_COMBO1,114,25,152,102,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + ICON IDI_ICON2,IDC_ULICON,0,0,20,20 + LTEXT "",IDC_TEXT2,0,40,108,21 + CONTROL "",IDC_TEXT1,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,0,27, + 108,8 + CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP | + WS_GROUP,0,111,111,8 + LTEXT "",IDC_INTROTEXT,25,0,241,25 + CONTROL "Tree1",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | + WS_BORDER | WS_TABSTOP,114,39,151,90 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#if defined(APSTUDIO_INVOKED) +IDD_INST$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 280, 162 +#else +IDD_INST DIALOG DISCARDABLE 0, 0, 280, 162 +#endif +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "",IDOK,223,142,50,14 + PUSHBUTTON "",IDCANCEL,7,142,50,14 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,138,267,1 + CONTROL "",IDC_CHILDRECT,"Static",SS_BLACKRECT | NOT WS_VISIBLE, + 7,6,266,130 + PUSHBUTTON "",IDC_BACK,171,142,50,14,NOT WS_VISIBLE + CTEXT "",IDC_VERSTR,59,145,108,8,WS_DISABLED +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#if defined(APSTUDIO_INVOKED) +IDD_INSTFILES$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_INSTFILES DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE | + WS_BORDER,24,10,241,11 + CONTROL "",IDC_PROGRESS2,"msctls_progress32",PBS_SMOOTH | NOT + WS_VISIBLE | WS_BORDER,24,10,241,11 + CONTROL "",IDC_INTROTEXT,"Static",SS_LEFTNOWORDWRAP | WS_GROUP, + 24,0,241,8 + CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL | + LVS_NOCOLUMNHEADER | NOT WS_VISIBLE | WS_BORDER | + WS_TABSTOP, 0,25,265,104 + ICON IDI_ICON2,IDC_ULICON,0,0,20,20 + PUSHBUTTON "",IDC_SHOWDETAILS,0,28,50,14,NOT WS_TABSTOP +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_UNINSTDLG) +#if defined(APSTUDIO_INVOKED) +IDD_UNINST$(_NSIS_CONFIG_UNINSTDLG) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_UNINST DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_CONTROL | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + ICON IDI_ICON2,IDC_ULICON,0,1,20,20 + LTEXT "",IDC_UNINSTFROM,0,45,55,8 + EDITTEXT IDC_EDIT1,56,43,209,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "",IDC_INTROTEXT,25,0,241,34 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_VERIFYDIALOG) +#if defined(APSTUDIO_INVOKED) +IDD_VERIFY$(_NSIS_CONFIG_VERIFYDIALOG) DIALOG DISCARDABLE 0, 0, 162, 22 +#else +IDD_VERIFY DIALOG DISCARDABLE 0, 0, 162, 22 +#endif +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "",IDC_STR,7,7,148,8 +END +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "IDD_INST$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 273 + TOPMARGIN, 6 + BOTTOMMARGIN, 156 + END + + "IDD_INSTFILES$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG + BEGIN + RIGHTMARGIN, 246 + BOTTOMMARGIN, 125 + END + + "IDD_VERIFY$(_NSIS_CONFIG_VERIFYDIALOG)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 155 + TOPMARGIN, 7 + BOTTOMMARGIN, 15 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""config.h""\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON2 ICON DISCARDABLE "nsis.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE) +#if defined(APSTUDIO_INVOKED) +IDB_BITMAP1$(NSIS_CONFIG_COMPONENTPAGE) BITMAP DISCARDABLE "bitmap1.bmp" +#else +IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" +#endif +#endif +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + diff --git a/Source/exehead/state.h b/Source/exehead/state.h new file mode 100644 index 00000000..b5de6e5b --- /dev/null +++ b/Source/exehead/state.h @@ -0,0 +1,11 @@ +extern char g_usrvars[24][NSIS_MAX_STRLEN]; +#define state_command_line (g_usrvars[20]) +#define state_install_directory (g_usrvars[21]) +#define state_output_directory (g_usrvars[22]) +#define state_exe_directory (g_usrvars[23]) + +extern char g_caption[NSIS_MAX_STRLEN*2]; +extern HWND g_hwnd; +extern int g_filehdrsize; +extern HANDLE g_hInstance; +extern HWND insthwnd,insthwndbutton; diff --git a/Source/exehead/ui.h b/Source/exehead/ui.h new file mode 100644 index 00000000..3c07c0c6 --- /dev/null +++ b/Source/exehead/ui.h @@ -0,0 +1,21 @@ +#ifndef _UI_H_ +#define _UI_H_ + +int ui_doinstall(void); +void update_status_text(const char *text1, const char *text2); +extern int ui_st_updateflag; + +extern char g_autoclose; +extern void *g_inst_combinedheader; +extern section *g_inst_section; +extern entry *g_inst_entry; + +#define g_inst_header ((header *)g_inst_combinedheader) +#define g_inst_cmnheader ((common_header *)g_inst_combinedheader) + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +#define g_inst_uninstheader ((uninstall_header *)g_inst_combinedheader) +extern int g_is_uninstaller; +#endif + +#endif//_UI_H_ diff --git a/Source/exehead/uninst.ico b/Source/exehead/uninst.ico new file mode 100644 index 00000000..90d7d225 Binary files /dev/null and b/Source/exehead/uninst.ico differ diff --git a/Source/exehead/util.c b/Source/exehead/util.c new file mode 100644 index 00000000..b513338d --- /dev/null +++ b/Source/exehead/util.c @@ -0,0 +1,548 @@ +#include +#include +#include "util.h" +#include "state.h" +#include "config.h" + +#include "fileform.h" +#include "ui.h" + +#ifdef NSIS_CONFIG_LOG +char g_log_file[1024]; +#endif + +char g_usrvars[24][NSIS_MAX_STRLEN]; + +HANDLE g_hInstance; + +HANDLE myCreateProcess(char *cmd, char *dir) +{ + PROCESS_INFORMATION ProcInfo={0,}; + STARTUPINFO StartUp={0,}; + StartUp.cb=sizeof(StartUp); + if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, dir, &StartUp, &ProcInfo)) + return NULL; + if (NULL != ProcInfo.hThread) CloseHandle( ProcInfo.hThread ); + return ProcInfo.hProcess; +} + + +void addtrailingslash(char *str) +{ + if (lastchar(str)!='\\') lstrcat(str,"\\"); +} + +char lastchar(const char *str) +{ + return *CharPrev(str,str+lstrlen(str)); +} + +void trimslashtoend(char *buf) +{ + char *p=scanendslash(buf); + if (pmisc_flags&8); + if (s[0] == '\\' && s[1] == '\\') // \\ path + { + if (lastchar(s)!='\\') ivp++; + while (*s) + { + if (*s == '\\') ivp++; + if (*s) s++; + } + ivp/=5-req; + } + else + { + if (*s) + { + if (*s) s++; + if (*s == ':') + { + if (*s) s++; + if (*s == '\\') + { + if (*s) s++; + if (req || (*s && *s != '\\')) ivp++; + } + } + } + } + return ivp; +} + +static char *findinmem(char *a, char *b, int len_of_a) +{ + if (len_of_a<0) len_of_a=lstrlen(a); + len_of_a -= lstrlen(b); + while (*a && len_of_a >= 0) + { + char *t=a,*u=b; + while (*t && *t == *u) + { + t++; + u++; + } + if (!*u) return a; + a++; + len_of_a--; + } + return NULL; +} + + +void *mini_memcpy(void *out, const void *in, int len) +{ + char *c_out=(char*)out; + char *c_in=(char *)in; + while (len-- > 0) + { + *c_out++=*c_in++; + } + return out; +} + + +HANDLE myOpenFile(const char *fn, DWORD da, DWORD cd) +{ + return CreateFile(fn,da,FILE_SHARE_READ,NULL,cd,0,NULL); +} + +#ifdef NSIS_SUPPORT_MOVEONREBOOT +BOOL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) +{ + BOOL fOk = 0; + HMODULE hLib=LoadLibrary("kernel32.dll"); + if (hLib) + { + typedef BOOL (WINAPI *mfea_t)(LPCSTR lpExistingFileName,LPCSTR lpNewFileName,DWORD dwFlags); + mfea_t mfea; + mfea=(mfea_t) GetProcAddress(hLib,"MoveFileExA"); + if (mfea) + { + fOk=mfea(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING); + } + FreeLibrary(hLib); + } + + if (!fOk) + { + static char szRenameLine[1024]; + static char wininit[1024]; + static char tmpbuf[1024]; + int cchRenameLine; + char *szRenameSec = "[Rename]\r\n"; + HANDLE hfile, hfilemap; + DWORD dwFileSize, dwRenameLinePos; + static const char nulint[4]="NUL"; + + if (pszNew) GetShortPathName(pszNew,tmpbuf,1024); + else *((int *)tmpbuf) = *((int *)nulint); + // wininit is used as a temporary here + GetShortPathName(pszExisting,wininit,1024); + cchRenameLine = wsprintf(szRenameLine,"%s=%s\r\n",tmpbuf,wininit); + + GetWindowsDirectory(wininit, 1024-16); + lstrcat(wininit, "\\wininit.ini"); + hfile = CreateFile(wininit, + GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + + if (hfile != INVALID_HANDLE_VALUE) + { + dwFileSize = GetFileSize(hfile, NULL); + hfilemap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0, dwFileSize + cchRenameLine + 10, NULL); + + if (hfilemap != NULL) + { + LPSTR pszWinInit = (LPSTR) MapViewOfFile(hfilemap, FILE_MAP_WRITE, 0, 0, 0); + + if (pszWinInit != NULL) + { + int do_write=0; + LPSTR pszRenameSecInFile = findinmem(pszWinInit, szRenameSec,-1); + if (pszRenameSecInFile == NULL) + { + lstrcpy(pszWinInit+dwFileSize, szRenameSec); + dwFileSize += 10; + dwRenameLinePos = dwFileSize; + do_write++; + } + else + { + char *pszFirstRenameLine = findinmem(pszRenameSecInFile, "\n",-1)+1; + int l=pszWinInit + dwFileSize-pszFirstRenameLine; + if (!findinmem(pszFirstRenameLine,szRenameLine,l)) + { + void* data=(void*)GlobalAlloc(GMEM_FIXED,l); + mini_memcpy(data, pszFirstRenameLine, l); + mini_memcpy(pszFirstRenameLine + cchRenameLine, data, l); + GlobalFree((HGLOBAL)data); + + dwRenameLinePos = pszFirstRenameLine - pszWinInit; + do_write++; + } + } + + if (do_write) + { + mini_memcpy(&pszWinInit[dwRenameLinePos], szRenameLine,cchRenameLine); + dwFileSize += cchRenameLine; + } + + UnmapViewOfFile(pszWinInit); + + fOk++; + } + CloseHandle(hfilemap); + } + SetFilePointer(hfile, dwFileSize, NULL, FILE_BEGIN); + SetEndOfFile(hfile); + CloseHandle(hfile); + } + } + return fOk; +} +#endif + +void recursive_create_directory(char *directory) +{ + char *tp; + char *p; + p=directory; + while (*p == ' ') if (*p) p++; + if (!*p) return; + tp=*p?p+1:p; + if (*tp == ':' && tp[1] == '\\') p=tp+2; + else if (p[0] == '\\' && p[1] == '\\') + { + int x; + for (x = 0; x < 2; x ++) + { + while (*p != '\\' && *p) if (*p) p++; // skip host then share + if (*p) if (*p) p++; + } + + } + else return; + while (*p) + { + while (*p != '\\' && *p) if (*p) p++; + if (!*p) CreateDirectory(directory,NULL); + else + { + *p=0; + CreateDirectory(directory,NULL); + *p++ = '\\'; + } + } +} + + +void myRegGetStr(HKEY root, const char *sub, const char *name, char *out) +{ + HKEY hKey; + *out=0; + if (RegOpenKeyEx(root,sub,0,KEY_READ,&hKey) == ERROR_SUCCESS) + { + DWORD l = NSIS_MAX_STRLEN; + DWORD t; + if (RegQueryValueEx(hKey,name,NULL,&t,out,&l ) != ERROR_SUCCESS || t != REG_SZ) *out=0; + out[NSIS_MAX_STRLEN-1]=0; + RegCloseKey(hKey); + } +} + + +char g_all_user_var_flag; + +static void queryShellFolders(const char *name, char *out) +{ + char f=g_all_user_var_flag; +again: + + myRegGetStr(g_all_user_var_flag?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + name+(f?0:7),out); + if (!out[0]) + { + if (f) + { + f=0; goto again; + } + GetTempPath(NSIS_MAX_STRLEN,out); + } +} + +char ps_tmpbuf[NSIS_MAX_STRLEN*2]; + + +void process_string_fromtab(char *out, int offs) +{ + process_string(ps_tmpbuf,GetStringFromStringTab(offs)); + lstrcpyn(out,ps_tmpbuf,NSIS_MAX_STRLEN); +} + +void myitoa(char *s, int d) { wsprintf(s,"%d",d); } +int myatoi(char *s) +{ + unsigned int v=0; + if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) + { + s+=2; + for (;;) + { + int c=*s++; + if (c >= '0' && c <= '9') c-='0'; + else if (c >= 'a' && c <= 'f') c-='a'-10; + else if (c >= 'A' && c <= 'F') c-='A'-10; + else break; + v<<=4; + v+=c; + } + } + else if (*s == '0' && s[1] <= '7' && s[1] >= '0') + { + s++; + for (;;) + { + int c=*s++; + if (c >= '0' && c <= '7') c-='0'; + else break; + v<<=3; + v+=c; + } + } + else + { + int sign=0; + if (*s == '-') { s++; sign++; } + for (;;) + { + int c=*s++ - '0'; + if (c < 0 || c > 9) break; + v*=10; + v+=c; + } + if (sign) return -(int) v; + } + return (int)v; +} + + +int process_string_fromtab_toint(int offs) +{ + process_string(ps_tmpbuf,GetStringFromStringTab(offs)); + return myatoi(ps_tmpbuf); +} + +// Dave Laundon's simplified process_string +void process_string(char *out, const char *in) +{ + char *outsave = out; + while (*in && out - outsave < NSIS_MAX_STRLEN) + { + int nVarIdx = (unsigned char)*in++; + if (nVarIdx < VAR_CODES_START) + { + *out++ = nVarIdx; + } + else if (nVarIdx == 255) + { + *out++ = *in++; + } + else + { + DWORD f; + switch (nVarIdx) // The order of this list must match that in ..\strlist.cpp (err, build.cpp -J) + { + case VAR_CODES_START + 0: // HWNDPARENT + wsprintf(out, "%u", (unsigned int)g_hwnd); + break; + case VAR_CODES_START + 1: // 0 + case VAR_CODES_START + 2: // 1 + case VAR_CODES_START + 3: // 2 + case VAR_CODES_START + 4: // 3 + case VAR_CODES_START + 5: // 4 + case VAR_CODES_START + 6: // 5 + case VAR_CODES_START + 7: // 6 + case VAR_CODES_START + 8: // 7 + case VAR_CODES_START + 9: // 8 + case VAR_CODES_START + 10: // 9 + case VAR_CODES_START + 11: // R0 + case VAR_CODES_START + 12: // R1 + case VAR_CODES_START + 13: // R2 + case VAR_CODES_START + 14: // R3 + case VAR_CODES_START + 15: // R4 + case VAR_CODES_START + 16: // R5 + case VAR_CODES_START + 17: // R6 + case VAR_CODES_START + 18: // R7 + case VAR_CODES_START + 19: // R8 + case VAR_CODES_START + 20: // R9 + case VAR_CODES_START + 21: // CMDLINE + case VAR_CODES_START + 22: // INSTDIR + case VAR_CODES_START + 23: // OUTDIR + case VAR_CODES_START + 24: // EXEDIR + lstrcpy(out, g_usrvars[nVarIdx - (VAR_CODES_START + 1)]); + break; + + case VAR_CODES_START + 25: // PROGRAMFILES + myRegGetStr(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProgramFilesDir", out); + if (!*out) + lstrcpy(out, "C:\\Program Files"); + break; + + case VAR_CODES_START + 26: // SMPROGRAMS + case VAR_CODES_START + 27: // SMSTARTUP + case VAR_CODES_START + 28: // DESKTOP + case VAR_CODES_START + 29: // STARTMENU + { + static const char *tab[]={ + "Common Programs", + "Common Startup", + "Common Desktop", + "Common Start Menu" + }; + queryShellFolders(tab[nVarIdx-(VAR_CODES_START+26)], out); + } + break; + + case VAR_CODES_START + 30: // QUICKLAUNCH + queryShellFolders("Common AppData", out); + lstrcat(out, "\\Microsoft\\Internet Explorer\\Quick Launch"); + f = GetFileAttributes(out); + if (f != (DWORD)-1 && (f & FILE_ATTRIBUTE_DIRECTORY)) + break; + case VAR_CODES_START + 31: // TEMP + GetTempPath(NSIS_MAX_STRLEN, out); + break; + + case VAR_CODES_START + 32: // WINDIR + GetWindowsDirectory(out, NSIS_MAX_STRLEN); + break; + + case VAR_CODES_START + 33: // SYSDIR + GetSystemDirectory(out, NSIS_MAX_STRLEN); + break; + + #if VAR_CODES_START + 33 >= 255 + #error "Too many variables! Extend VAR_CODES_START!" + #endif + } // switch + // remove trailing slash + while (*out && *(out+1)) out++; + if (nVarIdx > 21+VAR_CODES_START && *out == '\\') // only if not $0 to $R9, $CMDLINE, or $HWNDPARENT + *out = 0; + if (*out) out++; + } // >= VAR_CODES_START + } // while + *out = 0; +} +#ifdef NSIS_CONFIG_LOG + +char log_text[4096]; +int log_dolog; +void log_write(int close) +{ + extern char g_log_file[1024]; + static HANDLE fp=INVALID_HANDLE_VALUE; + if (close) + { + if (fp!=INVALID_HANDLE_VALUE) + { + CloseHandle(fp); + } + fp=INVALID_HANDLE_VALUE; + return; + } + if (log_dolog) + { + if (g_log_file[0] && fp==INVALID_HANDLE_VALUE) + { + fp = CreateFile(g_log_file,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,0,NULL); + if (fp!=INVALID_HANDLE_VALUE) + SetFilePointer(fp,0,NULL,FILE_END); + } + if (fp!=INVALID_HANDLE_VALUE) + { + DWORD d; + lstrcat(log_text,"\r\n"); + WriteFile(fp,log_text,lstrlen(log_text),&d,NULL); + } + } +} + + +#endif + +#ifdef NSIS_SUPPORT_CREATESHORTCUT +int CreateShortCut(HWND hwnd, LPCSTR pszShortcutFile, LPCSTR pszIconFile, int iconindex, LPCSTR pszExe, LPCSTR pszArg, LPCSTR workingdir, int showmode, int hotkey) +{ + HRESULT hres; + int rv=1; + IShellLink* psl; + hres=OleInitialize(NULL); + if (hres != S_FALSE && hres != S_OK) return rv; + + hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLink, (void **) &psl); + if (SUCCEEDED(hres)) + { + IPersistFile* ppf; + + hres = psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile, (void **) &ppf); + if (SUCCEEDED(hres)) + { + + hres = psl->lpVtbl->SetPath(psl,pszExe); + psl->lpVtbl->SetWorkingDirectory(psl,workingdir); + if (showmode) psl->lpVtbl->SetShowCmd(psl,showmode); + if (hotkey) psl->lpVtbl->SetHotkey(psl,(unsigned short)hotkey); + if (pszIconFile) psl->lpVtbl->SetIconLocation(psl,pszIconFile,iconindex); + if (pszArg) + { + psl->lpVtbl->SetArguments(psl,pszArg); + } + + if (SUCCEEDED(hres)) + { + WCHAR wsz[1024]; + MultiByteToWideChar(CP_ACP, 0, pszShortcutFile, -1, wsz, 1024); + hres=ppf->lpVtbl->Save(ppf,(const WCHAR*)wsz,TRUE); + if (SUCCEEDED(hres)) rv=0; + } + ppf->lpVtbl->Release(ppf); + } + psl->lpVtbl->Release(psl); + } + OleUninitialize(); + return rv; +} +#endif//NSIS_SUPPORT_CREATESHORTCUT \ No newline at end of file diff --git a/Source/exehead/util.h b/Source/exehead/util.h new file mode 100644 index 00000000..8e635610 --- /dev/null +++ b/Source/exehead/util.h @@ -0,0 +1,47 @@ +#include "config.h" + +void recursive_create_directory(char *directory); + +extern char ps_tmpbuf[NSIS_MAX_STRLEN*2]; +void process_string(char *out, const char *in); +void process_string_fromtab(char *out, int offs); +int process_string_fromtab_toint(int offs); +void myRegGetStr(HKEY root, const char *sub, const char *name, char *out); +int myatoi(char *s); +void myitoa(char *s, int d); + + +#ifdef NSIS_CONFIG_LOG +extern char log_text[NSIS_MAX_STRLEN*4]; +void log_write(int close); +#define log_printf(x1) wsprintf(log_text,x1); log_write(0) +#define log_printf2(x1,x2) wsprintf(log_text,x1,x2); log_write(0) +#define log_printf3(x1,x2,x3) wsprintf(log_text,x1,x2,x3); log_write(0) +#define log_printf4(x1,x2,x3,x4) wsprintf(log_text,x1,x2,x3,x4); log_write(0) +#define log_printf5(x1,x2,x3,x4,x5) wsprintf(log_text,x1,x2,x3,x4,x5); log_write(0) +#define log_printf6(x1,x2,x3,x4,x5,x6) wsprintf(log_text,x1,x2,x3,x4,x5,x6); log_write(0) +#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8) wsprintf(log_text,x1,x2,x3,x4,x5,x6,x7,x8); log_write(0) +extern int log_dolog; +extern char g_log_file[1024]; +#else +#define log_printf(x1) +#define log_printf2(x1,x2) +#define log_printf3(x1,x2,x3) +#define log_printf4(x1,x2,x3,x4) +#define log_printf5(x1,x2,x3,x4,x5) +#define log_printf6(x1,x2,x3,x4,x5,x6) +#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8) +#endif + +HANDLE myCreateProcess(char *cmd, char *dir); + +HANDLE myOpenFile(const char *fn, DWORD da, DWORD cd); +int CreateShortCut(HWND hwnd, LPCSTR pszShortcutFile, LPCSTR pszIconFile, int iconindex, LPCSTR pszExe, LPCSTR pszArg, LPCSTR workingdir, int showmode, int hotkey); +int validpathspec(char *ubuf); +void addtrailingslash(char *str); +char lastchar(const char *str); +void trimslashtoend(char *buf); +char *scanendslash(const char *str); +int is_valid_instpath(char *s); +BOOL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew); +void *mini_memcpy(void *out, const void *in, int len); diff --git a/Source/icon.ico b/Source/icon.ico new file mode 100644 index 00000000..b1f13afd Binary files /dev/null and b/Source/icon.ico differ diff --git a/Source/lineparse.h b/Source/lineparse.h new file mode 100644 index 00000000..fd811e7d --- /dev/null +++ b/Source/lineparse.h @@ -0,0 +1,150 @@ +#ifndef _LINEPARSE_H_ +#define _LINEPARSE_H_ + +class LineParser { + public: + + LineParser() + { + m_nt=m_eat=0; + m_tokens=0; + } + + ~LineParser() + { + freetokens(); + } + + int parse(char *line) // returns -1 on error + { + freetokens(); + int n=doline(line); + if (n) return n; + if (m_nt) + { + m_tokens=(char**)malloc(sizeof(char*)*m_nt); + n=doline(line); + if (n) + { + freetokens(); + return -1; + } + } + return 0; + } + + int getnumtokens() { return m_nt-m_eat; } + + void eattoken() { m_eat++; } + + double gettoken_float(int token, int *success=0) + { + token+=m_eat; + if (token < 0 || token >= m_nt) + { + if (success) *success=0; + return 0.0; + } + if (success) + { + char *t=m_tokens[token]; + *success=*t?1:0; + while (*t) + { + if ((*t < '0' || *t > '9')&&*t != '.') *success=0; + t++; + } + } + return atof(m_tokens[token]); + } + int gettoken_int(int token, int *success=0) + { + token+=m_eat; + if (token < 0 || token >= m_nt || !m_tokens[token][0]) + { + if (success) *success=0; + return 0; + } + char *tmp; + int l; + if (m_tokens[token][0] == '-') l=strtol(m_tokens[token],&tmp,0); + else l=(int)strtoul(m_tokens[token],&tmp,0); + if (success) *success=! (int)(*tmp); + return l; + } + char *gettoken_str(int token) + { + token+=m_eat; + if (token < 0 || token >= m_nt) return ""; + return m_tokens[token]; + } + int gettoken_enum(int token, const char *strlist) // null seperated list + { + int x=0; + char *tt=gettoken_str(token); + if (tt && *tt) while (*strlist) + { + if (!stricmp(tt,strlist)) return x; + strlist+=strlen(strlist)+1; + x++; + } + return -1; + } + private: + void freetokens() + { + if (m_tokens) + { + int x; + for (x = 0; x < m_nt; x ++) + free(m_tokens[x]); + free(m_tokens); + } + m_tokens=0; + m_nt=0; + } + + int doline(char *line) + { + m_nt=0; + while (*line == ' ' || *line == '\t') line++; + while (*line) + { + int lstate=0; // 1=", 2=`, 4=' + if (*line == ';' || *line == '#') break; + if (*line == '\"') lstate=1; + else if (*line == '\'') lstate=2; + else if (*line == '`') lstate=4; + if (lstate) line++; + int nc=0; + while (*line) + { + if (lstate==1 && *line =='\"') break; + if (lstate==2 && *line =='\'') break; + if (lstate==4 && *line =='`') break; + if (!lstate && (*line == ' ' || *line == '\t')) break; + line++; + nc++; + } + if (m_tokens) + { + m_tokens[m_nt]=(char*)malloc(nc+1); + strncpy(m_tokens[m_nt],line-nc,nc); + m_tokens[m_nt][nc]=0; + } + m_nt++; + if (lstate) + { + if (*line) line++; + else return -2; + } + while (*line == ' ' || *line == '\t') line++; + } + return 0; + } + + int m_eat; + int m_nt; + char **m_tokens; +}; +#endif//_LINEPARSE_H_ \ No newline at end of file diff --git a/Source/makenssi.cpp b/Source/makenssi.cpp new file mode 100644 index 00000000..4f9404c4 --- /dev/null +++ b/Source/makenssi.cpp @@ -0,0 +1,379 @@ +const char *NSIS_VERSION="v2.0a2"; + +/* + Nullsoft "SuperPimp" Installation System - makensis.cpp - installer compiler code + May 21st, 2002 + + Copyright (C) 1999-2002 Nullsoft, Inc. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + This source distribution includes portions of zlib. see zlib/zlib.h for + its license and so forth. Note that this license is also borrowed from zlib. +*/ + +#include +#include +#include + +#include "build.h" +#include "util.h" +#include "exedata.h" + + +int g_noconfig; +int g_display_errors=1; +FILE *g_output=stdout; + +void quit() +{ + if (g_display_errors) + { + fprintf(g_output,"\nNote: you may have one or two (large) stale temporary file(s)\n" + "left in your temporary directory (Generally this only happens on Windows 9x).\n"); + fflush(g_output); + } + exit(1); +} + +static void myatexit() +{ + dopause(); + if (g_output != stdout && g_output) fclose(g_output); +} + +static void sigint(int sig) +{ + if (g_display_errors) + { + fprintf(g_output,"\n\nAborting on Ctrl+C...\n"); + fflush(g_output); + } + quit(); +} + +int main(int argc, char **argv) +{ + CEXEBuild build; + int do_cd=0; + int outputtried=0; + int argpos=1; + int nousage=0; + int files_processed=0; + int cmds_processed=0; + FILE *fp; + int tmpargpos=1; + int no_logo=0; + + if (argc > 1 && argv[1][0]=='/' && (argv[1][1]=='v' || argv[1][1]=='V')) + { + tmpargpos++; + if (argv[1][2] <= '2' && argv[1][2] >= '0') + { + no_logo=1; + } + } + + if (!no_logo) + { + if (argc > tmpargpos && argv[tmpargpos][0]=='/' && (argv[tmpargpos][1]=='o' || argv[tmpargpos][1]=='O') && argv[tmpargpos][2]) + { + g_output=fopen(argv[tmpargpos]+2,"w"); + if (!g_output) + { + printf("Error opening output log for writing. Using stdout.\n"); + g_output=stdout; + } + outputtried=1; + } + fprintf(g_output,"MakeNSIS %s - Copyright 1999-2002 Nullsoft, Inc.\n" + "\n" + "Portions Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler (zlib).\n" + "Includes portions derived from bzip2 (see documentation for details).\n" + "Contributors: nnop@newmail.ru, Ryan Geiss, Andras Varga, Drew Davidson, Peter Windridge, Dave Laundon, Robert Rainwater, Yaroslav Faybishenko, Jeff Doozan, et al.\n\n",NSIS_VERSION); + fflush(g_output); + } + + atexit(myatexit); + + signal(SIGINT,sigint); + + if (!g_output) g_output=stdout; + while (argpos < argc) + { + if (argv[argpos][0]=='/' && (argv[argpos][1]=='D' || argv[argpos][1]=='d') && argv[argpos][2]) + { + char *p=argv[argpos]+2; + if (p[0]) + { + char *s=strdup(p),*v; + if (build.display_script) + { + fprintf(g_output,"Command line defined: \"%s\"\n",p); + fflush(g_output); + } + v=strstr(s,"="); + if (v) *v++=0; + build.define(s,v?v:""); + free(s); + } + else + { + build.warning("command line /D requires argument (i.e. \"/Ddefine\"). ignored."); + } + } + else if (argv[argpos][0]=='/' && (argv[argpos][1]=='X' || argv[argpos][1]=='x') && argv[argpos][2]) + { + if (build.process_oneline(argv[argpos]+2,"command line",argpos+1) != PS_OK) + { + return 1; + } + cmds_processed++; + } + else if (argv[argpos][0]=='/' && (argv[argpos][1]=='O' || argv[argpos][1]=='o') && argv[argpos][2]) + { + if (!outputtried) + { + g_output=fopen(argv[argpos]+2,"w"); + if (!g_output) + { + if (build.display_errors) printf("Error opening output log for writing. Using stdout.\n"); + g_output=stdout; + } + outputtried=1; + } + } + else if (!stricmp(argv[argpos],"/CD")) do_cd=1; + else if (argv[argpos][0] == '/' && (argv[argpos][1] == 'V' || argv[argpos][1] == 'v') && + argv[argpos][2] >= '0' && argv[argpos][2] <= '4' && !argv[argpos][3]) + { + int v=argv[argpos][2]-'0'; + build.display_script=v>3; + build.display_info=v>2; + build.display_warnings=v>1; + build.display_errors=v>0; + g_display_errors=build.display_errors; + } + else if (!stricmp(argv[argpos],"/NOCONFIG")) g_noconfig=1; + else if (!stricmp(argv[argpos],"/PAUSE")) g_dopause=1; + else if (!stricmp(argv[argpos],"/LICENSE")) + { + if (build.display_info) + { + fprintf(g_output,"This software is provided 'as-is', without any express or implied warranty. In\n" + "no event will the authors be held liable for any damages arising from the use\n" + "of this software.\n\n" + "Permission is granted to anyone to use this software for any purpose, including\n" + "commercial applications, and to alter it and redistribute it freely, subject to\n" + "the following restrictions:\n" + " 1. The origin of this software must not be misrepresented; you must not claim\n" + " that you wrote the original software. If you use this software in a\n" + " product, an acknowledgment in the product documentation would be\n" + " appreciated but is not required.\n" + " 2. Altered source versions must be plainly marked as such, and must not be\n" + " misrepresented as being the original software.\n" + " 3. This notice may not be removed or altered from any source distribution.\n\n"); + fflush(g_output); + } + nousage++; + } + else if (!stricmp(argv[argpos],"/CMDHELP")) + { + if (argpos < argc-1) + build.print_help(argv[++argpos]); + else + build.print_help(NULL); + nousage++; + } + else if (!stricmp(argv[argpos],"/HDRINFO")) + { + if (build.display_info) + { + fprintf(g_output,"EXE header size of %d bytes, info header size of %d bytes.\n", exeheader_size,sizeof(firstheader)); + fprintf(g_output,"Install header size of %d bytes, uninstall header size of %d bytes.\n",sizeof(header),sizeof(uninstall_header)); + fprintf(g_output,"Section size of %d bytes, instruction size of %d bytes.\n",sizeof(section),sizeof(entry)); + char *p=build.definedlist.defines.get(); + char *p2=build.definedlist.values.get(); + int x=0; + fprintf(g_output,"\nDefined symbols: "); + while (x < build.definedlist.defines.getlen()) + { + if (x) fprintf(g_output,",");; + fprintf(g_output,"%s",p+x); + if (*p2) fprintf(g_output,"=%s",p2); + + x+=strlen(p+x)+1; + p2+=strlen(p2)+1; + } + if (!x) fprintf(g_output,"none"); + fprintf(g_output,"\n"); + fflush(g_output); + } + nousage++; + } + else + { + if (argv[argpos][0]=='/') break; + files_processed++; + if (!strcmp(argv[argpos],"-")) g_dopause=0; + if (!g_noconfig) + { + g_noconfig=1; + char exepath[1024]; + strncpy(exepath,argv[0],1023); + exepath[1023]=0; + char *p=exepath; + while (*p) p++; + while (p > exepath && *p != '\\') p=CharPrev(exepath,p); + if (p>exepath) p++; + strcpy(p,"nsisconf.nsi"); + FILE *cfg=fopen(exepath,"rt"); + if (cfg) + { + if (build.display_script) + { + fprintf(g_output,"\n\nProcessing config: \n"); + fflush(g_output); + } + int lc=0; + int ret=build.process_script(cfg,exepath,&lc); + fclose(cfg); + if (ret != PS_OK && ret != PS_EOF) + { + if (build.display_errors) + { + fprintf(g_output,"Error in config on line %d -- aborting creation process\n",lc); + fflush(g_output); + } + return 1; + } + } + } + + { + char sfile[1024]; + if (!strcmp(argv[argpos],"-")) + { + fp=stdin; + strcpy(sfile,"stdin"); + } + else + { + strcpy(sfile,argv[argpos]); + fp=fopen(sfile,"rt"); + if (!fp) + { + sprintf(sfile,"%s.nsi",argv[argpos]); + fp=fopen(sfile,"rt"); + if (!fp) + { + if (build.display_errors) + { + fprintf(g_output,"Can't open script \"%s\"\n",sfile); + fflush(g_output); + } + return 1; + } + } + if (do_cd) + { + char dirbuf[1024],*p; + GetFullPathName(sfile,sizeof(dirbuf),dirbuf,&p); + p=dirbuf; + while (*p) p++; + while (p > dirbuf && *p != '\\') p=CharPrev(dirbuf,p); + *p=0; + if (dirbuf[0]) + { + if (build.display_script) + { + fprintf(g_output,"Changing directory to: \"%s\"\n",dirbuf); + fflush(g_output); + } + SetCurrentDirectory(dirbuf); + } + } + } + + + if (build.display_script) + { + fprintf(g_output,"\n\nProcessing script file: \"%s\"\n",sfile); + fflush(g_output); + } + int lc=0; + int ret=build.process_script(fp,sfile,&lc); + if (fp != stdin) fclose(fp); + + if (ret != PS_EOF && ret != PS_OK) + { + if (build.display_errors) + { + fprintf(g_output,"Error in script \"%s\" on line %d -- aborting creation process\n",sfile,lc); + fflush(g_output); + } + return 1; + } + } + } + argpos++; + } + + if (argpos\\nsisconf.nsi\n" + " /CD makes makensis change the current directory to that of the .nsi file\n" + " /Ddefine[=value] defines the symbol \"define\" for the script [to value]\n" + " /Xscriptcmd executes scriptcmd in script (i.e. \"/XOutFile poop.exe\")\n" + " for script file name, you can use - to read from the standard input\n"); + fflush(g_output); + } + return 1; + } + + if (build.display_info) + { + fprintf(g_output,"\nProcessed "); + if (files_processed) fprintf(g_output,"%d file%s, ",files_processed,files_processed==1?"":"s"); + if (cmds_processed) fprintf(g_output,"%d command line command%s, ",cmds_processed,cmds_processed==1?"":"s"); + fprintf(g_output,"writing output:\n"); + fflush(g_output); + } + + if (build.write_output()) + { + if (build.display_errors) + { + fprintf(g_output,"Error - aborting creation process\n"); + fflush(g_output); + } + return 1; + } + return 0; +} diff --git a/Source/makenssi.dsp b/Source/makenssi.dsp new file mode 100644 index 00000000..e2f7ddff --- /dev/null +++ b/Source/makenssi.dsp @@ -0,0 +1,247 @@ +# Microsoft Developer Studio Project File - Name="makenssi" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=makenssi - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "makenssi.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "makenssi.mak" CFG="makenssi - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "makenssi - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../makensis.exe" /opt:nowin98 +# Begin Target + +# Name "makenssi - Win32 Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Group "headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\zlib\Deflate.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infblock.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infcodes.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Infutil.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Zconf.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Zlib.h +# End Source File +# Begin Source File + +SOURCE=.\zlib\Zutil.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\zlib\deflate.c +# ADD CPP /G6 +# End Source File +# Begin Source File + +SOURCE=.\zlib\trees.c +# ADD CPP /G6 +# End Source File +# End Group +# Begin Group "bzip2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\bzip2\blocksort.c +# End Source File +# Begin Source File + +SOURCE=.\bzip2\bzlib.c +# End Source File +# Begin Source File + +SOURCE=.\bzip2\bzlib.h +# End Source File +# Begin Source File + +SOURCE=.\bzip2\bzlib_private.h +# End Source File +# Begin Source File + +SOURCE=.\bzip2\compress.c +# End Source File +# Begin Source File + +SOURCE=.\bzip2\huffman.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\build.cpp +# ADD CPP /G6 +# End Source File +# Begin Source File + +SOURCE=.\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\DialogTemplate.cpp +# End Source File +# Begin Source File + +SOURCE=.\exedata.cpp +# ADD CPP /G6 +# End Source File +# Begin Source File + +SOURCE=.\makenssi.cpp +# ADD CPP /G6 +# End Source File +# Begin Source File + +SOURCE=.\ResourceEditor.cpp +# End Source File +# Begin Source File + +SOURCE=.\script.cpp +# ADD CPP /Ot /Ow /Oy +# SUBTRACT CPP /Og +# End Source File +# Begin Source File + +SOURCE=.\tokens.cpp +# End Source File +# Begin Source File + +SOURCE=.\util.cpp +# ADD CPP /G6 +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\build.h +# End Source File +# Begin Source File + +SOURCE=.\cbzip2.h +# End Source File +# Begin Source File + +SOURCE=.\compressor.h +# End Source File +# Begin Source File + +SOURCE=.\czlib.h +# End Source File +# Begin Source File + +SOURCE=.\DialogTemplate.h +# End Source File +# Begin Source File + +SOURCE=.\exedata.h +# End Source File +# Begin Source File + +SOURCE=.\lineparse.h +# End Source File +# Begin Source File + +SOURCE=.\ResourceEditor.h +# End Source File +# Begin Source File + +SOURCE=.\strlist.h +# End Source File +# Begin Source File + +SOURCE=.\tokens.h +# End Source File +# Begin Source File + +SOURCE=.\util.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon.ico +# End Source File +# Begin Source File + +SOURCE=.\Script1.rc +# End Source File +# End Group +# Begin Source File + +SOURCE=..\makensis.htm +# End Source File +# Begin Source File + +SOURCE=..\makensis.nsi +# End Source File +# End Target +# End Project diff --git a/Source/makenssi.dsw b/Source/makenssi.dsw new file mode 100644 index 00000000..3d044acb --- /dev/null +++ b/Source/makenssi.dsw @@ -0,0 +1,59 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "exehead_bzip2"=".\exehead\exehead-bzip2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "exehead_zlib"=".\exehead\exehead-zlib.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "makenssi"=".\makenssi.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name exehead_bzip2 + End Project Dependency + Begin Project Dependency + Project_Dep_Name exehead_zlib + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Source/makenssi.ncb b/Source/makenssi.ncb new file mode 100644 index 00000000..954d0534 --- /dev/null +++ b/Source/makenssi.ncb @@ -0,0 +1 @@ +Microsoft C/C++ program database 2.00 diff --git a/Source/makenssi.opt b/Source/makenssi.opt new file mode 100644 index 00000000..121a7382 Binary files /dev/null and b/Source/makenssi.opt differ diff --git a/Source/makenssi.plg b/Source/makenssi.plg new file mode 100644 index 00000000..813f4f4a --- /dev/null +++ b/Source/makenssi.plg @@ -0,0 +1,260 @@ + + +
+

Build Log

+

+--------------------Configuration: exehead_bzip2 - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release-bzip2/resource.res" /d "NDEBUG" "C:\Program Files\NSIS\Source\exehead\resource.rc"" +Creating temporary file "F:\Temp\WinTemp\RSP2E5.tmp" with contents +[ +/nologo /ML /W3 /GX /O1 /Oy /D "_WINDOWS" /D "EXEHEAD" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /D "NSIS_COMPRESS_USE_BZIP2" /Fo"Release-bzip2/" /Fd"Release-bzip2/" /FD /c +"C:\Program Files\NSIS\Source\zlib\INFBLOCK.C" +"C:\Program Files\NSIS\Source\zlib\INFCODES.C" +"C:\Program Files\NSIS\Source\zlib\INFLATE.C" +"C:\Program Files\NSIS\Source\zlib\INFTREES.C" +"C:\Program Files\NSIS\Source\zlib\INFUTIL.C" +"C:\Program Files\NSIS\Source\bzip2\bzlib.c" +"C:\Program Files\NSIS\Source\bzip2\decompress.c" +"C:\Program Files\NSIS\Source\bzip2\huffman.c" +"C:\Program Files\NSIS\Source\bzip2\randtable.c" +"C:\Program Files\NSIS\Source\exehead\bgbg.c" +"C:\Program Files\NSIS\Source\crc32.c" +"C:\Program Files\NSIS\Source\exehead\exec.c" +"C:\Program Files\NSIS\Source\exehead\fileform.c" +"C:\Program Files\NSIS\Source\exehead\Main.c" +"C:\Program Files\NSIS\Source\exehead\Ui.c" +"C:\Program Files\NSIS\Source\exehead\util.c" +] +Creating command line "cl.exe @F:\Temp\WinTemp\RSP2E5.tmp" +Creating temporary file "F:\Temp\WinTemp\RSP2E6.tmp" with contents +[ +comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib shell32.lib /nologo /entry:"WinMain" /subsystem:windows /pdb:none /machine:I386 /nodefaultlib /out:"Release-bzip2/exehead_bzip2.exe" /opt:nowin98 +".\Release-bzip2\INFBLOCK.OBJ" +".\Release-bzip2\INFCODES.OBJ" +".\Release-bzip2\INFLATE.OBJ" +".\Release-bzip2\INFTREES.OBJ" +".\Release-bzip2\INFUTIL.OBJ" +".\Release-bzip2\bzlib.obj" +".\Release-bzip2\decompress.obj" +".\Release-bzip2\huffman.obj" +".\Release-bzip2\randtable.obj" +".\Release-bzip2\bgbg.obj" +".\Release-bzip2\crc32.obj" +".\Release-bzip2\exec.obj" +".\Release-bzip2\fileform.obj" +".\Release-bzip2\Main.obj" +".\Release-bzip2\Ui.obj" +".\Release-bzip2\util.obj" +".\Release-bzip2\resource.res" +] +Creating command line "link.exe @F:\Temp\WinTemp\RSP2E6.tmp" +

Output Window

+Compiling resources... +Compiling... +INFBLOCK.C +INFCODES.C +INFLATE.C +INFTREES.C +INFUTIL.C +bzlib.c +decompress.c +huffman.c +randtable.c +bgbg.c +crc32.c +exec.c +fileform.c +Main.c +Ui.c +util.c +Generating Code... +Linking... +Creating temporary file "F:\Temp\WinTemp\RSP2E8.bat" with contents +[ +@echo off +bin2h Release-bzip2\exehead_bzip2.exe Release-bzip2\exehead_bzip2.h bzip2_header_data +] +Creating command line "F:\Temp\WinTemp\RSP2E8.bat" +generating include file for makenssi +Release-bzip2\exehead_bzip2.exe -> bzip2_header_data (38400 bytes) + +

+--------------------Configuration: exehead_zlib - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release-zlib/resource.res" /d "NDEBUG" "C:\Program Files\NSIS\Source\exehead\resource.rc"" +Creating temporary file "F:\Temp\WinTemp\RSP2E9.tmp" with contents +[ +/nologo /ML /W3 /GX /O1 /Oy /D "_WINDOWS" /D "EXEHEAD" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /D "NSIS_COMPRESS_USE_ZLIB" /Fo"Release-zlib/" /Fd"Release-zlib/" /FD /c +"C:\Program Files\NSIS\Source\zlib\INFBLOCK.C" +"C:\Program Files\NSIS\Source\zlib\INFCODES.C" +"C:\Program Files\NSIS\Source\zlib\INFLATE.C" +"C:\Program Files\NSIS\Source\zlib\INFTREES.C" +"C:\Program Files\NSIS\Source\zlib\INFUTIL.C" +"C:\Program Files\NSIS\Source\bzip2\bzlib.c" +"C:\Program Files\NSIS\Source\bzip2\decompress.c" +"C:\Program Files\NSIS\Source\bzip2\huffman.c" +"C:\Program Files\NSIS\Source\bzip2\randtable.c" +"C:\Program Files\NSIS\Source\exehead\bgbg.c" +"C:\Program Files\NSIS\Source\crc32.c" +"C:\Program Files\NSIS\Source\exehead\exec.c" +"C:\Program Files\NSIS\Source\exehead\fileform.c" +"C:\Program Files\NSIS\Source\exehead\Main.c" +"C:\Program Files\NSIS\Source\exehead\Ui.c" +"C:\Program Files\NSIS\Source\exehead\util.c" +] +Creating command line "cl.exe @F:\Temp\WinTemp\RSP2E9.tmp" +Creating temporary file "F:\Temp\WinTemp\RSP2EA.tmp" with contents +[ +comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib shell32.lib /nologo /entry:"WinMain" /subsystem:windows /pdb:none /machine:I386 /nodefaultlib /out:"Release-zlib/exehead_zlib.exe" /opt:nowin98 +".\Release-zlib\INFBLOCK.OBJ" +".\Release-zlib\INFCODES.OBJ" +".\Release-zlib\INFLATE.OBJ" +".\Release-zlib\INFTREES.OBJ" +".\Release-zlib\INFUTIL.OBJ" +".\Release-zlib\bzlib.obj" +".\Release-zlib\decompress.obj" +".\Release-zlib\huffman.obj" +".\Release-zlib\randtable.obj" +".\Release-zlib\bgbg.obj" +".\Release-zlib\crc32.obj" +".\Release-zlib\exec.obj" +".\Release-zlib\fileform.obj" +".\Release-zlib\Main.obj" +".\Release-zlib\Ui.obj" +".\Release-zlib\util.obj" +".\Release-zlib\resource.res" +] +Creating command line "link.exe @F:\Temp\WinTemp\RSP2EA.tmp" +

Output Window

+Compiling resources... +Compiling... +INFBLOCK.C +INFCODES.C +INFLATE.C +INFTREES.C +INFUTIL.C +bzlib.c +decompress.c +huffman.c +randtable.c +bgbg.c +crc32.c +exec.c +fileform.c +Main.c +Ui.c +util.c +Generating Code... +Linking... +Creating temporary file "F:\Temp\WinTemp\RSP2EC.bat" with contents +[ +@echo off +bin2h Release-zlib\exehead_zlib.exe Release-zlib\exehead_zlib.h zlib_header_data +bin2h bitmap1.bmp Release-zlib\bitmap1.h bitmap1_data +bin2h nsis.ico Release-zlib\icon.h icon_data +bin2h uninst.ico Release-zlib\unicon.h unicon_data +] +Creating command line "F:\Temp\WinTemp\RSP2EC.bat" +generating include file for makenssi +Release-zlib\exehead_zlib.exe -> zlib_header_data (37888 bytes) + +bitmap1.bmp -> bitmap1_data (886 bytes) + +nsis.ico -> icon_data (766 bytes) + +uninst.ico -> unicon_data (766 bytes) + +

+--------------------Configuration: makenssi - Win32 Release-------------------- +

+

Command Lines

+Creating command line "rc.exe /l 0x409 /fo"Release/Script1.res" /d "NDEBUG" "C:\Program Files\NSIS\Source\Script1.rc"" +Creating temporary file "F:\Temp\WinTemp\RSP2ED.tmp" with contents +[ +/nologo /G6 /ML /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fo"Release/" /Fd"Release/" /FD /c +"C:\Program Files\NSIS\Source\zlib\deflate.c" +"C:\Program Files\NSIS\Source\zlib\trees.c" +"C:\Program Files\NSIS\Source\build.cpp" +"C:\Program Files\NSIS\Source\exedata.cpp" +"C:\Program Files\NSIS\Source\makenssi.cpp" +"C:\Program Files\NSIS\Source\util.cpp" +] +Creating command line "cl.exe @F:\Temp\WinTemp\RSP2ED.tmp" +Creating temporary file "F:\Temp\WinTemp\RSP2EE.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fo"Release/" /Fd"Release/" /FD /c +"C:\Program Files\NSIS\Source\bzip2\blocksort.c" +"C:\Program Files\NSIS\Source\bzip2\bzlib.c" +"C:\Program Files\NSIS\Source\bzip2\compress.c" +"C:\Program Files\NSIS\Source\bzip2\huffman.c" +"C:\Program Files\NSIS\Source\crc32.c" +"C:\Program Files\NSIS\Source\DialogTemplate.cpp" +"C:\Program Files\NSIS\Source\ResourceEditor.cpp" +"C:\Program Files\NSIS\Source\tokens.cpp" +] +Creating command line "cl.exe @F:\Temp\WinTemp\RSP2EE.tmp" +Creating temporary file "F:\Temp\WinTemp\RSP2EF.tmp" with contents +[ +/nologo /ML /W3 /GX /Ot /Ow /Oy /Ob2 /D "_CONSOLE" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fo"Release/" /Fd"Release/" /FD /c +"C:\Program Files\NSIS\Source\script.cpp" +] +Creating command line "cl.exe @F:\Temp\WinTemp\RSP2EF.tmp" +Creating temporary file "F:\Temp\WinTemp\RSP2F0.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../makensis.exe" /opt:nowin98 +".\Release\deflate.obj" +".\Release\trees.obj" +".\Release\blocksort.obj" +".\Release\bzlib.obj" +".\Release\compress.obj" +".\Release\huffman.obj" +".\Release\build.obj" +".\Release\crc32.obj" +".\Release\DialogTemplate.obj" +".\Release\exedata.obj" +".\Release\makenssi.obj" +".\Release\ResourceEditor.obj" +".\Release\script.obj" +".\Release\tokens.obj" +".\Release\util.obj" +".\Release\Script1.res" +] +Creating command line "link.exe @F:\Temp\WinTemp\RSP2F0.tmp" +

Output Window

+Compiling resources... +Compiling... +deflate.c +trees.c +Generating Code... +Compiling... +build.cpp +exedata.cpp +makenssi.cpp +util.cpp +Generating Code... +Compiling... +blocksort.c +bzlib.c +compress.c +huffman.c +crc32.c +Generating Code... +Compiling... +DialogTemplate.cpp +ResourceEditor.cpp +tokens.cpp +Generating Code... +Compiling... +script.cpp +Linking... + + + +

Results

+makensis.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/Source/resource.h b/Source/resource.h new file mode 100644 index 00000000..7a74bdaa --- /dev/null +++ b/Source/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Script1.rc +// +#define IDI_ICON1 101 +#define IDD_DIALOG1 110 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/script.cpp b/Source/script.cpp new file mode 100644 index 00000000..9fe9ad23 --- /dev/null +++ b/Source/script.cpp @@ -0,0 +1,3302 @@ +#include +#include +#include +#include "tokens.h" +#include "build.h" +#include "util.h" +#include "exedata.h" +#include "ResourceEditor.h" +#include "DialogTemplate.h" +#include "exehead/resource.h" + +#ifndef FOF_NOERRORUI +#define FOF_NOERRORUI 0x0400 +#endif + + +#define MAX_INCLUDEDEPTH 10 +#define MAX_LINELENGTH 4096 + + +static const char *usrvars="$0\0$1\0$2\0$3\0$4\0$5\0$6\0$7\0$8\0$9\0" + "$R0\0$R1\0$R2\0$R3\0$R4\0$R5\0$R6\0$R7\0$R8\0$R9\0" + "$CMDLINE\0$INSTDIR\0$OUTDIR\0$EXEDIR\0"; + + +int CEXEBuild::process_script(FILE *fp, char *curfilename, int *lineptr) +{ + if (has_called_write_output) + { + ERROR_MSG("Error (process_script): write_output already called, can't continue\n"); + return PS_ERROR; + } + int ret=parseScript(fp,curfilename,lineptr,0); + if (ret == PS_ENDIF) ERROR_MSG("!endif: stray !endif\n"); + if (IS_PS_ELSE(ret)) ERROR_MSG("!else: stray !else\n"); + if (m_linebuild.getlen()) + { + ERROR_MSG("Error: invalid script: last line ended with \\\n"); + return PS_ERROR; + } + return ret; +} + +#define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; } + + +int CEXEBuild::doParse(const char *str, FILE *fp, const char *curfilename, int *lineptr, int ignore) +{ + LineParser line; + int res; + + while (*str == ' ' || *str == '\t') str++; + + // if ignoring, ignore all lines that don't begin with !. + if (ignore && *str!='!') return PS_OK; + + if (m_linebuild.getlen()>1) m_linebuild.resize(m_linebuild.getlen()-2); + + m_linebuild.add(str,strlen(str)+1); + + // remove trailing slash and null + if (str[0] && CharPrev(str,str+strlen(str))[0] == '\\') return PS_OK; + + res=line.parse((char*)m_linebuild.get()); + + m_linebuild.resize(0); + + if (res) + { + if (res==-2) ERROR_MSG("Error: unterminated string parsing line at %s:%d\n",curfilename,*lineptr); + else ERROR_MSG("Error: error parsing line (%s:%d)\n",curfilename,*lineptr); + return PS_ERROR; + } + +parse_again: + if (line.getnumtokens() < 1) return PS_OK; + + int np,op; + int tkid=get_commandtoken(line.gettoken_str(0),&np,&op); + if (tkid == -1) + { + char *p=line.gettoken_str(0); + if (p[0] && p[strlen(p)-1]==':') + { + if (p[0] == '!' || (p[0] >= '0' && p[0] <= '9') || p[0] == '$' || p[0] == '-' || p[0] == '+') + { + ERROR_MSG("Invalid label: %s (labels cannot begin with !, $, -, +, or 0-9)\n",line.gettoken_str(0)); + return PS_ERROR; + } + if (add_label(line.gettoken_str(0))) return PS_ERROR; + line.eattoken(); + goto parse_again; + } + ERROR_MSG("Invalid command: %s\n",line.gettoken_str(0)); + return PS_ERROR; + } + + int v=line.getnumtokens()-(np+1); + if (v < 0 || (op >= 0 && v > op)) // opt_parms is -1 for unlimited + { + ERROR_MSG("%s expects %d",line.gettoken_str(0),np); + if (op < 0) ERROR_MSG("+"); + if (op > 0) ERROR_MSG("-%d",op); + ERROR_MSG(" parameters, got %d.\n",line.getnumtokens()-1); + PRINTHELP() + } + + int is_elseif=0; + + if (!fp && (tkid == TOK_P_ELSE || tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)) + { + ERROR_MSG("Error: !if/!else/!ifdef can only be specified in file mode, not in command/macro mode\n"); + return PS_ERROR; + } + + if (tkid == TOK_P_ELSE) + { + if (line.getnumtokens() == 1) return PS_ELSE; + + line.eattoken(); + + int v=line.gettoken_enum(0,"ifdef\0ifndef\0"); + if (v < 0) PRINTHELP() + if (line.getnumtokens() == 1) PRINTHELP() + if (!v) tkid = TOK_P_IFDEF; + else tkid = TOK_P_IFNDEF; + is_elseif=1; + } + + if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF) + { + int istrue=0; + if (!ignore || is_elseif) + { + int mod=0; + int p; + + // pure left to right precedence. Not too powerful, but useful. + for (p = 1; p < line.getnumtokens(); p ++) + { + if (p & 1) + { + int new_s=!!definedlist.find(line.gettoken_str(p)); + if (tkid == TOK_P_IFNDEF) new_s=!new_s; + + if (mod == 0) istrue = istrue || new_s; + else istrue = istrue && new_s; + } + else + { + mod=line.gettoken_enum(p,"|\0&\0||\0&&\0"); + if (mod == -1) PRINTHELP() + mod &= 1; + } + } + if (is_elseif) + { + if (istrue) return PS_ELSE_IF1; + return PS_ELSE_IF0; + } + } + + int r; + int hasexec=0; + istrue=!istrue; + + for (;;) + { + r=parseScript(fp,curfilename,lineptr, ignore || hasexec || istrue); + if (!istrue) hasexec=1; + if (r == PS_ELSE_IF0) istrue=1; + else if (r == PS_ELSE_IF1) istrue=0; + else break; + } + + if (r == PS_ELSE) + { + r=parseScript(fp,curfilename,lineptr, ignore || hasexec); + if (IS_PS_ELSE(r)) + { + ERROR_MSG("!else: stray !else\n"); + return PS_ERROR; + } + } + if (r == PS_EOF) + { + ERROR_MSG("!ifdef: open at EOF - need !endif\n"); + return PS_ERROR; + } + if (r == PS_ERROR) return r; + return PS_OK; + } + if (tkid == TOK_P_ENDIF) return PS_ENDIF; + if (!ignore) + { + int ret=doCommand(tkid,line,fp,curfilename,*lineptr); + if (ret != PS_OK) return ret; + } + return PS_OK; +} + +void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist) +{ + // convert $\r, $\n to their literals + // preprocessor replace ${VAR} with whatever value + // note that if VAR does not exist, ${VAR} will go through unmodified + const char *in=str; + while (*in) + { + int add=1; + char *t; + char c=*in; + t=CharNext(in); + + if (t-in > 1) // handle multibyte chars (no escape) + { + linedata.add((void*)in,t-in); + in=t; + continue; + } + in=t; + + if (c == '$') + { + if (in[0] == '\\') + { + if (in[1] == 'r') + { + in+=2; + c='\r'; + } + else if (in[1] == 'n') + { + in+=2; + c='\n'; + } + } + else if (in[0] == '{') + { + char *s=strdup(in+1); + char *t=s; + while (*t) + { + if (*t == '}') break; + t=CharNext(t); + } + if (*t && t!=s) + { + *t=0; + t=definedlist.find(s); + if (t && hist.find(s,0)<0) + { + in+=strlen(s)+2; + add=0; + hist.add(s,0); + ps_addtoline(t,linedata,hist); + hist.delbypos(hist.find(s,0)); + } + } + free(s); + } + } + if (add) linedata.add((void*)&c,1); + } +} + +int CEXEBuild::parseScript(FILE *fp, const char *curfilename, int *lineptr, int ignore) +{ + char str[MAX_LINELENGTH]; + + for (;;) + { + char *p=str; + *p=0; + fgets(str,MAX_LINELENGTH,fp); + (*lineptr)++; + if (feof(fp)&&!str[0]) break; + + // remove trailing whitespace + while (*p) p++; + if (p > str) p--; + while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--; + *++p=0; + + StringList hist; + GrowBuf linedata; + ps_addtoline(str,linedata,hist); + linedata.add((void*)"",1); + int ret=doParse((char*)linedata.get(),fp,curfilename,lineptr,ignore); + if (ret != PS_OK) return ret; + } + return PS_EOF; +} + +int CEXEBuild::process_oneline(char *line, char *curfilename, int lineptr) +{ + StringList hist; + GrowBuf linedata; + ps_addtoline(line,linedata,hist); + linedata.add((void*)"",1); + return doParse((char*)linedata.get(),NULL,curfilename,&lineptr,0); +} + +int CEXEBuild::process_jump(LineParser &line, int wt, int *offs) +{ + const char *s=line.gettoken_str(wt); + int v; + + if (!stricmp(s,"0") || !stricmp(s,"")) *offs=0; + else if ((v=line.gettoken_enum(wt,usrvars))>=0) + { + *offs=-v-1; // to jump to a user variable target, -variable_index-1 is stored. + } + else + { + if ((s[0] == '-' || s[0] == '+') && !atoi(s+1)) + { + ERROR_MSG("Error: Goto targets beginning with '+' or '-' must be followed by nonzero integer (relative jump)\n"); + return 1; + } + if ((s[0] >= '0' && s[0] <= '9') || s[0] == '$' || s[0] == '!') + { + ERROR_MSG("Error: Goto targets cannot begin with 0-9, $, !\n"); + return 1; + } + *offs=ns_label.add(s,0); + } + return 0; +} + +int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char *curfilename, int linecnt) +{ + static const char *rootkeys[2] = { + "HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0", + "HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0" + }; + static HKEY rootkey_tab[] = { + HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA + }; + + entry ent={0,}; + switch (which_token) + { + // macro shit + /////////////////////////////////////////////////////////////////////////////// + case TOK_P_MACRO: + { + if (!line.gettoken_str(1)[0]) PRINTHELP() + char *t=(char *)m_macros.get(); + while (t && *t) + { + if (!stricmp(t,line.gettoken_str(1))) break; + t+=strlen(t)+1; + + // advance over parameters + while (*t) t+=strlen(t)+1; + t++; + + // advance over data + while (*t) t+=strlen(t)+1; + if (t-(char *)m_macros.get() >= m_macros.getlen()-1) + break; + t++; + } + if (t && *t) + { + ERROR_MSG("!macro: macro named \"%s\" already found!\n",line.gettoken_str(1)); + return PS_ERROR; + } + m_macros.add(line.gettoken_str(1),strlen(line.gettoken_str(1))+1); + + int pc; + for (pc=2; pc < line.getnumtokens(); pc ++) + { + if (!line.gettoken_str(pc)[0]) + { + ERROR_MSG("!macro: macro parameter %d is empty, not valid!\n",pc-1); + return PS_ERROR; + } + int a; + for (a=2; a < pc; a ++) + { + if (!stricmp(line.gettoken_str(pc),line.gettoken_str(a))) + { + ERROR_MSG("!macro: macro parameter named %s is used multiple times!\n", + line.gettoken_str(pc)); + return PS_ERROR; + } + } + m_macros.add(line.gettoken_str(pc),strlen(line.gettoken_str(pc))+1); + } + m_macros.add("",1); + + for (;;) + { + char str[MAX_LINELENGTH]; + char *p=str; + str[0]=0; + fgets(str,MAX_LINELENGTH,fp); + if (feof(fp) || !str[0]) + { + ERROR_MSG("!macro \"%s\": unterminated (no !macroend found in file)!\n",line.gettoken_str(1)); + return PS_ERROR; + } + // remove trailing whitespace + while (*p) p++; + if (p > str) p--; + while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--; + *++p=0; + LineParser l2; + l2.parse(str); + if (!stricmp(l2.gettoken_str(0),"!macroend")) break; + if (str[0]) m_macros.add(str,strlen(str)+1); + else m_macros.add(" ",2); + } + m_macros.add("",1); + } + return PS_OK; + case TOK_P_MACROEND: + ERROR_MSG("!macroend: no macro currently open.\n"); + return PS_ERROR; + case TOK_P_INSERTMACRO: + { + if (!line.gettoken_str(1)[0]) PRINTHELP() + char *t=(char *)m_macros.get(); + while (t && *t) + { + if (!stricmp(t,line.gettoken_str(1))) break; + t+=strlen(t)+1; + + // advance over parms + while (*t) t+=strlen(t)+1; + t++; + + // advance over data + while (*t) t+=strlen(t)+1; + if (t-(char *)m_macros.get() >= m_macros.getlen()-1) + break; + t++; + } + SCRIPT_MSG("!insertmacro: %s\n",line.gettoken_str(1)); + if (!t || !*t) + { + ERROR_MSG("!insertmacro: macro named \"%s\" not found!\n",line.gettoken_str(1)); + return PS_ERROR; + } + t+=strlen(t)+1; + + + GrowBuf l_define_names; + DefineList l_define_saves; + int npr=0; + // advance over parms + while (*t) + { + char *v; + if (v=definedlist.find(t)) + { + l_define_saves.add(t,v); + definedlist.del(t); + } + l_define_names.add(t,strlen(t)+1); + definedlist.add(t,line.gettoken_str(npr+2)); + + npr++; + t+=strlen(t)+1; + } + l_define_names.add("",1); + t++; + if (npr != line.getnumtokens()-2) + { + ERROR_MSG("!insertmacro: macro \"%s\" requires %d parameter(s), passed %d!\n", + line.gettoken_str(1),npr,line.getnumtokens()-2); + return PS_ERROR; + } + + int lp=0; + char str[1024]; + if (m_macro_entry.find(line.gettoken_str(1),0)>=0) + { + ERROR_MSG("!insertmacro: macro \"%s\" already being inserted!\n",line.gettoken_str(1)); + return PS_ERROR; + } + int npos=m_macro_entry.add(line.gettoken_str(1),0); + + wsprintf(str,"macro:%s",line.gettoken_str(1)); + while (*t) + { + lp++; + if (strcmp(t," ")) + { + int ret=process_oneline(t,str,lp); + if (ret != PS_OK) + { + ERROR_MSG("Error in macro %s on macroline %d\n",line.gettoken_str(1),lp); + return ret; + } + } + t+=strlen(t)+1; + } + m_macro_entry.delbypos(npos); + { + char *p=(char*)l_define_names.get(); + while (*p) + { + definedlist.del(p); + char *v; + if ((v=l_define_saves.find(p))) definedlist.add(p,v); + p+=strlen(p); + } + } + SCRIPT_MSG("!insertmacro: end of %s\n",line.gettoken_str(1)); + } + + return PS_OK; + // header flags + /////////////////////////////////////////////////////////////////////////////// + case TOK_NAME: + if (build_header.common.name_ptr >= 0) + { + warning("Name: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_header.common.name_ptr=add_string_main(line.gettoken_str(1),0); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.common.name_ptr=add_string_uninst(line.gettoken_str(1),0); +#endif + SCRIPT_MSG("Name: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_CAPTION: + if (build_header.common.caption_ptr >= 0) + { + warning("Caption: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_header.common.caption_ptr=add_string_main(line.gettoken_str(1)); + SCRIPT_MSG("Caption: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_ICON: + SCRIPT_MSG("Icon: \"%s\"\n",line.gettoken_str(1)); + try { + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + if (replace_icon(&re, IDI_ICON2, line.gettoken_str(1))) { + ERROR_MSG("Error: File doesn't exist or is an invalid icon file\n"); + return PS_ERROR; + } + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + } + catch (exception& err) { + ERROR_MSG("Error while replacing icon: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#ifdef NSIS_CONFIG_COMPONENTPAGE + // Changed by Amir Szekely 24th July 2002 + case TOK_CHECKBITMAP: + SCRIPT_MSG("CheckBitmap: \"%s\"\n",line.gettoken_str(1)); + try { + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + if (update_bitmap(&re, IDB_BITMAP1, line.gettoken_str(1), 96, 16)) { + ERROR_MSG("Error: File doesn't exist, is an invalid bitmap, or has the wrong size\n"); + return PS_ERROR; + } + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + } + catch (exception& err) { + ERROR_MSG("Error while replacing bitmap: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else//NSIS_CONFIG_COMPONENTPAGE + case TOK_ENABLEDBITMAP: + case TOK_DISABLEDBITMAP: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE + case TOK_DIRTEXT: + if (build_header.text_ptr >= 0 && line.gettoken_str(1)[0]) + { + warning("DirText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_header.text_ptr=add_string_main(line.gettoken_str(1),0); + if (line.getnumtokens()>2) build_header.dirsubtext_ptr=add_string_main(line.gettoken_str(2),0); + if (line.getnumtokens()>3) build_header.browse_ptr=add_string_main(line.gettoken_str(3),0); + SCRIPT_MSG("DirText: \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#ifdef NSIS_CONFIG_COMPONENTPAGE + case TOK_COMPTEXT: + if (build_header.componenttext_ptr >= 0 && line.gettoken_str(1)[0]) + { + warning("ComponentText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_header.componenttext_ptr=add_string_main(line.gettoken_str(1),0); + if (line.getnumtokens()>2) build_header.componentsubtext_ptr[0]=add_string_main(line.gettoken_str(2),0); + if (line.getnumtokens()>3) build_header.componentsubtext_ptr[1]=add_string_main(line.gettoken_str(3),0); + SCRIPT_MSG("ComponentText: \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTTYPE: + { + int x; + if (!stricmp(line.gettoken_str(1),"/NOCUSTOM")) + { + build_header.no_custom_instmode_flag=1; + SCRIPT_MSG("InstType: disabling custom install type\n"); + } + else if (!stricmp(line.gettoken_str(1),"/COMPONENTSONLYONCUSTOM")) + { + build_header.no_custom_instmode_flag=2; + SCRIPT_MSG("InstType: making components viewable only on custom install type\n"); + } + else if (!strnicmp(line.gettoken_str(1),"/CUSTOMSTRING=",14)) + { + build_header.custom_ptr=add_string_main(line.gettoken_str(1)+14,0); + SCRIPT_MSG("InstType: setting custom text to: \"%s\"\n",line.gettoken_str(1)+14); + } + else if (line.gettoken_str(1)[0]=='/') PRINTHELP() + else + { + for (x = 0; x < NSIS_MAX_INST_TYPES && build_header.install_types_ptr[x]>=0; x ++); + if (x==NSIS_MAX_INST_TYPES) + { + ERROR_MSG("InstType: no more than %d install types allowed. %d specified\n",NSIS_MAX_INST_TYPES,NSIS_MAX_INST_TYPES+1); + return PS_ERROR; + } + else + { + build_header.install_types_ptr[x] = add_string_main(line.gettoken_str(1),0); + SCRIPT_MSG("InstType: %d=\"%s\"\n",x+1,line.gettoken_str(1)); + } + } + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else//NSIS_CONFIG_COMPONENTPAGE + case TOK_COMPTEXT: + case TOK_INSTTYPE: + ERROR_MSG("Error: %s specified but NSIS_CONFIG_COMPONENTPAGE not defined\n",line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_CONFIG_LICENSEPAGE + case TOK_LICENSETEXT: + if (build_header.licensetext_ptr >= 0) + { + warning("LicenseText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_header.licensetext_ptr=add_string_main(line.gettoken_str(1),0); + if (line.getnumtokens()>2) build_header.licensebutton_ptr=add_string_main(line.gettoken_str(2),0); + SCRIPT_MSG("LicenseText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_LICENSEDATA: + if (build_header.licensedata_ptr != -1) + { + warning("LicenseData: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_header.common.silent_install) + { + warning("LicenseData: SilentInstall enabled, wasting space (%s:%d)",curfilename,linecnt); + } +#endif + { + FILE *fp; + int datalen; + fp=fopen(line.gettoken_str(1),"rb"); + if (!fp) + { + ERROR_MSG("LicenseData: open failed \"%s\"\n",line.gettoken_str(1)); + PRINTHELP() + } + fseek(fp,0,SEEK_END); + datalen=ftell(fp); + rewind(fp); + char *data=(char*)malloc(datalen+1); + if (fread(data,1,datalen,fp) != datalen) { + ERROR_MSG("LicenseData: can't read file.\n"); + fclose(fp); + return PS_ERROR; + } + fclose(fp); + data[datalen]=0; + build_header.licensedata_ptr=add_string_main(data,0); + SCRIPT_MSG("LicenseData: \"%s\"\n",line.gettoken_str(1)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + // Added by Amir Szekely 30th July 2002 + case TOK_LICENSEBKCOLOR: + { + char *p = line.gettoken_str(1); + int v=strtoul(p,&p,16); + build_header.license_bg=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16); + SCRIPT_MSG("LicenseBkColor: %06X\n",v); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else//!NSIS_CONFIG_LICENSEPAGE + case TOK_LICENSETEXT: + case TOK_LICENSEDATA: + case TOK_LICENSEBKCOLOR: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_LICENSEPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_LICENSEPAGE +#ifdef NSIS_CONFIG_SILENT_SUPPORT + case TOK_SILENTINST: + build_header.common.silent_install=line.gettoken_enum(1,"normal\0silent\0silentlog\0"); + if (build_header.common.silent_install<0) PRINTHELP() +#ifndef NSIS_CONFIG_LOG + if (build_header.common.silent_install == 2) + { + ERROR_MSG("SilentInstall: silentlog specified, no log support compiled in (use NSIS_CONFIG_LOG)\n"); + return PS_ERROR; + } +#endif//NSIS_CONFIG_LOG + SCRIPT_MSG("SilentInstall: %s\n",line.gettoken_str(1)); +#ifdef NSIS_CONFIG_LICENSEPAGE + if (build_header.common.silent_install && build_header.licensedata_ptr != -1) + { + warning("SilentInstall: LicenseData already specified. wasting space (%s:%d)",curfilename,linecnt); + } +#endif//NSIS_CONFIG_LICENSEPAGE + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_SILENTUNINST: +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.common.silent_install=line.gettoken_enum(1,"normal\0silent\0"); + if (build_uninst.common.silent_install<0) PRINTHELP() + SCRIPT_MSG("SilentUnInstall: %s\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif +#else//!NSIS_CONFIG_SILENT_SUPPORT + case TOK_SILENTINST: + case TOK_SILENTUNINST: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_SILENT_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_SILENT_SUPPORT + case TOK_OUTFILE: + strncpy(build_output_filename,line.gettoken_str(1),1024-1); + SCRIPT_MSG("OutFile: \"%s\"\n",build_output_filename); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTDIR: + if (build_header.install_directory_ptr >= 0) + { + warning("InstallDir: specified multiple times. wasting space (%s:%d)",curfilename,linecnt); + } + build_header.install_directory_ptr = add_string_main(line.gettoken_str(1)); + SCRIPT_MSG("InstallDir: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTALLDIRREGKEY: // InstallDirRegKey + { + if (build_header.install_reg_key_ptr>= 0) + { + warning("InstallRegKey: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + int k=line.gettoken_enum(1,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(1,rootkeys[1]); + if (k == -1) PRINTHELP() + build_header.install_reg_rootkey=(int)rootkey_tab[k]; + build_header.install_reg_key_ptr = add_string_main(line.gettoken_str(2),0); + if (line.gettoken_str(2)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); + build_header.install_reg_value_ptr = add_string_main(line.gettoken_str(3),0); + SCRIPT_MSG("InstallRegKey: \"%s\\%s\\%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_CRCCHECK: + build_crcchk=line.gettoken_enum(1,"off\0on\0force\0"); + if (build_crcchk==-1) PRINTHELP() + SCRIPT_MSG("CRCCheck: %s\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTPROGRESSFLAGS: + { + int x; + build_header.common.progress_flags=0; + for (x = 1; x < line.getnumtokens(); x ++) + { + if (!stricmp(line.gettoken_str(x),"smooth")) build_header.common.progress_flags|=1; + else if (!stricmp(line.gettoken_str(x),"colored")) build_header.common.progress_flags|=2; + else PRINTHELP() + } + SCRIPT_MSG("InstProgressFlags: %d (smooth=%d,colored=%d)\n",build_header.common.progress_flags, + build_header.common.progress_flags&1, + (build_header.common.progress_flags&2)>>1); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_AUTOCLOSE: + { + int k=line.gettoken_enum(1,"false\0true\0"); + if (k == -1) PRINTHELP() + build_header.common.misc_flags&=~1; + build_header.common.misc_flags|=k; + SCRIPT_MSG("AutoCloseWindow: %s\n",k?"true":"false"); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_WINDOWICON: +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + // Changed by Amir Szekely 30th July 2002 + try { + int k=line.gettoken_enum(1,"on\0off\0"); + if (k == -1) PRINTHELP(); + SCRIPT_MSG("WindowIcon: %s\n",line.gettoken_str(1)); + + if (!k) return make_sure_not_in_secorfunc(line.gettoken_str(0)); + + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + +#define REMOVE_ICON(id) { \ + BYTE* dlg = re.GetResource(RT_DIALOG, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); \ + if (!dlg) throw runtime_error(#id " doesn't exist!"); \ + CDialogTemplate dt(dlg); \ + free(dlg); \ + dt.RemoveItem(IDC_ULICON); \ + DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \ + DialogItemTemplate* prog1 = dt.GetItem(IDC_PROGRESS1); \ + DialogItemTemplate* prog2 = dt.GetItem(IDC_PROGRESS2); \ + if (text) { \ + text->sWidth += text->sX; \ + text->sX = 0; \ + } \ + if (prog1) { \ + prog1->sWidth += prog1->sX; \ + prog1->sX = 0; \ + } \ + if (prog2) { \ + prog2->sWidth += prog2->sX; \ + prog2->sX = 0; \ + } \ + \ + DWORD dwSize; \ + dlg = dt.Save(dwSize); \ + re.UpdateResource(RT_DIALOG, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), dlg, dwSize); \ + free(dlg); \ + } + +#ifdef NSIS_CONFIG_LICENSEPAGE + REMOVE_ICON(IDD_LICENSE); +#endif + REMOVE_ICON(IDD_DIR); +#ifdef NSIS_CONFIG_COMPONENTPAGE + REMOVE_ICON(IDD_SELCOM); +#endif + REMOVE_ICON(IDD_INSTFILES); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + REMOVE_ICON(IDD_UNINST); +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT + REMOVE_ICON(IDD_VERIFY); +#endif + + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + } + catch (exception& err) { + ERROR_MSG("Error while changing font: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif // NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_SHOWDETAILSUNINST: +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + ERROR_MSG("Error: ShowUninstDetails specified but NSIS_CONFIG_UNINSTALL_SUPPORT not defined\n"); + return PS_ERROR; +#endif + case TOK_SHOWDETAILS: + { + int k=line.gettoken_enum(1,"hide\0show\0nevershow\0"); + if (k == -1) PRINTHELP() +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (which_token == TOK_SHOWDETAILSUNINST) build_uninst.common.show_details=k; + else +#endif + build_header.common.show_details=k; + SCRIPT_MSG("%s: %s\n",line.gettoken_str(0),line.gettoken_str(1)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_DIRSHOW: + { + int k=line.gettoken_enum(1,"show\0hide\0"); + if (k == -1) PRINTHELP() + build_header.common.misc_flags&=~2; + build_header.common.misc_flags|=(k<<1); + SCRIPT_MSG("DirShow: %s\n",k?"hide":"show"); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_ROOTDIRINST: + { + int k=line.gettoken_enum(1,"true\0false\0"); + if (k == -1) PRINTHELP() + build_header.common.misc_flags&=~8; + build_header.common.misc_flags|=(k<<3); + SCRIPT_MSG("AllowRootDirInstall: %s\n",k?"false":"true"); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_BGGRADIENT: +#ifndef NSIS_SUPPORT_BGBG + ERROR_MSG("Error: BGGradient specified but NSIS_SUPPORT_BGBG not defined\n"); + return PS_ERROR; +#else//NSIS_SUPPORT_BGBG + if (line.getnumtokens()==1) + { + SCRIPT_MSG("BGGradient: default colors\n"); + build_header.common.bg_color1=0; + build_header.common.bg_color2=RGB(0,0,255); + } + else if (!stricmp(line.gettoken_str(1),"off")) + { + build_header.common.bg_color1=build_header.common.bg_color2=-1; + SCRIPT_MSG("BGGradient: off\n"); + if (line.getnumtokens()>2) PRINTHELP() + } + else + { + char *p = line.gettoken_str(1); + int v1,v2,v3=-1; + v1=strtoul(p,&p,16); + build_header.common.bg_color1=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16); + p=line.gettoken_str(2); + v2=strtoul(p,&p,16); + build_header.common.bg_color2=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16); + + p=line.gettoken_str(3); + if (*p) + { + if (!stricmp(p,"notext")) build_header.common.bg_textcolor=-1; + else + { + v3=strtoul(p,&p,16); + build_header.common.bg_textcolor=((v3&0xff)<<16)|(v3&0xff00)|((v3&0xff0000)>>16); + } + } + + SCRIPT_MSG("BGGradient: %06X->%06X (text=%d)\n",v1,v2,v3); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.common.bg_color1=build_header.common.bg_color1; + build_uninst.common.bg_color2=build_header.common.bg_color2; + build_uninst.common.bg_textcolor=build_header.common.bg_textcolor; +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#endif//NSIS_SUPPORT_BGBG + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTCOLORS: + { + char *p = line.gettoken_str(1); + if (p[0]=='/') + { + if (stricmp(p,"/windows") || line.getnumtokens()!=2) PRINTHELP() + build_header.common.lb_fg=build_header.common.lb_bg=-1; + SCRIPT_MSG("InstallColors: windows default colors\n"); + } + else + { + int v1,v2; + if (line.getnumtokens()!=3) PRINTHELP() + v1=strtoul(p,&p,16); + build_header.common.lb_fg=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16); + p=line.gettoken_str(2); + v2=strtoul(p,&p,16); + build_header.common.lb_bg=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16); + SCRIPT_MSG("InstallColors: fg=%06X bg=%06X\n",v1,v2); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.common.lb_fg=build_header.common.lb_fg; + build_uninst.common.lb_bg=build_header.common.lb_bg; +#endif + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + // Added by Amir Szekely 7th July 2002 + case TOK_XPSTYLE: + try { + int k=line.gettoken_enum(1,"on\0off\0"); + if (k == -1) PRINTHELP() + SCRIPT_MSG("XPStyle: %s\n", line.gettoken_str(1)); + if (k == 0) { + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + char* szXPManifest = "Nullsoft Install System."; + re.UpdateResource(MAKEINTRESOURCE(24), MAKEINTRESOURCE(1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (unsigned char*)szXPManifest, lstrlen(szXPManifest)); + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + } + } + catch (exception& err) { + ERROR_MSG("Error while adding XP style: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + // Added by Amir Szekely 28th July 2002 +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_CHANGEUI: + try { + HINSTANCE hUIFile = LoadLibraryEx(line.gettoken_str(1), 0, LOAD_LIBRARY_AS_DATAFILE); + if (!hUIFile) { + ERROR_MSG("Error: Can't find \"%s\"!\n", line.gettoken_str(1)); + return PS_ERROR; + } + HRSRC hUIRes = FindResource(hUIFile, MAKEINTRESOURCE(IDD_INST), RT_DIALOG); + if (!hUIRes) { + ERROR_MSG("Error: \"%s\" doesn't contain a dialog named IDD_INST (%u)!\n", line.gettoken_str(1), IDD_INST); + return PS_ERROR; + } + HGLOBAL hUIMem = LoadResource(hUIFile, hUIRes); + if (!hUIMem) { + ERROR_MSG("Error: Can't load a dialog from \"%s\"!\n", line.gettoken_str(1)); + return PS_ERROR; + } + BYTE* pbUIData = (BYTE*)LockResource(hUIMem); + if (!pbUIData) { + ERROR_MSG("Error: Can't lock resource from \"%s\"!\n", line.gettoken_str(1)); + return PS_ERROR; + } + + CDialogTemplate UIDlg(pbUIData); + + // Search for required items + #define SEARCH(x) if (!UIDlg.GetItem(IDC_BACK)) {ERROR_MSG("Error: Can't find %s (%u) in the custom UI!\n", #x, x);return PS_ERROR;} + SEARCH(IDC_BACK); + SEARCH(IDC_CHILDRECT); + SEARCH(IDC_VERSTR); + SEARCH(IDOK); + SEARCH(IDCANCEL); + + // Search for bitmap holder (default for SetBrandingImage) + DialogItemTemplate* dlgItem = 0; + int i = 0; + while (dlgItem = UIDlg.GetItemByIdx(i)) { + if (IS_INTRESOURCE(dlgItem->szClass)) { + if (dlgItem->szClass == MAKEINTRESOURCE(0x0082)) { + if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) { + branding_image_found = true; + branding_image_id = dlgItem->wId; + break; + } + } + } + i++; + } + + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + re.UpdateResource(RT_DIALOG, IDD_INST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), pbUIData, UIDlg.GetSize()); + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + + SCRIPT_MSG("ChangeUI: %s%s\n", line.gettoken_str(1), branding_image_found?" (branding image holder found)":""); + } + catch (exception& err) { + ERROR_MSG("Error while changing UI: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif// NSIS_CONFIG_VISIBLE_SUPPORT + // Added by Amir Szekely 21st July 2002 +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_ADDBRANDINGIMAGE: + try { + int k=line.gettoken_enum(1,"top\0left\0"); + int wh=line.gettoken_int(2); + if (k == -1) PRINTHELP() + + CResourceEditor re(header_data_new, exeheader_size_new); + BYTE* dlg = re.GetResource(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); + + CDialogTemplate dt(dlg); + delete [] dlg; + + DialogItemTemplate *childRect = dt.GetItem(IDC_CHILDRECT); + DialogItemTemplate brandingCtl = {0,}; + + brandingCtl.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE; + brandingCtl.sX = childRect->sX; + brandingCtl.sY = childRect->sY; + brandingCtl.szClass = MAKEINTRESOURCE(0x0082); + brandingCtl.szTitle = ""; + brandingCtl.wId = IDC_BRANDIMAGE; + + brandingCtl.sHeight = wh; + brandingCtl.sWidth = wh; + dt.PixelsToDlgUnits(brandingCtl.sWidth, brandingCtl.sHeight); + if (k) { + // Left + dt.MoveAllAndResize(brandingCtl.sWidth + childRect->sX, 0); + + DialogItemTemplate *okButton = dt.GetItem(IDOK); + brandingCtl.sHeight = okButton->sY + okButton->sHeight - childRect->sY; + } + else { + // Top + dt.MoveAllAndResize(0, brandingCtl.sHeight + childRect->sY); + + brandingCtl.sWidth = childRect->sWidth; + } + + dt.AddItem(brandingCtl); + + DWORD dwDlgSize; + dlg = dt.Save(dwDlgSize); + + re.UpdateResource(RT_DIALOG, IDD_INST, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), dlg, dwDlgSize); + + delete [] dlg; + + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + + dt.DlgUnitsToPixels(brandingCtl.sWidth, brandingCtl.sHeight); + SCRIPT_MSG("AddBrandingImage: %s %ux%u\n", line.gettoken_str(1), brandingCtl.sWidth, brandingCtl.sHeight); + + branding_image_found = true; + branding_image_id = IDC_BRANDIMAGE; + } + catch (exception& err) { + ERROR_MSG("Error while adding image branding support: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif// NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_SETFONT: + SCRIPT_MSG("SetFont: \"%s\" %s\n", line.gettoken_str(1), line.gettoken_str(2)); + try { + build_compressor_set=true; + CResourceEditor re(header_data_new, exeheader_size_new); + +#define SET_FONT(id) { \ + BYTE* dlg = re.GetResource(RT_DIALOG, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); \ + if (!dlg) throw runtime_error(#id " doesn't exist!"); \ + CDialogTemplate td(dlg); \ + free(dlg); \ + td.SetFont(line.gettoken_str(1), line.gettoken_int(2)); \ + DWORD dwSize; \ + dlg = td.Save(dwSize); \ + re.UpdateResource(RT_DIALOG, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), dlg, dwSize); \ + free(dlg); \ + } + +#ifdef NSIS_CONFIG_LICENSEPAGE + SET_FONT(IDD_LICENSE); +#endif + SET_FONT(IDD_DIR); +#ifdef NSIS_CONFIG_COMPONENTPAGE + SET_FONT(IDD_SELCOM); +#endif + SET_FONT(IDD_INST); + SET_FONT(IDD_INSTFILES); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + SET_FONT(IDD_UNINST); +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT + SET_FONT(IDD_VERIFY); +#endif + + free(header_data_new); + header_data_new = re.Save((DWORD&)exeheader_size_new); + } + catch (exception& err) { + ERROR_MSG("Error while changing font: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif// NSIS_CONFIG_VISIBLE_SUPPORT + // Added by Amir Szekely 31st July 2002 + // Ability to change compression methods from within the script + case TOK_SETCOMPRESSOR: + { + if (build_compressor_set) { + ERROR_MSG("Error: can't change compressor after data already got compressed or header already changed!\n"); + return PS_ERROR; + } + int k=line.gettoken_enum(1,"zlib\0bzip2\0"); + switch (k) { + case 0: + // Default is zlib... + break; + case 1: + compressor=&bzip2_compressor; + free(header_data_new); + header_data_new=(unsigned char*)malloc(bzip2_exeheader_size); + exeheader_size_new=bzip2_exeheader_size; + exeheader_size=bzip2_exeheader_size; + + if (!header_data_new) + { + ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n",exeheader_size_new); + extern void quit(); quit(); + } + + memcpy(header_data_new,bzip2_header_data,bzip2_exeheader_size); +#ifdef NSIS_BZIP2_COMPRESS_WHOLE + build_compress_whole=true; +#else + build_compress_whole=false; +#endif + break; + default: + PRINTHELP(); + } + SCRIPT_MSG("SetCompressor: %s\n", line.gettoken_str(1)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + + // preprocessor-ish (ifdef/ifndef/else/endif are handled one step out from here) + /////////////////////////////////////////////////////////////////////////////// + case TOK_P_DEFINE: + if (definedlist.add(line.gettoken_str(1),line.gettoken_str(2))) + { + ERROR_MSG("!define: \"%s\" already defined!\n",line.gettoken_str(1)); + return PS_ERROR; + } + SCRIPT_MSG("!define: \"%s\"=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + return PS_OK; + case TOK_P_UNDEF: + if (definedlist.del(line.gettoken_str(1))) + { + ERROR_MSG("!undef: \"%s\" not defined!\n",line.gettoken_str(1)); + return PS_ERROR; + } + SCRIPT_MSG("!undef: \"%s\"\n",line.gettoken_str(1)); + return PS_OK; + case TOK_P_PACKEXEHEADER: + strncpy(build_packname,line.gettoken_str(1),sizeof(build_packname)-1); + strncpy(build_packcmd,line.gettoken_str(2),sizeof(build_packcmd)-1); + SCRIPT_MSG("!packhdr: filename=\"%s\", command=\"%s\"\n", + build_packname, build_packcmd); + return PS_OK; + case TOK_P_SYSTEMEXEC: + { + char *exec=line.gettoken_str(1); + int comp=line.gettoken_enum(2,"<\0>\0<>\0=\0ignore\0"); + if (comp == -1 && line.getnumtokens() == 3) comp=4; + if (comp == -1) PRINTHELP() + int success=0; + int cmpv=line.gettoken_int(3,&success); + if (!success && comp != 4) PRINTHELP() + SCRIPT_MSG("!system: \"%s\"\n",exec); + int ret=system(exec); + if (comp == 0 && ret < cmpv); + else if (comp == 1 && ret > cmpv); + else if (comp == 2 && ret != cmpv); + else if (comp == 3 && ret == cmpv); + else if (comp == 4); + else + { + ERROR_MSG("!system: returned %d, aborting\n",ret); + return PS_ERROR; + } + SCRIPT_MSG("!system: returned %d\n",ret); + } + return PS_OK; + case TOK_P_INCLUDE: + { + char *f=line.gettoken_str(1); + SCRIPT_MSG("!include: \"%s\"\n",f); + FILE *incfp=fopen(f,"rt"); + if (!incfp) + { + ERROR_MSG("!include: could not open file: \"%s\"\n",f); + return PS_ERROR; + } + static int depth; + if (depth >= MAX_INCLUDEDEPTH) + { + ERROR_MSG("parseScript: too many levels of includes (%d max).\n",MAX_INCLUDEDEPTH); + return PS_ERROR; + } + depth++; + int lc=0; + int r=parseScript(incfp,f,&lc,0); + depth--; + fclose(incfp); + if (r != PS_EOF && r != PS_OK) + { + if (r == PS_ENDIF) ERROR_MSG("!endif: stray !endif\n"); + if (IS_PS_ELSE(r)) ERROR_MSG("!else: stray !else\n"); + ERROR_MSG("!include: error in script: \"%s\" on line %d\n",f,lc); + return PS_ERROR; + } + SCRIPT_MSG("!include: closed: \"%s\"\n",f); + } + return PS_OK; + case TOK_P_CD: + if (!line.gettoken_str(1)[0] || !SetCurrentDirectory(line.gettoken_str(1))) + { + ERROR_MSG("!cd: error changing to: \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } + return PS_OK; + case TOK_P_ERROR: + ERROR_MSG("!error: %s\n",line.gettoken_str(1)); + return PS_ERROR; + case TOK_P_WARNING: + warning("!warning: %s (%s:%d)\n",line.gettoken_str(1),curfilename,linecnt); + return PS_OK; + // Added by Amir Szekely 23rd July 2002 + case TOK_P_ECHO: + SCRIPT_MSG("%s (%s:%d)\n", line.gettoken_str(1),curfilename,linecnt); + return PS_OK; + + // Added by Amir Szekely 23rd July 2002 + case TOK_P_VERBOSE: + { + extern int g_display_errors; + int v=line.gettoken_int(1); + display_script=v>3; + display_info=v>2; + display_warnings=v>1; + display_errors=v>0; + g_display_errors=display_errors; + } + return PS_OK; + + case TOK_UNINSTALLEXENAME: PRINTHELP() + + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + case TOK_UNINSTCAPTION: + if (build_uninst.common.caption_ptr >= 0) + { + warning("UninstCaption: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_uninst.common.caption_ptr=add_string_uninst(line.gettoken_str(1)); + SCRIPT_MSG("UninstCaption: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_UNINSTICON: + SCRIPT_MSG("UninstallIcon: \"%s\"\n",line.gettoken_str(1)); + try { + free(m_unicon_data); + m_unicon_data = generate_uninstall_icon_data(line.gettoken_str(1)); + if (!m_unicon_data) { + ERROR_MSG("Error: File doesn't exist or is an invalid icon file\n"); + return PS_ERROR; + } + } + catch (exception& err) { + ERROR_MSG("Error while replacing icon: %s\n", err.what()); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_UNINSTTEXT: + if (build_uninst.uninstalltext_ptr >= 0) + { + warning("UninstallText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt); + } + build_uninst.uninstalltext_ptr=add_string_uninst(line.gettoken_str(1),0); + if (line.getnumtokens()>2) build_uninst.uninstalltext2_ptr=add_string_uninst(line.gettoken_str(2),0); + SCRIPT_MSG("UninstallText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_UNINSTSUBCAPTION: + { + int s; + int w=line.gettoken_int(1,&s); + if (!s || w < 0 || w > 2) PRINTHELP() + build_uninst.common.subcaption_ptrs[w]=add_string_uninst(line.gettoken_str(2)); + SCRIPT_MSG("UninstSubCaption: page:%d, text=%s\n",w,line.gettoken_str(2)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_WRITEUNINSTALLER: + if (uninstall_mode) + { + ERROR_MSG("WriteUninstaller only valid from install, not from uninstall.\n"); + PRINTHELP() + } + uninstaller_writes_used++; + ent.which=EW_WRITEUNINSTALLER; + ent.offsets[0]=add_string_main(line.gettoken_str(1)); + ent.offsets[1]=0; // uninstall section 0 + ent.offsets[2]=0; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("WriteUninstaller: \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_CONFIG_UNINSTALL_SUPPORT + case TOK_WRITEUNINSTALLER: + case TOK_UNINSTCAPTION: + case TOK_UNINSTICON: + case TOK_UNINSTTEXT: + case TOK_UNINSTSUBCAPTION: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + + + + // section/function shit + /////////////////////////////////////////////////////////////////////////////// + + case TOK_SECTION: + { + int a=1,ex = 0; + if (!strcmp(line.gettoken_str(1),"/e")) + { + ex = 1; + a++; + } + SCRIPT_MSG("Section: \"%s\"",line.gettoken_str(a)); + if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1)); + SCRIPT_MSG("\n"); +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!stricmp(line.gettoken_str(a),"uninstall")) + { + ERROR_MSG("Error: Uninstall section declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n"); + return PS_ERROR; + } +#endif + + if (line.gettoken_str(a)[0]=='-') return add_section("",curfilename,linecnt,line.gettoken_str(a+1),ex); + return add_section(line.gettoken_str(a),curfilename,linecnt,line.gettoken_str(2),ex); + } + case TOK_SECTIONEND: + SCRIPT_MSG("SectionEnd\n"); + return section_end(); + case TOK_SECTIONIN: + { + SCRIPT_MSG("SectionIn: "); + int wt; + for (wt = 1; wt < line.getnumtokens(); wt ++) + { + char *p=line.gettoken_str(wt); + if (p[0]=='R' && p[1]=='O') + { + if (section_add_flags(DFS_SET|DFS_RO) != PS_OK) return PS_ERROR; + SCRIPT_MSG("[RO] "); + } + else + { + int x=atoi(p)-1; + if (x >= 0 && x < NSIS_MAX_INST_TYPES) + { + if (section_add_flags(1< 4) PRINTHELP() + build_header.common.subcaption_ptrs[w]=add_string_main(line.gettoken_str(2)); + SCRIPT_MSG("SubCaption: page:%d, text=%s\n",w,line.gettoken_str(2)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_FILEERRORTEXT: +#ifdef NSIS_SUPPORT_FILE + build_header.common.fileerrtext_ptr=add_string_main(line.gettoken_str(1)); + SCRIPT_MSG("FileErrorText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + case TOK_BRANDINGTEXT: + build_header.common.branding_ptr=add_string_main(line.gettoken_str(1),0); + SCRIPT_MSG("BrandingText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_MISCBUTTONTEXT: + build_header.backbutton_ptr=add_string_main(line.gettoken_str(1),0); + build_header.nextbutton_ptr=add_string_main(line.gettoken_str(2),0); + build_header.common.cancelbutton_ptr=add_string_main(line.gettoken_str(3),0); + build_header.common.closebutton_ptr=add_string_main(line.gettoken_str(4),0); + SCRIPT_MSG("MiscButtonText: back=\"%s\" next=\"%s\" cancel=\"%s\" close=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_SPACETEXTS: + if (!lstrcmp(line.gettoken_str(1), "none")) { + build_header.spacerequired_ptr=-2; // No space text + SCRIPT_MSG("SpaceTexts: none\n"); + } + else { + build_header.spacerequired_ptr=add_string_main(line.gettoken_str(1),0); + build_header.spaceavailable_ptr=add_string_main(line.gettoken_str(2),0); + SCRIPT_MSG("SpaceTexts: required=\"%s\" available=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_INSTBUTTONTEXT: + build_header.installbutton_ptr=add_string_main(line.gettoken_str(1),0); + SCRIPT_MSG("InstallButtonText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_DETAILSBUTTONTEXT: + build_header.common.showdetailsbutton_ptr=add_string_main(line.gettoken_str(1),0); + SCRIPT_MSG("DetailsButtonText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_COMPLETEDTEXT: + build_header.common.completed_ptr=add_string_main(line.gettoken_str(1),0); + SCRIPT_MSG("CompletedText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); + case TOK_UNINSTBUTTONTEXT: +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.uninstbutton_ptr=add_string_uninst(line.gettoken_str(1),0); + SCRIPT_MSG("UninstButtonText: \"%s\"\n",line.gettoken_str(1)); + return make_sure_not_in_secorfunc(line.gettoken_str(0)); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + + // instructions + /////////////////////////////////////////////////////////////////////////////// + case TOK_NOP: + SCRIPT_MSG("Nop\n"); + ent.which=EW_NOP; + return add_entry(&ent); + case TOK_GOTO: + ent.which=EW_NOP; + if (process_jump(line,1,&ent.offsets[0])) PRINTHELP() + SCRIPT_MSG("Goto: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETSHELLVARCONTEXT: + ent.which=EW_SETSFCONTEXT; + ent.offsets[0]=line.gettoken_enum(1,"current\0all\0"); + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("SetShellVarContext: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_RET: + SCRIPT_MSG("Return\n"); + ent.which=EW_RET; + return add_entry(&ent); + case TOK_CALL: + if (!line.gettoken_str(1)[0] || (line.gettoken_str(1)[0]==':' && !line.gettoken_str(1)[1] )) PRINTHELP() +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode && strnicmp(line.gettoken_str(1),"un.",3) && (line.gettoken_enum(1,usrvars) < 0)) + { + ERROR_MSG("Call must be used with function names starting with \"un.\" in the uninstall section.\n"); + PRINTHELP() + } + if (!uninstall_mode && !strnicmp(line.gettoken_str(1),"un.",3)) + { + ERROR_MSG("Call must not be used with functions starting with \"un.\" in the non-uninstall sections.\n"); + PRINTHELP() + } +#endif + ent.which=EW_CALL; + ent.offsets[1]=0; + { + int v; + if ((v=line.gettoken_enum(1,usrvars))>=0) + { + ent.offsets[0]=-v-2; + } + else + { + if (line.gettoken_str(1)[0] == ':') + { + ent.offsets[1]=1; + ent.offsets[0]=ns_label.add(line.gettoken_str(1)+1,0); + } + else ent.offsets[0]=ns_func.add(line.gettoken_str(1),0); + } + } + SCRIPT_MSG("Call \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETOUTPATH: + { + char *p=line.gettoken_str(1); + if (*p == '-') cur_out_path[0]=0; + else + { + if (p[0] == '\\' && p[1] != '\\') p++; + strncpy(cur_out_path,p,1024-1); + cur_out_path[1024-1]=0; + if (*CharPrev(cur_out_path,cur_out_path+strlen(cur_out_path))=='\\') + *CharPrev(cur_out_path,cur_out_path+strlen(cur_out_path))=0; // remove trailing slash + } + if (!cur_out_path[0]) strcpy(cur_out_path,"$INSTDIR"); + SCRIPT_MSG("SetOutPath: \"%s\"\n",cur_out_path); + ent.which=EW_CREATEDIR; + ent.offsets[0]=add_string(cur_out_path); + ent.offsets[1]=1; + } + return add_entry(&ent); + case TOK_CREATEDIR: + { + char out_path[1024]; + char *p=line.gettoken_str(1); + if (*p == '-') out_path[0]=0; + else + { + if (p[0] == '\\' && p[1] != '\\') p++; + strncpy(out_path,p,1024-1); + if (*CharPrev(out_path,out_path+strlen(out_path))=='\\') + *CharPrev(out_path,out_path+strlen(out_path))=0; // remove trailing slash + } + if (!*out_path) PRINTHELP() + SCRIPT_MSG("CreateDirectory: \"%s\"\n",out_path); + ent.which=EW_CREATEDIR; + ent.offsets[0]=add_string(out_path); + } + return add_entry(&ent); + case TOK_EXEC: + case TOK_EXECWAIT: +#ifdef NSIS_SUPPORT_EXECUTE + ent.which=EW_EXECUTE; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1] = 0; + if (which_token == TOK_EXECWAIT) + { + ent.offsets[1]=1; + ent.offsets[2]=line.gettoken_enum(2,usrvars); + if (line.gettoken_str(2)[0] && ent.offsets[2]<0) PRINTHELP() + } + SCRIPT_MSG("%s: \"%s\" (->%s)\n",ent.offsets[1]?"ExecWait":"Exec",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_EXECUTE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_EXECUTE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_EXECUTE + case TOK_EXECSHELL: // this uses improvements of Andras Varga +#ifdef NSIS_SUPPORT_SHELLEXECUTE + ent.which=EW_SHELLEXEC; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=SW_SHOWNORMAL; + if (line.getnumtokens() > 4) + { + int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED}; + int a=line.gettoken_enum(4,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0"); + if (a < 0) PRINTHELP() + ent.offsets[3]=tab[a]; + } + SCRIPT_MSG("ExecShell: %s: \"%s\" \"%s\" %s\n",line.gettoken_str(1),line.gettoken_str(2), + line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_SHELLEXECUTE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_SHELLEXECUTE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_SHELLEXECUTE + case TOK_CALLINSTDLL: + case TOK_REGDLL: + case TOK_UNREGDLL: +#ifndef NSIS_SUPPORT_ACTIVEXREG + ERROR_MSG("%s: support not compiled in (NSIS_SUPPORT_ACTIVEXREG)\n",line.gettoken_str(0)); + return PS_ERROR; +#else//NSIS_SUPPORT_ACTIVEXREG + ent.which=EW_REGISTERDLL; + ent.offsets[0]=add_string(line.gettoken_str(1)); + if (which_token == TOK_UNREGDLL) + { + ent.offsets[1]=add_string("DllUnregisterServer"); + ent.offsets[2]=add_string("Unregistering: "); + } + else if (which_token == TOK_CALLINSTDLL) + { + ent.offsets[1] = add_string(line.gettoken_str(2)); + if (ent.offsets[1]<0) PRINTHELP() + ent.offsets[2]=-1; + } + else // register + { + ent.offsets[1] = add_string(line.gettoken_str(2)); + if (ent.offsets[1]<0) ent.offsets[1]=add_string("DllRegisterServer"); + ent.offsets[2]=add_string("Registering: "); + } + + SCRIPT_MSG("%s: \"%s\" %s\n",line.gettoken_str(0),line.gettoken_str(1), line.gettoken_str(2)); + return add_entry(&ent); +#endif//NSIS_SUPPORT_ACTIVEXREG + case TOK_RENAME: +#ifdef NSIS_SUPPORT_RENAME + { + int a=1; + ent.which=EW_RENAME; + if (!stricmp(line.gettoken_str(1),"/REBOOTOK")) + { + ent.offsets[2]=1; + a++; +#ifndef NSIS_SUPPORT_MOVEONREBOOT + ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"); + PRINTHELP() +#endif + } + else if (line.gettoken_str(1)[0]=='/') + { + a=line.getnumtokens(); // cause usage to go here: + } + if (line.getnumtokens()!=a+2) PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + ent.offsets[1]=add_string(line.gettoken_str(a+1)); + SCRIPT_MSG("Rename: %s%s->%s\n",ent.offsets[2]?"/REBOOTOK ":"",line.gettoken_str(a),line.gettoken_str(a+1)); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_RENAME + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RENAME not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_RENAME + case TOK_MESSAGEBOX: +#ifdef NSIS_SUPPORT_MESSAGEBOX + { + #define MBD(x) {x,#x}, + struct + { + int id; + char *str; + } list[]= + { + MBD(MB_ABORTRETRYIGNORE) + MBD(MB_OK) + MBD(MB_OKCANCEL) + MBD(MB_RETRYCANCEL) + MBD(MB_YESNO) + MBD(MB_YESNOCANCEL) + MBD(MB_ICONEXCLAMATION) + MBD(MB_ICONINFORMATION) + MBD(MB_ICONQUESTION) + MBD(MB_ICONSTOP) + MBD(MB_TOPMOST) + MBD(MB_SETFOREGROUND) + MBD(MB_RIGHT) + MBD(MB_DEFBUTTON1) + MBD(MB_DEFBUTTON2) + MBD(MB_DEFBUTTON3) + MBD(MB_DEFBUTTON4) + }; + #undef MBD + int r=0; + int x; + char *p=line.gettoken_str(1); + + while (*p) + { + char *np=p; + while (*np && *np != '|') np++; + if (*np) *np++=0; + for (x =0 ; x < sizeof(list)/sizeof(list[0]) && strcmp(list[x].str,p); x ++); + if (x < sizeof(list)/sizeof(list[0])) + { + r|=list[x].id; + } + else PRINTHELP() + p=np; + } + ent.which=EW_MESSAGEBOX; + ent.offsets[0]=r; + ent.offsets[1]=add_string(line.gettoken_str(2)); + int rettab[] = + { + 0,IDABORT,IDCANCEL,IDIGNORE,IDNO,IDOK,IDRETRY,IDYES + }; + const char *retstr="0\0IDABORT\0IDCANCEL\0IDIGNORE\0IDNO\0IDOK\0IDRETRY\0IDYES\0"; + if (line.getnumtokens() > 3) + { + ent.offsets[2]=line.gettoken_enum(3,retstr); + if (ent.offsets[2] < 0) PRINTHELP() + ent.offsets[2] = rettab[ent.offsets[2]]; + if (process_jump(line,4,&ent.offsets[3])) PRINTHELP() + if (line.getnumtokens() > 5) + { + int v=line.gettoken_enum(5,retstr); + if (v < 0) PRINTHELP() + ent.offsets[2] |= rettab[v]<<16; + if (process_jump(line,6,&ent.offsets[4])) PRINTHELP() + } + } + SCRIPT_MSG("MessageBox: %d: \"%s\"",r,line.gettoken_str(2)); + if (line.getnumtokens()>4) SCRIPT_MSG(" (on %s goto %s)",line.gettoken_str(3),line.gettoken_str(4)); + SCRIPT_MSG("\n"); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_MESSAGEBOX + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_MESSAGEBOX not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_MESSAGEBOX + case TOK_CREATESHORTCUT: +#ifdef NSIS_SUPPORT_CREATESHORTCUT + ent.which=EW_CREATESHORTCUT; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + int s; + ent.offsets[4]=line.gettoken_int(5,&s)&0xff; + if (!s) + { + if (line.getnumtokens() > 5) + { + ERROR_MSG("CreateShortCut: cannot interpret icon index\n"); + PRINTHELP() + } + ent.offsets[4]=0; + } + if (line.getnumtokens() > 6) + { + int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINNOACTIVE/*SW_SHOWMINIMIZED doesn't work*/}; + int a=line.gettoken_enum(6,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0"); + if (a < 0) + { + ERROR_MSG("CreateShortCut: unknown show mode \"%s\"\n",line.gettoken_str(6)); + PRINTHELP() + } + ent.offsets[4]|=tab[a]<<8; + } + if (line.getnumtokens() > 7) + { + char *s=line.gettoken_str(7); + if (*s) + { + int c=0; + if (strstr(s,"ALT|")) ent.offsets[4]|=HOTKEYF_ALT << 24; + if (strstr(s,"CONTROL|")) ent.offsets[4]|=HOTKEYF_CONTROL << 24; + if (strstr(s,"EXT|")) ent.offsets[4]|=HOTKEYF_EXT << 24; + if (strstr(s,"SHIFT|")) ent.offsets[4]|=HOTKEYF_SHIFT << 24; + while (strstr(s,"|")) + { + s=strstr(s,"|")+1; + } + if ((s[0] == 'f' || s[0] == 'F') && (s[1] >= '1' && s[1] <= '9')) + { + c=VK_F1-1+atoi(s+1); + if (atoi(s+1) < 1 || atoi(s+1) > 24) + { + warning("CreateShortCut: F-key \"%s\" out of range (%s:%d)\n",s,curfilename,linecnt); + } + } + else if (s[0] >= 'a' && s[0] <= 'z' && !s[1]) + c=s[0]+'A'-'a'; + else if (((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= '0' && s[0] <= '9')) && !s[1]) + c=s[0]; + else + { + c=s[0]; + warning("CreateShortCut: unrecognized hotkey \"%s\" (%s:%d)\n",s,curfilename,linecnt); + } + ent.offsets[4] |= (c) << 16; + } + } + SCRIPT_MSG("CreateShortCut: \"%s\"->\"%s\" %s icon:%s,%d, showmode=0x%X, hotkey=0x%X\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3), + line.gettoken_str(4),ent.offsets[4]&0xff,(ent.offsets[4]>>8)&0xff,ent.offsets[4]>>16); + return add_entry(&ent); +#else//!NSIS_SUPPORT_CREATESHORTCUT + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_CREATESHORTCUT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_SUPPORT_CREATESHORTCUT +#ifdef NSIS_SUPPORT_HWNDS + case TOK_FINDWINDOW: + ent.which=EW_FINDWINDOW; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=add_string(line.gettoken_str(5)); + SCRIPT_MSG("FindWindow: output=%s, class=\"%s\", text=\"%s\" hwndparent=\"%s\" hwndafter=\"%s\"\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); + return add_entry(&ent); + case TOK_SENDMESSAGE: + ent.which=EW_SENDMESSAGE; + SCRIPT_MSG("SendMessage:"); + ent.offsets[0]=line.gettoken_enum(5,usrvars); + if (ent.offsets[0]>=0) + { + SCRIPT_MSG("(->%s)",line.gettoken_str(5)); + } + + ent.offsets[1]=add_string(line.gettoken_str(1)); + ent.offsets[2]=add_string(line.gettoken_str(2)); + ent.offsets[3]=add_string(line.gettoken_str(3)); + ent.offsets[4]=add_string(line.gettoken_str(4)); + + SCRIPT_MSG("(%s,%s,%s,%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_ISWINDOW: + ent.which=EW_ISWINDOW; + ent.offsets[0]=add_string(line.gettoken_str(1)); + if (process_jump(line,2,&ent.offsets[1])|| + process_jump(line,3,&ent.offsets[2])) PRINTHELP() + SCRIPT_MSG("IsWindow(%s): %s:%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_SETDLGITEMTEXT: + ent.which=EW_SETDLGITEMTEXT; + ent.offsets[0]=line.gettoken_int(1); + ent.offsets[1]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SetDlgItemText: item=%s text=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_HWNDS + case TOK_ISWINDOW: + case TOK_SENDMESSAGE: + case TOK_FINDWINDOW: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_HWNDS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_HWNDS + case TOK_DELETE: +#ifdef NSIS_SUPPORT_DELETE + { + int a=1; + ent.which=EW_DELETEFILE; + if (!stricmp(line.gettoken_str(a),"/REBOOTOK")) + { + a++; + ent.offsets[1]=1; +#ifndef NSIS_SUPPORT_MOVEONREBOOT + ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"); + PRINTHELP() +#endif + } + else if (line.gettoken_str(1)[0]=='/') + { + a=line.getnumtokens(); + } + if (line.getnumtokens() != a+1) PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + SCRIPT_MSG("Delete: %s\"%s\"\n",ent.offsets[1]?"/REBOOTOK ":"",line.gettoken_str(a)); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_DELETE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_DELETE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_DELETE + case TOK_RMDIR: +#ifdef NSIS_SUPPORT_RMDIR + { + int a=1; + ent.which=EW_RMDIR; + if (!stricmp(line.gettoken_str(1),"/r")) + { + if (line.getnumtokens() < 3) PRINTHELP() + a++; + ent.offsets[1]=1; + } + else if (line.gettoken_str(1)[0]=='/') PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + SCRIPT_MSG("RMDir: %s\"%s\"\n",ent.offsets[1]?"/r " : "",line.gettoken_str(a)); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_RMDIR + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RMDIR not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_RMDIR + case TOK_FILE: +#ifdef NSIS_SUPPORT_FILE + { + int a=1,attrib=0,rec=0; + if (!stricmp(line.gettoken_str(a),"/a")) + { + attrib=1; + a++; + } + if (!stricmp(line.gettoken_str(a),"/r")) + { + rec=1; + a++; + } + else if (!strnicmp(line.gettoken_str(a),"/oname=",7)) + { + char *on=line.gettoken_str(a)+7; + a++; + if (!*on||line.getnumtokens()!=a+1||strstr(on,"*") || strstr(on,"?")) PRINTHELP() + + int tf=0; + int v=do_add_file(line.gettoken_str(a), attrib, 0, linecnt,&tf,on); + if (v != PS_OK) return v; + if (tf > 1) PRINTHELP() + if (!tf) + { + ERROR_MSG("File: \"%s\" -> no files found.\n",line.gettoken_str(a)); + PRINTHELP() + } + + return PS_OK; + } + else if (line.gettoken_str(a)[0] == '/') PRINTHELP() + if (line.getnumtokens() no files found.\n",t); + PRINTHELP() + } + } + } + return PS_OK; +#else//!NSIS_SUPPORT_FILE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_FILE +#ifdef NSIS_SUPPORT_COPYFILES + case TOK_COPYFILES: + { + ent.which=EW_COPYFILES; + ent.offsets[2]=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_NOERRORUI|FOF_SIMPLEPROGRESS; + + int a=1; + int x; + for (x = 0; x < 2; x ++) + { + if (!stricmp(line.gettoken_str(a),"/SILENT")) + { + a++; + ent.offsets[2]&=~FOF_SIMPLEPROGRESS; + ent.offsets[2]|=FOF_SILENT; + } + else if (!stricmp(line.gettoken_str(a),"/FILESONLY")) + { + a++; + ent.offsets[2]|=FOF_FILESONLY; + } + else if (line.gettoken_str(a)[0]=='/') PRINTHELP() + else break; + } + ent.offsets[0]=add_string(line.gettoken_str(a)); + ent.offsets[1]=add_string(line.gettoken_str(a+1)); + int s; + int size_kb=line.gettoken_int(a+2,&s); + if (!s && line.gettoken_str(a+2)[0]) PRINTHELP() + section_add_size_kb(size_kb); + SCRIPT_MSG("CopyFiles: %s\"%s\" -> \"%s\", size=%iKB\n",ent.offsets[2]?"(silent) ":"", line.gettoken_str(a),line.gettoken_str(a+1),size_kb); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_COPYFILES + case TOK_COPYFILES: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_COPYFILES not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_COPYFILES + + case TOK_SETFILEATTRIBUTES: + { + #define MBD(x) {x,#x}, + struct + { + int id; + char *str; + } list[]= + { + MBD(FILE_ATTRIBUTE_NORMAL) + MBD(FILE_ATTRIBUTE_ARCHIVE) + MBD(FILE_ATTRIBUTE_HIDDEN) + MBD(FILE_ATTRIBUTE_OFFLINE) + MBD(FILE_ATTRIBUTE_READONLY) + MBD(FILE_ATTRIBUTE_SYSTEM) + MBD(FILE_ATTRIBUTE_TEMPORARY) + {FILE_ATTRIBUTE_NORMAL,"NORMAL"}, + {FILE_ATTRIBUTE_ARCHIVE,"ARCHIVE"}, + {FILE_ATTRIBUTE_HIDDEN,"HIDDEN"}, + {FILE_ATTRIBUTE_OFFLINE,"OFFLINE"}, + {FILE_ATTRIBUTE_READONLY,"READONLY"}, + {FILE_ATTRIBUTE_SYSTEM,"SYSTEM"}, + {FILE_ATTRIBUTE_TEMPORARY,"TEMPORARY"}, + {FILE_ATTRIBUTE_NORMAL,"0"}, + }; + #undef MBD + int r=0; + int x; + char *p=line.gettoken_str(2); + + while (*p) + { + char *np=p; + while (*np && *np != '|') np++; + if (*np) *np++=0; + for (x =0 ; x < sizeof(list)/sizeof(list[0]) && stricmp(list[x].str,p); x ++); + + if (x < sizeof(list)/sizeof(list[0])) + { + r|=list[x].id; + } + else PRINTHELP() + p=np; + } + ent.which=EW_SETFILEATTRIBUTES; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=r; + } + return add_entry(&ent); + case TOK_SLEEP: + { + ent.which=EW_SLEEP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("Sleep: %s ms\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_BRINGTOFRONT: + ent.which=EW_BRINGTOFRONT; + SCRIPT_MSG("BringToFront\n"); + return add_entry(&ent); + case TOK_HIDEWINDOW: + ent.which=EW_HIDEWINDOW; + SCRIPT_MSG("HideWindow\n"); + return add_entry(&ent); + case TOK_IFFILEEXISTS: + ent.which=EW_IFFILEEXISTS; + ent.offsets[0] = add_string(line.gettoken_str(1)); + if (process_jump(line,2,&ent.offsets[1]) || + process_jump(line,3,&ent.offsets[2])) PRINTHELP() + SCRIPT_MSG("IfFileExists: \"%s\" ? %s : %s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_QUIT: + ent.which=EW_QUIT; + SCRIPT_MSG("Quit\n"); + return add_entry(&ent); + case TOK_ABORT: + ent.which=EW_ABORT; + ent.offsets[0] = add_string(line.gettoken_str(1)); + SCRIPT_MSG("Abort: \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETDETAILSVIEW: + { + int v=line.gettoken_enum(1,"hide\0show\0"); + ent.which=EW_CHDETAILSVIEW; + if (v < 0) PRINTHELP() + ent.offsets[0] = v?SW_SHOWNA:SW_HIDE; + ent.offsets[1] = v?SW_HIDE:SW_SHOWNA; + SCRIPT_MSG("SetDetailsView: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_SETDETAILSPRINT: + ent.which=EW_UPDATETEXT; + ent.offsets[0] = -1; + ent.offsets[1] = line.gettoken_enum(1,"none\0listonly\0textonly\0both\0"); + if (ent.offsets[1] < 0) PRINTHELP() + if (!ent.offsets[1]) ent.offsets[1]=4; + SCRIPT_MSG("SetDetailsPrint: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETAUTOCLOSE: + ent.which=EW_SETWINDOWCLOSE; + ent.offsets[0] = line.gettoken_enum(1,"false\0true\0"); + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("SetAutoClose: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_IFERRORS: + ent.which=EW_IFERRORS; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + SCRIPT_MSG("IfErrors ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_CLEARERRORS: + ent.which=EW_IFERRORS; + SCRIPT_MSG("ClearErrors\n"); + return add_entry(&ent); + case TOK_SETERRORS: + ent.which=EW_IFERRORS; + ent.offsets[2]=1; + SCRIPT_MSG("SetErrors\n"); + return add_entry(&ent); +#ifdef NSIS_SUPPORT_STROPTS + case TOK_STRLEN: + ent.which=EW_STRLEN; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("StrLen %s \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_STRCPY: + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("StrCpy %s \"%s\" (%s) (%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_GETFUNCTIONADDR: + ent.which=EW_GETFUNCTIONADDR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=ns_func.add(line.gettoken_str(2),0); + ent.offsets[2]=-1; + ent.offsets[3]=-1; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("GetFunctionAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_GETLABELADDR: + ent.which=EW_GETLABELADDR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0 || process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=-1; + ent.offsets[3]=-1; + SCRIPT_MSG("GetLabelAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_GETCURRENTADDR: + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + { + char buf[32]; + wsprintf(buf,"%d",1+(uninstall_mode?build_uninst.code_size:build_header.common.num_entries)); + ent.offsets[1]=add_string(buf); + } + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[2]=-1; + ent.offsets[3]=-1; + SCRIPT_MSG("GetCurrentAddress: %s %s",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_STRCMP: + ent.which=EW_STRCMP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (process_jump(line,3,&ent.offsets[2]) || + process_jump(line,4,&ent.offsets[3])) PRINTHELP() + SCRIPT_MSG("StrCmp \"%s\" \"%s\" equal=%s, nonequal=%s\n",line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_GETDLLVERSIONLOCAL: + { + char buf[128]; + DWORD low, high; + DWORD s,d; + int flag=0; + s=GetFileVersionInfoSize(line.gettoken_str(1),&d); + if (s) + { + void *buf; + buf=(void*)GlobalAlloc(GPTR,s); + if (buf) + { + UINT uLen; + VS_FIXEDFILEINFO *pvsf; + if (GetFileVersionInfo(line.gettoken_str(1),0,s,buf) && VerQueryValue(buf,"\\",(void**)&pvsf,&uLen)) + { + low=pvsf->dwFileVersionLS; + high=pvsf->dwFileVersionMS; + flag=1; + } + GlobalFree(buf); + } + } + if (!flag) + { + ERROR_MSG("GetDLLVersionLocal: error reading version info from \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=line.gettoken_enum(2,usrvars); + wsprintf(buf,"%u",high); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=-1; + ent.offsets[3]=-1; + if (ent.offsets[0]<0) PRINTHELP() + add_entry(&ent); + + ent.offsets[0]=line.gettoken_enum(3,usrvars); + wsprintf(buf,"%u",low); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=-1; + ent.offsets[3]=-1; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetDLLVersionLocal: %s (%u,%u)->(%s,%s)\n", + line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); + } + return add_entry(&ent); + case TOK_GETFILETIMELOCAL: + { + char buf[129]; + DWORD high,low; + int flag=0; + HANDLE hFile=CreateFile(line.gettoken_str(1),0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + FILETIME ft; + if (GetFileTime(hFile,NULL,NULL,&ft)) + { + high=ft.dwHighDateTime; + low=ft.dwLowDateTime; + flag=1; + } + CloseHandle(hFile); + } + if (!flag) + { + ERROR_MSG("GetFileTimeLocal: error reading date from \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } + + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=line.gettoken_enum(2,usrvars); + wsprintf(buf,"%u",high); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=-1; + ent.offsets[3]=-1; + if (ent.offsets[0]<0) PRINTHELP() + add_entry(&ent); + + ent.offsets[0]=line.gettoken_enum(3,usrvars); + wsprintf(buf,"%u",low); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=-1; + ent.offsets[3]=-1; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetFileTimeLocal: %s (%u,%u)->(%s,%s)\n", + line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); + } + return add_entry(&ent); + +#else//!NSIS_SUPPORT_STROPTS + case TOK_GETDLLVERSIONLOCAL: + case TOK_GETFILETIMELOCAL: + case TOK_GETFUNCTIONADDR: + case TOK_GETLABELADDR: + case TOK_GETCURRENTADDR: + case TOK_STRLEN: + case TOK_STRCPY: + case TOK_STRCMP: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STROPTS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_STROPTS +#ifdef NSIS_SUPPORT_INIFILES + case TOK_DELETEINISEC: + case TOK_DELETEINISTR: + { + char *vname="
"; + ent.which=EW_WRITEINI; + ent.offsets[0]=add_string(line.gettoken_str(2)); // section name + if (line.getnumtokens() > 3) + { + vname=line.gettoken_str(3); + ent.offsets[1]=add_string(vname); // value name + } + else ent.offsets[1]=-1; + ent.offsets[2]=-1; + ent.offsets[3]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("DeleteINI%s: [%s] %s in %s\n",vname?"Str":"Sec", + line.gettoken_str(2),vname,line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_WRITEINISTR: + ent.which=EW_WRITEINI; + ent.offsets[0]=add_string(line.gettoken_str(2)); + ent.offsets[1]=add_string(line.gettoken_str(3)); + ent.offsets[2]=add_string(line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("WriteINIStr: [%s] %s=%s in %s\n", + line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_READINISTR: + ent.which=EW_READINISTR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(3)); + ent.offsets[2]=add_string(line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("ReadINIStr %s [%s]:%s from %s\n",line.gettoken_str(1),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(2)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_INIFILES + case TOK_DELETEINISEC: + case TOK_DELETEINISTR: + case TOK_WRITEINISTR: + case TOK_READINISTR: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INIFILES not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_INIFILES + case TOK_DETAILPRINT: + ent.which=EW_UPDATETEXT; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + SCRIPT_MSG("DetailPrint: \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); +#ifdef NSIS_SUPPORT_FNUTIL + case TOK_GETTEMPFILENAME: + ent.which=EW_GETTEMPFILENAME; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetTempFileName -> %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_GETFULLPATHNAME: + { + int a=0; + ent.which=EW_GETFULLPATHNAME; + if (line.getnumtokens()==4 && !stricmp(line.gettoken_str(1),"/SHORT")) a++; + else if (line.getnumtokens()==4 || *line.gettoken_str(1)=='/') PRINTHELP() + ent.offsets[0]=line.gettoken_enum(1+a,usrvars); + ent.offsets[1]=add_string(line.gettoken_str(2+a)); + ent.offsets[2]=!a; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetFullPathName: %s->%s (%d)\n", + line.gettoken_str(2+a),line.gettoken_str(1+a),a?"sfn":"lfn"); + } + return add_entry(&ent); + case TOK_SEARCHPATH: + ent.which=EW_SEARCHPATH; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SearchPath %s %s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); +#else + case TOK_SEARCHPATH: + case TOK_GETTEMPFILENAME: + case TOK_GETFULLPATHNAME: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FNUTIL not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + case TOK_GETDLLVERSION: +#ifdef NSIS_SUPPORT_GETDLLVERSION + ent.which=EW_GETDLLVERSION; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=line.gettoken_enum(2,usrvars); + ent.offsets[2]=line.gettoken_enum(3,usrvars); + if (ent.offsets[1]<0 || ent.offsets[2]<0) PRINTHELP() + SCRIPT_MSG("GetDLLVersion: %s->%s,%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_GETDLLVERSION + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETDLLVERSION not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_GETDLLVERSION + case TOK_GETFILETIME: +#ifdef NSIS_SUPPORT_GETFILETIME + ent.which=EW_GETFILETIME; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=line.gettoken_enum(2,usrvars); + ent.offsets[2]=line.gettoken_enum(3,usrvars); + if (ent.offsets[1]<0 || ent.offsets[2]<0) PRINTHELP() + SCRIPT_MSG("GetFileTime: %s->%s,%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_GETFILETIME + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETFILETIME not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_GETFILETIME +#ifdef NSIS_SUPPORT_INTOPTS + case TOK_INTOP: + ent.which=EW_INTOP; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[3]=line.gettoken_enum(3,"+\0-\0*\0/\0|\0&\0^\0~\0!\0||\0&&\0%\0"); + if (ent.offsets[0] < 0 || ent.offsets[3]<0 || ((ent.offsets[3] == 7 || ent.offsets[3]==8) && line.getnumtokens()>4)) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[3] != 7 && ent.offsets[3] != 8) ent.offsets[2]=add_string(line.gettoken_str(4)); + SCRIPT_MSG("IntOp: %s=%s%s%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_INTFMT: + ent.which=EW_INTFMT; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0]<0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + SCRIPT_MSG("IntFmt: %s->%s (fmt:%s)\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_INTCMP: + case TOK_INTCMPU: + ent.which=(which_token == TOK_INTCMP) ? EW_INTCMP : EW_INTCMPU; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (process_jump(line,3,&ent.offsets[2]) || + process_jump(line,4,&ent.offsets[3]) || + process_jump(line,5,&ent.offsets[4])) PRINTHELP() + SCRIPT_MSG("%s %s:%s equal=%s, < %s, > %s\n",line.gettoken_str(0), + line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_INTOPTS + case TOK_INTOP: + case TOK_INTCMP: + case TOK_INTFMT: + case TOK_INTCMPU: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INTOPTS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_INTOPTS +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + case TOK_READREGSTR: + case TOK_READREGDWORD: + { + ent.which=EW_READREGSTR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + int k=line.gettoken_enum(2,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); + if (ent.offsets[0] < 0 || k == -1) PRINTHELP() + ent.offsets[1]=(int)rootkey_tab[k]; + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + if (which_token == TOK_READREGDWORD) ent.offsets[4]=1; + else ent.offsets[4]=0; + if (line.gettoken_str(3)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); + + SCRIPT_MSG("%s %s %s\\%s\\%s\n",line.gettoken_str(0), + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return add_entry(&ent); + case TOK_DELETEREGVALUE: + case TOK_DELETEREGKEY: + { + int a=1; + if (which_token==TOK_DELETEREGKEY) + { + char *s=line.gettoken_str(a); + if (s[0] == '/') + { + if (stricmp(s,"/ifempty")) PRINTHELP() + a++; + ent.offsets[3]=1; + } + } + int k=line.gettoken_enum(a,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(a,rootkeys[1]); + if (k == -1) PRINTHELP() + ent.which=EW_DELREG; + ent.offsets[0]=(int)rootkey_tab[k]; + ent.offsets[1]=add_string(line.gettoken_str(a+1)); + ent.offsets[2]=(which_token==TOK_DELETEREGKEY)?-1:add_string(line.gettoken_str(a+2)); + if (line.gettoken_str(a+1)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); + if (which_token==TOK_DELETEREGKEY) + SCRIPT_MSG("DeleteRegKey: %s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1)); + else + SCRIPT_MSG("DeleteRegValue: %s\\%s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1),line.gettoken_str(a+2)); + } + return add_entry(&ent); + case TOK_WRITEREGSTR: + case TOK_WRITEREGEXPANDSTR: + case TOK_WRITEREGBIN: + case TOK_WRITEREGDWORD: + { + int k=line.gettoken_enum(1,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(1,rootkeys[1]); + if (k == -1) PRINTHELP() + ent.which=EW_WRITEREG; + ent.offsets[0]=(int)rootkey_tab[k]; + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (line.gettoken_str(2)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); + ent.offsets[2]=add_string(line.gettoken_str(3)); + if (which_token == TOK_WRITEREGSTR || which_token == TOK_WRITEREGEXPANDSTR) + { + SCRIPT_MSG("%s: %s\\%s\\%s=%s\n", + line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + if (which_token == TOK_WRITEREGEXPANDSTR) + { + ent.offsets[4]=0; + } + else ent.offsets[4]=1; + } + if (which_token == TOK_WRITEREGBIN) + { + char data[NSIS_MAX_STRLEN]; + char *p=line.gettoken_str(4); + int data_len=0; + while (*p) + { + int c; + int a,b; + a=*p; + if (a >= '0' && a <= '9') a-='0'; + else if (a >= 'a' && a <= 'f') a-='a'-10; + else if (a >= 'A' && a <= 'F') a-='A'-10; + else break; + b=*++p; + if (b >= '0' && b <= '9') b-='0'; + else if (b >= 'a' && b <= 'f') b-='a'-10; + else if (b >= 'A' && b <= 'F') b-='A'-10; + else break; + p++; + c=(a<<4)|b; + if (data_len >= NSIS_MAX_STRLEN) + { + ERROR_MSG("WriteRegBin: %d bytes of data exceeded\n",NSIS_MAX_STRLEN); + return PS_ERROR; + } + data[data_len++]=c; + } + if (*p) PRINTHELP() + SCRIPT_MSG("WriteRegBin: %s\\%s\\%s=%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + ent.offsets[3]=add_data(data,data_len); + if (ent.offsets[3] < 0) return PS_ERROR; + ent.offsets[4]=3; + } + if (which_token == TOK_WRITEREGDWORD) + { + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=2; + + SCRIPT_MSG("WriteRegDWORD: %s\\%s\\%s=%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + } + return add_entry(&ent); + case TOK_ENUMREGKEY: + case TOK_ENUMREGVAL: + { + ent.which=EW_REGENUM; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + int k=line.gettoken_enum(2,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); + if (ent.offsets[0] < 0 || k == -1) PRINTHELP() + ent.offsets[1]=(int)rootkey_tab[k]; + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=which_token == TOK_ENUMREGKEY; + if (line.gettoken_str(3)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); + SCRIPT_MSG("%s %s %s\\%s\\%s\n",which_token == TOK_ENUMREGKEY ? "EnumRegKey" : "EnumRegValue", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_REGISTRYFUNCTIONS + case TOK_READREGSTR: + case TOK_READREGDWORD: + case TOK_DELETEREGVALUE: + case TOK_DELETEREGKEY: + case TOK_WRITEREGSTR: + case TOK_WRITEREGEXPANDSTR: + case TOK_WRITEREGBIN: + case TOK_WRITEREGDWORD: + case TOK_ENUMREGKEY: + case TOK_ENUMREGVAL: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REGISTRYFUNCTIONS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_REGISTRYFUNCTIONS +#ifdef NSIS_SUPPORT_STACK + case TOK_EXCH: + { + int swapitem=1; + int save=line.gettoken_enum(1,usrvars); + ent.which=EW_PUSHPOP; + if (line.gettoken_str(1)[0] && save<0) + { + int s=0; + swapitem=line.gettoken_int(1,&s); + if (!s || swapitem <= 0) PRINTHELP() + } + if (save>=0) + { + SCRIPT_MSG("Exch(%s,0)\n",line.gettoken_str(1)); + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + ent.offsets[2]=0; + add_entry(&ent); + } + else SCRIPT_MSG("Exch(st(%d),0)\n",swapitem); + + ent.offsets[0]=0; + ent.offsets[1]=0; + ent.offsets[2]=swapitem; + + if (save>=0) + { + add_entry(&ent); + ent.offsets[0]=save; + ent.offsets[1]=1; + ent.offsets[2]=0; + } + } + return add_entry(&ent); + case TOK_PUSH: + ent.which=EW_PUSHPOP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + SCRIPT_MSG("Push: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_POP: + ent.which=EW_PUSHPOP; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=1; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("Pop: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_STACK + case TOK_POP: + case TOK_PUSH: + case TOK_EXCH: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STACK not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_STACK +#ifdef NSIS_SUPPORT_ENVIRONMENT + case TOK_READENVSTR: + ent.which=EW_READENVSTR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + { + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[0] < 0 || strlen(line.gettoken_str(2))<1) PRINTHELP() + } + ent.offsets[2]=1; + SCRIPT_MSG("ReadEnvStr: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_EXPANDENVSTRS: + ent.which=EW_READENVSTR; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=0; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("ExpandEnvStrings: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_ENVIRONMENT + case TOK_EXPANDENVSTRS: + case TOK_READENVSTR: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_ENVIRONMENT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_ENVIRONMENT +#ifdef NSIS_SUPPORT_FINDFIRST + case TOK_FINDFIRST: + ent.which=EW_FINDFIRST; + ent.offsets[0]=add_string(line.gettoken_str(3)); // filespec + ent.offsets[1]=line.gettoken_enum(2,usrvars); // out + ent.offsets[2]=line.gettoken_enum(1,usrvars); // handleout + if (ent.offsets[1] < 0 || ent.offsets[2] < 0) PRINTHELP() + SCRIPT_MSG("FindFirst: spec=\"%s\" handle=%s output=%s\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FINDNEXT: + ent.which=EW_FINDNEXT; + ent.offsets[0]=line.gettoken_enum(2,usrvars); + ent.offsets[1]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP() + SCRIPT_MSG("FindNext: handle=%s output=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FINDCLOSE: + ent.which=EW_FINDCLOSE; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("FindClose: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_FINDFIRST + case TOK_FINDCLOSE: + case TOK_FINDNEXT: + case TOK_FINDFIRST: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FINDFIRST not defined.\n", line.gettoken_str(0)); + return PS_ERROR; + +#endif//!NSIS_SUPPORT_FINDFIRST + + +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + case TOK_FILEOPEN: + { + ent.which=EW_FOPEN; + ent.offsets[3]=line.gettoken_enum(1,usrvars); // file handle + ent.offsets[0]=add_string(line.gettoken_str(2)); + ent.offsets[1]=0; //openmode + if (!stricmp(line.gettoken_str(3),"r")) + { + ent.offsets[1]=GENERIC_READ; + ent.offsets[2]=OPEN_EXISTING; + } + else if (!stricmp(line.gettoken_str(3),"w")) + { + ent.offsets[1]=GENERIC_WRITE; + ent.offsets[2]=CREATE_ALWAYS; + } + else if (!stricmp(line.gettoken_str(3),"a")) + { + ent.offsets[1]=GENERIC_WRITE|GENERIC_READ; + ent.offsets[2]=OPEN_ALWAYS; + } + + if (ent.offsets[3] < 0 || !ent.offsets[1]) PRINTHELP() + } + SCRIPT_MSG("FileOpen: %s as %s -> %s\n",line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILECLOSE: + ent.which=EW_FCLOSE; + ent.offsets[0]=line.gettoken_enum(1,usrvars); // file handle + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("FileClose: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILEREAD: + ent.which=EW_FGETS; + ent.offsets[0]=line.gettoken_enum(1,usrvars); // file handle + ent.offsets[1]=line.gettoken_enum(2,usrvars); // output string + ent.offsets[2]=add_string(line.gettoken_str(3)[0]?line.gettoken_str(3):"1023"); + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("FileRead: %s->%s (max:%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_FILEWRITE: + ent.which=EW_FPUTS; + ent.offsets[0]=line.gettoken_enum(1,usrvars); // file handle + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("FileWrite: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILEREADBYTE: + ent.which=EW_FGETS; + ent.offsets[0]=line.gettoken_enum(1,usrvars); // file handle + ent.offsets[1]=line.gettoken_enum(2,usrvars); // output string + ent.offsets[2]=add_string("1"); + ent.offsets[3]=1; + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("FileReadByte: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FILEWRITEBYTE: + ent.which=EW_FPUTS; + ent.offsets[0]=line.gettoken_enum(1,usrvars); // file handle + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=1; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("FileWriteByte: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILESEEK: + { + char *modestr; + int tab[3]={FILE_BEGIN,FILE_CURRENT,FILE_END}; + int mode=line.gettoken_enum(3,"SET\0CUR\0END\0"); + ent.which=EW_FSEEK; + ent.offsets[0]=line.gettoken_enum(1,usrvars); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[3]=line.gettoken_enum(4,usrvars); + + if (mode<0 && !line.gettoken_str(3)[0]) + { + mode=0; + modestr="SET"; + } + else modestr=line.gettoken_str(3); + + if (mode<0 || ent.offsets[0] < 0 || (ent.offsets[3]<0 && line.gettoken_str(4)[0])) PRINTHELP() + ent.offsets[2]=tab[mode]; + SCRIPT_MSG("FileSeek: fp=%s, ofs=%s, mode=%s, output=%s\n", + line.gettoken_str(1), + line.gettoken_str(2), + modestr, + line.gettoken_str(4)); + } + + return add_entry(&ent); +#else//!NSIS_SUPPORT_FILEFUNCTIONS + case TOK_FILEOPEN: + case TOK_FILECLOSE: + case TOK_FILESEEK: + case TOK_FILEREAD: + case TOK_FILEWRITE: + case TOK_FILEREADBYTE: + case TOK_FILEWRITEBYTE: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILEFUNCTIONS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; + +#endif//!NSIS_SUPPORT_FILEFUNCTIONS +#ifdef NSIS_SUPPORT_REBOOT + case TOK_REBOOT: + ent.which=EW_REBOOT; + ent.offsets[0]=0xbadf00d; + SCRIPT_MSG("Reboot! (WOW)\n"); + return add_entry(&ent); + case TOK_IFREBOOTFLAG: + ent.which=EW_IFREBOOTFLAG; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + SCRIPT_MSG("IfRebootFlag ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SETREBOOTFLAG: + ent.which=EW_SETREBOOTFLAG; + ent.offsets[0]=line.gettoken_enum(1,"false\0true\0"); + if (ent.offsets[0] < 0) PRINTHELP() + return add_entry(&ent); +#else//!NSIS_SUPPORT_REBOOT + case TOK_REBOOT: + case TOK_IFREBOOTFLAG: + case TOK_SETREBOOTFLAG: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REBOOT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_REBOOT +#ifdef NSIS_CONFIG_LOG + case TOK_LOGSET: + ent.which=EW_LOG; + ent.offsets[0]=1; + ent.offsets[1]=line.gettoken_enum(1,"off\0on\0"); + if (ent.offsets[1]<0) PRINTHELP() + + SCRIPT_MSG("LogSet: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_LOGTEXT: + ent.which=EW_LOG; + ent.offsets[0]=0; + ent.offsets[1]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("LogText \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_CONFIG_LOG + + case TOK_LOGSET: + case TOK_LOGTEXT: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_LOG not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_LOG +#ifdef NSIS_CONFIG_COMPONENTPAGE + case TOK_SECTIONSETTEXT: + if (uninstall_mode) + { + ERROR_MSG("Error: %s called in uninstall section.\n", line.gettoken_str(0)); + return PS_ERROR; + } + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + ent.offsets[2]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SectionSetText: %s=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETTEXT: + if (uninstall_mode) + { + ERROR_MSG("Error: %s called in uninstall section.\n", line.gettoken_str(0)); + return PS_ERROR; + } + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=1; + ent.offsets[2]=line.gettoken_enum(2,usrvars); + if (line.gettoken_str(2)[0] && ent.offsets[2]<0) PRINTHELP() + SCRIPT_MSG("SectionGetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONSETFLAGS: + if (uninstall_mode) + { + ERROR_MSG("Error: %s called in uninstall section.\n", line.gettoken_str(0)); + return PS_ERROR; + } + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=2; + ent.offsets[2]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SectionSetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETFLAGS: + if (uninstall_mode) + { + ERROR_MSG("Error: %s called in uninstall section.\n", line.gettoken_str(0)); + return PS_ERROR; + } + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=3; + ent.offsets[2]=line.gettoken_enum(2,usrvars); + if (line.gettoken_str(2)[0] && ent.offsets[2]<0) PRINTHELP() + SCRIPT_MSG("SectionGetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); +#else//!NSIS_CONFIG_COMPONENTPAGE + case TOK_SECTIONGETTEXT: + case TOK_SECTIONSETTEXT: + case TOK_SECTIONSETFLAGS: + case TOK_SECTIONGETFLAGS: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE + // Added by Amir Szekely 29th July 2002 + case TOK_SETBRANDINGIMAGE: +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + { + SCRIPT_MSG("SetBrandingImage: %s\n", line.gettoken_str(1)); + if (!branding_image_found) { + ERROR_MSG("Error: no branding image found in choosen UI!\n"); + return PS_ERROR; + } + ent.which=EW_SETBRANDINGIMAGE; + for (int i = 1; i < line.getnumtokens(); i++) + if (!strnicmp(line.gettoken_str(i),"/IMGID=",7)) + ent.offsets[1]=atoi(line.gettoken_str(i)+7); + else if (!stricmp(line.gettoken_str(i),"/RESIZETOFIT")) + ent.offsets[2]=1; + else if (!ent.offsets[0]) + ent.offsets[0]=add_string(line.gettoken_str(i)); + else + PRINTHELP(); + + if (!ent.offsets[1]) + ent.offsets[1]=branding_image_id; + } + return add_entry(&ent); +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif// NSIS_CONFIG_VISIBLE_SUPPORT + + // end of instructions + /////////////////////////////////////////////////////////////////////////////// + + default: break; + + } + ERROR_MSG("Error: doCommand: Invalid token \"%s\".\n",line.gettoken_str(0)); + return PS_ERROR; +} + +int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int linecnt, int *total_files, const char *name_override) +{ + char dir[1024]; + char newfn[1024], *s; + HANDLE h; + WIN32_FIND_DATA d; + strcpy(dir,lgss); + s=dir+strlen(dir); + while (s > dir && *s != '\\') s=CharPrev(dir,s); + *s=0; + + h = FindFirstFile(lgss,&d); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (recurse && strcmp(d.cFileName,"..") && strcmp(d.cFileName,".")) + { + entry ent={0,}; + int a; + int wd_save=strlen(cur_out_path); + + { + char *i=d.cFileName,*o=cur_out_path; + while (*o) o++; + if (o > cur_out_path && CharPrev(cur_out_path,o)[0] != '\\') *o++='\\'; + + while (*i) + { + char *ni=CharNext(i); + if (ni-i > 1) + { + int l=ni-i; + while (l--) + { + *o++=*i++; + } + } + else + { + char c=*i++; + *o++=c; + if (c == '$') *o++='$'; + } + } + *o=0; + } + + (*total_files)++; + ent.which=EW_CREATEDIR; + ent.offsets[0]=add_string(cur_out_path); + ent.offsets[1]=1; + a=add_entry(&ent); + if (a != PS_OK) + { + FindClose(h); + return a; + } + if (attrib) + { + ent.which=EW_SETFILEATTRIBUTES; + ent.offsets[0]=add_string(cur_out_path); + ent.offsets[1]=d.dwFileAttributes; + + a=add_entry(&ent); + if (a != PS_OK) + { + FindClose(h); + return a; + } + } + char spec[1024]; + sprintf(spec,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName); + SCRIPT_MSG("File: Descending to: \"%s\" -> \"%s\"\n",spec,cur_out_path); + strcat(spec,"\\*.*"); + a=do_add_file(spec,attrib,recurse,linecnt,total_files); + if (a != PS_OK) + { + FindClose(h); + return a; + } + + cur_out_path[wd_save]=0; + ent.which=EW_CREATEDIR; + ent.offsets[1]=1; + SCRIPT_MSG("File: Returning to: \"%s\" -> \"%s\"\n",dir,cur_out_path); + ent.offsets[0]=add_string(cur_out_path); + a=add_entry(&ent); + if (a != PS_OK) + { + FindClose(h); + return a; + } + } + } + else + { + HANDLE hFile,hFileMap; + DWORD len; + (*total_files)++; + sprintf(newfn,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName); + hFile=CreateFile(newfn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + ERROR_MSG("File: failed opening file \"%s\"\n",newfn); + return PS_ERROR; + } + hFileMap=NULL; + len = GetFileSize(hFile, NULL); + if (len && !(hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL))) + { + CloseHandle(hFile); + ERROR_MSG("File: failed creating mmap of \"%s\"\n",newfn); + return PS_ERROR; + } + char *filedata=NULL; + if (len) + { + filedata=(char*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); + if (!filedata) + { + if (hFileMap) CloseHandle(hFileMap); + CloseHandle(hFile); + ERROR_MSG("File: failed mmapping file \"%s\"\n",newfn); + return PS_ERROR; + } + } + + section_add_size_kb((len+1023)/1024); + if (name_override) SCRIPT_MSG("File: \"%s\"->\"%s\"",d.cFileName,name_override); + else SCRIPT_MSG("File: \"%s\"",d.cFileName); + if (!build_compress_whole) + if (build_compress) SCRIPT_MSG(" [compress]"); + fflush(stdout); + char buf[1024]; + int last_build_datablock_used=getcurdbsize(); + entry ent={0,}; + ent.which=EW_EXTRACTFILE; + ent.offsets[0]=build_overwrite; + if (name_override) + { + ent.offsets[1]=add_string(name_override); + } + else + { + char *i=d.cFileName,*o=buf; + while (*i) + { + char c=*i++; + *o++=c; + if (c == '$') *o++='$'; + } + *o=0; + ent.offsets[1]=add_string(buf); + } + ent.offsets[2]=add_data(filedata?filedata:"",len); + + if (filedata) UnmapViewOfFile(filedata); + if (hFileMap) CloseHandle(hFileMap); + + if (ent.offsets[2] < 0) + { + CloseHandle(hFile); + return PS_ERROR; + } + + { + DWORD s=getcurdbsize()-last_build_datablock_used; + if (s) s-=4; + if (s != len) SCRIPT_MSG(" %d/%d bytes\n",s,len); + else SCRIPT_MSG(" %d bytes\n",len); + } + + if (build_datesave || build_overwrite==0x3 /*ifnewer*/) + { + FILETIME ft; + if (GetFileTime(hFile,NULL,NULL,&ft)) + { + ent.offsets[3]=ft.dwLowDateTime; + ent.offsets[4]=ft.dwHighDateTime; + } + else + { + CloseHandle(hFile); + ERROR_MSG("File: failed getting file date from \"%s\"\n",newfn); + return PS_ERROR; + } + } + else + { + ent.offsets[3]=0xffffffff; + ent.offsets[4]=0xffffffff; + } + if (uninstall_mode) m_uninst_fileused++; + else m_inst_fileused++; + + CloseHandle(hFile); + int a=add_entry(&ent); + if (a != PS_OK) + { + FindClose(h); + return a; + } + if (attrib) + { + char tmp_path[1024]; + ent.which=EW_SETFILEATTRIBUTES; + if (name_override) + { + sprintf(tmp_path,"%s\\%s",cur_out_path,name_override); + } + else + { + sprintf(tmp_path,"%s\\%s",cur_out_path,buf); + } + ent.offsets[0]=add_string(tmp_path); + ent.offsets[1]=d.dwFileAttributes; + + a=add_entry(&ent); + if (a != PS_OK) + { + FindClose(h); + return a; + } + } + } + } while (FindNextFile(h,&d)); + FindClose(h); + } + return PS_OK; +} + diff --git a/Source/strlist.h b/Source/strlist.h new file mode 100644 index 00000000..e4782f8d --- /dev/null +++ b/Source/strlist.h @@ -0,0 +1,275 @@ +#ifndef _STRLIST_H_ +#define _STRLIST_H_ + +#include // for gcc + +class IGrowBuf +{ + public: + virtual int add(const void *data, int len)=0; + virtual void resize(int newlen)=0; + virtual int getlen()=0; + virtual void *get()=0; +}; + +class GrowBuf : public IGrowBuf +{ + public: + GrowBuf() { m_alloc=m_used=0; m_s=NULL; } + ~GrowBuf() { free(m_s); } + + int add(const void *data, int len) + { + if (len<=0) return 0; + resize(m_used+len); + memcpy((char*)m_s+m_used-len,data,len); + return m_used-len; + } + + void resize(int newlen) + { + int os=m_alloc; + m_used=newlen; + if (newlen > m_alloc) + { + void *n; + m_alloc = newlen*2 + 32768; + n = realloc(m_s, m_alloc); + if (!n) + { + extern FILE *g_output; + extern int g_display_errors; + if (g_display_errors) + { + fprintf(g_output,"\nack! realloc(%d) failed, trying malloc(%d)!\n",m_alloc,newlen); + fflush(g_output); + } + m_alloc=newlen; // try to malloc the minimum needed + n=malloc(m_alloc); + if (!n) + { + extern void quit(); + if (g_display_errors) + { + fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%d) failed.\n",m_alloc); + fflush(g_output); + } + quit(); + } + memcpy(n,m_s,min(newlen,os)); + free(m_s); + } + m_s=n; + } + if (!m_used && m_alloc > 65535) // only free if you resize to 0 and we're > 64k + { + m_alloc=0; + free(m_s); + m_s=NULL; + } + } + + int getlen() { return m_used; } + void *get() { return m_s; } + + private: + void *m_s; + int m_alloc; + int m_used; + +}; + +class StringList +{ +public: + StringList() { } + ~StringList() { } + + int add(const char *str, int case_sensitive) + { + int a=find(str,case_sensitive); + if (a >= 0 && case_sensitive!=-1) return a; + return gr.add(str,strlen(str)+1); + } + + // use 2 for case sensitive end-of-string matches too + int find(const char *str, int case_sensitive, int *idx=NULL) // returns -1 if not found + { + char *s=(char*)gr.get(); + int ml=gr.getlen(); + int offs=0; + if (idx) *idx=0; + while (offs < ml) + { + if ((case_sensitive && !strcmp(s+offs,str)) || + (!case_sensitive && !stricmp(s+offs,str))) + { + return offs; + } + if (case_sensitive==2 && + strlen(str) < strlen(s+offs) && // check for end of string + !strcmp(s+offs+strlen(s+offs)-strlen(str),str)) + { + return offs+strlen(s+offs)-strlen(str); + } + offs+=strlen(s+offs)+1; + if (idx) (*idx)++; + } + return -1; + } + + void delbypos(int pos) + { + char *s=(char*)gr.get(); + int len=strlen(s+pos)+1; + if (pos+len < gr.getlen()) memcpy(s+pos,s+pos+len,gr.getlen()-(pos+len)); + gr.resize(gr.getlen()-len); + } + + int idx2pos(int idx) + { + char *s=(char*)gr.get(); + int offs=0; + int cnt=0; + if (idx>=0) while (offs < gr.getlen()) + { + if (cnt++ == idx) return offs; + offs+=strlen(s+offs)+1; + } + return -1; + } + + char *get() { return (char*)gr.get(); } + int getlen() { return gr.getlen(); } +private: + GrowBuf gr; +}; + + +class DefineList +{ +public: + DefineList() { } + ~DefineList() { } + + int add(const char *str, const char *value="") + { + if (defines.find(str,0)>=0) return 1; + + defines.add(str,0); + values.add(value,-1); + return 0; + } + + int del(const char *str) + { + int id; + int v=defines.find(str,0,&id); + if (v<0) return 1; + id=values.idx2pos(id); + if (id<0)return 1; + defines.delbypos(v); + values.delbypos(id); + return 0; + } + + char *find(const char *str) // returns NULL if not found + { + int id; + int v=defines.find(str,0,&id); + if (v<0) return NULL; + v=values.idx2pos(id); + if (v<0) return NULL; + return (char*)values.get()+v; + } + + StringList defines, values; +}; + + +class MMapBuf : public IGrowBuf +{ + public: + MMapBuf() + { + m_hFile = INVALID_HANDLE_VALUE; + m_hFileMap = 0; + m_mapping=NULL; + m_gb_u=0; + m_alloc=m_used=0; + } + ~MMapBuf() + { + if (m_mapping) UnmapViewOfFile(m_mapping); + if (m_hFileMap) CloseHandle(m_hFileMap); + if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile); + } + + int add(const void *data, int len) + { + if (len<=0) return 0; + resize(getlen()+len); + memcpy((char*)get()+getlen()-len,data,len); + return getlen()-len; + } + + void resize(int newlen) + { + if (!m_gb_u && newlen < (16<<20)) // still in db mode + { + m_gb.resize(newlen); + return; + } + m_gb_u=1; + m_used=newlen; + if (newlen > m_alloc) + { + if (m_mapping) UnmapViewOfFile(m_mapping); + if (m_hFileMap) CloseHandle(m_hFileMap); + m_hFileMap=0; + m_mapping=NULL; + m_alloc = newlen + (16<<20); // add 16mb to top of mapping + if (m_hFile == INVALID_HANDLE_VALUE) + { + char buf[MAX_PATH],buf2[MAX_PATH]; + GetTempPath(MAX_PATH,buf); + GetTempFileName(buf,"nsd",0,buf2); + m_hFile=CreateFile(buf2,GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE,NULL); + } + if (m_hFile != INVALID_HANDLE_VALUE) + m_hFileMap=CreateFileMapping(m_hFile,NULL,PAGE_READWRITE,0,m_alloc,NULL); + if (m_hFileMap) + m_mapping=MapViewOfFile(m_hFileMap,FILE_MAP_WRITE,0,0,m_alloc); + if (!m_mapping) + { + extern FILE *g_output; + extern void quit(); extern int g_display_errors; + if (g_display_errors) + { + fprintf(g_output,"\nInternal compiler error #12345: error mmapping datablock to %d.\n",m_alloc); + fflush(g_output); + } + quit(); + } + if (m_gb.getlen()) + { + memcpy(m_mapping,m_gb.get(),m_gb.getlen()); + m_gb.resize(0); + } + } + } + + int getlen() { if (m_gb_u) return m_used; return m_gb.getlen(); } + void *get() { if (m_gb_u) return m_mapping; return m_gb.get(); } + + private: + GrowBuf m_gb; + int m_gb_u; + + HANDLE m_hFile, m_hFileMap; + void *m_mapping; + int m_alloc, m_used; +}; + + +#endif//_STRLIST_H_ diff --git a/Source/tokens.cpp b/Source/tokens.cpp new file mode 100644 index 00000000..3633db5e --- /dev/null +++ b/Source/tokens.cpp @@ -0,0 +1,226 @@ +#include +#include +#include + +#include "build.h" +#include "tokens.h" + +typedef struct +{ + int id; + char *name; + int num_parms; // minimum number of parameters + int opt_parms; // optional parmaters, usually 0, can be -1 for unlimited. + char *usage_str; +} tokenType; + + +static tokenType tokenlist[TOK__LAST] = +{ +{TOK_ABORT,"Abort",0,1,"[message]"}, +{TOK_ADDBRANDINGIMAGE,"AddBrandingImage",2,0,"(top|left) (height|width)"}, +{TOK_ADDSIZE,"AddSize",1,0,"size_to_add_to_section_in_kb"}, +{TOK_AUTOCLOSE,"AutoCloseWindow",1,0,"(false|true)"}, +{TOK_BGGRADIENT,"BGGradient",0,3,"(off | [top_color [bottom_color [text_color]]])"}, +{TOK_BRANDINGTEXT,"BrandingText",1,0,"installer_text"}, +{TOK_BRINGTOFRONT,"BringToFront",0,0,""}, +{TOK_CALL,"Call",1,0,"function_name | [:label_name]"}, +{TOK_CALLINSTDLL,"CallInstDLL",2,0,"dll_path_on_target.dll function"}, +{TOK_CAPTION,"Caption",1,0,"installer_caption"}, +{TOK_CHANGEUI,"ChangeUI",1,0,"ui_file.exe"}, +{TOK_CLEARERRORS,"ClearErrors",0,0,""}, +{TOK_COMPTEXT,"ComponentText",0,3,"[component_page_description] [component_subtext1] [component_subtext2]"}, +{TOK_GETDLLVERSION,"GetDLLVersion",3,0,"filename $(user_var: high output) $(user_var: low output)"}, +{TOK_GETDLLVERSIONLOCAL,"GetDLLVersionLocal",3,0,"localfilename $(user_var: high output) $(user_var: low output)"}, +{TOK_GETFILETIME,"GetFileTime",3,0,"file $(user_var: high output) $(user_var: low output)"}, +{TOK_GETFILETIMELOCAL,"GetFileTimeLocal",3,0,"localfile $(user_var: high output) $(user_var: low output)"}, +{TOK_COPYFILES,"CopyFiles",2,3,"[/SILENT] [/FILESONLY] source_path destination_path [total_size_in_kb]"}, +{TOK_CRCCHECK,"CRCCheck",1,0,"(on|force|off)"}, +{TOK_CREATEDIR,"CreateDirectory",1,0,"directory_name"}, +{TOK_CREATESHORTCUT,"CreateShortCut",2,5,"shortcut_name.lnk shortcut_target [parameters [icon_file [icon index [showmode [hotkey]]]]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED)\n hotkey=(ALT|CONTROL|EXT|SHIFT)|(F1-F24|A-Z)"}, +{TOK_DBOPTIMIZE,"SetDatablockOptimize",1,0,"(off|on)"}, +{TOK_DELETEINISEC,"DeleteINISec",2,0,"ini_file section_name"}, +{TOK_DELETEINISTR,"DeleteINIStr",3,0,"ini_file section_name entry_name"}, +{TOK_DELETEREGKEY,"DeleteRegKey",2,1,"[/ifempty] root_key subkey\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_DELETEREGVALUE,"DeleteRegValue",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_DELETE,"Delete",1,1,"[/REBOOTOK] filespec"}, +{TOK_DETAILPRINT,"DetailPrint",1,0,"message"}, +{TOK_DIRTEXT,"DirText",0,3,"[directory_page_description] [directory_page_subtext] [browse button text]"}, +{TOK_DIRSHOW,"DirShow",1,0,"(show|hide)"}, +{TOK_ROOTDIRINST,"AllowRootDirInstall",1,0,"(true|false)"}, +{TOK_CHECKBITMAP,"CheckBitmap",1,0,"local_bitmap.bmp"}, +{TOK_ENUMREGKEY,"EnumRegKey",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_ENUMREGVAL,"EnumRegValue",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_EXCH,"Exch",0,1,"[$(user_var)] | [stack_item_index]"}, +{TOK_EXEC,"Exec",1,0,"command_line"}, +{TOK_EXECWAIT,"ExecWait",1,1,"command_line [$(user_var: return value)]"}, +{TOK_EXECSHELL,"ExecShell",2,2,"(open|print|etc) command_line [parameters [showmode]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED)"}, +{TOK_EXPANDENVSTRS,"ExpandEnvStrings",2,0,"$(user_var: output) string"}, +{TOK_FINDWINDOW,"FindWindow",2,3,"$(user_var: handle output) WindowClass [WindowTitle] [Window_Parent] [Child_After]"}, +{TOK_FINDCLOSE,"FindClose",1,0,"$(user_var: handle input)"}, +{TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec"}, +{TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)"}, +{TOK_FILE,"File",1,-1,"([/a] [/r] filespec [...]|/oname=outfile one_file_only)"}, +{TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)"}, +{TOK_FILEERRORTEXT,"FileErrorText",0,1,"[text (can contain $0)]"}, +{TOK_FILEOPEN,"FileOpen",3,0,"$(user_var: handle output) filename openmode\n openmode=r|w|a"}, +{TOK_FILEREAD,"FileRead",2,1,"$(user_var: handle input) $(user_var: text output) [maxlen]"}, +{TOK_FILEWRITE,"FileWrite",2,0,"$(user_var: handle input) text"}, +{TOK_FILEREADBYTE,"FileReadByte",2,0,"$(user_var: handle input) $(user_var: bytevalue output)"}, +{TOK_FILEWRITEBYTE,"FileWriteByte",2,0,"$(user_var: handle input) bytevalue"}, +{TOK_FILESEEK,"FileSeek",2,2,"$(user_var: handle input) offset [mode] [$(user_var: new position output)]\n mode=SET|CUR|END"}, +{TOK_FUNCTION,"Function",1,0,"function_name"}, +{TOK_FUNCTIONEND,"FunctionEnd",0,0,""}, +{TOK_SEARCHPATH,"SearchPath",2,0,"$(user_var: result) filename"}, +{TOK_GETFULLPATHNAME,"GetFullPathName",2,1,"[/SHORT] $(user_var: result) path_or_file"}, +{TOK_GETTEMPFILENAME,"GetTempFileName",1,0,"$(user_var: name output)"}, +{TOK_HIDEWINDOW,"HideWindow",0,0,""}, +{TOK_ICON,"Icon",1,0,"local_icon.ico"}, +{TOK_IFERRORS,"IfErrors",1,1,"label_to_goto_if_errors [label_to_goto_if_no_errors]"}, +{TOK_IFFILEEXISTS,"IfFileExists",2,1,"filename label_to_goto_if_file_exists [label_to_goto_otherwise]"}, +{TOK_IFREBOOTFLAG,"IfRebootFlag",1,1,"jump_if_set [jump_if_not_set]"}, +{TOK_INSTALLDIRREGKEY,"InstallDirRegKey",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_INSTCOLORS,"InstallColors",1,1,"(/windows | (foreground_color background_color))"}, +{TOK_INSTDIR,"InstallDir",1,0,"default_install_directory"}, +{TOK_INSTPROGRESSFLAGS,"InstProgressFlags",0,-1,"[flag [...]]\n flag={smooth|colored}"}, +{TOK_INSTTYPE,"InstType",1,0,"(/NOCUSTOM|/CUSTOMSTRING=CustomStr|TypeName)"}, +{TOK_INTOP,"IntOp",3,1,"$(user_var: result) val1 OP [val2]\n OP=(+ - * / % | & ^ ~ ! || &&)"}, +{TOK_INTCMP,"IntCmp",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"}, +{TOK_INTCMPU,"IntCmpU",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]"}, +{TOK_INTFMT,"IntFmt",3,0,"$(user_var: output) format_string input"}, +{TOK_ISWINDOW,"IsWindow",2,1,"hwnd jump_if_window [jump_if_not_window]"}, +{TOK_GOTO,"Goto",1,0,"label"}, +{TOK_LICENSEDATA,"LicenseData",1,0,"local_file_that_has_license_text.txt"}, +{TOK_LICENSETEXT,"LicenseText",1,1,"license_page_description [license_button_text]"}, +{TOK_LICENSEBKCOLOR,"LicenseBkColor",1,0,"background_color"}, +{TOK_LOGSET,"LogSet",1,0,"on|off"}, +{TOK_LOGTEXT,"LogText",1,0,"text"}, +{TOK_MESSAGEBOX,"MessageBox",2,4,"mode messagebox_text [return_check label_to_goto_if_equal [return_check2 label2]]\n mode=modeflag[|modeflag[|modeflag[...]]]\n " + "modeflag=(MB_ABORTRETRYIGNORE|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_YESNO|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND|MB_RIGHT"}, +{TOK_NOP,"Nop",0,0,""}, +{TOK_NAME,"Name",1,0,"installer_name"}, +{TOK_OUTFILE,"OutFile",1,0,"install_output.exe"}, +{TOK_POP,"Pop",1,0,"$(user_var: output)"}, +{TOK_PUSH,"Push",1,0,"string"}, +{TOK_QUIT,"Quit",0,0,""}, +{TOK_READINISTR,"ReadINIStr",4,0,"$(user_var: output) ini_file section entry_name"}, +{TOK_READREGDWORD,"ReadRegDWORD",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_READREGSTR,"ReadRegStr",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_READENVSTR,"ReadEnvStr",2,0,"$(user_var: output) name"}, +{TOK_REBOOT,"Reboot",0,0,""}, +{TOK_REGDLL,"RegDLL",1,1,"dll_path_on_target.dll [entrypoint_symbol]"}, +{TOK_RENAME,"Rename",2,1,"[/REBOOTOK] source_file destination_file"}, +{TOK_RET,"Return",0,0,""}, +{TOK_RMDIR,"RMDir",1,1,"[/r] directory_name"}, +{TOK_SECTION,"Section",0,3,"[/e] [section_name|-section_name] [section index output]"}, +{TOK_SUBSECTION,"SubSection",1,1,"[/e] subsection_name"}, +{TOK_SUBSECTIONEND,"SubSectionEnd",0,0,""}, +{TOK_SECTIONSETFLAGS,"SectionSetFlags",2,0,"section_index flags"}, +{TOK_SECTIONGETFLAGS,"SectionGetFlags",2,0,"section_index $(user_var: output flags)"}, +{TOK_SECTIONGETTEXT,"SectionGetText",2,0,"section_index $(user_var: output text)"}, +{TOK_SECTIONSETTEXT,"SectionSetText",2,0,"section_index text_string"}, +{TOK_SECTIONEND,"SectionEnd",0,0,""}, +{TOK_SECTIONIN,"SectionIn",1,-1,"InstTypeIdx [InstTypeIdx [...]]"}, +{TOK_SENDMESSAGE,"SendMessage",4,1,"hwnd message wparam lparam [$(user_var: return value)]"}, +{TOK_SETAUTOCLOSE,"SetAutoClose",1,0,"(false|true)"}, +{TOK_SETBRANDINGIMAGE,"SetBrandingImage",1,2,"[/IMGID=image_item_id_in_dialog] [/RESIZETOFIT] bitmap.bmp"}, +{TOK_SETCOMPRESS,"SetCompress",1,0,"(off|auto|force)"}, +{TOK_SETCOMPRESSOR,"SetCompressor",1,0,"(zlib|bzip2)"}, +{TOK_SETDATESAVE,"SetDateSave",1,0,"(off|on)"}, +{TOK_SETDETAILSVIEW,"SetDetailsView",1,0,"(hide|show)"}, +{TOK_SETDETAILSPRINT,"SetDetailsPrint",1,0,"(none|listonly|textonly|both)"}, +{TOK_SETFILEATTRIBUTES,"SetFileAttributes",2,0,"file attribute[|attribute[...]]\n attribute=(NORMAL|ARCHIVE|HIDDEN|OFFLINE|READONLY|SYSTEM|TEMPORARY|0)"}, +{TOK_SETFONT,"SetFont",2,0,"font_face_name font_size"}, +{TOK_SETERRORS,"SetErrors",0,0,""}, +{TOK_SETDLGITEMTEXT,"SetDlgItemText",2,0,"item text"}, +{TOK_SETOUTPATH,"SetOutPath",1,0,"output_path"}, +{TOK_SETOVERWRITE,"SetOverwrite",1,0,"(on|off|try|ifnewer)"}, +{TOK_SETREBOOTFLAG,"SetRebootFlag",1,0,"true|false"}, +{TOK_SETSHELLVARCONTEXT,"SetShellVarContext",1,0,"all|current"}, +{TOK_SHOWDETAILS,"ShowInstDetails",1,0,"(hide|show|nevershow)"}, +{TOK_SHOWDETAILSUNINST,"ShowUninstDetails",1,0,"(hide|show|nevershow)"}, +{TOK_SILENTINST,"SilentInstall",1,0,"(normal|silent|silentlog)"}, +{TOK_SILENTUNINST,"SilentUnInstall",1,0,"(normal|silent)"}, +{TOK_SLEEP,"Sleep",1,0,"sleep_time_in_ms"}, +{TOK_STRCMP,"StrCmp",3,1,"str1 str2 label_to_goto_if_equal [label_to_goto_if_not]"}, +{TOK_STRCPY,"StrCpy",2,2,"$(user_var: output) str [maxlen] [startoffset]"}, +{TOK_STRLEN,"StrLen",2,0,"$(user_var: length output) str"}, +{TOK_SUBCAPTION,"SubCaption",2,0,"page_number(0-4) new_subcaption"}, +{TOK_UNINSTALLEXENAME,"UninstallExeName",0,0,"no longer supported, use WriteUninstaller from section."}, +{TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico"}, +{TOK_UNINSTTEXT,"UninstallText",1,1,"Text_to_go_on_uninstall page [subtext]"}, +{TOK_UNINSTCAPTION,"UninstallCaption",1,0,"uninstaller_caption"}, +{TOK_UNINSTSUBCAPTION,"UninstallSubCaption",2,0,"page_number(0-2) new_subcaption"}, +{TOK_UNREGDLL,"UnRegDLL",1,0,"dll_path_on_target.dll"}, +{TOK_WINDOWICON,"WindowIcon",1,0,"on|off"}, +{TOK_WRITEINISTR,"WriteINIStr",4,0,"ini_file section_name entry_name new_value"}, +{TOK_WRITEREGBIN,"WriteRegBin",4,0,"rootkey subkey entry_name hex_string_like_12848412AB\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_WRITEREGDWORD,"WriteRegDWORD",4,0,"rootkey subkey entry_name new_value_dword\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_WRITEREGSTR,"WriteRegStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_WRITEREGEXPANDSTR,"WriteRegExpandStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)"}, +{TOK_WRITEUNINSTALLER,"WriteUninstaller",1,0,"uninstall_exe_name"}, +{TOK_XPSTYLE, "XPStyle",1,0,"(on|off)"}, +{TOK_P_PACKEXEHEADER,"!packhdr",2,0,"temp_file_name command_line_to_compress_that_temp_file"}, +{TOK_P_SYSTEMEXEC,"!system",1,2,"command (<|>|<>|=|ignore) retval"}, +{TOK_P_INCLUDE,"!include",1,0,"filename.nsi"}, +{TOK_P_CD,"!cd",1,0,"absolute_or_relative_new_directory"}, +{TOK_P_IFDEF,"!ifdef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]"}, +{TOK_P_IFNDEF,"!ifndef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]"}, +{TOK_P_ENDIF,"!endif",0,0,""}, +{TOK_P_DEFINE,"!define",1,1,"symbol [value]"}, +{TOK_P_UNDEF,"!undef",1,1,"symbol [value]"}, +{TOK_P_ELSE,"!else",0,-1,"[ifdef|ifndef symbol [|symbol2 [& symbol3 [...]]]]"}, +{TOK_P_ECHO,"!echo",1,0,"message"}, +{TOK_P_WARNING,"!warning",0,1,"[warning_message]"}, +{TOK_P_ERROR,"!error",0,1,"[error_message]"}, + +{TOK_P_VERBOSE,"!verbose",1,0,"verbose_level"}, + +{TOK_P_MACRO,"!macro",1,-1,"macroname [parms ...]"}, +{TOK_P_MACROEND,"!macroend",0,0,""}, +{TOK_P_INSERTMACRO,"!insertmacro",1,-1,"macroname [parms ...]"}, + + +{TOK_MISCBUTTONTEXT,"MiscButtonText",0,4,"[back button text] [next button text] [cancel button text] [close button text]"}, +{TOK_DETAILSBUTTONTEXT,"DetailsButtonText",0,1,"[details button text]"}, +{TOK_UNINSTBUTTONTEXT,"UninstallButtonText",0,1,"[uninstall button text]"}, +{TOK_INSTBUTTONTEXT,"InstallButtonText",0,1,"[install button text]"}, +{TOK_SPACETEXTS,"SpaceTexts",0,2,"[space required text] [space available text]"}, +{TOK_COMPLETEDTEXT,"CompletedText",0,1,"[completed text]"}, + +{TOK_GETFUNCTIONADDR,"GetFunctionAddress",2,0,"output function"}, +{TOK_GETLABELADDR,"GetLabelAddress",2,0,"output label"}, +{TOK_GETCURRENTADDR,"GetCurrentAddress",1,0,"output"}, + +}; + +void CEXEBuild::print_help(char *commandname) +{ + int x; + for (x = 0; x < TOK__LAST; x ++) + { + if (!commandname || !stricmp(tokenlist[x].name,commandname)) + { + ERROR_MSG("%s%s %s\n",commandname?"Usage: ":"",tokenlist[x].name,tokenlist[x].usage_str); + if (commandname) break; + } + } + if (x == TOK__LAST && commandname)\ + { + ERROR_MSG("Invalid command \"%s\"\n",commandname); + } + +} + +int CEXEBuild::get_commandtoken(char *s, int *np, int *op) +{ + int x; + for (x = 0; x < TOK__LAST; x ++) + if (!stricmp(tokenlist[x].name,s)) + { + *np=tokenlist[x].num_parms; + *op=tokenlist[x].opt_parms; + return tokenlist[x].id; + } + return -1; +} diff --git a/Source/tokens.h b/Source/tokens.h new file mode 100644 index 00000000..9ff27373 --- /dev/null +++ b/Source/tokens.h @@ -0,0 +1,192 @@ +#ifndef _TOKENS_H_ +#define _TOKENS_H_ + +// the order of these two lists no longer needs to match. -J +enum +{ + // header setting tokens + TOK_NAME, + TOK_CAPTION, + TOK_UNINSTCAPTION, + TOK_ICON, + TOK_UNINSTICON, + TOK_CHECKBITMAP, + TOK_WINDOWICON, + TOK_DIRTEXT, + TOK_COMPTEXT, + TOK_LICENSETEXT, + TOK_LICENSEDATA, + TOK_LICENSEBKCOLOR, + TOK_UNINSTTEXT, + TOK_SILENTINST, + TOK_SILENTUNINST, + TOK_INSTTYPE, + TOK_OUTFILE, + TOK_INSTDIR, + TOK_INSTALLDIRREGKEY, + TOK_UNINSTALLEXENAME, + TOK_CRCCHECK, + TOK_AUTOCLOSE, + TOK_SHOWDETAILS, + TOK_SHOWDETAILSUNINST, + TOK_DIRSHOW, + TOK_ROOTDIRINST, + TOK_BGGRADIENT, + TOK_INSTCOLORS, + TOK_SUBCAPTION, + TOK_UNINSTSUBCAPTION, + TOK_BRANDINGTEXT, + TOK_FILEERRORTEXT, + TOK_INSTPROGRESSFLAGS, + TOK_XPSTYLE, + TOK_CHANGEUI, + TOK_ADDBRANDINGIMAGE, + TOK_SETFONT, + TOK_SETCOMPRESSOR, + + TOK_MISCBUTTONTEXT, + TOK_DETAILSBUTTONTEXT, + TOK_UNINSTBUTTONTEXT, + TOK_INSTBUTTONTEXT, + TOK_SPACETEXTS, + TOK_COMPLETEDTEXT, + + // system "preprocessor"ish tokens + TOK_P_IFDEF, + TOK_P_IFNDEF, + TOK_P_ELSE, + TOK_P_ENDIF, + TOK_P_DEFINE, + TOK_P_UNDEF, + TOK_P_PACKEXEHEADER, + TOK_P_SYSTEMEXEC, + TOK_P_INCLUDE, + TOK_P_CD, + TOK_P_ECHO, + TOK_P_WARNING, + TOK_P_ERROR, + + TOK_P_VERBOSE, + + TOK_P_MACRO, + TOK_P_MACROEND, + TOK_P_INSERTMACRO, + + // section/function shit + TOK_SECTION, + TOK_SECTIONEND, + TOK_SECTIONIN, + TOK_SUBSECTION, + TOK_SUBSECTIONEND, + TOK_FUNCTION, + TOK_FUNCTIONEND, + TOK_ADDSIZE, + + // flag setters + TOK_SETDATESAVE, + TOK_SETOVERWRITE, + TOK_SETCOMPRESS, + TOK_DBOPTIMIZE, + + // instructions + TOK_NOP, + TOK_GOTO, + TOK_RET, + TOK_CALL, + TOK_SETOUTPATH, + TOK_CREATEDIR, + TOK_EXEC, + TOK_EXECWAIT, + TOK_EXECSHELL, + TOK_CALLINSTDLL, + TOK_REGDLL, + TOK_UNREGDLL, + TOK_RENAME, + TOK_MESSAGEBOX, + TOK_DELETEREGVALUE, + TOK_DELETEREGKEY, + TOK_WRITEREGSTR, + TOK_WRITEREGEXPANDSTR, + TOK_WRITEREGBIN, + TOK_WRITEREGDWORD, + TOK_DELETEINISEC, + TOK_DELETEINISTR, + TOK_WRITEINISTR, + TOK_CREATESHORTCUT, + TOK_FINDWINDOW, + TOK_DELETE, + TOK_RMDIR, + TOK_FILE, + TOK_COPYFILES, + TOK_SETFILEATTRIBUTES, + TOK_SLEEP, + TOK_BRINGTOFRONT, + TOK_HIDEWINDOW, + TOK_IFFILEEXISTS, + TOK_ABORT, + TOK_QUIT, + TOK_SETDETAILSVIEW, + TOK_SETDETAILSPRINT, + TOK_SETAUTOCLOSE, + TOK_IFERRORS, + TOK_CLEARERRORS, + TOK_SETERRORS, + TOK_STRCPY, + TOK_STRCMP, + TOK_GETTEMPFILENAME, + TOK_GETFUNCTIONADDR, + TOK_GETLABELADDR, + TOK_GETCURRENTADDR, + TOK_READINISTR, + TOK_READREGSTR, + TOK_READREGDWORD, + TOK_READENVSTR, + TOK_EXPANDENVSTRS, + TOK_DETAILPRINT, + TOK_SEARCHPATH, + TOK_GETDLLVERSION, + TOK_GETDLLVERSIONLOCAL, + TOK_GETFILETIME, + TOK_GETFILETIMELOCAL, + TOK_STRLEN, + TOK_INTOP, + TOK_INTCMP, + TOK_INTCMPU, + TOK_INTFMT, + TOK_ENUMREGKEY, + TOK_ENUMREGVAL, + TOK_PUSH, + TOK_POP, + TOK_EXCH, + TOK_SENDMESSAGE, + TOK_ISWINDOW, + TOK_SETDLGITEMTEXT, + TOK_FINDFIRST, + TOK_FINDNEXT, + TOK_FINDCLOSE, + TOK_FILEOPEN, + TOK_FILECLOSE, + TOK_FILEREAD, + TOK_FILEWRITE, + TOK_FILEREADBYTE, + TOK_FILEWRITEBYTE, + TOK_FILESEEK, + TOK_GETFULLPATHNAME, + TOK_REBOOT, + TOK_IFREBOOTFLAG, + TOK_SETREBOOTFLAG, + TOK_WRITEUNINSTALLER, + TOK_LOGSET, + TOK_LOGTEXT, + TOK_SETBRANDINGIMAGE, + TOK_SECTIONSETTEXT, + TOK_SECTIONGETTEXT, + TOK_SECTIONSETFLAGS, + TOK_SECTIONGETFLAGS, + TOK_SETSHELLVARCONTEXT, + + + TOK__LAST +}; + +#endif//_TOKENS_H_ \ No newline at end of file diff --git a/Source/util.cpp b/Source/util.cpp new file mode 100644 index 00000000..95cf1ac0 --- /dev/null +++ b/Source/util.cpp @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include "exedata.h" +#include "exehead/fileform.h" +#include "util.h" +#include "strlist.h" + +int g_dopause=0; +extern int g_display_errors; +extern FILE *g_output; + + +void dopause(void) +{ + if (g_dopause) + { + if (g_display_errors) fprintf(g_output,"MakeNSIS done - hit enter to close..."); + fflush(stdout); + int a; + while ((a=_getch()) != '\r' && a != 27/*esc*/); + } +} + +// Returns 0 if everything is OK +// Returns -1 the bitmap file is invalid or has the wrong size +int update_bitmap(CResourceEditor* re, WORD id, char* filename, int width/*=0*/, int height/*=0*/) { + FILE *f = fopen(filename, "rb"); + if (!f) return -1; + + if (fgetc(f) != 'B' || fgetc(f) != 'M') { + fclose(f); + return -1; + } + + if (width != 0) { + LONG biWidth; + fseek(f, 18, SEEK_SET); // Seek to the width member of the header + fread(&biWidth, sizeof(LONG), 1, f); + if (width != biWidth) { + fclose(f); + return -1; + } + } + + if (height != 0) { + LONG biHeight; + fseek(f, 22, SEEK_SET); // Seek to the height member of the header + fread(&biHeight, sizeof(LONG), 1, f); + if (height != abs(biHeight)) { + fclose(f); + return -1; // Bitmap height can be negative too... + } + } + + DWORD dwSize; + fseek(f, 2, SEEK_SET); + fread(&dwSize, sizeof(DWORD), 1, f); + dwSize -= 14; + + unsigned char* bitmap = (unsigned char*)malloc(dwSize); + if (!bitmap) throw bad_alloc(); + + fseek(f, 14, SEEK_SET); + if (fread(bitmap, 1, dwSize, f) != dwSize) { + fclose(f); + return -1; + } + fclose(f); + + re->UpdateResource(RT_BITMAP, MAKEINTRESOURCE(id), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), bitmap, dwSize); + + return 0; +} + +// Added by Amir Szekely 8th July 2002 +// Icon editing structures +typedef struct { + WORD wReserved; + WORD wIsIcon; + WORD wCount; +} IconGroupHeader; + +typedef struct { + BYTE bWidth; + BYTE bHeight; + BYTE bPaletteEntries; + BYTE bReserved; + WORD wPlanes; + WORD wBitsPerPixel; + DWORD dwRawSize; + DWORD dwImageOffset; +} FileIconGroupEntry; + +typedef struct { + BYTE bWidth; + BYTE bHeight; + BYTE bPaletteEntries; + BYTE bReserved; + WORD wPlanes; + WORD wBitsPerPixel; + DWORD dwRawSize; + WORD wRsrcId; +} RsrcIconGroupEntry; + +#define SIZEOF_RSRC_ICON_GROUP_ENTRY 14 + +// Added by Amir Szekely 8th July 2002 +// replace_icon, must get an initialized resource editor +// return values: +// 0 - All OK +// -1 - Bad icon file +int replace_icon(CResourceEditor* re, WORD wIconId, char* filename) +{ + FILE* f = fopen(filename, "rb"); + if (!f) return -1; + + IconGroupHeader igh; + fread(&igh, sizeof(IconGroupHeader), 1, f); + + if (igh.wIsIcon != 1 && igh.wReserved != 0) return -1; + + BYTE* rsrcIconGroup = (BYTE*)malloc(sizeof(IconGroupHeader) + igh.wCount*SIZEOF_RSRC_ICON_GROUP_ENTRY); + if (!rsrcIconGroup) throw bad_alloc(); + + CopyMemory(rsrcIconGroup, &igh, sizeof(IconGroupHeader)); + + RsrcIconGroupEntry* ige = (RsrcIconGroupEntry*)(rsrcIconGroup + sizeof(IconGroupHeader)); + + int iNewIconSize = 0; + + for (int i = 0; i < igh.wCount; i++) { + fread(ige, sizeof(FileIconGroupEntry)-sizeof(DWORD), 1, f); + ige->wRsrcId = i+1; + + DWORD dwOffset; + fread(&dwOffset, sizeof(DWORD), 1, f); + + fpos_t pos; + fgetpos(f, &pos); + + if (fseek(f, dwOffset, SEEK_SET)) return -1; + BYTE* iconData = (BYTE*)malloc(ige->dwRawSize); + if (!iconData) throw bad_alloc(); + fread(iconData, sizeof(BYTE), ige->dwRawSize, f); + re->UpdateResource(RT_ICON, MAKEINTRESOURCE(i+1), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), iconData, ige->dwRawSize); + free(iconData); + + fsetpos(f, &pos); + + // Every icon entry should be 8 aligned + iNewIconSize += ((ige->dwRawSize%8 == 0) ? ige->dwRawSize : ige->dwRawSize - (ige->dwRawSize%8) + 8); + + // Seems like the compiler refuses to increase the pointer by just 14. + // If you'll replace this line by ige++ you will get unwanted results. + ige = (RsrcIconGroupEntry*)((BYTE*)ige + SIZEOF_RSRC_ICON_GROUP_ENTRY); + } + + fclose(f); + + re->UpdateResource(RT_GROUP_ICON, MAKEINTRESOURCE(wIconId), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), rsrcIconGroup, sizeof(IconGroupHeader) + igh.wCount*SIZEOF_RSRC_ICON_GROUP_ENTRY); + + icondata_size = iNewIconSize; + + return 0; +} + +// Added by Amir Szekely 8th July 2002 +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +// returns the data of the uninstaller icon that should replace the installer icon data +// return values: +// 0 - Bad icon file +// Anything else - Pointer to the uninstaller icon data +unsigned char* generate_uninstall_icon_data(char* filename) +{ + int i; + + FILE* f = fopen(filename, "rb"); + if (!f) return 0; + + IconGroupHeader igh; + if (!fread(&igh, sizeof(IconGroupHeader), 1, f)) return 0; + + if (igh.wIsIcon != 1 && igh.wReserved != 0) return 0; + + int iNewIconSize = 0; + FileIconGroupEntry ige; + + DWORD* offsets = (DWORD*)malloc(sizeof(DWORD)*igh.wCount); + DWORD* rawSizes = (DWORD*)malloc(sizeof(DWORD)*igh.wCount); + if (!offsets || !rawSizes) throw bad_alloc(); + + for (i = 0; i < igh.wCount; i++) { + if (!fread(&ige, sizeof(FileIconGroupEntry), 1, f)) return 0; + offsets[i] = ige.dwImageOffset; + rawSizes[i] = ige.dwRawSize; + iNewIconSize += ige.dwRawSize; + } + + // First DWORD tells how many icons this array contains + // Before each icon come two DWORDs, one for size and the other for offset (set later) + iNewIconSize += sizeof(DWORD)*(1 + igh.wCount*2); + + BYTE* pbUninstIcon = (BYTE*)malloc(iNewIconSize); + if (!pbUninstIcon) throw bad_alloc(); + + BYTE* seeker = pbUninstIcon; + + *(DWORD*)seeker = igh.wCount; + seeker += sizeof(DWORD); + + for (i = 0; i < igh.wCount; i++) { + *(DWORD*)seeker = rawSizes[i]; + seeker += sizeof(DWORD); + *(DWORD*)seeker = 0; + seeker += sizeof(DWORD); + fseek(f, offsets[i], SEEK_SET); + fread(seeker, 1, rawSizes[i], f); + seeker += rawSizes[i]; + } + + free(offsets); + free(rawSizes); + + unicondata_size = iNewIconSize; + + return pbUninstIcon; +} + +// Added by Amir Szekely 11th July 2002 +#define MY_ASSERT(x, y) if (x) {if (g_display_errors) fprintf(g_output,"\ngenerate_unicons_offsets: %s -- failing!\n", y);return 0;} + +int find_in_dir(PRESOURCE_DIRECTORY rd, WORD id) { + for (int i = rd->Header.NumberOfNamedEntries; i < rd->Header.NumberOfNamedEntries + rd->Header.NumberOfIdEntries; i++) { + if (rd->Entries[i].Id == id) { + return i; + } + } + return -1; +} + +// Fill the array of icons for uninstall with their offsets +// Returns 0 if failed, anything else is icon_offset. +int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIconData) { + int i; + + MY_ASSERT(PIMAGE_DOS_HEADER(exeHeader)->e_magic != IMAGE_DOS_SIGNATURE, "invalid dos header"); + + PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(exeHeader + PIMAGE_DOS_HEADER(exeHeader)->e_lfanew); + + MY_ASSERT(ntHeaders->Signature != IMAGE_NT_SIGNATURE, "invalid nt headers"); + + DWORD dwResourceSectionVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); + + for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) + if (dwResourceSectionVA == sectionHeadersArray[i].VirtualAddress) + break; + + MY_ASSERT(i == ntHeaders->FileHeader.NumberOfSections, "can't find resource section"); + + PRESOURCE_DIRECTORY rdRoot = PRESOURCE_DIRECTORY(exeHeader + sectionHeadersArray[i].PointerToRawData); + + int idx = find_in_dir(rdRoot, WORD(RT_ICON)); + MY_ASSERT(idx == -1, "no icons?!"); + MY_ASSERT(!rdRoot->Entries[idx].DataIsDirectory, "bad resource directory"); + + PRESOURCE_DIRECTORY rdIcons = PRESOURCE_DIRECTORY(rdRoot->Entries[idx].OffsetToDirectory + DWORD(rdRoot)); + + unsigned char* seeker = uninstIconData; + MY_ASSERT(*(DWORD*)seeker != rdIcons->Header.NumberOfIdEntries, "number of icons doesn't match"); + seeker += sizeof(DWORD); + + for (i = 0; i < rdIcons->Header.NumberOfIdEntries; i++) { // Icons dir can't have named entries + MY_ASSERT(!rdIcons->Entries[i].DataIsDirectory, "bad resource directory"); + PRESOURCE_DIRECTORY rd = PRESOURCE_DIRECTORY(rdIcons->Entries[i].OffsetToDirectory + DWORD(rdRoot)); + MY_ASSERT(rd->Entries[0].DataIsDirectory, "bad resource directory"); + PIMAGE_RESOURCE_DATA_ENTRY rde = PIMAGE_RESOURCE_DATA_ENTRY(rd->Entries[0].OffsetToData + DWORD(rdRoot)); + + DWORD dwSize = *(DWORD*)seeker; + seeker += sizeof(DWORD); + MY_ASSERT(dwSize != rde->Size, "installer, uninstaller icon size mismatch"); + // Set offset + *(DWORD*)seeker = rde->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); + seeker += sizeof(DWORD) + dwSize; + } + MY_ASSERT(i == 0, "no icons found"); + + return PIMAGE_RESOURCE_DATA_ENTRY(PRESOURCE_DIRECTORY(rdIcons->Entries[0].OffsetToDirectory + DWORD(rdRoot))->Entries[0].OffsetToData + DWORD(rdRoot))->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); +} +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT diff --git a/Source/util.h b/Source/util.h new file mode 100644 index 00000000..73f93b00 --- /dev/null +++ b/Source/util.h @@ -0,0 +1,24 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include "ResourceEditor.h" + +// these are the standard pause-before-quit shit. +extern int g_dopause; +extern void dopause(void); + +// Adds the bitmap in filename using resource editor re as id id. +// If width or height are specified it will also make sure the bitmap is in that size +int update_bitmap(CResourceEditor* re, WORD id, char* filename, int width=0, int height=0); + +// reads icon file filename and places its icons in the resource wIconId using resource editor re. Also updates icondata_size. +int replace_icon(CResourceEditor* re, WORD wIconId, char* filename); + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +// returns the data of the uninstaller icon (inside filename) that should replace the installer icon data +unsigned char* generate_uninstall_icon_data(char* filename); +// Fill the array of icons for uninstall with their offsets +int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIconData); +#endif NSIS_CONFIG_UNINSTALL_SUPPORT + +#endif //_UTIL_H_ \ No newline at end of file diff --git a/Source/zlib/DEFLATE.H b/Source/zlib/DEFLATE.H new file mode 100644 index 00000000..4189e2d6 --- /dev/null +++ b/Source/zlib/DEFLATE.H @@ -0,0 +1,238 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-1998 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + + ulg window_size; + + Posf *prev; + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + long block_start; + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + + uInt max_chain_length; + + uInt max_lazy_match; +# define max_insert_length max_lazy_match + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + + int nice_match; /* Stop searching when current match exceeds this */ + + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + int bi_valid; + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/Source/zlib/INFBLOCK.C b/Source/zlib/INFBLOCK.C new file mode 100644 index 00000000..685ffa6b --- /dev/null +++ b/Source/zlib/INFBLOCK.C @@ -0,0 +1,309 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_ZLIB +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +local const char border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c) *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + Tracev((stderr, "inflate: blocks reset\n")); +} + +int inflate_blocks_getssize() +{ + return sizeof(struct inflate_blocks_state); +} + +void inflate_blocks_init(z_streamp z,inflate_blocks_statef *s) +{ + s->end = s->window + (1 << DEF_WBITS); + s->mode = TYPE; + inflate_blocks_reset(s, z, Z_NULL); +} + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + for (;;) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; +// z->msg = (char*)"err";//invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; +// z->msg = (char*)"err";//invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; +// z->msg = (char*)"err";//too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + ZFREE(z, s->sub.trees.blens); + r = t; + if (r == Z_DATA_ERROR) + s->mode = BAD; + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & (uInt)inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & (uInt)inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; +// z->msg = (char*)"err";//invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + ZFREE(z, s->sub.trees.blens); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + s->mode = BAD; + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} +#endif \ No newline at end of file diff --git a/Source/zlib/INFBLOCK.H b/Source/zlib/INFBLOCK.H new file mode 100644 index 00000000..aa946315 --- /dev/null +++ b/Source/zlib/INFBLOCK.H @@ -0,0 +1,32 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/Source/zlib/INFCODES.C b/Source/zlib/INFCODES.C new file mode 100644 index 00000000..dc623720 --- /dev/null +++ b/Source/zlib/INFCODES.C @@ -0,0 +1,246 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_ZLIB +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ +// z->msg = (char*)"err";//invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & (uInt)inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ +// z->msg = (char*)"err";//invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & (uInt)inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ +#ifndef __TURBOC__ /* Turbo C bug for following expression */ + f = (uInt)(q - s->window) < c->sub.copy.dist ? + s->end - (c->sub.copy.dist - (q - s->window)) : + q - c->sub.copy.dist; +#else + f = q - c->sub.copy.dist; + if ((uInt)(q - s->window) < c->sub.copy.dist) + f = s->end - (c->sub.copy.dist - (uInt)(q - s->window)); +#endif + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} +#endif diff --git a/Source/zlib/INFCODES.H b/Source/zlib/INFCODES.H new file mode 100644 index 00000000..db401cac --- /dev/null +++ b/Source/zlib/INFCODES.H @@ -0,0 +1,22 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/Source/zlib/INFLATE.C b/Source/zlib/INFLATE.C new file mode 100644 index 00000000..c91aee40 --- /dev/null +++ b/Source/zlib/INFLATE.C @@ -0,0 +1,65 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_ZLIB +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + + * this has been HEAVILY modified for NSIS use, and is no longer compatible + * with the stock zlib. + + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state { int dummy; }; /* for buggy compilers */ + + +/* inflate private state */ +struct internal_state { + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + inflate_blocks_statef blocks; /* current inflate_blocks state */ +}; + + +int inflateReset(z_streamp z) +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + inflate_blocks_reset(&z->state->blocks, z, Z_NULL); + return Z_OK; +} + + +int inflateInit(z_streamp z) +{ + int inflate_blocks_getssize(); + void inflate_blocks_init(z_streamp z,inflate_blocks_statef *s); + + if ((z->state = + (struct internal_state FAR *) ZALLOC(z,1,sizeof(struct internal_state)+inflate_blocks_getssize())) == Z_NULL) + return Z_MEM_ERROR; + + inflate_blocks_init(z,&z->state->blocks); + + return Z_OK; +} + + +int inflate(z_streamp z) +{ + return inflate_blocks(&z->state->blocks, z, Z_OK); +} + +#endif diff --git a/Source/zlib/INFTREES.C b/Source/zlib/INFTREES.C new file mode 100644 index 00000000..8db38028 --- /dev/null +++ b/Source/zlib/INFTREES.C @@ -0,0 +1,324 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_ZLIB +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const unsigned short cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const unsigned short cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const unsigned short cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const unsigned short cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build( +uIntf *b, /* code lengths in bits (all assumed <= BMAX) */ +uInt n, /* number of codes (assumed <= 288) */ +uInt s, /* number of simple-valued codes (0..s-1) */ +const unsigned short *d, /* list of base values for non-simple codes */ +const unsigned short *e, /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t, /* result: starting table */ +uIntf *m, /* maximum lookup bits, returns actual */ +inflate_huft *hp, /* space for trees */ +uInt *hn) /* working area: values in order of bit length */ +{ + static uIntf v[288]; /* work area for huft_build */ + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + uInt i; /* counter, current code */ + uInt j; /* counter */ + int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p=c; + y=16; while (y--) *p++ = 0; + p = b; + i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_MEM_ERROR; /* not enough memory */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + + r = huft_build(c, 19, 19, (short *)Z_NULL, (short*)Z_NULL, + tb, bb, hp, &hn); + if (r == Z_BUF_ERROR || *bb == 0) + { + return Z_DATA_ERROR; + } + return r; +} + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn); + if (r != Z_OK || *bl == 0) + { + if (r != Z_MEM_ERROR) return Z_DATA_ERROR; + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r != Z_MEM_ERROR) return Z_DATA_ERROR; + return r; + } + + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + static uIntf c[288]; /* length list for huft_build */ + + /* literal table */ + for (k = 0; k < 144; k++) c[k] = 8; + for (; k < 256; k++) c[k] = 9; + for (; k < 280; k++) c[k] = 7; + for (; k < 288; k++) c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, fixed_mem, &f); + + /* distance table */ + for (k = 0; k < 30; k++) c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, fixed_mem, &f); + + /* done */ + fixed_built = 1; + } + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} +#endif \ No newline at end of file diff --git a/Source/zlib/INFTREES.H b/Source/zlib/INFTREES.H new file mode 100644 index 00000000..0eb2e968 --- /dev/null +++ b/Source/zlib/INFTREES.H @@ -0,0 +1,45 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + } word; + unsigned short base; /* literal, length base, distance base, + or table offset */ +}; + +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, + uIntf *, + inflate_huft * FAR *, + inflate_huft *, + z_streamp)); + +extern int inflate_trees_dynamic OF(( + uInt, + uInt, + uIntf *, + uIntf *, + uIntf *, + inflate_huft * FAR *, + inflate_huft * FAR *, + inflate_huft *, + z_streamp)); + +extern int inflate_trees_fixed OF(( + uIntf *, + uIntf *, + inflate_huft * FAR *, + inflate_huft * FAR *, + z_streamp)); diff --git a/Source/zlib/INFUTIL.C b/Source/zlib/INFUTIL.C new file mode 100644 index 00000000..432ca8ee --- /dev/null +++ b/Source/zlib/INFUTIL.C @@ -0,0 +1,87 @@ +#include "../exehead/config.h" +#ifdef NSIS_COMPRESS_USE_ZLIB +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +unsigned short inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +int __myleave(inflate_blocks_statef *s, z_streamp z, int r, int b, int k, Bytef *p, int n, Bytef *q) +{ + UPDATE + return inflate_flush(s,z,r); +} + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} +#endif \ No newline at end of file diff --git a/Source/zlib/INFUTIL.H b/Source/zlib/INFUTIL.H new file mode 100644 index 00000000..bd950394 --- /dev/null +++ b/Source/zlib/INFUTIL.H @@ -0,0 +1,97 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft hufts[MANY]; /* single malloc for tree space */ + Bytef window[1 << DEF_WBITS]; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE return __myleave(s,z,r,b,k,p,n,q); +extern int __myleave(inflate_blocks_statef *s, z_streamp z, int r, int b, int k, Bytef *p, int n, Bytef *q); + +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} + + +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern unsigned short inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/Source/zlib/ZCONF.H b/Source/zlib/ZCONF.H new file mode 100644 index 00000000..3618fe39 --- /dev/null +++ b/Source/zlib/ZCONF.H @@ -0,0 +1,58 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + + +#define MAX_MEM_LEVEL 9 + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +#define OF(args) args + + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +typedef Byte FAR Bytef; +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +typedef void FAR *voidpf; +typedef void *voidp; + +#ifndef z_off_t +# define z_off_t long +#endif + + +#endif /* _ZCONF_H */ diff --git a/Source/zlib/ZLIB.H b/Source/zlib/ZLIB.H new file mode 100644 index 00000000..83d0864c --- /dev/null +++ b/Source/zlib/ZLIB.H @@ -0,0 +1,157 @@ +/* + Note: this version of zlib has been hacked up quite a bit in order to reduce + the size of the EXE header and to remove what we didn't need. + For the complete real thing, go to: + + http://www.info-zip.org/pub/infozip/zlib/ + + Peace, + + -Justin +*/ + + + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + +// char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + +} z_stream; + +typedef z_stream FAR *z_streamp; + + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + +int inflate(z_streamp z); +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +int inflateReset(z_streamp z); + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +//ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + // const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), "", sizeof(z_stream)) + +extern int inflateInit(z_streamp z); + + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/Source/zlib/ZUTIL.H b/Source/zlib/ZUTIL.H new file mode 100644 index 00000000..573015b8 --- /dev/null +++ b/Source/zlib/ZUTIL.H @@ -0,0 +1,68 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include +#include "zlib.h" + +#ifndef local +# define local static +#endif + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#define DEF_MEM_LEVEL MAX_MEM_LEVEL + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + +#ifdef EXEHEAD +#include "../exehead/util.h" +#define zmemcpy mini_memcpy +#else +#define zmemcpy memcpy +#define zmemzero(a,b) memset(a,0,b) +#endif + +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) + +#define ZALLOC(strm, items, size) GlobalAlloc(GPTR,(items)*(size)) +#define ZFREE(strm, addr) { if (addr) GlobalFree(addr); } +#define TRY_FREE(s, p) { ZFREE(s, p); } +#define ERR_RETURN(strm,err) return (err) + +#endif /* _Z_UTIL_H */ diff --git a/Source/zlib/deflate.c b/Source/zlib/deflate.c new file mode 100644 index 00000000..0bd1270f --- /dev/null +++ b/Source/zlib/deflate.c @@ -0,0 +1,986 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + +// strm->msg = Z_NULL; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { +// strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; +// strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { +// putShortMSB(s, (uInt)(strm->adler >> 16)); + // putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } +// strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; + return Z_OK; + } + + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + flush_pending(strm); + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + + +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + //if (!strm->state->noheader) { +// strm->adler = adler32(strm->adler, strm->next_in, len); + // } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +# define check_match(s, start, match, length) + +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + s->match_length = MIN_MATCH-1; + } + } + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/Source/zlib/trees.c b/Source/zlib/trees.c new file mode 100644 index 00000000..ce869ceb --- /dev/null +++ b/Source/zlib/trees.c @@ -0,0 +1,883 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-1998 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +local ct_data static_ltree[L_CODES+2]; + +local ct_data static_dtree[D_CODES]; + +uch _dist_code[DIST_CODE_LEN]; + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +} + + +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + overflow -= 2; + } while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); +} + +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +}