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
This commit is contained in:
kichik 2002-08-02 10:01:35 +00:00
parent 9b3b220a13
commit 3e9e73ec59
177 changed files with 37677 additions and 0 deletions

463
Source/DialogTemplate.cpp Normal file
View file

@ -0,0 +1,463 @@
/*
Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
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;
}

121
Source/DialogTemplate.h Normal file
View file

@ -0,0 +1,121 @@
/*
Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
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 <Windows.h>
#include <Vector>
#include <StdExcept>
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<DialogItemTemplate*> m_vItems;
};
#endif // !defined(AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_)

74
Source/Makefile Normal file
View file

@ -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

BIN
Source/Release/Script1.res Normal file

Binary file not shown.

1
Source/Release/vc60.idb Normal file
View file

@ -0,0 +1 @@
Microsoft C/C++ program database 2.00

780
Source/ResourceEditor.cpp Normal file
View file

@ -0,0 +1,780 @@
/*
Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
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<CResourceDirectory*> qDirs; // Used to scan the tree by level
queue<CResourceDataEntry*> qDataEntries; // Used for writing the data entries
queue<CResourceDataEntry*> qDataEntries2; // Used for writing raw resources data
queue<CResourceDirectoryEntry*> 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;
}

167
Source/ResourceEditor.h Normal file
View file

@ -0,0 +1,167 @@
/*
Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
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 <Windows.h>
#include <WinNT.h>
#include <Time.h>
#include <Vector>
#include <Queue>
#endif // #ifdef RESOURCE_EDITOR_NO_API
#include <StdExcept>
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<CResourceDirectoryEntry*> 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_)

72
Source/Script1.rc Normal file
View file

@ -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

5
Source/afxres.h Normal file
View file

@ -0,0 +1,5 @@
#include <windows.h>
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif

1971
Source/build.cpp Normal file

File diff suppressed because it is too large Load diff

169
Source/build.h Normal file
View file

@ -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_

1100
Source/bzip2/blocksort.c Normal file

File diff suppressed because it is too large Load diff

790
Source/bzip2/bzlib.c Normal file
View file

@ -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

174
Source/bzip2/bzlib.h Normal file
View file

@ -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 <stdio.h>
# include <windows.h>
# 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 ---*/
/*-------------------------------------------------------------*/

View file

@ -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 <stdlib.h>
#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 ---*/
/*-------------------------------------------------------------*/

681
Source/bzip2/compress.c Normal file
View file

@ -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 ---*/
/*-------------------------------------------------------------*/

569
Source/bzip2/decompress.c Normal file
View file

@ -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

229
Source/bzip2/huffman.c Normal file
View file

@ -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 ---*/
/*-------------------------------------------------------------*/

127
Source/bzip2/randtable.c Normal file
View file

@ -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

51
Source/cbzip2.h Normal file
View file

@ -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

22
Source/compressor.h Normal file
View file

@ -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

34
Source/crc32.c Normal file
View file

@ -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

51
Source/czlib.h Normal file
View file

@ -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

17
Source/exedata.cpp Normal file
View file

@ -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;

16
Source/exedata.h Normal file
View file

@ -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_

364
Source/exehead/Main.c Normal file
View file

@ -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 <windows.h>
#include <commctrl.h>
#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<m_length)
#endif//NSIS_CONFIG_CRC_ANAL
crc=CRC32(crc, temp, l);
#endif//NSIS_CONFIG_CRC_SUPPORT
m_pos+=l;
left -= l;
}
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (hwnd) DestroyWindow(hwnd);
#endif//NSIS_CONFIG_CRC_SUPPORT
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
if (!g_filehdrsize) m_Err=g_crcinvalid;
else
{
#ifdef NSIS_CONFIG_CRC_SUPPORT
if (do_crc)
{
DWORD l;
int fcrc;
SetFilePointer(g_db_hFile,m_pos,NULL,FILE_BEGIN);
if (!ReadFile(g_db_hFile,&fcrc,4,&l,NULL) || crc != fcrc)
{
m_Err=g_crcinvalid;
goto end;
}
}
#endif//NSIS_CONFIG_CRC_SUPPORT
SetFilePointer(g_db_hFile,g_filehdrsize,NULL,FILE_BEGIN);
if (loadHeaders()) m_Err=g_crcinvalid;
}
if (m_Err) goto end;
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
if (g_is_uninstaller)
{
if (cmdline[0] == '_' && cmdline[1] == '=' && cmdline[2])
{
cmdline[-1]=0;
cmdline+=2;
if (is_valid_instpath(cmdline))
{
lstrcpy(state_install_directory,cmdline);
lstrcpy(state_output_directory,cmdline);
}
else
{
m_Err = g_errorcopyinginstall;
goto end;
}
}
else
{
int x,done=0;
for (x = 0; x < 26; x ++)
{
static char s[]="A~NSISu_.exe";
static char buf2[NSIS_MAX_STRLEN*2];
static char ibuf[NSIS_MAX_STRLEN];
buf2[0]='\"';
GetTempPath(sizeof(buf2)-1,buf2+1);
lstrcat(buf2,s);
DeleteFile(buf2+1); // clean up after all the other ones if they are there
if (!done)
{
// get current name
int l=GetModuleFileName(g_hInstance,ibuf,sizeof(ibuf));
// check if it is ?~NSISu_.exe - if so, fuck it
if (!lstrcmpi(ibuf+l-(sizeof(s)-2),s+1)) break;
// copy file
if (CopyFile(ibuf,buf2+1,FALSE))
{
HANDLE hProc;
#ifdef NSIS_SUPPORT_MOVEONREBOOT
MoveFileOnReboot(buf2+1,NULL);
#endif
if (state_install_directory[0]) lstrcpy(ibuf,state_install_directory);
else trimslashtoend(ibuf);
if (!is_valid_instpath(ibuf)) break;
done++;
lstrcat(buf2,"\" ");
lstrcat(buf2,realcmds);
lstrcat(buf2," _=");
lstrcat(buf2,ibuf);
GetTempPath(sizeof(ibuf),ibuf);
hProc=myCreateProcess(buf2,ibuf);
if (hProc) CloseHandle(hProc);
else m_Err = g_errorcopyinginstall;
}
}
s[0]++;
}
if (!done) m_Err=g_errorcopyinginstall;
goto end;
}
}
#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
#ifdef NSIS_CONFIG_SILENT_SUPPORT
if (!g_inst_cmnheader->silent_install) g_inst_cmnheader->silent_install=silent;
#endif//NSIS_CONFIG_SILENT_SUPPORT
#endif//NSIS_CONFIG_VISIBLE_SUPPORT
ret=ui_doinstall();
#ifdef NSIS_CONFIG_LOG
log_write(1);
#endif//NSIS_CONFIG_LOG
end:
if (g_db_hFile!=INVALID_HANDLE_VALUE) CloseHandle(g_db_hFile);
#ifdef NSIS_COMPRESS_WHOLE
if (dbd_hFile!=INVALID_HANDLE_VALUE) CloseHandle(dbd_hFile);
#endif
if (m_Err) MessageBox(NULL,m_Err,g_caption,MB_OK|MB_ICONSTOP);
ExitProcess(ret);
}

81
Source/exehead/Makefile Normal file
View file

@ -0,0 +1,81 @@
# -- Objects and source files --
SRCS = bgbg.c exec.c fileform.c main.c ui.c util.c ../crc32.c ../zlib/infblock.c ../zlib/infcodes.c ../zlib/inflate.c ../zlib/inftrees.c ../zlib/infutil.c ../bzip2/bzlib.c ../bzip2/decompress.c ../bzip2/huffman.c ../bzip2/randtable.c
OBJS = bgbg.o exec.o fileform.o main.o ui.o util.o resource.res crc32.o infblock.o infcodes.o inflate.o inftrees.o infutil.o bzlib.o decompress.o huffman.o randtable.o
LIBS = -lole32 -lgdi32 -lversion -luuid -lcomctl32 -lkernel32 -luser32 -lshell32 -ladvapi32
# -- Programs --
CC = gcc
RC = windres
RM = del
# -- Compilers and linker flags --
DEFINES = -DWIN32 -D_WINDOWS_ -DEXEHEAD -DWinMain=WinMainCRTStartup
CFLAGS = -Os -fomit-frame-pointer -fno-inline $(DEFINES)
LFLAGS = -s -mwindows -nostdlib -nostartfiles -Wl,--enable-stdcall-fixup
RCFLAGS = --input-format rc --output-format coff
all : exehead
exehead : $(OBJS)
$(CC) $(CFLAGS) $(LFLAGS) -o exehead.exe $(OBJS) $(LIBS)
bin2h exehead.exe Release\exehead.h header_data
bin2h bitmap1.bmp Release\bitmap1.h bitmap1_data
bin2h bitmap2.bmp Release\bitmap2.h bitmap2_data
bin2h nsis.ico Release\icon.h icon_data
bin2h uninst.ico Release\unicon.h unicon_data
# -- Dependencies --
bgbg.o : bgbg.c resource.h config.h Makefile
exec.o : exec.c fileform.h util.h state.h ui.h exec.h config.h lang.h Makefile
fileform.o : fileform.c fileform.h util.h state.h ../zlib/zlib.h ../zlib/zconf.h ui.h config.h Makefile
main.o : main.c resource.h util.h fileform.h state.h ui.h ../zlib/zlib.h ../zlib/zconf.h config.h lang.h Makefile
ui.o : ui.c resource.h fileform.h state.h ui.h config.h Makefile
util.o : util.c util.h state.h fileform.h ui.h config.h Makefile
# -- Special command line for the resource file --
resource.res : resource.rc resource.h config.h Makefile
$(RC) $(RCFLAGS) -o resource.res -i resource.rc
crc32.o : ../crc32.c config.h Makefile
$(CC) $(CFLAGS) -c ../crc32.c -o crc32.o
# -- Special command lines for zlib --
infblock.o : ../zlib/infblock.c ../zlib/zutil.h ../zlib/infblock.h ../zlib/inftrees.h ../zlib/infcodes.h ../zlib/infutil.h ../zlib/zlib.h ../zlib/zconf.h Makefile
$(CC) $(CFLAGS) -c ../zlib/infblock.c -o infblock.o
infcodes.o : ../zlib/infcodes.c ../zlib/zutil.h ../zlib/inftrees.h ../zlib/infblock.h ../zlib/infcodes.h ../zlib/infutil.h ../zlib/zlib.h ../zlib/zconf.h Makefile
$(CC) $(CFLAGS) -c ../zlib/infcodes.c -o infcodes.o
inflate.o : ../zlib/inflate.c ../zlib/zutil.h ../zlib/infblock.h ../zlib/zlib.h ../zlib/zconf.h Makefile
$(CC) $(CFLAGS) -c ../zlib/inflate.c -o inflate.o
inftrees.o : ../zlib/inftrees.c ../zlib/zutil.h ../zlib/inftrees.h ../zlib/zlib.h ../zlib/zconf.h Makefile
$(CC) $(CFLAGS) -c ../zlib/inftrees.c -o inftrees.o
infutil.o : ../zlib/infutil.c ../zlib/zutil.h ../zlib/infblock.h ../zlib/inftrees.h ../zlib/infcodes.h ../zlib/infutil.h ../zlib/zlib.h ../zlib/zconf.h Makefile
$(CC) $(CFLAGS) -c ../zlib/infutil.c -o infutil.o
# -- Special command lines for bzip2 --
bzlib.o : ../bzip2/bzlib.c ../bzip2/bzlib.h ../bzip2/bzlib_private.h config.h
$(CC) $(CFLAGS) -c ../bzip2/bzlib.c -o bzlib.o
decompress.o : ../bzip2/decompress.c ../bzip2/bzlib.h ../bzip2/bzlib_private.h config.h
$(CC) $(CFLAGS) -c ../bzip2/decompress.c -o decompress.o
huffman.o : ../bzip2/huffman.c ../bzip2/bzlib.h ../bzip2/bzlib_private.h config.h
$(CC) $(CFLAGS) -c ../bzip2/huffman.c -o huffman.o
randtable.o : ../bzip2/randtable.c ../bzip2/bzlib.h ../bzip2/bzlib_private.h config.h
$(CC) $(CFLAGS) -c ../bzip2/randtable.c -o randtable.o
# -- Clean script --
clean ::
$(RM) *.o
$(RM) resource.res
$(RM) exehead.exe
$(RM) Release\exehead.h
$(RM) Release\bitmap1.h
$(RM) Release\bitmap2.h
$(RM) Release\icon.h
$(RM) Release\unicon.h

1237
Source/exehead/Ui.c Normal file

File diff suppressed because it is too large Load diff

5
Source/exehead/afxres.h Normal file
View file

@ -0,0 +1,5 @@
#include <windows.h>
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif

90
Source/exehead/bgbg.c Normal file
View file

@ -0,0 +1,90 @@
#include <windows.h>
#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

60
Source/exehead/bin2h.c Normal file
View file

@ -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 <stdio.h>
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;
}

BIN
Source/exehead/bin2h.exe Executable file

Binary file not shown.

BIN
Source/exehead/bitmap1.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

260
Source/exehead/config.h Normal file
View file

@ -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

1423
Source/exehead/exec.c Normal file

File diff suppressed because it is too large Load diff

7
Source/exehead/exec.h Normal file
View file

@ -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_

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="Nullsoft.NSIS.exehead" type="win32"/>
<description>Nullsoft Install System.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>

323
Source/exehead/fileform.c Normal file
View file

@ -0,0 +1,323 @@
#include <windows.h>
#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);
}

324
Source/exehead/fileform.h Normal file
View file

@ -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, val1<val2, val1>val2]
EW_INTCMPU, // IntCmpU: 5 [val1, val2, equal, val1<val2, val1>val2]
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_

57
Source/exehead/lang.h Normal file
View file

@ -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_

BIN
Source/exehead/nsis.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

63
Source/exehead/resource.h Normal file
View file

@ -0,0 +1,63 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
#define IDC_BACK 3
#define IDD_DIALOG1 101
#define IDI_ICON1 102
#define IDD_DIALOG2 102
#define IDD_LICENSE 102
#define IDI_ICON2 103
#define IDD_DIR 103
#define IDD_SELCOM 104
#define IDD_INST 105
#define IDD_INSTFILES 106
#define IDD_UNINST 107
#define IDB_BITMAP1 109
#define IDB_BITMAP2 110
#define IDI_ICON3 110
#define IDD_VERIFY 111
#define IDB_BITMAP3 111
#define IDC_EDIT1 1000
#define IDC_BROWSE 1001
#define IDC_COPYRIGHT 1003
#define IDC_PROGRESS1 1004
#define IDC_PROGRESS2 1005
#define IDC_INTROTEXT 1006
#define IDC_WMA 1007
#define IDC_CHECK1 1008
#define IDC_MJF 1008
#define IDC_VERSION 1009
#define IDC_DIRCAPTION 1011
#define IDC_STATUSTEXT 1014
#define IDC_LICTEXT 1015
#define IDC_LIST1 1016
#define IDC_COMBO1 1017
#define IDC_CHILDRECT 1018
#define IDC_DIR 1019
#define IDC_SELDIRTEXT 1020
#define IDC_TEXT1 1021
#define IDC_TEXT2 1022
#define IDC_SPACEREQUIRED 1023
#define IDC_SPACEAVAILABLE 1024
#define IDC_INSTVER 1024
#define IDC_UNINSTTEXT 1025
#define IDC_PROGRESSTEXT 1026
#define IDC_SHOWDETAILS 1027
#define IDC_VERSTR 1028
#define IDC_UNINSTFROM 1029
#define IDC_STR 1030
#define IDC_ULICON 1031
#define IDC_TREE1 1032
#define IDC_BRANDIMAGE 1033
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 112
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1034
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

247
Source/exehead/resource.rc Normal file
View file

@ -0,0 +1,247 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "config.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE)
#if defined(APSTUDIO_INVOKED)
IDD_LICENSE$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130
#else
IDD_LICENSE DIALOG DISCARDABLE 0, 0, 266, 130
#endif
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
ICON IDI_ICON2,IDC_ULICON,0,0,20,20
LTEXT "",IDC_INTROTEXT,25,0,241,23
CONTROL "",IDC_EDIT1,"RICHEDIT",ES_MULTILINE | ES_READONLY |
WS_VSCROLL | WS_BORDER,0,24,266,105
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT)
#if defined(APSTUDIO_INVOKED)
IDD_DIR$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 266, 130
#else
IDD_DIR DIALOG DISCARDABLE 0, 0, 266, 130
#endif
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_DIR,11,49,188,12,ES_AUTOHSCROLL
PUSHBUTTON "",IDC_BROWSE,203,48,50,14
ICON IDI_ICON2,IDC_ULICON,0,0,20,20
CONTROL "",IDC_SELDIRTEXT,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,
0,36,265,8
CONTROL "",IDC_SPACEAVAILABLE,"Static",SS_LEFTNOWORDWRAP |
WS_GROUP,0,122,265,8
CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE |
WS_TABSTOP,12,65,118,10
CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP |
WS_GROUP,0,111,265,8
LTEXT "",IDC_INTROTEXT,25,0,241,34
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE)
#if defined(APSTUDIO_INVOKED)
IDD_SELCOM$(NSIS_CONFIG_COMPONENTPAGE) DIALOG DISCARDABLE 0, 0, 266, 130
#else
IDD_SELCOM DIALOG DISCARDABLE 0, 0, 266, 130
#endif
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
COMBOBOX IDC_COMBO1,114,25,152,102,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
ICON IDI_ICON2,IDC_ULICON,0,0,20,20
LTEXT "",IDC_TEXT2,0,40,108,21
CONTROL "",IDC_TEXT1,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,0,27,
108,8
CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP |
WS_GROUP,0,111,111,8
LTEXT "",IDC_INTROTEXT,25,0,241,25
CONTROL "Tree1",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS |
TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP |
WS_BORDER | WS_TABSTOP,114,39,151,90
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT)
#if defined(APSTUDIO_INVOKED)
IDD_INST$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 280, 162
#else
IDD_INST DIALOG DISCARDABLE 0, 0, 280, 162
#endif
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
FONT 8, "MS Sans Serif"
BEGIN
PUSHBUTTON "",IDOK,223,142,50,14
PUSHBUTTON "",IDCANCEL,7,142,50,14
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,138,267,1
CONTROL "",IDC_CHILDRECT,"Static",SS_BLACKRECT | NOT WS_VISIBLE,
7,6,266,130
PUSHBUTTON "",IDC_BACK,171,142,50,14,NOT WS_VISIBLE
CTEXT "",IDC_VERSTR,59,145,108,8,WS_DISABLED
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT)
#if defined(APSTUDIO_INVOKED)
IDD_INSTFILES$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOG DISCARDABLE 0, 0, 266, 130
#else
IDD_INSTFILES DIALOG DISCARDABLE 0, 0, 266, 130
#endif
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE |
WS_BORDER,24,10,241,11
CONTROL "",IDC_PROGRESS2,"msctls_progress32",PBS_SMOOTH | NOT
WS_VISIBLE | WS_BORDER,24,10,241,11
CONTROL "",IDC_INTROTEXT,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,
24,0,241,8
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL |
LVS_NOCOLUMNHEADER | NOT WS_VISIBLE | WS_BORDER |
WS_TABSTOP, 0,25,265,104
ICON IDI_ICON2,IDC_ULICON,0,0,20,20
PUSHBUTTON "",IDC_SHOWDETAILS,0,28,50,14,NOT WS_TABSTOP
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_UNINSTDLG)
#if defined(APSTUDIO_INVOKED)
IDD_UNINST$(_NSIS_CONFIG_UNINSTDLG) DIALOG DISCARDABLE 0, 0, 266, 130
#else
IDD_UNINST DIALOG DISCARDABLE 0, 0, 266, 130
#endif
STYLE DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif"
BEGIN
ICON IDI_ICON2,IDC_ULICON,0,1,20,20
LTEXT "",IDC_UNINSTFROM,0,45,55,8
EDITTEXT IDC_EDIT1,56,43,209,12,ES_AUTOHSCROLL | ES_READONLY
LTEXT "",IDC_INTROTEXT,25,0,241,34
END
#endif
#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_VERIFYDIALOG)
#if defined(APSTUDIO_INVOKED)
IDD_VERIFY$(_NSIS_CONFIG_VERIFYDIALOG) DIALOG DISCARDABLE 0, 0, 162, 22
#else
IDD_VERIFY DIALOG DISCARDABLE 0, 0, 162, 22
#endif
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE
FONT 8, "MS Sans Serif"
BEGIN
CTEXT "",IDC_STR,7,7,148,8
END
#endif
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"IDD_INST$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 273
TOPMARGIN, 6
BOTTOMMARGIN, 156
END
"IDD_INSTFILES$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG
BEGIN
RIGHTMARGIN, 246
BOTTOMMARGIN, 125
END
"IDD_VERIFY$(_NSIS_CONFIG_VERIFYDIALOG)", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 155
TOPMARGIN, 7
BOTTOMMARGIN, 15
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""config.h""\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON2 ICON DISCARDABLE "nsis.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE)
#if defined(APSTUDIO_INVOKED)
IDB_BITMAP1$(NSIS_CONFIG_COMPONENTPAGE) BITMAP DISCARDABLE "bitmap1.bmp"
#else
IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp"
#endif
#endif
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////

11
Source/exehead/state.h Normal file
View file

@ -0,0 +1,11 @@
extern char g_usrvars[24][NSIS_MAX_STRLEN];
#define state_command_line (g_usrvars[20])
#define state_install_directory (g_usrvars[21])
#define state_output_directory (g_usrvars[22])
#define state_exe_directory (g_usrvars[23])
extern char g_caption[NSIS_MAX_STRLEN*2];
extern HWND g_hwnd;
extern int g_filehdrsize;
extern HANDLE g_hInstance;
extern HWND insthwnd,insthwndbutton;

21
Source/exehead/ui.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef _UI_H_
#define _UI_H_
int ui_doinstall(void);
void update_status_text(const char *text1, const char *text2);
extern int ui_st_updateflag;
extern char g_autoclose;
extern void *g_inst_combinedheader;
extern section *g_inst_section;
extern entry *g_inst_entry;
#define g_inst_header ((header *)g_inst_combinedheader)
#define g_inst_cmnheader ((common_header *)g_inst_combinedheader)
#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
#define g_inst_uninstheader ((uninstall_header *)g_inst_combinedheader)
extern int g_is_uninstaller;
#endif
#endif//_UI_H_

BIN
Source/exehead/uninst.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

548
Source/exehead/util.c Normal file
View file

@ -0,0 +1,548 @@
#include <windows.h>
#include <shlobj.h>
#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 (p<buf) p=buf;
*p=0;
}
char *scanendslash(const char *str)
{
char *s=CharPrev(str,str+lstrlen(str));
if (!*str) return (char*)str-1;
for (;;)
{
char *t;
if ('\\' == *s) return s;
t=CharPrev(str,s);
if (t==s) return (char*)str-1;
s=t;
}
}
int validpathspec(char *ubuf)
{
return ((ubuf[0]=='\\' && ubuf[1]=='\\') || (ubuf[0] && *(ubuf+1)==':'));
}
int is_valid_instpath(char *s)
{
int ivp=0;
// if 8 is set, req is 0, which means rootdirs are not allowed.
int req=!(g_inst_cmnheader->misc_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

47
Source/exehead/util.h Normal file
View file

@ -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);

BIN
Source/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

150
Source/lineparse.h Normal file
View file

@ -0,0 +1,150 @@
#ifndef _LINEPARSE_H_
#define _LINEPARSE_H_
class LineParser {
public:
LineParser()
{
m_nt=m_eat=0;
m_tokens=0;
}
~LineParser()
{
freetokens();
}
int parse(char *line) // returns -1 on error
{
freetokens();
int n=doline(line);
if (n) return n;
if (m_nt)
{
m_tokens=(char**)malloc(sizeof(char*)*m_nt);
n=doline(line);
if (n)
{
freetokens();
return -1;
}
}
return 0;
}
int getnumtokens() { return m_nt-m_eat; }
void eattoken() { m_eat++; }
double gettoken_float(int token, int *success=0)
{
token+=m_eat;
if (token < 0 || token >= m_nt)
{
if (success) *success=0;
return 0.0;
}
if (success)
{
char *t=m_tokens[token];
*success=*t?1:0;
while (*t)
{
if ((*t < '0' || *t > '9')&&*t != '.') *success=0;
t++;
}
}
return atof(m_tokens[token]);
}
int gettoken_int(int token, int *success=0)
{
token+=m_eat;
if (token < 0 || token >= m_nt || !m_tokens[token][0])
{
if (success) *success=0;
return 0;
}
char *tmp;
int l;
if (m_tokens[token][0] == '-') l=strtol(m_tokens[token],&tmp,0);
else l=(int)strtoul(m_tokens[token],&tmp,0);
if (success) *success=! (int)(*tmp);
return l;
}
char *gettoken_str(int token)
{
token+=m_eat;
if (token < 0 || token >= m_nt) return "";
return m_tokens[token];
}
int gettoken_enum(int token, const char *strlist) // null seperated list
{
int x=0;
char *tt=gettoken_str(token);
if (tt && *tt) while (*strlist)
{
if (!stricmp(tt,strlist)) return x;
strlist+=strlen(strlist)+1;
x++;
}
return -1;
}
private:
void freetokens()
{
if (m_tokens)
{
int x;
for (x = 0; x < m_nt; x ++)
free(m_tokens[x]);
free(m_tokens);
}
m_tokens=0;
m_nt=0;
}
int doline(char *line)
{
m_nt=0;
while (*line == ' ' || *line == '\t') line++;
while (*line)
{
int lstate=0; // 1=", 2=`, 4='
if (*line == ';' || *line == '#') break;
if (*line == '\"') lstate=1;
else if (*line == '\'') lstate=2;
else if (*line == '`') lstate=4;
if (lstate) line++;
int nc=0;
while (*line)
{
if (lstate==1 && *line =='\"') break;
if (lstate==2 && *line =='\'') break;
if (lstate==4 && *line =='`') break;
if (!lstate && (*line == ' ' || *line == '\t')) break;
line++;
nc++;
}
if (m_tokens)
{
m_tokens[m_nt]=(char*)malloc(nc+1);
strncpy(m_tokens[m_nt],line-nc,nc);
m_tokens[m_nt][nc]=0;
}
m_nt++;
if (lstate)
{
if (*line) line++;
else return -2;
}
while (*line == ' ' || *line == '\t') line++;
}
return 0;
}
int m_eat;
int m_nt;
char **m_tokens;
};
#endif//_LINEPARSE_H_

379
Source/makenssi.cpp Normal file
View file

@ -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 <windows.h>
#include <stdio.h>
#include <signal.h>
#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<argc || (!files_processed && !cmds_processed))
{
if (build.display_errors && !nousage)
{
fprintf(g_output,"Usage:\n"
" makensis [options] [script.nsi | - [...]]\n"
" options are:\n"
" /CMDHELP item prints out help for 'item', or lists all commands\n"
" /HDRINFO prints information about what options makensis was compiled with\n"
" /LICENSE prints the makensis software license\n");
fprintf(g_output,
" /Vx verbosity where x is 4=all,3=no script,2=no info,1=no warnings,0=none\n"
" /Ofile specifies a text file to log compiler output (default is stdout)\n"
" /PAUSE pauses after execution\n"
" /NOCONFIG disables inclusion of <path to makensis.exe>\\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;
}

247
Source/makenssi.dsp Normal file
View file

@ -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

59
Source/makenssi.dsw Normal file
View file

@ -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>
{{{
}}}
###############################################################################

1
Source/makenssi.ncb Normal file
View file

@ -0,0 +1 @@
Microsoft C/C++ program database 2.00

BIN
Source/makenssi.opt Normal file

Binary file not shown.

260
Source/makenssi.plg Normal file
View file

@ -0,0 +1,260 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: exehead_bzip2 - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
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"
<h3>Output Window</h3>
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)
<h3>
--------------------Configuration: exehead_zlib - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
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"
<h3>Output Window</h3>
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)
<h3>
--------------------Configuration: makenssi - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
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"
<h3>Output Window</h3>
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...
<h3>Results</h3>
makensis.exe - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

17
Source/resource.h Normal file
View file

@ -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

3302
Source/script.cpp Normal file

File diff suppressed because it is too large Load diff

275
Source/strlist.h Normal file
View file

@ -0,0 +1,275 @@
#ifndef _STRLIST_H_
#define _STRLIST_H_
#include <stdlib.h> // 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_

226
Source/tokens.cpp Normal file
View file

@ -0,0 +1,226 @@
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#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;
}

192
Source/tokens.h Normal file
View file

@ -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_

292
Source/util.cpp Normal file
View file

@ -0,0 +1,292 @@
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <conio.h>
#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

24
Source/util.h Normal file
View file

@ -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_

238
Source/zlib/DEFLATE.H Normal file
View file

@ -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

309
Source/zlib/INFBLOCK.C Normal file
View file

@ -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

32
Source/zlib/INFBLOCK.H Normal file
View file

@ -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));

246
Source/zlib/INFCODES.C Normal file
View file

@ -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

22
Source/zlib/INFCODES.H Normal file
View file

@ -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 ));

65
Source/zlib/INFLATE.C Normal file
View file

@ -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

324
Source/zlib/INFTREES.C Normal file
View file

@ -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

45
Source/zlib/INFTREES.H Normal file
View file

@ -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));

87
Source/zlib/INFUTIL.C Normal file
View file

@ -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

97
Source/zlib/INFUTIL.H Normal file
View file

@ -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)<<k;k+=8;}}
#define DUMPBITS(j) {b>>=(j);k-=(j);}
/* output bytes */
#define WAVAIL (uInt)(q<s->read?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

58
Source/zlib/ZCONF.H Normal file
View file

@ -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 */

157
Source/zlib/ZLIB.H Normal file
View file

@ -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 */

68
Source/zlib/ZUTIL.H Normal file
View file

@ -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 <windows.h>
#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 */

986
Source/zlib/deflate.c Normal file
View file

@ -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)<<s->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;
}

883
Source/zlib/trees.c Normal file
View file

@ -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 <ctype.h>
#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<<extra_lbits[code]); n++) {
_length_code[length++] = (uch)code;
}
}
Assert (length == 256, "tr_static_init: length != 256");
_length_code[length-1] = (uch)code;
/* Initialize the mapping dist (0..32K) -> dist code (0..29) */
dist = 0;
for (code = 0 ; code < 16; code++) {
base_dist[code] = dist;
for (n = 0; n < (1<<extra_dbits[code]); n++) {
_dist_code[dist++] = (uch)code;
}
}
Assert (dist == 256, "tr_static_init: dist != 256");
dist >>= 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<<MAX_BITS)-1,
"inconsistent bit counts");
Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++) {
int len = tree[n].Len;
if (len == 0) continue;
/* Now reverse the bits */
tree[n].Code = bi_reverse(next_code[len]++, len);
Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
}
}
local void build_tree(s, desc)
deflate_state *s;
tree_desc *desc; /* the tree descriptor */
{
ct_data *tree = desc->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++);
}
}