From 3e9e73ec59e8280d9ea9c8db97d1e94643d8331a Mon Sep 17 00:00:00 2001 From: kichik Date: Fri, 2 Aug 2002 10:01:35 +0000 Subject: [PATCH] This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@625 212acab6-be3b-0410-9dea-997c60f758d6 --- Contrib/ExDLL/exdll.c | 102 + Contrib/ExDLL/exdll.dpr | 122 + Contrib/ExDLL/exdll.dsp | 107 + Contrib/ExDLL/exdll.dsw | 29 + Contrib/Icons/checks1.bmp | Bin 0 -> 886 bytes Contrib/Icons/checks2.bmp | Bin 0 -> 886 bytes Contrib/Icons/checks4.bmp | Bin 0 -> 886 bytes Contrib/Icons/checksX.bmp | Bin 0 -> 886 bytes Contrib/Icons/checksX2.bmp | Bin 0 -> 886 bytes Contrib/Icons/jarsonic-checks.bmp | Bin 0 -> 886 bytes Contrib/Icons/lucas-checks.bmp | Bin 0 -> 886 bytes Contrib/Icons/normal-install.ico | Bin 0 -> 766 bytes Contrib/Icons/normal-uninstall.ico | Bin 0 -> 766 bytes Contrib/Icons/setup.ico | Bin 0 -> 766 bytes Contrib/InstallOptions/Install Options.html | 363 ++ Contrib/InstallOptions/InstallerOptions.cpp | 1074 ++++++ Contrib/InstallOptions/io.dsp | 115 + Contrib/InstallOptions/io.dsw | 29 + Contrib/InstallOptions/ioptdll.rc | 94 + Contrib/InstallOptions/resource.h | 16 + Contrib/InstallOptions/test.ini | 67 + Contrib/InstallOptions/test.nsi | 128 + Contrib/Makensisw/License.txt | 18 + Contrib/Makensisw/Readme.txt | 152 + Contrib/Makensisw/afxres.h | 5 + Contrib/Makensisw/makensisw.cpp | 363 ++ Contrib/Makensisw/makensisw.dsp | 160 + Contrib/Makensisw/makensisw.dsw | 29 + Contrib/Makensisw/makensisw.h | 74 + Contrib/Makensisw/makensisw.xml | 10 + Contrib/Makensisw/noclib.cpp | 52 + Contrib/Makensisw/noclib.h | 32 + Contrib/Makensisw/resource.h | 38 + Contrib/Makensisw/resource.rc | 179 + Contrib/Makensisw/utils.cpp | 185 ++ Contrib/Makensisw/utils.h | 46 + Contrib/Makensisw/version.cpp | 30 + Contrib/NSISdl/ReadMe.txt | 59 + Contrib/NSISdl/Script1.rc | 78 + Contrib/NSISdl/asyncdns.cpp | 78 + Contrib/NSISdl/asyncdns.h | 38 + Contrib/NSISdl/connection.cpp | 447 +++ Contrib/NSISdl/connection.h | 135 + Contrib/NSISdl/httpget.cpp | 471 +++ Contrib/NSISdl/httpget.h | 109 + Contrib/NSISdl/netinc.h | 82 + Contrib/NSISdl/nsisdl.cpp | 448 +++ Contrib/NSISdl/nsisdl.dsp | 152 + Contrib/NSISdl/nsisdl.dsw | 29 + Contrib/NSISdl/resource.h | 19 + Contrib/NSISdl/util.cpp | 64 + Contrib/NSISdl/util.h | 41 + Contrib/Splash/splash.c | 137 + Contrib/Splash/splash.dsp | 108 + Contrib/Splash/splash.dsw | 29 + Contrib/Splash/splash.txt | 38 + Contrib/UIs/default.exe | Bin 0 -> 3072 bytes Contrib/UIs/mlbl.exe | Bin 0 -> 3072 bytes Contrib/UIs/mlbl2.exe | Bin 0 -> 3072 bytes Contrib/zip2exe/icon.ico | Bin 0 -> 766 bytes Contrib/zip2exe/main.cpp | 715 ++++ Contrib/zip2exe/res.rc | 132 + Contrib/zip2exe/resource.h | 37 + Contrib/zip2exe/zip2exe.dsp | 160 + Contrib/zip2exe/zip2exe.dsw | 29 + Contrib/zip2exe/zlib/ADLER32.C | 48 + Contrib/zip2exe/zlib/CRC32.C | 162 + Contrib/zip2exe/zlib/INFBLOCK.C | 398 +++ Contrib/zip2exe/zlib/INFBLOCK.H | 39 + Contrib/zip2exe/zlib/INFCODES.C | 257 ++ Contrib/zip2exe/zlib/INFCODES.H | 27 + Contrib/zip2exe/zlib/INFFAST.C | 170 + Contrib/zip2exe/zlib/INFFAST.H | 17 + Contrib/zip2exe/zlib/INFFIXED.H | 151 + Contrib/zip2exe/zlib/INFLATE.C | 366 ++ Contrib/zip2exe/zlib/INFTREES.C | 455 +++ Contrib/zip2exe/zlib/INFTREES.H | 58 + Contrib/zip2exe/zlib/INFUTIL.C | 87 + Contrib/zip2exe/zlib/INFUTIL.H | 98 + Contrib/zip2exe/zlib/UNZIP.H | 275 ++ Contrib/zip2exe/zlib/Unzip.c | 1295 ++++++++ Contrib/zip2exe/zlib/ZCONF.H | 279 ++ Contrib/zip2exe/zlib/ZLIB.H | 893 +++++ Contrib/zip2exe/zlib/ZUTIL.H | 220 ++ Contrib/zip2exe/zlib/Zutil.c | 226 ++ Examples/WinMessages.NSH | 164 + Examples/bigtest.nsi | 239 ++ Examples/branding.nsh | 104 + Examples/example1.nsi | 29 + Examples/example2.nsi | 67 + Examples/functions.htm | 614 ++++ Examples/gfx.nsi | 86 + Examples/makensis.nsi | 420 +++ Examples/primes.nsi | 48 + Examples/rtest.nsi | 56 + Examples/viewhtml.nsi | 43 + Examples/waplugin.nsi | 153 + Source/DialogTemplate.cpp | 463 +++ Source/DialogTemplate.h | 121 + Source/Makefile | 74 + Source/Release/Script1.res | Bin 0 -> 860 bytes Source/Release/vc60.idb | 1 + Source/ResourceEditor.cpp | 780 +++++ Source/ResourceEditor.h | 167 + Source/Script1.rc | 72 + Source/afxres.h | 5 + Source/build.cpp | 1971 +++++++++++ Source/build.h | 169 + Source/bzip2/blocksort.c | 1100 ++++++ Source/bzip2/bzlib.c | 790 +++++ Source/bzip2/bzlib.h | 174 + Source/bzip2/bzlib_private.h | 474 +++ Source/bzip2/compress.c | 681 ++++ Source/bzip2/decompress.c | 569 ++++ Source/bzip2/huffman.c | 229 ++ Source/bzip2/randtable.c | 127 + Source/cbzip2.h | 51 + Source/compressor.h | 22 + Source/crc32.c | 34 + Source/czlib.h | 51 + Source/exedata.cpp | 17 + Source/exedata.h | 16 + Source/exehead/Main.c | 364 ++ Source/exehead/Makefile | 81 + Source/exehead/Ui.c | 1237 +++++++ Source/exehead/afxres.h | 5 + Source/exehead/bgbg.c | 90 + Source/exehead/bin2h.c | 60 + Source/exehead/bin2h.exe | Bin 0 -> 25088 bytes Source/exehead/bitmap1.bmp | Bin 0 -> 886 bytes Source/exehead/config.h | 260 ++ Source/exehead/exec.c | 1423 ++++++++ Source/exehead/exec.h | 7 + Source/exehead/exehead-bzip2.dsp | 251 ++ Source/exehead/exehead-zlib.dsp | 251 ++ Source/exehead/exehead.xml | 10 + Source/exehead/fileform.c | 323 ++ Source/exehead/fileform.h | 324 ++ Source/exehead/lang.h | 57 + Source/exehead/nsis.ico | Bin 0 -> 766 bytes Source/exehead/resource.h | 63 + Source/exehead/resource.rc | 247 ++ Source/exehead/state.h | 11 + Source/exehead/ui.h | 21 + Source/exehead/uninst.ico | Bin 0 -> 766 bytes Source/exehead/util.c | 548 +++ Source/exehead/util.h | 47 + Source/icon.ico | Bin 0 -> 766 bytes Source/lineparse.h | 150 + Source/makenssi.cpp | 379 +++ Source/makenssi.dsp | 247 ++ Source/makenssi.dsw | 59 + Source/makenssi.ncb | 1 + Source/makenssi.opt | Bin 0 -> 58880 bytes Source/makenssi.plg | 260 ++ Source/resource.h | 17 + Source/script.cpp | 3302 +++++++++++++++++++ Source/strlist.h | 275 ++ Source/tokens.cpp | 226 ++ Source/tokens.h | 192 ++ Source/util.cpp | 292 ++ Source/util.h | 24 + Source/zlib/DEFLATE.H | 238 ++ Source/zlib/INFBLOCK.C | 309 ++ Source/zlib/INFBLOCK.H | 32 + Source/zlib/INFCODES.C | 246 ++ Source/zlib/INFCODES.H | 22 + Source/zlib/INFLATE.C | 65 + Source/zlib/INFTREES.C | 324 ++ Source/zlib/INFTREES.H | 45 + Source/zlib/INFUTIL.C | 87 + Source/zlib/INFUTIL.H | 97 + Source/zlib/ZCONF.H | 58 + Source/zlib/ZLIB.H | 157 + Source/zlib/ZUTIL.H | 68 + Source/zlib/deflate.c | 986 ++++++ Source/zlib/trees.c | 883 +++++ 177 files changed, 37677 insertions(+) create mode 100644 Contrib/ExDLL/exdll.c create mode 100644 Contrib/ExDLL/exdll.dpr create mode 100644 Contrib/ExDLL/exdll.dsp create mode 100644 Contrib/ExDLL/exdll.dsw create mode 100644 Contrib/Icons/checks1.bmp create mode 100644 Contrib/Icons/checks2.bmp create mode 100644 Contrib/Icons/checks4.bmp create mode 100644 Contrib/Icons/checksX.bmp create mode 100644 Contrib/Icons/checksX2.bmp create mode 100644 Contrib/Icons/jarsonic-checks.bmp create mode 100644 Contrib/Icons/lucas-checks.bmp create mode 100644 Contrib/Icons/normal-install.ico create mode 100644 Contrib/Icons/normal-uninstall.ico create mode 100644 Contrib/Icons/setup.ico create mode 100644 Contrib/InstallOptions/Install Options.html create mode 100644 Contrib/InstallOptions/InstallerOptions.cpp create mode 100644 Contrib/InstallOptions/io.dsp create mode 100644 Contrib/InstallOptions/io.dsw create mode 100644 Contrib/InstallOptions/ioptdll.rc create mode 100644 Contrib/InstallOptions/resource.h create mode 100644 Contrib/InstallOptions/test.ini create mode 100644 Contrib/InstallOptions/test.nsi create mode 100644 Contrib/Makensisw/License.txt create mode 100644 Contrib/Makensisw/Readme.txt create mode 100644 Contrib/Makensisw/afxres.h create mode 100644 Contrib/Makensisw/makensisw.cpp create mode 100644 Contrib/Makensisw/makensisw.dsp create mode 100644 Contrib/Makensisw/makensisw.dsw create mode 100644 Contrib/Makensisw/makensisw.h create mode 100644 Contrib/Makensisw/makensisw.xml create mode 100644 Contrib/Makensisw/noclib.cpp create mode 100644 Contrib/Makensisw/noclib.h create mode 100644 Contrib/Makensisw/resource.h create mode 100644 Contrib/Makensisw/resource.rc create mode 100644 Contrib/Makensisw/utils.cpp create mode 100644 Contrib/Makensisw/utils.h create mode 100644 Contrib/Makensisw/version.cpp create mode 100644 Contrib/NSISdl/ReadMe.txt create mode 100644 Contrib/NSISdl/Script1.rc create mode 100644 Contrib/NSISdl/asyncdns.cpp create mode 100644 Contrib/NSISdl/asyncdns.h create mode 100644 Contrib/NSISdl/connection.cpp create mode 100644 Contrib/NSISdl/connection.h create mode 100644 Contrib/NSISdl/httpget.cpp create mode 100644 Contrib/NSISdl/httpget.h create mode 100644 Contrib/NSISdl/netinc.h create mode 100644 Contrib/NSISdl/nsisdl.cpp create mode 100644 Contrib/NSISdl/nsisdl.dsp create mode 100644 Contrib/NSISdl/nsisdl.dsw create mode 100644 Contrib/NSISdl/resource.h create mode 100644 Contrib/NSISdl/util.cpp create mode 100644 Contrib/NSISdl/util.h create mode 100644 Contrib/Splash/splash.c create mode 100644 Contrib/Splash/splash.dsp create mode 100644 Contrib/Splash/splash.dsw create mode 100644 Contrib/Splash/splash.txt create mode 100755 Contrib/UIs/default.exe create mode 100755 Contrib/UIs/mlbl.exe create mode 100755 Contrib/UIs/mlbl2.exe create mode 100644 Contrib/zip2exe/icon.ico create mode 100644 Contrib/zip2exe/main.cpp create mode 100644 Contrib/zip2exe/res.rc create mode 100644 Contrib/zip2exe/resource.h create mode 100644 Contrib/zip2exe/zip2exe.dsp create mode 100644 Contrib/zip2exe/zip2exe.dsw create mode 100644 Contrib/zip2exe/zlib/ADLER32.C create mode 100644 Contrib/zip2exe/zlib/CRC32.C create mode 100644 Contrib/zip2exe/zlib/INFBLOCK.C create mode 100644 Contrib/zip2exe/zlib/INFBLOCK.H create mode 100644 Contrib/zip2exe/zlib/INFCODES.C create mode 100644 Contrib/zip2exe/zlib/INFCODES.H create mode 100644 Contrib/zip2exe/zlib/INFFAST.C create mode 100644 Contrib/zip2exe/zlib/INFFAST.H create mode 100644 Contrib/zip2exe/zlib/INFFIXED.H create mode 100644 Contrib/zip2exe/zlib/INFLATE.C create mode 100644 Contrib/zip2exe/zlib/INFTREES.C create mode 100644 Contrib/zip2exe/zlib/INFTREES.H create mode 100644 Contrib/zip2exe/zlib/INFUTIL.C create mode 100644 Contrib/zip2exe/zlib/INFUTIL.H create mode 100644 Contrib/zip2exe/zlib/UNZIP.H create mode 100644 Contrib/zip2exe/zlib/Unzip.c create mode 100644 Contrib/zip2exe/zlib/ZCONF.H create mode 100644 Contrib/zip2exe/zlib/ZLIB.H create mode 100644 Contrib/zip2exe/zlib/ZUTIL.H create mode 100644 Contrib/zip2exe/zlib/Zutil.c create mode 100644 Examples/WinMessages.NSH create mode 100644 Examples/bigtest.nsi create mode 100644 Examples/branding.nsh create mode 100644 Examples/example1.nsi create mode 100644 Examples/example2.nsi create mode 100644 Examples/functions.htm create mode 100644 Examples/gfx.nsi create mode 100644 Examples/makensis.nsi create mode 100644 Examples/primes.nsi create mode 100644 Examples/rtest.nsi create mode 100644 Examples/viewhtml.nsi create mode 100644 Examples/waplugin.nsi create mode 100644 Source/DialogTemplate.cpp create mode 100644 Source/DialogTemplate.h create mode 100644 Source/Makefile create mode 100644 Source/Release/Script1.res create mode 100644 Source/Release/vc60.idb create mode 100644 Source/ResourceEditor.cpp create mode 100644 Source/ResourceEditor.h create mode 100644 Source/Script1.rc create mode 100644 Source/afxres.h create mode 100644 Source/build.cpp create mode 100644 Source/build.h create mode 100644 Source/bzip2/blocksort.c create mode 100644 Source/bzip2/bzlib.c create mode 100644 Source/bzip2/bzlib.h create mode 100644 Source/bzip2/bzlib_private.h create mode 100644 Source/bzip2/compress.c create mode 100644 Source/bzip2/decompress.c create mode 100644 Source/bzip2/huffman.c create mode 100644 Source/bzip2/randtable.c create mode 100644 Source/cbzip2.h create mode 100644 Source/compressor.h create mode 100644 Source/crc32.c create mode 100644 Source/czlib.h create mode 100644 Source/exedata.cpp create mode 100644 Source/exedata.h create mode 100644 Source/exehead/Main.c create mode 100644 Source/exehead/Makefile create mode 100644 Source/exehead/Ui.c create mode 100644 Source/exehead/afxres.h create mode 100644 Source/exehead/bgbg.c create mode 100644 Source/exehead/bin2h.c create mode 100755 Source/exehead/bin2h.exe create mode 100644 Source/exehead/bitmap1.bmp create mode 100644 Source/exehead/config.h create mode 100644 Source/exehead/exec.c create mode 100644 Source/exehead/exec.h create mode 100644 Source/exehead/exehead-bzip2.dsp create mode 100644 Source/exehead/exehead-zlib.dsp create mode 100644 Source/exehead/exehead.xml create mode 100644 Source/exehead/fileform.c create mode 100644 Source/exehead/fileform.h create mode 100644 Source/exehead/lang.h create mode 100644 Source/exehead/nsis.ico create mode 100644 Source/exehead/resource.h create mode 100644 Source/exehead/resource.rc create mode 100644 Source/exehead/state.h create mode 100644 Source/exehead/ui.h create mode 100644 Source/exehead/uninst.ico create mode 100644 Source/exehead/util.c create mode 100644 Source/exehead/util.h create mode 100644 Source/icon.ico create mode 100644 Source/lineparse.h create mode 100644 Source/makenssi.cpp create mode 100644 Source/makenssi.dsp create mode 100644 Source/makenssi.dsw create mode 100644 Source/makenssi.ncb create mode 100644 Source/makenssi.opt create mode 100644 Source/makenssi.plg create mode 100644 Source/resource.h create mode 100644 Source/script.cpp create mode 100644 Source/strlist.h create mode 100644 Source/tokens.cpp create mode 100644 Source/tokens.h create mode 100644 Source/util.cpp create mode 100644 Source/util.h create mode 100644 Source/zlib/DEFLATE.H create mode 100644 Source/zlib/INFBLOCK.C create mode 100644 Source/zlib/INFBLOCK.H create mode 100644 Source/zlib/INFCODES.C create mode 100644 Source/zlib/INFCODES.H create mode 100644 Source/zlib/INFLATE.C create mode 100644 Source/zlib/INFTREES.C create mode 100644 Source/zlib/INFTREES.H create mode 100644 Source/zlib/INFUTIL.C create mode 100644 Source/zlib/INFUTIL.H create mode 100644 Source/zlib/ZCONF.H create mode 100644 Source/zlib/ZLIB.H create mode 100644 Source/zlib/ZUTIL.H create mode 100644 Source/zlib/deflate.c create mode 100644 Source/zlib/trees.c 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 0000000000000000000000000000000000000000..8159715416e2f300f03685c71382e386b4b9912c GIT binary patch literal 886 zcmah{F_MHJ5ajCi0r!l1$L05i`^64Mm`O%x5&0FLWCk0}H8Z%POVzeAEzmYC^7DKD zG=e+oH`*WC7utupp#pVYJ8d0}!EMG-2^EiKT~~0KV7U!*c|yZghDu+Mv+~=zg(}Hj z5U#Alo-1#=+>#(%c$#F`rpix$>&lxcSoc_z6Gl>__juDD{+LzWFe?-F^n3opKgO=! zdPM5@4>2w!7gl#|9(-`ozxWUHV^)2llb%FhQUm$O!zs#l^H~q`sps#Qho$TjGr4wu z2n%%bLzklJ6P@*T>g0!>hgtlYsM&vPfbaV=S3O_!w(*z$PH)cxRxij_4^+7DRL@!3 S&s(TadqQNv&Pls&=j|V=aw%f~ literal 0 HcmV?d00001 diff --git a/Contrib/Icons/checks2.bmp b/Contrib/Icons/checks2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e88402aaf07d93a788492a5e313e47e2a4f90999 GIT binary patch literal 886 zcmah{u@QqX3{)=Z$rzak%LD zH~bF2&x)v2!Z2f2JxzA>0?f3=b!%qeP literal 0 HcmV?d00001 diff --git a/Contrib/Icons/checks4.bmp b/Contrib/Icons/checks4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9ec0527c502d158a8009407d4d1a1d37bd9e9c8d GIT binary patch literal 886 zcmaiyu@S;B3`NDkUCJ;9bI`K`Be)_ZDbu-5l~pnlrBjLjEnP5)IYcbk&eNAse7!x6 zlI;P1!MJ0bF%EKqhxvP3l)e|iBYkfH9#fg;8IdnEKcdPR27cV)I$KKErnMG+$7l(Z zq5b6@PgdyF?qWv^t$1AZb0YZ#Gsa|bo1e@kV4*vZ&;_IKRQ2bc%+7QuRo#y z&oiX>r7xkW=`YTw4Ihl(=|g>_F4TuoAL>%mhrlxNJgO;{{}-okYUc+yYUWX(=nont zU8O%P;C$Nfp{w)T@h*yeufWSqt?p67S7 HwEzAM>6E$e literal 0 HcmV?d00001 diff --git a/Contrib/Icons/checksX.bmp b/Contrib/Icons/checksX.bmp new file mode 100644 index 0000000000000000000000000000000000000000..43d5dd65123c1e5b8d0441209fde8fba1bfd36f1 GIT binary patch literal 886 zcma)4K@x)?3{0oJ+h_D0z4s4&h4F?rx$z~REqgO9 zO!`VHS7Xn3(h(NS?mT&#)Uk66Onl9(*_8U!ErGArBYzse5AwPGLez==%B*tzLF?&C zUj{9F$1IroVU3P1^y~aoprkX=t@l&*Uw?0@U!P~Gzx5Syf3NKJ`Jc|Sxp>}|C;dPF KHxn(^HQ@)p>O*V* literal 0 HcmV?d00001 diff --git a/Contrib/Icons/checksX2.bmp b/Contrib/Icons/checksX2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ede88a0f793134368289a2f2836802c31b933189 GIT binary patch literal 886 zcma)4OA^8$42`2RF6%KohkNhf5xQ!+qq}C;EA>d-$qrutu}&N?C3$>a9t3*34@ZhN zAYS1Q_yvBT6Cy0Hr@=l>L})Zk2@uhxbzOnF5MrYcvqvq>jbq(jTCyb4F!tq9flUWN!+_WN`o^C05zFZ7e=jCfn0Z#p*iBL4sX^cGklgF9bp{x4_!0fmn6UH||9 literal 0 HcmV?d00001 diff --git a/Contrib/Icons/lucas-checks.bmp b/Contrib/Icons/lucas-checks.bmp new file mode 100644 index 0000000000000000000000000000000000000000..733f8de1be6754de07107d5e05cb1551fd666a90 GIT binary patch literal 886 zcmah`J9dOH3{+lHq}v>0&yhZN$SGEIqJxeraU?q2DKoP3{9)f)fh9{GjRy1m^LUrA z2mBrD7wZe_O+MgZJm&z9t?c`b$ODg8+_}TT!xHnblyZFSw*t{@_9_;5 zvb?b|j{X1q4UQ%DvDD66(90UF;ZL8)fj^b8@=q)ASN@rI0K5+PHSjp2RsJLb4zn|c zSN>^TA?V6~+zto=9v!WoX`vts_Lkp0<2^p0@~Z~^svkdbqkea=wRnY~XZ#!xcnIq7 z7;x23fs*k);1zft!|MGoJ8r@6r*-@~EzkMA;4!BDFYXp29jxc)eMY(0j|SU{^*lQ8 G*8C5ylsJ3< literal 0 HcmV?d00001 diff --git a/Contrib/Icons/normal-install.ico b/Contrib/Icons/normal-install.ico new file mode 100644 index 0000000000000000000000000000000000000000..55c32414090d14c8454976e8fff0c491f3f49f9b GIT binary patch literal 766 zcmZuvu};G<5PfNol1{V>BP|;rfdrq_?V>F8mWY96O*P_89oAKH#b zp>0K>8?_~~)V~d+h1cf=GQ)B#P=(o*R(tI|f*vy8*UM2~4~KvBa>4J`)h`#k^S)+z zUysL^n)@?<(GRsAo(TQ%K2FDP!#;Xp9`mzK!vcCb!nyAW9_z$Rwz0jo(KfMB9UI2O rzvPR8(Ql`W$;1G+7I-)@vxr-=Chy3Ij4cL9$JjCExuvhk7K!@-72oC) literal 0 HcmV?d00001 diff --git a/Contrib/Icons/normal-uninstall.ico b/Contrib/Icons/normal-uninstall.ico new file mode 100644 index 0000000000000000000000000000000000000000..9b336f06d739754912b6ec63aa8ad921c0a39bd2 GIT binary patch literal 766 zcmbu7F>-@25Jf+6W=NM*X`#$5l3U?U+d=0maTL#_N$HXzj&Nl2eZcXHL^V;>Ky}I}%sMrHjF5 z26Gn!@0SHwxJ$ulvLUu(oM7CU19f1tPWTE{U78(RANmf{dfw?S8 zA|D>|m?QBhVZ?$Im6m)CWnQbd$V^)kU{$oLIE8B literal 0 HcmV?d00001 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: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NumFields(required)The number of control elements to be + displayed on the dialog window.
    Title(optional)If specified, gives the text to set the + titlebar to. Otherwise, the titlebar text is not changed.
    CancelConfirm(optional)If specified, prompts the user (With text) whether or not to cancel if they select the cancel button.
    BackEnabled(optional)Controls whether or not the back button in the NSIS window is enabled. If set to 0 or omitted, the back button will be disabled. If set to 1, the back button will be enabled.
    CancelButtonText(optional)Overrides the text for the cancel button. If not specified, the cancel button text will not be changed. Recommended value: "Cancel"
    NextButtonText(optional)Overrides the text for the next button. If not specified, the next button text will not be changed. Recommended value: "Next >"
    BackButtonText(optional)Overrides the text for the back button. If not specified, the back button text will not be changed. Recommended value: "< Back"
+

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

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Type(required)Type of control to be created. Valid + values are "Label", "Text", "Password", + "Combobox", "DropList", "Listbox", "CheckBox", + "RadioButton", + "FileRequest", or "DirRequest".
    A + "label" is used to display static text. (i.e. a caption for a + textbox)
    A "textbox" and "password" accept text input + from the user. "password" masks the input with * characters.
    A + "combobox" allows the user to type text not in the popup list, a + "droplist" only allows selection of items in the list.
    A + "listbox" shows multiple items and can optionally allow the user + to select more than one item.
    + A "CheckBox" control displays a check box with label.
    + A "RadioButton" control displays a radio button with label.
    + A "FileRequest" control displays + a textbox and a browse button. Clicking the browse button will display a + file requester where the user can browse for a file.
    A + "DirRequest" control displays a textbox and a browse button. + Clicking the browse button will display a directory requester where the + user can browse for a directory.
    Text(optional)Specifies the caption of a label, checkbox, or radio button control. +
    State(optional)Specifies the state of the control. This is updated when the user closes the window, + so you can read from it from NSIS. For edit texts and dir and file request boxes, this is the string that is + specified. For radio button and check boxes, this can be '0' or '1' (for unchecked or checked). +
    ListItems(optional)A list of items to display in a combobox, + droplist, or listbox.
    This is a single line of text with each item + separated by a pipe character '|'
    MaxLen(optional)Causes validation on the selected control + to limit the maximum length of text.
    If the user specifies more text + than this, a message box will appear when they click "OK" and the dialog + will not be dismissed.
    You should not use this on a + "combobox" since the user can not control what is + selected.
    This should be set to a maximum of 260 + for "FileRequest" and "DirRequest" + controls.
    Ignored on "label" + controls.
    MinLen(optional)Causes validation on the selected control + to force the user to enter a minimum amount of text.
    If the user + specifies less text than this, a message box will appear when they click + "OK" and the dialog will not be dismissed.
    Unlike MaxLen, this is + useful for "Combobox" controls. By setting this to a value of "1" + the program will force the user to select an item.
    Ignored on "label" controls.
    ValidateText(optional)If a particular field fails the test for + "MinLen" or "MaxLen", a messagebox will be displayed with + this text.
    NOTE: The only formatting performed on this + text is "\n" will be replaced with a newline in the + messagebox.
    Left
    Right
    Top
    Bottom
    (required)The position on the dialog where this + control appears.
    Sorry, no GUI here to help you.
    NOTE: For combobox or droplist, the "bottom" value is not + used in the same way.
    In this case, the bottom value is the maximum + size of the window when the pop-up list is being displayed. All other + times, the combobox is automatically szed to be one element tall. If you + have trouble where you can not see the combobox drop-down, then check + the bottom value and ensure it is large enough.
    NOTE (2): + FileRequest and DirRequest controls will allocate 20 pixels to the + browse button. Make this control wide enough the contents of the textbox + can be seen. Note that you can specify negative coordinates to specify the distance from the right or bottom edge.
    Filter(optional)Specifies the filter to be used in the + "FileRequest" control.
    This is constructed by putting pairs of + entries together, each item seperated by a | character.
    The first + value in each pair is the text to display for the filter.
    The second + value is the pattern to use to match files.
    For example, you might + specify:
    +
      Filter=Text Files|*.txt|Programs|*.exe;*.com|All Files|*.* +
    If not specified, then the filter defaults to All + Files|*.*
    NOTE: you should not put any extra + spaces around the | characters.
    Root(optional)Used by DirRequest controls to + specify the root directory of the search. By default, this allows the + user to browse any directory on the computer. This will limit the search + to a particular directory on the system.
    Flags(optional)This specifies additional flags for the + display of different controls. Each value should be seperated by a | + character, and you should be careful not to put any spaces around the | + character.
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ValueMeaning
    REQ_SAVEThis causes the "FileRequest" to dislpay a + Save As dialog. If not specified, an Open dialog is used.
    FILE_MUST_EXISTUsed by "FileRequest" to determine if the + selected file must exist.
    This only applies if an "Open" dialog + is being displayed.
    This currently does not force + the file to exist other than through the browse + button.
    FILE_EXPLORERUsed by "FileRequest", enables new file request look (recommended)
    FILE_HIDEREADONLYUsed by "FileRequest", hides "open read only" checkbox in open dialog.
    WARN_IF_EXISTUsed by "FileRequest" to display a warning + message if the selected file already exists.
    The + warning message is only displayed for files selected with the + browse button.
    PATH_MUST_EXISTUsed by "FileRequest" to force the path to + exist. Prevents the user from typing a non-existant path into the + browse dialog window.
    This only validates path's + selected with the browse button.
    PROMPT_CREATEUsed by "FileRequest" to display a warning + if the selected file does not exist. However, it still allows the + user to select the file.
    This only displays the + warning for files selected with the browse button.
    RIGHTUsed by "Checkbox" and "Radiobutton" + controls to specify you want the checkbox to the right of the text + instead of the left as is the default.
    MULTISELECTUsed by "Listbox" controls to specify if + more than item may be selected. If this flag is not specified, + then only one item may be selected from the + list.
+
+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 0000000000000000000000000000000000000000..11e6832f6f5ddd1f245d6043597472fdb86a75e0 GIT binary patch literal 3072 zcmeHJ&ubKS6#slT8?#1@D>M*_rQg6JdTu_-}%m*{2T)Svg9}hu2BkE$@9sNRk}xBy*`4g8*hzYQ`5J`=NfLP&jo%xa29mc z@jO4$9~d1hdfN4L>4>ct{F*6l*)m*6OW&UF-2H0kUT2Me?|e(VP2VHwZ|di}m{83-y1zfp)2o z+nwjj5xp|G^`lSOX%lf&$i<`EwI%xK80DW!cKdW8ckFn3;w8ey&OH|F_)dF&UeFj( zBg>c1j(@JicN%%(=0FN^0#phhAkziS!6c?Vv6(fP)*Ng+;7QbTvi#ZiPVHO$A1D=k z);+Xd{?p&MjPkM@RRX_i!Vq=!wuxr^+G5L0I$o`14g&9#XAhUB_w6m#S}ovW#%}ma z$6c@HF9F*mzSOEuMP>o`IAfcr>zd<9$y}AG_+j+!q8rVyyi+$kJIh|J3CJcT^{C=^c(z^=|fKSLt=Z%*5^$Sy1pm#CirM* z0zKtLCYX1sM(@^hCX8IK{wyuzxt>K~kn@iLE9=*w;L^Zr!Qbo~dF)TpcftaGrR>pa z?#7Df-K)l!`Yv_kFaw*1hYbfF!bCF&Sbsi^P!&<`;xp{U2o!InE2)S7;lwwT`Z9gK zJd&FmhVThCDanfC3uzu(v_u_ZH^b@z9t^DcSTpfmPHPVI)l|rwki6IN1zNleWwZTx I;(7Y%5nO5mRsaA1 literal 0 HcmV?d00001 diff --git a/Contrib/UIs/mlbl.exe b/Contrib/UIs/mlbl.exe new file mode 100755 index 0000000000000000000000000000000000000000..b0e50308543601d4ed6e23751abd0fd6b441f9e2 GIT binary patch literal 3072 zcmeHJ&ubKS6#slTn`Vs~x6sf~Ed2(SVh=8&cr#^UcWV}tbeoB_Xw^=4$KBa(X6)>w z$uTHx54(a0ZJ~#H@m453v>>I2pdcc664X;$+MeovpoQt@eRswr2qMKovA*Tad!P4f z-g^w+{mvXYhXDXtavTGfD1|KZeDq_L?vYo19KrXSZj4`2(>KQFn_fqs3WG-IEa;l! z`$42XaCNxoYtPrEw`{!-)ZOCNt;2<+^v#pKU%njrt+&R%_bw1G6z=!VQ(h_D?0rF5 zReu;c=hd1Ln|4+$1Jf#t*N&AYQroZCrZ%hRfDA1ZLKpLV2y3!TCp!Hyw@@lkT?3MC z0wq=wjC>%(h#eZ(CyE7pr$l)|q*?nBrHYZe9MOMOVx%u=_Q4QhG^4&>4C_wh0Iy1K znk;e2PN*5O*nP1dhBw8si!54VmwiRn&kVGX9W2AlVI5~WU-KXLr%p4H2FcF{y$ znrV5`5KR22rVyB=d`ACt17B&NM;7`?1J}uS$bXXmBIm|os7^hlZ$&4c5}D9TjN779 zv{63pJHA1A*^8=SP;)ySG}Hk%nhENQZFkD?>uq-uI9Q&WEl=;+U97j;!1;{b43-Xi zemz(Mo|pJiyHSbU1>n<+?M8jqJWopIs!TQLL~k#8(G1Hw4VPzU*{_#8ryVr#HTuf_ zV7cn>-)jsb^AIsX{2vT+Rx9u2$}JY?U*V}FXicP+A_lF(}I z+KQj5$>LHxEXss)Sy|1?wLTd znYM`Eq((_u?H7XyftNFciSu`={6I!X#Fwnj=Qtn%-GpU zlVfOUFS~-|V8KIs@m44vdXUmXXrYMUNzk6!VtcCpffdHj`|gZMD2RwcvA*Ta=Y8IL z-#71l8NU0SId%a90J79L2CfoCEc1NyV~ydFT|bQA`>i*|ud3-A2fC#~ zZcm;cNA&vCjxWx$(-z{Wkc&rO)0WtyW5l~lcK4$~?#R*Z#LJ}3-Fq$A@$K$`ys$B{ zW|kkH9p9?Px0`wL)<8mXLR3N^B-1CYL6g&+*v1-M)*5Wy<4KeTS^m_?RocmiR)RbO$bJphp$?Q3Kbhzf%9E-lyiqVWdtwmG8u+o)b*uRpxEe zDcg*X`;Ko>UiPAD7}VTO2MzU}8_fju#kM=;`1Q6s2^=cV&6cP4?<>~ZZD2KHH-n|4 zo?j1^fSr|ZrrQCAXw4l}T!sgsyZtTN_M>EAqt4XZZp4XnrbJ`?*SsX4Hrrb5Q_Qo(tA&dX3XE9;K4 U`}8LhRLm5q=h@*28R4nR1M40PRsaA1 literal 0 HcmV?d00001 diff --git a/Contrib/zip2exe/icon.ico b/Contrib/zip2exe/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b755e000cc59c4501da907479cfa0a6ccd6227ba GIT binary patch literal 766 zcmb7?F;2rk5JmqY3nx;jfcwZ+*F0opz zm{pMQgNUx^e6*yYYkm(d#GS(L!$hkd7g3OAL`)uqd)UtRI zFFd7&!+tZ|Ghe6u${N_t^L4c|oyRxO$*JC~9y?USV4HS>vi*x;?SXE^BJT7 +#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 0000000000000000000000000000000000000000..59f1e0a5601329c9e29b3054dd3300d325e68515 GIT binary patch literal 860 zcmcgrJx{|h5PgP-G*Z>35<5XGjQjwk@>5vYySZYiw?twH*~o7|V(owg-S`s>Y%q3f z5mC%LyKaNT!on%&?hpCc3;BK4D3?1+lPDCO(#ePmLcxa(dwv%K z@PjelP}9X?v7nWN3?asPL+$61U`Nc>*E#)M--p2P@fpziX%YgoJ-vM2@Sdhjuiv!e zDs@~x%x9igp5M&1Yp?6H5XlQ88&B%`*2Q~MZWX9Uby`}ADIBjx6$-{n15_-pkfIn` zOP;VXNtr9+Nn9GH0(bRlwB`Jr^a~focCIhpMr0lnNXO=~Ge5SAy1`bvf^tc}%Vps% z|A)N%B8belS_j5M6K-}~_E}u+IMXk-87kYx%Gwr|z4i{u^6YJdgEqpTiO_HQIA6cw w__M*u2IH?5W8R|~V(Pzur;j6o-G>|{Bdi?|S8lNGJCNJ2kYy=#1bH(^b literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5828c9f1b9b8c60fa92a8c7a307e3627b29f7e3a GIT binary patch literal 25088 zcmeHv4_I8)weK0`00$VDNdg8V(MdvVBATKk8l0d*!T`~bOq?(iR7j$LFhxk=ocys6 zha9Gt!*MkB+I!o3ebyM;rnUDzUu$h_Q-w@~sHvL7)>Qp8wy7RGsH90@k|5{();0amEo0^+jMCV;~&Q__}+1TtXS>tow+frM% zC_OzjH;%e?_<<*!5C7rRh49ByHsqH-cM!!+eFm=t{h)P7mamt5J=fiNTi%-Z}7%jHL~6U z1Bp~&K@VCLzDCMyjwSQUr7nc=tTkNFzP<3(4aD4Q+bL z240cQbXb)Qe9+?aYwsu1_-wAI;u&kdLk-yKM-K=VNysbX2d9H_HCbIFsK@huKXSmT zRL8`H>hIKd`_3iGf4oA?{PyD=Zf>OHEj}bJP>;A?Z<`ysF;%h}p4f8z)X0I5G<_hk z8yvUckM<>4e;Tkk}#(-Hux=M^ZKj@Fqdk7Uo27n z;EG62nELAbz^YnDN|MlFFqjYogU)DI#7E#6lV+=Bf?6S154rl<(n3oaDS{iMl%+fM z#RNV^Ek1?}-p84YFZ2jo)73S$kv>689C?u!t!h~|b5b1AXVpninLN{lhXa#_Ho0ol;mbs6&QZ448)>U z)!vYpoI3^xJ#()`bnF#G+sHv)N**Z9Cc*-Sn44*AacIjyDyFC4B{^o;zumV|?bFjQ z;^~GOnqz-}mdbuYJ{<8lyjaClAVIn!R%3qc8YJa|+3LWCn(FB8-Ur>BKbRTrt&x%$ zC-fv&e@C*~zlUmqyjLrM@UGgke}|h3_f|=Bg1lc@LUmf+MHNDDmi8K!Nmap1`!uXh zHH(@k{4}}ODfjV34Q+0&{iA}T&&88v4@Hdv8|Ojn2&y=CfnuL4C1^S%syo3H)0AF`?Ze~InJ-fwB^$hACO1Uhv&95wy8LB_DJ| zgKiYrC}>9v!vI#|dC+KhdL#DZBa7TzEv;bATdT~cSRQg<$0>E1k;Ma|;AqbqO4j2T zhkB^Rsq64ayT7~P8Jq*rSO zoaz};1vN#fIN@EZ&BgGms-h|gmQH9JQ7spBp;dyIsJ(V6Iu>(z%|N1oh&QrmQUQMf z=*JU4Zy`|?hY~=nIbm#@*t-s*@m{w*yr1F(G1cb8`XBsHfu}4-*%y#y z3kVa-mQNNdutkGh(83BJq-j{uK+v+Gu;_I#U7Cgp!N_ueeO@EWhDdJDwQ)Z6&fH9; z=rBOKXVa#TmhFDpq+za_{u8A9k*|-rhFfQ-NhV$LC%kJ3fwX;G)8HhcvWcjx&}CIs z!vZSEr2@|HOSsald-67IEkJxA&MNCUr*gE(^yM{*XmC#b`POQ?^I+g^AQ z$V__P#d3k*5|_$m|4MSCn|0sUmL1xN?ggXYotUcHVWzhi8U-do{6;xe@IPJ1i*Kf^JN}6 z%Dcwfe_8OhIoM^#jmYBTQbqXf{!+eEN(_#y*HhJKIa_DFe*xlbAXa0tVTdyWlik?n z8yLNElN?LHB3{kAb-Nt1N~uT+I*;$r3i-UX{of5nxRI4f(^pe{hkURk3jXmv7vqFK z(AK6NQiuD_vSW2wWa3!0kCa@?TSUKCv*ut;#*8Y-W}Y-D=vQBZrIF26aSkY4KolOA z&*N}0vT~8p6AF64ixjVRoJ4@`RFgxs`TS>*l6+o`>Y4KV2e4$Z8b}==gxEwlNX_Mi zRfB#1FiNXxqJC{25;S)t-D{#FrRi?bP9k70*4XIrs+!AsqXoS+Q6C)!wt~0m6jl$( z?^{D>6QmpJeAt1R@8W1PVq9-Yzf-+3B~VVmF;{D*rSFyHqWQ?2yHLtW<|ZvU{~f zbUJ`@;_MarEGp%s86$lOVun|n5wDUG(qg49hOGT(tf3ke6X;luGlQr-fEgeTZ0#Hu za2iT{L9d?HIZleKbT@QZBXJwpSU*~7vst9uaB zj7Vu_FhL=ix?U;GhIrG{)ti-?Y-NX_+@#d-^_{D23Dbak!yPq@y`YWf{Nh|`;qO7@p3F#@w{&Tr+-5OBR4!e7eE!mhEjQ0sXVS!o=_@JDwShO4@1Quc3UvGYtN7gGcZ+l^U~OB13d(`5?p_2~$(Ab_|jYqgOm< zpj2Kr;5km{^@Xx_yLg?frHC(<+q*QB4GI{bcAV_5Zq{_bbA~`oJPItI55XHY(4PT_ zHhO_t&WB$TuO9JyCWtfbFK|aRj1fJ>hdKCj;%41DG;-7q?m>3Twv-VVrFWC5F}Vm{PG%b&n~Y{WQbz5k)-v=&;37P^B^XU}onBA+!}U z<&I%a%7_CQSyuy~im*?IpuSL?%ZeFWuaVL*k(S7>p97=7;ed8EX|aQ2pheai?OnuV zSxdBcJ%$9>)J2iFmNsD5XJ}K7vj4?kup?hWs{zj&UqN19me+SAHuwxm%-LsSu875_ zT@*q~InfFWFRyR#A=Ye|97<>nQ-~Y!jD^5^2t!V+?(w|Q@A)X7UpwGA3GQ*-9$hbw zLr@#hg&`#9OW3?zh8aYivr0^Kn}J_;3U^ey7FdQRunVf7sK3)AUCSk=Q^M@oG5bsjdusM?=4AR%=UOYIj} zC#q-Is2C3S-k(G@qD%Fh`R;ArfM4Qa?Ma z*6KH402>vt?ri<%K$wS&Cx-qLuu8>C)rwfCFkd1|E*(H_2V?C4?4A( zsD(~VB@xd@q<~1UX|6L%N21t1BT;@zi+t@*K!+A`$2*)@EO(sYcF@?>>R4o(QLkE8 z0M8-s3hfM(a~NJ#JFbgV46OxXR<0d4TdMPPSRDM0) zs>5cUd^q#MGtL?Y>@Ma%XrArnN^+o~Av}ff2ZWChu0Z)u5paO26*glfzb!+Z*5eVn z6AX*}S!e-7n6?MjUsV+}4eWC%5xQ)3)ZnV4@bW$E!*4W;au_=&e{he;`GL^hufH zRSqI0o)KV97RS`J6M0nDQ?03`1?>M5RLJ8e)OWY0LyA~~mKwR=E`KmwV4!sCRj%3I zZEkLBx=$N~<_;%c*pTx4LBUuO>Ttv4ym}*q6!bZ1u3R*HpBvltQom+5)f+KWf6f<# z%j}0>3k0;OOhILe`2#^~fl(9J-AbnDZeJa7+hj4_tNr-XxXNZJlgBgLXEGRL@zWXv z7{@YIa_-aIgvz#`kWXl>Vy<61NmCK-^^2)coIy_&v>&L+akBG4HrNa^iF`z^BC=EL z@;8ARM#JbAxwi75gEt1W`^iZ`n&h%cr_v?C1g!zZL5r$s8<41Sy;vpY1T-I|A;=e_ zGpx~6QzKV3XiOgmv|riLnYD_vaW4F^m{O@-p8=awY)m6iZZ)hoDJvHrLe-a zBrJyd&U)ME`2r|CNu*4c@=VuTyB5>Du|lUvlcdV1;xZP8K@!Cr0|*QiuGKTmKG} zaj8vye_Z}xOnxb$^VJX_^_}}jUk)FVs?rV(w$h5%?h>J`ERwY}QWBFS_sEOAk}LEZ z_n;5eh1D@>(SRpLopyd;ykHoE%i_f|CyHO?+)xDOqZm!aaElHZx1kt9I9K#H^8GtnE}c>{-`=_96Xdb+N4Hsas$O*h?i zc5_QCOLl!GW~-yFzhJzp9fs1(E6p~gSx^=!%{gj6*^#8v`$+gK0qqcz_AVz9>Utsk zw!JG0N%?%DWRo`vSfJ|%(^&yryCYzdn*I*#6Qu&GzD;3is5|mm!5%)uYGY7j)T}Xl zTaWl%FLz``7O%`Z5?TE7ZWNK7(Qms&8ill3!i#RM2-Dk3wkc&~Aka4#?V3{5Nk!E~ z4^Jr~bwj_U=%1$)g{kOVP4S^dsWw?BJy zWap-KH^+-M!xA15lX@K8mz26$`nN2tzsfRv=t{1X5R|(06|5wYRrfgD_GjN3k*6X_ z?8)xFycE4S#T4|C5;~V69qu|RS<7_+eej`r1ExSW2i4c!bpj*naS&`G!I3J=%4uUw zC0?z}G!h0p0?kIj+o7d*O1yi8K1w8A4J}NX4-ZF2wwNB;W|j=V+9e?pLA!bVYyX0-QxhAx5ypY9NbYLfj88~YRnTER8L;vQTN@yJFAh8dQ@nUpm|tNayAU?$`r={alH?mmgL##gCc zX!>-dJqys_FX!Qj~)+#`$G1qx}*GDKZ>k^O}#9qfSYq5tr zk-!?VneFXe2avBXyj<-UGu-a_!fffR8T~o0Uo9#Jx+5{4&+YSh{XU;klDpV=Q`KC$ zcwMDd3#*d03_O|QJfE+Ut`u?sWxR>AIRhDo_UlpFCwD?sL+~3}B}86S_mOLFmFql- zj0uXxWlOJ62O!LsW=rSkYb0;Lt!kCpXRu7!c7}6kL{F=Pz8;&6!5p-~W#}e^{p2wr z$qiS1L2r;NEXfrb=%lkh(hF^Y15CJg52;sTmiAsc33bUnp}4F=E#wVEdGs&|et)16 zK5MSwnQNep;Sk8lQ2KHBKBO>Si0f0OBI}nsdbkk;Pk7+s~9$a7UNhDyNMJoR zp1^gXa;u=M;FYi0s_rSlwqhj*e2W>GnC zYYK6rtQb?lr1gpg+m->!r~L?SGWj5n zTE9`x>f(p=-TP>4dJY?jo<+!mhEIFUY+uca zCnlv5vm&Sq)#4nlTAb}=w~+Edp&BFH-38HyRWGJv#;=l#nsCNgq&W>^KyIqN8ukv9 zT6Vc%P-z0b*ky9(5UDO|rGWcBC-~@ch-q*$6c;^>O#3OndJ0#xu79B_dpHN66P>{| z0vzZtJ>H?c>rE7No}*svU8nFJ3Ezp4u+zW`6`CCfXfPvQF4W>eL|btQD5)}w0^Z24 zsfqSHtbI4^p=DbZnl)bSDHP%8U?^qH6|`Do4LmRew1+RJ_2P(xH=y+OY+;t?XOK@fL1*K3!9 z7-;C%2hW(!eQdv4Y_J-3{IL6ZRT2U&=DD}aFM@4qKQ6stAApG%bfiqVAA0d{k$#M^j1A@_W@MfKR=8-QDiF6qgeCBFhN z*s(p_vRU@7|3qe4x|r6TTxNJ2gAXISvarI@h7;Q1rW^ev+2csiYxbc%EAMwO1h~FhH?D zHtz!?HuH*@Ayq6un>qDb5YHC`>+f`}@54m(J@ZP4d>(!mYaM92?TfF_F3s=-&**|L_!r&k3yv6BP2j1TtmNbu^xpAhi-ob=?@FiP1llU$ z_dFH%8Z4W95R+`}XDqovUTVM-9hc`<6!hjD5*;f=VWl*~OFet3XYYlcWm~@SF#d9tsaVen;`RE?mWwZ-uA}iznt9XitN|lIO9xJdW0$0yz3mW)G_%p|C>`Hv|*cdH>H>Qh zw+2H1Fr_%&FzEx4iZcN?8E^++Ga%>VodES2j0hTx{=*BvkCL#PHHI0{i%dD`7NPaP z?txtX4fc=O7fBYSh^9urB+oPaWeb;HrD4aI3#io!k@LAV)Ppr7pKwPHvk%iD`$&+9 znLU=`u3phS%Cgcarr@cTUmD}%JFKtE!$!dY?D8LR7E7n7sl{V}y{_w|nENA)oD*jt zf>cbL~fz#kjKz~b|Xl7)QVSq_YVx~|0oz_*L2TQj)K2USG zhv6?P$<0pdm9jxaCen_Aqob$P<4D;MAJdDmYw+NMv}h_jGI-?eBOe_(p7xS-X7n_! z0cvxz0fA>_qaRq0v}U*fw^e9Ob^&&aWp%+(wZG<$0}g1j=Ep~%@$MKx)*a3Ubanu@ zuwK@k1KrsGDSWQGL+CE^VSG8_ec8}g2Ko}V2zj9WvURzchy}#9(YJ6@@fJs&Gs6K7 zIO&4E#<6#&z3ViXK~I2miY?+LbmzX;Vfy>j)k5yLl7U-!z_WKYbv7>dQ(MBs+n~AT zZMZ1JZ^F}j+IMkxMCVqrU)vkQ%B3rD!4eQ_;|~BL6^QT3J2zu(Xk_tC>4hytgWPA?68+ArQUB}6G6b_m^qo*A@2&D%gI z>n2eacGxyx{_&_lw_{bYHygUZUOLfh26%zY`CyEuL;t8)R?yo6-UZaN@;Scsn$h3m zDT65F9f1n8QaYy|>N_D=`zUfCdRhL1wQn#%OgjA(nkE6}7QmqS2DaUzyN93@UfM?w_h#xEI%0NHrdkO_57v`f>`?!l_jQ|k`;ep9vkOYrDH7efTaYKDb;5byace}!Gr~Rp>%)WSw494$_)wx?Q2`$ zi?FGyX7H|6GX$v|n^QjPY|D88q=k-s8d+uGN8g;&{&dNBij;?5=M?I>a^Hz~HK5}V z`=36D763{jpzS;`3TpcdUSUZdNx=%&^>zWosOS3(evNG0yu}*4c>~0}{66R!vWFiB ziaeNv6=RG-r82hicHAph*tR4p81u{4>M`{^5Kwd1xh)CmIoE6A*Pt}2Yk3z8(Mjs* z?kIHZBSzcNIqNP^KaEizub!a(=$uC`qJAyUPzvfwUb)3g^Xf`LxkXSbV{*q3C#7I9 z+Pf6=f+rRc+t~?7N&`#*hFf@Lt$=UWErN7+&#GizHk{oR_VK=Mq}%3)I_$Uz{uR-w zzIIFp(^4*-%tcC`E=kGO7cwA6WX%ayV?tH&$WP2p7o$66sS2ighLu^$oioM^IDfHh zxZSku=xNt`L}q#ua%$0?5TkwX+pXocUvVKATAUjXN!G%}!s=O*ICE0G0?Wo*x*hV9 z-897}Ue)awFJEB-lsiJ(SAZw-Mt+=?$lGvp*o1o{W3$b8lNA}89T)ZoUEQ!nuV%3& z&xiU>B&dfNVBVp~s%b-OBjuTEz1rGoq$mgwDMmVN5?3OPX^U0XGVxjgNhO^&lWqmj z9;#B7&@kbzh?{?zQ@Zi_BYX(&cymsm3faxE&j!RVlYMUm1Lx8IoWq{N_rgm3Ov`c4o4E__qXR!D5>hUmce*`hp zr@e*!U8UaYP%P>S2UJt0bJHiTblPdxH|nLerlVBJ|>P0fS+IR)9%H_oq?$8X+&jbGy$wRh2FMtqZO z!UpNco7@8s0+IHm{OB>IdT8FA-6aabxLv|h$6d$JoHYH~sr!P#Mjl`*boAJqOULbK zCZ)xJZ{@K>&<-2;K3?vKaU_+nv+oliknCNL5Pv{v`zbzRJEh!*UH?~GxVC3i5-*Qq z3#WA~9PbNtq;cISk;Q|mCb))!#W=qN>>{&4WO1i?d+ZueN*&@=LB4@=l1#yo1y8BSutDdL=(+u5C$#xt z8qJhf3kIIY?ciat1G!r2fW=AoVRXo?W#?N!{kj8IdBNM^UaY4RaH^}(;LVM_biCaj z>B?tk8!QO7ptyOMmA8OB=YxFThj#0B8*>3PkdTYh0yR{?jvmBS6&Lwe`o)v$+}350 zGKX9qGvw|eI~IMUdkoQldu$jHSlB&=J8Y$#9|&nEpu$8tv?Jxiu9vqA&@IRsTVf1r z7;lUL24_O#7MoHoD8;;7`&bF5?0<|lUr*_Zo#%h(F;N=2j>#*bNnNHp#Yw2*nmK(*2EO7=zfpk(9=S71})PV>P=JhDMSukJ7tZXM5@ zs3ZiZkQ{S}SIRM`m@UWh@e_=gTl$qE4eMEW3xlS(ZJu}(gP*Sq|B{0bWFN5RJrh91XVTLx{rz;tVx?*LF8IdSqTjCiuo)LEu*mshzK)9{d=w zj2y&0U)m_FQh^l;dg@+>n8eZ!?c^sgJ&)tp46gU285fz|*+8J*6y*GPlM=xjf4uo( z4^&`Lw{OI{9d?b1({a;~gAA6~Wk}L%0n_;NYPmp+pF<4(4rt8x#TABIPoek4G))4W z)SnRuyk=GEY4sJG#e6>8?MaJFc|jbiODl&jjhD9Jfvq^=u_cJj(4FC;{>Cw;JL5$I zUNlM>oy>le(VJMI-yEu&fhS5cU`+Y6p^q3KXuKrUF=G~4uERcUUOJ8v_8ek5-9q@Z zyh(hL&8IyI&AbY`M!%FK9+sKMCWvWxfedG)Gs0dVvxPfh3?ZiX7=j**Jedn3IF(t7 z0n_3X?WO_hnlM2Bw(U6&w&yI<_RP3odu})M^vL#cU5IS|Ot(h1ld)-wTXux==T}0(I-3TtIpHsmS8n@Q$SK z1OCU6$F_l@kc(4a5wGr9YXLuS{fZ}1=Uf9@VQY-_d}|{Bgk6Nj?Hbtfm*V13At${7 z6+w;)_|X~P+6TclkhltC2IZW04~<^yC&Hd>LfaSI$bbL)ReOl`@9UL7u-$+VD95IT z31w0!xQh(5Xg%fE9zbjYUqGrSDYL1Af?kI0si&UO(+g+EV3Ua%+Jk7I{S;p~S*%#D zY)xYFczHfSfUDz@V<3^zM4&Oho3Z+{iwnD0;h1FKO+JSU;LQHJ=1IscajvZK;!Igf z7j5MtxnB11kX+Gy)7du8;kTD!Xvhu|x6yZT$t^mzW-Y4JmoM*GZgk^t=NZuYy?Cep zD2^Tm16P1q>z}Oln~k)Esc{&1w>}TkKq5a5X91ji@XmtXNQAnqSEu2oMZCnEdPmPA zi9_h5d)G#cUeCd0i|8<`oKywe`X57&QzhpvE(QZ$&{xK}BFBnbFO_4rZ_S**btu&5 z?Cxfmu8?D!T4%_y`?h9GpgR;Abm}K2kO9^6xGR#2=;a4=so-bY)#RreNTdQOj? zKe<{e9QdUte4$6I{jTvXf-7dZpn8@b=^UWL z5Av-x`GnPa2=D11zZJaBjeG~yyAbD4{4~nmLEw;?cccf-hn`YPcbTQ9Gy!P4%M#>% zt31GvAD%=WS$P4LL0RPf1bHBVNch1d)GiZWDIm(I=7Gr?w7(zyH6hd@+=;LbVHH9N z!ZHN46e!arY0oTNQoHgeokLF_mssKU2yOtuo9wCI#Q)-=eq`S~r=boK{mgtJt zUznp$668-A_aB%7xoZj>sK@BybM=W;{*-3azVmi$ohdDV`wjH}4#G)+_?9A+Biu>2 zC+4NpiqTJ*2bRZZr_2Gy1{kyKqIqNQk;Wiy@tSIRgBQ2MM%FHfS9&UfpBFB90O^Jj z6bFpo!Bs|(qPJnOSs-`gd|>tqIt8M~<@e{LY6Dn?%&fQUCsu4^N zSt?P(?1mYcJE~{w|K*tD%Zq9#=(drYa)!D>L=%PTZnEb)TtcAcd}wq6C&_nDXp#B)>$S#Xt+@fq-`j_*#JAMVOF7evRZ7~u_s4-qgg{{`}lI#UhK2W1r@8{uk%$$9y| zk!RR6>?yOh8k(99z9fIah-Fy5LxUAqR zP~_99-Y0tL7sHQ`*d88z_p*`Ecj3D;CZ4Yl64T0M_oLJr&##6KvT?$ZGx66HQm8Y! zpkY2){ItIT()|m6+Mfd>N~zOunOt-=#Jf})z;Czj@HK2i1M{%~Tse<}90-0vnN2YI z+&}<-Q3L?6zp@@>b@ncL5I>Me^$F;_up@H^jNMFJ)@t;!rwTtS%-l`2WRTA`q#Q%a zHtXp!mwtCkhz8#!!s!L$F^0q`3Cu1~Jk9`YJwm5?a?PKx3vT!YoJQ7n&`yQx_oVAR zd)K3AMvi9wGP&29JEqORv4i2M2Nlmd_<@t5!!BP>e;S|wKkQ;9YW2y&j(5a*JO+Qq z>;b=JpTLVjS75NL%A}H5p$;q3akwC^8}X#$xpZMij=k%r=-4IY+<&<_w9hxeoj~{@ zfIt_oJB0g-T7{<4^qR-t_DA^ZO`11=fkg8=O7#gw^YlrY@h4?42o=4*Cq9EW#?r~p zkp_Yv1wDa)#0LU;l1Yr;XI|^lsOV0Y{3rIVuR{Y;`v;pST8GDVu-w8&{gGP?Je$SO z&~WL0Y9-#!oJOWbO3XubR6RhNIhIrC%a#+_#8n8t} zPUXVt?8!xwjd!Z-wSekzPFXbB=AuzNCtOkSZkXheWjJL`=KldGi23+w?>hnfL7BOK zWP3|bo0tQ<&80cOtK5b7^Ahk-VVUFRoR%|Nia<#VAHD@z)HGUpxEiTD{JB{te#al+ zwB7!>#{`jeeSFWVKAwJ`e^XE2^CW}jBXEUcu1!h|y??)+-bsH&!3`s5TIi(^4X!)2 zem>W0?XQWN0*AbgdR+KS$b$)uWNi_1sp3s#Yi8#lrLUo{u!WVk4doqD4~8x3`}h@< zoA*W!8}m0}ApiLM-5j_FZ@}s}t_$H?2tPphCBk8ZcMv{87(=ktbKK)bL4-FDP9mH` zNX3Q0EQG5O=mQyGY|e6XT?k1W{zGItIBOD@l;Ge!9#0~DmgI9@0(LG~>Rq2Ka5v=V z2fWG1JK=)iIALSMMttyh%{FhtM*sxe(}I9Vz(303Z@4vc64!)(3#kdWpjm2aLK1(< zPHeol&RN&m+S2OexO8|f)~#CO^O+@-<$NnwmrcoXC2J~*SFXNLa@+O!*DXy?y~Zgu zZ@R0g&MCIwuj4g}jhmVp@2hh*)NR_#&~OBI1HsXs(W`52k?v`5wr$>Ycb&5yeK)mi zZJg3@li1kOe4*X-U)rusto}40vqR1-L}nj zcZ+qkj58Ow$Ps_8W&DxQV;tsQsYz@U8(Ql&)q+EJf9><|U(T0!Bl^2{AU8dA(_PIi zt@nZf6MxT8tZTiuvH4;?=d^u`PMi&Bsa|D9yk%f!VME%)BLskwGlV{=_G zhaZd8iT=9QHtZ{o>)<@tDVUMF!AS10gmv+SRyR?^jWP^UYb(~sMB%*&zB;iSD4Xh5 zv|!RP$Ar}<)|!PJmqq!~#-_S;+c(#7UbA)+cJ=0!&GjwC+$<`g*=37@R2g6-crPut zx>k<+uB9B(sJIC`iTfT)m$ueHvR}rnXliMzi+A)N36;$ajF4K-w!7;#le7RDh9Q^w zsA#E`n(7GiYOJneNP3R&crNS^pV*3Z-d4>0>`Q6_+|h(UV{P4vhE1*OS}JIlFW)ZK zaY=;#uMu&=7ncV(?tidxl+?9}tu5QRe`mQBkQYG4y^!EHr5+pRR}*d%n<|^PVwH36 zB?MXog+ zPje!qI`IvKzqzgPo@N}}cVp9{%^mY=tDQy8Z#bQ)91}S=;^>!}YT3cYG=UaL+$@RC zdTa$C-3pl&hoce(Ru55Ei@MgkIIfaTog1BZH8x+@z}nCst#twiK`&~6UiG!Q<_&b9 zrEx;%$g)5tG8Y4)J}6OAwDCb|a=sjeNuw#N;oS*n`%1n)pV2 zfuGEQ3EPm-N@KJk5d9Pr{S*`ZR7bp@s3W}O?4sC?Kz-2osEo!(W1~Rja}cO}NjzU1 z&##E*y@;vJZSitnJjS8P@K+(GzMJCZ_ab&8Y(^lSv?36#G!CLCgg`WR#^arcsa{5) z`Yr^b2XoIX*2m)c-H3_aClRQ>A0iOkFA#`6a$!;Zn+Q~&4W;PK!3*M+ft{@=y$o#4vEKMVKw{hNwmCwJjr0=V(_{F`X+ zoM6;HV#a|OZOADfO9DN6!TLk_#+}=D&WYFk;5{?3`}=0x`Mndg)j9W$5R3N$zHiT4 zdz@zVUwwCun?>$;{PVvPzBms5EZ|>z;^Y&vxIaCiJ#ojEDE|NP^S=S+T*{{a literal 0 HcmV?d00001 diff --git a/Source/exehead/bitmap1.bmp b/Source/exehead/bitmap1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..9bad965a0ca456448a621d1d6034c7cc76849a33 GIT binary patch literal 886 zcma))JraW;5QR6B%%n8O$T`yI4mm<9*A6@Bypl(q6;!2&Bwtyw?ufUZKEKgOT#cgbwcbV5$&Pj(N8+I2q9`Y_X(NU!j&}P zA)qe8mGtW$DqT6cOs`t^?LyMof8o)ybUCrZ5Rcm|)}5BM?q%e3|9 e=7+zXS8r~|ukYv2|3O_4A$SW{(mq98R?Z)vO%;Iv literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d529d42cb80bc1c0d0f612d102a59abf59153f50 GIT binary patch literal 766 zcmZuvv1-FG5Pgmdwx=XZ$0ptS5ry`XvYp8iZ8jZhGJ4D0Lg^j|`jl)51cEo4w&1># z)VhH_``z8so#c~bAmTHhPoOxCfNT0Ya!x*y5w2(n=KhBP_`(?PXc@vrC<()PEBV;Tf&&hm z-lc~Ny=g=ig?Qxha%9b*mv5)G9ke{1w_K8+Cv?SUYH7XJvHV26K*ddYlv~N!hqmKT zXj_r*Ms3L~^=|`d;q=b}xnVihsQm0otDSZpUT4f3jL`&LPyXsG3!3Mw^;x~7!W41~{30cUfkuFlxEXy3})}rN`908T{?R7P=vXo@}mST?UVHJD2WCP zbbNNZHzP7qp!B7zU5}Xh`g}{>GQ{uFM0n?yGFW zf)f3Tw-dV}Ca2G(ShyA@DhK9?iQww;D~bn4aV9gNi?p`{Pf46sE8N52hauCwun-3p zTa*WaSh*siEnTT%h1x22RKoJjjf#A@7RQcuaR26SVD2Y;`ijwylwmvp;|dJV;z9kh ej=<(g-OS&X+E6_;8juW~&***O6~9RCo% +#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 0000000000000000000000000000000000000000..b1f13afdbadf6d4af6dcb1581df8a66e2088ed8f GIT binary patch literal 766 zcmchVJx;?w5QX0&3nx-U?1mO28V-RJj=~YrZA6ppyiy9|4xa&uHU$!-;}R5fP^L=| zmWMa%IB`Kk!>s4$o7u5vR|X7MmL*X6JOWPXFR2;znraZy0*{BUpS!T_7VyFScE)e<1k^($J4lQ zEOi|An{?0ooc1fLVLRWi(N1(8*Fn$cda`!xkPU-v4jYO!<38()`}_}e{X{1^-)7qp zFHPAUSkLKi4$Sha)MFz}Y(yFed*vQRc=r= 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 0000000000000000000000000000000000000000..121a7382053677b5527c576149a996f788a8929b GIT binary patch literal 58880 zcmeI5?{*VK7{({0EujQ#Ye7WN6;VJ1r3Dm3#HJKl`DcT~Kh?5L$2K%g;%+!VKY0P( zgx~zCm*5TPCFmDDhg6o1-Nm&v2g3WcQtUXMVHk>3Nx%{q>jO-@gBG z|L>|UT~KlL&-xBE5V#&gS>&Z5h5PI4QZ~7iafzvm2>gw{T9~&u)CcuLGUwZ&1hfMh zgmywQ&%2QChMs}&2&iFb1bP-4h4w&V_Z;$l(DTrK=mqEibP#$GdI=J{Y2=5XSD?et ztI%uE5$Gs%40;_B+c%LPhfY9mL2pARp)qJ2It7W{8RYLk??PvxbI^OxdFXxU0wi`9 zk$(tHKq+Vvx&%!@m!T_=*oi(u`6_e`x(?ldZbBbJvrrlmyHAkchBDBn&}Y!+&==4g z^d%&A^T_W&Hnad`p+!hTUqeff*yWJlg;tevss;n%Gynx(M z57A=lX)m4_<9p+GLxbuUzx(Nj{Mnyl(qChefp-U^b1@nl6f}C0Mn7ywSTswP+7{ae zBYAeEAIA3v0R3*qPM1xtmUL$+1_hsa#&WbJx?;>A7_A zo|DyczNyKNdsR*>x+Qr4607!#F1T*)SZEu@%2Z1l|7-c&!s*be_3ovHX+}oIL;@s0 z0wh2J|2=`eKh-w*!Gm z_+Rf#Jx59cBtQZr5QPBae^F@BmIO$E1W14cNT34=F#gwplfo{Mz!nimVD;a%t245+ zmGQqVVoo~td_?EntdLM|9?>~;2+t{+bBbB#Z_jXR-?>~R(#_WY5vrF5`$_?#SE{ERS zV>WVoyTWTLCTF$lZ6U9^2(~z!&N{hL`K0CeX1>1>^SS;;LiVOt+d7mfIxB9;&T8w3 z>G_d!*0@!2ig$IkeAGP_bl0+Z%Z8QK>nXM}CA1*{5+DH*=yU>%|91Kev412$0wh2J zBtQa92r&NJ1Q2hNz*9`%&ZEl0&x5sLyW>_SR~R3&W_4cMt{(R929J77s1%Nfl(<@W z-SE3|7U!dWS$Zm^zr2#*9!QL)(-X5;l)6);ZrRR~E>D;BYItLTipk1Zm6g*gV>rUr z>+EHxc(3F)-6!WpZhB|C9E7PIchj5wiP6cKjQ`V%aW*weUh&!s=}V=#-6lNR)H1%P zaoFalN=@pLE-dOo_F<}6DBHP$cKqSh^waCJ&|xA05+DH*XqN!vf9;ZEJrW=R5+DH* zAb}1c!1!N>Oa!|@0#AT|iT@oi@jr=*S#{yRArt8@xLgvXiEYlKmsH{0wmCZ1Q`G8z)4}3NMMTynDZCgbvM|?`GYg!%s+oH zg>x2d@65y7IQ3BD#7Rpax{wLvcLETeJ_@|W<8N)~$CbRNkG+FQ)Uwh1%GYj5GFa zGPuaFa%tn;G4io;SY*R>n_U0t?Za;Un8(^V2wl}#Gc}=>T>mMLDiaBi00~4U!1!Ne zWUN2}BtQZrKmsJtSp*pW>#X@;Z%AM(2@HDCKk;Z*5B8xvkg?0z<&&l`W(wn`aLV*i z-rS-KuIs(An(;rpHm2#zTNwW{4-az^AORBSCIXEAb<=FIuOvVMBtQZrKmwZ(VEk_r zD7-`hJwjjrZ&+6T3P9QIs}$pZ^5W^5*C%uTZ;yN%I7|{C0TKuy!1!MX9Nr=U5+DH* WAORBS1_F%#b;B&Nk0kK_5cn53I4Z*c literal 0 HcmV?d00001 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++); + } +}