diff options
author | Didier Raboud <odyx@debian.org> | 2018-03-31 20:38:19 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2018-03-31 20:38:19 +0200 |
commit | f05798f0619384fdb055f634ca4233378f2779dd (patch) | |
tree | b1f9b212f77580c824cc765ac3778fc6c8f4d4d8 /Source | |
parent | 59c41c0897494001ced424157660d4ee59bb5426 (diff) |
Import Upstream version 2.32
Diffstat (limited to 'Source')
151 files changed, 44346 insertions, 44065 deletions
diff --git a/Source/7zip/7zGuids.cpp b/Source/7zip/7zGuids.cpp index f076b0f..1ca1ac1 100755 --- a/Source/7zip/7zGuids.cpp +++ b/Source/7zip/7zGuids.cpp @@ -1,31 +1,31 @@ -/*
- * 7zGuids.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-// DLLExports.cpp
-
-// #include "StdAfx.h"
-
-#ifdef WIN32
-# include <objbase.h>
-# include <initguid.h>
-#endif
-
-#include "../Platform.h"
-
-#define INITGUID
-#include "7zip/ICoder.h"
-#include "7zip/Compress/LZ/IMatchFinder.h"
+/* + * 7zGuids.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +// DLLExports.cpp + +// #include "StdAfx.h" + +#ifdef WIN32 +# include <objbase.h> +# include <initguid.h> +#endif + +#include "../Platform.h" + +#define INITGUID +#include "7zip/ICoder.h" +#include "7zip/Compress/LZ/IMatchFinder.h" diff --git a/Source/7zip/7zip/Common/InBuffer.cpp b/Source/7zip/7zip/Common/InBuffer.cpp index 4d99f5c..e0dcb3d 100755 --- a/Source/7zip/7zip/Common/InBuffer.cpp +++ b/Source/7zip/7zip/Common/InBuffer.cpp @@ -1,95 +1,95 @@ -/*
- * InBuffer.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "InBuffer.h"
-
-#include "../../Common/Alloc.h"
-
-CInBuffer::CInBuffer():
- _buffer(0),
- _bufferLimit(0),
- _bufferBase(0),
- _stream(0),
- _bufferSize(0)
-{}
-
-bool CInBuffer::Create(UInt32 bufferSize)
-{
- const UInt32 kMinBlockSize = 1;
- if (bufferSize < kMinBlockSize)
- bufferSize = kMinBlockSize;
- if (_bufferBase != 0 && _bufferSize == bufferSize)
- return true;
- Free();
- _bufferSize = bufferSize;
- _bufferBase = (Byte *)::MidAlloc(bufferSize);
- return (_bufferBase != 0);
-}
-
-void CInBuffer::Free()
-{
- ::MidFree(_bufferBase);
- _bufferBase = 0;
-}
-
-void CInBuffer::SetStream(ISequentialInStream *stream)
-{
- _stream = stream;
-}
-
-void CInBuffer::Init()
-{
- _processedSize = 0;
- _buffer = _bufferBase;
- _bufferLimit = _buffer;
- _wasFinished = false;
- #ifdef _NO_EXCEPTIONS
- ErrorCode = S_OK;
- #endif
-}
-
-bool CInBuffer::ReadBlock()
-{
- #ifdef _NO_EXCEPTIONS
- if (ErrorCode != S_OK)
- return false;
- #endif
- if (_wasFinished)
- return false;
- _processedSize += (_buffer - _bufferBase);
- UInt32 numProcessedBytes;
- HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes);
- #ifdef _NO_EXCEPTIONS
- ErrorCode = result;
- #else
- if (result != S_OK)
- throw CInBufferException(result);
- #endif
- _buffer = _bufferBase;
- _bufferLimit = _buffer + numProcessedBytes;
- _wasFinished = (numProcessedBytes == 0);
- return (!_wasFinished);
-}
-
-Byte CInBuffer::ReadBlock2()
-{
- if(!ReadBlock())
- return 0xFF;
- return *_buffer++;
-}
+/* + * InBuffer.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "InBuffer.h" + +#include "../../Common/Alloc.h" + +CInBuffer::CInBuffer(): + _buffer(0), + _bufferLimit(0), + _bufferBase(0), + _stream(0), + _bufferSize(0) +{} + +bool CInBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_bufferBase != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _bufferBase = (Byte *)::MidAlloc(bufferSize); + return (_bufferBase != 0); +} + +void CInBuffer::Free() +{ + ::MidFree(_bufferBase); + _bufferBase = 0; +} + +void CInBuffer::SetStream(ISequentialInStream *stream) +{ + _stream = stream; +} + +void CInBuffer::Init() +{ + _processedSize = 0; + _buffer = _bufferBase; + _bufferLimit = _buffer; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +bool CInBuffer::ReadBlock() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return false; + #endif + if (_wasFinished) + return false; + _processedSize += (_buffer - _bufferBase); + UInt32 numProcessedBytes; + HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw CInBufferException(result); + #endif + _buffer = _bufferBase; + _bufferLimit = _buffer + numProcessedBytes; + _wasFinished = (numProcessedBytes == 0); + return (!_wasFinished); +} + +Byte CInBuffer::ReadBlock2() +{ + if(!ReadBlock()) + return 0xFF; + return *_buffer++; +} diff --git a/Source/7zip/7zip/Common/InBuffer.h b/Source/7zip/7zip/Common/InBuffer.h index 797875f..d1a3556 100755 --- a/Source/7zip/7zip/Common/InBuffer.h +++ b/Source/7zip/7zip/Common/InBuffer.h @@ -1,91 +1,91 @@ -/*
- * InBuffer.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __INBUFFER_H
-#define __INBUFFER_H
-
-#include "../IStream.h"
-#include "../../Common/MyCom.h"
-
-#ifndef _NO_EXCEPTIONS
-class CInBufferException
-{
-public:
- HRESULT ErrorCode;
- CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {}
-};
-#endif
-
-class CInBuffer
-{
- Byte *_buffer;
- Byte *_bufferLimit;
- Byte *_bufferBase;
- CMyComPtr<ISequentialInStream> _stream;
- UInt64 _processedSize;
- UInt32 _bufferSize;
- bool _wasFinished;
-
- bool ReadBlock();
- Byte ReadBlock2();
-
-public:
- #ifdef _NO_EXCEPTIONS
- HRESULT ErrorCode;
- #endif
-
- CInBuffer();
- ~CInBuffer() { Free(); }
-
- bool Create(UInt32 bufferSize);
- void Free();
-
- void SetStream(ISequentialInStream *stream);
- void Init();
- void ReleaseStream() { _stream.Release(); }
-
- bool ReadByte(Byte &b)
- {
- if(_buffer >= _bufferLimit)
- if(!ReadBlock())
- return false;
- b = *_buffer++;
- return true;
- }
- Byte ReadByte()
- {
- if(_buffer >= _bufferLimit)
- return ReadBlock2();
- return *_buffer++;
- }
- void ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
- {
- for(processedSize = 0; processedSize < size; processedSize++)
- if (!ReadByte(((Byte *)data)[processedSize]))
- return;
- }
- bool ReadBytes(void *data, UInt32 size)
- {
- UInt32 processedSize;
- ReadBytes(data, size, processedSize);
- return (processedSize == size);
- }
- UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); }
- bool WasFinished() const { return _wasFinished; }
-};
-
-#endif
+/* + * InBuffer.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __INBUFFER_H +#define __INBUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" + +#ifndef _NO_EXCEPTIONS +class CInBufferException +{ +public: + HRESULT ErrorCode; + CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; +#endif + +class CInBuffer +{ + Byte *_buffer; + Byte *_bufferLimit; + Byte *_bufferBase; + CMyComPtr<ISequentialInStream> _stream; + UInt64 _processedSize; + UInt32 _bufferSize; + bool _wasFinished; + + bool ReadBlock(); + Byte ReadBlock2(); + +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + CInBuffer(); + ~CInBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetStream(ISequentialInStream *stream); + void Init(); + void ReleaseStream() { _stream.Release(); } + + bool ReadByte(Byte &b) + { + if(_buffer >= _bufferLimit) + if(!ReadBlock()) + return false; + b = *_buffer++; + return true; + } + Byte ReadByte() + { + if(_buffer >= _bufferLimit) + return ReadBlock2(); + return *_buffer++; + } + void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) + { + for(processedSize = 0; processedSize < size; processedSize++) + if (!ReadByte(((Byte *)data)[processedSize])) + return; + } + bool ReadBytes(void *data, UInt32 size) + { + UInt32 processedSize; + ReadBytes(data, size, processedSize); + return (processedSize == size); + } + UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } + bool WasFinished() const { return _wasFinished; } +}; + +#endif diff --git a/Source/7zip/7zip/Common/OutBuffer.cpp b/Source/7zip/7zip/Common/OutBuffer.cpp index 09bed1b..2803a6a 100755 --- a/Source/7zip/7zip/Common/OutBuffer.cpp +++ b/Source/7zip/7zip/Common/OutBuffer.cpp @@ -1,131 +1,131 @@ -/*
- * OutBuffer.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "OutBuffer.h"
-
-#include "../../Common/Alloc.h"
-
-bool COutBuffer::Create(UInt32 bufferSize)
-{
- const UInt32 kMinBlockSize = 1;
- if (bufferSize < kMinBlockSize)
- bufferSize = kMinBlockSize;
- if (_buffer != 0 && _bufferSize == bufferSize)
- return true;
- Free();
- _bufferSize = bufferSize;
- _buffer = (Byte *)::MidAlloc(bufferSize);
- return (_buffer != 0);
-}
-
-void COutBuffer::Free()
-{
- ::MidFree(_buffer);
- _buffer = 0;
-}
-
-void COutBuffer::SetStream(ISequentialOutStream *stream)
-{
- _stream = stream;
-}
-
-void COutBuffer::Init()
-{
- _streamPos = 0;
- _limitPos = _bufferSize;
- _pos = 0;
- _processedSize = 0;
- _overDict = false;
- #ifdef _NO_EXCEPTIONS
- ErrorCode = S_OK;
- #endif
-}
-
-UInt64 COutBuffer::GetProcessedSize() const
-{
- UInt64 res = _processedSize + _pos - _streamPos;
- if (_streamPos > _pos)
- res += _bufferSize;
- return res;
-}
-
-
-HRESULT COutBuffer::FlushPart()
-{
- // _streamPos < _bufferSize
- UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos);
- HRESULT result = S_OK;
- #ifdef _NO_EXCEPTIONS
- result = ErrorCode;
- #endif
- if (_buffer2 != 0)
- {
- memmove(_buffer2, _buffer + _streamPos, size);
- _buffer2 += size;
- }
-
- if (_stream != 0
- #ifdef _NO_EXCEPTIONS
- && (ErrorCode == S_OK)
- #endif
- )
- {
- UInt32 processedSize = 0;
- result = _stream->Write(_buffer + _streamPos, size, &processedSize);
- size = processedSize;
- }
- _streamPos += size;
- if (_streamPos == _bufferSize)
- _streamPos = 0;
- if (_pos == _bufferSize)
- {
- _overDict = true;
- _pos = 0;
- }
- _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize;
- _processedSize += size;
- return result;
-}
-
-HRESULT COutBuffer::Flush()
-{
- #ifdef _NO_EXCEPTIONS
- if (ErrorCode != S_OK)
- return ErrorCode;
- #endif
-
- while(_streamPos != _pos)
- {
- HRESULT result = FlushPart();
- if (result != S_OK)
- return result;
- }
- return S_OK;
-}
-
-void COutBuffer::FlushWithCheck()
-{
- HRESULT result = FlushPart();
- #ifdef _NO_EXCEPTIONS
- ErrorCode = result;
- #else
- if (result != S_OK)
- throw COutBufferException(result);
- #endif
-}
+/* + * OutBuffer.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "OutBuffer.h" + +#include "../../Common/Alloc.h" + +bool COutBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_buffer != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _buffer = (Byte *)::MidAlloc(bufferSize); + return (_buffer != 0); +} + +void COutBuffer::Free() +{ + ::MidFree(_buffer); + _buffer = 0; +} + +void COutBuffer::SetStream(ISequentialOutStream *stream) +{ + _stream = stream; +} + +void COutBuffer::Init() +{ + _streamPos = 0; + _limitPos = _bufferSize; + _pos = 0; + _processedSize = 0; + _overDict = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +UInt64 COutBuffer::GetProcessedSize() const +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufferSize; + return res; +} + + +HRESULT COutBuffer::FlushPart() +{ + // _streamPos < _bufferSize + UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + result = ErrorCode; + #endif + if (_buffer2 != 0) + { + memmove(_buffer2, _buffer + _streamPos, size); + _buffer2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode == S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buffer + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + if (_streamPos == _bufferSize) + _streamPos = 0; + if (_pos == _bufferSize) + { + _overDict = true; + _pos = 0; + } + _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return ErrorCode; + #endif + + while(_streamPos != _pos) + { + HRESULT result = FlushPart(); + if (result != S_OK) + return result; + } + return S_OK; +} + +void COutBuffer::FlushWithCheck() +{ + HRESULT result = FlushPart(); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw COutBufferException(result); + #endif +} diff --git a/Source/7zip/7zip/Common/OutBuffer.h b/Source/7zip/7zip/Common/OutBuffer.h index 34915b7..851ef09 100755 --- a/Source/7zip/7zip/Common/OutBuffer.h +++ b/Source/7zip/7zip/Common/OutBuffer.h @@ -1,79 +1,79 @@ -/*
- * OutBuffer.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __OUTBUFFER_H
-#define __OUTBUFFER_H
-
-#include "../IStream.h"
-#include "../../Common/MyCom.h"
-
-#ifndef _NO_EXCEPTIONS
-struct COutBufferException
-{
- HRESULT ErrorCode;
- COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {}
-};
-#endif
-
-class COutBuffer
-{
-protected:
- Byte *_buffer;
- UInt32 _pos;
- UInt32 _limitPos;
- UInt32 _streamPos;
- UInt32 _bufferSize;
- CMyComPtr<ISequentialOutStream> _stream;
- UInt64 _processedSize;
- Byte *_buffer2;
- bool _overDict;
-
- HRESULT FlushPart();
- void FlushWithCheck();
-public:
- #ifdef _NO_EXCEPTIONS
- HRESULT ErrorCode;
- #endif
-
- COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {}
- ~COutBuffer() { Free(); }
-
- bool Create(UInt32 bufferSize);
- void Free();
-
- void SetMemStream(Byte *buffer) { _buffer2 = buffer; }
- void SetStream(ISequentialOutStream *stream);
- void Init();
- HRESULT Flush();
- void ReleaseStream() { _stream.Release(); }
-
- void WriteByte(Byte b)
- {
- _buffer[_pos++] = b;
- if(_pos == _limitPos)
- FlushWithCheck();
- }
- void WriteBytes(const void *data, size_t size)
- {
- for (size_t i = 0; i < size; i++)
- WriteByte(((const Byte *)data)[i]);
- }
-
- UInt64 GetProcessedSize() const;
-};
-
-#endif
+/* + * OutBuffer.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __OUTBUFFER_H +#define __OUTBUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" + +#ifndef _NO_EXCEPTIONS +struct COutBufferException +{ + HRESULT ErrorCode; + COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; +#endif + +class COutBuffer +{ +protected: + Byte *_buffer; + UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; + UInt32 _bufferSize; + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _processedSize; + Byte *_buffer2; + bool _overDict; + + HRESULT FlushPart(); + void FlushWithCheck(); +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} + ~COutBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetMemStream(Byte *buffer) { _buffer2 = buffer; } + void SetStream(ISequentialOutStream *stream); + void Init(); + HRESULT Flush(); + void ReleaseStream() { _stream.Release(); } + + void WriteByte(Byte b) + { + _buffer[_pos++] = b; + if(_pos == _limitPos) + FlushWithCheck(); + } + void WriteBytes(const void *data, size_t size) + { + for (size_t i = 0; i < size; i++) + WriteByte(((const Byte *)data)[i]); + } + + UInt64 GetProcessedSize() const; +}; + +#endif diff --git a/Source/7zip/7zip/Common/StdAfx.h b/Source/7zip/7zip/Common/StdAfx.h index 8e1b1ea..2736abc 100755 --- a/Source/7zip/7zip/Common/StdAfx.h +++ b/Source/7zip/7zip/Common/StdAfx.h @@ -1,8 +1,8 @@ -// StdAfx.h
-
-#ifndef __STDAFX_H
-#define __STDAFX_H
-
-#include "../../Common/MyWindows.h"
-
-#endif
+// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" + +#endif diff --git a/Source/7zip/7zip/Common/StreamUtils.cpp b/Source/7zip/7zip/Common/StreamUtils.cpp index ad77344..e072a67 100755 --- a/Source/7zip/7zip/Common/StreamUtils.cpp +++ b/Source/7zip/7zip/Common/StreamUtils.cpp @@ -1,59 +1,59 @@ -/*
- * StreamUtils.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "../../Common/MyCom.h"
-#include "StreamUtils.h"
-
-HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != 0)
- *processedSize = 0;
- while(size != 0)
- {
- UInt32 processedSizeLoc;
- HRESULT res = stream->Read(data, size, &processedSizeLoc);
- if (processedSize != 0)
- *processedSize += processedSizeLoc;
- data = (Byte *)((Byte *)data + processedSizeLoc);
- size -= processedSizeLoc;
- RINOK(res);
- if (processedSizeLoc == 0)
- return S_OK;
- }
- return S_OK;
-}
-
-HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize)
-{
- if (processedSize != 0)
- *processedSize = 0;
- while(size != 0)
- {
- UInt32 processedSizeLoc;
- HRESULT res = stream->Write(data, size, &processedSizeLoc);
- if (processedSize != 0)
- *processedSize += processedSizeLoc;
- data = (const void *)((const Byte *)data + processedSizeLoc);
- size -= processedSizeLoc;
- RINOK(res);
- if (processedSizeLoc == 0)
- break;
- }
- return S_OK;
-}
+/* + * StreamUtils.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" +#include "StreamUtils.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Read(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (Byte *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return S_OK; + } + return S_OK; +} + +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Write(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (const void *)((const Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + break; + } + return S_OK; +} diff --git a/Source/7zip/7zip/Common/StreamUtils.h b/Source/7zip/7zip/Common/StreamUtils.h index 58b8141..76cc8b2 100755 --- a/Source/7zip/7zip/Common/StreamUtils.h +++ b/Source/7zip/7zip/Common/StreamUtils.h @@ -1,26 +1,26 @@ -/*
- * StreamUtils.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __STREAMUTILS_H
-#define __STREAMUTILS_H
-
-#include "../IStream.h"
-
-HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize);
-HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize);
-
-#endif
+/* + * StreamUtils.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __STREAMUTILS_H +#define __STREAMUTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h index 186adab..c672b6b 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree.h @@ -1,69 +1,69 @@ -/*
- * BinTree.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../LZInWindow.h"
-#include "../IMatchFinder.h"
-
-namespace BT_NAMESPACE {
-
-typedef UInt32 CIndex;
-const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
-
-class CMatchFinder:
- public IMatchFinder,
- public CLZInWindow,
- public CMyUnknownImp,
- public IMatchFinderSetNumPasses
-{
- UInt32 _cyclicBufferPos;
- UInt32 _cyclicBufferSize; // it must be historySize + 1
- UInt32 _matchMaxLen;
- CIndex *_hash;
- CIndex *_son;
- UInt32 _hashMask;
- UInt32 _cutValue;
- UInt32 _hashSizeSum;
-
- void Normalize();
- void FreeThisClassMemory();
- void FreeMemory();
-
- MY_UNKNOWN_IMP
-
- STDMETHOD(SetStream)(ISequentialInStream *inStream);
- STDMETHOD_(void, ReleaseStream)();
- STDMETHOD(Init)();
- HRESULT MovePos();
- STDMETHOD_(Byte, GetIndexByte)(Int32 index);
- STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
- STDMETHOD_(UInt32, GetNumAvailableBytes)();
- STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
- STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes);
- STDMETHOD_(void, ChangeBufferPos)();
-
- STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
- UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
- STDMETHOD(GetMatches)(UInt32 *distances);
- STDMETHOD(Skip)(UInt32 num);
-
-public:
- CMatchFinder();
- virtual ~CMatchFinder();
- virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; }
-};
-
-}
+/* + * BinTree.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../LZInWindow.h" +#include "../IMatchFinder.h" + +namespace BT_NAMESPACE { + +typedef UInt32 CIndex; +const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; + +class CMatchFinder: + public IMatchFinder, + public CLZInWindow, + public CMyUnknownImp, + public IMatchFinderSetNumPasses +{ + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize; // it must be historySize + 1 + UInt32 _matchMaxLen; + CIndex *_hash; + CIndex *_son; + UInt32 _hashMask; + UInt32 _cutValue; + UInt32 _hashSizeSum; + + void Normalize(); + void FreeThisClassMemory(); + void FreeMemory(); + + MY_UNKNOWN_IMP + + STDMETHOD(SetStream)(ISequentialInStream *inStream); + STDMETHOD_(void, ReleaseStream)(); + STDMETHOD(Init)(); + HRESULT MovePos(); + STDMETHOD_(Byte, GetIndexByte)(Int32 index); + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); + STDMETHOD_(UInt32, GetNumAvailableBytes)(); + STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes); + STDMETHOD_(void, ChangeBufferPos)(); + + STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + STDMETHOD(GetMatches)(UInt32 *distances); + STDMETHOD(Skip)(UInt32 num); + +public: + CMatchFinder(); + virtual ~CMatchFinder(); + virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; } +}; + +} diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h index 2e2996a..0a7e559 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree2.h @@ -1,27 +1,27 @@ -/*
- * BinTree2.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE2_H
-#define __BINTREE2_H
-
-#define BT_NAMESPACE NBT2
-
-#include "BinTreeMain.h"
-
-#undef BT_NAMESPACE
-
-#endif
+/* + * BinTree2.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE2_H +#define __BINTREE2_H + +#define BT_NAMESPACE NBT2 + +#include "BinTreeMain.h" + +#undef BT_NAMESPACE + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h index 6b5b116..9515b65 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3.h @@ -1,31 +1,31 @@ -/*
- * BinTree3.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE3_H
-#define __BINTREE3_H
-
-#define BT_NAMESPACE NBT3
-
-#define HASH_ARRAY_2
-
-#include "BinTreeMain.h"
-
-#undef HASH_ARRAY_2
-
-#undef BT_NAMESPACE
-
-#endif
+/* + * BinTree3.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE3_H +#define __BINTREE3_H + +#define BT_NAMESPACE NBT3 + +#define HASH_ARRAY_2 + +#include "BinTreeMain.h" + +#undef HASH_ARRAY_2 + +#undef BT_NAMESPACE + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h index f21cdbd..97d0175 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3Z.h @@ -1,31 +1,31 @@ -/*
- * BinTree3Z.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE3Z_H
-#define __BINTREE3Z_H
-
-#define BT_NAMESPACE NBT3Z
-
-#define HASH_ZIP
-
-#include "BinTreeMain.h"
-
-#undef HASH_ZIP
-
-#undef BT_NAMESPACE
-
-#endif
+/* + * BinTree3Z.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE3Z_H +#define __BINTREE3Z_H + +#define BT_NAMESPACE NBT3Z + +#define HASH_ZIP + +#include "BinTreeMain.h" + +#undef HASH_ZIP + +#undef BT_NAMESPACE + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h index 15a786c..bb5425b 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree3ZMain.h @@ -1,31 +1,31 @@ -/*
- * BinTree3ZMain.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE3ZMAIN__H
-#define __BINTREE3ZMAIN__H
-
-#undef BT_NAMESPACE
-#define BT_NAMESPACE NBT3Z
-
-#define HASH_ZIP
-
-#include "BinTreeMain.h"
-
-#undef HASH_ZIP
-
-#endif
-
+/* + * BinTree3ZMain.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE3ZMAIN__H +#define __BINTREE3ZMAIN__H + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT3Z + +#define HASH_ZIP + +#include "BinTreeMain.h" + +#undef HASH_ZIP + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h index 1b215a3..9339f1f 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4.h @@ -1,33 +1,33 @@ -/*
- * BinTree4.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE4_H
-#define __BINTREE4_H
-
-#define BT_NAMESPACE NBT4
-
-#define HASH_ARRAY_2
-#define HASH_ARRAY_3
-
-#include "BinTreeMain.h"
-
-#undef HASH_ARRAY_2
-#undef HASH_ARRAY_3
-
-#undef BT_NAMESPACE
-
-#endif
+/* + * BinTree4.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE4_H +#define __BINTREE4_H + +#define BT_NAMESPACE NBT4 + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 + +#include "BinTreeMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 + +#undef BT_NAMESPACE + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h index e7c23ca..6dea0da 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTree4b.h @@ -1,39 +1,39 @@ -/*
- * BinTreeb.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __BINTREE4B__H
-#define __BINTREE4B__H
-
-#undef BT_CLSID
-#define BT_CLSID CLSID_CMatchFinderBT4b
-
-#undef BT_NAMESPACE
-#define BT_NAMESPACE NBT4B
-
-#define HASH_ARRAY_2
-#define HASH_ARRAY_3
-#define HASH_BIG
-
-#include "BinTreeMF.h"
-#include "BinTreeMFMain.h"
-
-#undef HASH_ARRAY_2
-#undef HASH_ARRAY_3
-#undef HASH_BIG
-
-#endif
-
+/* + * BinTreeb.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __BINTREE4B__H +#define __BINTREE4B__H + +#undef BT_CLSID +#define BT_CLSID CLSID_CMatchFinderBT4b + +#undef BT_NAMESPACE +#define BT_NAMESPACE NBT4B + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 +#define HASH_BIG + +#include "BinTreeMF.h" +#include "BinTreeMFMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 +#undef HASH_BIG + +#endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h index 12b70f3..47e6099 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMF.h @@ -1,119 +1,119 @@ -/*
- * BinTreeMF.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-// #ifndef __BINTREEMF_H
-// #define __BINTREEMF_H
-
-#include "../../../ICoder.h"
-#include "BinTree.h"
-
-namespace BT_NAMESPACE {
-
-#undef kIDByte
-#undef kIDString
-
-#ifdef HASH_ARRAY_2
- #ifdef HASH_ARRAY_3
- #ifdef HASH_BIG
- #define kIDByte 0x4
- #define kIDString TEXT("4b")
- #else
- #define kIDByte 0x3
- #define kIDString TEXT("4")
- #endif
- #else
- #define kIDByte 0x2
- #define kIDString TEXT("3")
- #endif
-#else
- #ifdef HASH_ZIP
- #define kIDByte 0x0
- #define kIDString TEXT("3Z")
- #else
- #define kIDByte 0x1
- #define kIDString TEXT("2")
- #endif
-#endif
-
-#undef kIDUse3BytesByte
-#undef kIDUse3BytesString
-
-#define kIDUse3BytesByte 0x00
-#define kIDUse3BytesString TEXT("")
-
-// #undef kIDStringFull
-
-// #define kIDStringFull TEXT("Compress.MatchFinderBT") kIDString kIDUse3BytesString
-
-// {23170F69-40C1-278C-02XX-0000000000}
-DEFINE_GUID(BT_CLSID,
-0x23170F69, 0x40C1, 0x278C, 0x02, kIDByte | kIDUse3BytesByte,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-
-class CInTree2: public CInTree
-{
- CMyComPtr<IMatchFinderCallback> _callback;
- virtual void BeforeMoveBlock();
- virtual void AfterMoveBlock();
-public:
- void SetCallback(IMatchFinderCallback *callback)
- {
- _callback = callback;
- }
-};
-
-class CMatchFinderBinTree:
- public IMatchFinder,
- public IMatchFinderSetCallback,
- public CMyUnknownImp
-{
- MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
-
- STDMETHOD(Init)(ISequentialInStream *stream);
- STDMETHOD_(void, ReleaseStream)();
- STDMETHOD(MovePos)();
- STDMETHOD_(Byte, GetIndexByte)(Int32 index);
- STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
- STDMETHOD_(UInt32, GetNumAvailableBytes)();
- STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
- STDMETHOD(Create)(UInt32 sizeHistory,
- UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
- UInt32 keepAddBufferAfter);
- STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
- STDMETHOD_(void, DummyLongestMatch)();
-
- // IMatchFinderSetCallback
- STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
-
-private:
- // UInt32 m_WindowReservSize;
- CInTree2 _matchFinder;
-public:
- // CMatchFinderBinTree(): m_WindowReservSize((1 << 19) + 256) {};
- void SetCutValue(UInt32 cutValue)
- { _matchFinder.SetCutValue(cutValue); }
- /*
- void SetWindowReservSize(UInt32 reservWindowSize)
- { m_WindowReservSize = reservWindowSize; }
- */
- virtual ~CMatchFinderBinTree() {}
-};
-
-}
-
-// #endif
-
+/* + * BinTreeMF.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +// #ifndef __BINTREEMF_H +// #define __BINTREEMF_H + +#include "../../../ICoder.h" +#include "BinTree.h" + +namespace BT_NAMESPACE { + +#undef kIDByte +#undef kIDString + +#ifdef HASH_ARRAY_2 + #ifdef HASH_ARRAY_3 + #ifdef HASH_BIG + #define kIDByte 0x4 + #define kIDString TEXT("4b") + #else + #define kIDByte 0x3 + #define kIDString TEXT("4") + #endif + #else + #define kIDByte 0x2 + #define kIDString TEXT("3") + #endif +#else + #ifdef HASH_ZIP + #define kIDByte 0x0 + #define kIDString TEXT("3Z") + #else + #define kIDByte 0x1 + #define kIDString TEXT("2") + #endif +#endif + +#undef kIDUse3BytesByte +#undef kIDUse3BytesString + +#define kIDUse3BytesByte 0x00 +#define kIDUse3BytesString TEXT("") + +// #undef kIDStringFull + +// #define kIDStringFull TEXT("Compress.MatchFinderBT") kIDString kIDUse3BytesString + +// {23170F69-40C1-278C-02XX-0000000000} +DEFINE_GUID(BT_CLSID, +0x23170F69, 0x40C1, 0x278C, 0x02, kIDByte | kIDUse3BytesByte, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + +class CInTree2: public CInTree +{ + CMyComPtr<IMatchFinderCallback> _callback; + virtual void BeforeMoveBlock(); + virtual void AfterMoveBlock(); +public: + void SetCallback(IMatchFinderCallback *callback) + { + _callback = callback; + } +}; + +class CMatchFinderBinTree: + public IMatchFinder, + public IMatchFinderSetCallback, + public CMyUnknownImp +{ + MY_UNKNOWN_IMP1(IMatchFinderSetCallback) + + STDMETHOD(Init)(ISequentialInStream *stream); + STDMETHOD_(void, ReleaseStream)(); + STDMETHOD(MovePos)(); + STDMETHOD_(Byte, GetIndexByte)(Int32 index); + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); + STDMETHOD_(UInt32, GetNumAvailableBytes)(); + STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); + STDMETHOD(Create)(UInt32 sizeHistory, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, + UInt32 keepAddBufferAfter); + STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances); + STDMETHOD_(void, DummyLongestMatch)(); + + // IMatchFinderSetCallback + STDMETHOD(SetCallback)(IMatchFinderCallback *callback); + +private: + // UInt32 m_WindowReservSize; + CInTree2 _matchFinder; +public: + // CMatchFinderBinTree(): m_WindowReservSize((1 << 19) + 256) {}; + void SetCutValue(UInt32 cutValue) + { _matchFinder.SetCutValue(cutValue); } + /* + void SetWindowReservSize(UInt32 reservWindowSize) + { m_WindowReservSize = reservWindowSize; } + */ + virtual ~CMatchFinderBinTree() {} +}; + +} + +// #endif + diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h index f72a89e..5b4d979 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMFMain.h @@ -1,98 +1,98 @@ -/*
- * BinTreeMFMain.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-// #include "StdAfx.h"
-
-// #include "BinTreeMF.h"
-#include "BinTreeMain.h"
-
-namespace BT_NAMESPACE {
-
-void CInTree2::BeforeMoveBlock()
-{
- if (_callback)
- _callback->BeforeChangingBufferPos();
- CInTree::BeforeMoveBlock();
-}
-
-void CInTree2::AfterMoveBlock()
-{
- CInTree::AfterMoveBlock();
- if (_callback)
- _callback->AfterChangingBufferPos();
-}
-
-STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream)
- { return _matchFinder.Init(stream); }
-
-STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream()
-{
- // _matchFinder.ReleaseStream();
-}
-
-STDMETHODIMP CMatchFinderBinTree::MovePos()
- { return _matchFinder.MovePos(); }
-
-STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index)
- { return _matchFinder.GetIndexByte(index); }
-
-STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index,
- UInt32 back, UInt32 limit)
- { return _matchFinder.GetMatchLen(index, back, limit); }
-
-STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes()
- { return _matchFinder.GetNumAvailableBytes(); }
-
-STDMETHODIMP CMatchFinderBinTree::Create(UInt32 sizeHistory,
- UInt32 keepAddBufferBefore, UInt32 matchMaxLen,
- UInt32 keepAddBufferAfter)
-{
- UInt32 windowReservSize = (sizeHistory + keepAddBufferBefore +
- matchMaxLen + keepAddBufferAfter) / 2 + 256;
- // try
- {
- return _matchFinder.Create(sizeHistory, keepAddBufferBefore,
- matchMaxLen, keepAddBufferAfter, windowReservSize);
- }
- /*
- catch(...)
- {
- return E_OUTOFMEMORY;
- }
- */
-}
-
-STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
- { return _matchFinder.GetLongestMatch(distances); }
-
-STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
- { _matchFinder.DummyLongestMatch(); }
-
-STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos()
-{
- return _matchFinder.GetPointerToCurrentPos();
-}
-
-// IMatchFinderSetCallback
-STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback)
-{
- _matchFinder.SetCallback(callback);
- return S_OK;
-}
-
-
-}
+/* + * BinTreeMFMain.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +// #include "StdAfx.h" + +// #include "BinTreeMF.h" +#include "BinTreeMain.h" + +namespace BT_NAMESPACE { + +void CInTree2::BeforeMoveBlock() +{ + if (_callback) + _callback->BeforeChangingBufferPos(); + CInTree::BeforeMoveBlock(); +} + +void CInTree2::AfterMoveBlock() +{ + CInTree::AfterMoveBlock(); + if (_callback) + _callback->AfterChangingBufferPos(); +} + +STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream) + { return _matchFinder.Init(stream); } + +STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream() +{ + // _matchFinder.ReleaseStream(); +} + +STDMETHODIMP CMatchFinderBinTree::MovePos() + { return _matchFinder.MovePos(); } + +STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index) + { return _matchFinder.GetIndexByte(index); } + +STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index, + UInt32 back, UInt32 limit) + { return _matchFinder.GetMatchLen(index, back, limit); } + +STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes() + { return _matchFinder.GetNumAvailableBytes(); } + +STDMETHODIMP CMatchFinderBinTree::Create(UInt32 sizeHistory, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, + UInt32 keepAddBufferAfter) +{ + UInt32 windowReservSize = (sizeHistory + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + // try + { + return _matchFinder.Create(sizeHistory, keepAddBufferBefore, + matchMaxLen, keepAddBufferAfter, windowReservSize); + } + /* + catch(...) + { + return E_OUTOFMEMORY; + } + */ +} + +STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances) + { return _matchFinder.GetLongestMatch(distances); } + +STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch() + { _matchFinder.DummyLongestMatch(); } + +STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos() +{ + return _matchFinder.GetPointerToCurrentPos(); +} + +// IMatchFinderSetCallback +STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback) +{ + _matchFinder.SetCallback(callback); + return S_OK; +} + + +} diff --git a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h index ed161c3..486165c 100755 --- a/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h +++ b/Source/7zip/7zip/Compress/LZ/BinTree/BinTreeMain.h @@ -1,546 +1,546 @@ -/*
- * BinTreeMain.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../../../../Common/Defs.h"
-#include "../../../../Common/CRC.h"
-#include "../../../../Common/Alloc.h"
-
-#include "BinTree.h"
-
-// #include <xmmintrin.h>
-// It's for prefetch
-// But prefetch doesn't give big gain in K8.
-
-namespace BT_NAMESPACE {
-
-#ifdef HASH_ARRAY_2
- static const UInt32 kHash2Size = 1 << 10;
- #define kNumHashDirectBytes 0
- #ifdef HASH_ARRAY_3
- static const UInt32 kNumHashBytes = 4;
- static const UInt32 kHash3Size = 1 << 16;
- #else
- static const UInt32 kNumHashBytes = 3;
- #endif
- static const UInt32 kHashSize = 0;
- static const UInt32 kMinMatchCheck = kNumHashBytes;
- static const UInt32 kStartMaxLen = 1;
-#else
- #ifdef HASH_ZIP
- #define kNumHashDirectBytes 0
- static const UInt32 kNumHashBytes = 3;
- static const UInt32 kHashSize = 1 << 16;
- static const UInt32 kMinMatchCheck = kNumHashBytes;
- static const UInt32 kStartMaxLen = 1;
- #else
- #define kNumHashDirectBytes 2
- static const UInt32 kNumHashBytes = 2;
- static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
- static const UInt32 kMinMatchCheck = kNumHashBytes + 1;
- static const UInt32 kStartMaxLen = 1;
- #endif
-#endif
-
-#ifdef HASH_ARRAY_2
-#ifdef HASH_ARRAY_3
-static const UInt32 kHash3Offset = kHash2Size;
-#endif
-#endif
-
-static const UInt32 kFixHashSize = 0
- #ifdef HASH_ARRAY_2
- + kHash2Size
- #ifdef HASH_ARRAY_3
- + kHash3Size
- #endif
- #endif
- ;
-
-CMatchFinder::CMatchFinder():
- _hash(0)
-{
-}
-
-void CMatchFinder::FreeThisClassMemory()
-{
- BigFree(_hash);
- _hash = 0;
-}
-
-void CMatchFinder::FreeMemory()
-{
- FreeThisClassMemory();
- CLZInWindow::Free();
-}
-
-CMatchFinder::~CMatchFinder()
-{
- FreeMemory();
-}
-
-STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
- UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
-{
- if (historySize > kMaxValForNormalize - 256)
- {
- FreeMemory();
- return E_INVALIDARG;
- }
- _cutValue =
- #ifdef _HASH_CHAIN
- 8 + (matchMaxLen >> 2);
- #else
- 16 + (matchMaxLen >> 1);
- #endif
- UInt32 sizeReserv = (historySize + keepAddBufferBefore +
- matchMaxLen + keepAddBufferAfter) / 2 + 256;
- if (CLZInWindow::Create(historySize + keepAddBufferBefore,
- matchMaxLen + keepAddBufferAfter, sizeReserv))
- {
- _matchMaxLen = matchMaxLen;
- UInt32 newCyclicBufferSize = historySize + 1;
- if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
- return S_OK;
- FreeThisClassMemory();
- _cyclicBufferSize = newCyclicBufferSize; // don't change it
-
- UInt32 hs = kHashSize;
-
- #ifdef HASH_ARRAY_2
- hs = historySize - 1;
- hs |= (hs >> 1);
- hs |= (hs >> 2);
- hs |= (hs >> 4);
- hs |= (hs >> 8);
- hs >>= 1;
- hs |= 0xFFFF;
- if (hs > (1 << 24))
- {
- #ifdef HASH_ARRAY_3
- hs >>= 1;
- #else
- hs = (1 << 24) - 1;
- #endif
- }
- _hashMask = hs;
- hs++;
- #endif
- _hashSizeSum = hs + kFixHashSize;
- UInt32 numItems = _hashSizeSum + _cyclicBufferSize
- #ifndef _HASH_CHAIN
- * 2
- #endif
- ;
- size_t sizeInBytes = (size_t)numItems * sizeof(CIndex);
- if (sizeInBytes / sizeof(CIndex) != numItems)
- return E_OUTOFMEMORY;
- _hash = (CIndex *)BigAlloc(sizeInBytes);
- _son = _hash + _hashSizeSum;
- if (_hash != 0)
- return S_OK;
- }
- FreeMemory();
- return E_OUTOFMEMORY;
-}
-
-static const UInt32 kEmptyHashValue = 0;
-
-STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream)
-{
- CLZInWindow::SetStream(stream);
- return S_OK;
-}
-
-STDMETHODIMP CMatchFinder::Init()
-{
- RINOK(CLZInWindow::Init());
- for(UInt32 i = 0; i < _hashSizeSum; i++)
- _hash[i] = kEmptyHashValue;
- _cyclicBufferPos = 0;
- ReduceOffsets(-1);
- return S_OK;
-}
-
-STDMETHODIMP_(void) CMatchFinder::ReleaseStream()
-{
- // ReleaseStream();
-}
-
-#ifdef HASH_ARRAY_2
-#ifdef HASH_ARRAY_3
-
-#define HASH_CALC { \
- UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \
- hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; }
-
-#else // no HASH_ARRAY_3
-#define HASH_CALC { \
- UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \
- hash2Value = temp & (kHash2Size - 1); \
- hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; }
-#endif // HASH_ARRAY_3
-#else // no HASH_ARRAY_2
-#ifdef HASH_ZIP
-inline UInt32 Hash(const Byte *pointer)
-{
- return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
-}
-#else // no HASH_ZIP
-inline UInt32 Hash(const Byte *pointer)
-{
- return pointer[0] ^ (UInt32(pointer[1]) << 8);
-}
-#endif // HASH_ZIP
-#endif // HASH_ARRAY_2
-
-STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances)
-{
- UInt32 lenLimit;
- if (_pos + _matchMaxLen <= _streamPos)
- lenLimit = _matchMaxLen;
- else
- {
- lenLimit = _streamPos - _pos;
- if(lenLimit < kMinMatchCheck)
- {
- distances[0] = 0;
- return MovePos();
- }
- }
-
- int offset = 1;
-
- UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
- const Byte *cur = _buffer + _pos;
-
- UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
-
- #ifdef HASH_ARRAY_2
- UInt32 hash2Value;
- #ifdef HASH_ARRAY_3
- UInt32 hash3Value;
- #endif
- UInt32 hashValue;
- HASH_CALC;
- #else
- UInt32 hashValue = Hash(cur);
- #endif
-
- UInt32 curMatch = _hash[kFixHashSize + hashValue];
- #ifdef HASH_ARRAY_2
- UInt32 curMatch2 = _hash[hash2Value];
- #ifdef HASH_ARRAY_3
- UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
- #endif
- _hash[hash2Value] = _pos;
- if(curMatch2 > matchMinPos)
- if (_buffer[curMatch2] == cur[0])
- {
- distances[offset++] = maxLen = 2;
- distances[offset++] = _pos - curMatch2 - 1;
- }
-
- #ifdef HASH_ARRAY_3
- _hash[kHash3Offset + hash3Value] = _pos;
- if(curMatch3 > matchMinPos)
- if (_buffer[curMatch3] == cur[0])
- {
- if (curMatch3 == curMatch2)
- offset -= 2;
- distances[offset++] = maxLen = 3;
- distances[offset++] = _pos - curMatch3 - 1;
- curMatch2 = curMatch3;
- }
- #endif
- if (offset != 1 && curMatch2 == curMatch)
- {
- offset -= 2;
- maxLen = kStartMaxLen;
- }
- #endif
-
- _hash[kFixHashSize + hashValue] = _pos;
-
- CIndex *son = _son;
-
- #ifdef _HASH_CHAIN
- son[_cyclicBufferPos] = curMatch;
- #else
- CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CIndex *ptr1 = son + (_cyclicBufferPos << 1);
-
- UInt32 len0, len1;
- len0 = len1 = kNumHashDirectBytes;
- #endif
-
- #if kNumHashDirectBytes != 0
- if(curMatch > matchMinPos)
- {
- if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes])
- {
- distances[offset++] = maxLen = kNumHashDirectBytes;
- distances[offset++] = _pos - curMatch - 1;
- }
- }
- #endif
- UInt32 count = _cutValue;
- while(true)
- {
- if(curMatch <= matchMinPos || count-- == 0)
- {
- #ifndef _HASH_CHAIN
- *ptr0 = *ptr1 = kEmptyHashValue;
- #endif
- break;
- }
- UInt32 delta = _pos - curMatch;
- UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
- (_cyclicBufferPos - delta):
- (_cyclicBufferPos - delta + _cyclicBufferSize);
- CIndex *pair = son +
- #ifdef _HASH_CHAIN
- cyclicPos;
- #else
- (cyclicPos << 1);
- #endif
-
- // _mm_prefetch((const char *)pair, _MM_HINT_T0);
-
- const Byte *pb = _buffer + curMatch;
- UInt32 len =
- #ifdef _HASH_CHAIN
- kNumHashDirectBytes;
- if (pb[maxLen] == cur[maxLen])
- #else
- MyMin(len0, len1);
- #endif
- if (pb[len] == cur[len])
- {
- while(++len != lenLimit)
- if (pb[len] != cur[len])
- break;
- if (maxLen < len)
- {
- distances[offset++] = maxLen = len;
- distances[offset++] = delta - 1;
- if (len == lenLimit)
- {
- #ifndef _HASH_CHAIN
- *ptr1 = pair[0];
- *ptr0 = pair[1];
- #endif
- break;
- }
- }
- }
- #ifdef _HASH_CHAIN
- curMatch = *pair;
- #else
- if (pb[len] < cur[len])
- {
- *ptr1 = curMatch;
- ptr1 = pair + 1;
- curMatch = *ptr1;
- len1 = len;
- }
- else
- {
- *ptr0 = curMatch;
- ptr0 = pair;
- curMatch = *ptr0;
- len0 = len;
- }
- #endif
- }
- distances[0] = offset - 1;
- if (++_cyclicBufferPos == _cyclicBufferSize)
- _cyclicBufferPos = 0;
- RINOK(CLZInWindow::MovePos());
- if (_pos == kMaxValForNormalize)
- Normalize();
- return S_OK;
-}
-
-STDMETHODIMP CMatchFinder::Skip(UInt32 num)
-{
- do
- {
- #ifdef _HASH_CHAIN
- if (_streamPos - _pos < kNumHashBytes)
- {
- RINOK(MovePos());
- continue;
- }
- #else
- UInt32 lenLimit;
- if (_pos + _matchMaxLen <= _streamPos)
- lenLimit = _matchMaxLen;
- else
- {
- lenLimit = _streamPos - _pos;
- if(lenLimit < kMinMatchCheck)
- {
- RINOK(MovePos());
- continue;
- }
- }
- UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
- #endif
- const Byte *cur = _buffer + _pos;
-
- #ifdef HASH_ARRAY_2
- UInt32 hash2Value;
- #ifdef HASH_ARRAY_3
- UInt32 hash3Value;
- UInt32 hashValue;
- HASH_CALC;
- _hash[kHash3Offset + hash3Value] = _pos;
- #else
- UInt32 hashValue;
- HASH_CALC;
- #endif
- _hash[hash2Value] = _pos;
- #else
- UInt32 hashValue = Hash(cur);
- #endif
-
- UInt32 curMatch = _hash[kFixHashSize + hashValue];
- _hash[kFixHashSize + hashValue] = _pos;
-
- #ifdef _HASH_CHAIN
- _son[_cyclicBufferPos] = curMatch;
- #else
- CIndex *son = _son;
- CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CIndex *ptr1 = son + (_cyclicBufferPos << 1);
-
- UInt32 len0, len1;
- len0 = len1 = kNumHashDirectBytes;
- UInt32 count = _cutValue;
- while(true)
- {
- if(curMatch <= matchMinPos || count-- == 0)
- {
- *ptr0 = *ptr1 = kEmptyHashValue;
- break;
- }
-
- UInt32 delta = _pos - curMatch;
- UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
- (_cyclicBufferPos - delta):
- (_cyclicBufferPos - delta + _cyclicBufferSize);
- CIndex *pair = son + (cyclicPos << 1);
-
- // _mm_prefetch((const char *)pair, _MM_HINT_T0);
-
- const Byte *pb = _buffer + curMatch;
- UInt32 len = MyMin(len0, len1);
-
- if (pb[len] == cur[len])
- {
- while(++len != lenLimit)
- if (pb[len] != cur[len])
- break;
- if (len == lenLimit)
- {
- *ptr1 = pair[0];
- *ptr0 = pair[1];
- break;
- }
- }
- if (pb[len] < cur[len])
- {
- *ptr1 = curMatch;
- ptr1 = pair + 1;
- curMatch = *ptr1;
- len1 = len;
- }
- else
- {
- *ptr0 = curMatch;
- ptr0 = pair;
- curMatch = *ptr0;
- len0 = len;
- }
- }
- #endif
- if (++_cyclicBufferPos == _cyclicBufferSize)
- _cyclicBufferPos = 0;
- RINOK(CLZInWindow::MovePos());
- if (_pos == kMaxValForNormalize)
- Normalize();
- }
- while(--num != 0);
- return S_OK;
-}
-
-void CMatchFinder::Normalize()
-{
- UInt32 subValue = _pos - _cyclicBufferSize;
- CIndex *items = _hash;
- UInt32 numItems = (_hashSizeSum + _cyclicBufferSize
- #ifndef _HASH_CHAIN
- * 2
- #endif
- );
- for (UInt32 i = 0; i < numItems; i++)
- {
- UInt32 value = items[i];
- if (value <= subValue)
- value = kEmptyHashValue;
- else
- value -= subValue;
- items[i] = value;
- }
- ReduceOffsets(subValue);
-}
-
-HRESULT CMatchFinder::MovePos()
-{
- if (++_cyclicBufferPos == _cyclicBufferSize)
- _cyclicBufferPos = 0;
- RINOK(CLZInWindow::MovePos());
- if (_pos == kMaxValForNormalize)
- Normalize();
- return S_OK;
-}
-
-STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index)
- { return CLZInWindow::GetIndexByte(index); }
-
-STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index,
- UInt32 back, UInt32 limit)
- { return CLZInWindow::GetMatchLen(index, back, limit); }
-
-STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes()
- { return CLZInWindow::GetNumAvailableBytes(); }
-
-STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos()
- { return CLZInWindow::GetPointerToCurrentPos(); }
-
-STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes)
- { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; }
-
-STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos()
- { CLZInWindow::MoveBlock();}
-
-#undef HASH_CALC
-#undef kNumHashDirectBytes
-
-}
+/* + * BinTreeMain.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../../../../Common/Defs.h" +#include "../../../../Common/CRC.h" +#include "../../../../Common/Alloc.h" + +#include "BinTree.h" + +// #include <xmmintrin.h> +// It's for prefetch +// But prefetch doesn't give big gain in K8. + +namespace BT_NAMESPACE { + +#ifdef HASH_ARRAY_2 + static const UInt32 kHash2Size = 1 << 10; + #define kNumHashDirectBytes 0 + #ifdef HASH_ARRAY_3 + static const UInt32 kNumHashBytes = 4; + static const UInt32 kHash3Size = 1 << 16; + #else + static const UInt32 kNumHashBytes = 3; + #endif + static const UInt32 kHashSize = 0; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; +#else + #ifdef HASH_ZIP + #define kNumHashDirectBytes 0 + static const UInt32 kNumHashBytes = 3; + static const UInt32 kHashSize = 1 << 16; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; + #else + #define kNumHashDirectBytes 2 + static const UInt32 kNumHashBytes = 2; + static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); + static const UInt32 kMinMatchCheck = kNumHashBytes + 1; + static const UInt32 kStartMaxLen = 1; + #endif +#endif + +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 +static const UInt32 kHash3Offset = kHash2Size; +#endif +#endif + +static const UInt32 kFixHashSize = 0 + #ifdef HASH_ARRAY_2 + + kHash2Size + #ifdef HASH_ARRAY_3 + + kHash3Size + #endif + #endif + ; + +CMatchFinder::CMatchFinder(): + _hash(0) +{ +} + +void CMatchFinder::FreeThisClassMemory() +{ + BigFree(_hash); + _hash = 0; +} + +void CMatchFinder::FreeMemory() +{ + FreeThisClassMemory(); + CLZInWindow::Free(); +} + +CMatchFinder::~CMatchFinder() +{ + FreeMemory(); +} + +STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) +{ + if (historySize > kMaxValForNormalize - 256) + { + FreeMemory(); + return E_INVALIDARG; + } + _cutValue = + #ifdef _HASH_CHAIN + 8 + (matchMaxLen >> 2); + #else + 16 + (matchMaxLen >> 1); + #endif + UInt32 sizeReserv = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + if (CLZInWindow::Create(historySize + keepAddBufferBefore, + matchMaxLen + keepAddBufferAfter, sizeReserv)) + { + _matchMaxLen = matchMaxLen; + UInt32 newCyclicBufferSize = historySize + 1; + if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) + return S_OK; + FreeThisClassMemory(); + _cyclicBufferSize = newCyclicBufferSize; // don't change it + + UInt32 hs = kHashSize; + + #ifdef HASH_ARRAY_2 + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + { + #ifdef HASH_ARRAY_3 + hs >>= 1; + #else + hs = (1 << 24) - 1; + #endif + } + _hashMask = hs; + hs++; + #endif + _hashSizeSum = hs + kFixHashSize; + UInt32 numItems = _hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ; + size_t sizeInBytes = (size_t)numItems * sizeof(CIndex); + if (sizeInBytes / sizeof(CIndex) != numItems) + return E_OUTOFMEMORY; + _hash = (CIndex *)BigAlloc(sizeInBytes); + _son = _hash + _hashSizeSum; + if (_hash != 0) + return S_OK; + } + FreeMemory(); + return E_OUTOFMEMORY; +} + +static const UInt32 kEmptyHashValue = 0; + +STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream) +{ + CLZInWindow::SetStream(stream); + return S_OK; +} + +STDMETHODIMP CMatchFinder::Init() +{ + RINOK(CLZInWindow::Init()); + for(UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + return S_OK; +} + +STDMETHODIMP_(void) CMatchFinder::ReleaseStream() +{ + // ReleaseStream(); +} + +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 + +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; } + +#else // no HASH_ARRAY_3 +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; } +#endif // HASH_ARRAY_3 +#else // no HASH_ARRAY_2 +#ifdef HASH_ZIP +inline UInt32 Hash(const Byte *pointer) +{ + return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); +} +#else // no HASH_ZIP +inline UInt32 Hash(const Byte *pointer) +{ + return pointer[0] ^ (UInt32(pointer[1]) << 8); +} +#endif // HASH_ZIP +#endif // HASH_ARRAY_2 + +STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances) +{ + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if(lenLimit < kMinMatchCheck) + { + distances[0] = 0; + return MovePos(); + } + } + + int offset = 1; + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + const Byte *cur = _buffer + _pos; + + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + + #ifdef HASH_ARRAY_2 + UInt32 hash2Value; + #ifdef HASH_ARRAY_3 + UInt32 hash3Value; + #endif + UInt32 hashValue; + HASH_CALC; + #else + UInt32 hashValue = Hash(cur); + #endif + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + #ifdef HASH_ARRAY_2 + UInt32 curMatch2 = _hash[hash2Value]; + #ifdef HASH_ARRAY_3 + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + #endif + _hash[hash2Value] = _pos; + if(curMatch2 > matchMinPos) + if (_buffer[curMatch2] == cur[0]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + + #ifdef HASH_ARRAY_3 + _hash[kHash3Offset + hash3Value] = _pos; + if(curMatch3 > matchMinPos) + if (_buffer[curMatch3] == cur[0]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + #endif + if (offset != 1 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + #endif + + _hash[kFixHashSize + hashValue] = _pos; + + CIndex *son = _son; + + #ifdef _HASH_CHAIN + son[_cyclicBufferPos] = curMatch; + #else + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + #endif + + #if kNumHashDirectBytes != 0 + if(curMatch > matchMinPos) + { + if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + #endif + UInt32 count = _cutValue; + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + #ifndef _HASH_CHAIN + *ptr0 = *ptr1 = kEmptyHashValue; + #endif + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + + #ifdef _HASH_CHAIN + cyclicPos; + #else + (cyclicPos << 1); + #endif + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = + #ifdef _HASH_CHAIN + kNumHashDirectBytes; + if (pb[maxLen] == cur[maxLen]) + #else + MyMin(len0, len1); + #endif + if (pb[len] == cur[len]) + { + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + #ifndef _HASH_CHAIN + *ptr1 = pair[0]; + *ptr0 = pair[1]; + #endif + break; + } + } + } + #ifdef _HASH_CHAIN + curMatch = *pair; + #else + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + #endif + } + distances[0] = offset - 1; + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; +} + +STDMETHODIMP CMatchFinder::Skip(UInt32 num) +{ + do + { + #ifdef _HASH_CHAIN + if (_streamPos - _pos < kNumHashBytes) + { + RINOK(MovePos()); + continue; + } + #else + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if(lenLimit < kMinMatchCheck) + { + RINOK(MovePos()); + continue; + } + } + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + #endif + const Byte *cur = _buffer + _pos; + + #ifdef HASH_ARRAY_2 + UInt32 hash2Value; + #ifdef HASH_ARRAY_3 + UInt32 hash3Value; + UInt32 hashValue; + HASH_CALC; + _hash[kHash3Offset + hash3Value] = _pos; + #else + UInt32 hashValue; + HASH_CALC; + #endif + _hash[hash2Value] = _pos; + #else + UInt32 hashValue = Hash(cur); + #endif + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + #ifdef _HASH_CHAIN + _son[_cyclicBufferPos] = curMatch; + #else + CIndex *son = _son; + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + UInt32 count = _cutValue; + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + (cyclicPos << 1); + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = MyMin(len0, len1); + + if (pb[len] == cur[len]) + { + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + #endif + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + } + while(--num != 0); + return S_OK; +} + +void CMatchFinder::Normalize() +{ + UInt32 subValue = _pos - _cyclicBufferSize; + CIndex *items = _hash; + UInt32 numItems = (_hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ); + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + ReduceOffsets(subValue); +} + +HRESULT CMatchFinder::MovePos() +{ + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; +} + +STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index) + { return CLZInWindow::GetIndexByte(index); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, + UInt32 back, UInt32 limit) + { return CLZInWindow::GetMatchLen(index, back, limit); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes() + { return CLZInWindow::GetNumAvailableBytes(); } + +STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos() + { return CLZInWindow::GetPointerToCurrentPos(); } + +STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes) + { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; } + +STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos() + { CLZInWindow::MoveBlock();} + +#undef HASH_CALC +#undef kNumHashDirectBytes + +} diff --git a/Source/7zip/7zip/Compress/LZ/IMatchFinder.h b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h index 2979eaa..007b1e2 100755 --- a/Source/7zip/7zip/Compress/LZ/IMatchFinder.h +++ b/Source/7zip/7zip/Compress/LZ/IMatchFinder.h @@ -1,47 +1,47 @@ -/*
- * IMatchFinder.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __IMATCHFINDER_H
-#define __IMATCHFINDER_H
-
-struct IInWindowStream: public IUnknown
-{
- STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE;
- STDMETHOD_(void, ReleaseStream)() PURE;
- STDMETHOD(Init)() PURE;
- STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE;
- STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE;
- STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE;
- STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE;
- STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE;
- STDMETHOD_(void, ChangeBufferPos)() PURE;
-};
-
-struct IMatchFinder: public IInWindowStream
-{
- STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
- UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE;
- STDMETHOD(GetMatches)(UInt32 *distances) PURE;
- STDMETHOD(Skip)(UInt32 num) PURE;
-};
-
-struct IMatchFinderSetNumPasses
-{
- virtual void SetNumPasses(UInt32 numPasses) PURE;
-};
-
-#endif
+/* + * IMatchFinder.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __IMATCHFINDER_H +#define __IMATCHFINDER_H + +struct IInWindowStream: public IUnknown +{ + STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE; + STDMETHOD_(void, ReleaseStream)() PURE; + STDMETHOD(Init)() PURE; + STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; + STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; + STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE; + STDMETHOD_(void, ChangeBufferPos)() PURE; +}; + +struct IMatchFinder: public IInWindowStream +{ + STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; + STDMETHOD(GetMatches)(UInt32 *distances) PURE; + STDMETHOD(Skip)(UInt32 num) PURE; +}; + +struct IMatchFinderSetNumPasses +{ + virtual void SetNumPasses(UInt32 numPasses) PURE; +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp index c5e1720..0af3b01 100755 --- a/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.cpp @@ -1,120 +1,120 @@ -/*
- * LZInWindow.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "LZInWindow.h"
-#include "../../../Common/MyCom.h"
-#include "../../../Common/Alloc.h"
-
-void CLZInWindow::Free()
-{
- ::BigFree(_bufferBase);
- _bufferBase = 0;
-}
-
-bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
-{
- _keepSizeBefore = keepSizeBefore;
- _keepSizeAfter = keepSizeAfter;
- UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
- if (_bufferBase == 0 || _blockSize != blockSize)
- {
- Free();
- _blockSize = blockSize;
- if (_blockSize != 0)
- _bufferBase = (Byte *)::BigAlloc(_blockSize);
- }
- _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter;
- if (_blockSize == 0)
- return true;
- return (_bufferBase != 0);
-}
-
-void CLZInWindow::SetStream(ISequentialInStream *stream)
-{
- _stream = stream;
-}
-
-HRESULT CLZInWindow::Init()
-{
- _buffer = _bufferBase;
- _pos = 0;
- _streamPos = 0;
- _streamEndWasReached = false;
- return ReadBlock();
-}
-
-/*
-void CLZInWindow::ReleaseStream()
-{
- _stream.Release();
-}
-*/
-
-///////////////////////////////////////////
-// ReadBlock
-
-// In State:
-// (_buffer + _streamPos) <= (_bufferBase + _blockSize)
-// Out State:
-// _posLimit <= _blockSize - _keepSizeAfter;
-// if(_streamEndWasReached == false):
-// _streamPos >= _pos + _keepSizeAfter
-// _posLimit = _streamPos - _keepSizeAfter;
-// else
-//
-
-HRESULT CLZInWindow::ReadBlock()
-{
- if(_streamEndWasReached)
- return S_OK;
- while(true)
- {
- UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos;
- if(size == 0)
- return S_OK;
- UInt32 numReadBytes;
- RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes));
- if(numReadBytes == 0)
- {
- _posLimit = _streamPos;
- const Byte *pointerToPostion = _buffer + _posLimit;
- if(pointerToPostion > _pointerToLastSafePosition)
- _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer);
- _streamEndWasReached = true;
- return S_OK;
- }
- _streamPos += numReadBytes;
- if(_streamPos >= _pos + _keepSizeAfter)
- {
- _posLimit = _streamPos - _keepSizeAfter;
- return S_OK;
- }
- }
-}
-
-void CLZInWindow::MoveBlock()
-{
- UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore;
- // we need one additional byte, since MovePos moves on 1 byte.
- if (offset > 0)
- offset--;
- UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset;
- memmove(_bufferBase, _bufferBase + offset, numBytes);
- _buffer -= offset;
-}
+/* + * LZInWindow.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "LZInWindow.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/Alloc.h" + +void CLZInWindow::Free() +{ + ::BigFree(_bufferBase); + _bufferBase = 0; +} + +bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) +{ + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == 0 || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + if (_blockSize != 0) + _bufferBase = (Byte *)::BigAlloc(_blockSize); + } + _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; + if (_blockSize == 0) + return true; + return (_bufferBase != 0); +} + +void CLZInWindow::SetStream(ISequentialInStream *stream) +{ + _stream = stream; +} + +HRESULT CLZInWindow::Init() +{ + _buffer = _bufferBase; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + return ReadBlock(); +} + +/* +void CLZInWindow::ReleaseStream() +{ + _stream.Release(); +} +*/ + +/////////////////////////////////////////// +// ReadBlock + +// In State: +// (_buffer + _streamPos) <= (_bufferBase + _blockSize) +// Out State: +// _posLimit <= _blockSize - _keepSizeAfter; +// if(_streamEndWasReached == false): +// _streamPos >= _pos + _keepSizeAfter +// _posLimit = _streamPos - _keepSizeAfter; +// else +// + +HRESULT CLZInWindow::ReadBlock() +{ + if(_streamEndWasReached) + return S_OK; + while(true) + { + UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos; + if(size == 0) + return S_OK; + UInt32 numReadBytes; + RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); + if(numReadBytes == 0) + { + _posLimit = _streamPos; + const Byte *pointerToPostion = _buffer + _posLimit; + if(pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); + _streamEndWasReached = true; + return S_OK; + } + _streamPos += numReadBytes; + if(_streamPos >= _pos + _keepSizeAfter) + { + _posLimit = _streamPos - _keepSizeAfter; + return S_OK; + } + } +} + +void CLZInWindow::MoveBlock() +{ + UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset; + memmove(_bufferBase, _bufferBase + offset, numBytes); + _buffer -= offset; +} diff --git a/Source/7zip/7zip/Compress/LZ/LZInWindow.h b/Source/7zip/7zip/Compress/LZ/LZInWindow.h index 1bafd1a..4d6c5fe 100755 --- a/Source/7zip/7zip/Compress/LZ/LZInWindow.h +++ b/Source/7zip/7zip/Compress/LZ/LZInWindow.h @@ -1,102 +1,102 @@ -/*
- * LZInWindow.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __LZ_IN_WINDOW_H
-#define __LZ_IN_WINDOW_H
-
-#include "../../IStream.h"
-
-class CLZInWindow
-{
- Byte *_bufferBase; // pointer to buffer with data
- ISequentialInStream *_stream;
- UInt32 _posLimit; // offset (from _buffer) when new block reading must be done
- bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
- const Byte *_pointerToLastSafePosition;
-protected:
- Byte *_buffer; // Pointer to virtual Buffer begin
- UInt32 _blockSize; // Size of Allocated memory block
- UInt32 _pos; // offset (from _buffer) of curent byte
- UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
- UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
- UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
-
- void MoveBlock();
- HRESULT ReadBlock();
- void Free();
-public:
- CLZInWindow(): _bufferBase(0) {}
- virtual ~CLZInWindow() { Free(); }
-
- // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G)
- bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17));
-
- void SetStream(ISequentialInStream *stream);
- HRESULT Init();
- // void ReleaseStream();
-
- Byte *GetBuffer() const { return _buffer; }
-
- const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; }
-
- HRESULT MovePos()
- {
- _pos++;
- if (_pos > _posLimit)
- {
- const Byte *pointerToPostion = _buffer + _pos;
- if(pointerToPostion > _pointerToLastSafePosition)
- MoveBlock();
- return ReadBlock();
- }
- else
- return S_OK;
- }
- Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; }
-
- // index + limit have not to exceed _keepSizeAfter;
- // -2G <= index < 2G
- UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const
- {
- if(_streamEndWasReached)
- if ((_pos + index) + limit > _streamPos)
- limit = _streamPos - (_pos + index);
- distance++;
- const Byte *pby = _buffer + (size_t)_pos + index;
- UInt32 i;
- for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++);
- return i;
- }
-
- UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; }
-
- void ReduceOffsets(Int32 subValue)
- {
- _buffer += subValue;
- _posLimit -= subValue;
- _pos -= subValue;
- _streamPos -= subValue;
- }
-
- bool NeedMove(UInt32 numCheckBytes)
- {
- UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos);
- return (reserv <= numCheckBytes);
- }
-};
-
-#endif
+/* + * LZInWindow.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __LZ_IN_WINDOW_H +#define __LZ_IN_WINDOW_H + +#include "../../IStream.h" + +class CLZInWindow +{ + Byte *_bufferBase; // pointer to buffer with data + ISequentialInStream *_stream; + UInt32 _posLimit; // offset (from _buffer) when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + const Byte *_pointerToLastSafePosition; +protected: + Byte *_buffer; // Pointer to virtual Buffer begin + UInt32 _blockSize; // Size of Allocated memory block + UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + void MoveBlock(); + HRESULT ReadBlock(); + void Free(); +public: + CLZInWindow(): _bufferBase(0) {} + virtual ~CLZInWindow() { Free(); } + + // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G) + bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); + + void SetStream(ISequentialInStream *stream); + HRESULT Init(); + // void ReleaseStream(); + + Byte *GetBuffer() const { return _buffer; } + + const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } + + HRESULT MovePos() + { + _pos++; + if (_pos > _posLimit) + { + const Byte *pointerToPostion = _buffer + _pos; + if(pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + return ReadBlock(); + } + else + return S_OK; + } + Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + // -2G <= index < 2G + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const + { + if(_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (_pos + index); + distance++; + const Byte *pby = _buffer + (size_t)_pos + index; + UInt32 i; + for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); + return i; + } + + UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } + + void ReduceOffsets(Int32 subValue) + { + _buffer += subValue; + _posLimit -= subValue; + _pos -= subValue; + _streamPos -= subValue; + } + + bool NeedMove(UInt32 numCheckBytes) + { + UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos); + return (reserv <= numCheckBytes); + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp index 5370eff..cf05633 100755 --- a/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.cpp @@ -1,32 +1,32 @@ -/*
- * LZOutWindow.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "../../../Common/Alloc.h"
-#include "LZOutWindow.h"
-
-void CLZOutWindow::Init(bool solid)
-{
- if(!solid)
- COutBuffer::Init();
- #ifdef _NO_EXCEPTIONS
- ErrorCode = S_OK;
- #endif
-}
-
-
+/* + * LZOutWindow.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "../../../Common/Alloc.h" +#include "LZOutWindow.h" + +void CLZOutWindow::Init(bool solid) +{ + if(!solid) + COutBuffer::Init(); + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + + diff --git a/Source/7zip/7zip/Compress/LZ/LZOutWindow.h b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h index e0ee36e..32648a0 100755 --- a/Source/7zip/7zip/Compress/LZ/LZOutWindow.h +++ b/Source/7zip/7zip/Compress/LZ/LZOutWindow.h @@ -1,71 +1,71 @@ -/*
- * LZOutWindow.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __LZ_OUT_WINDOW_H
-#define __LZ_OUT_WINDOW_H
-
-#include "../../IStream.h"
-#include "../../Common/OutBuffer.h"
-
-#ifndef _NO_EXCEPTIONS
-typedef COutBufferException CLZOutWindowException;
-#endif
-
-class CLZOutWindow: public COutBuffer
-{
-public:
- void Init(bool solid = false);
-
- // distance >= 0, len > 0,
- bool CopyBlock(UInt32 distance, UInt32 len)
- {
- UInt32 pos = _pos - distance - 1;
- if (distance >= _pos)
- {
- if (!_overDict || distance >= _bufferSize)
- return false;
- pos += _bufferSize;
- }
- do
- {
- if (pos == _bufferSize)
- pos = 0;
- _buffer[_pos++] = _buffer[pos++];
- if (_pos == _limitPos)
- FlushWithCheck();
- }
- while(--len != 0);
- return true;
- }
-
- void PutByte(Byte b)
- {
- _buffer[_pos++] = b;
- if (_pos == _limitPos)
- FlushWithCheck();
- }
-
- Byte GetByte(UInt32 distance) const
- {
- UInt32 pos = _pos - distance - 1;
- if (pos >= _bufferSize)
- pos += _bufferSize;
- return _buffer[pos];
- }
-};
-
-#endif
+/* + * LZOutWindow.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __LZ_OUT_WINDOW_H +#define __LZ_OUT_WINDOW_H + +#include "../../IStream.h" +#include "../../Common/OutBuffer.h" + +#ifndef _NO_EXCEPTIONS +typedef COutBufferException CLZOutWindowException; +#endif + +class CLZOutWindow: public COutBuffer +{ +public: + void Init(bool solid = false); + + // distance >= 0, len > 0, + bool CopyBlock(UInt32 distance, UInt32 len) + { + UInt32 pos = _pos - distance - 1; + if (distance >= _pos) + { + if (!_overDict || distance >= _bufferSize) + return false; + pos += _bufferSize; + } + do + { + if (pos == _bufferSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos == _limitPos) + FlushWithCheck(); + } + while(--len != 0); + return true; + } + + void PutByte(Byte b) + { + _buffer[_pos++] = b; + if (_pos == _limitPos) + FlushWithCheck(); + } + + Byte GetByte(UInt32 distance) const + { + UInt32 pos = _pos - distance - 1; + if (pos >= _bufferSize) + pos += _bufferSize; + return _buffer[pos]; + } +}; + +#endif diff --git a/Source/7zip/7zip/Compress/LZ/StdAfx.h b/Source/7zip/7zip/Compress/LZ/StdAfx.h index 3de038a..3ff6d8a 100755 --- a/Source/7zip/7zip/Compress/LZ/StdAfx.h +++ b/Source/7zip/7zip/Compress/LZ/StdAfx.h @@ -1,6 +1,6 @@ -// StdAfx.h
-
-#ifndef __STDAFX_H
-#define __STDAFX_H
-
-#endif
+// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMA.h b/Source/7zip/7zip/Compress/LZMA/LZMA.h index 13e94e0..dbab974 100755 --- a/Source/7zip/7zip/Compress/LZMA/LZMA.h +++ b/Source/7zip/7zip/Compress/LZMA/LZMA.h @@ -1,97 +1,97 @@ -/*
- * LZMA.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __LZMA_H
-#define __LZMA_H
-
-namespace NCompress {
-namespace NLZMA {
-
-const UInt32 kNumRepDistances = 4;
-
-const int kNumStates = 12;
-
-const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
-const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
-const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
-const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
-
-class CState
-{
-public:
- Byte Index;
- void Init() { Index = 0; }
- void UpdateChar() { Index = kLiteralNextStates[Index]; }
- void UpdateMatch() { Index = kMatchNextStates[Index]; }
- void UpdateRep() { Index = kRepNextStates[Index]; }
- void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
- bool IsCharState() const { return Index < 7; }
-};
-
-const int kNumPosSlotBits = 6;
-const int kDicLogSizeMin = 0;
-const int kDicLogSizeMax = 32;
-const int kDistTableSizeMax = kDicLogSizeMax * 2;
-
-const UInt32 kNumLenToPosStates = 4;
-
-inline UInt32 GetLenToPosState(UInt32 len)
-{
- len -= 2;
- if (len < kNumLenToPosStates)
- return len;
- return kNumLenToPosStates - 1;
-}
-
-namespace NLength {
-
-const int kNumPosStatesBitsMax = 4;
-const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
-
-const int kNumPosStatesBitsEncodingMax = 4;
-const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
-
-const int kNumLowBits = 3;
-const int kNumMidBits = 3;
-const int kNumHighBits = 8;
-const UInt32 kNumLowSymbols = 1 << kNumLowBits;
-const UInt32 kNumMidSymbols = 1 << kNumMidBits;
-const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);
-
-}
-
-const UInt32 kMatchMinLen = 2;
-const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;
-
-const int kNumAlignBits = 4;
-const UInt32 kAlignTableSize = 1 << kNumAlignBits;
-const UInt32 kAlignMask = (kAlignTableSize - 1);
-
-const UInt32 kStartPosModelIndex = 4;
-const UInt32 kEndPosModelIndex = 14;
-const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
-
-const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2);
-
-const int kNumLitPosStatesBitsEncodingMax = 4;
-const int kNumLitContextBitsMax = 8;
-
-const int kNumMoveBits = 5;
-
-}}
-
-#endif
+/* + * LZMA.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __LZMA_H +#define __LZMA_H + +namespace NCompress { +namespace NLZMA { + +const UInt32 kNumRepDistances = 4; + +const int kNumStates = 12; + +const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +class CState +{ +public: + Byte Index; + void Init() { Index = 0; } + void UpdateChar() { Index = kLiteralNextStates[Index]; } + void UpdateMatch() { Index = kMatchNextStates[Index]; } + void UpdateRep() { Index = kRepNextStates[Index]; } + void UpdateShortRep() { Index = kShortRepNextStates[Index]; } + bool IsCharState() const { return Index < 7; } +}; + +const int kNumPosSlotBits = 6; +const int kDicLogSizeMin = 0; +const int kDicLogSizeMax = 32; +const int kDistTableSizeMax = kDicLogSizeMax * 2; + +const UInt32 kNumLenToPosStates = 4; + +inline UInt32 GetLenToPosState(UInt32 len) +{ + len -= 2; + if (len < kNumLenToPosStates) + return len; + return kNumLenToPosStates - 1; +} + +namespace NLength { + +const int kNumPosStatesBitsMax = 4; +const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + +const int kNumPosStatesBitsEncodingMax = 4; +const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + +const int kNumLowBits = 3; +const int kNumMidBits = 3; +const int kNumHighBits = 8; +const UInt32 kNumLowSymbols = 1 << kNumLowBits; +const UInt32 kNumMidSymbols = 1 << kNumMidBits; +const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); + +} + +const UInt32 kMatchMinLen = 2; +const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; + +const int kNumAlignBits = 4; +const UInt32 kAlignTableSize = 1 << kNumAlignBits; +const UInt32 kAlignMask = (kAlignTableSize - 1); + +const UInt32 kStartPosModelIndex = 4; +const UInt32 kEndPosModelIndex = 14; +const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + +const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); + +const int kNumLitPosStatesBitsEncodingMax = 4; +const int kNumLitContextBitsMax = 8; + +const int kNumMoveBits = 5; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp index 5eae213..171ff7f 100755 --- a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.cpp @@ -1,1580 +1,1580 @@ -/*
- * LZMAEncoder.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "../../../Common/Defs.h"
-#include "../../Common/StreamUtils.h"
-
-#include "LZMAEncoder.h"
-
-// for minimal compressing code size define these:
-// #define COMPRESS_MF_BT
-// #define COMPRESS_MF_BT4
-
-#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC)
-#define COMPRESS_MF_BT
-#define COMPRESS_MF_HC
-#endif
-
-#ifdef COMPRESS_MF_BT
-#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4)
-#define COMPRESS_MF_BT2
-#define COMPRESS_MF_BT3
-#define COMPRESS_MF_BT4
-#endif
-#ifdef COMPRESS_MF_BT2
-#include "../LZ/BinTree/BinTree2.h"
-#endif
-#ifdef COMPRESS_MF_BT3
-#include "../LZ/BinTree/BinTree3.h"
-#endif
-#ifdef COMPRESS_MF_BT4
-#include "../LZ/BinTree/BinTree4.h"
-#endif
-#endif
-
-#ifdef COMPRESS_MF_HC
-#include "../LZ/HashChain/HC4.h"
-#endif
-
-#ifdef COMPRESS_MF_MT
-#include "../LZ/MT/MT.h"
-#endif
-
-namespace NCompress {
-namespace NLZMA {
-
-const int kDefaultDictionaryLogSize = 22;
-const UInt32 kNumFastBytesDefault = 0x20;
-
-enum
-{
- kBT2,
- kBT3,
- kBT4,
- kHC4
-};
-
-/*static const wchar_t *kMatchFinderIDs[] =
-{
- L"BT2",
- L"BT3",
- L"BT4",
- L"HC4"
-};*/
-
-Byte g_FastPos[1 << 11];
-
-class CFastPosInit
-{
-public:
- CFastPosInit() { Init(); }
- void Init()
- {
- const Byte kFastSlots = 22;
- int c = 2;
- g_FastPos[0] = 0;
- g_FastPos[1] = 1;
-
- for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
- {
- UInt32 k = (1 << ((slotFast >> 1) - 1));
- for (UInt32 j = 0; j < k; j++, c++)
- g_FastPos[c] = slotFast;
- }
- }
-} g_FastPosInit;
-
-
-void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
-{
- UInt32 context = 1;
- int i = 8;
- do
- {
- i--;
- UInt32 bit = (symbol >> i) & 1;
- _encoders[context].Encode(rangeEncoder, bit);
- context = (context << 1) | bit;
- }
- while(i != 0);
-}
-
-void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder,
- Byte matchByte, Byte symbol)
-{
- UInt32 context = 1;
- int i = 8;
- do
- {
- i--;
- UInt32 bit = (symbol >> i) & 1;
- UInt32 matchBit = (matchByte >> i) & 1;
- _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
- context = (context << 1) | bit;
- if (matchBit != bit)
- {
- while(i != 0)
- {
- i--;
- UInt32 bit = (symbol >> i) & 1;
- _encoders[context].Encode(rangeEncoder, bit);
- context = (context << 1) | bit;
- }
- break;
- }
- }
- while(i != 0);
-}
-
-UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
-{
- UInt32 price = 0;
- UInt32 context = 1;
- int i = 8;
- if (matchMode)
- {
- do
- {
- i--;
- UInt32 matchBit = (matchByte >> i) & 1;
- UInt32 bit = (symbol >> i) & 1;
- price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
- context = (context << 1) | bit;
- if (matchBit != bit)
- break;
- }
- while (i != 0);
- }
- while(i != 0)
- {
- i--;
- UInt32 bit = (symbol >> i) & 1;
- price += _encoders[context].GetPrice(bit);
- context = (context << 1) | bit;
- }
- return price;
-};
-
-
-namespace NLength {
-
-void CEncoder::Init(UInt32 numPosStates)
-{
- _choice.Init();
- _choice2.Init();
- for (UInt32 posState = 0; posState < numPosStates; posState++)
- {
- _lowCoder[posState].Init();
- _midCoder[posState].Init();
- }
- _highCoder.Init();
-}
-
-void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
-{
- if(symbol < kNumLowSymbols)
- {
- _choice.Encode(rangeEncoder, 0);
- _lowCoder[posState].Encode(rangeEncoder, symbol);
- }
- else
- {
- _choice.Encode(rangeEncoder, 1);
- if(symbol < kNumLowSymbols + kNumMidSymbols)
- {
- _choice2.Encode(rangeEncoder, 0);
- _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
- }
- else
- {
- _choice2.Encode(rangeEncoder, 1);
- _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
- }
- }
-}
-
-void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const
-{
- UInt32 a0 = _choice.GetPrice0();
- UInt32 a1 = _choice.GetPrice1();
- UInt32 b0 = a1 + _choice2.GetPrice0();
- UInt32 b1 = a1 + _choice2.GetPrice1();
- UInt32 i = 0;
- for (i = 0; i < kNumLowSymbols; i++)
- {
- if (i >= numSymbols)
- return;
- prices[i] = a0 + _lowCoder[posState].GetPrice(i);
- }
- for (; i < kNumLowSymbols + kNumMidSymbols; i++)
- {
- if (i >= numSymbols)
- return;
- prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols);
- }
- for (; i < numSymbols; i++)
- prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols);
-}
-
-}
-CEncoder::CEncoder():
- _numFastBytes(kNumFastBytesDefault),
- _distTableSize(kDefaultDictionaryLogSize * 2),
- _posStateBits(2),
- _posStateMask(4 - 1),
- _numLiteralPosStateBits(0),
- _numLiteralContextBits(3),
- _dictionarySize(1 << kDefaultDictionaryLogSize),
- _dictionarySizePrev(UInt32(-1)),
- _numFastBytesPrev(UInt32(-1)),
- _matchFinderCycles(0),
- _matchFinderIndex(kBT4),
- #ifdef COMPRESS_MF_MT
- _multiThread(false),
- #endif
- _writeEndMark(false),
- setMfPasses(0)
-{
- // _maxMode = false;
- _fastMode = false;
-}
-
-HRESULT CEncoder::Create()
-{
- if (!_rangeEncoder.Create(1 << 20))
- return E_OUTOFMEMORY;
- if (!_matchFinder)
- {
- switch(_matchFinderIndex)
- {
- #ifdef COMPRESS_MF_BT
- #ifdef COMPRESS_MF_BT2
- case kBT2:
- {
- NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder;
- setMfPasses = mfSpec;
- _matchFinder = mfSpec;
- break;
- }
- #endif
- #ifdef COMPRESS_MF_BT3
- case kBT3:
- {
- NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder;
- setMfPasses = mfSpec;
- _matchFinder = mfSpec;
- break;
- }
- #endif
- #ifdef COMPRESS_MF_BT4
- case kBT4:
- {
- NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder;
- setMfPasses = mfSpec;
- _matchFinder = mfSpec;
- break;
- }
- #endif
- #endif
-
- #ifdef COMPRESS_MF_HC
- case kHC4:
- {
- NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder;
- setMfPasses = mfSpec;
- _matchFinder = mfSpec;
- break;
- }
- #endif
- }
- if (_matchFinder == 0)
- return E_OUTOFMEMORY;
-
- #ifdef COMPRESS_MF_MT
- if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4)))
- {
- CMatchFinderMT *mfSpec = new CMatchFinderMT;
- if (mfSpec == 0)
- return E_OUTOFMEMORY;
- CMyComPtr<IMatchFinder> mf = mfSpec;
- RINOK(mfSpec->SetMatchFinder(_matchFinder));
- _matchFinder.Release();
- _matchFinder = mf;
- }
- #endif
- }
-
- if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
- return E_OUTOFMEMORY;
-
- if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
- return S_OK;
- RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes
- if (_matchFinderCycles != 0 && setMfPasses != 0)
- setMfPasses->SetNumPasses(_matchFinderCycles);
- _dictionarySizePrev = _dictionarySize;
- _numFastBytesPrev = _numFastBytes;
- return S_OK;
-}
-
-/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
-{
- while (true)
- {
- wchar_t c = *testString;
- if (c >= 'a' && c <= 'z')
- c -= 0x20;
- if (*base != c)
- return false;
- if (c == 0)
- return true;
- base++;
- testString++;
- }
-}
-
-static int FindMatchFinder(const wchar_t *s)
-{
- for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++)
- if (AreStringsEqual(kMatchFinderIDs[m], s))
- return m;
- return -1;
-}*/
-
-STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
- const PROPVARIANT *properties, UInt32 numProperties)
-{
- for (UInt32 i = 0; i < numProperties; i++)
- {
- const PROPVARIANT &prop = properties[i];
- switch(propIDs[i])
- {
- case NCoderPropID::kNumFastBytes:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 numFastBytes = prop.ulVal;
- if(numFastBytes < 5 || numFastBytes > kMatchMaxLen)
- return E_INVALIDARG;
- _numFastBytes = numFastBytes;
- break;
- }
- case NCoderPropID::kMatchFinderCycles:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- _matchFinderCycles = prop.ulVal;
- break;
- }
- case NCoderPropID::kAlgorithm:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 maximize = prop.ulVal;
- _fastMode = (maximize == 0);
- // _maxMode = (maximize >= 2);
- break;
- }
- case NCoderPropID::kMatchFinder:
- {
- return E_NOTIMPL;
- /*if (prop.vt != VT_BSTR)
- return E_INVALIDARG;
- int matchFinderIndexPrev = _matchFinderIndex;
- int m = FindMatchFinder(prop.bstrVal);
- if (m < 0)
- return E_INVALIDARG;
- _matchFinderIndex = m;
- if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex)
- {
- _dictionarySizePrev = (UInt32)-1;
- ReleaseMatchFinder();
- }
- break;*/
- }
- #ifdef COMPRESS_MF_MT
- case NCoderPropID::kMultiThread:
- {
- if (prop.vt != VT_BOOL)
- return E_INVALIDARG;
- bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
- if (newMultiThread != _multiThread)
- {
- _dictionarySizePrev = (UInt32)-1;
- ReleaseMatchFinder();
- _multiThread = newMultiThread;
- }
- break;
- }
- case NCoderPropID::kNumThreads:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- bool newMultiThread = (prop.ulVal > 1);
- if (newMultiThread != _multiThread)
- {
- _dictionarySizePrev = (UInt32)-1;
- ReleaseMatchFinder();
- _multiThread = newMultiThread;
- }
- break;
- }
- #endif
- case NCoderPropID::kDictionarySize:
- {
- const int kDicLogSizeMaxCompress = 30;
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 dictionarySize = prop.ulVal;
- if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
- dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
- return E_INVALIDARG;
- _dictionarySize = dictionarySize;
- UInt32 dicLogSize;
- for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
- if (dictionarySize <= (UInt32(1) << dicLogSize))
- break;
- _distTableSize = dicLogSize * 2;
- break;
- }
- case NCoderPropID::kPosStateBits:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 value = prop.ulVal;
- if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
- return E_INVALIDARG;
- _posStateBits = value;
- _posStateMask = (1 << _posStateBits) - 1;
- break;
- }
- case NCoderPropID::kLitPosBits:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 value = prop.ulVal;
- if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
- return E_INVALIDARG;
- _numLiteralPosStateBits = value;
- break;
- }
- case NCoderPropID::kLitContextBits:
- {
- if (prop.vt != VT_UI4)
- return E_INVALIDARG;
- UInt32 value = prop.ulVal;
- if (value > (UInt32)kNumLitContextBitsMax)
- return E_INVALIDARG;
- _numLiteralContextBits = value;
- break;
- }
- case NCoderPropID::kEndMarker:
- {
- if (prop.vt != VT_BOOL)
- return E_INVALIDARG;
- SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
- break;
- }
- default:
- return E_INVALIDARG;
- }
- }
- return S_OK;
-}
-
-STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
-{
- const UInt32 kPropSize = 5;
- Byte properties[kPropSize];
- properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits;
- for (int i = 0; i < 4; i++)
- properties[1 + i] = Byte(_dictionarySize >> (8 * i));
- return WriteStream(outStream, properties, kPropSize, NULL);
-}
-
-STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
-{
- _rangeEncoder.SetStream(outStream);
- return S_OK;
-}
-
-STDMETHODIMP CEncoder::ReleaseOutStream()
-{
- _rangeEncoder.ReleaseStream();
- return S_OK;
-}
-
-HRESULT CEncoder::Init()
-{
- CBaseState::Init();
-
- // RINOK(_matchFinder->Init(inStream));
- _rangeEncoder.Init();
-
- for(int i = 0; i < kNumStates; i++)
- {
- for (UInt32 j = 0; j <= _posStateMask; j++)
- {
- _isMatch[i][j].Init();
- _isRep0Long[i][j].Init();
- }
- _isRep[i].Init();
- _isRepG0[i].Init();
- _isRepG1[i].Init();
- _isRepG2[i].Init();
- }
-
- _literalEncoder.Init();
-
- {
- for(UInt32 i = 0; i < kNumLenToPosStates; i++)
- _posSlotEncoder[i].Init();
- }
- {
- for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
- _posEncoders[i].Init();
- }
-
- _lenEncoder.Init(1 << _posStateBits);
- _repMatchLenEncoder.Init(1 << _posStateBits);
-
- _posAlignEncoder.Init();
-
- _longestMatchWasFound = false;
- _optimumEndIndex = 0;
- _optimumCurrentIndex = 0;
- _additionalOffset = 0;
-
- return S_OK;
-}
-
-HRESULT CEncoder::MovePos(UInt32 num)
-{
- if (num == 0)
- return S_OK;
- _additionalOffset += num;
- return _matchFinder->Skip(num);
-}
-
-UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
-{
- _optimumEndIndex = cur;
- UInt32 posMem = _optimum[cur].PosPrev;
- UInt32 backMem = _optimum[cur].BackPrev;
- do
- {
- if (_optimum[cur].Prev1IsChar)
- {
- _optimum[posMem].MakeAsChar();
- _optimum[posMem].PosPrev = posMem - 1;
- if (_optimum[cur].Prev2)
- {
- _optimum[posMem - 1].Prev1IsChar = false;
- _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
- _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
- }
- }
- UInt32 posPrev = posMem;
- UInt32 backCur = backMem;
-
- backMem = _optimum[posPrev].BackPrev;
- posMem = _optimum[posPrev].PosPrev;
-
- _optimum[posPrev].BackPrev = backCur;
- _optimum[posPrev].PosPrev = cur;
- cur = posPrev;
- }
- while(cur != 0);
- backRes = _optimum[0].BackPrev;
- _optimumCurrentIndex = _optimum[0].PosPrev;
- return _optimumCurrentIndex;
-}
-
-/*
-Out:
- (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal
-*/
-
-HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
-{
- if(_optimumEndIndex != _optimumCurrentIndex)
- {
- const COptimal &optimum = _optimum[_optimumCurrentIndex];
- lenRes = optimum.PosPrev - _optimumCurrentIndex;
- backRes = optimum.BackPrev;
- _optimumCurrentIndex = optimum.PosPrev;
- return S_OK;
- }
- _optimumCurrentIndex = _optimumEndIndex = 0;
-
- UInt32 lenMain, numDistancePairs;
- if (!_longestMatchWasFound)
- {
- RINOK(ReadMatchDistances(lenMain, numDistancePairs));
- }
- else
- {
- lenMain = _longestMatchLength;
- numDistancePairs = _numDistancePairs;
- _longestMatchWasFound = false;
- }
-
- const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
- UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;
- if (numAvailableBytes < 2)
- {
- backRes = (UInt32)(-1);
- lenRes = 1;
- return S_OK;
- }
- if (numAvailableBytes > kMatchMaxLen)
- numAvailableBytes = kMatchMaxLen;
-
- UInt32 reps[kNumRepDistances];
- UInt32 repLens[kNumRepDistances];
- UInt32 repMaxIndex = 0;
- UInt32 i;
- for(i = 0; i < kNumRepDistances; i++)
- {
- reps[i] = _repDistances[i];
- UInt32 backOffset = reps[i] + 1;
- if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset])
- {
- repLens[i] = 0;
- continue;
- }
- UInt32 lenTest;
- for (lenTest = 2; lenTest < numAvailableBytes &&
- data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++);
- repLens[i] = lenTest;
- if (lenTest > repLens[repMaxIndex])
- repMaxIndex = i;
- }
- if(repLens[repMaxIndex] >= _numFastBytes)
- {
- backRes = repMaxIndex;
- lenRes = repLens[repMaxIndex];
- return MovePos(lenRes - 1);
- }
-
- UInt32 *matchDistances = _matchDistances + 1;
- if(lenMain >= _numFastBytes)
- {
- backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
- lenRes = lenMain;
- return MovePos(lenMain - 1);
- }
- Byte currentByte = *data;
- Byte matchByte = data[(size_t)0 - reps[0] - 1];
-
- if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
- {
- backRes = (UInt32)-1;
- lenRes = 1;
- return S_OK;
- }
-
- _optimum[0].State = _state;
-
- UInt32 posState = (position & _posStateMask);
-
- _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
- _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte);
- _optimum[1].MakeAsChar();
-
- UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
- UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
-
- if(matchByte == currentByte)
- {
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
- if(shortRepPrice < _optimum[1].Price)
- {
- _optimum[1].Price = shortRepPrice;
- _optimum[1].MakeAsShortRep();
- }
- }
- UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
-
- if(lenEnd < 2)
- {
- backRes = _optimum[1].BackPrev;
- lenRes = 1;
- return S_OK;
- }
-
- _optimum[1].PosPrev = 0;
- for (i = 0; i < kNumRepDistances; i++)
- _optimum[0].Backs[i] = reps[i];
-
- UInt32 len = lenEnd;
- do
- _optimum[len--].Price = kIfinityPrice;
- while (len >= 2);
-
- for(i = 0; i < kNumRepDistances; i++)
- {
- UInt32 repLen = repLens[i];
- if (repLen < 2)
- continue;
- UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
- do
- {
- UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
- COptimal &optimum = _optimum[repLen];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = 0;
- optimum.BackPrev = i;
- optimum.Prev1IsChar = false;
- }
- }
- while(--repLen >= 2);
- }
-
- UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
-
- len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
- if (len <= lenMain)
- {
- UInt32 offs = 0;
- while (len > matchDistances[offs])
- offs += 2;
- for(; ; len++)
- {
- UInt32 distance = matchDistances[offs + 1];
- UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
- COptimal &optimum = _optimum[len];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = 0;
- optimum.BackPrev = distance + kNumRepDistances;
- optimum.Prev1IsChar = false;
- }
- if (len == matchDistances[offs])
- {
- offs += 2;
- if (offs == numDistancePairs)
- break;
- }
- }
- }
-
- UInt32 cur = 0;
-
- while(true)
- {
- cur++;
- if(cur == lenEnd)
- {
- lenRes = Backward(backRes, cur);
- return S_OK;
- }
- UInt32 newLen, numDistancePairs;
- RINOK(ReadMatchDistances(newLen, numDistancePairs));
- if(newLen >= _numFastBytes)
- {
- _numDistancePairs = numDistancePairs;
- _longestMatchLength = newLen;
- _longestMatchWasFound = true;
- lenRes = Backward(backRes, cur);
- return S_OK;
- }
- position++;
- COptimal &curOptimum = _optimum[cur];
- UInt32 posPrev = curOptimum.PosPrev;
- CState state;
- if (curOptimum.Prev1IsChar)
- {
- posPrev--;
- if (curOptimum.Prev2)
- {
- state = _optimum[curOptimum.PosPrev2].State;
- if (curOptimum.BackPrev2 < kNumRepDistances)
- state.UpdateRep();
- else
- state.UpdateMatch();
- }
- else
- state = _optimum[posPrev].State;
- state.UpdateChar();
- }
- else
- state = _optimum[posPrev].State;
- if (posPrev == cur - 1)
- {
- if (curOptimum.IsShortRep())
- state.UpdateShortRep();
- else
- state.UpdateChar();
- }
- else
- {
- UInt32 pos;
- if (curOptimum.Prev1IsChar && curOptimum.Prev2)
- {
- posPrev = curOptimum.PosPrev2;
- pos = curOptimum.BackPrev2;
- state.UpdateRep();
- }
- else
- {
- pos = curOptimum.BackPrev;
- if (pos < kNumRepDistances)
- state.UpdateRep();
- else
- state.UpdateMatch();
- }
- const COptimal &prevOptimum = _optimum[posPrev];
- if (pos < kNumRepDistances)
- {
- reps[0] = prevOptimum.Backs[pos];
- UInt32 i;
- for(i = 1; i <= pos; i++)
- reps[i] = prevOptimum.Backs[i - 1];
- for(; i < kNumRepDistances; i++)
- reps[i] = prevOptimum.Backs[i];
- }
- else
- {
- reps[0] = (pos - kNumRepDistances);
- for(UInt32 i = 1; i < kNumRepDistances; i++)
- reps[i] = prevOptimum.Backs[i - 1];
- }
- }
- curOptimum.State = state;
- for(UInt32 i = 0; i < kNumRepDistances; i++)
- curOptimum.Backs[i] = reps[i];
- UInt32 curPrice = curOptimum.Price;
- const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
- const Byte currentByte = *data;
- const Byte matchByte = data[(size_t)0 - reps[0] - 1];
-
- UInt32 posState = (position & _posStateMask);
-
- UInt32 curAnd1Price = curPrice +
- _isMatch[state.Index][posState].GetPrice0() +
- _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte);
-
- COptimal &nextOptimum = _optimum[cur + 1];
-
- bool nextIsChar = false;
- if (curAnd1Price < nextOptimum.Price)
- {
- nextOptimum.Price = curAnd1Price;
- nextOptimum.PosPrev = cur;
- nextOptimum.MakeAsChar();
- nextIsChar = true;
- }
-
- UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
- UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
-
- if(matchByte == currentByte &&
- !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
- {
- UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
- if(shortRepPrice <= nextOptimum.Price)
- {
- nextOptimum.Price = shortRepPrice;
- nextOptimum.PosPrev = cur;
- nextOptimum.MakeAsShortRep();
- nextIsChar = true;
- }
- }
- /*
- if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
- continue;
- */
-
- UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1;
- numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull);
- UInt32 numAvailableBytes = numAvailableBytesFull;
-
- if (numAvailableBytes < 2)
- continue;
- if (numAvailableBytes > _numFastBytes)
- numAvailableBytes = _numFastBytes;
- if (!nextIsChar && matchByte != currentByte) // speed optimization
- {
- // try Literal + rep0
- UInt32 backOffset = reps[0] + 1;
- UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1);
- UInt32 temp;
- for (temp = 1; temp < limit &&
- data[temp] == data[(size_t)temp - backOffset]; temp++);
- UInt32 lenTest2 = temp - 1;
- if (lenTest2 >= 2)
- {
- CState state2 = state;
- state2.UpdateChar();
- UInt32 posStateNext = (position + 1) & _posStateMask;
- UInt32 nextRepMatchPrice = curAnd1Price +
- _isMatch[state2.Index][posStateNext].GetPrice1() +
- _isRep[state2.Index].GetPrice1();
- // for (; lenTest2 >= 2; lenTest2--)
- {
- UInt32 offset = cur + 1 + lenTest2;
- while(lenEnd < offset)
- _optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
- 0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = false;
- }
- }
- }
- }
-
- UInt32 startLen = 2; // speed optimization
- for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
- {
- // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
- UInt32 backOffset = reps[repIndex] + 1;
- if (data[0] != data[(size_t)0 - backOffset] ||
- data[1] != data[(size_t)1 - backOffset])
- continue;
- UInt32 lenTest;
- for (lenTest = 2; lenTest < numAvailableBytes &&
- data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++);
- while(lenEnd < cur + lenTest)
- _optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 lenTestTemp = lenTest;
- UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);
- do
- {
- UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState);
- COptimal &optimum = _optimum[cur + lenTest];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur;
- optimum.BackPrev = repIndex;
- optimum.Prev1IsChar = false;
- }
- }
- while(--lenTest >= 2);
- lenTest = lenTestTemp;
-
- if (repIndex == 0)
- startLen = lenTest + 1;
-
- // if (_maxMode)
- {
- UInt32 lenTest2 = lenTest + 1;
- UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
- for (; lenTest2 < limit &&
- data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);
- lenTest2 -= lenTest + 1;
- if (lenTest2 >= 2)
- {
- CState state2 = state;
- state2.UpdateRep();
- UInt32 posStateNext = (position + lenTest) & _posStateMask;
- UInt32 curAndLenCharPrice =
- price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) +
- _isMatch[state2.Index][posStateNext].GetPrice0() +
- _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice(
- true, data[(size_t)lenTest - backOffset], data[lenTest]);
- state2.UpdateChar();
- posStateNext = (position + lenTest + 1) & _posStateMask;
- UInt32 nextRepMatchPrice = curAndLenCharPrice +
- _isMatch[state2.Index][posStateNext].GetPrice1() +
- _isRep[state2.Index].GetPrice1();
-
- // for(; lenTest2 >= 2; lenTest2--)
- {
- UInt32 offset = cur + lenTest + 1 + lenTest2;
- while(lenEnd < offset)
- _optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
- 0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + lenTest + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = true;
- optimum.PosPrev2 = cur;
- optimum.BackPrev2 = repIndex;
- }
- }
- }
- }
- }
-
- // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
- if (newLen > numAvailableBytes)
- {
- newLen = numAvailableBytes;
- for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
- matchDistances[numDistancePairs] = newLen;
- numDistancePairs += 2;
- }
- if (newLen >= startLen)
- {
- UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
- while(lenEnd < cur + newLen)
- _optimum[++lenEnd].Price = kIfinityPrice;
-
- UInt32 offs = 0;
- while(startLen > matchDistances[offs])
- offs += 2;
- UInt32 curBack = matchDistances[offs + 1];
- UInt32 posSlot = GetPosSlot2(curBack);
- for(UInt32 lenTest = /*2*/ startLen; ; lenTest++)
- {
- UInt32 curAndLenPrice = normalMatchPrice;
- UInt32 lenToPosState = GetLenToPosState(lenTest);
- if (curBack < kNumFullDistances)
- curAndLenPrice += _distancesPrices[lenToPosState][curBack];
- else
- curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask];
-
- curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState);
-
- COptimal &optimum = _optimum[cur + lenTest];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur;
- optimum.BackPrev = curBack + kNumRepDistances;
- optimum.Prev1IsChar = false;
- }
-
- if (/*_maxMode && */lenTest == matchDistances[offs])
- {
- // Try Match + Literal + Rep0
- UInt32 backOffset = curBack + 1;
- UInt32 lenTest2 = lenTest + 1;
- UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes);
- for (; lenTest2 < limit &&
- data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++);
- lenTest2 -= lenTest + 1;
- if (lenTest2 >= 2)
- {
- CState state2 = state;
- state2.UpdateMatch();
- UInt32 posStateNext = (position + lenTest) & _posStateMask;
- UInt32 curAndLenCharPrice = curAndLenPrice +
- _isMatch[state2.Index][posStateNext].GetPrice0() +
- _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice(
- true, data[(size_t)lenTest - backOffset], data[lenTest]);
- state2.UpdateChar();
- posStateNext = (posStateNext + 1) & _posStateMask;
- UInt32 nextRepMatchPrice = curAndLenCharPrice +
- _isMatch[state2.Index][posStateNext].GetPrice1() +
- _isRep[state2.Index].GetPrice1();
-
- // for(; lenTest2 >= 2; lenTest2--)
- {
- UInt32 offset = cur + lenTest + 1 + lenTest2;
- while(lenEnd < offset)
- _optimum[++lenEnd].Price = kIfinityPrice;
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
- COptimal &optimum = _optimum[offset];
- if (curAndLenPrice < optimum.Price)
- {
- optimum.Price = curAndLenPrice;
- optimum.PosPrev = cur + lenTest + 1;
- optimum.BackPrev = 0;
- optimum.Prev1IsChar = true;
- optimum.Prev2 = true;
- optimum.PosPrev2 = cur;
- optimum.BackPrev2 = curBack + kNumRepDistances;
- }
- }
- }
- offs += 2;
- if (offs == numDistancePairs)
- break;
- curBack = matchDistances[offs + 1];
- if (curBack >= kNumFullDistances)
- posSlot = GetPosSlot2(curBack);
- }
- }
- }
- }
-}
-
-static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
-{
- return ((bigDist >> 7) > smallDist);
-}
-
-
-HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs)
-{
- lenRes = 0;
- RINOK(_matchFinder->GetMatches(_matchDistances));
- numDistancePairs = _matchDistances[0];
- if (numDistancePairs > 0)
- {
- lenRes = _matchDistances[1 + numDistancePairs - 2];
- if (lenRes == _numFastBytes)
- lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1],
- kMatchMaxLen - lenRes);
- }
- _additionalOffset++;
- return S_OK;
-}
-
-HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
-{
- UInt32 lenMain, numDistancePairs;
- if (!_longestMatchWasFound)
- {
- RINOK(ReadMatchDistances(lenMain, numDistancePairs));
- }
- else
- {
- lenMain = _longestMatchLength;
- numDistancePairs = _numDistancePairs;
- _longestMatchWasFound = false;
- }
-
- const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
- UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;
- if (numAvailableBytes > kMatchMaxLen)
- numAvailableBytes = kMatchMaxLen;
- if (numAvailableBytes < 2)
- {
- backRes = (UInt32)(-1);
- lenRes = 1;
- return S_OK;
- }
-
- UInt32 repLens[kNumRepDistances];
- UInt32 repMaxIndex = 0;
-
- for(UInt32 i = 0; i < kNumRepDistances; i++)
- {
- UInt32 backOffset = _repDistances[i] + 1;
- if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset])
- {
- repLens[i] = 0;
- continue;
- }
- UInt32 len;
- for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);
- if(len >= _numFastBytes)
- {
- backRes = i;
- lenRes = len;
- return MovePos(lenRes - 1);
- }
- repLens[i] = len;
- if (len > repLens[repMaxIndex])
- repMaxIndex = i;
- }
- UInt32 *matchDistances = _matchDistances + 1;
- if(lenMain >= _numFastBytes)
- {
- backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances;
- lenRes = lenMain;
- return MovePos(lenMain - 1);
- }
-
- UInt32 backMain = 0; // for GCC
- if (lenMain >= 2)
- {
- backMain = matchDistances[numDistancePairs - 1];
- while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
- {
- if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
- break;
- numDistancePairs -= 2;
- lenMain = matchDistances[numDistancePairs - 2];
- backMain = matchDistances[numDistancePairs - 1];
- }
- if (lenMain == 2 && backMain >= 0x80)
- lenMain = 1;
- }
-
- if (repLens[repMaxIndex] >= 2)
- {
- if (repLens[repMaxIndex] + 1 >= lenMain ||
- repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ||
- repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)))
- {
- backRes = repMaxIndex;
- lenRes = repLens[repMaxIndex];
- return MovePos(lenRes - 1);
- }
- }
-
- if (lenMain >= 2 && numAvailableBytes > 2)
- {
- RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs));
- if (_longestMatchLength >= 2)
- {
- UInt32 newDistance = matchDistances[_numDistancePairs - 1];
- if (_longestMatchLength >= lenMain && newDistance < backMain ||
- _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ||
- _longestMatchLength > lenMain + 1 ||
- _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain))
- {
- _longestMatchWasFound = true;
- backRes = UInt32(-1);
- lenRes = 1;
- return S_OK;
- }
- }
- data++;
- numAvailableBytes--;
- for(UInt32 i = 0; i < kNumRepDistances; i++)
- {
- UInt32 backOffset = _repDistances[i] + 1;
- if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset])
- {
- repLens[i] = 0;
- continue;
- }
- UInt32 len;
- for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++);
- if (len + 1 >= lenMain)
- {
- _longestMatchWasFound = true;
- backRes = UInt32(-1);
- lenRes = 1;
- return S_OK;
- }
- }
- backRes = backMain + kNumRepDistances;
- lenRes = lenMain;
- return MovePos(lenMain - 2);
- }
- backRes = UInt32(-1);
- lenRes = 1;
- return S_OK;
-}
-
-HRESULT CEncoder::Flush(UInt32 nowPos)
-{
- ReleaseMFStream();
- WriteEndMarker(nowPos & _posStateMask);
- _rangeEncoder.FlushData();
- return _rangeEncoder.FlushStream();
-}
-
-void CEncoder::WriteEndMarker(UInt32 posState)
-{
- // This function for writing End Mark for stream version of LZMA.
- // In current version this feature is not used.
- if (!_writeEndMark)
- return;
-
- _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
- _isRep[_state.Index].Encode(&_rangeEncoder, 0);
- _state.UpdateMatch();
- UInt32 len = kMatchMinLen; // kMatchMaxLen;
- _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
- UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
- UInt32 lenToPosState = GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
- UInt32 footerBits = 30;
- UInt32 posReduced = (UInt32(1) << footerBits) - 1;
- _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
- _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
-}
-
-HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress)
-{
- _needReleaseMFStream = false;
- CCoderReleaser coderReleaser(this);
- RINOK(SetStreams(inStream, outStream, inSize, outSize));
- while(true)
- {
- UInt64 processedInSize;
- UInt64 processedOutSize;
- Int32 finished;
- RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
- if (finished != 0)
- return S_OK;
- if (progress != 0)
- {
- RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
- }
- }
-}
-
-HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize)
-{
- _inStream = inStream;
- _finished = false;
- RINOK(Create());
- RINOK(SetOutStream(outStream));
- RINOK(Init());
-
- // CCoderReleaser releaser(this);
-
- /*
- if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush();
- */
-
- if (!_fastMode)
- {
- FillDistancesPrices();
- FillAlignPrices();
- }
-
- _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
- _lenEncoder.UpdateTables(1 << _posStateBits);
- _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen);
- _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
-
- nowPos64 = 0;
- return S_OK;
-}
-
-HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
-{
- if (_inStream != 0)
- {
- RINOK(_matchFinder->SetStream(_inStream));
- RINOK(_matchFinder->Init());
- _needReleaseMFStream = true;
- _inStream = 0;
- }
-
-
- *finished = 1;
- if (_finished)
- return S_OK;
- _finished = true;
-
- if (nowPos64 == 0)
- {
- if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush(UInt32(nowPos64));
- UInt32 len, numDistancePairs;
- RINOK(ReadMatchDistances(len, numDistancePairs));
- UInt32 posState = UInt32(nowPos64) & _posStateMask;
- _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
- _state.UpdateChar();
- Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
- _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
- _previousByte = curByte;
- _additionalOffset--;
- nowPos64++;
- }
-
- UInt32 nowPos32 = (UInt32)nowPos64;
- UInt32 progressPosValuePrev = nowPos32;
-
- if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush(nowPos32);
-
- while(true)
- {
- #ifdef _NO_EXCEPTIONS
- if (_rangeEncoder.Stream.ErrorCode != S_OK)
- return _rangeEncoder.Stream.ErrorCode;
- #endif
- UInt32 pos, len;
- HRESULT result;
- if (_fastMode)
- result = GetOptimumFast(nowPos32, pos, len);
- else
- result = GetOptimum(nowPos32, pos, len);
- RINOK(result);
-
- UInt32 posState = nowPos32 & _posStateMask;
- if(len == 1 && pos == 0xFFFFFFFF)
- {
- _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
- Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
- CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte);
- if(_state.IsCharState())
- subCoder->Encode(&_rangeEncoder, curByte);
- else
- {
- Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
- subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
- }
- _state.UpdateChar();
- _previousByte = curByte;
- }
- else
- {
- _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
- if(pos < kNumRepDistances)
- {
- _isRep[_state.Index].Encode(&_rangeEncoder, 1);
- if(pos == 0)
- {
- _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
- _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1));
- }
- else
- {
- UInt32 distance = _repDistances[pos];
- _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
- if (pos == 1)
- _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
- else
- {
- _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
- _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
- if (pos == 3)
- _repDistances[3] = _repDistances[2];
- _repDistances[2] = _repDistances[1];
- }
- _repDistances[1] = _repDistances[0];
- _repDistances[0] = distance;
- }
- if (len == 1)
- _state.UpdateShortRep();
- else
- {
- _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
- _state.UpdateRep();
- }
- }
- else
- {
- _isRep[_state.Index].Encode(&_rangeEncoder, 0);
- _state.UpdateMatch();
- _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode);
- pos -= kNumRepDistances;
- UInt32 posSlot = GetPosSlot(pos);
- _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot);
-
- if (posSlot >= kStartPosModelIndex)
- {
- UInt32 footerBits = ((posSlot >> 1) - 1);
- UInt32 base = ((2 | (posSlot & 1)) << footerBits);
- UInt32 posReduced = pos - base;
-
- if (posSlot < kEndPosModelIndex)
- NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,
- &_rangeEncoder, footerBits, posReduced);
- else
- {
- _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
- _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
- _alignPriceCount++;
- }
- }
- _repDistances[3] = _repDistances[2];
- _repDistances[2] = _repDistances[1];
- _repDistances[1] = _repDistances[0];
- _repDistances[0] = pos;
- _matchPriceCount++;
- }
- _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
- }
- _additionalOffset -= len;
- nowPos32 += len;
- if (_additionalOffset == 0)
- {
- if (!_fastMode)
- {
- if (_matchPriceCount >= (1 << 7))
- FillDistancesPrices();
- if (_alignPriceCount >= kAlignTableSize)
- FillAlignPrices();
- }
- if (_matchFinder->GetNumAvailableBytes() == 0)
- return Flush(nowPos32);
- if (nowPos32 - progressPosValuePrev >= (1 << 14))
- {
- nowPos64 += nowPos32 - progressPosValuePrev;
- *inSize = nowPos64;
- *outSize = _rangeEncoder.GetProcessedSize();
- _finished = false;
- *finished = 0;
- return S_OK;
- }
- }
- }
-}
-
-STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
- ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress)
-{
- #ifndef _NO_EXCEPTIONS
- try
- {
- #endif
- return CodeReal(inStream, outStream, inSize, outSize, progress);
- #ifndef _NO_EXCEPTIONS
- }
- catch(const COutBufferException &e) { return e.ErrorCode; }
- catch(...) { return E_FAIL; }
- #endif
-}
-
-void CEncoder::FillDistancesPrices()
-{
- UInt32 tempPrices[kNumFullDistances];
- for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++)
- {
- UInt32 posSlot = GetPosSlot(i);
- UInt32 footerBits = ((posSlot >> 1) - 1);
- UInt32 base = ((2 | (posSlot & 1)) << footerBits);
- tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
- base - posSlot - 1, footerBits, i - base);
- }
-
- for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
- {
- UInt32 posSlot;
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState];
- UInt32 *posSlotPrices = _posSlotPrices[lenToPosState];
- for (posSlot = 0; posSlot < _distTableSize; posSlot++)
- posSlotPrices[posSlot] = encoder.GetPrice(posSlot);
- for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
- posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
-
- UInt32 *distancesPrices = _distancesPrices[lenToPosState];
- UInt32 i;
- for (i = 0; i < kStartPosModelIndex; i++)
- distancesPrices[i] = posSlotPrices[i];
- for (; i < kNumFullDistances; i++)
- distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i];
- }
- _matchPriceCount = 0;
-}
-
-void CEncoder::FillAlignPrices()
-{
- for (UInt32 i = 0; i < kAlignTableSize; i++)
- _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
- _alignPriceCount = 0;
-}
-
-}}
+/* + * LZMAEncoder.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" + +#include "LZMAEncoder.h" + +// for minimal compressing code size define these: +// #define COMPRESS_MF_BT +// #define COMPRESS_MF_BT4 + +#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC) +#define COMPRESS_MF_BT +#define COMPRESS_MF_HC +#endif + +#ifdef COMPRESS_MF_BT +#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) +#define COMPRESS_MF_BT2 +#define COMPRESS_MF_BT3 +#define COMPRESS_MF_BT4 +#endif +#ifdef COMPRESS_MF_BT2 +#include "../LZ/BinTree/BinTree2.h" +#endif +#ifdef COMPRESS_MF_BT3 +#include "../LZ/BinTree/BinTree3.h" +#endif +#ifdef COMPRESS_MF_BT4 +#include "../LZ/BinTree/BinTree4.h" +#endif +#endif + +#ifdef COMPRESS_MF_HC +#include "../LZ/HashChain/HC4.h" +#endif + +#ifdef COMPRESS_MF_MT +#include "../LZ/MT/MT.h" +#endif + +namespace NCompress { +namespace NLZMA { + +const int kDefaultDictionaryLogSize = 22; +const UInt32 kNumFastBytesDefault = 0x20; + +enum +{ + kBT2, + kBT3, + kBT4, + kHC4 +}; + +/*static const wchar_t *kMatchFinderIDs[] = +{ + L"BT2", + L"BT3", + L"BT4", + L"HC4" +};*/ + +Byte g_FastPos[1 << 11]; + +class CFastPosInit +{ +public: + CFastPosInit() { Init(); } + void Init() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } +} g_FastPosInit; + + +void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) +{ + UInt32 context = 1; + int i = 8; + do + { + i--; + UInt32 bit = (symbol >> i) & 1; + _encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + while(i != 0); +} + +void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, + Byte matchByte, Byte symbol) +{ + UInt32 context = 1; + int i = 8; + do + { + i--; + UInt32 bit = (symbol >> i) & 1; + UInt32 matchBit = (matchByte >> i) & 1; + _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + while(i != 0) + { + i--; + UInt32 bit = (symbol >> i) & 1; + _encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + break; + } + } + while(i != 0); +} + +UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const +{ + UInt32 price = 0; + UInt32 context = 1; + int i = 8; + if (matchMode) + { + do + { + i--; + UInt32 matchBit = (matchByte >> i) & 1; + UInt32 bit = (symbol >> i) & 1; + price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + break; + } + while (i != 0); + } + while(i != 0) + { + i--; + UInt32 bit = (symbol >> i) & 1; + price += _encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; +}; + + +namespace NLength { + +void CEncoder::Init(UInt32 numPosStates) +{ + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); +} + +void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) +{ + if(symbol < kNumLowSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice.Encode(rangeEncoder, 1); + if(symbol < kNumLowSymbols + kNumMidSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); + } + } +} + +void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const +{ + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < kNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < kNumLowSymbols + kNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); + } + for (; i < numSymbols; i++) + prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); +} + +} +CEncoder::CEncoder(): + _numFastBytes(kNumFastBytesDefault), + _distTableSize(kDefaultDictionaryLogSize * 2), + _posStateBits(2), + _posStateMask(4 - 1), + _numLiteralPosStateBits(0), + _numLiteralContextBits(3), + _dictionarySize(1 << kDefaultDictionaryLogSize), + _dictionarySizePrev(UInt32(-1)), + _numFastBytesPrev(UInt32(-1)), + _matchFinderCycles(0), + _matchFinderIndex(kBT4), + #ifdef COMPRESS_MF_MT + _multiThread(false), + #endif + _writeEndMark(false), + setMfPasses(0) +{ + // _maxMode = false; + _fastMode = false; +} + +HRESULT CEncoder::Create() +{ + if (!_rangeEncoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_matchFinder) + { + switch(_matchFinderIndex) + { + #ifdef COMPRESS_MF_BT + #ifdef COMPRESS_MF_BT2 + case kBT2: + { + NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #ifdef COMPRESS_MF_BT3 + case kBT3: + { + NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #ifdef COMPRESS_MF_BT4 + case kBT4: + { + NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #endif + + #ifdef COMPRESS_MF_HC + case kHC4: + { + NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + } + if (_matchFinder == 0) + return E_OUTOFMEMORY; + + #ifdef COMPRESS_MF_MT + if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4))) + { + CMatchFinderMT *mfSpec = new CMatchFinderMT; + if (mfSpec == 0) + return E_OUTOFMEMORY; + CMyComPtr<IMatchFinder> mf = mfSpec; + RINOK(mfSpec->SetMatchFinder(_matchFinder)); + _matchFinder.Release(); + _matchFinder = mf; + } + #endif + } + + if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) + return E_OUTOFMEMORY; + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return S_OK; + RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes + if (_matchFinderCycles != 0 && setMfPasses != 0) + setMfPasses->SetNumPasses(_matchFinderCycles); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + return S_OK; +} + +/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) +{ + while (true) + { + wchar_t c = *testString; + if (c >= 'a' && c <= 'z') + c -= 0x20; + if (*base != c) + return false; + if (c == 0) + return true; + base++; + testString++; + } +} + +static int FindMatchFinder(const wchar_t *s) +{ + for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) + if (AreStringsEqual(kMatchFinderIDs[m], s)) + return m; + return -1; +}*/ + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) +{ + for (UInt32 i = 0; i < numProperties; i++) + { + const PROPVARIANT &prop = properties[i]; + switch(propIDs[i]) + { + case NCoderPropID::kNumFastBytes: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 numFastBytes = prop.ulVal; + if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) + return E_INVALIDARG; + _numFastBytes = numFastBytes; + break; + } + case NCoderPropID::kMatchFinderCycles: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + _matchFinderCycles = prop.ulVal; + break; + } + case NCoderPropID::kAlgorithm: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 maximize = prop.ulVal; + _fastMode = (maximize == 0); + // _maxMode = (maximize >= 2); + break; + } + case NCoderPropID::kMatchFinder: + { + return E_NOTIMPL; + /*if (prop.vt != VT_BSTR) + return E_INVALIDARG; + int matchFinderIndexPrev = _matchFinderIndex; + int m = FindMatchFinder(prop.bstrVal); + if (m < 0) + return E_INVALIDARG; + _matchFinderIndex = m; + if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + } + break;*/ + } + #ifdef COMPRESS_MF_MT + case NCoderPropID::kMultiThread: + { + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + bool newMultiThread = (prop.boolVal == VARIANT_TRUE); + if (newMultiThread != _multiThread) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + break; + } + case NCoderPropID::kNumThreads: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + bool newMultiThread = (prop.ulVal > 1); + if (newMultiThread != _multiThread) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + break; + } + #endif + case NCoderPropID::kDictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 dictionarySize = prop.ulVal; + if (dictionarySize < UInt32(1 << kDicLogSizeMin) || + dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) + return E_INVALIDARG; + _dictionarySize = dictionarySize; + UInt32 dicLogSize; + for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= (UInt32(1) << dicLogSize)) + break; + _distTableSize = dicLogSize * 2; + break; + } + case NCoderPropID::kPosStateBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) + return E_INVALIDARG; + _posStateBits = value; + _posStateMask = (1 << _posStateBits) - 1; + break; + } + case NCoderPropID::kLitPosBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) + return E_INVALIDARG; + _numLiteralPosStateBits = value; + break; + } + case NCoderPropID::kLitContextBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)kNumLitContextBitsMax) + return E_INVALIDARG; + _numLiteralContextBits = value; + break; + } + case NCoderPropID::kEndMarker: + { + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); + break; + } + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + const UInt32 kPropSize = 5; + Byte properties[kPropSize]; + properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; + for (int i = 0; i < 4; i++) + properties[1 + i] = Byte(_dictionarySize >> (8 * i)); + return WriteStream(outStream, properties, kPropSize, NULL); +} + +STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) +{ + _rangeEncoder.SetStream(outStream); + return S_OK; +} + +STDMETHODIMP CEncoder::ReleaseOutStream() +{ + _rangeEncoder.ReleaseStream(); + return S_OK; +} + +HRESULT CEncoder::Init() +{ + CBaseState::Init(); + + // RINOK(_matchFinder->Init(inStream)); + _rangeEncoder.Init(); + + for(int i = 0; i < kNumStates; i++) + { + for (UInt32 j = 0; j <= _posStateMask; j++) + { + _isMatch[i][j].Init(); + _isRep0Long[i][j].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + + _literalEncoder.Init(); + + { + for(UInt32 i = 0; i < kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + } + { + for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + _posEncoders[i].Init(); + } + + _lenEncoder.Init(1 << _posStateBits); + _repMatchLenEncoder.Init(1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + + return S_OK; +} + +HRESULT CEncoder::MovePos(UInt32 num) +{ + if (num == 0) + return S_OK; + _additionalOffset += num; + return _matchFinder->Skip(num); +} + +UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) +{ + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while(cur != 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; +} + +/* +Out: + (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal +*/ + +HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) +{ + if(_optimumEndIndex != _optimumCurrentIndex) + { + const COptimal &optimum = _optimum[_optimumCurrentIndex]; + lenRes = optimum.PosPrev - _optimumCurrentIndex; + backRes = optimum.BackPrev; + _optimumCurrentIndex = optimum.PosPrev; + return S_OK; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; + + UInt32 reps[kNumRepDistances]; + UInt32 repLens[kNumRepDistances]; + UInt32 repMaxIndex = 0; + UInt32 i; + for(i = 0; i < kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + UInt32 backOffset = reps[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 lenTest; + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if(repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + return MovePos(lenRes - 1); + } + + UInt32 *matchDistances = _matchDistances + 1; + if(lenMain >= _numFastBytes) + { + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 1); + } + Byte currentByte = *data; + Byte matchByte = data[(size_t)0 - reps[0] - 1]; + + if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)-1; + lenRes = 1; + return S_OK; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if(matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if(shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + lenRes = 1; + return S_OK; + } + + _optimum[1].PosPrev = 0; + for (i = 0; i < kNumRepDistances; i++) + _optimum[0].Backs[i] = reps[i]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for(i = 0; i < kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + COptimal &optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while(--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > matchDistances[offs]) + offs += 2; + for(; ; len++) + { + UInt32 distance = matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + COptimal &optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while(true) + { + cur++; + if(cur == lenEnd) + { + lenRes = Backward(backRes, cur); + return S_OK; + } + UInt32 newLen, numDistancePairs; + RINOK(ReadMatchDistances(newLen, numDistancePairs)); + if(newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + lenRes = Backward(backRes, cur); + return S_OK; + } + position++; + COptimal &curOptimum = _optimum[cur]; + UInt32 posPrev = curOptimum.PosPrev; + CState state; + if (curOptimum.Prev1IsChar) + { + posPrev--; + if (curOptimum.Prev2) + { + state = _optimum[curOptimum.PosPrev2].State; + if (curOptimum.BackPrev2 < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (curOptimum.IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (curOptimum.Prev1IsChar && curOptimum.Prev2) + { + posPrev = curOptimum.PosPrev2; + pos = curOptimum.BackPrev2; + state.UpdateRep(); + } + else + { + pos = curOptimum.BackPrev; + if (pos < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + const COptimal &prevOptimum = _optimum[posPrev]; + if (pos < kNumRepDistances) + { + reps[0] = prevOptimum.Backs[pos]; + UInt32 i; + for(i = 1; i <= pos; i++) + reps[i] = prevOptimum.Backs[i - 1]; + for(; i < kNumRepDistances; i++) + reps[i] = prevOptimum.Backs[i]; + } + else + { + reps[0] = (pos - kNumRepDistances); + for(UInt32 i = 1; i < kNumRepDistances; i++) + reps[i] = prevOptimum.Backs[i - 1]; + } + } + curOptimum.State = state; + for(UInt32 i = 0; i < kNumRepDistances; i++) + curOptimum.Backs[i] = reps[i]; + UInt32 curPrice = curOptimum.Price; + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + const Byte currentByte = *data; + const Byte matchByte = data[(size_t)0 - reps[0] - 1]; + + UInt32 posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte); + + COptimal &nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if(matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if(shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + /* + if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? + continue; + */ + + UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; + numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); + UInt32 numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) // speed optimization + { + // try Literal + rep0 + UInt32 backOffset = reps[0] + 1; + UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); + UInt32 temp; + for (temp = 1; temp < limit && + data[temp] == data[(size_t)temp - backOffset]; temp++); + UInt32 lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + // for (; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) + { + // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; + UInt32 backOffset = reps[repIndex] + 1; + if (data[0] != data[(size_t)0 - backOffset] || + data[1] != data[(size_t)1 - backOffset]) + continue; + UInt32 lenTest; + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + while(lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 lenTestTemp = lenTest; + UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( + true, data[(size_t)lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); + matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while(lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while(startLen > matchDistances[offs]) + offs += 2; + UInt32 curBack = matchDistances[offs + 1]; + UInt32 posSlot = GetPosSlot2(curBack); + for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice; + UInt32 lenToPosState = GetLenToPosState(lenTest); + if (curBack < kNumFullDistances) + curAndLenPrice += _distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; + + curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); + + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (/*_maxMode && */lenTest == matchDistances[offs]) + { + // Try Match + Literal + Rep0 + UInt32 backOffset = curBack + 1; + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( + true, data[(size_t)lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (posStateNext + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + curBack = matchDistances[offs + 1]; + if (curBack >= kNumFullDistances) + posSlot = GetPosSlot2(curBack); + } + } + } + } +} + +static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) +{ + return ((bigDist >> 7) > smallDist); +} + + +HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs) +{ + lenRes = 0; + RINOK(_matchFinder->GetMatches(_matchDistances)); + numDistancePairs = _matchDistances[0]; + if (numDistancePairs > 0) + { + lenRes = _matchDistances[1 + numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1], + kMatchMaxLen - lenRes); + } + _additionalOffset++; + return S_OK; +} + +HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) +{ + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + + UInt32 repLens[kNumRepDistances]; + UInt32 repMaxIndex = 0; + + for(UInt32 i = 0; i < kNumRepDistances; i++) + { + UInt32 backOffset = _repDistances[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if(len >= _numFastBytes) + { + backRes = i; + lenRes = len; + return MovePos(lenRes - 1); + } + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + } + UInt32 *matchDistances = _matchDistances + 1; + if(lenMain >= _numFastBytes) + { + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 1); + } + + UInt32 backMain = 0; // for GCC + if (lenMain >= 2) + { + backMain = matchDistances[numDistancePairs - 1]; + while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) + { + if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) + break; + numDistancePairs -= 2; + lenMain = matchDistances[numDistancePairs - 2]; + backMain = matchDistances[numDistancePairs - 1]; + } + if (lenMain == 2 && backMain >= 0x80) + lenMain = 1; + } + + if (repLens[repMaxIndex] >= 2) + { + if (repLens[repMaxIndex] + 1 >= lenMain || + repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) || + repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))) + { + backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + return MovePos(lenRes - 1); + } + } + + if (lenMain >= 2 && numAvailableBytes > 2) + { + RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs)); + if (_longestMatchLength >= 2) + { + UInt32 newDistance = matchDistances[_numDistancePairs - 1]; + if (_longestMatchLength >= lenMain && newDistance < backMain || + _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) || + _longestMatchLength > lenMain + 1 || + _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)) + { + _longestMatchWasFound = true; + backRes = UInt32(-1); + lenRes = 1; + return S_OK; + } + } + data++; + numAvailableBytes--; + for(UInt32 i = 0; i < kNumRepDistances; i++) + { + UInt32 backOffset = _repDistances[i] + 1; + if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if (len + 1 >= lenMain) + { + _longestMatchWasFound = true; + backRes = UInt32(-1); + lenRes = 1; + return S_OK; + } + } + backRes = backMain + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 2); + } + backRes = UInt32(-1); + lenRes = 1; + return S_OK; +} + +HRESULT CEncoder::Flush(UInt32 nowPos) +{ + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); +} + +void CEncoder::WriteEndMarker(UInt32 posState) +{ + // This function for writing End Mark for stream version of LZMA. + // In current version this feature is not used. + if (!_writeEndMark) + return; + + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); + _isRep[_state.Index].Encode(&_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = kMatchMinLen; // kMatchMaxLen; + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + UInt32 posSlot = (1 << kNumPosSlotBits) - 1; + UInt32 lenToPosState = GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); + UInt32 footerBits = 30; + UInt32 posReduced = (UInt32(1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); +} + +HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + _needReleaseMFStream = false; + CCoderReleaser coderReleaser(this); + RINOK(SetStreams(inStream, outStream, inSize, outSize)); + while(true) + { + UInt64 processedInSize; + UInt64 processedOutSize; + Int32 finished; + RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); + if (finished != 0) + return S_OK; + if (progress != 0) + { + RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); + } + } +} + +HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize) +{ + _inStream = inStream; + _finished = false; + RINOK(Create()); + RINOK(SetOutStream(outStream)); + RINOK(Init()); + + // CCoderReleaser releaser(this); + + /* + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(); + */ + + if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); + _lenEncoder.UpdateTables(1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); + _repMatchLenEncoder.UpdateTables(1 << _posStateBits); + + nowPos64 = 0; + return S_OK; +} + +HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) +{ + if (_inStream != 0) + { + RINOK(_matchFinder->SetStream(_inStream)); + RINOK(_matchFinder->Init()); + _needReleaseMFStream = true; + _inStream = 0; + } + + + *finished = 1; + if (_finished) + return S_OK; + _finished = true; + + if (nowPos64 == 0) + { + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(UInt32(nowPos64)); + UInt32 len, numDistancePairs; + RINOK(ReadMatchDistances(len, numDistancePairs)); + UInt32 posState = UInt32(nowPos64) & _posStateMask; + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + + UInt32 nowPos32 = (UInt32)nowPos64; + UInt32 progressPosValuePrev = nowPos32; + + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(nowPos32); + + while(true) + { + #ifdef _NO_EXCEPTIONS + if (_rangeEncoder.Stream.ErrorCode != S_OK) + return _rangeEncoder.Stream.ErrorCode; + #endif + UInt32 pos, len; + HRESULT result; + if (_fastMode) + result = GetOptimumFast(nowPos32, pos, len); + else + result = GetOptimum(nowPos32, pos, len); + RINOK(result); + + UInt32 posState = nowPos32 & _posStateMask; + if(len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); + Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); + if(_state.IsCharState()) + subCoder->Encode(&_rangeEncoder, curByte); + else + { + Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); + subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); + } + _state.UpdateChar(); + _previousByte = curByte; + } + else + { + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); + if(pos < kNumRepDistances) + { + _isRep[_state.Index].Encode(&_rangeEncoder, 1); + if(pos == 0) + { + _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); + _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = _repDistances[pos]; + _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); + if (pos == 3) + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; + } + _repDistances[1] = _repDistances[0]; + _repDistances[0] = distance; + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + _state.UpdateRep(); + } + } + else + { + _isRep[_state.Index].Encode(&_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + pos -= kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, + &_rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); + _alignPriceCount++; + } + } + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; + _repDistances[1] = _repDistances[0]; + _repDistances[0] = pos; + _matchPriceCount++; + } + _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); + } + _additionalOffset -= len; + nowPos32 += len; + if (_additionalOffset == 0) + { + if (!_fastMode) + { + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= kAlignTableSize) + FillAlignPrices(); + } + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(nowPos32); + if (nowPos32 - progressPosValuePrev >= (1 << 14)) + { + nowPos64 += nowPos32 - progressPosValuePrev; + *inSize = nowPos64; + *outSize = _rangeEncoder.GetProcessedSize(); + _finished = false; + *finished = 0; + return S_OK; + } + } + } +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + #ifndef _NO_EXCEPTIONS + try + { + #endif + return CodeReal(inStream, outStream, inSize, outSize, progress); + #ifndef _NO_EXCEPTIONS + } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } + #endif +} + +void CEncoder::FillDistancesPrices() +{ + UInt32 tempPrices[kNumFullDistances]; + for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + + base - posSlot - 1, footerBits, i - base); + } + + for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> &encoder = _posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] = encoder.GetPrice(posSlot); + for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); + + UInt32 *distancesPrices = _distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; +} + +void CEncoder::FillAlignPrices() +{ + for (UInt32 i = 0; i < kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; +} + +}} diff --git a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h index 5fe8d4c..41c7118 100755 --- a/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h +++ b/Source/7zip/7zip/Compress/LZMA/LZMAEncoder.h @@ -1,426 +1,426 @@ -/*
- * LZMAEncoder.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __LZMA_ENCODER_H
-#define __LZMA_ENCODER_H
-
-#include "../../../Common/MyCom.h"
-#include "../../../Common/Alloc.h"
-#include "../../ICoder.h"
-#include "../LZ/IMatchFinder.h"
-#include "../RangeCoder/RangeCoderBitTree.h"
-
-#include "LZMA.h"
-
-namespace NCompress {
-namespace NLZMA {
-
-typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;
-
-class CBaseState
-{
-protected:
- CState _state;
- Byte _previousByte;
- UInt32 _repDistances[kNumRepDistances];
- void Init()
- {
- _state.Init();
- _previousByte = 0;
- for(UInt32 i = 0 ; i < kNumRepDistances; i++)
- _repDistances[i] = 0;
- }
-};
-
-struct COptimal
-{
- CState State;
-
- bool Prev1IsChar;
- bool Prev2;
-
- UInt32 PosPrev2;
- UInt32 BackPrev2;
-
- UInt32 Price;
- UInt32 PosPrev; // posNext;
- UInt32 BackPrev;
- UInt32 Backs[kNumRepDistances];
- void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }
- void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
- bool IsShortRep() { return (BackPrev == 0); }
-};
-
-
-extern Byte g_FastPos[1 << 11];
-inline UInt32 GetPosSlot(UInt32 pos)
-{
- if (pos < (1 << 11))
- return g_FastPos[pos];
- if (pos < (1 << 21))
- return g_FastPos[pos >> 10] + 20;
- return g_FastPos[pos >> 20] + 40;
-}
-
-inline UInt32 GetPosSlot2(UInt32 pos)
-{
- if (pos < (1 << 17))
- return g_FastPos[pos >> 6] + 12;
- if (pos < (1 << 27))
- return g_FastPos[pos >> 16] + 32;
- return g_FastPos[pos >> 26] + 52;
-}
-
-const UInt32 kIfinityPrice = 0xFFFFFFF;
-
-const UInt32 kNumOpts = 1 << 12;
-
-
-class CLiteralEncoder2
-{
- CMyBitEncoder _encoders[0x300];
-public:
- void Init()
- {
- for (int i = 0; i < 0x300; i++)
- _encoders[i].Init();
- }
- void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);
- void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);
- UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;
-};
-
-class CLiteralEncoder
-{
- CLiteralEncoder2 *_coders;
- int _numPrevBits;
- int _numPosBits;
- UInt32 _posMask;
-public:
- CLiteralEncoder(): _coders(0) {}
- ~CLiteralEncoder() { Free(); }
- void Free()
- {
- MyFree(_coders);
- _coders = 0;
- }
- bool Create(int numPosBits, int numPrevBits)
- {
- if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))
- {
- Free();
- UInt32 numStates = 1 << (numPosBits + numPrevBits);
- _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));
- }
- _numPosBits = numPosBits;
- _posMask = (1 << numPosBits) - 1;
- _numPrevBits = numPrevBits;
- return (_coders != 0);
- }
- void Init()
- {
- UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
- for (UInt32 i = 0; i < numStates; i++)
- _coders[i].Init();
- }
- CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
- { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }
-};
-
-namespace NLength {
-
-class CEncoder
-{
- CMyBitEncoder _choice;
- CMyBitEncoder _choice2;
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
-public:
- void Init(UInt32 numPosStates);
- void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
- void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;
-};
-
-const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
-
-class CPriceTableEncoder: public CEncoder
-{
- UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];
- UInt32 _tableSize;
- UInt32 _counters[kNumPosStatesEncodingMax];
-public:
- void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
- UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }
- void UpdateTable(UInt32 posState)
- {
- SetPrices(posState, _tableSize, _prices[posState]);
- _counters[posState] = _tableSize;
- }
- void UpdateTables(UInt32 numPosStates)
- {
- for (UInt32 posState = 0; posState < numPosStates; posState++)
- UpdateTable(posState);
- }
- void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)
- {
- CEncoder::Encode(rangeEncoder, symbol, posState);
- if (updatePrice)
- if (--_counters[posState] == 0)
- UpdateTable(posState);
- }
-};
-
-}
-
-class CEncoder :
- public ICompressCoder,
- public ICompressSetOutStream,
- public ICompressSetCoderProperties,
- public ICompressWriteCoderProperties,
- public CBaseState,
- public CMyUnknownImp
-{
- COptimal _optimum[kNumOpts];
- CMyComPtr<IMatchFinder> _matchFinder; // test it
- NRangeCoder::CEncoder _rangeEncoder;
-
- CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
- CMyBitEncoder _isRep[kNumStates];
- CMyBitEncoder _isRepG0[kNumStates];
- CMyBitEncoder _isRepG1[kNumStates];
- CMyBitEncoder _isRepG2[kNumStates];
- CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];
-
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
-
- CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
- NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;
-
- NLength::CPriceTableEncoder _lenEncoder;
- NLength::CPriceTableEncoder _repMatchLenEncoder;
-
- CLiteralEncoder _literalEncoder;
-
- UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];
-
- bool _fastMode;
- // bool _maxMode;
- UInt32 _numFastBytes;
- UInt32 _longestMatchLength;
- UInt32 _numDistancePairs;
-
- UInt32 _additionalOffset;
-
- UInt32 _optimumEndIndex;
- UInt32 _optimumCurrentIndex;
-
- bool _longestMatchWasFound;
-
- UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
-
- UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];
-
- UInt32 _alignPrices[kAlignTableSize];
- UInt32 _alignPriceCount;
-
- UInt32 _distTableSize;
-
- UInt32 _posStateBits;
- UInt32 _posStateMask;
- UInt32 _numLiteralPosStateBits;
- UInt32 _numLiteralContextBits;
-
- UInt32 _dictionarySize;
-
- UInt32 _dictionarySizePrev;
- UInt32 _numFastBytesPrev;
-
- UInt32 _matchPriceCount;
- UInt64 nowPos64;
- bool _finished;
- ISequentialInStream *_inStream;
-
- UInt32 _matchFinderCycles;
- int _matchFinderIndex;
- #ifdef COMPRESS_MF_MT
- bool _multiThread;
- #endif
-
- bool _writeEndMark;
-
- bool _needReleaseMFStream;
-
- IMatchFinderSetNumPasses *setMfPasses;
-
- void ReleaseMatchFinder()
- {
- setMfPasses = 0;
- _matchFinder.Release();
- }
-
- HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);
-
- HRESULT MovePos(UInt32 num);
- UInt32 GetRepLen1Price(CState state, UInt32 posState) const
- {
- return _isRepG0[state.Index].GetPrice0() +
- _isRep0Long[state.Index][posState].GetPrice0();
- }
-
- UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const
- {
- UInt32 price;
- if(repIndex == 0)
- {
- price = _isRepG0[state.Index].GetPrice0();
- price += _isRep0Long[state.Index][posState].GetPrice1();
- }
- else
- {
- price = _isRepG0[state.Index].GetPrice1();
- if (repIndex == 1)
- price += _isRepG1[state.Index].GetPrice0();
- else
- {
- price += _isRepG1[state.Index].GetPrice1();
- price += _isRepG2[state.Index].GetPrice(repIndex - 2);
- }
- }
- return price;
- }
- UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
- {
- return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +
- GetPureRepPrice(repIndex, state, posState);
- }
- /*
- UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
- {
- if (pos >= kNumFullDistances)
- return kIfinityPrice;
- return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);
- }
- UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const
- {
- UInt32 price;
- UInt32 lenToPosState = GetLenToPosState(len);
- if (pos < kNumFullDistances)
- price = _distancesPrices[lenToPosState][pos];
- else
- price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
- _alignPrices[pos & kAlignMask];
- return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
- }
- */
- UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
- {
- UInt32 price;
- UInt32 lenToPosState = GetLenToPosState(len);
- if (pos < kNumFullDistances)
- price = _distancesPrices[lenToPosState][pos];
- else
- price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
- _alignPrices[pos & kAlignMask];
- return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
- }
-
- UInt32 Backward(UInt32 &backRes, UInt32 cur);
- HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
- HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
-
- void FillDistancesPrices();
- void FillAlignPrices();
-
- void ReleaseMFStream()
- {
- if (_matchFinder && _needReleaseMFStream)
- {
- _matchFinder->ReleaseStream();
- _needReleaseMFStream = false;
- }
- }
-
- void ReleaseStreams()
- {
- ReleaseMFStream();
- ReleaseOutStream();
- }
-
- HRESULT Flush(UInt32 nowPos);
- class CCoderReleaser
- {
- CEncoder *_coder;
- public:
- CCoderReleaser(CEncoder *coder): _coder(coder) {}
- ~CCoderReleaser()
- {
- _coder->ReleaseStreams();
- }
- };
- friend class CCoderReleaser;
-
- void WriteEndMarker(UInt32 posState);
-
-public:
- CEncoder();
- void SetWriteEndMarkerMode(bool writeEndMarker)
- { _writeEndMark= writeEndMarker; }
-
- HRESULT Create();
-
- MY_UNKNOWN_IMP3(
- ICompressSetOutStream,
- ICompressSetCoderProperties,
- ICompressWriteCoderProperties
- )
-
- HRESULT Init();
-
- // ICompressCoder interface
- HRESULT SetStreams(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize);
- HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);
-
- HRESULT CodeReal(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress);
-
- // ICompressCoder interface
- STDMETHOD(Code)(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize, const UInt64 *outSize,
- ICompressProgressInfo *progress);
-
- // ICompressSetCoderProperties2
- STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
- const PROPVARIANT *properties, UInt32 numProperties);
-
- // ICompressWriteCoderProperties
- STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
-
- STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
- STDMETHOD(ReleaseOutStream)();
-
- virtual ~CEncoder() {}
-};
-
-}}
-
-#endif
+/* + * LZMAEncoder.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __LZMA_ENCODER_H +#define __LZMA_ENCODER_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/Alloc.h" +#include "../../ICoder.h" +#include "../LZ/IMatchFinder.h" +#include "../RangeCoder/RangeCoderBitTree.h" + +#include "LZMA.h" + +namespace NCompress { +namespace NLZMA { + +typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder; + +class CBaseState +{ +protected: + CState _state; + Byte _previousByte; + UInt32 _repDistances[kNumRepDistances]; + void Init() + { + _state.Init(); + _previousByte = 0; + for(UInt32 i = 0 ; i < kNumRepDistances; i++) + _repDistances[i] = 0; + } +}; + +struct COptimal +{ + CState State; + + bool Prev1IsChar; + bool Prev2; + + UInt32 PosPrev2; + UInt32 BackPrev2; + + UInt32 Price; + UInt32 PosPrev; // posNext; + UInt32 BackPrev; + UInt32 Backs[kNumRepDistances]; + void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } + void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + bool IsShortRep() { return (BackPrev == 0); } +}; + + +extern Byte g_FastPos[1 << 11]; +inline UInt32 GetPosSlot(UInt32 pos) +{ + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return g_FastPos[pos >> 10] + 20; + return g_FastPos[pos >> 20] + 40; +} + +inline UInt32 GetPosSlot2(UInt32 pos) +{ + if (pos < (1 << 17)) + return g_FastPos[pos >> 6] + 12; + if (pos < (1 << 27)) + return g_FastPos[pos >> 16] + 32; + return g_FastPos[pos >> 26] + 52; +} + +const UInt32 kIfinityPrice = 0xFFFFFFF; + +const UInt32 kNumOpts = 1 << 12; + + +class CLiteralEncoder2 +{ + CMyBitEncoder _encoders[0x300]; +public: + void Init() + { + for (int i = 0; i < 0x300; i++) + _encoders[i].Init(); + } + void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); + void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); + UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; +}; + +class CLiteralEncoder +{ + CLiteralEncoder2 *_coders; + int _numPrevBits; + int _numPosBits; + UInt32 _posMask; +public: + CLiteralEncoder(): _coders(0) {} + ~CLiteralEncoder() { Free(); } + void Free() + { + MyFree(_coders); + _coders = 0; + } + bool Create(int numPosBits, int numPrevBits) + { + if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) + { + Free(); + UInt32 numStates = 1 << (numPosBits + numPrevBits); + _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); + } + _numPosBits = numPosBits; + _posMask = (1 << numPosBits) - 1; + _numPrevBits = numPrevBits; + return (_coders != 0); + } + void Init() + { + UInt32 numStates = 1 << (_numPrevBits + _numPosBits); + for (UInt32 i = 0; i < numStates; i++) + _coders[i].Init(); + } + CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) + { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } +}; + +namespace NLength { + +class CEncoder +{ + CMyBitEncoder _choice; + CMyBitEncoder _choice2; + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder; +public: + void Init(UInt32 numPosStates); + void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); + void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; +}; + +const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; + +class CPriceTableEncoder: public CEncoder +{ + UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; + UInt32 _tableSize; + UInt32 _counters[kNumPosStatesEncodingMax]; +public: + void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices[posState]); + _counters[posState] = _tableSize; + } + void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) + { + CEncoder::Encode(rangeEncoder, symbol, posState); + if (updatePrice) + if (--_counters[posState] == 0) + UpdateTable(posState); + } +}; + +} + +class CEncoder : + public ICompressCoder, + public ICompressSetOutStream, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CBaseState, + public CMyUnknownImp +{ + COptimal _optimum[kNumOpts]; + CMyComPtr<IMatchFinder> _matchFinder; // test it + NRangeCoder::CEncoder _rangeEncoder; + + CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; + CMyBitEncoder _isRep[kNumStates]; + CMyBitEncoder _isRepG0[kNumStates]; + CMyBitEncoder _isRepG1[kNumStates]; + CMyBitEncoder _isRepG2[kNumStates]; + CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; + + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates]; + + CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; + NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder; + + NLength::CPriceTableEncoder _lenEncoder; + NLength::CPriceTableEncoder _repMatchLenEncoder; + + CLiteralEncoder _literalEncoder; + + UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; + + bool _fastMode; + // bool _maxMode; + UInt32 _numFastBytes; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + + UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + UInt32 _alignPrices[kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize; + + UInt32 _posStateBits; + UInt32 _posStateMask; + UInt32 _numLiteralPosStateBits; + UInt32 _numLiteralContextBits; + + UInt32 _dictionarySize; + + UInt32 _dictionarySizePrev; + UInt32 _numFastBytesPrev; + + UInt32 _matchPriceCount; + UInt64 nowPos64; + bool _finished; + ISequentialInStream *_inStream; + + UInt32 _matchFinderCycles; + int _matchFinderIndex; + #ifdef COMPRESS_MF_MT + bool _multiThread; + #endif + + bool _writeEndMark; + + bool _needReleaseMFStream; + + IMatchFinderSetNumPasses *setMfPasses; + + void ReleaseMatchFinder() + { + setMfPasses = 0; + _matchFinder.Release(); + } + + HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs); + + HRESULT MovePos(UInt32 num); + UInt32 GetRepLen1Price(CState state, UInt32 posState) const + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[state.Index][posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const + { + UInt32 price; + if(repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[state.Index][posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const + { + return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + + GetPureRepPrice(repIndex, state, posState); + } + /* + UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const + { + if (pos >= kNumFullDistances) + return kIfinityPrice; + return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); + } + UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const + { + UInt32 price; + UInt32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + */ + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const + { + UInt32 price; + UInt32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + + UInt32 Backward(UInt32 &backRes, UInt32 cur); + HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); + HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); + + void FillDistancesPrices(); + void FillAlignPrices(); + + void ReleaseMFStream() + { + if (_matchFinder && _needReleaseMFStream) + { + _matchFinder->ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + HRESULT Flush(UInt32 nowPos); + class CCoderReleaser + { + CEncoder *_coder; + public: + CCoderReleaser(CEncoder *coder): _coder(coder) {} + ~CCoderReleaser() + { + _coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + void WriteEndMarker(UInt32 posState); + +public: + CEncoder(); + void SetWriteEndMarkerMode(bool writeEndMarker) + { _writeEndMark= writeEndMarker; } + + HRESULT Create(); + + MY_UNKNOWN_IMP3( + ICompressSetOutStream, + ICompressSetCoderProperties, + ICompressWriteCoderProperties + ) + + HRESULT Init(); + + // ICompressCoder interface + HRESULT SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize); + HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + // ICompressCoder interface + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + // ICompressSetCoderProperties2 + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties); + + // ICompressWriteCoderProperties + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + + virtual ~CEncoder() {} +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/LZMA/StdAfx.h b/Source/7zip/7zip/Compress/LZMA/StdAfx.h index 83fdd22..e7fb698 100755 --- a/Source/7zip/7zip/Compress/LZMA/StdAfx.h +++ b/Source/7zip/7zip/Compress/LZMA/StdAfx.h @@ -1,8 +1,8 @@ -// StdAfx.h
-
-#ifndef __STDAFX_H
-#define __STDAFX_H
-
-#include "../../../Common/MyWindows.h"
-
-#endif
+// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h index cbf5524..2373565 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoder.h @@ -1,220 +1,220 @@ -/*
- * RangeCoder.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMPRESS_RANGECODER_H
-#define __COMPRESS_RANGECODER_H
-
-#include "../../Common/InBuffer.h"
-#include "../../Common/OutBuffer.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-const int kNumTopBits = 24;
-const UInt32 kTopValue = (1 << kNumTopBits);
-
-class CEncoder
-{
- UInt32 _cacheSize;
- Byte _cache;
-public:
- UInt64 Low;
- UInt32 Range;
- COutBuffer Stream;
- bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
-
- void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
- void Init()
- {
- Stream.Init();
- Low = 0;
- Range = 0xFFFFFFFF;
- _cacheSize = 1;
- _cache = 0;
- }
-
- void FlushData()
- {
- // Low += 1;
- for(int i = 0; i < 5; i++)
- ShiftLow();
- }
-
- HRESULT FlushStream() { return Stream.Flush(); }
-
- void ReleaseStream() { Stream.ReleaseStream(); }
-
- void Encode(UInt32 start, UInt32 size, UInt32 total)
- {
- Low += start * (Range /= total);
- Range *= size;
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- void ShiftLow()
- {
- if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
- {
- Byte temp = _cache;
- do
- {
- Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
- temp = 0xFF;
- }
- while(--_cacheSize != 0);
- _cache = (Byte)((UInt32)Low >> 24);
- }
- _cacheSize++;
- Low = (UInt32)Low << 8;
- }
-
- void EncodeDirectBits(UInt32 value, int numTotalBits)
- {
- for (int i = numTotalBits - 1; i >= 0; i--)
- {
- Range >>= 1;
- if (((value >> i) & 1) == 1)
- Low += Range;
- if (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
- }
-
- void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
- {
- UInt32 newBound = (Range >> numTotalBits) * size0;
- if (symbol == 0)
- Range = newBound;
- else
- {
- Low += newBound;
- Range -= newBound;
- }
- while (Range < kTopValue)
- {
- Range <<= 8;
- ShiftLow();
- }
- }
-
- UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
-};
-
-class CDecoder
-{
-public:
- CInBuffer Stream;
- UInt32 Range;
- UInt32 Code;
- bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
-
- void Normalize()
- {
- while (Range < kTopValue)
- {
- Code = (Code << 8) | Stream.ReadByte();
- Range <<= 8;
- }
- }
-
- void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
- void Init()
- {
- Stream.Init();
- Code = 0;
- Range = 0xFFFFFFFF;
- for(int i = 0; i < 5; i++)
- Code = (Code << 8) | Stream.ReadByte();
- }
-
- void ReleaseStream() { Stream.ReleaseStream(); }
-
- UInt32 GetThreshold(UInt32 total)
- {
- return (Code) / ( Range /= total);
- }
-
- void Decode(UInt32 start, UInt32 size)
- {
- Code -= start * Range;
- Range *= size;
- Normalize();
- }
-
- UInt32 DecodeDirectBits(int numTotalBits)
- {
- UInt32 range = Range;
- UInt32 code = Code;
- UInt32 result = 0;
- for (int i = numTotalBits; i != 0; i--)
- {
- range >>= 1;
- /*
- result <<= 1;
- if (code >= range)
- {
- code -= range;
- result |= 1;
- }
- */
- UInt32 t = (code - range) >> 31;
- code -= range & (t - 1);
- result = (result << 1) | (1 - t);
-
- if (range < kTopValue)
- {
- code = (code << 8) | Stream.ReadByte();
- range <<= 8;
- }
- }
- Range = range;
- Code = code;
- return result;
- }
-
- UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
- {
- UInt32 newBound = (Range >> numTotalBits) * size0;
- UInt32 symbol;
- if (Code < newBound)
- {
- symbol = 0;
- Range = newBound;
- }
- else
- {
- symbol = 1;
- Code -= newBound;
- Range -= newBound;
- }
- Normalize();
- return symbol;
- }
-
- UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
-};
-
-}}
-
-#endif
+/* + * RangeCoder.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMPRESS_RANGECODER_H +#define __COMPRESS_RANGECODER_H + +#include "../../Common/InBuffer.h" +#include "../../Common/OutBuffer.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumTopBits = 24; +const UInt32 kTopValue = (1 << kNumTopBits); + +class CEncoder +{ + UInt32 _cacheSize; + Byte _cache; +public: + UInt64 Low; + UInt32 Range; + COutBuffer Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + void FlushData() + { + // Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() { return Stream.Flush(); } + + void ReleaseStream() { Stream.ReleaseStream(); } + + void Encode(UInt32 start, UInt32 size, UInt32 total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + void ShiftLow() + { + if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) + { + Byte temp = _cache; + do + { + Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (Byte)((UInt32)Low >> 24); + } + _cacheSize++; + Low = (UInt32)Low << 8; + } + + void EncodeDirectBits(UInt32 value, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((value >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } +}; + +class CDecoder +{ +public: + CInBuffer Stream; + UInt32 Range; + UInt32 Code; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Code = 0; + Range = 0xFFFFFFFF; + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + void ReleaseStream() { Stream.ReleaseStream(); } + + UInt32 GetThreshold(UInt32 total) + { + return (Code) / ( Range /= total); + } + + void Decode(UInt32 start, UInt32 size) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + UInt32 DecodeDirectBits(int numTotalBits) + { + UInt32 range = Range; + UInt32 code = Code; + UInt32 result = 0; + for (int i = numTotalBits; i != 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UInt32 t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + UInt32 symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp index 235797a..dbf0f2f 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp @@ -1,95 +1,95 @@ -/*
- * RangeCoderBit.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "RangeCoderBit.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
-static CPriceTables g_PriceTables;
-
-CPriceTables::CPriceTables() { Init(); }
-
-void CPriceTables::Init()
-{
- const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
- for(int i = kNumBits - 1; i >= 0; i--)
- {
- UInt32 start = 1 << (kNumBits - i - 1);
- UInt32 end = 1 << (kNumBits - i);
- for (UInt32 j = start; j < end; j++)
- ProbPrices[j] = (i << kNumBitPriceShiftBits) +
- (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
- }
-
- /*
- // simplest: bad solution
- for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
- ProbPrices[i] = kBitPrice;
- */
-
- /*
- const double kDummyMultMid = (1.0 / kBitPrice) / 2;
- const double kDummyMultMid = 0;
- // float solution
- double ln2 = log(double(2));
- double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits));
- for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
- ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice);
- */
-
- /*
- // experimental, slow, solution:
- for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++)
- {
- const int kCyclesBits = 5;
- const UInt32 kCycles = (1 << kCyclesBits);
-
- UInt32 range = UInt32(-1);
- UInt32 bitCount = 0;
- for (UInt32 j = 0; j < kCycles; j++)
- {
- range >>= (kNumBitModelTotalBits - kNumMoveReducingBits);
- range *= i;
- while(range < (1 << 31))
- {
- range <<= 1;
- bitCount++;
- }
- }
- bitCount <<= kNumBitPriceShiftBits;
- range -= (1 << 31);
- for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--)
- {
- range <<= 1;
- if (range > (1 << 31))
- {
- bitCount += (1 << k);
- range -= (1 << 31);
- }
- }
- ProbPrices[i] = (bitCount
- // + (1 << (kCyclesBits - 1))
- ) >> kCyclesBits;
- }
- */
-}
-
-}}
+/* + * RangeCoderBit.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "RangeCoderBit.h" + +namespace NCompress { +namespace NRangeCoder { + +UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; +static CPriceTables g_PriceTables; + +CPriceTables::CPriceTables() { Init(); } + +void CPriceTables::Init() +{ + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for(int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = 1 << (kNumBits - i - 1); + UInt32 end = 1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = (i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + + /* + // simplest: bad solution + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + ProbPrices[i] = kBitPrice; + */ + + /* + const double kDummyMultMid = (1.0 / kBitPrice) / 2; + const double kDummyMultMid = 0; + // float solution + double ln2 = log(double(2)); + double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); + */ + + /* + // experimental, slow, solution: + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + { + const int kCyclesBits = 5; + const UInt32 kCycles = (1 << kCyclesBits); + + UInt32 range = UInt32(-1); + UInt32 bitCount = 0; + for (UInt32 j = 0; j < kCycles; j++) + { + range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); + range *= i; + while(range < (1 << 31)) + { + range <<= 1; + bitCount++; + } + } + bitCount <<= kNumBitPriceShiftBits; + range -= (1 << 31); + for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) + { + range <<= 1; + if (range > (1 << 31)) + { + bitCount += (1 << k); + range -= (1 << 31); + } + } + ProbPrices[i] = (bitCount + // + (1 << (kCyclesBits - 1)) + ) >> kCyclesBits; + } + */ +} + +}} diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h index e2e7902..366abbc 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBit.h @@ -1,135 +1,135 @@ -/*
- * RangeCoderBit.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMPRESS_RANGECODER_BIT_H
-#define __COMPRESS_RANGECODER_BIT_H
-
-#include "RangeCoder.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-const int kNumBitModelTotalBits = 11;
-const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
-
-const int kNumMoveReducingBits = 2;
-
-const int kNumBitPriceShiftBits = 6;
-const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
-
-class CPriceTables
-{
-public:
- static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
- static void Init();
- CPriceTables();
-};
-
-template <int numMoveBits>
-class CBitModel
-{
-public:
- UInt32 Prob;
- void UpdateModel(UInt32 symbol)
- {
- /*
- Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
- Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
- */
- if (symbol == 0)
- Prob += (kBitModelTotal - Prob) >> numMoveBits;
- else
- Prob -= (Prob) >> numMoveBits;
- }
-public:
- void Init() { Prob = kBitModelTotal / 2; }
-};
-
-template <int numMoveBits>
-class CBitEncoder: public CBitModel<numMoveBits>
-{
-public:
- void Encode(CEncoder *encoder, UInt32 symbol)
- {
- /*
- encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
- this->UpdateModel(symbol);
- */
- UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
- if (symbol == 0)
- {
- encoder->Range = newBound;
- this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
- }
- else
- {
- encoder->Low += newBound;
- encoder->Range -= newBound;
- this->Prob -= (this->Prob) >> numMoveBits;
- }
- if (encoder->Range < kTopValue)
- {
- encoder->Range <<= 8;
- encoder->ShiftLow();
- }
- }
- UInt32 GetPrice(UInt32 symbol) const
- {
- return CPriceTables::ProbPrices[
- (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
- }
- UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }
- UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }
-};
-
-
-template <int numMoveBits>
-class CBitDecoder: public CBitModel<numMoveBits>
-{
-public:
- UInt32 Decode(CDecoder *decoder)
- {
- UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
- if (decoder->Code < newBound)
- {
- decoder->Range = newBound;
- this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
- if (decoder->Range < kTopValue)
- {
- decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
- decoder->Range <<= 8;
- }
- return 0;
- }
- else
- {
- decoder->Range -= newBound;
- decoder->Code -= newBound;
- this->Prob -= (this->Prob) >> numMoveBits;
- if (decoder->Range < kTopValue)
- {
- decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
- decoder->Range <<= 8;
- }
- return 1;
- }
- }
-};
-
-}}
-
-#endif
+/* + * RangeCoderBit.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMPRESS_RANGECODER_BIT_H +#define __COMPRESS_RANGECODER_BIT_H + +#include "RangeCoder.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumBitModelTotalBits = 11; +const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveReducingBits = 2; + +const int kNumBitPriceShiftBits = 6; +const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; + +class CPriceTables +{ +public: + static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + static void Init(); + CPriceTables(); +}; + +template <int numMoveBits> +class CBitModel +{ +public: + UInt32 Prob; + void UpdateModel(UInt32 symbol) + { + /* + Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; + Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); + */ + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } +public: + void Init() { Prob = kBitModelTotal / 2; } +}; + +template <int numMoveBits> +class CBitEncoder: public CBitModel<numMoveBits> +{ +public: + void Encode(CEncoder *encoder, UInt32 symbol) + { + /* + encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); + this->UpdateModel(symbol); + */ + UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (symbol == 0) + { + encoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + } + else + { + encoder->Low += newBound; + encoder->Range -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + } + if (encoder->Range < kTopValue) + { + encoder->Range <<= 8; + encoder->ShiftLow(); + } + } + UInt32 GetPrice(UInt32 symbol) const + { + return CPriceTables::ProbPrices[ + (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } + UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } +}; + + +template <int numMoveBits> +class CBitDecoder: public CBitModel<numMoveBits> +{ +public: + UInt32 Decode(CDecoder *decoder) + { + UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (decoder->Code < newBound) + { + decoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 0; + } + else + { + decoder->Range -= newBound; + decoder->Code -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 1; + } + } +}; + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h index cd8ae5a..126f6f0 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderBitTree.h @@ -1,176 +1,176 @@ -/*
- * RangeCoderBitTree.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMPRESS_RANGECODER_BIT_TREE_H
-#define __COMPRESS_RANGECODER_BIT_TREE_H
-
-#include "RangeCoderBit.h"
-#include "RangeCoderOpt.h"
-
-namespace NCompress {
-namespace NRangeCoder {
-
-template <int numMoveBits, int NumBitLevels>
-class CBitTreeEncoder
-{
- CBitEncoder<numMoveBits> Models[1 << NumBitLevels];
-public:
- void Init()
- {
- for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
- Models[i].Init();
- }
- void Encode(CEncoder *rangeEncoder, UInt32 symbol)
- {
- UInt32 modelIndex = 1;
- for (int bitIndex = NumBitLevels; bitIndex != 0 ;)
- {
- bitIndex--;
- UInt32 bit = (symbol >> bitIndex) & 1;
- Models[modelIndex].Encode(rangeEncoder, bit);
- modelIndex = (modelIndex << 1) | bit;
- }
- };
- void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol)
- {
- UInt32 modelIndex = 1;
- for (int i = 0; i < NumBitLevels; i++)
- {
- UInt32 bit = symbol & 1;
- Models[modelIndex].Encode(rangeEncoder, bit);
- modelIndex = (modelIndex << 1) | bit;
- symbol >>= 1;
- }
- }
- UInt32 GetPrice(UInt32 symbol) const
- {
- symbol |= (1 << NumBitLevels);
- UInt32 price = 0;
- while (symbol != 1)
- {
- price += Models[symbol >> 1].GetPrice(symbol & 1);
- symbol >>= 1;
- }
- return price;
- }
- UInt32 ReverseGetPrice(UInt32 symbol) const
- {
- UInt32 price = 0;
- UInt32 modelIndex = 1;
- for (int i = NumBitLevels; i != 0; i--)
- {
- UInt32 bit = symbol & 1;
- symbol >>= 1;
- price += Models[modelIndex].GetPrice(bit);
- modelIndex = (modelIndex << 1) | bit;
- }
- return price;
- }
-};
-
-template <int numMoveBits, int NumBitLevels>
-class CBitTreeDecoder
-{
- CBitDecoder<numMoveBits> Models[1 << NumBitLevels];
-public:
- void Init()
- {
- for(UInt32 i = 1; i < (1 << NumBitLevels); i++)
- Models[i].Init();
- }
- UInt32 Decode(CDecoder *rangeDecoder)
- {
- UInt32 modelIndex = 1;
- RC_INIT_VAR
- for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--)
- {
- // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder);
- RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex)
- }
- RC_FLUSH_VAR
- return modelIndex - (1 << NumBitLevels);
- };
- UInt32 ReverseDecode(CDecoder *rangeDecoder)
- {
- UInt32 modelIndex = 1;
- UInt32 symbol = 0;
- RC_INIT_VAR
- for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
- {
- // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
- // modelIndex <<= 1;
- // modelIndex += bit;
- // symbol |= (bit << bitIndex);
- RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
- }
- RC_FLUSH_VAR
- return symbol;
- }
-};
-
-template <int numMoveBits>
-void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models,
- CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol)
-{
- UInt32 modelIndex = 1;
- for (int i = 0; i < NumBitLevels; i++)
- {
- UInt32 bit = symbol & 1;
- Models[modelIndex].Encode(rangeEncoder, bit);
- modelIndex = (modelIndex << 1) | bit;
- symbol >>= 1;
- }
-}
-
-template <int numMoveBits>
-UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models,
- UInt32 NumBitLevels, UInt32 symbol)
-{
- UInt32 price = 0;
- UInt32 modelIndex = 1;
- for (int i = NumBitLevels; i != 0; i--)
- {
- UInt32 bit = symbol & 1;
- symbol >>= 1;
- price += Models[modelIndex].GetPrice(bit);
- modelIndex = (modelIndex << 1) | bit;
- }
- return price;
-}
-
-template <int numMoveBits>
-UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models,
- CDecoder *rangeDecoder, int NumBitLevels)
-{
- UInt32 modelIndex = 1;
- UInt32 symbol = 0;
- RC_INIT_VAR
- for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
- {
- // UInt32 bit = Models[modelIndex].Decode(rangeDecoder);
- // modelIndex <<= 1;
- // modelIndex += bit;
- // symbol |= (bit << bitIndex);
- RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex))
- }
- RC_FLUSH_VAR
- return symbol;
-}
-
-}}
-
-#endif
+/* + * RangeCoderBitTree.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMPRESS_RANGECODER_BIT_TREE_H +#define __COMPRESS_RANGECODER_BIT_TREE_H + +#include "RangeCoderBit.h" +#include "RangeCoderOpt.h" + +namespace NCompress { +namespace NRangeCoder { + +template <int numMoveBits, int NumBitLevels> +class CBitTreeEncoder +{ + CBitEncoder<numMoveBits> Models[1 << NumBitLevels]; +public: + void Init() + { + for(UInt32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + void Encode(CEncoder *rangeEncoder, UInt32 symbol) + { + UInt32 modelIndex = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0 ;) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + } + }; + void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) + { + UInt32 modelIndex = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } + } + UInt32 GetPrice(UInt32 symbol) const + { + symbol |= (1 << NumBitLevels); + UInt32 price = 0; + while (symbol != 1) + { + price += Models[symbol >> 1].GetPrice(symbol & 1); + symbol >>= 1; + } + return price; + } + UInt32 ReverseGetPrice(UInt32 symbol) const + { + UInt32 price = 0; + UInt32 modelIndex = 1; + for (int i = NumBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) | bit; + } + return price; + } +}; + +template <int numMoveBits, int NumBitLevels> +class CBitTreeDecoder +{ + CBitDecoder<numMoveBits> Models[1 << NumBitLevels]; +public: + void Init() + { + for(UInt32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + UInt32 Decode(CDecoder *rangeDecoder) + { + UInt32 modelIndex = 1; + RC_INIT_VAR + for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) + { + // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); + RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) + } + RC_FLUSH_VAR + return modelIndex - (1 << NumBitLevels); + }; + UInt32 ReverseDecode(CDecoder *rangeDecoder) + { + UInt32 modelIndex = 1; + UInt32 symbol = 0; + RC_INIT_VAR + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; + } +}; + +template <int numMoveBits> +void ReverseBitTreeEncode(CBitEncoder<numMoveBits> *Models, + CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) +{ + UInt32 modelIndex = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } +} + +template <int numMoveBits> +UInt32 ReverseBitTreeGetPrice(CBitEncoder<numMoveBits> *Models, + UInt32 NumBitLevels, UInt32 symbol) +{ + UInt32 price = 0; + UInt32 modelIndex = 1; + for (int i = NumBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) | bit; + } + return price; +} + +template <int numMoveBits> +UInt32 ReverseBitTreeDecode(CBitDecoder<numMoveBits> *Models, + CDecoder *rangeDecoder, int NumBitLevels) +{ + UInt32 modelIndex = 1; + UInt32 symbol = 0; + RC_INIT_VAR + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; +} + +}} + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h index 4b59e82..e3ec84c 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h +++ b/Source/7zip/7zip/Compress/RangeCoder/RangeCoderOpt.h @@ -1,46 +1,46 @@ -/*
- * RangeCoderOpt.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMPRESS_RANGECODER_OPT_H
-#define __COMPRESS_RANGECODER_OPT_H
-
-#define RC_INIT_VAR \
- UInt32 range = rangeDecoder->Range; \
- UInt32 code = rangeDecoder->Code;
-
-#define RC_FLUSH_VAR \
- rangeDecoder->Range = range; \
- rangeDecoder->Code = code;
-
-#define RC_NORMALIZE \
- if (range < NCompress::NRangeCoder::kTopValue) \
- { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; }
-
-#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \
- { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \
- if (code < bound) \
- { A0; range = bound; \
- prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \
- mi <<= 1; } \
- else \
- { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \
- mi = (mi + mi) + 1; }} \
- RC_NORMALIZE
-
-#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;)
-
-#endif
+/* + * RangeCoderOpt.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMPRESS_RANGECODER_OPT_H +#define __COMPRESS_RANGECODER_OPT_H + +#define RC_INIT_VAR \ + UInt32 range = rangeDecoder->Range; \ + UInt32 code = rangeDecoder->Code; + +#define RC_FLUSH_VAR \ + rangeDecoder->Range = range; \ + rangeDecoder->Code = code; + +#define RC_NORMALIZE \ + if (range < NCompress::NRangeCoder::kTopValue) \ + { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } + +#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ + { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ + if (code < bound) \ + { A0; range = bound; \ + prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ + mi <<= 1; } \ + else \ + { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ + mi = (mi + mi) + 1; }} \ + RC_NORMALIZE + +#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) + +#endif diff --git a/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h index 21c2fd7..b637fd4 100755 --- a/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h +++ b/Source/7zip/7zip/Compress/RangeCoder/StdAfx.h @@ -1,6 +1,6 @@ -// StdAfx.h
-
-#ifndef __STDAFX_H
-#define __STDAFX_H
-
-#endif
+// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#endif diff --git a/Source/7zip/7zip/ICoder.h b/Source/7zip/7zip/ICoder.h index a0e93e4..7e90f2c 100755 --- a/Source/7zip/7zip/ICoder.h +++ b/Source/7zip/7zip/ICoder.h @@ -1,178 +1,178 @@ -/*
- * ICoder.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __ICODER_H
-#define __ICODER_H
-
-#include "IStream.h"
-
-// "23170F69-40C1-278A-0000-000400xx0000"
-#define CODER_INTERFACE(i, x) \
-DEFINE_GUID(IID_ ## i, \
-0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \
-struct i: public IUnknown
-
-CODER_INTERFACE(ICompressProgressInfo, 0x04)
-{
- STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
-};
-
-CODER_INTERFACE(ICompressCoder, 0x05)
-{
- STDMETHOD(Code)(ISequentialInStream *inStream,
- ISequentialOutStream *outStream,
- const UInt64 *inSize,
- const UInt64 *outSize,
- ICompressProgressInfo *progress) PURE;
-};
-
-CODER_INTERFACE(ICompressCoder2, 0x18)
-{
- STDMETHOD(Code)(ISequentialInStream **inStreams,
- const UInt64 **inSizes,
- UInt32 numInStreams,
- ISequentialOutStream **outStreams,
- const UInt64 **outSizes,
- UInt32 numOutStreams,
- ICompressProgressInfo *progress) PURE;
-};
-
-namespace NCoderPropID
-{
- enum EEnum
- {
- kDictionarySize = 0x400,
- kUsedMemorySize,
- kOrder,
- kPosStateBits = 0x440,
- kLitContextBits,
- kLitPosBits,
- kNumFastBytes = 0x450,
- kMatchFinder,
- kMatchFinderCycles,
- kNumPasses = 0x460,
- kAlgorithm = 0x470,
- kMultiThread = 0x480,
- kNumThreads,
- kEndMarker = 0x490
- };
-}
-
-CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
-{
- STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
- const PROPVARIANT *properties, UInt32 numProperties) PURE;
-};
-
-/*
-CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
-{
- STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
-};
-*/
-
-CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
-{
- STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
-};
-
-CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
-{
- STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE;
-};
-
-CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
-{
- STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
-};
-
-CODER_INTERFACE(ICompressSetCoderMt, 0x25)
-{
- STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;
-};
-
-CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
-{
- STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
-};
-
-CODER_INTERFACE(ICompressSetInStream, 0x31)
-{
- STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
- STDMETHOD(ReleaseInStream)() PURE;
-};
-
-CODER_INTERFACE(ICompressSetOutStream, 0x32)
-{
- STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
- STDMETHOD(ReleaseOutStream)() PURE;
-};
-
-CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
-{
- STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
-};
-
-CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
-{
- STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
-};
-
-CODER_INTERFACE(ICompressFilter, 0x40)
-{
- STDMETHOD(Init)() PURE;
- STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE;
- // Filter return outSize (UInt32)
- // if (outSize <= size): Filter have converted outSize bytes
- // if (outSize > size): Filter have not converted anything.
- // and it needs at least outSize bytes to convert one block
- // (it's for crypto block algorithms).
-};
-
-CODER_INTERFACE(ICryptoProperties, 0x80)
-{
- STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
- STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
-};
-
-CODER_INTERFACE(ICryptoSetPassword, 0x90)
-{
- STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
-};
-
-CODER_INTERFACE(ICryptoSetCRC, 0xA0)
-{
- STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
-};
-
-//////////////////////
-// It's for DLL file
-namespace NMethodPropID
-{
- enum EEnum
- {
- kID,
- kName,
- kDecoder,
- kEncoder,
- kInStreams,
- kOutStreams,
- kDescription
- };
-}
-
-#endif
+/* + * ICoder.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +// "23170F69-40C1-278A-0000-000400xx0000" +#define CODER_INTERFACE(i, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ +struct i: public IUnknown + +CODER_INTERFACE(ICompressProgressInfo, 0x04) +{ + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressCoder, 0x05) +{ + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, + const UInt64 *outSize, + ICompressProgressInfo *progress) PURE; +}; + +CODER_INTERFACE(ICompressCoder2, 0x18) +{ + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +namespace NCoderPropID +{ + enum EEnum + { + kDictionarySize = 0x400, + kUsedMemorySize, + kOrder, + kPosStateBits = 0x440, + kLitContextBits, + kLitPosBits, + kNumFastBytes = 0x450, + kMatchFinder, + kMatchFinderCycles, + kNumPasses = 0x460, + kAlgorithm = 0x470, + kMultiThread = 0x480, + kNumThreads, + kEndMarker = 0x490 + }; +} + +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) +{ + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetInStream, 0x31) +{ + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetOutStream, 0x32) +{ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + STDMETHOD(Init)() PURE; + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; + // Filter return outSize (UInt32) + // if (outSize <= size): Filter have converted outSize bytes + // if (outSize > size): Filter have not converted anything. + // and it needs at least outSize bytes to convert one block + // (it's for crypto block algorithms). +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + +////////////////////// +// It's for DLL file +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kInStreams, + kOutStreams, + kDescription + }; +} + +#endif diff --git a/Source/7zip/7zip/IStream.h b/Source/7zip/7zip/IStream.h index 62f6060..3c6d56f 100755 --- a/Source/7zip/7zip/IStream.h +++ b/Source/7zip/7zip/IStream.h @@ -1,77 +1,77 @@ -/*
- * IStream.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __ISTREAM_H
-#define __ISTREAM_H
-
-#include "../Common/MyUnknown.h"
-#include "../Common/Types.h"
-
-// "23170F69-40C1-278A-0000-000300xx0000"
-
-#define STREAM_INTERFACE_SUB(i, b, x) \
-DEFINE_GUID(IID_ ## i, \
-0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \
-struct i: public b
-
-#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x)
-
-STREAM_INTERFACE(ISequentialInStream, 0x01)
-{
- STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE;
- /*
- Out: if size != 0, return_value = S_OK and (*processedSize == 0),
- then there are no more bytes in stream.
- if (size > 0) && there are bytes in stream,
- this function must read at least 1 byte.
- This function is allowed to read less than number of remaining bytes in stream.
- You must call Read function in loop, if you need exact amount of data
- */
-};
-
-STREAM_INTERFACE(ISequentialOutStream, 0x02)
-{
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE;
- /*
- if (size > 0) this function must write at least 1 byte.
- This function is allowed to write less than "size".
- You must call Write function in loop, if you need to write exact amount of data
- */
-};
-
-STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03)
-{
- STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
-};
-
-STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04)
-{
- STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE;
- STDMETHOD(SetSize)(Int64 newSize) PURE;
-};
-
-STREAM_INTERFACE(IStreamGetSize, 0x06)
-{
- STDMETHOD(GetSize)(UInt64 *size) PURE;
-};
-
-STREAM_INTERFACE(IOutStreamFlush, 0x07)
-{
- STDMETHOD(Flush)() PURE;
-};
-
-#endif
+/* + * IStream.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __ISTREAM_H +#define __ISTREAM_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.h" + +// "23170F69-40C1-278A-0000-000300xx0000" + +#define STREAM_INTERFACE_SUB(i, b, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ +struct i: public b + +#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) + +STREAM_INTERFACE(ISequentialInStream, 0x01) +{ + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + Out: if size != 0, return_value = S_OK and (*processedSize == 0), + then there are no more bytes in stream. + if (size > 0) && there are bytes in stream, + this function must read at least 1 byte. + This function is allowed to read less than number of remaining bytes in stream. + You must call Read function in loop, if you need exact amount of data + */ +}; + +STREAM_INTERFACE(ISequentialOutStream, 0x02) +{ + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + if (size > 0) this function must write at least 1 byte. + This function is allowed to write less than "size". + You must call Write function in loop, if you need to write exact amount of data + */ +}; + +STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; +}; + +STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; + STDMETHOD(SetSize)(Int64 newSize) PURE; +}; + +STREAM_INTERFACE(IStreamGetSize, 0x06) +{ + STDMETHOD(GetSize)(UInt64 *size) PURE; +}; + +STREAM_INTERFACE(IOutStreamFlush, 0x07) +{ + STDMETHOD(Flush)() PURE; +}; + +#endif diff --git a/Source/7zip/Common/Alloc.cpp b/Source/7zip/Common/Alloc.cpp index 2898c6d..9ac1946 100755 --- a/Source/7zip/Common/Alloc.cpp +++ b/Source/7zip/Common/Alloc.cpp @@ -1,133 +1,133 @@ -/*
- * Alloc.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#ifdef _WIN32
-#include "MyWindows.h"
-#else
-#include <stdlib.h>
-#endif
-
-#include "Alloc.h"
-
-/* #define _SZ_ALLOC_DEBUG */
-/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
-#ifdef _SZ_ALLOC_DEBUG
-#include <stdio.h>
-int g_allocCount = 0;
-int g_allocCountMid = 0;
-int g_allocCountBig = 0;
-#endif
-
-void *MyAlloc(size_t size) throw()
-{
- if (size == 0)
- return 0;
- #ifdef _SZ_ALLOC_DEBUG
- fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
- #endif
- return ::malloc(size);
-}
-
-void MyFree(void *address) throw()
-{
- #ifdef _SZ_ALLOC_DEBUG
- if (address != 0)
- fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
- #endif
-
- ::free(address);
-}
-
-#ifdef _WIN32
-
-void *MidAlloc(size_t size) throw()
-{
- if (size == 0)
- return 0;
- #ifdef _SZ_ALLOC_DEBUG
- fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
- #endif
- return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
-}
-
-void MidFree(void *address) throw()
-{
- #ifdef _SZ_ALLOC_DEBUG
- if (address != 0)
- fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
- #endif
- if (address == 0)
- return;
- ::VirtualFree(address, 0, MEM_RELEASE);
-}
-
-static SIZE_T g_LargePageSize =
- #ifdef _WIN64
- (1 << 21);
- #else
- (1 << 22);
- #endif
-
-typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
-
-bool SetLargePageSize()
-{
- GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
- ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
- if (largePageMinimum == 0)
- return false;
- SIZE_T size = largePageMinimum();
- if (size == 0 || (size & (size - 1)) != 0)
- return false;
- g_LargePageSize = size;
- return true;
-}
-
-
-void *BigAlloc(size_t size) throw()
-{
- if (size == 0)
- return 0;
- #ifdef _SZ_ALLOC_DEBUG
- fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
- #endif
-
- if (size >= (1 << 18))
- {
- void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
- MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
- if (res != 0)
- return res;
- }
- return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
-}
-
-void BigFree(void *address) throw()
-{
- #ifdef _SZ_ALLOC_DEBUG
- if (address != 0)
- fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
- #endif
-
- if (address == 0)
- return;
- ::VirtualFree(address, 0, MEM_RELEASE);
-}
-
-#endif
+/* + * Alloc.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#ifdef _WIN32 +#include "MyWindows.h" +#else +#include <stdlib.h> +#endif + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include <stdio.h> +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); + #endif + return ::malloc(size); +} + +void MyFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d", --g_allocCount); + #endif + + ::free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + ::VirtualFree(address, 0, MEM_RELEASE); +} + +static SIZE_T g_LargePageSize = + #ifdef _WIN64 + (1 << 21); + #else + (1 << 22); + #endif + +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); + +bool SetLargePageSize() +{ + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return false; + SIZE_T size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return false; + g_LargePageSize = size; + return true; +} + + +void *BigAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + if (size >= (1 << 18)) + { + void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + ::VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/Source/7zip/Common/Alloc.h b/Source/7zip/Common/Alloc.h index 93705a1..5916ef0 100755 --- a/Source/7zip/Common/Alloc.h +++ b/Source/7zip/Common/Alloc.h @@ -1,44 +1,44 @@ -/*
- * Alloc.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMMON_ALLOC_H
-#define __COMMON_ALLOC_H
-
-#include <stddef.h>
-
-void *MyAlloc(size_t size) throw();
-void MyFree(void *address) throw();
-
-#ifdef _WIN32
-
-bool SetLargePageSize();
-
-void *MidAlloc(size_t size) throw();
-void MidFree(void *address) throw();
-void *BigAlloc(size_t size) throw();
-void BigFree(void *address) throw();
-
-#else
-
-#define MidAlloc(size) MyAlloc(size)
-#define MidFree(address) MyFree(address)
-#define BigAlloc(size) MyAlloc(size)
-#define BigFree(address) MyFree(address)
-
-#endif
-
-#endif
+/* + * Alloc.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include <stddef.h> + +void *MyAlloc(size_t size) throw(); +void MyFree(void *address) throw(); + +#ifdef _WIN32 + +bool SetLargePageSize(); + +void *MidAlloc(size_t size) throw(); +void MidFree(void *address) throw(); +void *BigAlloc(size_t size) throw(); +void BigFree(void *address) throw(); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#endif diff --git a/Source/7zip/Common/CRC.cpp b/Source/7zip/Common/CRC.cpp index 998a579..dad6432 100755 --- a/Source/7zip/Common/CRC.cpp +++ b/Source/7zip/Common/CRC.cpp @@ -1,76 +1,76 @@ -/*
- * CRC.cpp
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "StdAfx.h"
-
-#include "CRC.h"
-
-static const UInt32 kCRCPoly = 0xEDB88320;
-
-UInt32 CCRC::Table[256];
-
-void CCRC::InitTable()
-{
- for (UInt32 i = 0; i < 256; i++)
- {
- UInt32 r = i;
- for (int j = 0; j < 8; j++)
- if (r & 1)
- r = (r >> 1) ^ kCRCPoly;
- else
- r >>= 1;
- CCRC::Table[i] = r;
- }
-}
-
-class CCRCTableInit
-{
-public:
- CCRCTableInit() { CCRC::InitTable(); }
-} g_CRCTableInit;
-
-void CCRC::UpdateByte(Byte b)
-{
- _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8);
-}
-
-void CCRC::UpdateUInt16(UInt16 v)
-{
- UpdateByte(Byte(v));
- UpdateByte(Byte(v >> 8));
-}
-
-void CCRC::UpdateUInt32(UInt32 v)
-{
- for (int i = 0; i < 4; i++)
- UpdateByte((Byte)(v >> (8 * i)));
-}
-
-void CCRC::UpdateUInt64(UInt64 v)
-{
- for (int i = 0; i < 8; i++)
- UpdateByte((Byte)(v >> (8 * i)));
-}
-
-void CCRC::Update(const void *data, size_t size)
-{
- UInt32 v = _value;
- const Byte *p = (const Byte *)data;
- for (; size > 0 ; size--, p++)
- v = Table[((Byte)(v)) ^ *p] ^ (v >> 8);
- _value = v;
-}
+/* + * CRC.cpp + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "StdAfx.h" + +#include "CRC.h" + +static const UInt32 kCRCPoly = 0xEDB88320; + +UInt32 CCRC::Table[256]; + +void CCRC::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = r; + } +} + +class CCRCTableInit +{ +public: + CCRCTableInit() { CCRC::InitTable(); } +} g_CRCTableInit; + +void CCRC::UpdateByte(Byte b) +{ + _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); +} + +void CCRC::UpdateUInt16(UInt16 v) +{ + UpdateByte(Byte(v)); + UpdateByte(Byte(v >> 8)); +} + +void CCRC::UpdateUInt32(UInt32 v) +{ + for (int i = 0; i < 4; i++) + UpdateByte((Byte)(v >> (8 * i))); +} + +void CCRC::UpdateUInt64(UInt64 v) +{ + for (int i = 0; i < 8; i++) + UpdateByte((Byte)(v >> (8 * i))); +} + +void CCRC::Update(const void *data, size_t size) +{ + UInt32 v = _value; + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); + _value = v; +} diff --git a/Source/7zip/Common/CRC.h b/Source/7zip/Common/CRC.h index e01c72f..72cb518 100755 --- a/Source/7zip/Common/CRC.h +++ b/Source/7zip/Common/CRC.h @@ -1,51 +1,51 @@ -/*
- * CRC.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMMON_CRC_H
-#define __COMMON_CRC_H
-
-#include <stddef.h>
-#include "Types.h"
-
-class CCRC
-{
- UInt32 _value;
-public:
- static UInt32 Table[256];
- static void InitTable();
-
- CCRC(): _value(0xFFFFFFFF){};
- void Init() { _value = 0xFFFFFFFF; }
- void UpdateByte(Byte v);
- void UpdateUInt16(UInt16 v);
- void UpdateUInt32(UInt32 v);
- void UpdateUInt64(UInt64 v);
- void Update(const void *data, size_t size);
- UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }
- static UInt32 CalculateDigest(const void *data, size_t size)
- {
- CCRC crc;
- crc.Update(data, size);
- return crc.GetDigest();
- }
- static bool VerifyDigest(UInt32 digest, const void *data, size_t size)
- {
- return (CalculateDigest(data, size) == digest);
- }
-};
-
-#endif
+/* + * CRC.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMMON_CRC_H +#define __COMMON_CRC_H + +#include <stddef.h> +#include "Types.h" + +class CCRC +{ + UInt32 _value; +public: + static UInt32 Table[256]; + static void InitTable(); + + CCRC(): _value(0xFFFFFFFF){}; + void Init() { _value = 0xFFFFFFFF; } + void UpdateByte(Byte v); + void UpdateUInt16(UInt16 v); + void UpdateUInt32(UInt32 v); + void UpdateUInt64(UInt64 v); + void Update(const void *data, size_t size); + UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } + static UInt32 CalculateDigest(const void *data, size_t size) + { + CCRC crc; + crc.Update(data, size); + return crc.GetDigest(); + } + static bool VerifyDigest(UInt32 digest, const void *data, size_t size) + { + return (CalculateDigest(data, size) == digest); + } +}; + +#endif diff --git a/Source/7zip/Common/Defs.h b/Source/7zip/Common/Defs.h index f1746a8..dd55dbe 100755 --- a/Source/7zip/Common/Defs.h +++ b/Source/7zip/Common/Defs.h @@ -1,35 +1,35 @@ -/*
- * Defs.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMMON_DEFS_H
-#define __COMMON_DEFS_H
-
-template <class T> inline T MyMin(T a, T b)
- { return a < b ? a : b; }
-template <class T> inline T MyMax(T a, T b)
- { return a > b ? a : b; }
-
-template <class T> inline int MyCompare(T a, T b)
- { return a < b ? -1 : (a == b ? 0 : 1); }
-
-inline int BoolToInt(bool value)
- { return (value ? 1: 0); }
-
-inline bool IntToBool(int value)
- { return (value != 0); }
-
-#endif
+/* + * Defs.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template <class T> inline T MyMin(T a, T b) + { return a < b ? a : b; } +template <class T> inline T MyMax(T a, T b) + { return a > b ? a : b; } + +template <class T> inline int MyCompare(T a, T b) + { return a < b ? -1 : (a == b ? 0 : 1); } + +inline int BoolToInt(bool value) + { return (value ? 1: 0); } + +inline bool IntToBool(int value) + { return (value != 0); } + +#endif diff --git a/Source/7zip/Common/MyCom.h b/Source/7zip/Common/MyCom.h index 119aaff..c5e18df 100755 --- a/Source/7zip/Common/MyCom.h +++ b/Source/7zip/Common/MyCom.h @@ -1,218 +1,218 @@ -/*
- * MyCom.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __MYCOM_H
-#define __MYCOM_H
-
-#include "MyWindows.h"
-
-#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; }
-
-template <class T>
-class CMyComPtr
-{
- T* _p;
-public:
- // typedef T _PtrClass;
- CMyComPtr() { _p = NULL;}
- CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
- CMyComPtr(const CMyComPtr<T>& lp)
- {
- if ((_p = lp._p) != NULL)
- _p->AddRef();
- }
- ~CMyComPtr() { if (_p) _p->Release(); }
- void Release() { if (_p) { _p->Release(); _p = NULL; } }
- operator T*() const { return (T*)_p; }
- // T& operator*() const { return *_p; }
- T** operator&() { return &_p; }
- T* operator->() const { return _p; }
- T* operator=(T* p)
- {
- if (p != 0)
- p->AddRef();
- if (_p)
- _p->Release();
- _p = p;
- return p;
- }
- T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
- bool operator!() const { return (_p == NULL); }
- // bool operator==(T* pT) const { return _p == pT; }
- // Compare two objects for equivalence
- void Attach(T* p2)
- {
- Release();
- _p = p2;
- }
- T* Detach()
- {
- T* pt = _p;
- _p = NULL;
- return pt;
- }
- #ifdef _WIN32
- HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
- {
- return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
- }
- #endif
- /*
- HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
- {
- CLSID clsid;
- HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
- ATLASSERT(_p == NULL);
- if (SUCCEEDED(hr))
- hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
- return hr;
- }
- */
- template <class Q>
- HRESULT QueryInterface(REFGUID iid, Q** pp) const
- {
- return _p->QueryInterface(iid, (void**)pp);
- }
-};
-
-//////////////////////////////////////////////////////////
-
-class CMyComBSTR
-{
-public:
- BSTR m_str;
- CMyComBSTR() { m_str = NULL; }
- CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); }
- // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
- // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
- CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
- /*
- CMyComBSTR(REFGUID src)
- {
- LPOLESTR szGuid;
- StringFromCLSID(src, &szGuid);
- m_str = ::SysAllocString(szGuid);
- CoTaskMemFree(szGuid);
- }
- */
- ~CMyComBSTR() { ::SysFreeString(m_str); }
- CMyComBSTR& operator=(const CMyComBSTR& src)
- {
- if (m_str != src.m_str)
- {
- if (m_str)
- ::SysFreeString(m_str);
- m_str = src.MyCopy();
- }
- return *this;
- }
- CMyComBSTR& operator=(LPCOLESTR pSrc)
- {
- ::SysFreeString(m_str);
- m_str = ::SysAllocString(pSrc);
- return *this;
- }
- unsigned int Length() const { return ::SysStringLen(m_str); }
- operator BSTR() const { return m_str; }
- BSTR* operator&() { return &m_str; }
- BSTR MyCopy() const
- {
- int byteLen = ::SysStringByteLen(m_str);
- BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
- memmove(res, m_str, byteLen);
- return res;
- }
- void Attach(BSTR src) { m_str = src; }
- BSTR Detach()
- {
- BSTR s = m_str;
- m_str = NULL;
- return s;
- }
- void Empty()
- {
- ::SysFreeString(m_str);
- m_str = NULL;
- }
- bool operator!() const { return (m_str == NULL); }
-};
-
-
-//////////////////////////////////////////////////////////
-
-class CMyUnknownImp
-{
-public:
- ULONG __m_RefCount;
- CMyUnknownImp(): __m_RefCount(0) {}
-};
-
-#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
- (REFGUID iid, void **outObject) {
-
-#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \
- { *outObject = (void *)(i *)this; AddRef(); return S_OK; }
-
-#define MY_QUERYINTERFACE_END return E_NOINTERFACE; }
-
-#define MY_ADDREF_RELEASE \
-STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \
-STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \
- return __m_RefCount; delete this; return 0; }
-
-#define MY_UNKNOWN_IMP_SPEC(i) \
- MY_QUERYINTERFACE_BEGIN \
- i \
- MY_QUERYINTERFACE_END \
- MY_ADDREF_RELEASE
-
-
-#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \
- MY_QUERYINTERFACE_END \
- MY_ADDREF_RELEASE
-
-#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
- MY_QUERYINTERFACE_ENTRY(i) \
- )
-
-#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
- MY_QUERYINTERFACE_ENTRY(i1) \
- MY_QUERYINTERFACE_ENTRY(i2) \
- )
-
-#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
- MY_QUERYINTERFACE_ENTRY(i1) \
- MY_QUERYINTERFACE_ENTRY(i2) \
- MY_QUERYINTERFACE_ENTRY(i3) \
- )
-
-#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
- MY_QUERYINTERFACE_ENTRY(i1) \
- MY_QUERYINTERFACE_ENTRY(i2) \
- MY_QUERYINTERFACE_ENTRY(i3) \
- MY_QUERYINTERFACE_ENTRY(i4) \
- )
-
-#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
- MY_QUERYINTERFACE_ENTRY(i1) \
- MY_QUERYINTERFACE_ENTRY(i2) \
- MY_QUERYINTERFACE_ENTRY(i3) \
- MY_QUERYINTERFACE_ENTRY(i4) \
- MY_QUERYINTERFACE_ENTRY(i5) \
- )
-
-#endif
+/* + * MyCom.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __MYCOM_H +#define __MYCOM_H + +#include "MyWindows.h" + +#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } + +template <class T> +class CMyComPtr +{ + T* _p; +public: + // typedef T _PtrClass; + CMyComPtr() { _p = NULL;} + CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr<T>& lp) + { + if ((_p = lp._p) != NULL) + _p->AddRef(); + } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p != 0) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + // Compare two objects for equivalence + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + #ifdef _WIN32 + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + #endif + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template <class Q> + HRESULT QueryInterface(REFGUID iid, Q** pp) const + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +class CMyComBSTR +{ +public: + BSTR m_str; + CMyComBSTR() { m_str = NULL; } + CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + ~CMyComBSTR() { ::SysFreeString(m_str); } + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + CMyComBSTR& operator=(LPCOLESTR pSrc) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(pSrc); + return *this; + } + unsigned int Length() const { return ::SysStringLen(m_str); } + operator BSTR() const { return m_str; } + BSTR* operator&() { return &m_str; } + BSTR MyCopy() const + { + int byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + memmove(res, m_str, byteLen); + return res; + } + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } + bool operator!() const { return (m_str == NULL); } +}; + + +////////////////////////////////////////////////////////// + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} +}; + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ + (REFGUID iid, void **outObject) { + +#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) + +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) + +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + ) + +#endif diff --git a/Source/7zip/Common/MyGuidDef.h b/Source/7zip/Common/MyGuidDef.h index 5e2cf4a..b01a444 100755 --- a/Source/7zip/Common/MyGuidDef.h +++ b/Source/7zip/Common/MyGuidDef.h @@ -1,69 +1,69 @@ -/*
- * MyGuidDef.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef GUID_DEFINED
-#define GUID_DEFINED
-
-#include "Types.h"
-
-typedef struct {
- UInt32 Data1;
- UInt16 Data2;
- UInt16 Data3;
- unsigned char Data4[8];
-} GUID;
-
-#ifdef __cplusplus
-#define REFGUID const GUID &
-#else
-#define REFGUID const GUID *
-#endif
-
-#define REFCLSID REFGUID
-#define REFIID REFGUID
-
-#ifdef __cplusplus
-inline bool operator==(REFGUID g1, REFGUID g2)
-{
- for (int i = 0; i < (int)sizeof(g1); i++)
- if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])
- return false;
- return true;
-}
-inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
-#endif
-
-#ifdef __cplusplus
- #define MY_EXTERN_C extern "C"
-#else
- #define MY_EXTERN_C extern
-#endif
-
-#endif // GUID_DEFINED
-
-
-#ifdef DEFINE_GUID
-#undef DEFINE_GUID
-#endif
-
-#ifdef INITGUID
- #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
- MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
-#else
- #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
- MY_EXTERN_C const GUID name
-#endif
+/* + * MyGuidDef.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "Types.h" + +typedef struct { + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +#define REFCLSID REFGUID +#define REFIID REFGUID + +#ifdef __cplusplus +inline bool operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < (int)sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return false; + return true; +} +inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } +#endif + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#endif // GUID_DEFINED + + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif diff --git a/Source/7zip/Common/MyUnknown.h b/Source/7zip/Common/MyUnknown.h index 7508b60..e45adb7 100755 --- a/Source/7zip/Common/MyUnknown.h +++ b/Source/7zip/Common/MyUnknown.h @@ -1,39 +1,39 @@ -/*
- * MyUnknown.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __MYUNKNOWN_H
-#define __MYUNKNOWN_H
-
-#ifdef _WIN32
-
-#ifdef _WIN32_WCE
-#if (_WIN32_WCE > 300)
-#include <basetyps.h>
-#else
-#define MIDL_INTERFACE(x) struct
-#endif
-#else
-#include <basetyps.h>
-#endif
-
-#include <unknwn.h>
-
-#else
-#include "MyWindows.h"
-#endif
-
-#endif
+/* + * MyUnknown.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __MYUNKNOWN_H +#define __MYUNKNOWN_H + +#ifdef _WIN32 + +#ifdef _WIN32_WCE +#if (_WIN32_WCE > 300) +#include <basetyps.h> +#else +#define MIDL_INTERFACE(x) struct +#endif +#else +#include <basetyps.h> +#endif + +#include <unknwn.h> + +#else +#include "MyWindows.h" +#endif + +#endif diff --git a/Source/7zip/Common/MyWindows.h b/Source/7zip/Common/MyWindows.h index 02f8710..b3977d2 100755 --- a/Source/7zip/Common/MyWindows.h +++ b/Source/7zip/Common/MyWindows.h @@ -1,220 +1,220 @@ -/*
- * MyWindows.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __MYWINDOWS_H
-#define __MYWINDOWS_H
-
-#include "../../Platform.h"
-
-#ifdef _WIN32
-
-#include <windows.h>
-
-/*
-#define CHAR_PATH_SEPARATOR '\\'
-#define WCHAR_PATH_SEPARATOR L'\\'
-#define STRING_PATH_SEPARATOR "\\"
-#define WSTRING_PATH_SEPARATOR L"\\"
-*/
-
-#else
-
-/*
-#define CHAR_PATH_SEPARATOR '/'
-#define WCHAR_PATH_SEPARATOR L'/'
-#define STRING_PATH_SEPARATOR "/"
-#define WSTRING_PATH_SEPARATOR L"/"
-
-#include <stddef.h> // for wchar_t
-#include <string.h>
-*/
-#include "MyGuidDef.h"
-/*
-typedef char CHAR;
-typedef unsigned char UCHAR;
-
-#undef BYTE
-typedef unsigned char BYTE;
-
-typedef short SHORT;
-typedef unsigned short USHORT;
-
-#undef WORD
-typedef unsigned short WORD;
-typedef short VARIANT_BOOL;
-
-typedef int INT;
-typedef Int32 INT32;
-typedef unsigned int UINT;
-typedef UInt32 UINT32;
-typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit
-typedef UINT32 ULONG;
-
-#undef DWORD
-typedef UINT32 DWORD;
-
-typedef Int64 LONGLONG;
-typedef UInt64 ULONGLONG;
-
-typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER;
-typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER;
-
-typedef const CHAR *LPCSTR;
-typedef CHAR TCHAR;
-typedef const TCHAR *LPCTSTR;
-typedef wchar_t WCHAR;
-typedef WCHAR OLECHAR;
-typedef const WCHAR *LPCWSTR;
-typedef OLECHAR *BSTR;
-typedef const OLECHAR *LPCOLESTR;
-typedef OLECHAR *LPOLESTR;
-*/
-typedef struct _FILETIME
-{
- DWORD dwLowDateTime;
- DWORD dwHighDateTime;
-}FILETIME;
-
-#define HRESULT LONG
-#define FAILED(Status) ((HRESULT)(Status)<0)
-typedef ULONG PROPID;
-typedef LONG SCODE;
-
-#define S_OK ((HRESULT)0x00000000L)
-#define S_FALSE ((HRESULT)0x00000001L)
-#define E_NOTIMPL ((HRESULT)0x80004001L)
-#define E_NOINTERFACE ((HRESULT)0x80004002L)
-#define E_ABORT ((HRESULT)0x80004004L)
-#define E_FAIL ((HRESULT)0x80004005L)
-#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
-#define E_OUTOFMEMORY ((HRESULT)0x8007000EL)
-#define E_INVALIDARG ((HRESULT)0x80070057L)
-
-#ifdef _MSC_VER
-#define STDMETHODCALLTYPE __stdcall
-#else
-#define STDMETHODCALLTYPE
-#endif
-
-#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f
-#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
-#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
-#define STDMETHODIMP STDMETHODIMP_(HRESULT)
-
-#define PURE = 0
-
-#define MIDL_INTERFACE(x) struct
-
-struct IUnknown
-{
- STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
- STDMETHOD_(ULONG, AddRef)() PURE;
- STDMETHOD_(ULONG, Release)() PURE;
-};
-
-typedef IUnknown *LPUNKNOWN;
-
-#define VARIANT_TRUE ((VARIANT_BOOL)-1)
-#define VARIANT_FALSE ((VARIANT_BOOL)0)
-
-enum VARENUM
-{
- VT_EMPTY = 0,
- VT_NULL = 1,
- VT_I2 = 2,
- VT_I4 = 3,
- VT_R4 = 4,
- VT_R8 = 5,
- VT_CY = 6,
- VT_DATE = 7,
- VT_BSTR = 8,
- VT_DISPATCH = 9,
- VT_ERROR = 10,
- VT_BOOL = 11,
- VT_VARIANT = 12,
- VT_UNKNOWN = 13,
- VT_DECIMAL = 14,
- VT_I1 = 16,
- VT_UI1 = 17,
- VT_UI2 = 18,
- VT_UI4 = 19,
- VT_I8 = 20,
- VT_UI8 = 21,
- VT_INT = 22,
- VT_UINT = 23,
- VT_VOID = 24,
- VT_HRESULT = 25,
- VT_FILETIME = 64
-};
-
-typedef unsigned short VARTYPE;
-typedef WORD PROPVAR_PAD1;
-typedef WORD PROPVAR_PAD2;
-typedef WORD PROPVAR_PAD3;
-
-typedef struct tagPROPVARIANT
-{
- VARTYPE vt;
- PROPVAR_PAD1 wReserved1;
- PROPVAR_PAD2 wReserved2;
- PROPVAR_PAD3 wReserved3;
- union
- {
- CHAR cVal;
- UCHAR bVal;
- SHORT iVal;
- USHORT uiVal;
- LONG lVal;
- ULONG ulVal;
- INT intVal;
- UINT uintVal;
- LARGE_INTEGER hVal;
- ULARGE_INTEGER uhVal;
- VARIANT_BOOL boolVal;
- SCODE scode;
- FILETIME filetime;
- BSTR bstrVal;
- };
-} PROPVARIANT;
-
-typedef PROPVARIANT tagVARIANT;
-typedef tagVARIANT VARIANT;
-typedef VARIANT VARIANTARG;
-
-MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
-MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
-MY_EXTERN_C void SysFreeString(BSTR bstr);
-MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);
-MY_EXTERN_C UINT SysStringLen(BSTR bstr);
-
-MY_EXTERN_C DWORD GetLastError();
-MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
-MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src);
-MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
-
-#define CP_ACP 0
-#define CP_OEMCP 1
-
-typedef enum tagSTREAM_SEEK
-{
- STREAM_SEEK_SET = 0,
- STREAM_SEEK_CUR = 1,
- STREAM_SEEK_END = 2
-} STREAM_SEEK;
-
-#endif
-#endif
+/* + * MyWindows.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __MYWINDOWS_H +#define __MYWINDOWS_H + +#include "../../Platform.h" + +#ifdef _WIN32 + +#include <windows.h> + +/* +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" +*/ + +#else + +/* +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#include <stddef.h> // for wchar_t +#include <string.h> +*/ +#include "MyGuidDef.h" +/* +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; +typedef short VARIANT_BOOL; + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; +typedef OLECHAR *BSTR; +typedef const OLECHAR *LPCOLESTR; +typedef OLECHAR *LPOLESTR; +*/ +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +}FILETIME; + +#define HRESULT LONG +#define FAILED(Status) ((HRESULT)(Status)<0) +typedef ULONG PROPID; +typedef LONG SCODE; + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOINTERFACE ((HRESULT)0x80004002L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) + +#ifdef _MSC_VER +#define STDMETHODCALLTYPE __stdcall +#else +#define STDMETHODCALLTYPE +#endif + +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0 + +#define MIDL_INTERFACE(x) struct + +struct IUnknown +{ + STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; +}; + +typedef IUnknown *LPUNKNOWN; + +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +enum VARENUM +{ + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_FILETIME = 64 +}; + +typedef unsigned short VARTYPE; +typedef WORD PROPVAR_PAD1; +typedef WORD PROPVAR_PAD2; +typedef WORD PROPVAR_PAD3; + +typedef struct tagPROPVARIANT +{ + VARTYPE vt; + PROPVAR_PAD1 wReserved1; + PROPVAR_PAD2 wReserved2; + PROPVAR_PAD3 wReserved3; + union + { + CHAR cVal; + UCHAR bVal; + SHORT iVal; + USHORT uiVal; + LONG lVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + SCODE scode; + FILETIME filetime; + BSTR bstrVal; + }; +} PROPVARIANT; + +typedef PROPVARIANT tagVARIANT; +typedef tagVARIANT VARIANT; +typedef VARIANT VARIANTARG; + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); + +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); + +#define CP_ACP 0 +#define CP_OEMCP 1 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + +#endif +#endif diff --git a/Source/7zip/Common/StdAfx.h b/Source/7zip/Common/StdAfx.h index af02b27..d83e5c0 100755 --- a/Source/7zip/Common/StdAfx.h +++ b/Source/7zip/Common/StdAfx.h @@ -1,23 +1,23 @@ -/*
- * StdAfx.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __STDAFX_H
-#define __STDAFX_H
-
-// #include "MyWindows.h"
-
-#endif
+/* + * StdAfx.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __STDAFX_H +#define __STDAFX_H + +// #include "MyWindows.h" + +#endif diff --git a/Source/7zip/Common/Types.h b/Source/7zip/Common/Types.h index 10791e4..4e28bf4 100755 --- a/Source/7zip/Common/Types.h +++ b/Source/7zip/Common/Types.h @@ -1,72 +1,72 @@ -/*
- * Types.h
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMMON_TYPES_H
-#define __COMMON_TYPES_H
-
-#ifndef _7ZIP_BYTE_DEFINED
-#define _7ZIP_BYTE_DEFINED
-typedef unsigned char Byte;
-#endif
-
-#ifndef _7ZIP_INT16_DEFINED
-#define _7ZIP_INT16_DEFINED
-typedef short Int16;
-#endif
-
-#ifndef _7ZIP_UINT16_DEFINED
-#define _7ZIP_UINT16_DEFINED
-typedef unsigned short UInt16;
-#endif
-
-#ifndef _7ZIP_INT32_DEFINED
-#define _7ZIP_INT32_DEFINED
-typedef int Int32;
-#endif
-
-#ifndef _7ZIP_UINT32_DEFINED
-#define _7ZIP_UINT32_DEFINED
-typedef unsigned int UInt32;
-#endif
-
-#ifdef _MSC_VER
-
-#ifndef _7ZIP_INT64_DEFINED
-#define _7ZIP_INT64_DEFINED
-typedef __int64 Int64;
-#endif
-
-#ifndef _7ZIP_UINT64_DEFINED
-#define _7ZIP_UINT64_DEFINED
-typedef unsigned __int64 UInt64;
-#endif
-
-#else
-
-#ifndef _7ZIP_INT64_DEFINED
-#define _7ZIP_INT64_DEFINED
-typedef long long int Int64;
-#endif
-
-#ifndef _7ZIP_UINT64_DEFINED
-#define _7ZIP_UINT64_DEFINED
-typedef unsigned long long int UInt64;
-#endif
-
-#endif
-
-#endif
+/* + * Types.h + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2006 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_INT16_DEFINED +#define _7ZIP_INT16_DEFINED +typedef short Int16; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_INT32_DEFINED +#define _7ZIP_INT32_DEFINED +typedef int Int32; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +typedef unsigned int UInt32; +#endif + +#ifdef _MSC_VER + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED +typedef __int64 Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +typedef unsigned __int64 UInt64; +#endif + +#else + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED +typedef long long int Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +typedef unsigned long long int UInt64; +#endif + +#endif + +#endif diff --git a/Source/7zip/LZMADecode.c b/Source/7zip/LZMADecode.c index e16d4c0..8b8fe0a 100755 --- a/Source/7zip/LZMADecode.c +++ b/Source/7zip/LZMADecode.c @@ -1,546 +1,546 @@ -/*
- * LZMADecode.c
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2007 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include <stdlib.h>
-#include "LZMADecode.h"
-
-#define LEAVE { goto saveStateAndReturn; }
-#define NEED_BYTE(c) case c: if (!avail_in) { mode = c; LEAVE; }
-#define NEED_BYTE_ if (!avail_in) LEAVE;
-#define NEXT_BYTE (avail_in--, *next_in++)
-#define NEED_OUT(c) case c: if (!avail_out) { mode = c; LEAVE; }
-#define PUT_BYTE_(b) { *next_out = b; next_out++; avail_out--; }
-#define PUT_BYTE(b) { totalOut++; PUT_BYTE_(b) }
-#define DECODE_BIT(c, x) prob = x; last = c; goto _LZMA_C_RDBD; case c:
-#define DECODE_LEN(c, x) probs = x; last2 = c; goto _LZMA_C_LEND; case c:
-#define DECODE_BIT_TREE(c, x, y) probs = x; numLevels = y; last3 = c; goto _LZMA_C_BTD; case c:
-
-enum {
- /* 0 */ LZMA_C_INIT = 0,
- /* 1 */ LZMA_C_GETDICT,
- /* 2 */ LZMA_C_BLOCK,
- /* 3 */ LZMA_C_RDI, /* RangeDecoderInit */
- /* 4 */ LZMA_C_RDBD, /* RangeDecoderBitDecode */
- /* 5 */ LZMA_C_RDBD_IN, /* RangeDecoderBitDecode */
- /* 6 */ LZMA_C_TYPE,
- /* 7 */ LZMA_C_ISREP,
- /* 8 */ LZMA_C_ISREPG0,
- /* 9 */ LZMA_C_ISREP0LONG,
- /* 10 */ LZMA_C_ISREPG1,
- /* 11 */ LZMA_C_ISREPG2,
- /* 12 */ LZMA_C_NORM,
- /* 13 */ LZMA_C_LITDM1, /* LzmaLiteralDecodeMatch */
- /* 14 */ LZMA_C_LITDM2, /* LzmaLiteralDecodeMatch */
- /* 15 */ LZMA_C_LITD, /* LzmaLiteralDecode */
- /* 16 */ LZMA_C_RDRBTD, /* RangeDecoderReverseBitTreeDecode */
- /* 17 */ LZMA_C_LEND, /* LzmaLenDecode */
- /* 18 */ LZMA_C_LEND1, /* LzmaLenDecode */
- /* 19 */ LZMA_C_LEND2, /* LzmaLenDecode */
- /* 20 */ LZMA_C_LEND_RES, /* LzmaLenDecode */
- /* 21 */ LZMA_C_LEND_C1,
- /* 22 */ LZMA_C_LEND_C2,
- /* 23 */ LZMA_C_BTD, /* RangeDecoderBitTreeDecode */
- /* 24 */ LZMA_C_BTD_LOOP,
- /* 25 */ LZMA_C_BTD_C1,
- /* 26 */ LZMA_C_OUTPUT_1,
- /* 27 */ LZMA_C_OUTPUT_2,
- /* 28 */ LZMA_C_OUTPUT_3
-};
-
-#define kNumTopBits 24
-#define kTopValue ((UInt32)1 << kNumTopBits)
-
-#define kNumBitModelTotalBits 11
-#define kBitModelTotal (1 << kNumBitModelTotalBits)
-#define kNumMoveBits 5
-
-#define RC_NORMALIZE(c) if (range < kTopValue) { NEED_BYTE(c); range <<= 8; code = (code << 8) | NEXT_BYTE; }
-
-#define RC_GET_BIT2(c, prob, mi, A0, A1) { \
- UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
- if (code < bound) \
- { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
- else \
- { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
- RC_NORMALIZE(c) \
-}
-
-#define RC_GET_BIT(c, prob, mi) RC_GET_BIT2(c, prob, mi, ; , ;)
-
-#define kNumPosBitsMax 4
-#define kNumPosStatesMax (1 << kNumPosBitsMax)
-
-#define kLenNumLowBits 3
-#define kLenNumLowSymbols (1 << kLenNumLowBits)
-#define kLenNumMidBits 3
-#define kLenNumMidSymbols (1 << kLenNumMidBits)
-#define kLenNumHighBits 8
-#define kLenNumHighSymbols (1 << kLenNumHighBits)
-
-#define LenChoice 0
-#define LenChoice2 (LenChoice + 1)
-#define LenLow (LenChoice2 + 1)
-#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
-#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
-#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
-
-#define kNumStates 12
-
-#define kStartPosModelIndex 4
-#define kEndPosModelIndex 14
-#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
-
-#define kNumPosSlotBits 6
-#define kNumLenToPosStates 4
-
-#define kNumAlignBits 4
-#define kAlignTableSize (1 << kNumAlignBits)
-
-#define kMatchMinLen 2
-
-#define IsMatch 0
-#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
-#define IsRepG0 (IsRep + kNumStates)
-#define IsRepG1 (IsRepG0 + kNumStates)
-#define IsRepG2 (IsRepG1 + kNumStates)
-#define IsRep0Long (IsRepG2 + kNumStates)
-#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
-#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
-#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
-#define LenCoder (Align + kAlignTableSize)
-#define RepLenCoder (LenCoder + kNumLenProbs)
-#define Literal (RepLenCoder + kNumLenProbs)
-
-#define LZMA_BASE_SIZE 1846
-#define LZMA_LIT_SIZE 768
-
-#if Literal != LZMA_BASE_SIZE
-StopCompilingDueBUG
-#endif
-
-void LZMACALL lzmaInit(lzma_stream *s)
-{
- /* size of lzma_stream minus the size of the two allocated buffer pointers.
- we don't want to lose to pointer or else we won't be able to free them. */
- size_t i = sizeof(lzma_stream) - (sizeof(unsigned char *) * 2);
- while (i--)
- ((Byte *)s)[i] = 0;
-
- s->rep0 = s->rep1 = s->rep2 = s->rep3 = 1;
- s->range = (0xFFFFFFFF);
-}
-
-int LZMACALL lzmaDecode(lzma_stream *s)
-{
- /* restore decoder state */
- lzma_stream _s = *s;
-
-#define mode _s.mode
-#define last _s.last
-#define last2 _s.last2
-#define last3 _s.last3
-
-#define p (*(CProb **) &_s.dynamicData)
-#define dynamicDataSize _s.dynamicDataSize
-
-#define state _s.state
-#define isPreviousMatch _s.isPreviousMatch
-#define previousByte _s.previousByte
-#define rep0 _s.rep0
-#define rep1 _s.rep1
-#define rep2 _s.rep2
-#define rep3 _s.rep3
-#define lc _s.lc
-#define len _s.len
-#define totalOut _s.totalOut
-
-#define dictionary _s.dictionary
-#define dictionarySize _s.dictionarySize
-#define dictionaryPos _s.dictionaryPos
-
-#define posStateMask _s.posStateMask
-#define literalPosMask _s.literalPosMask
-
-#define avail_in _s.avail_in
-#define next_in _s.next_in
-#define avail_out _s.avail_out
-#define next_out _s.next_out
-
-#define range _s.range
-#define code _s.code
-
-#define probs _s.probs
-#define prob _s.prob
-
-#define symbol _s.temp2
-#define bit _s.temp3
-#define matchBit _s.temp1
-#define i _s.temp1
-#define result _s.temp2
-#define numLevels _s.temp3
-#define posSlot _s.temp2
-#define newDictionarySize (*(UInt32*) &_s.temp3)
-
-#define matchByte _s.matchByte
-#define mi _s.mi
-#define posState _s.posState
-
- if (len == -1)
- return LZMA_STREAM_END;
-
- for (;;) switch (mode)
- {
- case LZMA_C_INIT:
- {
- Byte firstByte;
- UInt32 newDynamicDataSize;
- UInt32 numProbs;
- int lp;
- int pb;
-
- NEED_BYTE_;
-
- firstByte = NEXT_BYTE;
-
- if (firstByte > (9*5*5))
- return LZMA_DATA_ERROR;
-
- pb = firstByte / (9*5);
- firstByte %= (9*5);
- lp = firstByte / 9;
- firstByte %= 9;
- lc = firstByte;
-
- posStateMask = (1 << (pb)) - 1;
- literalPosMask = (1 << (lp)) - 1;
-
- numProbs = Literal + (LZMA_LIT_SIZE << (lc + pb));
- newDynamicDataSize = numProbs * sizeof(CProb);
-
- if (newDynamicDataSize != dynamicDataSize)
- {
- if (p)
- lzmafree(p);
- p = lzmaalloc(newDynamicDataSize);
- if (!p)
- return LZMA_NOT_ENOUGH_MEM;
- dynamicDataSize = newDynamicDataSize;
- }
-
- while (numProbs--)
- p[numProbs] = kBitModelTotal >> 1;
-
- for (i = 0, newDictionarySize = 0; i < 4; i++)
- {
- NEED_BYTE(LZMA_C_GETDICT);
- newDictionarySize |= NEXT_BYTE << (i * 8);
- }
-
- if (newDictionarySize != dictionarySize)
- {
- dictionarySize = newDictionarySize;
- if (dictionary)
- lzmafree(dictionary);
- dictionary = lzmaalloc(dictionarySize);
- if (!dictionary)
- return LZMA_NOT_ENOUGH_MEM;
- }
-
- dictionary[dictionarySize - 1] = 0;
-
- i = 5;
- while (i--)
- {
- NEED_BYTE(LZMA_C_RDI);
- code = (code << 8) | NEXT_BYTE;
- }
- }
- case LZMA_C_BLOCK:
- posState = (int)(totalOut & posStateMask);
- DECODE_BIT(LZMA_C_TYPE, p + IsMatch + (state << kNumPosBitsMax) + posState);
- if (bit == 0)
- {
- probs = p + Literal + (LZMA_LIT_SIZE *
- (((totalOut & literalPosMask) << lc) + (previousByte >> (8 - lc))));
-
- if (state < 4) state = 0;
- else if (state < 10) state -= 3;
- else state -= 6;
- if (isPreviousMatch)
- {
- UInt32 pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- matchByte = dictionary[pos];
- {
- symbol = 1;
- do
- {
- matchBit = (matchByte >> 7) & 1;
- matchByte <<= 1;
- {
- prob = probs + ((1 + matchBit) << 8) + symbol;
- RC_GET_BIT2(LZMA_C_LITDM1, prob, symbol, bit = 0, bit = 1)
- }
- if (matchBit != bit)
- {
- while (symbol < 0x100)
- {
- prob = probs + symbol;
- RC_GET_BIT(LZMA_C_LITDM2, prob, symbol)
- }
- break;
- }
- }
- while (symbol < 0x100);
- previousByte = symbol;
- }
- isPreviousMatch = 0;
- }
- else
- {
- symbol = 1;
- do
- {
- prob = probs + symbol;
- RC_GET_BIT(LZMA_C_LITD, prob, symbol)
- }
- while (symbol < 0x100);
- previousByte = symbol;
- }
- NEED_OUT(LZMA_C_OUTPUT_1);
- PUT_BYTE(previousByte);
- dictionary[dictionaryPos] = previousByte;
- dictionaryPos = (dictionaryPos + 1) % dictionarySize;
- }
- /* bit == 1 */
- else
- {
- isPreviousMatch = 1;
- DECODE_BIT(LZMA_C_ISREP, p + IsRep + state);
- if (bit == 1)
- {
- DECODE_BIT(LZMA_C_ISREPG0, p + IsRepG0 + state);
- if (bit == 0)
- {
- DECODE_BIT(LZMA_C_ISREP0LONG, p + IsRep0Long + (state << kNumPosBitsMax) + posState);
- if (bit == 0)
- {
- UInt32 pos;
- if (totalOut == 0)
- return LZMA_DATA_ERROR;
- state = state < 7 ? 9 : 11;
- NEED_OUT(LZMA_C_OUTPUT_2);
- pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- previousByte = dictionary[pos];
- dictionary[dictionaryPos] = previousByte;
- dictionaryPos = (dictionaryPos + 1) % dictionarySize;
- PUT_BYTE(previousByte);
- mode = LZMA_C_BLOCK;
- break;
- }
- }
- else
- {
- UInt32 distance;
- DECODE_BIT(LZMA_C_ISREPG1, p + IsRepG1 + state);
- if (bit == 0)
- {
- distance = rep1;
- }
- else
- {
- DECODE_BIT(LZMA_C_ISREPG2, p + IsRepG2 + state);
- if (bit == 0)
- distance = rep2;
- else
- {
- distance = rep3;
- rep3 = rep2;
- }
- rep2 = rep1;
- }
- rep1 = rep0;
- rep0 = distance;
- }
- DECODE_LEN(LZMA_C_LEND_C1, p + RepLenCoder);
- state = state < 7 ? 8 : 11;
- }
- else
- {
- rep3 = rep2;
- rep2 = rep1;
- rep1 = rep0;
- state = state < 7 ? 7 : 10;
- DECODE_LEN(LZMA_C_LEND_C2, p + LenCoder);
- DECODE_BIT_TREE(
- LZMA_C_BTD_C1,
- p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits),
- kNumPosSlotBits
- );
- if (posSlot >= kStartPosModelIndex)
- {
- int numDirectBits = ((posSlot >> 1) - 1);
- rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
- if (posSlot < kEndPosModelIndex)
- {
- probs = p + SpecPos + rep0 - posSlot - 1;
- numLevels = numDirectBits;
- }
- else
- {
- int numTotalBits = numDirectBits - kNumAlignBits;
- result = 0;
- for (i = numTotalBits; i > 0; i--)
- {
- /* UInt32 t; */
- range >>= 1;
-
- result <<= 1;
- if (code >= range)
- {
- code -= range;
- result |= 1;
- }
- /*
- t = (code - range) >> 31;
- t &= 1;
- code -= range & (t - 1);
- result = (result + result) | (1 - t);
- */
- RC_NORMALIZE(LZMA_C_NORM)
- }
- rep0 += result << kNumAlignBits;
- probs = p + Align;
- numLevels = kNumAlignBits;
- }
- mi = 1;
- symbol = 0;
- for(i = 0; i < numLevels; i++)
- {
- prob = probs + mi;
- RC_GET_BIT2(LZMA_C_RDRBTD, prob, mi, ; , symbol |= (1 << i));
- }
- rep0 += symbol;
- }
- else
- rep0 = posSlot;
- rep0++;
- }
- if (rep0 == (UInt32)(0))
- {
- len = -1;
- LEAVE;
- }
- if (rep0 > totalOut)
- {
- return LZMA_DATA_ERROR;
- }
- len += kMatchMinLen;
- totalOut += len;
- do
- {
- UInt32 pos;
- NEED_OUT(LZMA_C_OUTPUT_3);
- pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- previousByte = dictionary[pos];
- dictionary[dictionaryPos] = previousByte;
- dictionaryPos = (dictionaryPos + 1) % dictionarySize;
- PUT_BYTE_(previousByte);
- len--;
- }
- while(len > 0);
- }
- mode = LZMA_C_BLOCK;
- break;
- case LZMA_C_RDBD:
- _LZMA_C_RDBD:
- {
- UInt32 bound = (range >> kNumBitModelTotalBits) * *prob;
- if (code < bound)
- {
- range = bound;
- *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
- bit = 0;
- }
- else
- {
- range -= bound;
- code -= bound;
- *prob -= (*prob) >> kNumMoveBits;
- bit = 1;
- }
- RC_NORMALIZE(LZMA_C_RDBD_IN);
- }
- mode = last;
- break;
- case LZMA_C_LEND:
- _LZMA_C_LEND:
- DECODE_BIT(LZMA_C_LEND1, probs + LenChoice);
- if (bit == 0)
- {
- len = 0;
- probs += LenLow + (posState << kLenNumLowBits);
- numLevels = kLenNumLowBits;
- }
- else {
- DECODE_BIT(LZMA_C_LEND2, probs + LenChoice2);
- if (bit == 0)
- {
- len = kLenNumLowSymbols;
- probs += + LenMid + (posState << kLenNumMidBits);
- numLevels = kLenNumMidBits;
- }
- else
- {
- len = kLenNumLowSymbols + kLenNumMidSymbols;
- probs += LenHigh;
- numLevels = kLenNumHighBits;
- }
- }
-
- last3 = LZMA_C_LEND_RES;
- case LZMA_C_BTD:
- _LZMA_C_BTD:
- mi = 1;
- for(i = numLevels; i > 0; i--)
- {
- prob = probs + mi;
- RC_GET_BIT(LZMA_C_BTD_LOOP, prob, mi)
- }
- result = mi - (1 << numLevels);
- mode = last3;
- break;
- case LZMA_C_LEND_RES:
- len += result;
- mode = last2;
- break;
- default:
- return LZMA_DATA_ERROR;
- }
-
-saveStateAndReturn:
-
- /* save decoder state */
- *s = _s;
-
- return LZMA_OK;
-}
+/* + * LZMADecode.c + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2007 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include <stdlib.h> +#include "LZMADecode.h" + +#define LEAVE { goto saveStateAndReturn; } +#define NEED_BYTE(c) case c: if (!avail_in) { mode = c; LEAVE; } +#define NEED_BYTE_ if (!avail_in) LEAVE; +#define NEXT_BYTE (avail_in--, *next_in++) +#define NEED_OUT(c) case c: if (!avail_out) { mode = c; LEAVE; } +#define PUT_BYTE_(b) { *next_out = b; next_out++; avail_out--; } +#define PUT_BYTE(b) { totalOut++; PUT_BYTE_(b) } +#define DECODE_BIT(c, x) prob = x; last = c; goto _LZMA_C_RDBD; case c: +#define DECODE_LEN(c, x) probs = x; last2 = c; goto _LZMA_C_LEND; case c: +#define DECODE_BIT_TREE(c, x, y) probs = x; numLevels = y; last3 = c; goto _LZMA_C_BTD; case c: + +enum { + /* 0 */ LZMA_C_INIT = 0, + /* 1 */ LZMA_C_GETDICT, + /* 2 */ LZMA_C_BLOCK, + /* 3 */ LZMA_C_RDI, /* RangeDecoderInit */ + /* 4 */ LZMA_C_RDBD, /* RangeDecoderBitDecode */ + /* 5 */ LZMA_C_RDBD_IN, /* RangeDecoderBitDecode */ + /* 6 */ LZMA_C_TYPE, + /* 7 */ LZMA_C_ISREP, + /* 8 */ LZMA_C_ISREPG0, + /* 9 */ LZMA_C_ISREP0LONG, + /* 10 */ LZMA_C_ISREPG1, + /* 11 */ LZMA_C_ISREPG2, + /* 12 */ LZMA_C_NORM, + /* 13 */ LZMA_C_LITDM1, /* LzmaLiteralDecodeMatch */ + /* 14 */ LZMA_C_LITDM2, /* LzmaLiteralDecodeMatch */ + /* 15 */ LZMA_C_LITD, /* LzmaLiteralDecode */ + /* 16 */ LZMA_C_RDRBTD, /* RangeDecoderReverseBitTreeDecode */ + /* 17 */ LZMA_C_LEND, /* LzmaLenDecode */ + /* 18 */ LZMA_C_LEND1, /* LzmaLenDecode */ + /* 19 */ LZMA_C_LEND2, /* LzmaLenDecode */ + /* 20 */ LZMA_C_LEND_RES, /* LzmaLenDecode */ + /* 21 */ LZMA_C_LEND_C1, + /* 22 */ LZMA_C_LEND_C2, + /* 23 */ LZMA_C_BTD, /* RangeDecoderBitTreeDecode */ + /* 24 */ LZMA_C_BTD_LOOP, + /* 25 */ LZMA_C_BTD_C1, + /* 26 */ LZMA_C_OUTPUT_1, + /* 27 */ LZMA_C_OUTPUT_2, + /* 28 */ LZMA_C_OUTPUT_3 +}; + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_NORMALIZE(c) if (range < kTopValue) { NEED_BYTE(c); range <<= 8; code = (code << 8) | NEXT_BYTE; } + +#define RC_GET_BIT2(c, prob, mi, A0, A1) { \ + UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ + if (code < bound) \ + { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ + else \ + { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ + RC_NORMALIZE(c) \ +} + +#define RC_GET_BIT(c, prob, mi) RC_GET_BIT2(c, prob, mi, ; , ;) + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +#define kNumStates 12 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +void LZMACALL lzmaInit(lzma_stream *s) +{ + /* size of lzma_stream minus the size of the two allocated buffer pointers. + we don't want to lose to pointer or else we won't be able to free them. */ + size_t i = sizeof(lzma_stream) - (sizeof(unsigned char *) * 2); + while (i--) + ((Byte *)s)[i] = 0; + + s->rep0 = s->rep1 = s->rep2 = s->rep3 = 1; + s->range = (0xFFFFFFFF); +} + +int LZMACALL lzmaDecode(lzma_stream *s) +{ + /* restore decoder state */ + lzma_stream _s = *s; + +#define mode _s.mode +#define last _s.last +#define last2 _s.last2 +#define last3 _s.last3 + +#define p (*(CProb **) &_s.dynamicData) +#define dynamicDataSize _s.dynamicDataSize + +#define state _s.state +#define isPreviousMatch _s.isPreviousMatch +#define previousByte _s.previousByte +#define rep0 _s.rep0 +#define rep1 _s.rep1 +#define rep2 _s.rep2 +#define rep3 _s.rep3 +#define lc _s.lc +#define len _s.len +#define totalOut _s.totalOut + +#define dictionary _s.dictionary +#define dictionarySize _s.dictionarySize +#define dictionaryPos _s.dictionaryPos + +#define posStateMask _s.posStateMask +#define literalPosMask _s.literalPosMask + +#define avail_in _s.avail_in +#define next_in _s.next_in +#define avail_out _s.avail_out +#define next_out _s.next_out + +#define range _s.range +#define code _s.code + +#define probs _s.probs +#define prob _s.prob + +#define symbol _s.temp2 +#define bit _s.temp3 +#define matchBit _s.temp1 +#define i _s.temp1 +#define result _s.temp2 +#define numLevels _s.temp3 +#define posSlot _s.temp2 +#define newDictionarySize (*(UInt32*) &_s.temp3) + +#define matchByte _s.matchByte +#define mi _s.mi +#define posState _s.posState + + if (len == -1) + return LZMA_STREAM_END; + + for (;;) switch (mode) + { + case LZMA_C_INIT: + { + Byte firstByte; + UInt32 newDynamicDataSize; + UInt32 numProbs; + int lp; + int pb; + + NEED_BYTE_; + + firstByte = NEXT_BYTE; + + if (firstByte > (9*5*5)) + return LZMA_DATA_ERROR; + + pb = firstByte / (9*5); + firstByte %= (9*5); + lp = firstByte / 9; + firstByte %= 9; + lc = firstByte; + + posStateMask = (1 << (pb)) - 1; + literalPosMask = (1 << (lp)) - 1; + + numProbs = Literal + (LZMA_LIT_SIZE << (lc + pb)); + newDynamicDataSize = numProbs * sizeof(CProb); + + if (newDynamicDataSize != dynamicDataSize) + { + if (p) + lzmafree(p); + p = lzmaalloc(newDynamicDataSize); + if (!p) + return LZMA_NOT_ENOUGH_MEM; + dynamicDataSize = newDynamicDataSize; + } + + while (numProbs--) + p[numProbs] = kBitModelTotal >> 1; + + for (i = 0, newDictionarySize = 0; i < 4; i++) + { + NEED_BYTE(LZMA_C_GETDICT); + newDictionarySize |= NEXT_BYTE << (i * 8); + } + + if (newDictionarySize != dictionarySize) + { + dictionarySize = newDictionarySize; + if (dictionary) + lzmafree(dictionary); + dictionary = lzmaalloc(dictionarySize); + if (!dictionary) + return LZMA_NOT_ENOUGH_MEM; + } + + dictionary[dictionarySize - 1] = 0; + + i = 5; + while (i--) + { + NEED_BYTE(LZMA_C_RDI); + code = (code << 8) | NEXT_BYTE; + } + } + case LZMA_C_BLOCK: + posState = (int)(totalOut & posStateMask); + DECODE_BIT(LZMA_C_TYPE, p + IsMatch + (state << kNumPosBitsMax) + posState); + if (bit == 0) + { + probs = p + Literal + (LZMA_LIT_SIZE * + (((totalOut & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + if (isPreviousMatch) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + { + symbol = 1; + do + { + matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + { + prob = probs + ((1 + matchBit) << 8) + symbol; + RC_GET_BIT2(LZMA_C_LITDM1, prob, symbol, bit = 0, bit = 1) + } + if (matchBit != bit) + { + while (symbol < 0x100) + { + prob = probs + symbol; + RC_GET_BIT(LZMA_C_LITDM2, prob, symbol) + } + break; + } + } + while (symbol < 0x100); + previousByte = symbol; + } + isPreviousMatch = 0; + } + else + { + symbol = 1; + do + { + prob = probs + symbol; + RC_GET_BIT(LZMA_C_LITD, prob, symbol) + } + while (symbol < 0x100); + previousByte = symbol; + } + NEED_OUT(LZMA_C_OUTPUT_1); + PUT_BYTE(previousByte); + dictionary[dictionaryPos] = previousByte; + dictionaryPos = (dictionaryPos + 1) % dictionarySize; + } + /* bit == 1 */ + else + { + isPreviousMatch = 1; + DECODE_BIT(LZMA_C_ISREP, p + IsRep + state); + if (bit == 1) + { + DECODE_BIT(LZMA_C_ISREPG0, p + IsRepG0 + state); + if (bit == 0) + { + DECODE_BIT(LZMA_C_ISREP0LONG, p + IsRep0Long + (state << kNumPosBitsMax) + posState); + if (bit == 0) + { + UInt32 pos; + if (totalOut == 0) + return LZMA_DATA_ERROR; + state = state < 7 ? 9 : 11; + NEED_OUT(LZMA_C_OUTPUT_2); + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + dictionaryPos = (dictionaryPos + 1) % dictionarySize; + PUT_BYTE(previousByte); + mode = LZMA_C_BLOCK; + break; + } + } + else + { + UInt32 distance; + DECODE_BIT(LZMA_C_ISREPG1, p + IsRepG1 + state); + if (bit == 0) + { + distance = rep1; + } + else + { + DECODE_BIT(LZMA_C_ISREPG2, p + IsRepG2 + state); + if (bit == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + DECODE_LEN(LZMA_C_LEND_C1, p + RepLenCoder); + state = state < 7 ? 8 : 11; + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < 7 ? 7 : 10; + DECODE_LEN(LZMA_C_LEND_C2, p + LenCoder); + DECODE_BIT_TREE( + LZMA_C_BTD_C1, + p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits), + kNumPosSlotBits + ); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + { + probs = p + SpecPos + rep0 - posSlot - 1; + numLevels = numDirectBits; + } + else + { + int numTotalBits = numDirectBits - kNumAlignBits; + result = 0; + for (i = numTotalBits; i > 0; i--) + { + /* UInt32 t; */ + range >>= 1; + + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + /* + t = (code - range) >> 31; + t &= 1; + code -= range & (t - 1); + result = (result + result) | (1 - t); + */ + RC_NORMALIZE(LZMA_C_NORM) + } + rep0 += result << kNumAlignBits; + probs = p + Align; + numLevels = kNumAlignBits; + } + mi = 1; + symbol = 0; + for(i = 0; i < numLevels; i++) + { + prob = probs + mi; + RC_GET_BIT2(LZMA_C_RDRBTD, prob, mi, ; , symbol |= (1 << i)); + } + rep0 += symbol; + } + else + rep0 = posSlot; + rep0++; + } + if (rep0 == (UInt32)(0)) + { + len = -1; + LEAVE; + } + if (rep0 > totalOut) + { + return LZMA_DATA_ERROR; + } + len += kMatchMinLen; + totalOut += len; + do + { + UInt32 pos; + NEED_OUT(LZMA_C_OUTPUT_3); + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + dictionaryPos = (dictionaryPos + 1) % dictionarySize; + PUT_BYTE_(previousByte); + len--; + } + while(len > 0); + } + mode = LZMA_C_BLOCK; + break; + case LZMA_C_RDBD: + _LZMA_C_RDBD: + { + UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; + if (code < bound) + { + range = bound; + *prob += (kBitModelTotal - *prob) >> kNumMoveBits; + bit = 0; + } + else + { + range -= bound; + code -= bound; + *prob -= (*prob) >> kNumMoveBits; + bit = 1; + } + RC_NORMALIZE(LZMA_C_RDBD_IN); + } + mode = last; + break; + case LZMA_C_LEND: + _LZMA_C_LEND: + DECODE_BIT(LZMA_C_LEND1, probs + LenChoice); + if (bit == 0) + { + len = 0; + probs += LenLow + (posState << kLenNumLowBits); + numLevels = kLenNumLowBits; + } + else { + DECODE_BIT(LZMA_C_LEND2, probs + LenChoice2); + if (bit == 0) + { + len = kLenNumLowSymbols; + probs += + LenMid + (posState << kLenNumMidBits); + numLevels = kLenNumMidBits; + } + else + { + len = kLenNumLowSymbols + kLenNumMidSymbols; + probs += LenHigh; + numLevels = kLenNumHighBits; + } + } + + last3 = LZMA_C_LEND_RES; + case LZMA_C_BTD: + _LZMA_C_BTD: + mi = 1; + for(i = numLevels; i > 0; i--) + { + prob = probs + mi; + RC_GET_BIT(LZMA_C_BTD_LOOP, prob, mi) + } + result = mi - (1 << numLevels); + mode = last3; + break; + case LZMA_C_LEND_RES: + len += result; + mode = last2; + break; + default: + return LZMA_DATA_ERROR; + } + +saveStateAndReturn: + + /* save decoder state */ + *s = _s; + + return LZMA_OK; +} diff --git a/Source/7zip/LZMADecode.h b/Source/7zip/LZMADecode.h index dddf709..fd87af7 100755 --- a/Source/7zip/LZMADecode.h +++ b/Source/7zip/LZMADecode.h @@ -1,138 +1,138 @@ -/*
- * LZMADecode.c
- *
- * This file is a part of LZMA compression module for NSIS.
- *
- * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
- * Modifications Copyright (C) 2003-2007 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the Common Public License version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __LZMADECODE_H
-#define __LZMADECODE_H
-
-/***********************
- * Configuration *
- ***********************/
-
-#include "../Platform.h"
-
-/* #define _LZMA_PROB32 */
-/* It can increase speed on some 32-bit CPUs,
- but memory usage will be doubled in that case */
-
-#ifdef _WIN32
-# define lzmaalloc(bytes) GlobalAlloc(GPTR,bytes)
-# define lzmafree GlobalFree
-#endif
-
-/***********************
- * Configuration End *
- ***********************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef lzmaalloc
-#define lzmaalloc malloc
-#endif
-
-#ifndef lzmafree
-#define lzmafree free
-#endif
-
-#ifndef LZMACALL
-# define LZMACALL
-#endif
-
-#ifndef UInt32
-#ifdef _LZMA_UINT32_IS_ULONG
-#define UInt32 unsigned long
-#else
-#define UInt32 unsigned int
-#endif
-#endif
-
-#ifdef _LZMA_PROB32
-#define CProb UInt32
-#else
-#define CProb unsigned short
-#endif
-
-typedef unsigned char Byte;
-
-#define LZMA_STREAM_END 1
-#define LZMA_OK 0
-#define LZMA_DATA_ERROR -1
-/* we don't really care what the problem is... */
-/* #define LZMA_RESULT_NOT_ENOUGH_MEM -2 */
-#define LZMA_NOT_ENOUGH_MEM -1
-
-typedef struct
-{
- /* mode control */
- int mode;
- int last;
- int last2;
- int last3;
-
- /* properties */
- UInt32 dynamicDataSize;
- UInt32 dictionarySize;
-
- /* io */
- Byte *next_in; /* next input byte */
- UInt32 avail_in; /* number of bytes available at next_in */
-
- Byte *next_out; /* next output byte should be put there */
- UInt32 avail_out; /* remaining free space at next_out */
-
- UInt32 totalOut; /* total output - not always correct when lzmaDecode returns */
-
- /* saved state */
- Byte previousByte;
- Byte matchByte;
- CProb *probs;
- CProb *prob;
- int mi;
- int posState;
- int temp1;
- int temp2;
- int temp3;
- int lc;
- int state;
- int isPreviousMatch;
- int len;
- UInt32 rep0;
- UInt32 rep1;
- UInt32 rep2;
- UInt32 rep3;
- UInt32 posStateMask;
- UInt32 literalPosMask;
- UInt32 dictionaryPos;
-
- /* range coder */
- UInt32 range;
- UInt32 code;
-
- /* allocated buffers */
- Byte *dictionary;
- Byte *dynamicData;
-} lzma_stream;
-
-void LZMACALL lzmaInit(lzma_stream *);
-int LZMACALL lzmaDecode(lzma_stream *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* + * LZMADecode.c + * + * This file is a part of LZMA compression module for NSIS. + * + * Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov + * Modifications Copyright (C) 2003-2007 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the Common Public License version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +/*********************** + * Configuration * + ***********************/ + +#include "../Platform.h" + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +#ifdef _WIN32 +# define lzmaalloc(bytes) GlobalAlloc(GPTR,bytes) +# define lzmafree GlobalFree +#endif + +/*********************** + * Configuration End * + ***********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef lzmaalloc +#define lzmaalloc malloc +#endif + +#ifndef lzmafree +#define lzmafree free +#endif + +#ifndef LZMACALL +# define LZMACALL +#endif + +#ifndef UInt32 +#ifdef _LZMA_UINT32_IS_ULONG +#define UInt32 unsigned long +#else +#define UInt32 unsigned int +#endif +#endif + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb unsigned short +#endif + +typedef unsigned char Byte; + +#define LZMA_STREAM_END 1 +#define LZMA_OK 0 +#define LZMA_DATA_ERROR -1 +/* we don't really care what the problem is... */ +/* #define LZMA_RESULT_NOT_ENOUGH_MEM -2 */ +#define LZMA_NOT_ENOUGH_MEM -1 + +typedef struct +{ + /* mode control */ + int mode; + int last; + int last2; + int last3; + + /* properties */ + UInt32 dynamicDataSize; + UInt32 dictionarySize; + + /* io */ + Byte *next_in; /* next input byte */ + UInt32 avail_in; /* number of bytes available at next_in */ + + Byte *next_out; /* next output byte should be put there */ + UInt32 avail_out; /* remaining free space at next_out */ + + UInt32 totalOut; /* total output - not always correct when lzmaDecode returns */ + + /* saved state */ + Byte previousByte; + Byte matchByte; + CProb *probs; + CProb *prob; + int mi; + int posState; + int temp1; + int temp2; + int temp3; + int lc; + int state; + int isPreviousMatch; + int len; + UInt32 rep0; + UInt32 rep1; + UInt32 rep2; + UInt32 rep3; + UInt32 posStateMask; + UInt32 literalPosMask; + UInt32 dictionaryPos; + + /* range coder */ + UInt32 range; + UInt32 code; + + /* allocated buffers */ + Byte *dictionary; + Byte *dynamicData; +} lzma_stream; + +void LZMACALL lzmaInit(lzma_stream *); +int LZMACALL lzmaDecode(lzma_stream *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Source/7zip/sdk.diff b/Source/7zip/sdk.diff index 3390ad0..647ed11 100755 --- a/Source/7zip/sdk.diff +++ b/Source/7zip/sdk.diff @@ -1,167 +1,167 @@ -Only in 7zip: 7zGuids.cpp
-Only in 7zip-orig/7zip: Archive
-Only in 7zip/7zip: CVS
-Only in 7zip/7zip/Common: CVS
-Only in 7zip-orig/7zip/Common: FileStreams.cpp
-Only in 7zip-orig/7zip/Common: FileStreams.h
-diff -ru 7zip-orig/7zip/Common/StdAfx.h 7zip/7zip/Common/StdAfx.h
---- 7zip-orig/7zip/Common/StdAfx.h Mon Jul 11 15:14:54 2005
-+++ 7zip/7zip/Common/StdAfx.h Mon Oct 16 10:39:10 2006
-@@ -4,6 +4,5 @@
- #define __STDAFX_H
-
- #include "../../Common/MyWindows.h"
--#include "../../Common/NewHandler.h"
-
- #endif
-Only in 7zip-orig/7zip/Compress: Branch
-Only in 7zip/7zip/Compress: CVS
-Only in 7zip/7zip/Compress/LZ/BinTree: BinTree3ZMain.h
-Only in 7zip/7zip/Compress/LZ/BinTree: BinTree4b.h
-Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMF.h
-Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMFMain.h
-Only in 7zip/7zip/Compress/LZ/BinTree: CVS
-Only in 7zip/7zip/Compress/LZ: CVS
-Only in 7zip-orig/7zip/Compress/LZ: HashChain
-Only in 7zip/7zip/Compress/LZMA: CVS
-Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.cpp
-Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.h
-diff -ru 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp
---- 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp Sat May 20 08:23:48 2006
-+++ 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp Mon Oct 16 10:26:43 2006
-@@ -55,13 +55,13 @@
- kHC4
- };
-
--static const wchar_t *kMatchFinderIDs[] =
-+/*static const wchar_t *kMatchFinderIDs[] =
- {
- L"BT2",
- L"BT3",
- L"BT4",
- L"HC4"
--};
-+};*/
-
- Byte g_FastPos[1 << 11];
-
-@@ -318,7 +318,7 @@
- return S_OK;
- }
-
--static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
-+/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
- {
- while (true)
- {
-@@ -340,7 +340,7 @@
- if (AreStringsEqual(kMatchFinderIDs[m], s))
- return m;
- return -1;
--}
-+}*/
-
- STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
- const PROPVARIANT *properties, UInt32 numProperties)
-@@ -378,7 +378,8 @@
- }
- case NCoderPropID::kMatchFinder:
- {
-- if (prop.vt != VT_BSTR)
-+ return E_NOTIMPL;
-+ /*if (prop.vt != VT_BSTR)
- return E_INVALIDARG;
- int matchFinderIndexPrev = _matchFinderIndex;
- int m = FindMatchFinder(prop.bstrVal);
-@@ -390,7 +391,7 @@
- _dictionarySizePrev = (UInt32)-1;
- ReleaseMatchFinder();
- }
-- break;
-+ break;*/
- }
- #ifdef COMPRESS_MF_MT
- case NCoderPropID::kMultiThread:
-Only in 7zip-orig/7zip/Compress: LZMA_Alone
-Only in 7zip-orig/7zip/Compress: LZMA_C
-Only in 7zip/7zip/Compress/RangeCoder: CVS
-Only in 7zip: CVS
-Only in 7zip/Common: CVS
-Only in 7zip-orig/Common: C_FileIO.cpp
-Only in 7zip-orig/Common: C_FileIO.h
-Only in 7zip-orig/Common: ComTry.h
-Only in 7zip-orig/Common: CommandLineParser.cpp
-Only in 7zip-orig/Common: CommandLineParser.h
-Only in 7zip-orig/Common: MyInitGuid.h
-diff -ru 7zip-orig/Common/MyWindows.h 7zip/Common/MyWindows.h
---- 7zip-orig/Common/MyWindows.h Sun Apr 16 16:53:43 2006
-+++ 7zip/Common/MyWindows.h Mon Oct 16 10:20:04 2006
-@@ -3,17 +3,22 @@
- #ifndef __MYWINDOWS_H
- #define __MYWINDOWS_H
-
-+#include "../../Platform.h"
-+
- #ifdef _WIN32
-
- #include <windows.h>
-
-+/*
- #define CHAR_PATH_SEPARATOR '\\'
- #define WCHAR_PATH_SEPARATOR L'\\'
- #define STRING_PATH_SEPARATOR "\\"
- #define WSTRING_PATH_SEPARATOR L"\\"
-+*/
-
- #else
-
-+/*
- #define CHAR_PATH_SEPARATOR '/'
- #define WCHAR_PATH_SEPARATOR L'/'
- #define STRING_PATH_SEPARATOR "/"
-@@ -21,9 +26,9 @@
-
- #include <stddef.h> // for wchar_t
- #include <string.h>
--
-+*/
- #include "MyGuidDef.h"
--
-+/*
- typedef char CHAR;
- typedef unsigned char UCHAR;
-
-@@ -62,7 +67,7 @@
- typedef OLECHAR *BSTR;
- typedef const OLECHAR *LPCOLESTR;
- typedef OLECHAR *LPOLESTR;
--
-+*/
- typedef struct _FILETIME
- {
- DWORD dwLowDateTime;
-Only in 7zip-orig/Common: NewHandler.cpp
-Only in 7zip-orig/Common: NewHandler.h
-diff -ru 7zip-orig/Common/StdAfx.h 7zip/Common/StdAfx.h
---- 7zip-orig/Common/StdAfx.h Mon Jul 11 15:16:00 2005
-+++ 7zip/Common/StdAfx.h Mon Oct 16 10:39:16 2006
-@@ -4,6 +4,5 @@
- #define __STDAFX_H
-
- // #include "MyWindows.h"
--#include "NewHandler.h"
-
- #endif
-Only in 7zip-orig/Common: String.cpp
-Only in 7zip-orig/Common: String.h
-Only in 7zip-orig/Common: StringConvert.cpp
-Only in 7zip-orig/Common: StringConvert.h
-Only in 7zip-orig/Common: StringToInt.cpp
-Only in 7zip-orig/Common: StringToInt.h
-Only in 7zip-orig/Common: Vector.cpp
-Only in 7zip-orig/Common: Vector.h
-Only in 7zip: LZMADecode.c
-Only in 7zip: LZMADecode.h
-Only in 7zip-orig: Windows
-Only in 7zip: copying.txt
-Only in 7zip: readme.txt
+Only in 7zip: 7zGuids.cpp +Only in 7zip-orig/7zip: Archive +Only in 7zip/7zip: CVS +Only in 7zip/7zip/Common: CVS +Only in 7zip-orig/7zip/Common: FileStreams.cpp +Only in 7zip-orig/7zip/Common: FileStreams.h +diff -ru 7zip-orig/7zip/Common/StdAfx.h 7zip/7zip/Common/StdAfx.h +--- 7zip-orig/7zip/Common/StdAfx.h Mon Jul 11 15:14:54 2005 ++++ 7zip/7zip/Common/StdAfx.h Mon Oct 16 10:39:10 2006 +@@ -4,6 +4,5 @@ + #define __STDAFX_H + + #include "../../Common/MyWindows.h" +-#include "../../Common/NewHandler.h" + + #endif +Only in 7zip-orig/7zip/Compress: Branch +Only in 7zip/7zip/Compress: CVS +Only in 7zip/7zip/Compress/LZ/BinTree: BinTree3ZMain.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTree4b.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMF.h +Only in 7zip/7zip/Compress/LZ/BinTree: BinTreeMFMain.h +Only in 7zip/7zip/Compress/LZ/BinTree: CVS +Only in 7zip/7zip/Compress/LZ: CVS +Only in 7zip-orig/7zip/Compress/LZ: HashChain +Only in 7zip/7zip/Compress/LZMA: CVS +Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.cpp +Only in 7zip-orig/7zip/Compress/LZMA: LZMADecoder.h +diff -ru 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp +--- 7zip-orig/7zip/Compress/LZMA/LZMAEncoder.cpp Sat May 20 08:23:48 2006 ++++ 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp Mon Oct 16 10:26:43 2006 +@@ -55,13 +55,13 @@ + kHC4 + }; + +-static const wchar_t *kMatchFinderIDs[] = ++/*static const wchar_t *kMatchFinderIDs[] = + { + L"BT2", + L"BT3", + L"BT4", + L"HC4" +-}; ++};*/ + + Byte g_FastPos[1 << 11]; + +@@ -318,7 +318,7 @@ + return S_OK; + } + +-static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) ++/*static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) + { + while (true) + { +@@ -340,7 +340,7 @@ + if (AreStringsEqual(kMatchFinderIDs[m], s)) + return m; + return -1; +-} ++}*/ + + STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) +@@ -378,7 +378,8 @@ + } + case NCoderPropID::kMatchFinder: + { +- if (prop.vt != VT_BSTR) ++ return E_NOTIMPL; ++ /*if (prop.vt != VT_BSTR) + return E_INVALIDARG; + int matchFinderIndexPrev = _matchFinderIndex; + int m = FindMatchFinder(prop.bstrVal); +@@ -390,7 +391,7 @@ + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + } +- break; ++ break;*/ + } + #ifdef COMPRESS_MF_MT + case NCoderPropID::kMultiThread: +Only in 7zip-orig/7zip/Compress: LZMA_Alone +Only in 7zip-orig/7zip/Compress: LZMA_C +Only in 7zip/7zip/Compress/RangeCoder: CVS +Only in 7zip: CVS +Only in 7zip/Common: CVS +Only in 7zip-orig/Common: C_FileIO.cpp +Only in 7zip-orig/Common: C_FileIO.h +Only in 7zip-orig/Common: ComTry.h +Only in 7zip-orig/Common: CommandLineParser.cpp +Only in 7zip-orig/Common: CommandLineParser.h +Only in 7zip-orig/Common: MyInitGuid.h +diff -ru 7zip-orig/Common/MyWindows.h 7zip/Common/MyWindows.h +--- 7zip-orig/Common/MyWindows.h Sun Apr 16 16:53:43 2006 ++++ 7zip/Common/MyWindows.h Mon Oct 16 10:20:04 2006 +@@ -3,17 +3,22 @@ + #ifndef __MYWINDOWS_H + #define __MYWINDOWS_H + ++#include "../../Platform.h" ++ + #ifdef _WIN32 + + #include <windows.h> + ++/* + #define CHAR_PATH_SEPARATOR '\\' + #define WCHAR_PATH_SEPARATOR L'\\' + #define STRING_PATH_SEPARATOR "\\" + #define WSTRING_PATH_SEPARATOR L"\\" ++*/ + + #else + ++/* + #define CHAR_PATH_SEPARATOR '/' + #define WCHAR_PATH_SEPARATOR L'/' + #define STRING_PATH_SEPARATOR "/" +@@ -21,9 +26,9 @@ + + #include <stddef.h> // for wchar_t + #include <string.h> +- ++*/ + #include "MyGuidDef.h" +- ++/* + typedef char CHAR; + typedef unsigned char UCHAR; + +@@ -62,7 +67,7 @@ + typedef OLECHAR *BSTR; + typedef const OLECHAR *LPCOLESTR; + typedef OLECHAR *LPOLESTR; +- ++*/ + typedef struct _FILETIME + { + DWORD dwLowDateTime; +Only in 7zip-orig/Common: NewHandler.cpp +Only in 7zip-orig/Common: NewHandler.h +diff -ru 7zip-orig/Common/StdAfx.h 7zip/Common/StdAfx.h +--- 7zip-orig/Common/StdAfx.h Mon Jul 11 15:16:00 2005 ++++ 7zip/Common/StdAfx.h Mon Oct 16 10:39:16 2006 +@@ -4,6 +4,5 @@ + #define __STDAFX_H + + // #include "MyWindows.h" +-#include "NewHandler.h" + + #endif +Only in 7zip-orig/Common: String.cpp +Only in 7zip-orig/Common: String.h +Only in 7zip-orig/Common: StringConvert.cpp +Only in 7zip-orig/Common: StringConvert.h +Only in 7zip-orig/Common: StringToInt.cpp +Only in 7zip-orig/Common: StringToInt.h +Only in 7zip-orig/Common: Vector.cpp +Only in 7zip-orig/Common: Vector.h +Only in 7zip: LZMADecode.c +Only in 7zip: LZMADecode.h +Only in 7zip-orig: Windows +Only in 7zip: copying.txt +Only in 7zip: readme.txt diff --git a/Source/DialogTemplate.cpp b/Source/DialogTemplate.cpp index 099bfee..0ece79d 100755 --- a/Source/DialogTemplate.cpp +++ b/Source/DialogTemplate.cpp @@ -1,654 +1,654 @@ -/*
- * DialogTemplate.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "DialogTemplate.h"
-#include "winchar.h"
-#include <cassert> // for assert(3)
-#ifndef _WIN32
-# include "util.h" // for Unicode conversion functions
-# include <stdio.h>
-# include <stdlib.h>
-# include <iconv.h>
-# include <errno.h>
-#endif
-
-using namespace std;
-
-//////////////////////////////////////////////////////////////////////
-// Utilities
-//////////////////////////////////////////////////////////////////////
-
-static inline DWORD ConvertEndianness(DWORD d) {
- return FIX_ENDIAN_INT32(d);
-}
-
-static inline WORD ConvertEndianness(WORD w) {
- return FIX_ENDIAN_INT16(w);
-}
-
-static inline short ConvertEndianness(short s) {
- return ConvertEndianness(WORD(s));
-}
-
-#define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn
-
-// Reads a variant length array from seeker into readInto and advances seeker
-void ReadVarLenArr(LPBYTE &seeker, WCHAR* &readInto, unsigned int uCodePage) {
- WORD* arr = (WORD*)seeker;
- switch (ConvertEndianness(arr[0])) {
- case 0x0000:
- readInto = 0;
- seeker += sizeof(WORD);
- break;
- case 0xFFFF:
- readInto = MAKEINTRESOURCEW(ConvertEndianness(arr[1]));
- seeker += 2*sizeof(WORD);
- break;
- default:
- {
- readInto = winchar_strdup((WCHAR *) arr);
- PWCHAR wseeker = PWCHAR(seeker);
- while (*wseeker++);
- seeker = LPBYTE(wseeker);
- }
- 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 = ConvertEndianness(WORD(DWORD(x))); \
- seeker += sizeof(WORD); \
- } \
- else { \
- winchar_strcpy((WCHAR *) seeker, x); \
- seeker += winchar_strlen((WCHAR *) seeker) * sizeof(WCHAR) + 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) : (winchar_strlen(x) + 1) * sizeof(WCHAR)) : sizeof(WORD)
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-CDialogTemplate::CDialogTemplate(BYTE* pbData, unsigned int uCodePage) {
- m_uCodePage = uCodePage;
-
- m_dwHelpId = 0;
- m_szClass = 0;
- m_szFont = 0;
- m_sFontSize = 0;
- m_sFontWeight = 0;
- m_bItalic = 0;
- m_bCharset = 0;
- m_szMenu = 0;
- m_szTitle = 0;
-
- WORD wItems = 0;
-
- if (*(DWORD*)pbData == EXTENDED_DIALOG) { // Extended dialog template signature
- m_bExtended = true;
-
- DLGTEMPLATEEX* dTemplateEx = (DLGTEMPLATEEX*)pbData;
-
- m_dwHelpId = ConvertEndianness(dTemplateEx->helpID);
- m_dwStyle = ConvertEndianness(dTemplateEx->style);
- m_dwExtStyle = ConvertEndianness(dTemplateEx->exStyle);
- m_sX = ConvertEndianness(dTemplateEx->x);
- m_sY = ConvertEndianness(dTemplateEx->y);
- m_sWidth = ConvertEndianness(dTemplateEx->cx);
- m_sHeight = ConvertEndianness(dTemplateEx->cy);
-
- wItems = ConvertEndianness(dTemplateEx->cDlgItems);
- }
- else {
- m_bExtended = false;
-
- DLGTEMPLATE* dTemplate = (DLGTEMPLATE*)pbData;
-
- m_dwStyle = ConvertEndianness(dTemplate->style);
- m_dwExtStyle = ConvertEndianness(dTemplate->dwExtendedStyle);
- m_sX = ConvertEndianness(dTemplate->x);
- m_sY = ConvertEndianness(dTemplate->y);
- m_sWidth = ConvertEndianness(dTemplate->cx);
- m_sHeight = ConvertEndianness(dTemplate->cy);
-
- wItems = ConvertEndianness(dTemplate->cdit);
- }
-
- BYTE* seeker = pbData + (m_bExtended ? sizeof(DLGTEMPLATEEX) : sizeof(DLGTEMPLATE));
-
- // Read menu variant length array
- ReadVarLenArr(seeker, m_szMenu, m_uCodePage);
- // Read class variant length array
- ReadVarLenArr(seeker, m_szClass, m_uCodePage);
- // Read title variant length array
- ReadVarLenArr(seeker, m_szTitle, m_uCodePage);
- // Read font size and variant length array (only if style DS_SETFONT is used!)
- if (m_dwStyle & DS_SETFONT) {
- m_sFontSize = ConvertEndianness(*(short*)seeker);
- seeker += sizeof(short);
- if (m_bExtended) {
- m_sFontWeight = ConvertEndianness(*(short*)seeker);
- seeker += sizeof(short);
- m_bItalic = *(BYTE*)seeker;
- seeker += sizeof(BYTE);
- m_bCharset = *(BYTE*)seeker;
- seeker += sizeof(BYTE);
- }
- ReadVarLenArr(seeker, m_szFont, m_uCodePage);
- }
-
- // Read items
- for (int i = 0; i < wItems; i++) {
- // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary
- 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 = ConvertEndianness(rawItem->helpID);
- item->dwStyle = ConvertEndianness(rawItem->style);
- item->dwExtStyle = ConvertEndianness(rawItem->exStyle);
- item->sX = ConvertEndianness(rawItem->x);
- item->sY = ConvertEndianness(rawItem->y);
- item->sWidth = ConvertEndianness(rawItem->cx);
- item->sHeight = ConvertEndianness(rawItem->cy);
- item->wId = ConvertEndianness(rawItem->id);
-
- seeker += sizeof(DLGITEMTEMPLATEEX);
- }
- else {
- DLGITEMTEMPLATE* rawItem = (DLGITEMTEMPLATE*)seeker;
-
- item->dwHelpId = 0;
- item->dwStyle = ConvertEndianness(rawItem->style);
- item->dwExtStyle = ConvertEndianness(rawItem->dwExtendedStyle);
- item->sX = ConvertEndianness(rawItem->x);
- item->sY = ConvertEndianness(rawItem->y);
- item->sWidth = ConvertEndianness(rawItem->cx);
- item->sHeight = ConvertEndianness(rawItem->cy);
- item->wId = ConvertEndianness(rawItem->id);
-
- seeker += sizeof(DLGITEMTEMPLATE);
- }
-
- // Read class variant length array
- ReadVarLenArr(seeker, item->szClass, m_uCodePage);
- // Read title variant length array
- ReadVarLenArr(seeker, item->szTitle, m_uCodePage);
-
- // Read creation data variant length array
- // First read the size of the array (no null termination)
- item->wCreateDataSize = ConvertEndianness(*(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_szFont;
-
- for (unsigned 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 the width of the dialog
-short CDialogTemplate::GetWidth() {
- return m_sWidth;
-}
-
-// Returns the height of the dialog
-short CDialogTemplate::GetHeight() {
- return m_sHeight;
-}
-
-// Returns info about the item with the id wId
-DialogItemTemplate* CDialogTemplate::GetItem(WORD wId) {
- for (unsigned 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
-// Returns 1 if removed, 0 otherwise
-int CDialogTemplate::RemoveItem(WORD wId) {
- for (unsigned int i = 0; i < m_vItems.size(); i++) {
- if (m_vItems[i]->wId == wId) {
- m_vItems.erase(m_vItems.begin() + i);
- return 1;
- }
- }
- return 0;
-}
-
-// Sets the font of the dialog
-void CDialogTemplate::SetFont(char* szFaceName, WORD wFontSize) {
- if (strcmp(szFaceName, "MS Shell Dlg")) {
- // not MS Shell Dlg
- m_dwStyle &= ~DS_SHELLFONT;
- }
- else {
- // MS Shell Dlg
- m_dwStyle |= DS_SHELLFONT;
- }
- m_bCharset = DEFAULT_CHARSET;
- m_dwStyle |= DS_SETFONT;
- if (m_szFont) delete [] m_szFont;
- m_szFont = winchar_fromansi(szFaceName, m_uCodePage);
- 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 = winchar_strdup(item.szClass);
- }
- if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) {
- newItem->szTitle = winchar_strdup(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)
-void CDialogTemplate::MoveAll(short x, short y) {
- for (unsigned int i = 0; i < m_vItems.size(); i++) {
- m_vItems[i]->sX += x;
- m_vItems[i]->sY += y;
- }
-}
-
-// Resizes the dialog by (x,y)
-void CDialogTemplate::Resize(short x, short y) {
- m_sWidth += x;
- m_sHeight += y;
-}
-
-#ifdef _WIN32
-// Creates a dummy dialog that is used for converting units
-HWND CDialogTemplate::CreateDummyDialog() {
- 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!");
-
- return hDlg;
-}
-
-// Converts pixels to this dialog's units
-void CDialogTemplate::PixelsToDlgUnits(short& x, short& y) {
- HWND hDlg = CreateDummyDialog();
- RECT r = {0, 0, 10000, 10000};
- MapDialogRect(hDlg, &r);
- DestroyWindow(hDlg);
-
- x = short(float(x) / (float(r.right)/10000));
- y = short(float(y) / (float(r.bottom)/10000));
-}
-
-// Converts pixels to this dialog's units
-void CDialogTemplate::DlgUnitsToPixels(short& x, short& y) {
- HWND hDlg = CreateDummyDialog();
- RECT r = {0, 0, 10000, 10000};
- MapDialogRect(hDlg, &r);
- DestroyWindow(hDlg);
-
- x = short(float(x) * (float(r.right)/10000));
- y = short(float(y) * (float(r.bottom)/10000));
-}
-
-// Returns the size of a string in the dialog (in dialog units)
-SIZE CDialogTemplate::GetStringSize(WORD id, char *str) {
- HWND hDlg = CreateDummyDialog();
-
- LOGFONT f;
- GetObject((HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0), sizeof(LOGFONT), &f);
-
- HDC memDC = CreateCompatibleDC(GetDC(hDlg));
- HFONT font = CreateFontIndirect(&f);
- SelectObject(memDC, font);
-
- SIZE size;
- GetTextExtentPoint32(memDC, str, strlen(str), &size);
-
- DestroyWindow(hDlg);
- DeleteObject(font);
- DeleteDC(memDC);
-
- PixelsToDlgUnits((short&)size.cx, (short&)size.cy);
-
- return size;
-}
-
-// Trims the right margins of a control to fit a given text string size.
-void CDialogTemplate::RTrimToString(WORD id, char *str, int margins) {
- DialogItemTemplate* item = GetItem(id);
- if (!item) return;
-
- SIZE size = GetStringSize(id, str);
-
- size.cx += margins;
- size.cy += 2;
-
- item->sWidth = short(size.cx);
- item->sHeight = short(size.cy);
-}
-
-// Trims the left margins of a control to fit a given text string size.
-void CDialogTemplate::LTrimToString(WORD id, char *str, int margins) {
- DialogItemTemplate* item = GetItem(id);
- if (!item) return;
-
- SIZE size = GetStringSize(id, str);
-
- size.cx += margins;
- size.cy += 2;
-
- item->sX += item->sWidth - short(size.cx);
- item->sWidth = short(size.cx);
- item->sHeight = short(size.cy);
-}
-
-// Trims the left and right margins of a control to fit a given text string size.
-void CDialogTemplate::CTrimToString(WORD id, char *str, int margins) {
- DialogItemTemplate* item = GetItem(id);
- if (!item) return;
-
- SIZE size = GetStringSize(id, str);
-
- size.cx += margins;
- size.cy += 2;
-
- item->sX += item->sWidth/2 - short(size.cx/2);
- item->sWidth = short(size.cx);
- item->sHeight = short(size.cy);
-}
-#endif
-
-// Moves every item right and gives it the WS_EX_RIGHT extended style
-void CDialogTemplate::ConvertToRTL() {
- for (unsigned int i = 0; i < m_vItems.size(); i++) {
- bool addExStyle = false;
- char *szClass;
-
- if (IS_INTRESOURCE(m_vItems[i]->szClass))
- szClass = (char *) m_vItems[i]->szClass;
- else
- szClass = winchar_toansi(m_vItems[i]->szClass);
-
- // Button
- if (long(m_vItems[i]->szClass) == 0x80) {
- m_vItems[i]->dwStyle ^= BS_LEFTTEXT;
- m_vItems[i]->dwStyle ^= BS_RIGHT;
- m_vItems[i]->dwStyle ^= BS_LEFT;
-
- if ((m_vItems[i]->dwStyle & (BS_LEFT|BS_RIGHT)) == (BS_LEFT|BS_RIGHT)) {
- m_vItems[i]->dwStyle ^= BS_LEFT;
- m_vItems[i]->dwStyle ^= BS_RIGHT;
- if (m_vItems[i]->dwStyle & (BS_RADIOBUTTON|BS_CHECKBOX|BS_USERBUTTON)) {
- m_vItems[i]->dwStyle |= BS_RIGHT;
- }
- }
- }
- // Edit
- else if (long(m_vItems[i]->szClass) == 0x81) {
- if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) {
- m_vItems[i]->dwStyle ^= ES_RIGHT;
- }
- }
- // Static
- else if (long(m_vItems[i]->szClass) == 0x82) {
- if ((m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_LEFT || (m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_LEFTNOWORDWRAP)
- {
- m_vItems[i]->dwStyle &= ~SS_TYPEMASK;
- m_vItems[i]->dwStyle |= SS_RIGHT;
- }
- else if ((m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_ICON) {
- m_vItems[i]->dwStyle |= SS_CENTERIMAGE;
- }
- }
- else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "RichEdit20A")) {
- if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) {
- m_vItems[i]->dwStyle ^= ES_RIGHT;
- }
- }
- else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "SysTreeView32")) {
- m_vItems[i]->dwStyle |= TVS_RTLREADING;
- addExStyle = true;
- }
- else addExStyle = true;
-
- if (addExStyle)
- m_vItems[i]->dwExtStyle |= WS_EX_RIGHT;
-
- m_vItems[i]->dwExtStyle |= WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR;
-
- m_vItems[i]->sX = m_sWidth - m_vItems[i]->sWidth - m_vItems[i]->sX;
-
- if (!IS_INTRESOURCE(m_vItems[i]->szClass))
- delete [] szClass;
- }
- m_dwExtStyle |= WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR;
-}
-
-// 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 = {
- ConvertEndianness(WORD(0x0001)),
- ConvertEndianness(WORD(0xFFFF)),
- ConvertEndianness(m_dwHelpId),
- ConvertEndianness(m_dwExtStyle),
- ConvertEndianness(m_dwStyle),
- ConvertEndianness(WORD(m_vItems.size())),
- ConvertEndianness(m_sX),
- ConvertEndianness(m_sY),
- ConvertEndianness(m_sWidth),
- ConvertEndianness(m_sHeight)
- };
-
- CopyMemory(seeker, &dh, sizeof(DLGTEMPLATEEX));
- seeker += sizeof(DLGTEMPLATEEX);
- }
- else {
- DLGTEMPLATE dh = {
- ConvertEndianness(m_dwStyle),
- ConvertEndianness(m_dwExtStyle),
- ConvertEndianness(WORD(m_vItems.size())),
- ConvertEndianness(m_sX),
- ConvertEndianness(m_sY),
- ConvertEndianness(m_sWidth),
- ConvertEndianness(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 = ConvertEndianness(m_sFontSize);
- seeker += sizeof(short);
- if (m_bExtended) {
- *(short*)seeker = ConvertEndianness(m_sFontWeight);
- seeker += sizeof(short);
- *(BYTE*)seeker = m_bItalic;
- seeker += sizeof(BYTE);
- *(BYTE*)seeker = m_bCharset;
- seeker += sizeof(BYTE);
- }
- WriteStringOrId(m_szFont);
- }
-
- // Write all of the items
- for (unsigned int i = 0; i < m_vItems.size(); i++) {
- // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary
- if (DWORD(seeker - pbDlg) % sizeof(DWORD))
- seeker += sizeof(WORD);
-
- if (m_bExtended) {
- DLGITEMTEMPLATEEX dih = {
- ConvertEndianness(m_vItems[i]->dwHelpId),
- ConvertEndianness(m_vItems[i]->dwExtStyle),
- ConvertEndianness(m_vItems[i]->dwStyle),
- ConvertEndianness(m_vItems[i]->sX),
- ConvertEndianness(m_vItems[i]->sY),
- ConvertEndianness(m_vItems[i]->sWidth),
- ConvertEndianness(m_vItems[i]->sHeight),
- ConvertEndianness(m_vItems[i]->wId)
- };
-
- CopyMemory(seeker, &dih, sizeof(DLGITEMTEMPLATEEX));
- seeker += sizeof(DLGITEMTEMPLATEEX);
- }
- else {
- DLGITEMTEMPLATE dih = {
- ConvertEndianness(m_vItems[i]->dwStyle),
- ConvertEndianness(m_vItems[i]->dwExtStyle),
- ConvertEndianness(m_vItems[i]->sX),
- ConvertEndianness(m_vItems[i]->sY),
- ConvertEndianness(m_vItems[i]->sWidth),
- ConvertEndianness(m_vItems[i]->sHeight),
- ConvertEndianness(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
- WORD wCreateDataSize = m_vItems[i]->wCreateDataSize;
- if (m_vItems[i]->wCreateDataSize) wCreateDataSize += sizeof(WORD);
- *(WORD*)seeker = ConvertEndianness(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;
- }
- }
-
- assert((DWORD) seeker - (DWORD) pbDlg == dwSize);
-
- // 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 ? sizeof(short) + 2*sizeof(BYTE) : 0);
- AddStringOrIdSize(m_szFont);
- }
-
- for (unsigned int i = 0; i < m_vItems.size(); i++) {
- // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary
- 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;
-}
+/* + * DialogTemplate.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "DialogTemplate.h" +#include "winchar.h" +#include <cassert> // for assert(3) +#ifndef _WIN32 +# include "util.h" // for Unicode conversion functions +# include <stdio.h> +# include <stdlib.h> +# include <iconv.h> +# include <errno.h> +#endif + +using namespace std; + +////////////////////////////////////////////////////////////////////// +// Utilities +////////////////////////////////////////////////////////////////////// + +static inline DWORD ConvertEndianness(DWORD d) { + return FIX_ENDIAN_INT32(d); +} + +static inline WORD ConvertEndianness(WORD w) { + return FIX_ENDIAN_INT16(w); +} + +static inline short ConvertEndianness(short s) { + return ConvertEndianness(WORD(s)); +} + +#define ALIGN(dwToAlign, dwAlignOn) dwToAlign = (dwToAlign%dwAlignOn == 0) ? dwToAlign : dwToAlign - (dwToAlign%dwAlignOn) + dwAlignOn + +// Reads a variant length array from seeker into readInto and advances seeker +void ReadVarLenArr(LPBYTE &seeker, WCHAR* &readInto, unsigned int uCodePage) { + WORD* arr = (WORD*)seeker; + switch (ConvertEndianness(arr[0])) { + case 0x0000: + readInto = 0; + seeker += sizeof(WORD); + break; + case 0xFFFF: + readInto = MAKEINTRESOURCEW(ConvertEndianness(arr[1])); + seeker += 2*sizeof(WORD); + break; + default: + { + readInto = winchar_strdup((WCHAR *) arr); + PWCHAR wseeker = PWCHAR(seeker); + while (*wseeker++); + seeker = LPBYTE(wseeker); + } + 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 = ConvertEndianness(WORD(DWORD(x))); \ + seeker += sizeof(WORD); \ + } \ + else { \ + winchar_strcpy((WCHAR *) seeker, x); \ + seeker += winchar_strlen((WCHAR *) seeker) * sizeof(WCHAR) + 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) : (winchar_strlen(x) + 1) * sizeof(WCHAR)) : sizeof(WORD) + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CDialogTemplate::CDialogTemplate(BYTE* pbData, unsigned int uCodePage) { + m_uCodePage = uCodePage; + + m_dwHelpId = 0; + m_szClass = 0; + m_szFont = 0; + m_sFontSize = 0; + m_sFontWeight = 0; + m_bItalic = 0; + m_bCharset = 0; + m_szMenu = 0; + m_szTitle = 0; + + WORD wItems = 0; + + if (*(DWORD*)pbData == EXTENDED_DIALOG) { // Extended dialog template signature + m_bExtended = true; + + DLGTEMPLATEEX* dTemplateEx = (DLGTEMPLATEEX*)pbData; + + m_dwHelpId = ConvertEndianness(dTemplateEx->helpID); + m_dwStyle = ConvertEndianness(dTemplateEx->style); + m_dwExtStyle = ConvertEndianness(dTemplateEx->exStyle); + m_sX = ConvertEndianness(dTemplateEx->x); + m_sY = ConvertEndianness(dTemplateEx->y); + m_sWidth = ConvertEndianness(dTemplateEx->cx); + m_sHeight = ConvertEndianness(dTemplateEx->cy); + + wItems = ConvertEndianness(dTemplateEx->cDlgItems); + } + else { + m_bExtended = false; + + DLGTEMPLATE* dTemplate = (DLGTEMPLATE*)pbData; + + m_dwStyle = ConvertEndianness(dTemplate->style); + m_dwExtStyle = ConvertEndianness(dTemplate->dwExtendedStyle); + m_sX = ConvertEndianness(dTemplate->x); + m_sY = ConvertEndianness(dTemplate->y); + m_sWidth = ConvertEndianness(dTemplate->cx); + m_sHeight = ConvertEndianness(dTemplate->cy); + + wItems = ConvertEndianness(dTemplate->cdit); + } + + BYTE* seeker = pbData + (m_bExtended ? sizeof(DLGTEMPLATEEX) : sizeof(DLGTEMPLATE)); + + // Read menu variant length array + ReadVarLenArr(seeker, m_szMenu, m_uCodePage); + // Read class variant length array + ReadVarLenArr(seeker, m_szClass, m_uCodePage); + // Read title variant length array + ReadVarLenArr(seeker, m_szTitle, m_uCodePage); + // Read font size and variant length array (only if style DS_SETFONT is used!) + if (m_dwStyle & DS_SETFONT) { + m_sFontSize = ConvertEndianness(*(short*)seeker); + seeker += sizeof(short); + if (m_bExtended) { + m_sFontWeight = ConvertEndianness(*(short*)seeker); + seeker += sizeof(short); + m_bItalic = *(BYTE*)seeker; + seeker += sizeof(BYTE); + m_bCharset = *(BYTE*)seeker; + seeker += sizeof(BYTE); + } + ReadVarLenArr(seeker, m_szFont, m_uCodePage); + } + + // Read items + for (int i = 0; i < wItems; i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary + 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 = ConvertEndianness(rawItem->helpID); + item->dwStyle = ConvertEndianness(rawItem->style); + item->dwExtStyle = ConvertEndianness(rawItem->exStyle); + item->sX = ConvertEndianness(rawItem->x); + item->sY = ConvertEndianness(rawItem->y); + item->sWidth = ConvertEndianness(rawItem->cx); + item->sHeight = ConvertEndianness(rawItem->cy); + item->wId = ConvertEndianness(rawItem->id); + + seeker += sizeof(DLGITEMTEMPLATEEX); + } + else { + DLGITEMTEMPLATE* rawItem = (DLGITEMTEMPLATE*)seeker; + + item->dwHelpId = 0; + item->dwStyle = ConvertEndianness(rawItem->style); + item->dwExtStyle = ConvertEndianness(rawItem->dwExtendedStyle); + item->sX = ConvertEndianness(rawItem->x); + item->sY = ConvertEndianness(rawItem->y); + item->sWidth = ConvertEndianness(rawItem->cx); + item->sHeight = ConvertEndianness(rawItem->cy); + item->wId = ConvertEndianness(rawItem->id); + + seeker += sizeof(DLGITEMTEMPLATE); + } + + // Read class variant length array + ReadVarLenArr(seeker, item->szClass, m_uCodePage); + // Read title variant length array + ReadVarLenArr(seeker, item->szTitle, m_uCodePage); + + // Read creation data variant length array + // First read the size of the array (no null termination) + item->wCreateDataSize = ConvertEndianness(*(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_szFont; + + for (unsigned 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 the width of the dialog +short CDialogTemplate::GetWidth() { + return m_sWidth; +} + +// Returns the height of the dialog +short CDialogTemplate::GetHeight() { + return m_sHeight; +} + +// Returns info about the item with the id wId +DialogItemTemplate* CDialogTemplate::GetItem(WORD wId) { + for (unsigned 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 +// Returns 1 if removed, 0 otherwise +int CDialogTemplate::RemoveItem(WORD wId) { + for (unsigned int i = 0; i < m_vItems.size(); i++) { + if (m_vItems[i]->wId == wId) { + m_vItems.erase(m_vItems.begin() + i); + return 1; + } + } + return 0; +} + +// Sets the font of the dialog +void CDialogTemplate::SetFont(char* szFaceName, WORD wFontSize) { + if (strcmp(szFaceName, "MS Shell Dlg")) { + // not MS Shell Dlg + m_dwStyle &= ~DS_SHELLFONT; + } + else { + // MS Shell Dlg + m_dwStyle |= DS_SHELLFONT; + } + m_bCharset = DEFAULT_CHARSET; + m_dwStyle |= DS_SETFONT; + if (m_szFont) delete [] m_szFont; + m_szFont = winchar_fromansi(szFaceName, m_uCodePage); + 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 = winchar_strdup(item.szClass); + } + if (item.szTitle && !IS_INTRESOURCE(item.szTitle)) { + newItem->szTitle = winchar_strdup(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) +void CDialogTemplate::MoveAll(short x, short y) { + for (unsigned int i = 0; i < m_vItems.size(); i++) { + m_vItems[i]->sX += x; + m_vItems[i]->sY += y; + } +} + +// Resizes the dialog by (x,y) +void CDialogTemplate::Resize(short x, short y) { + m_sWidth += x; + m_sHeight += y; +} + +#ifdef _WIN32 +// Creates a dummy dialog that is used for converting units +HWND CDialogTemplate::CreateDummyDialog() { + 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!"); + + return hDlg; +} + +// Converts pixels to this dialog's units +void CDialogTemplate::PixelsToDlgUnits(short& x, short& y) { + HWND hDlg = CreateDummyDialog(); + RECT r = {0, 0, 10000, 10000}; + MapDialogRect(hDlg, &r); + DestroyWindow(hDlg); + + x = short(float(x) / (float(r.right)/10000)); + y = short(float(y) / (float(r.bottom)/10000)); +} + +// Converts pixels to this dialog's units +void CDialogTemplate::DlgUnitsToPixels(short& x, short& y) { + HWND hDlg = CreateDummyDialog(); + RECT r = {0, 0, 10000, 10000}; + MapDialogRect(hDlg, &r); + DestroyWindow(hDlg); + + x = short(float(x) * (float(r.right)/10000)); + y = short(float(y) * (float(r.bottom)/10000)); +} + +// Returns the size of a string in the dialog (in dialog units) +SIZE CDialogTemplate::GetStringSize(WORD id, char *str) { + HWND hDlg = CreateDummyDialog(); + + LOGFONT f; + GetObject((HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0), sizeof(LOGFONT), &f); + + HDC memDC = CreateCompatibleDC(GetDC(hDlg)); + HFONT font = CreateFontIndirect(&f); + SelectObject(memDC, font); + + SIZE size; + GetTextExtentPoint32(memDC, str, strlen(str), &size); + + DestroyWindow(hDlg); + DeleteObject(font); + DeleteDC(memDC); + + PixelsToDlgUnits((short&)size.cx, (short&)size.cy); + + return size; +} + +// Trims the right margins of a control to fit a given text string size. +void CDialogTemplate::RTrimToString(WORD id, char *str, int margins) { + DialogItemTemplate* item = GetItem(id); + if (!item) return; + + SIZE size = GetStringSize(id, str); + + size.cx += margins; + size.cy += 2; + + item->sWidth = short(size.cx); + item->sHeight = short(size.cy); +} + +// Trims the left margins of a control to fit a given text string size. +void CDialogTemplate::LTrimToString(WORD id, char *str, int margins) { + DialogItemTemplate* item = GetItem(id); + if (!item) return; + + SIZE size = GetStringSize(id, str); + + size.cx += margins; + size.cy += 2; + + item->sX += item->sWidth - short(size.cx); + item->sWidth = short(size.cx); + item->sHeight = short(size.cy); +} + +// Trims the left and right margins of a control to fit a given text string size. +void CDialogTemplate::CTrimToString(WORD id, char *str, int margins) { + DialogItemTemplate* item = GetItem(id); + if (!item) return; + + SIZE size = GetStringSize(id, str); + + size.cx += margins; + size.cy += 2; + + item->sX += item->sWidth/2 - short(size.cx/2); + item->sWidth = short(size.cx); + item->sHeight = short(size.cy); +} +#endif + +// Moves every item right and gives it the WS_EX_RIGHT extended style +void CDialogTemplate::ConvertToRTL() { + for (unsigned int i = 0; i < m_vItems.size(); i++) { + bool addExStyle = false; + char *szClass; + + if (IS_INTRESOURCE(m_vItems[i]->szClass)) + szClass = (char *) m_vItems[i]->szClass; + else + szClass = winchar_toansi(m_vItems[i]->szClass); + + // Button + if (long(m_vItems[i]->szClass) == 0x80) { + m_vItems[i]->dwStyle ^= BS_LEFTTEXT; + m_vItems[i]->dwStyle ^= BS_RIGHT; + m_vItems[i]->dwStyle ^= BS_LEFT; + + if ((m_vItems[i]->dwStyle & (BS_LEFT|BS_RIGHT)) == (BS_LEFT|BS_RIGHT)) { + m_vItems[i]->dwStyle ^= BS_LEFT; + m_vItems[i]->dwStyle ^= BS_RIGHT; + if (m_vItems[i]->dwStyle & (BS_RADIOBUTTON|BS_CHECKBOX|BS_USERBUTTON)) { + m_vItems[i]->dwStyle |= BS_RIGHT; + } + } + } + // Edit + else if (long(m_vItems[i]->szClass) == 0x81) { + if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) { + m_vItems[i]->dwStyle ^= ES_RIGHT; + } + } + // Static + else if (long(m_vItems[i]->szClass) == 0x82) { + if ((m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_LEFT || (m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_LEFTNOWORDWRAP) + { + m_vItems[i]->dwStyle &= ~SS_TYPEMASK; + m_vItems[i]->dwStyle |= SS_RIGHT; + } + else if ((m_vItems[i]->dwStyle & SS_TYPEMASK) == SS_ICON) { + m_vItems[i]->dwStyle |= SS_CENTERIMAGE; + } + } + else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "RichEdit20A")) { + if ((m_vItems[i]->dwStyle & ES_CENTER) == 0) { + m_vItems[i]->dwStyle ^= ES_RIGHT; + } + } + else if (!IS_INTRESOURCE(m_vItems[i]->szClass) && !stricmp(szClass, "SysTreeView32")) { + m_vItems[i]->dwStyle |= TVS_RTLREADING; + addExStyle = true; + } + else addExStyle = true; + + if (addExStyle) + m_vItems[i]->dwExtStyle |= WS_EX_RIGHT; + + m_vItems[i]->dwExtStyle |= WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; + + m_vItems[i]->sX = m_sWidth - m_vItems[i]->sWidth - m_vItems[i]->sX; + + if (!IS_INTRESOURCE(m_vItems[i]->szClass)) + delete [] szClass; + } + m_dwExtStyle |= WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR; +} + +// 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 = { + ConvertEndianness(WORD(0x0001)), + ConvertEndianness(WORD(0xFFFF)), + ConvertEndianness(m_dwHelpId), + ConvertEndianness(m_dwExtStyle), + ConvertEndianness(m_dwStyle), + ConvertEndianness(WORD(m_vItems.size())), + ConvertEndianness(m_sX), + ConvertEndianness(m_sY), + ConvertEndianness(m_sWidth), + ConvertEndianness(m_sHeight) + }; + + CopyMemory(seeker, &dh, sizeof(DLGTEMPLATEEX)); + seeker += sizeof(DLGTEMPLATEEX); + } + else { + DLGTEMPLATE dh = { + ConvertEndianness(m_dwStyle), + ConvertEndianness(m_dwExtStyle), + ConvertEndianness(WORD(m_vItems.size())), + ConvertEndianness(m_sX), + ConvertEndianness(m_sY), + ConvertEndianness(m_sWidth), + ConvertEndianness(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 = ConvertEndianness(m_sFontSize); + seeker += sizeof(short); + if (m_bExtended) { + *(short*)seeker = ConvertEndianness(m_sFontWeight); + seeker += sizeof(short); + *(BYTE*)seeker = m_bItalic; + seeker += sizeof(BYTE); + *(BYTE*)seeker = m_bCharset; + seeker += sizeof(BYTE); + } + WriteStringOrId(m_szFont); + } + + // Write all of the items + for (unsigned int i = 0; i < m_vItems.size(); i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary + if (DWORD(seeker - pbDlg) % sizeof(DWORD)) + seeker += sizeof(WORD); + + if (m_bExtended) { + DLGITEMTEMPLATEEX dih = { + ConvertEndianness(m_vItems[i]->dwHelpId), + ConvertEndianness(m_vItems[i]->dwExtStyle), + ConvertEndianness(m_vItems[i]->dwStyle), + ConvertEndianness(m_vItems[i]->sX), + ConvertEndianness(m_vItems[i]->sY), + ConvertEndianness(m_vItems[i]->sWidth), + ConvertEndianness(m_vItems[i]->sHeight), + ConvertEndianness(m_vItems[i]->wId) + }; + + CopyMemory(seeker, &dih, sizeof(DLGITEMTEMPLATEEX)); + seeker += sizeof(DLGITEMTEMPLATEEX); + } + else { + DLGITEMTEMPLATE dih = { + ConvertEndianness(m_vItems[i]->dwStyle), + ConvertEndianness(m_vItems[i]->dwExtStyle), + ConvertEndianness(m_vItems[i]->sX), + ConvertEndianness(m_vItems[i]->sY), + ConvertEndianness(m_vItems[i]->sWidth), + ConvertEndianness(m_vItems[i]->sHeight), + ConvertEndianness(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 + WORD wCreateDataSize = m_vItems[i]->wCreateDataSize; + if (m_vItems[i]->wCreateDataSize) wCreateDataSize += sizeof(WORD); + *(WORD*)seeker = ConvertEndianness(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; + } + } + + assert((DWORD) seeker - (DWORD) pbDlg == dwSize); + + // 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 ? sizeof(short) + 2*sizeof(BYTE) : 0); + AddStringOrIdSize(m_szFont); + } + + for (unsigned int i = 0; i < m_vItems.size(); i++) { + // DLGITEMTEMPLATE[EX]s must be aligned on DWORD boundary + ALIGN(dwSize, sizeof(DWORD)); + + dwSize += m_bExtended ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE); + + // Class + AddStringOrIdSize(m_vItems[i]->szClass); + // Title + AddStringOrIdSize(m_vItems[i]->szTitle); + + dwSize += sizeof(WORD) + m_vItems[i]->wCreateDataSize; + } + + return dwSize; +} diff --git a/Source/DialogTemplate.h b/Source/DialogTemplate.h index c6bc58e..918ca23 100755 --- a/Source/DialogTemplate.h +++ b/Source/DialogTemplate.h @@ -1,165 +1,165 @@ -/*
- * DialogTemplate.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il>
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#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 "Platform.h"
-
-#include <vector>
-#include <stdexcept>
-
-#ifndef __BIG_ENDIAN__
-# define EXTENDED_DIALOG ((DWORD) 0xFFFF0001)
-#else
-# define EXTENDED_DIALOG ((DWORD) 0x0100FFFF)
-#endif
-
-struct DialogItemTemplate {
- DWORD dwHelpId; // Extended only
-
- short sX;
- short sY;
- short sWidth;
- short sHeight;
- DWORD dwExtStyle;
- DWORD dwStyle;
- WORD wId;
-
- WCHAR *szClass;
- WCHAR *szTitle;
- char *szCreationData;
-
- WORD wCreateDataSize;
-};
-
-#pragma pack(1)
-
-#ifndef _WIN32
-typedef struct {
- DWORD style;
- DWORD dwExtendedStyle;
- WORD cdit;
- short x;
- short y;
- short cx;
- short cy;
-} DLGTEMPLATE;
-#endif
-
-typedef struct {
- WORD dlgVer;
- WORD signature;
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- WORD cDlgItems;
- short x;
- short y;
- short cx;
- short cy;
-} DLGTEMPLATEEX;
-
-#ifndef _WIN32
-typedef struct {
- DWORD style;
- DWORD dwExtendedStyle;
- short x;
- short y;
- short cx;
- short cy;
- WORD id;
-} DLGITEMTEMPLATE;
-#endif
-
-typedef struct {
- DWORD helpID;
- DWORD exStyle;
- DWORD style;
- short x;
- short y;
- short cx;
- short cy;
- WORD id;
- WORD _miscrosoft_docs_are_wrong;
-} DLGITEMTEMPLATEEX;
-
-#pragma pack()
-
-class CDialogTemplate {
-public:
- CDialogTemplate(BYTE* pbData, unsigned int uCodePage=CP_ACP);
- virtual ~CDialogTemplate();
-
- short GetWidth();
- short GetHeight();
- DialogItemTemplate* GetItem(WORD wId);
- DialogItemTemplate* GetItemByIdx(DWORD i);
- int RemoveItem(WORD wId);
- void SetFont(char* szFaceName, WORD wFontSize);
- void AddItem(DialogItemTemplate item);
-#ifdef _WIN32
- HWND CreateDummyDialog();
-#endif
- void MoveAll(short x, short y);
- void Resize(short x, short y);
-#ifdef _WIN32
- void PixelsToDlgUnits(short& x, short& y);
- void DlgUnitsToPixels(short& x, short& y);
- SIZE GetStringSize(WORD id, char *str);
- void RTrimToString(WORD id, char *str, int margins);
- void LTrimToString(WORD id, char *str, int margins);
- void CTrimToString(WORD id, char *str, int margins);
-#endif
- void ConvertToRTL();
- 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;
-
- WCHAR *m_szMenu;
- WCHAR *m_szClass;
- WCHAR *m_szTitle;
-
- // Only if DS_FONT style is set
- short m_sFontSize;
- short m_sFontWeight; // Extended only
- BYTE m_bItalic; // Extended only
- BYTE m_bCharset; // Extended only
- WCHAR *m_szFont;
-
- // For (en/de)coding Unicode
- unsigned int m_uCodePage;
-
- // Items vector
- std::vector<DialogItemTemplate*> m_vItems;
-};
-
-#endif // !defined(AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_)
+/* + * DialogTemplate.h + * + * This file is a part of NSIS. + * + * Copyright (C) 2002 Amir Szekely <kichik@netvision.net.il> + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#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 "Platform.h" + +#include <vector> +#include <stdexcept> + +#ifndef __BIG_ENDIAN__ +# define EXTENDED_DIALOG ((DWORD) 0xFFFF0001) +#else +# define EXTENDED_DIALOG ((DWORD) 0x0100FFFF) +#endif + +struct DialogItemTemplate { + DWORD dwHelpId; // Extended only + + short sX; + short sY; + short sWidth; + short sHeight; + DWORD dwExtStyle; + DWORD dwStyle; + WORD wId; + + WCHAR *szClass; + WCHAR *szTitle; + char *szCreationData; + + WORD wCreateDataSize; +}; + +#pragma pack(1) + +#ifndef _WIN32 +typedef struct { + DWORD style; + DWORD dwExtendedStyle; + WORD cdit; + short x; + short y; + short cx; + short cy; +} DLGTEMPLATE; +#endif + +typedef struct { + WORD dlgVer; + WORD signature; + DWORD helpID; + DWORD exStyle; + DWORD style; + WORD cDlgItems; + short x; + short y; + short cx; + short cy; +} DLGTEMPLATEEX; + +#ifndef _WIN32 +typedef struct { + DWORD style; + DWORD dwExtendedStyle; + short x; + short y; + short cx; + short cy; + WORD id; +} DLGITEMTEMPLATE; +#endif + +typedef struct { + DWORD helpID; + DWORD exStyle; + DWORD style; + short x; + short y; + short cx; + short cy; + WORD id; + WORD _miscrosoft_docs_are_wrong; +} DLGITEMTEMPLATEEX; + +#pragma pack() + +class CDialogTemplate { +public: + CDialogTemplate(BYTE* pbData, unsigned int uCodePage=CP_ACP); + virtual ~CDialogTemplate(); + + short GetWidth(); + short GetHeight(); + DialogItemTemplate* GetItem(WORD wId); + DialogItemTemplate* GetItemByIdx(DWORD i); + int RemoveItem(WORD wId); + void SetFont(char* szFaceName, WORD wFontSize); + void AddItem(DialogItemTemplate item); +#ifdef _WIN32 + HWND CreateDummyDialog(); +#endif + void MoveAll(short x, short y); + void Resize(short x, short y); +#ifdef _WIN32 + void PixelsToDlgUnits(short& x, short& y); + void DlgUnitsToPixels(short& x, short& y); + SIZE GetStringSize(WORD id, char *str); + void RTrimToString(WORD id, char *str, int margins); + void LTrimToString(WORD id, char *str, int margins); + void CTrimToString(WORD id, char *str, int margins); +#endif + void ConvertToRTL(); + 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; + + WCHAR *m_szMenu; + WCHAR *m_szClass; + WCHAR *m_szTitle; + + // Only if DS_FONT style is set + short m_sFontSize; + short m_sFontWeight; // Extended only + BYTE m_bItalic; // Extended only + BYTE m_bCharset; // Extended only + WCHAR *m_szFont; + + // For (en/de)coding Unicode + unsigned int m_uCodePage; + + // Items vector + std::vector<DialogItemTemplate*> m_vItems; +}; + +#endif // !defined(AFX_DIALOGTEMPLATE_H__C5A973AF_0F56_4BEC_814A_79318E2EB4AC__INCLUDED_) diff --git a/Source/Platform.h b/Source/Platform.h index 28d7209..98ef2cf 100755 --- a/Source/Platform.h +++ b/Source/Platform.h @@ -1,875 +1,875 @@ -/*
- * Platform.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___PLATFORM__H___
-#define ___PLATFORM__H___
-
-// some definitions for non Win32 platforms were taken from MinGW's free Win32 library
-
-// includes
-
-#ifdef _WIN32
-# include <windows.h>
-# include <commctrl.h>
-#else
-# ifndef EXEHEAD
-# include <string.h>
-# include <stdlib.h>
-# endif
-// basic types
-typedef unsigned char BYTE, *PBYTE, *LPBYTE;
-typedef unsigned short WORD, *LPWORD;
-typedef unsigned int DWORD, *LPDWORD;
-typedef short SHORT;
-typedef unsigned short USHORT;
-typedef unsigned int UINT;
-typedef unsigned int UINT32;
-typedef int INT;
-typedef int INT32;
-typedef long LONG;
-typedef unsigned long ULONG;
-typedef long long INT64, LARGE_INTEGER;
-typedef unsigned long long UINT64, ULARGE_INTEGER;
-typedef int BOOL, *LPBOOL;
-typedef short VARIANT_BOOL;
-typedef void VOID;
-typedef void *LPVOID;
-typedef char CHAR, *PCHAR, *LPCH, *PCH, *NPSTR, *LPSTR, *PSTR;
-typedef unsigned char UCHAR;
-typedef const char *LPCCH, *PCSTR, *LPCSTR;
-typedef unsigned short WCHAR, OLECHAR, *PWCHAR, *LPWCH, *PWCH, *NWPSTR, *LPWSTR, *PWSTR, *BSTR;
-typedef const unsigned short *LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR, *LPCOLESTR;
-typedef unsigned int UINT_PTR;
-// basic stuff
-typedef void * HANDLE;
-typedef HANDLE HWND;
-typedef unsigned long HKEY;
-// some gdi
-typedef unsigned long COLORREF;
-typedef unsigned long HBRUSH;
-// bool
-# define FALSE 0
-# define TRUE 1
-// more
-typedef WORD LANGID;
-// ULONGLONG
-#ifdef __GNUC__
-#define _HAVE_INT64
-#define _INTEGRAL_MAX_BITS 64
-#undef __int64
-#define __int64 long long
-#elif defined(__WATCOMC__) && (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 )
-#define _HAVE_INT64
-#endif /* __GNUC__/__WATCOMC */
-#if defined(_HAVE_INT64) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64)
-typedef __int64 LONGLONG;
-typedef unsigned __int64 DWORDLONG;
-#else
-typedef double LONGLONG,DWORDLONG;
-#endif
-typedef LONGLONG *PLONGLONG;
-typedef DWORDLONG *PDWORDLONG;
-typedef DWORDLONG ULONGLONG,*PULONGLONG;
-#endif
-
-#ifndef __BIG_ENDIAN__
-# define FIX_ENDIAN_INT32_INPLACE(x) ((void)(x))
-# define FIX_ENDIAN_INT32(x) (x)
-# define FIX_ENDIAN_INT16_INPLACE(x) ((void)(x))
-# define FIX_ENDIAN_INT16(x) (x)
-#else
-# define FIX_ENDIAN_INT32_INPLACE(x) ((x) = SWAP_ENDIAN_INT32(x))
-# define FIX_ENDIAN_INT32(x) SWAP_ENDIAN_INT32(x)
-# define FIX_ENDIAN_INT16_INPLACE(x) ((x) = SWAP_ENDIAN_INT16(x))
-# define FIX_ENDIAN_INT16(x) SWAP_ENDIAN_INT16(x)
-#endif
-#define SWAP_ENDIAN_INT32(x) ( \
- (((x)&0xFF000000) >> 24) | \
- (((x)&0x00FF0000) >> 8) | \
- (((x)&0x0000FF00) << 8) | \
- (((x)&0x000000FF) << 24) )
-#define SWAP_ENDIAN_INT16(x) ( \
- (((x)&0xFF00) >> 8) | \
- (((x)&0x00FF) << 8) )
-
-// script path separator
-
-# define PATH_SEPARATOR_STR "\\"
-# define PATH_SEPARATOR_C '\\'
-
-// system specific characters
-
-#ifdef _WIN32
-# define PLATFORM_PATH_SEPARATOR_STR "\\"
-# define PLATFORM_PATH_SEPARATOR_C '\\'
-# define OPT_STR "/"
-# define OPT_C '/'
-# define IS_OPT(a) (a[0]==OPT_C||a[0]=='-')
-#else
-# define PLATFORM_PATH_SEPARATOR_STR "/"
-# define PLATFORM_PATH_SEPARATOR_C '/'
-# define OPT_STR "-"
-# define OPT_C '-'
-# define IS_OPT(a) (a[0]==OPT_C)
-#endif
-
-// attributes
-
-#ifdef _MSC_VER
-# define FORCE_INLINE __forceinline
-#else
-# ifdef __GNUC__
-# if __GNUC__ < 3
-# define FORCE_INLINE inline
-# else
-# define FORCE_INLINE inline __attribute__ ((always_inline))
-# endif
-# else
-# define FORCE_INLINE inline
-# endif
-#endif
-
-// Added by Dave Laundon 19th August 2002
-// For all internal functions, use of stdcall calling convention moves the
-// responsibility for tidying the stack to callee from caller, reducing the code
-// involved considerably. Gives an instant saving of 0.5K.
-// NB - the zlib and bzip2 portions have been given the same treatment, but with
-// project compiler-options settings and/or project-wide defines.
-// NB - safer for NSIS's routines to be defined explicitly to avoid problems
-// calling DLL functions.
-#if defined(_WIN32) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED))
-# define NSISCALL __stdcall // Ordinary functions
-# define NSISCALLV __cdecl // Variable-argument-list functions
-#else
-# if defined(__GNUC__) && defined(__i386__)
-# define NSISCALL __attribute__((__stdcall__)) // Ordinary functions
-# define NSISCALLV __attribute__((__cdecl__)) // Variable-argument-list functions
-# else
-# define NSISCALL
-# define NSISCALLV
-# endif
-#endif
-
-#if defined(__GNUC__)
-#define UNUSED __attribute__((unused))
-#else
-#define UNUSED
-#endif
-
-// macros
-
-#ifndef _WIN32
-# ifndef FIELD_OFFSET
-# define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))
-# endif
-# ifndef MAKEINTRESOURCEA
-# define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
-# endif
-# ifndef MAKEINTRESOURCEW
-# define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
-# endif
-# ifndef MAKEINTRESOURCE
-# define MAKEINTRESOURCE MAKEINTRESOURCEA
-# endif
-# ifndef IMAGE_FIRST_SECTION
-# define IMAGE_FIRST_SECTION(h) ( PIMAGE_SECTION_HEADER( (DWORD) h + \
- FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + \
- FIX_ENDIAN_INT16(PIMAGE_NT_HEADERS(h)->FileHeader.SizeOfOptionalHeader) ) )
-# endif
-# ifndef RGB
-# define RGB(r,g,b) ((DWORD)(((BYTE)(r)|((WORD)(g)<<8))|(((DWORD)(BYTE)(b))<<16)))
-# endif
-# ifndef MAKELONG
-# define MAKELONG(a,b) ((LONG)(((WORD)(a))|(((DWORD)((WORD)(b)))<<16)))
-# endif
-#endif
-#ifndef IS_INTRESOURCE
-# define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
-#endif
-
-// functions
-
-#ifndef _WIN32
-# define stricmp strcasecmp
-# define strcmpi strcasecmp
-# define strnicmp strncasecmp
-# define CopyMemory memcpy
-# define ZeroMemory(x, y) memset(x, 0, y)
-#endif
-
-// defines
-
-#ifndef FOF_NOERRORUI
-# define FOF_NOERRORUI 0x0400
-#endif
-
-#ifndef ULONG_PTR
-# define ULONG_PTR DWORD
-#endif
-
-#ifndef IDC_HAND
-# define IDC_HAND MAKEINTRESOURCE(32649)
-#endif
-
-#ifndef BIF_NEWDIALOGSTYLE
-# define BIF_NEWDIALOGSTYLE 0x0040
-#endif
-
-#ifndef TVITEM
-# define TVITEM TV_ITEM
-#endif
-
-#ifndef TVM_SETITEMHEIGHT
-# define TVM_SETITEMHEIGHT (TV_FIRST + 27)
-#endif
-
-#ifndef TVM_GETITEMHEIGHT
-# define TVM_GETITEMHEIGHT (TV_FIRST + 28)
-#endif
-
-#ifndef LVS_EX_LABELTIP
-# define LVS_EX_LABELTIP 0x00004000
-#endif
-
-#ifndef EXEHEAD
-# ifndef SF_TEXT
-# define SF_TEXT 1
-# endif
-# ifndef SF_RTF
-# define SF_RTF 2
-# endif
-#endif
-
-#ifdef __GNUC__
-# undef INVALID_FILE_ATTRIBUTES
-#endif
-#ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((unsigned long) -1)
-#endif
-
-// shell folders
-
-#ifdef _WIN32
-# include <shlobj.h>
-#endif
-
-#ifndef CSIDL_FLAG_CREATE
-# define CSIDL_FLAG_CREATE 0x8000
-#endif
-
-#ifndef CSIDL_PROGRAMS
-# define CSIDL_PROGRAMS 0x2
-#endif
-#ifndef CSIDL_COMMON_PROGRAMS
-# define CSIDL_COMMON_PROGRAMS 0x17
-#endif
-#ifndef CSIDL_PRINTERS
-# define CSIDL_PRINTERS 0x4
-#endif
-#ifndef CSIDL_PERSONAL
-# define CSIDL_PERSONAL 0x5
-#endif
-#ifndef CSIDL_COMMON_DOCUMENTS
-# define CSIDL_COMMON_DOCUMENTS 0x2E
-#endif
-#ifndef CSIDL_FAVORITES
-# define CSIDL_FAVORITES 0x6
-#endif
-#ifndef CSIDL_COMMON_FAVORITES
-# define CSIDL_COMMON_FAVORITES 0x1F
-#endif
-#ifndef CSIDL_STARTUP
-# define CSIDL_STARTUP 0x7
-#endif
-#ifndef CSIDL_COMMON_STARTUP
-# define CSIDL_COMMON_STARTUP 0x18
-#endif
-#ifndef CSIDL_RECENT
-# define CSIDL_RECENT 0x8
-#endif
-#ifndef CSIDL_SENDTO
-# define CSIDL_SENDTO 0x9
-#endif
-#ifndef CSIDL_STARTMENU
-# define CSIDL_STARTMENU 0xB
-#endif
-#ifndef CSIDL_COMMON_STARTMENU
-# define CSIDL_COMMON_STARTMENU 0x16
-#endif
-#ifndef CSIDL_DESKTOPDIRECTORY
-# define CSIDL_DESKTOPDIRECTORY 0x10
-#endif
-#ifndef CSIDL_COMMON_DESKTOPDIRECTORY
-# define CSIDL_COMMON_DESKTOPDIRECTORY 0x19
-#endif
-#ifndef CSIDL_NETHOOD
-# define CSIDL_NETHOOD 0x13
-#endif
-#ifndef CSIDL_FONTS
-# define CSIDL_FONTS 0x14
-#endif
-#ifndef CSIDL_TEMPLATES
-# define CSIDL_TEMPLATES 0x15
-#endif
-#ifndef CSIDL_COMMON_TEMPLATES
-# define CSIDL_COMMON_TEMPLATES 0x2D
-#endif
-#ifndef CSIDL_APPDATA
-# define CSIDL_APPDATA 0x1A
-#endif
-#ifndef CSIDL_COMMON_APPDATA
-# define CSIDL_COMMON_APPDATA 0x23
-#endif
-#ifndef CSIDL_LOCAL_APPDATA
-# define CSIDL_LOCAL_APPDATA 0x1C
-#endif
-#ifndef CSIDL_PRINTHOOD
-# define CSIDL_PRINTHOOD 0x1B
-#endif
-#ifndef CSIDL_ALTSTARTUP
-# define CSIDL_ALTSTARTUP 0x1D
-#endif
-#ifndef CSIDL_COMMON_ALTSTARTUP
-# define CSIDL_COMMON_ALTSTARTUP 0x1E
-#endif
-#ifndef CSIDL_INTERNET_CACHE
-# define CSIDL_INTERNET_CACHE 0x20
-#endif
-#ifndef CSIDL_COOKIES
-# define CSIDL_COOKIES 0x21
-#endif
-#ifndef CSIDL_HISTORY
-# define CSIDL_HISTORY 0x22
-#endif
-#ifndef CSIDL_WINDOWS
-# define CSIDL_WINDOWS 0x24
-#endif
-#ifndef CSIDL_SYSTEM
-# define CSIDL_SYSTEM 0x25
-#endif
-#ifndef CSIDL_PROGRAM_FILES
-# define CSIDL_PROGRAM_FILES 0x26
-#endif
-#ifndef CSIDL_PROGRAM_FILES_COMMON
-# define CSIDL_PROGRAM_FILES_COMMON 0x2B
-#endif
-#ifndef CSIDL_MYPICTURES
-# define CSIDL_MYPICTURES 0x27
-#endif
-#ifndef CSIDL_COMMON_PICTURES
-# define CSIDL_COMMON_PICTURES 0x36
-#endif
-#ifndef CSIDL_PROFILE
-# define CSIDL_PROFILE 0x28
-#endif
-#ifndef CSIDL_ADMINTOOLS
-# define CSIDL_ADMINTOOLS 0x30
-#endif
-#ifndef CSIDL_COMMON_ADMINTOOLS
-# define CSIDL_COMMON_ADMINTOOLS 0x2F
-#endif
-#ifndef CSIDL_MYMUSIC
-# define CSIDL_MYMUSIC 0xD
-#endif
-#ifndef CSIDL_COMMON_MUSIC
-# define CSIDL_COMMON_MUSIC 0x35
-#endif
-#ifndef CSIDL_MYVIDEO
-# define CSIDL_MYVIDEO 0xE
-#endif
-#ifndef CSIDL_COMMON_VIDEO
-# define CSIDL_COMMON_VIDEO 0x37
-#endif
-#ifndef CSIDL_RESOURCES
-# define CSIDL_RESOURCES 0x38
-#endif
-#ifndef CSIDL_RESOURCES_LOCALIZED
-# define CSIDL_RESOURCES_LOCALIZED 0x39
-#endif
-#ifndef CSIDL_CDBURN_AREA
-# define CSIDL_CDBURN_AREA 0x3B
-#endif
-
-// other shell stuff
-
-#ifndef SHACF_FILESYSTEM
-# define SHACF_FILESYSTEM 1
-#endif
-
-// other stuff
-
-#ifndef CP_ACP
-# define CP_ACP 0
-#endif
-
-#ifndef COLOR_BTNFACE
-# define COLOR_BTNFACE 15
-#endif
-#ifndef COLOR_WINDOW
-# define COLOR_WINDOW 5
-#endif
-
-// resources
-
-#ifndef RT_BITMAP
-# define RT_BITMAP MAKEINTRESOURCE(2)
-#endif
-#ifndef RT_ICON
-# define RT_ICON MAKEINTRESOURCE(3)
-#endif
-#ifndef RT_DIALOG
-# define RT_DIALOG MAKEINTRESOURCE(5)
-#endif
-#ifndef RT_GROUP_ICON
-# define RT_GROUP_ICON MAKEINTRESOURCE(14)
-#endif
-#ifndef RT_VERSION
-# define RT_VERSION MAKEINTRESOURCE(16)
-#endif
-
-// version
-
-#ifndef VS_FILE_INFO
-# define VS_FILE_INFO RT_VERSION
-#endif
-#ifndef VS_VERSION_INFO
-# define VS_VERSION_INFO 1
-#endif
-#ifndef VS_FFI_SIGNATURE
-# define VS_FFI_SIGNATURE 0xFEEF04BD
-#endif
-
-// message box
-
-#ifndef MB_OK
-# define MB_OK 0
-# define MB_OKCANCEL 1
-# define MB_ABORTRETRYIGNORE 2
-# define MB_YESNOCANCEL 3
-# define MB_YESNO 4
-# define MB_RETRYCANCEL 5
-# define MB_DEFBUTTON1 0
-# define MB_DEFBUTTON2 256
-# define MB_DEFBUTTON3 512
-# define MB_DEFBUTTON4 768
-# define MB_ICONSTOP 16
-# define MB_ICONQUESTION 32
-# define MB_ICONEXCLAMATION 48
-# define MB_ICONINFORMATION 64
-# define MB_USERICON 128
-# define MB_SETFOREGROUND 0x10000
-# define MB_TOPMOST 0x40000
-# define MB_RIGHT 0x80000
-# define MB_RTLREADING 0x100000
-#endif
-
-#ifndef IDOK
-# define IDOK 1
-# define IDCANCEL 2
-# define IDABORT 3
-# define IDRETRY 4
-# define IDIGNORE 5
-# define IDYES 6
-# define IDNO 7
-#endif
-
-// window styles
-
-#ifndef _WIN32
-# define WS_CHILD 0x40000000
-# define WS_VISIBLE 0x10000000
-
-# define BS_CHECKBOX 2
-# define BS_LEFT 256
-# define BS_LEFTTEXT 32
-# define BS_RADIOBUTTON 4
-# define BS_RIGHT 512
-# define BS_USERBUTTON 8
-
-# define ES_LEFT 0
-# define ES_CENTER 1
-# define ES_RIGHT 2
-
-# define SS_BITMAP 14
-# define SS_CENTER 1
-# define SS_CENTERIMAGE 512
-# define SS_ICON 3
-# define SS_LEFT 0
-# define SS_LEFTNOWORDWRAP 0xc
-# define SS_RIGHT 2
-# define SS_RIGHTJUST 0x400
-# define SS_USERITEM 10
-# define SS_TYPEMASK 0x0000001FL
-
-# define DS_FIXEDSYS 8
-# define DS_SETFONT 64
-
-# define WS_EX_RIGHT 0x1000
-# define WS_EX_RIGHTSCROLLBAR 0
-# define WS_EX_RTLREADING 0x2000
-# define WS_EX_LEFTSCROLLBAR 0x4000
-
-# define TVS_RTLREADING 64
-
-# define PBS_SMOOTH 1
-#endif
-
-#ifndef DS_SHELLFONT
-# define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS)
-#endif
-
-// brush styles
-
-#ifndef BS_SOLID
-# define BS_SOLID 0
-#endif
-#ifndef BS_NULL
-# define BS_NULL 1
-#endif
-
-// reg
-#ifndef HKEY_CLASSES_ROOT
-# define HKEY_CLASSES_ROOT ((HKEY)0x80000000)
-# define HKEY_CURRENT_USER ((HKEY)0x80000001)
-# define HKEY_LOCAL_MACHINE ((HKEY)0x80000002)
-# define HKEY_USERS ((HKEY)0x80000003)
-# define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004)
-# define HKEY_CURRENT_CONFIG ((HKEY)0x80000005)
-# define HKEY_DYN_DATA ((HKEY)0x80000006)
-#endif
-
-#ifndef KEY_WOW64_64KEY
-# define KEY_WOW64_64KEY 0x100
-#endif
-
-// show modes
-
-#ifndef SW_SHOWNORMAL
-# define SW_HIDE 0
-# define SW_SHOWNORMAL 1
-# define SW_SHOWMINIMIZED 2
-# define SW_SHOWMAXIMIZED 3
-# define SW_SHOWNOACTIVATE 4
-# define SW_SHOWMINNOACTIVE 7
-# define SW_SHOWNA 8
-#endif
-
-// hotkeys
-
-#ifndef HOTKEYF_SHIFT
-# define HOTKEYF_SHIFT 1
-# define HOTKEYF_CONTROL 2
-# define HOTKEYF_ALT 4
-# define HOTKEYF_EXT 8
-#endif
-
-// vk
-#ifndef VK_F1
-# define VK_F1 0x70
-#endif
-
-// gdi
-
-#ifndef OPAQUE
-# define OPAQUE 2
-#endif
-#ifndef TRANSPARENT
-# define TRANSPARENT 1
-#endif
-#ifndef LF_FACESIZE
-# define LF_FACESIZE 32
-#endif
-#ifndef FW_NORMAL
-# define FW_NORMAL 400
-#endif
-#ifndef FW_BOLD
-# define FW_BOLD 700
-#endif
-#ifndef DEFAULT_CHARSET
-# define DEFAULT_CHARSET 1
-#endif
-#ifndef OUT_DEFAULT_PRECIS
-# define OUT_DEFAULT_PRECIS 0
-#endif
-#ifndef CLIP_DEFAULT_PRECIS
-# define CLIP_DEFAULT_PRECIS 0
-#endif
-#ifndef DEFAULT_QUALITY
-# define DEFAULT_QUALITY 0
-#endif
-#ifndef DEFAULT_PITCH
-# define DEFAULT_PITCH 0
-#endif
-
-// file ops
-
-#ifndef FOF_SILENT
-# define FOF_SILENT 4
-# define FOF_NOCONFIRMATION 16
-# define FOF_FILESONLY 128
-# define FOF_SIMPLEPROGRESS 256
-# define FOF_NOCONFIRMMKDIR 512
-#endif
-
-// file attribs
-
-#ifndef FILE_ATTRIBUTE_READONLY
-# define FILE_ATTRIBUTE_READONLY 0x00000001
-# define FILE_ATTRIBUTE_HIDDEN 0x00000002
-# define FILE_ATTRIBUTE_SYSTEM 0x00000004
-# define FILE_ATTRIBUTE_ARCHIVE 0x00000020
-# define FILE_ATTRIBUTE_NORMAL 0x00000080
-# define FILE_ATTRIBUTE_TEMPORARY 0x00000100
-# define FILE_ATTRIBUTE_OFFLINE 0x00001000
-#endif
-
-// registry
-
-#ifndef REG_SZ
-# define REG_SZ 1
-# define REG_EXPAND_SZ 2
-# define REG_BINARY 3
-# define REG_DWORD 4
-#endif
-
-// fopen
-#ifndef GENERIC_READ
-# define GENERIC_READ 0x80000000
-# define GENERIC_WRITE 0x40000000
-#endif
-
-#ifndef CREATE_NEW
-# define CREATE_NEW 1
-# define CREATE_ALWAYS 2
-# define OPEN_EXISTING 3
-# define OPEN_ALWAYS 4
-#endif
-
-// fseek
-
-#ifndef FILE_BEGIN
-# define FILE_BEGIN 0
-# define FILE_CURRENT 1
-# define FILE_END 2
-#endif
-
-// PE
-
-#ifndef _WIN32
-# define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-# ifndef __BIG_ENDIAN__
-# define IMAGE_DOS_SIGNATURE 0x5A4D
-# define IMAGE_NT_SIGNATURE 0x00004550
-# else
-# define IMAGE_DOS_SIGNATURE 0x4D5A
-# define IMAGE_NT_SIGNATURE 0x50450000
-# endif
-# define IMAGE_FILE_DLL 8192
-# define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-# define IMAGE_SIZEOF_SHORT_NAME 8
-#endif
-
-// structures
-
-#ifndef _WIN32
-typedef struct _LOGFONT {
- LONG lfHeight;
- LONG lfWidth;
- LONG lfEscapement;
- LONG lfOrientation;
- LONG lfWeight;
- BYTE lfItalic;
- BYTE lfUnderline;
- BYTE lfStrikeOut;
- BYTE lfCharSet;
- BYTE lfOutPrecision;
- BYTE lfClipPrecision;
- BYTE lfQuality;
- BYTE lfPitchAndFamily;
- CHAR lfFaceName[LF_FACESIZE];
-} LOGFONT;
-# pragma pack(2)
-typedef struct _IMAGE_DOS_HEADER {
- WORD e_magic;
- WORD e_cblp;
- WORD e_cp;
- WORD e_crlc;
- WORD e_cparhdr;
- WORD e_minalloc;
- WORD e_maxalloc;
- WORD e_ss;
- WORD e_sp;
- WORD e_csum;
- WORD e_ip;
- WORD e_cs;
- WORD e_lfarlc;
- WORD e_ovno;
- WORD e_res[4];
- WORD e_oemid;
- WORD e_oeminfo;
- WORD e_res2[10];
- LONG e_lfanew;
-} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
-# pragma pack()
-# pragma pack(4)
-typedef struct _IMAGE_FILE_HEADER {
- WORD Machine;
- WORD NumberOfSections;
- DWORD TimeDateStamp;
- DWORD PointerToSymbolTable;
- DWORD NumberOfSymbols;
- WORD SizeOfOptionalHeader;
- WORD Characteristics;
-} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
-typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
-} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
-typedef struct _IMAGE_OPTIONAL_HEADER {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Reserved1;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-} IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32;
-typedef struct _IMAGE_OPTIONAL_HEADER64 {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- ULONGLONG ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- ULONGLONG SizeOfStackReserve;
- ULONGLONG SizeOfStackCommit;
- ULONGLONG SizeOfHeapReserve;
- ULONGLONG SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
-} IMAGE_OPTIONAL_HEADER64,*PIMAGE_OPTIONAL_HEADER64;
-#ifdef _WIN64
-typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER;
-typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER;
-#else
-typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER;
-typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER;
-#endif
-#ifndef __BIG_ENDIAN__
-# define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
-# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
-#else
-# define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x0b01
-# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x0b02
-#endif
-typedef struct _IMAGE_NT_HEADERS {
- DWORD Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER OptionalHeader;
-} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
-typedef struct _IMAGE_SECTION_HEADER {
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- DWORD PhysicalAddress;
- DWORD VirtualSize;
- } Misc;
- DWORD VirtualAddress;
- DWORD SizeOfRawData;
- DWORD PointerToRawData;
- DWORD PointerToRelocations;
- DWORD PointerToLinenumbers;
- WORD NumberOfRelocations;
- WORD NumberOfLinenumbers;
- DWORD Characteristics;
-} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
-typedef struct _IMAGE_EXPORT_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- DWORD Name;
- DWORD Base;
- DWORD NumberOfFunctions;
- DWORD NumberOfNames;
- DWORD AddressOfFunctions;
- DWORD AddressOfNames;
- DWORD AddressOfNameOrdinals;
-} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
-typedef struct tagVS_FIXEDFILEINFO {
- DWORD dwSignature;
- DWORD dwStrucVersion;
- DWORD dwFileVersionMS;
- DWORD dwFileVersionLS;
- DWORD dwProductVersionMS;
- DWORD dwProductVersionLS;
- DWORD dwFileFlagsMask;
- DWORD dwFileFlags;
- DWORD dwFileOS;
- DWORD dwFileType;
- DWORD dwFileSubtype;
- DWORD dwFileDateMS;
- DWORD dwFileDateLS;
-} VS_FIXEDFILEINFO;
-# pragma pack()
-#endif
-
-#ifndef SHGFP_TYPE_CURRENT
- #define SHGFP_TYPE_CURRENT 0
-#endif
-
-#endif
+/* + * Platform.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___PLATFORM__H___ +#define ___PLATFORM__H___ + +// some definitions for non Win32 platforms were taken from MinGW's free Win32 library + +// includes + +#ifdef _WIN32 +# include <windows.h> +# include <commctrl.h> +#else +# ifndef EXEHEAD +# include <string.h> +# include <stdlib.h> +# endif +// basic types +typedef unsigned char BYTE, *PBYTE, *LPBYTE; +typedef unsigned short WORD, *LPWORD; +typedef unsigned int DWORD, *LPDWORD; +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned int UINT; +typedef unsigned int UINT32; +typedef int INT; +typedef int INT32; +typedef long LONG; +typedef unsigned long ULONG; +typedef long long INT64, LARGE_INTEGER; +typedef unsigned long long UINT64, ULARGE_INTEGER; +typedef int BOOL, *LPBOOL; +typedef short VARIANT_BOOL; +typedef void VOID; +typedef void *LPVOID; +typedef char CHAR, *PCHAR, *LPCH, *PCH, *NPSTR, *LPSTR, *PSTR; +typedef unsigned char UCHAR; +typedef const char *LPCCH, *PCSTR, *LPCSTR; +typedef unsigned short WCHAR, OLECHAR, *PWCHAR, *LPWCH, *PWCH, *NWPSTR, *LPWSTR, *PWSTR, *BSTR; +typedef const unsigned short *LPCWCH, *PCWCH, *LPCWSTR, *PCWSTR, *LPCOLESTR; +typedef unsigned int UINT_PTR; +// basic stuff +typedef void * HANDLE; +typedef HANDLE HWND; +typedef unsigned long HKEY; +// some gdi +typedef unsigned long COLORREF; +typedef unsigned long HBRUSH; +// bool +# define FALSE 0 +# define TRUE 1 +// more +typedef WORD LANGID; +// ULONGLONG +#ifdef __GNUC__ +#define _HAVE_INT64 +#define _INTEGRAL_MAX_BITS 64 +#undef __int64 +#define __int64 long long +#elif defined(__WATCOMC__) && (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 ) +#define _HAVE_INT64 +#endif /* __GNUC__/__WATCOMC */ +#if defined(_HAVE_INT64) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64) +typedef __int64 LONGLONG; +typedef unsigned __int64 DWORDLONG; +#else +typedef double LONGLONG,DWORDLONG; +#endif +typedef LONGLONG *PLONGLONG; +typedef DWORDLONG *PDWORDLONG; +typedef DWORDLONG ULONGLONG,*PULONGLONG; +#endif + +#ifndef __BIG_ENDIAN__ +# define FIX_ENDIAN_INT32_INPLACE(x) ((void)(x)) +# define FIX_ENDIAN_INT32(x) (x) +# define FIX_ENDIAN_INT16_INPLACE(x) ((void)(x)) +# define FIX_ENDIAN_INT16(x) (x) +#else +# define FIX_ENDIAN_INT32_INPLACE(x) ((x) = SWAP_ENDIAN_INT32(x)) +# define FIX_ENDIAN_INT32(x) SWAP_ENDIAN_INT32(x) +# define FIX_ENDIAN_INT16_INPLACE(x) ((x) = SWAP_ENDIAN_INT16(x)) +# define FIX_ENDIAN_INT16(x) SWAP_ENDIAN_INT16(x) +#endif +#define SWAP_ENDIAN_INT32(x) ( \ + (((x)&0xFF000000) >> 24) | \ + (((x)&0x00FF0000) >> 8) | \ + (((x)&0x0000FF00) << 8) | \ + (((x)&0x000000FF) << 24) ) +#define SWAP_ENDIAN_INT16(x) ( \ + (((x)&0xFF00) >> 8) | \ + (((x)&0x00FF) << 8) ) + +// script path separator + +# define PATH_SEPARATOR_STR "\\" +# define PATH_SEPARATOR_C '\\' + +// system specific characters + +#ifdef _WIN32 +# define PLATFORM_PATH_SEPARATOR_STR "\\" +# define PLATFORM_PATH_SEPARATOR_C '\\' +# define OPT_STR "/" +# define OPT_C '/' +# define IS_OPT(a) (a[0]==OPT_C||a[0]=='-') +#else +# define PLATFORM_PATH_SEPARATOR_STR "/" +# define PLATFORM_PATH_SEPARATOR_C '/' +# define OPT_STR "-" +# define OPT_C '-' +# define IS_OPT(a) (a[0]==OPT_C) +#endif + +// attributes + +#ifdef _MSC_VER +# define FORCE_INLINE __forceinline +#else +# ifdef __GNUC__ +# if __GNUC__ < 3 +# define FORCE_INLINE inline +# else +# define FORCE_INLINE inline __attribute__ ((always_inline)) +# endif +# else +# define FORCE_INLINE inline +# endif +#endif + +// Added by Dave Laundon 19th August 2002 +// For all internal functions, use of stdcall calling convention moves the +// responsibility for tidying the stack to callee from caller, reducing the code +// involved considerably. Gives an instant saving of 0.5K. +// NB - the zlib and bzip2 portions have been given the same treatment, but with +// project compiler-options settings and/or project-wide defines. +// NB - safer for NSIS's routines to be defined explicitly to avoid problems +// calling DLL functions. +#if defined(_WIN32) && ((_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)) +# define NSISCALL __stdcall // Ordinary functions +# define NSISCALLV __cdecl // Variable-argument-list functions +#else +# if defined(__GNUC__) && defined(__i386__) +# define NSISCALL __attribute__((__stdcall__)) // Ordinary functions +# define NSISCALLV __attribute__((__cdecl__)) // Variable-argument-list functions +# else +# define NSISCALL +# define NSISCALLV +# endif +#endif + +#if defined(__GNUC__) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +// macros + +#ifndef _WIN32 +# ifndef FIELD_OFFSET +# define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f)) +# endif +# ifndef MAKEINTRESOURCEA +# define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) +# endif +# ifndef MAKEINTRESOURCEW +# define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) +# endif +# ifndef MAKEINTRESOURCE +# define MAKEINTRESOURCE MAKEINTRESOURCEA +# endif +# ifndef IMAGE_FIRST_SECTION +# define IMAGE_FIRST_SECTION(h) ( PIMAGE_SECTION_HEADER( (DWORD) h + \ + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + \ + FIX_ENDIAN_INT16(PIMAGE_NT_HEADERS(h)->FileHeader.SizeOfOptionalHeader) ) ) +# endif +# ifndef RGB +# define RGB(r,g,b) ((DWORD)(((BYTE)(r)|((WORD)(g)<<8))|(((DWORD)(BYTE)(b))<<16))) +# endif +# ifndef MAKELONG +# define MAKELONG(a,b) ((LONG)(((WORD)(a))|(((DWORD)((WORD)(b)))<<16))) +# endif +#endif +#ifndef IS_INTRESOURCE +# define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0) +#endif + +// functions + +#ifndef _WIN32 +# define stricmp strcasecmp +# define strcmpi strcasecmp +# define strnicmp strncasecmp +# define CopyMemory memcpy +# define ZeroMemory(x, y) memset(x, 0, y) +#endif + +// defines + +#ifndef FOF_NOERRORUI +# define FOF_NOERRORUI 0x0400 +#endif + +#ifndef ULONG_PTR +# define ULONG_PTR DWORD +#endif + +#ifndef IDC_HAND +# define IDC_HAND MAKEINTRESOURCE(32649) +#endif + +#ifndef BIF_NEWDIALOGSTYLE +# define BIF_NEWDIALOGSTYLE 0x0040 +#endif + +#ifndef TVITEM +# define TVITEM TV_ITEM +#endif + +#ifndef TVM_SETITEMHEIGHT +# define TVM_SETITEMHEIGHT (TV_FIRST + 27) +#endif + +#ifndef TVM_GETITEMHEIGHT +# define TVM_GETITEMHEIGHT (TV_FIRST + 28) +#endif + +#ifndef LVS_EX_LABELTIP +# define LVS_EX_LABELTIP 0x00004000 +#endif + +#ifndef EXEHEAD +# ifndef SF_TEXT +# define SF_TEXT 1 +# endif +# ifndef SF_RTF +# define SF_RTF 2 +# endif +#endif + +#ifdef __GNUC__ +# undef INVALID_FILE_ATTRIBUTES +#endif +#ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES ((unsigned long) -1) +#endif + +// shell folders + +#ifdef _WIN32 +# include <shlobj.h> +#endif + +#ifndef CSIDL_FLAG_CREATE +# define CSIDL_FLAG_CREATE 0x8000 +#endif + +#ifndef CSIDL_PROGRAMS +# define CSIDL_PROGRAMS 0x2 +#endif +#ifndef CSIDL_COMMON_PROGRAMS +# define CSIDL_COMMON_PROGRAMS 0x17 +#endif +#ifndef CSIDL_PRINTERS +# define CSIDL_PRINTERS 0x4 +#endif +#ifndef CSIDL_PERSONAL +# define CSIDL_PERSONAL 0x5 +#endif +#ifndef CSIDL_COMMON_DOCUMENTS +# define CSIDL_COMMON_DOCUMENTS 0x2E +#endif +#ifndef CSIDL_FAVORITES +# define CSIDL_FAVORITES 0x6 +#endif +#ifndef CSIDL_COMMON_FAVORITES +# define CSIDL_COMMON_FAVORITES 0x1F +#endif +#ifndef CSIDL_STARTUP +# define CSIDL_STARTUP 0x7 +#endif +#ifndef CSIDL_COMMON_STARTUP +# define CSIDL_COMMON_STARTUP 0x18 +#endif +#ifndef CSIDL_RECENT +# define CSIDL_RECENT 0x8 +#endif +#ifndef CSIDL_SENDTO +# define CSIDL_SENDTO 0x9 +#endif +#ifndef CSIDL_STARTMENU +# define CSIDL_STARTMENU 0xB +#endif +#ifndef CSIDL_COMMON_STARTMENU +# define CSIDL_COMMON_STARTMENU 0x16 +#endif +#ifndef CSIDL_DESKTOPDIRECTORY +# define CSIDL_DESKTOPDIRECTORY 0x10 +#endif +#ifndef CSIDL_COMMON_DESKTOPDIRECTORY +# define CSIDL_COMMON_DESKTOPDIRECTORY 0x19 +#endif +#ifndef CSIDL_NETHOOD +# define CSIDL_NETHOOD 0x13 +#endif +#ifndef CSIDL_FONTS +# define CSIDL_FONTS 0x14 +#endif +#ifndef CSIDL_TEMPLATES +# define CSIDL_TEMPLATES 0x15 +#endif +#ifndef CSIDL_COMMON_TEMPLATES +# define CSIDL_COMMON_TEMPLATES 0x2D +#endif +#ifndef CSIDL_APPDATA +# define CSIDL_APPDATA 0x1A +#endif +#ifndef CSIDL_COMMON_APPDATA +# define CSIDL_COMMON_APPDATA 0x23 +#endif +#ifndef CSIDL_LOCAL_APPDATA +# define CSIDL_LOCAL_APPDATA 0x1C +#endif +#ifndef CSIDL_PRINTHOOD +# define CSIDL_PRINTHOOD 0x1B +#endif +#ifndef CSIDL_ALTSTARTUP +# define CSIDL_ALTSTARTUP 0x1D +#endif +#ifndef CSIDL_COMMON_ALTSTARTUP +# define CSIDL_COMMON_ALTSTARTUP 0x1E +#endif +#ifndef CSIDL_INTERNET_CACHE +# define CSIDL_INTERNET_CACHE 0x20 +#endif +#ifndef CSIDL_COOKIES +# define CSIDL_COOKIES 0x21 +#endif +#ifndef CSIDL_HISTORY +# define CSIDL_HISTORY 0x22 +#endif +#ifndef CSIDL_WINDOWS +# define CSIDL_WINDOWS 0x24 +#endif +#ifndef CSIDL_SYSTEM +# define CSIDL_SYSTEM 0x25 +#endif +#ifndef CSIDL_PROGRAM_FILES +# define CSIDL_PROGRAM_FILES 0x26 +#endif +#ifndef CSIDL_PROGRAM_FILES_COMMON +# define CSIDL_PROGRAM_FILES_COMMON 0x2B +#endif +#ifndef CSIDL_MYPICTURES +# define CSIDL_MYPICTURES 0x27 +#endif +#ifndef CSIDL_COMMON_PICTURES +# define CSIDL_COMMON_PICTURES 0x36 +#endif +#ifndef CSIDL_PROFILE +# define CSIDL_PROFILE 0x28 +#endif +#ifndef CSIDL_ADMINTOOLS +# define CSIDL_ADMINTOOLS 0x30 +#endif +#ifndef CSIDL_COMMON_ADMINTOOLS +# define CSIDL_COMMON_ADMINTOOLS 0x2F +#endif +#ifndef CSIDL_MYMUSIC +# define CSIDL_MYMUSIC 0xD +#endif +#ifndef CSIDL_COMMON_MUSIC +# define CSIDL_COMMON_MUSIC 0x35 +#endif +#ifndef CSIDL_MYVIDEO +# define CSIDL_MYVIDEO 0xE +#endif +#ifndef CSIDL_COMMON_VIDEO +# define CSIDL_COMMON_VIDEO 0x37 +#endif +#ifndef CSIDL_RESOURCES +# define CSIDL_RESOURCES 0x38 +#endif +#ifndef CSIDL_RESOURCES_LOCALIZED +# define CSIDL_RESOURCES_LOCALIZED 0x39 +#endif +#ifndef CSIDL_CDBURN_AREA +# define CSIDL_CDBURN_AREA 0x3B +#endif + +// other shell stuff + +#ifndef SHACF_FILESYSTEM +# define SHACF_FILESYSTEM 1 +#endif + +// other stuff + +#ifndef CP_ACP +# define CP_ACP 0 +#endif + +#ifndef COLOR_BTNFACE +# define COLOR_BTNFACE 15 +#endif +#ifndef COLOR_WINDOW +# define COLOR_WINDOW 5 +#endif + +// resources + +#ifndef RT_BITMAP +# define RT_BITMAP MAKEINTRESOURCE(2) +#endif +#ifndef RT_ICON +# define RT_ICON MAKEINTRESOURCE(3) +#endif +#ifndef RT_DIALOG +# define RT_DIALOG MAKEINTRESOURCE(5) +#endif +#ifndef RT_GROUP_ICON +# define RT_GROUP_ICON MAKEINTRESOURCE(14) +#endif +#ifndef RT_VERSION +# define RT_VERSION MAKEINTRESOURCE(16) +#endif + +// version + +#ifndef VS_FILE_INFO +# define VS_FILE_INFO RT_VERSION +#endif +#ifndef VS_VERSION_INFO +# define VS_VERSION_INFO 1 +#endif +#ifndef VS_FFI_SIGNATURE +# define VS_FFI_SIGNATURE 0xFEEF04BD +#endif + +// message box + +#ifndef MB_OK +# define MB_OK 0 +# define MB_OKCANCEL 1 +# define MB_ABORTRETRYIGNORE 2 +# define MB_YESNOCANCEL 3 +# define MB_YESNO 4 +# define MB_RETRYCANCEL 5 +# define MB_DEFBUTTON1 0 +# define MB_DEFBUTTON2 256 +# define MB_DEFBUTTON3 512 +# define MB_DEFBUTTON4 768 +# define MB_ICONSTOP 16 +# define MB_ICONQUESTION 32 +# define MB_ICONEXCLAMATION 48 +# define MB_ICONINFORMATION 64 +# define MB_USERICON 128 +# define MB_SETFOREGROUND 0x10000 +# define MB_TOPMOST 0x40000 +# define MB_RIGHT 0x80000 +# define MB_RTLREADING 0x100000 +#endif + +#ifndef IDOK +# define IDOK 1 +# define IDCANCEL 2 +# define IDABORT 3 +# define IDRETRY 4 +# define IDIGNORE 5 +# define IDYES 6 +# define IDNO 7 +#endif + +// window styles + +#ifndef _WIN32 +# define WS_CHILD 0x40000000 +# define WS_VISIBLE 0x10000000 + +# define BS_CHECKBOX 2 +# define BS_LEFT 256 +# define BS_LEFTTEXT 32 +# define BS_RADIOBUTTON 4 +# define BS_RIGHT 512 +# define BS_USERBUTTON 8 + +# define ES_LEFT 0 +# define ES_CENTER 1 +# define ES_RIGHT 2 + +# define SS_BITMAP 14 +# define SS_CENTER 1 +# define SS_CENTERIMAGE 512 +# define SS_ICON 3 +# define SS_LEFT 0 +# define SS_LEFTNOWORDWRAP 0xc +# define SS_RIGHT 2 +# define SS_RIGHTJUST 0x400 +# define SS_USERITEM 10 +# define SS_TYPEMASK 0x0000001FL + +# define DS_FIXEDSYS 8 +# define DS_SETFONT 64 + +# define WS_EX_RIGHT 0x1000 +# define WS_EX_RIGHTSCROLLBAR 0 +# define WS_EX_RTLREADING 0x2000 +# define WS_EX_LEFTSCROLLBAR 0x4000 + +# define TVS_RTLREADING 64 + +# define PBS_SMOOTH 1 +#endif + +#ifndef DS_SHELLFONT +# define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS) +#endif + +// brush styles + +#ifndef BS_SOLID +# define BS_SOLID 0 +#endif +#ifndef BS_NULL +# define BS_NULL 1 +#endif + +// reg +#ifndef HKEY_CLASSES_ROOT +# define HKEY_CLASSES_ROOT ((HKEY)0x80000000) +# define HKEY_CURRENT_USER ((HKEY)0x80000001) +# define HKEY_LOCAL_MACHINE ((HKEY)0x80000002) +# define HKEY_USERS ((HKEY)0x80000003) +# define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004) +# define HKEY_CURRENT_CONFIG ((HKEY)0x80000005) +# define HKEY_DYN_DATA ((HKEY)0x80000006) +#endif + +#ifndef KEY_WOW64_64KEY +# define KEY_WOW64_64KEY 0x100 +#endif + +// show modes + +#ifndef SW_SHOWNORMAL +# define SW_HIDE 0 +# define SW_SHOWNORMAL 1 +# define SW_SHOWMINIMIZED 2 +# define SW_SHOWMAXIMIZED 3 +# define SW_SHOWNOACTIVATE 4 +# define SW_SHOWMINNOACTIVE 7 +# define SW_SHOWNA 8 +#endif + +// hotkeys + +#ifndef HOTKEYF_SHIFT +# define HOTKEYF_SHIFT 1 +# define HOTKEYF_CONTROL 2 +# define HOTKEYF_ALT 4 +# define HOTKEYF_EXT 8 +#endif + +// vk +#ifndef VK_F1 +# define VK_F1 0x70 +#endif + +// gdi + +#ifndef OPAQUE +# define OPAQUE 2 +#endif +#ifndef TRANSPARENT +# define TRANSPARENT 1 +#endif +#ifndef LF_FACESIZE +# define LF_FACESIZE 32 +#endif +#ifndef FW_NORMAL +# define FW_NORMAL 400 +#endif +#ifndef FW_BOLD +# define FW_BOLD 700 +#endif +#ifndef DEFAULT_CHARSET +# define DEFAULT_CHARSET 1 +#endif +#ifndef OUT_DEFAULT_PRECIS +# define OUT_DEFAULT_PRECIS 0 +#endif +#ifndef CLIP_DEFAULT_PRECIS +# define CLIP_DEFAULT_PRECIS 0 +#endif +#ifndef DEFAULT_QUALITY +# define DEFAULT_QUALITY 0 +#endif +#ifndef DEFAULT_PITCH +# define DEFAULT_PITCH 0 +#endif + +// file ops + +#ifndef FOF_SILENT +# define FOF_SILENT 4 +# define FOF_NOCONFIRMATION 16 +# define FOF_FILESONLY 128 +# define FOF_SIMPLEPROGRESS 256 +# define FOF_NOCONFIRMMKDIR 512 +#endif + +// file attribs + +#ifndef FILE_ATTRIBUTE_READONLY +# define FILE_ATTRIBUTE_READONLY 0x00000001 +# define FILE_ATTRIBUTE_HIDDEN 0x00000002 +# define FILE_ATTRIBUTE_SYSTEM 0x00000004 +# define FILE_ATTRIBUTE_ARCHIVE 0x00000020 +# define FILE_ATTRIBUTE_NORMAL 0x00000080 +# define FILE_ATTRIBUTE_TEMPORARY 0x00000100 +# define FILE_ATTRIBUTE_OFFLINE 0x00001000 +#endif + +// registry + +#ifndef REG_SZ +# define REG_SZ 1 +# define REG_EXPAND_SZ 2 +# define REG_BINARY 3 +# define REG_DWORD 4 +#endif + +// fopen +#ifndef GENERIC_READ +# define GENERIC_READ 0x80000000 +# define GENERIC_WRITE 0x40000000 +#endif + +#ifndef CREATE_NEW +# define CREATE_NEW 1 +# define CREATE_ALWAYS 2 +# define OPEN_EXISTING 3 +# define OPEN_ALWAYS 4 +#endif + +// fseek + +#ifndef FILE_BEGIN +# define FILE_BEGIN 0 +# define FILE_CURRENT 1 +# define FILE_END 2 +#endif + +// PE + +#ifndef _WIN32 +# define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +# ifndef __BIG_ENDIAN__ +# define IMAGE_DOS_SIGNATURE 0x5A4D +# define IMAGE_NT_SIGNATURE 0x00004550 +# else +# define IMAGE_DOS_SIGNATURE 0x4D5A +# define IMAGE_NT_SIGNATURE 0x50450000 +# endif +# define IMAGE_FILE_DLL 8192 +# define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +# define IMAGE_SIZEOF_SHORT_NAME 8 +#endif + +// structures + +#ifndef _WIN32 +typedef struct _LOGFONT { + LONG lfHeight; + LONG lfWidth; + LONG lfEscapement; + LONG lfOrientation; + LONG lfWeight; + BYTE lfItalic; + BYTE lfUnderline; + BYTE lfStrikeOut; + BYTE lfCharSet; + BYTE lfOutPrecision; + BYTE lfClipPrecision; + BYTE lfQuality; + BYTE lfPitchAndFamily; + CHAR lfFaceName[LF_FACESIZE]; +} LOGFONT; +# pragma pack(2) +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; + WORD e_cblp; + WORD e_cp; + WORD e_crlc; + WORD e_cparhdr; + WORD e_minalloc; + WORD e_maxalloc; + WORD e_ss; + WORD e_sp; + WORD e_csum; + WORD e_ip; + WORD e_cs; + WORD e_lfarlc; + WORD e_ovno; + WORD e_res[4]; + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; + LONG e_lfanew; +} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; +# pragma pack() +# pragma pack(4) +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; +typedef struct _IMAGE_OPTIONAL_HEADER { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Reserved1; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32; +typedef struct _IMAGE_OPTIONAL_HEADER64 { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64,*PIMAGE_OPTIONAL_HEADER64; +#ifdef _WIN64 +typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; +#else +typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER; +#endif +#ifndef __BIG_ENDIAN__ +# define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b +# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b +#else +# define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x0b01 +# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x0b02 +#endif +typedef struct _IMAGE_NT_HEADERS { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS; +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; +typedef struct tagVS_FIXEDFILEINFO { + DWORD dwSignature; + DWORD dwStrucVersion; + DWORD dwFileVersionMS; + DWORD dwFileVersionLS; + DWORD dwProductVersionMS; + DWORD dwProductVersionLS; + DWORD dwFileFlagsMask; + DWORD dwFileFlags; + DWORD dwFileOS; + DWORD dwFileType; + DWORD dwFileSubtype; + DWORD dwFileDateMS; + DWORD dwFileDateLS; +} VS_FIXEDFILEINFO; +# pragma pack() +#endif + +#ifndef SHGFP_TYPE_CURRENT + #define SHGFP_TYPE_CURRENT 0 +#endif + +#endif diff --git a/Source/Plugins.cpp b/Source/Plugins.cpp index 9e4d5c5..9c2999e 100755 --- a/Source/Plugins.cpp +++ b/Source/Plugins.cpp @@ -1,207 +1,207 @@ -/*
- * Plugins.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "exehead/config.h"
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
-
-#include <map>
-#include <string>
-#include <fstream>
-
-#include "Plugins.h"
-#include "Platform.h"
-#include "util.h"
-#include "ResourceEditor.h"
-
-#include "dirreader.h"
-
-#ifdef _WIN32
-# include <WinNT.h>
-#else
-# include <sys/stat.h>
-#endif
-
-#include "boost/scoped_ptr.hpp"
-
-using namespace std;
-
-extern FILE *g_output;
-
-void Plugins::FindCommands(const string &path, bool displayInfo)
-{
- boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
- dr->read(path);
-
- for (dir_reader::iterator files_itr = dr->files().begin();
- files_itr != dr->files().end();
- files_itr++)
- {
- if (!dir_reader::matches(*files_itr, "*.dll"))
- continue;
-
- const string plugin = path + PLATFORM_PATH_SEPARATOR_C + *files_itr;
- GetExports(plugin, displayInfo);
- }
-}
-
-struct NSISException : public std::runtime_error
-{
- NSISException(const string& msg) : std::runtime_error(msg) {}
-};
-
-namespace {
-size_t file_size(ifstream& file) {
- const ifstream::pos_type pos = file.tellg();
-
- file.seekg(0, ios::end);
-
- ifstream::pos_type result = file.tellg();
- assert(result >= (ifstream::pos_type)0);
-
- file.seekg(pos);
-
- return (size_t)result;
-}
-
-vector<unsigned char> read_file(const string& filename) {
- ifstream file(filename.c_str(), ios::binary);
-
- if (!file) {
- throw NSISException("Can't open file '" + filename + "'");
- }
-
- // get the file size
- size_t filesize = file_size(file);
-
- vector<unsigned char> result;
- result.resize(filesize);
-
- file.read(reinterpret_cast<char*>(&result[0]), filesize);
-
- if (size_t(file.tellg()) != filesize) { // ifstream::eof doesn't return true here
- throw NSISException("Couldn't read entire file '" + filename + "'");
- }
-
- return result;
-}
-}
-
-void Plugins::GetExports(const string &pathToDll, bool displayInfo)
-{
- vector<unsigned char> dlldata;
- PIMAGE_NT_HEADERS NTHeaders;
- try {
- dlldata = read_file(pathToDll);
- NTHeaders = CResourceEditor::GetNTHeaders(&dlldata[0]);
- } catch (std::runtime_error&) {
- return;
- }
-
- const string dllName = remove_file_extension(get_file_name(pathToDll));
-
- FIX_ENDIAN_INT16_INPLACE(NTHeaders->FileHeader.Characteristics);
- if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
- {
- FIX_ENDIAN_INT32_INPLACE(NTHeaders->OptionalHeader.NumberOfRvaAndSizes);
- if (NTHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) return;
-
- DWORD ExportDirVA = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- DWORD ExportDirSize = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
- PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(NTHeaders);
-
- FIX_ENDIAN_INT32_INPLACE(ExportDirVA);
- FIX_ENDIAN_INT32_INPLACE(ExportDirSize);
-
- WORD num_sections = FIX_ENDIAN_INT16(NTHeaders->FileHeader.NumberOfSections);
-
- for (DWORD i = 0; i < num_sections; i++)
- {
- DWORD va = FIX_ENDIAN_INT32(sections[i].VirtualAddress);
- if (va <= ExportDirVA
- && va + FIX_ENDIAN_INT32(sections[i].Misc.VirtualSize) >= ExportDirVA + ExportDirSize)
- {
- DWORD prd = FIX_ENDIAN_INT32(sections[i].PointerToRawData);
- PIMAGE_EXPORT_DIRECTORY exports = PIMAGE_EXPORT_DIRECTORY(&dlldata[0] + prd + ExportDirVA - va);
- DWORD na = FIX_ENDIAN_INT32(exports->AddressOfNames);
- unsigned long *names = (unsigned long*)((unsigned long) exports + (char *) na - ExportDirVA);
- for (unsigned long j = 0; j < FIX_ENDIAN_INT32(exports->NumberOfNames); j++)
- {
- const string name = string((char*)exports + FIX_ENDIAN_INT32(names[j]) - ExportDirVA);
- const string signature = dllName + "::" + name;
- const string lcsig = lowercase(signature);
- m_command_to_path[lcsig] = pathToDll;
- m_command_lowercase_to_command[lcsig] = signature;
- if (displayInfo)
- fprintf(g_output, " - %s\n", signature.c_str());
- }
- break;
- }
- }
- }
-}
-
-bool Plugins::IsPluginCommand(const string& token) const {
- return m_command_to_path.find(lowercase(token)) != m_command_to_path.end();
-}
-
-namespace {
-template <class Key, class Value>
-Value get_value(const map<Key, Value>& the_map,
- const Key& key)
-{
- assert(the_map.find(key) != the_map.end());
- return the_map.find(key)->second;
-}
-
-template <class Key, class Value>
-Value get_value(const map<Key, Value>& the_map,
- const Key& key,
- const Value& defaultValue)
-{
- if (the_map.find(key) == the_map.end())
- return defaultValue;
- return the_map.find(key)->second;
-}
-}
-
-string Plugins::NormalizedCommand(const string& command) const {
- return get_value(m_command_lowercase_to_command, lowercase(command));
-}
-
-int Plugins::GetPluginHandle(bool uninst, const string& command) const {
- if (uninst) {
- return get_value(m_command_to_uninstall_data_handle, command, -1);
- }
- else {
- return get_value(m_command_to_data_handle, command, -1);
- }
-}
-
-string Plugins::GetPluginPath(const string& command) const {
- return get_value(m_command_to_path, lowercase(command));
-}
-
-void Plugins::SetDllDataHandle(bool uninst, const string& command, int dataHandle)
-{
- if (uninst) {
- m_command_to_uninstall_data_handle[command] = dataHandle;
- }
- else {
- m_command_to_data_handle[command] = dataHandle;
- }
-}
-
-#endif
+/* + * Plugins.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "exehead/config.h" +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + +#include <map> +#include <string> +#include <fstream> + +#include "Plugins.h" +#include "Platform.h" +#include "util.h" +#include "ResourceEditor.h" + +#include "dirreader.h" + +#ifdef _WIN32 +# include <WinNT.h> +#else +# include <sys/stat.h> +#endif + +#include "boost/scoped_ptr.hpp" + +using namespace std; + +extern FILE *g_output; + +void Plugins::FindCommands(const string &path, bool displayInfo) +{ + boost::scoped_ptr<dir_reader> dr( new_dir_reader() ); + dr->read(path); + + for (dir_reader::iterator files_itr = dr->files().begin(); + files_itr != dr->files().end(); + files_itr++) + { + if (!dir_reader::matches(*files_itr, "*.dll")) + continue; + + const string plugin = path + PLATFORM_PATH_SEPARATOR_C + *files_itr; + GetExports(plugin, displayInfo); + } +} + +struct NSISException : public std::runtime_error +{ + NSISException(const string& msg) : std::runtime_error(msg) {} +}; + +namespace { +size_t file_size(ifstream& file) { + const ifstream::pos_type pos = file.tellg(); + + file.seekg(0, ios::end); + + ifstream::pos_type result = file.tellg(); + assert(result >= (ifstream::pos_type)0); + + file.seekg(pos); + + return (size_t)result; +} + +vector<unsigned char> read_file(const string& filename) { + ifstream file(filename.c_str(), ios::binary); + + if (!file) { + throw NSISException("Can't open file '" + filename + "'"); + } + + // get the file size + size_t filesize = file_size(file); + + vector<unsigned char> result; + result.resize(filesize); + + file.read(reinterpret_cast<char*>(&result[0]), filesize); + + if (size_t(file.tellg()) != filesize) { // ifstream::eof doesn't return true here + throw NSISException("Couldn't read entire file '" + filename + "'"); + } + + return result; +} +} + +void Plugins::GetExports(const string &pathToDll, bool displayInfo) +{ + vector<unsigned char> dlldata; + PIMAGE_NT_HEADERS NTHeaders; + try { + dlldata = read_file(pathToDll); + NTHeaders = CResourceEditor::GetNTHeaders(&dlldata[0]); + } catch (std::runtime_error&) { + return; + } + + const string dllName = remove_file_extension(get_file_name(pathToDll)); + + FIX_ENDIAN_INT16_INPLACE(NTHeaders->FileHeader.Characteristics); + if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) + { + FIX_ENDIAN_INT32_INPLACE(NTHeaders->OptionalHeader.NumberOfRvaAndSizes); + if (NTHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) return; + + DWORD ExportDirVA = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + DWORD ExportDirSize = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(NTHeaders); + + FIX_ENDIAN_INT32_INPLACE(ExportDirVA); + FIX_ENDIAN_INT32_INPLACE(ExportDirSize); + + WORD num_sections = FIX_ENDIAN_INT16(NTHeaders->FileHeader.NumberOfSections); + + for (DWORD i = 0; i < num_sections; i++) + { + DWORD va = FIX_ENDIAN_INT32(sections[i].VirtualAddress); + if (va <= ExportDirVA + && va + FIX_ENDIAN_INT32(sections[i].Misc.VirtualSize) >= ExportDirVA + ExportDirSize) + { + DWORD prd = FIX_ENDIAN_INT32(sections[i].PointerToRawData); + PIMAGE_EXPORT_DIRECTORY exports = PIMAGE_EXPORT_DIRECTORY(&dlldata[0] + prd + ExportDirVA - va); + DWORD na = FIX_ENDIAN_INT32(exports->AddressOfNames); + unsigned long *names = (unsigned long*)((unsigned long) exports + (char *) na - ExportDirVA); + for (unsigned long j = 0; j < FIX_ENDIAN_INT32(exports->NumberOfNames); j++) + { + const string name = string((char*)exports + FIX_ENDIAN_INT32(names[j]) - ExportDirVA); + const string signature = dllName + "::" + name; + const string lcsig = lowercase(signature); + m_command_to_path[lcsig] = pathToDll; + m_command_lowercase_to_command[lcsig] = signature; + if (displayInfo) + fprintf(g_output, " - %s\n", signature.c_str()); + } + break; + } + } + } +} + +bool Plugins::IsPluginCommand(const string& token) const { + return m_command_to_path.find(lowercase(token)) != m_command_to_path.end(); +} + +namespace { +template <class Key, class Value> +Value get_value(const map<Key, Value>& the_map, + const Key& key) +{ + assert(the_map.find(key) != the_map.end()); + return the_map.find(key)->second; +} + +template <class Key, class Value> +Value get_value(const map<Key, Value>& the_map, + const Key& key, + const Value& defaultValue) +{ + if (the_map.find(key) == the_map.end()) + return defaultValue; + return the_map.find(key)->second; +} +} + +string Plugins::NormalizedCommand(const string& command) const { + return get_value(m_command_lowercase_to_command, lowercase(command)); +} + +int Plugins::GetPluginHandle(bool uninst, const string& command) const { + if (uninst) { + return get_value(m_command_to_uninstall_data_handle, command, -1); + } + else { + return get_value(m_command_to_data_handle, command, -1); + } +} + +string Plugins::GetPluginPath(const string& command) const { + return get_value(m_command_to_path, lowercase(command)); +} + +void Plugins::SetDllDataHandle(bool uninst, const string& command, int dataHandle) +{ + if (uninst) { + m_command_to_uninstall_data_handle[command] = dataHandle; + } + else { + m_command_to_data_handle[command] = dataHandle; + } +} + +#endif diff --git a/Source/Plugins.h b/Source/Plugins.h index 932cf1d..ec9e809 100755 --- a/Source/Plugins.h +++ b/Source/Plugins.h @@ -1,43 +1,43 @@ -/*
- * Plugins.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __X18_PLUGINS_H
-#define __X18_PLUGINS_H
-
-#include <map>
-#include <string>
-
-class Plugins
-{
- public:
- void FindCommands(const std::string& path, bool displayInfo);
- bool IsPluginCommand(const std::string& command) const;
- std::string NormalizedCommand(const std::string& command) const;
- int GetPluginHandle(bool uninst, const std::string& command) const;
- std::string GetPluginPath(const std::string& command) const;
- void SetDllDataHandle(bool uninst, const std::string& command, int dataHandle);
-
- private: // methods
- void GetExports(const std::string &pathToDll, bool displayInfo);
-
- private: // data members
- std::map<std::string, std::string> m_command_lowercase_to_command;
- std::map<std::string, std::string> m_command_to_path;
- std::map<std::string, int> m_command_to_data_handle;
- std::map<std::string, int> m_command_to_uninstall_data_handle;
-};
-
-#endif
+/* + * Plugins.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __X18_PLUGINS_H +#define __X18_PLUGINS_H + +#include <map> +#include <string> + +class Plugins +{ + public: + void FindCommands(const std::string& path, bool displayInfo); + bool IsPluginCommand(const std::string& command) const; + std::string NormalizedCommand(const std::string& command) const; + int GetPluginHandle(bool uninst, const std::string& command) const; + std::string GetPluginPath(const std::string& command) const; + void SetDllDataHandle(bool uninst, const std::string& command, int dataHandle); + + private: // methods + void GetExports(const std::string &pathToDll, bool displayInfo); + + private: // data members + std::map<std::string, std::string> m_command_lowercase_to_command; + std::map<std::string, std::string> m_command_to_path; + std::map<std::string, int> m_command_to_data_handle; + std::map<std::string, int> m_command_to_uninstall_data_handle; +}; + +#endif diff --git a/Source/ResourceEditor.cpp b/Source/ResourceEditor.cpp index 0c42202..13e286f 100755 --- a/Source/ResourceEditor.cpp +++ b/Source/ResourceEditor.cpp @@ -1,1019 +1,1073 @@ -/*
- * ResourceEditor.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2002-2007 Amir Szekely <kichik@users.sourceforge.net>
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "ResourceEditor.h"
-#include "util.h"
-#include "winchar.h"
-#include <queue>
-using namespace std;
-
-//////////////////////////////////////////////////////////////////////
-// 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)
-
-#ifndef _WIN32
-static inline ULONG ConvertEndianness(ULONG u) {
- return FIX_ENDIAN_INT32(u);
-}
-#endif
-
-static inline DWORD ConvertEndianness(DWORD d) {
- return FIX_ENDIAN_INT32(d);
-}
-
-static inline LONG ConvertEndianness(LONG l) {
- return FIX_ENDIAN_INT32(l);
-}
-
-static inline WORD ConvertEndianness(WORD w) {
- return FIX_ENDIAN_INT16(w);
-}
-
-PIMAGE_NT_HEADERS CResourceEditor::GetNTHeaders(BYTE* pbPE) {
- // Get dos header
- PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) pbPE;
- if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
- throw runtime_error("PE file contains invalid DOS header");
-
- // Get NT headers
- PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(pbPE + ConvertEndianness(dosHeader->e_lfanew));
- if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
- throw runtime_error("PE file missing NT signature");
-
- // Make sure this is a supported PE format
- if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
- ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
- throw runtime_error("Unsupported PE format");
-
- return ntHeaders;
-}
-
-PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory(
- BYTE* pbPE,
- DWORD dwSize,
- PIMAGE_NT_HEADERS ntHeaders,
- DWORD *pdwResSecVA /*=NULL*/,
- DWORD *pdwSectionIndex /*=NULL*/
-) {
- PIMAGE_DATA_DIRECTORY dataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory);
- DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes);
-
- if (ConvertEndianness(dwNumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE)
- throw runtime_error("No resource section found");
- // Get resource section virtual address
- DWORD dwResSecVA = ConvertEndianness(dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
- // Pointer to the sections headers array
- PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);
-
- DWORD dwSectionIndex = (DWORD) -1;
-
- // Find resource section index in the array
- for (int i = 0; i < ConvertEndianness(ntHeaders->FileHeader.NumberOfSections); i++) {
- if (dwResSecVA == ConvertEndianness(sectionHeadersArray[i].VirtualAddress)) {
- // Remember resource section index
- dwSectionIndex = i;
- // Check for invalid resource section pointer
- if (!sectionHeadersArray[i].PointerToRawData)
- throw runtime_error("Invalid resource section pointer");
-
- break;
- }
-
- // Invalid section pointer (goes beyond the PE image)
- if (ConvertEndianness(sectionHeadersArray[i].PointerToRawData) > dwSize)
- throw runtime_error("Invalid section pointer");
- }
-
- // No resource section...
- if (dwSectionIndex == (DWORD) -1)
- throw runtime_error("PE file doesn't contain any resource section");
-
- // Return extra parameters
- if (pdwSectionIndex)
- *pdwSectionIndex = dwSectionIndex;
- if (pdwResSecVA)
- *pdwResSecVA = dwResSecVA;
-
- // Pointer to section data, the first resource directory
- DWORD dwResSecPtr = ConvertEndianness(sectionHeadersArray[dwSectionIndex].PointerToRawData);
- return PRESOURCE_DIRECTORY(pbPE + dwResSecPtr);
-}
-
-//////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////
-// CResourceEditor
-//////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize) {
- // Copy the data pointer
- m_pbPE = pbPE;
- m_iSize = iSize;
-
- // Get NT headers
- m_ntHeaders = GetNTHeaders(m_pbPE);
-
- // No check sum support yet...
- DWORD* pdwCheckSum = GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, CheckSum);
- if (*pdwCheckSum)
- {
- // clear checksum (should be [re]calculated after all changes done)
- pdwCheckSum = 0;
- //throw runtime_error("CResourceEditor doesn't yet support check sum");
- }
-
- // Get resource section virtual address, resource section index and pointer to resource directory
- PRESOURCE_DIRECTORY rdRoot = GetResourceDirectory(m_pbPE, iSize, m_ntHeaders, &m_dwResourceSectionVA, &m_dwResourceSectionIndex);
-
- // Scan the resource directory
- m_cResDir = ScanDirectory(rdRoot, rdRoot);
-}
-
-CResourceEditor::~CResourceEditor() {
- if (m_cResDir) {
- m_cResDir->Destroy();
- delete m_cResDir;
- }
-}
-
-//////////////////////////////////////////////////////////////////////
-// Methods
-//////////////////////////////////////////////////////////////////////
-
-// Adds/Replaces/Removes a resource.
-// If lpData is 0 UpdateResource removes the resource.
-bool CResourceEditor::UpdateResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- CResourceDirectory* nameDir = 0;
- CResourceDirectory* langDir = 0;
- CResourceDataEntry* data = 0;
- IMAGE_RESOURCE_DIRECTORY rd = {0, /*time(0),*/};
- int iTypeIdx = -1, iNameIdx = -1, iLangIdx = -1;
-
- 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 true;
- }
-
- 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(MAKEINTRESOURCEW(wLanguage), data));
- }
- }
- else if (data) {
- // Delete the resource
- delete data;
- langDir->RemoveEntry(iLangIdx);
- // Delete directories holding the resource if empty
- if (!langDir->CountEntries()) {
- delete langDir;
- nameDir->RemoveEntry(iNameIdx);
- if (!nameDir->CountEntries()) {
- delete nameDir;
- m_cResDir->RemoveEntry(iTypeIdx);
- }
- }
- }
- else return false;
- return true;
-}
-
-static WCHAR* ResStringToUnicode(const char *szString) {
- if (IS_INTRESOURCE(szString))
- return MAKEINTRESOURCEW((ULONG_PTR)szString);
- else
- return winchar_fromansi(szString);
-}
-
-static void FreeUnicodeResString(WCHAR* szwString) {
- if (!IS_INTRESOURCE(szwString))
- delete [] szwString;
-}
-
-bool CResourceEditor::UpdateResourceW(WORD szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- return UpdateResourceW(MAKEINTRESOURCEW(szType), szName, wLanguage, lpData, dwSize);
-}
-
-bool CResourceEditor::UpdateResourceW(WCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- return UpdateResourceW(szType, MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize);
-}
-
-bool CResourceEditor::UpdateResourceA(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- WCHAR* szwType = ResStringToUnicode(szType);
- WCHAR* szwName = ResStringToUnicode(szName);
-
- bool result = UpdateResourceW(szwType, szwName, wLanguage, lpData, dwSize);
-
- FreeUnicodeResString(szwType);
- FreeUnicodeResString(szwName);
-
- return result;
-}
-
-bool CResourceEditor::UpdateResourceA(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- return UpdateResourceA(MAKEINTRESOURCE(szType), szName, wLanguage, lpData, dwSize);
-}
-
-bool CResourceEditor::UpdateResourceA(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- return UpdateResourceA(szType, MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize);
-}
-
-bool CResourceEditor::UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) {
- return UpdateResourceW(MAKEINTRESOURCEW(szType), MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize);
-}
-
-// Returns a copy of the requested resource
-// Returns 0 if the requested resource can't be found
-BYTE* CResourceEditor::GetResourceW(WCHAR* szType, WCHAR* szName, LANGID 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 = 0;
- if (wLanguage)
- 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 NULL;
-}
-
-BYTE* CResourceEditor::GetResourceA(char* szType, char* szName, LANGID wLanguage) {
- WCHAR* szwType = ResStringToUnicode(szType);
- WCHAR* szwName = ResStringToUnicode(szName);
-
- BYTE* result = GetResourceW(szwType, szwName, wLanguage);
-
- FreeUnicodeResString(szwType);
- FreeUnicodeResString(szwName);
-
- return result;
-}
-
-// Returns the size of the requested resource
-// Returns -1 if the requested resource can't be found
-int CResourceEditor::GetResourceSizeW(WCHAR* szType, WCHAR* szName, LANGID 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 = 0;
- if (wLanguage)
- i = langDir->Find(wLanguage);
- if (i > -1) {
- data = langDir->GetEntry(i)->GetDataEntry();
- }
- }
- }
-
- if (data)
- return (int) data->GetSize();
- else
- return -1;
-}
-
-int CResourceEditor::GetResourceSizeA(char* szType, char* szName, LANGID wLanguage) {
- WCHAR* szwType = ResStringToUnicode(szType);
- WCHAR* szwName = ResStringToUnicode(szName);
-
- int result = GetResourceSizeW(szwType, szwName, wLanguage);
-
- FreeUnicodeResString(szwType);
- FreeUnicodeResString(szwName);
-
- return result;
-}
-
-void CResourceEditor::FreeResource(BYTE* pbResource)
-{
- if (pbResource)
- delete [] pbResource;
-}
-
-// Saves the edited PE into a buffer and returns it.
-DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) {
- unsigned int i;
- DWORD dwReqSize;
-
- DWORD dwFileAlign = ConvertEndianness(m_ntHeaders->OptionalHeader.FileAlignment);
- DWORD dwSecAlign = ConvertEndianness(m_ntHeaders->OptionalHeader.SectionAlignment);
-
- DWORD dwRsrcSize = m_cResDir->GetSize(); // Size of new resource section
- DWORD dwRsrcSizeAligned = RALIGN(dwRsrcSize, dwFileAlign); // Align it to FileAlignment
-
- // Calculate the total new PE size
- DWORD dwOldRsrcSize = ConvertEndianness(IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData);
- dwReqSize = m_iSize - dwOldRsrcSize + dwRsrcSizeAligned;
-
- if (!pbBuf || dwSize < dwReqSize)
- return dwReqSize;
-
- // Use buffer
- BYTE* pbNewPE = pbBuf;
- dwSize = dwReqSize;
- // Fill buffer with zeros
- ZeroMemory(pbNewPE, dwSize);
-
- BYTE* seeker = pbNewPE;
- BYTE* oldSeeker = m_pbPE;
-
- PIMAGE_SECTION_HEADER old_sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders);
-
- DWORD dwHeaderSize = ConvertEndianness(old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData);
- WORD wNumberOfSections = ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections);
-
- // Copy everything until the resource section (including headers and everything that might come after them)
- // We don't use SizeOfHeaders because sometimes (using VC6) it can extend beyond the first section
- // or (Borland) there could be some more information between the headers and the first section.
- CopyMemory(seeker, oldSeeker, dwHeaderSize);
-
- // Skip the headers and whatever comes after them
- seeker += dwHeaderSize;
- oldSeeker += dwHeaderSize;
-
- // Get new nt headers pointer
- PIMAGE_NT_HEADERS ntHeaders = GetNTHeaders(pbNewPE);
- // Get a pointer to the new section headers
- PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);
-
- // Skip the resource section in the old PE seeker.
- oldSeeker += dwOldRsrcSize;
-
- // Save the old virtual size of the resource section
- DWORD dwNewVirtualSize = RALIGN(dwRsrcSize, dwSecAlign);
- DWORD dwOldVirtualSize = ConvertEndianness(sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize);
- ALIGN(dwOldVirtualSize, dwSecAlign);
- DWORD dwVAAdjustment = dwNewVirtualSize - dwOldVirtualSize;
-
- // Set the new size of the resource section (size aligned to FileAlignment)
- sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = ConvertEndianness(dwRsrcSizeAligned);
- // Set the virtual size as well (in memory)
- sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = ConvertEndianness(dwRsrcSize);
- (*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory))[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize);
-
- // Set the new virtual size of the image
- DWORD* pdwSizeOfImage = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfImage);
- *pdwSizeOfImage = AlignVA(*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfHeaders));
- for (i = 0; i < wNumberOfSections; i++) {
- DWORD dwSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize);
- *pdwSizeOfImage = AlignVA(AdjustVA(*pdwSizeOfImage, dwSecSize));
- }
-
- // Set the new AddressOfEntryPoint if needed
- DWORD* pdwAddressOfEntryPoint = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, AddressOfEntryPoint);
- if (ConvertEndianness(*pdwAddressOfEntryPoint) > m_dwResourceSectionVA)
- *pdwAddressOfEntryPoint = AdjustVA(*pdwAddressOfEntryPoint, dwVAAdjustment);
-
- // Set the new BaseOfCode if needed
- DWORD* pdwBaseOfCode = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, BaseOfCode);
- if (ConvertEndianness(*pdwBaseOfCode) > m_dwResourceSectionVA)
- *pdwBaseOfCode = AdjustVA(*pdwBaseOfCode, dwVAAdjustment);
-
- // Set the new BaseOfData if needed
- if (ntHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
- DWORD* pdwBaseOfData = &((PIMAGE_OPTIONAL_HEADER32)&ntHeaders->OptionalHeader)->BaseOfData;
- if (*pdwBaseOfData > m_dwResourceSectionVA)
- *pdwBaseOfData = AdjustVA(*pdwBaseOfData, dwVAAdjustment);
- }
-
- // Refresh the headers of the sections that come after the resource section, and the data directory
- DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes);
- PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory);
- for (i = m_dwResourceSectionIndex + 1; i < wNumberOfSections; i++) {
- if (sectionHeadersArray[i].PointerToRawData) {
- AdjustVA(sectionHeadersArray[i].PointerToRawData, dwRsrcSizeAligned - dwOldRsrcSize);
- }
-
- // We must find the right data directory entry before we change the virtual address
- unsigned int uDataDirIdx = 0;
- for (unsigned int j = 0; j < ConvertEndianness(dwNumberOfRvaAndSizes); j++)
- if (pDataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress)
- uDataDirIdx = j;
-
- sectionHeadersArray[i].VirtualAddress = AdjustVA(sectionHeadersArray[i].VirtualAddress, dwVAAdjustment);
-
- // Change the virtual address in the data directory too
- if (uDataDirIdx)
- pDataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress;
- }
-
- // Write the resource section
- WriteRsrcSec(seeker);
- // Advance the pointer
- seeker += dwRsrcSizeAligned;
-
- // Copy everything that comes after the resource section (other sections and tacked data)
- DWORD dwLeft = m_iSize - (oldSeeker - m_pbPE);
- if (dwLeft)
- CopyMemory(seeker, oldSeeker, dwLeft);
-
- seeker += dwLeft;
- oldSeeker += dwLeft;
-
- /**********************************************************
- * To add checksum to the header use MapFileAndCheckSum
- **********************************************************/
-
- // From now on, we are working on the new PE
- // Freeing the old PE memory is up to the user
- m_pbPE = pbNewPE;
- m_iSize = dwSize;
- m_ntHeaders = ntHeaders;
- // We just wrote the resource section according to m_cResDir, so we don't need to rescan
- // m_dwResourceSectionIndex and m_dwResourceSectionVA have also been left unchanged as
- // we didn't move the resources section
-
- return 0;
-}
-
-// This function scans exe sections and after find a match with given name
-// increments it's virtual size (auto fixes image size based on section alignment, etc)
-bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize)
-{
- PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders);
-
- // Refresh the headers of the sections that come after the resource section, and the data directory
- for (int i = 0; i < ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections); i++) {
- if (!strcmp((LPCSTR)sectionHeadersArray[i].Name, pszSectionName)) {
- sectionHeadersArray[i].Misc.VirtualSize = AlignVA(AdjustVA(sectionHeadersArray[i].Misc.VirtualSize, addsize));
-
- sectionHeadersArray[i].Characteristics &= ConvertEndianness((DWORD) ~IMAGE_SCN_MEM_DISCARDABLE);
-
- // now fix any section after
- for (int k = i + 1; k < ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections); k++, i++) {
- DWORD dwLastSecVA = ConvertEndianness(sectionHeadersArray[i].VirtualAddress);
- DWORD dwLastSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize);
- DWORD dwSecVA = AlignVA(ConvertEndianness(dwLastSecVA + dwLastSecSize));
-
- sectionHeadersArray[k].VirtualAddress = dwSecVA;
-
- if (m_dwResourceSectionIndex == (DWORD) k)
- {
- // fix the resources virtual address if it changed
- PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, DataDirectory);
- pDataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA;
- m_dwResourceSectionVA = ConvertEndianness(dwSecVA);
- }
- }
-
- return true;
- }
- }
-
- return false;
-}
-
-//////////////////////////////////////////////////////////////////////
-// 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));
- WCHAR* szName;
- PIMAGE_RESOURCE_DATA_ENTRY rde = NULL;
-
- // Go through all entries of this resource directory
- int entries = ConvertEndianness(rdToScan->Header.NumberOfNamedEntries);
- entries += ConvertEndianness(rdToScan->Header.NumberOfIdEntries);
-
- for (int i = 0; i < entries; i++) {
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY rd = rdToScan->Entries[i];
- rd.UOffset.OffsetToData = ConvertEndianness(rd.UOffset.OffsetToData);
- rd.UName.Name = ConvertEndianness(rd.UName.Name);
-
- // If this entry points to data entry get a pointer to it
- if (!rd.UOffset.DirectoryOffset.DataIsDirectory)
- rde = PIMAGE_RESOURCE_DATA_ENTRY(rd.UOffset.OffsetToData + (BYTE*)rdRoot);
-
- // If this entry has a name, translate it from Unicode
- if (rd.UName.NameString.NameIsString) {
- PIMAGE_RESOURCE_DIR_STRING_U rds = PIMAGE_RESOURCE_DIR_STRING_U(rd.UName.NameString.NameOffset + (char*)rdRoot);
-
- size_t nameSize = ConvertEndianness(rds->Length);
- szName = new WCHAR[nameSize+1];
- winchar_strncpy(szName, rds->NameString, nameSize);
- szName[nameSize] = 0;
- }
- // Else, set the name to this entry's id
- else
- szName = MAKEINTRESOURCEW(ConvertEndianness(rdToScan->Entries[i].UName.Id));
-
- if (rd.UOffset.DirectoryOffset.DataIsDirectory)
- rdc->AddEntry(
- new CResourceDirectoryEntry(
- szName,
- ScanDirectory(
- rdRoot,
- PRESOURCE_DIRECTORY(rd.UOffset.DirectoryOffset.OffsetToDirectory + (BYTE*)rdRoot)
- )
- )
- );
- else
- rdc->AddEntry(
- new CResourceDirectoryEntry(
- szName,
- new CResourceDataEntry(
- (BYTE*)rdRoot + ConvertEndianness(rde->OffsetToData) - m_dwResourceSectionVA,
- ConvertEndianness(rde->Size),
- ConvertEndianness(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();
-
- IMAGE_RESOURCE_DIRECTORY rdDir = crd->GetInfo();
-
- rdDir.NumberOfNamedEntries = ConvertEndianness(rdDir.NumberOfNamedEntries);
- rdDir.NumberOfIdEntries = ConvertEndianness(rdDir.NumberOfIdEntries);
-
- CopyMemory(seeker, &rdDir, 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());
- }
-
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY rDirE;
- ZeroMemory(&rDirE, sizeof(rDirE));
- rDirE.UOffset.DirectoryOffset.DataIsDirectory = crd->GetEntry(i)->IsDataDirectory();
- rDirE.UName.Id = crd->GetEntry(i)->HasName() ? 0 : crd->GetEntry(i)->GetId();
- rDirE.UName.Id = ConvertEndianness(rDirE.UName.Id);
- rDirE.UName.NameString.NameIsString = (crd->GetEntry(i)->HasName()) ? 1 : 0;
-
- CopyMemory(seeker, &rDirE, sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY));
- crd->GetEntry(i)->m_dwWrittenAt = DWORD(seeker);
- seeker += sizeof(MY_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 = ConvertEndianness(cRDataE->GetCodePage());
- rDataE.Size = ConvertEndianness(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();
-
- PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->UName.NameString.NameOffset = ConvertEndianness(DWORD(seeker) - DWORD(pbRsrcSec));
-
- WCHAR* szName = cRDirE->GetName();
- WORD iLen = winchar_strlen(szName) + 1;
-
- *(WORD*)seeker = ConvertEndianness(iLen);
- CopyMemory(seeker + sizeof(WORD), szName, iLen*sizeof(WCHAR));
-
- seeker += RALIGN(iLen * sizeof(WCHAR) + sizeof(WORD), 4);
-
- delete [] szName;
-
- 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 = ConvertEndianness(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++) {
- PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY rde = PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt);
- if (resDir->GetEntry(i)->IsDataDirectory()) {
- rde->UOffset.DirectoryOffset.DataIsDirectory = 1;
- rde->UOffset.DirectoryOffset.OffsetToDirectory = resDir->GetEntry(i)->GetSubDirectory()->m_dwWrittenAt - newResDirAt;
- rde->UOffset.OffsetToData = ConvertEndianness(rde->UOffset.OffsetToData);
- SetOffsets(resDir->GetEntry(i)->GetSubDirectory(), newResDirAt);
- }
- else {
- rde->UOffset.OffsetToData = ConvertEndianness(resDir->GetEntry(i)->GetDataEntry()->m_dwWrittenAt - newResDirAt);
- }
- }
-}
-
-// Adjusts a virtual address by a specific amount
-DWORD CResourceEditor::AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment) {
- dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
- dwVirtualAddress += dwAdjustment;
- dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
-
- return dwVirtualAddress;
-}
-
-// Aligns a virtual address to the section alignment
-DWORD CResourceEditor::AlignVA(DWORD dwVirtualAddress) {
- DWORD dwSectionAlignment = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, SectionAlignment);
- DWORD dwAlignment = ConvertEndianness(dwSectionAlignment);
-
- dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
- dwVirtualAddress = RALIGN(dwVirtualAddress, dwAlignment);
- dwVirtualAddress = ConvertEndianness(dwVirtualAddress);
-
- return dwVirtualAddress;
-}
-
-//////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////
-// 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(unsigned int i) {
- if (m_vEntries.size() < i)
- 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()) {
- WCHAR* szEntName = entry->GetName();
- for (i = 0; i < m_rdDir.NumberOfNamedEntries; i++) {
- WCHAR* szName = m_vEntries[i]->GetName();
- int cmp = winchar_strcmp(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--;
- delete m_vEntries[i];
- 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(WCHAR* szName) {
- if (IS_INTRESOURCE(szName))
- return Find((WORD) (DWORD) szName);
- else
- if (szName[0] == '#')
- return Find(WORD(winchar_stoi(szName + 1)));
-
- for (unsigned int i = 0; i < m_vEntries.size(); i++) {
- if (!m_vEntries[i]->HasName())
- continue;
-
- WCHAR* szEntName = m_vEntries[i]->GetName();
- int cmp = winchar_strcmp(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 (unsigned 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 (unsigned int i = 0; i < m_vEntries.size(); i++) {
- dwSize += sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY);
- if (m_vEntries[i]->HasName())
- dwSize += sizeof(IMAGE_RESOURCE_DIR_STRING_U) + (m_vEntries[i]->GetNameLength()+1)*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 (unsigned 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(WCHAR* szName, CResourceDirectory* rdSubDir) {
- if (IS_INTRESOURCE(szName)) {
- m_bHasName = false;
- m_szName = 0;
- m_wId = (WORD) (DWORD) szName;
- }
- else {
- m_bHasName = true;
- m_szName = winchar_strdup(szName);
- }
- m_bIsDataDirectory = true;
- m_rdSubDir = rdSubDir;
-}
-
-CResourceDirectoryEntry::CResourceDirectoryEntry(WCHAR* szName, CResourceDataEntry* rdeData) {
- if (IS_INTRESOURCE(szName)) {
- m_bHasName = false;
- m_szName = 0;
- m_wId = (WORD) (DWORD) szName;
- }
- else {
- m_bHasName = true;
- m_szName = winchar_strdup(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!
-WCHAR* CResourceDirectoryEntry::GetName() {
- if (!m_bHasName)
- return 0;
- return winchar_strdup(m_szName);
-}
-
-int CResourceDirectoryEntry::GetNameLength() {
- return winchar_strlen(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;
-}
+/* + * ResourceEditor.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 2002-2007 Amir Szekely <kichik@users.sourceforge.net> + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "ResourceEditor.h" +#include "util.h" +#include "winchar.h" +#include <queue> +using namespace std; + +////////////////////////////////////////////////////////////////////// +// 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) + +#ifndef _WIN32 +static inline ULONG ConvertEndianness(ULONG u) { + return FIX_ENDIAN_INT32(u); +} +#endif + +static inline DWORD ConvertEndianness(DWORD d) { + return FIX_ENDIAN_INT32(d); +} + +static inline LONG ConvertEndianness(LONG l) { + return FIX_ENDIAN_INT32(l); +} + +static inline WORD ConvertEndianness(WORD w) { + return FIX_ENDIAN_INT16(w); +} + +PIMAGE_NT_HEADERS CResourceEditor::GetNTHeaders(BYTE* pbPE) { + // Get dos header + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) pbPE; + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) + throw runtime_error("PE file contains invalid DOS header"); + + // Get NT headers + PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(pbPE + ConvertEndianness(dosHeader->e_lfanew)); + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) + throw runtime_error("PE file missing NT signature"); + + // Make sure this is a supported PE format + if (ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC && + ntHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) + throw runtime_error("Unsupported PE format"); + + return ntHeaders; +} + +PRESOURCE_DIRECTORY CResourceEditor::GetResourceDirectory( + BYTE* pbPE, + DWORD dwSize, + PIMAGE_NT_HEADERS ntHeaders, + DWORD *pdwResSecVA /*=NULL*/, + DWORD *pdwSectionIndex /*=NULL*/ +) { + PIMAGE_DATA_DIRECTORY dataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory); + DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes); + + if (ConvertEndianness(dwNumberOfRvaAndSizes) <= IMAGE_DIRECTORY_ENTRY_RESOURCE) + throw runtime_error("No resource section found"); + // Get resource section virtual address + DWORD dwResSecVA = ConvertEndianness(dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + // Pointer to the sections headers array + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); + + DWORD dwSectionIndex = (DWORD) -1; + + // Find resource section index in the array + for (int i = 0; i < ConvertEndianness(ntHeaders->FileHeader.NumberOfSections); i++) { + if (dwResSecVA == ConvertEndianness(sectionHeadersArray[i].VirtualAddress)) { + // Remember resource section index + dwSectionIndex = i; + // Check for invalid resource section pointer + if (!sectionHeadersArray[i].PointerToRawData) + throw runtime_error("Invalid resource section pointer"); + + break; + } + + // Invalid section pointer (goes beyond the PE image) + if (ConvertEndianness(sectionHeadersArray[i].PointerToRawData) > dwSize) + throw runtime_error("Invalid section pointer"); + } + + // No resource section... + if (dwSectionIndex == (DWORD) -1) + throw runtime_error("PE file doesn't contain any resource section"); + + // Return extra parameters + if (pdwSectionIndex) + *pdwSectionIndex = dwSectionIndex; + if (pdwResSecVA) + *pdwResSecVA = dwResSecVA; + + // Pointer to section data, the first resource directory + DWORD dwResSecPtr = ConvertEndianness(sectionHeadersArray[dwSectionIndex].PointerToRawData); + return PRESOURCE_DIRECTORY(pbPE + dwResSecPtr); +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// CResourceEditor +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResourceEditor::CResourceEditor(BYTE* pbPE, int iSize) { + // Copy the data pointer + m_pbPE = pbPE; + m_iSize = iSize; + + // Get NT headers + m_ntHeaders = GetNTHeaders(m_pbPE); + + // No check sum support yet... + DWORD* pdwCheckSum = GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, CheckSum); + if (*pdwCheckSum) + { + // clear checksum (should be [re]calculated after all changes done) + pdwCheckSum = 0; + //throw runtime_error("CResourceEditor doesn't yet support check sum"); + } + + // Get resource section virtual address, resource section index and pointer to resource directory + PRESOURCE_DIRECTORY rdRoot = GetResourceDirectory(m_pbPE, iSize, m_ntHeaders, &m_dwResourceSectionVA, &m_dwResourceSectionIndex); + + // Scan the resource directory + m_cResDir = ScanDirectory(rdRoot, rdRoot); +} + +CResourceEditor::~CResourceEditor() { + if (m_cResDir) { + m_cResDir->Destroy(); + delete m_cResDir; + } +} + +////////////////////////////////////////////////////////////////////// +// Methods +////////////////////////////////////////////////////////////////////// + +// Adds/Replaces/Removes a resource. +// If lpData is 0 UpdateResource removes the resource. +bool CResourceEditor::UpdateResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + CResourceDirectory* nameDir = 0; + CResourceDirectory* langDir = 0; + CResourceDataEntry* data = 0; + IMAGE_RESOURCE_DIRECTORY rd = {0, /*time(0),*/}; + int iTypeIdx = -1, iNameIdx = -1, iLangIdx = -1; + + 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 true; + } + + 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(MAKEINTRESOURCEW(wLanguage), data)); + } + } + else if (data) { + // Delete the resource + delete data; + langDir->RemoveEntry(iLangIdx); + // Delete directories holding the resource if empty + if (!langDir->CountEntries()) { + delete langDir; + nameDir->RemoveEntry(iNameIdx); + if (!nameDir->CountEntries()) { + delete nameDir; + m_cResDir->RemoveEntry(iTypeIdx); + } + } + } + else return false; + return true; +} + +static WCHAR* ResStringToUnicode(const char *szString) { + if (IS_INTRESOURCE(szString)) + return MAKEINTRESOURCEW((ULONG_PTR)szString); + else + return winchar_fromansi(szString); +} + +static void FreeUnicodeResString(WCHAR* szwString) { + if (!IS_INTRESOURCE(szwString)) + delete [] szwString; +} + +bool CResourceEditor::UpdateResourceW(WORD szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + return UpdateResourceW(MAKEINTRESOURCEW(szType), szName, wLanguage, lpData, dwSize); +} + +bool CResourceEditor::UpdateResourceW(WCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + return UpdateResourceW(szType, MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize); +} + +bool CResourceEditor::UpdateResourceA(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + WCHAR* szwType = ResStringToUnicode(szType); + WCHAR* szwName = ResStringToUnicode(szName); + + bool result = UpdateResourceW(szwType, szwName, wLanguage, lpData, dwSize); + + FreeUnicodeResString(szwType); + FreeUnicodeResString(szwName); + + return result; +} + +bool CResourceEditor::UpdateResourceA(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + return UpdateResourceA(MAKEINTRESOURCE(szType), szName, wLanguage, lpData, dwSize); +} + +bool CResourceEditor::UpdateResourceA(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + return UpdateResourceA(szType, MAKEINTRESOURCE(szName), wLanguage, lpData, dwSize); +} + +bool CResourceEditor::UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize) { + return UpdateResourceW(MAKEINTRESOURCEW(szType), MAKEINTRESOURCEW(szName), wLanguage, lpData, dwSize); +} + +// Returns a copy of the requested resource +// Returns 0 if the requested resource can't be found +BYTE* CResourceEditor::GetResourceW(WCHAR* szType, WCHAR* szName, LANGID 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 = 0; + if (wLanguage) + 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 NULL; +} + +BYTE* CResourceEditor::GetResourceA(char* szType, char* szName, LANGID wLanguage) { + WCHAR* szwType = ResStringToUnicode(szType); + WCHAR* szwName = ResStringToUnicode(szName); + + BYTE* result = GetResourceW(szwType, szwName, wLanguage); + + FreeUnicodeResString(szwType); + FreeUnicodeResString(szwName); + + return result; +} + +// Returns the size of the requested resource +// Returns -1 if the requested resource can't be found +int CResourceEditor::GetResourceSizeW(WCHAR* szType, WCHAR* szName, LANGID 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 = 0; + if (wLanguage) + i = langDir->Find(wLanguage); + if (i > -1) { + data = langDir->GetEntry(i)->GetDataEntry(); + } + } + } + + if (data) + return (int) data->GetSize(); + else + return -1; +} + +int CResourceEditor::GetResourceSizeA(char* szType, char* szName, LANGID wLanguage) { + WCHAR* szwType = ResStringToUnicode(szType); + WCHAR* szwName = ResStringToUnicode(szName); + + int result = GetResourceSizeW(szwType, szwName, wLanguage); + + FreeUnicodeResString(szwType); + FreeUnicodeResString(szwName); + + return result; +} + +// Returns the offset of the requested resource in the original PE +// Returns -1 if the requested resource can't be found +DWORD CResourceEditor::GetResourceOffsetW(WCHAR* szType, WCHAR* szName, LANGID 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 = 0; + if (wLanguage) + i = langDir->Find(wLanguage); + if (i > -1) { + data = langDir->GetEntry(i)->GetDataEntry(); + } + } + } + + if (data) + return data->GetOffset(); + else + return DWORD(-1); +} + +DWORD CResourceEditor::GetResourceOffsetA(char* szType, char* szName, LANGID wLanguage) { + WCHAR* szwType = ResStringToUnicode(szType); + WCHAR* szwName = ResStringToUnicode(szName); + + DWORD result = GetResourceOffsetW(szwType, szwName, wLanguage); + + FreeUnicodeResString(szwType); + FreeUnicodeResString(szwName); + + return result; +} + +void CResourceEditor::FreeResource(BYTE* pbResource) +{ + if (pbResource) + delete [] pbResource; +} + +// Saves the edited PE into a buffer and returns it. +DWORD CResourceEditor::Save(BYTE* pbBuf, DWORD &dwSize) { + unsigned int i; + DWORD dwReqSize; + + DWORD dwFileAlign = ConvertEndianness(m_ntHeaders->OptionalHeader.FileAlignment); + DWORD dwSecAlign = ConvertEndianness(m_ntHeaders->OptionalHeader.SectionAlignment); + + DWORD dwRsrcSize = m_cResDir->GetSize(); // Size of new resource section + DWORD dwRsrcSizeAligned = RALIGN(dwRsrcSize, dwFileAlign); // Align it to FileAlignment + + // Calculate the total new PE size + DWORD dwOldRsrcSize = ConvertEndianness(IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData); + dwReqSize = m_iSize - dwOldRsrcSize + dwRsrcSizeAligned; + + if (!pbBuf || dwSize < dwReqSize) + return dwReqSize; + + // Use buffer + BYTE* pbNewPE = pbBuf; + dwSize = dwReqSize; + // Fill buffer with zeros + ZeroMemory(pbNewPE, dwSize); + + BYTE* seeker = pbNewPE; + BYTE* oldSeeker = m_pbPE; + + PIMAGE_SECTION_HEADER old_sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders); + + DWORD dwHeaderSize = ConvertEndianness(old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData); + WORD wNumberOfSections = ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections); + + // Copy everything until the resource section (including headers and everything that might come after them) + // We don't use SizeOfHeaders because sometimes (using VC6) it can extend beyond the first section + // or (Borland) there could be some more information between the headers and the first section. + CopyMemory(seeker, oldSeeker, dwHeaderSize); + + // Skip the headers and whatever comes after them + seeker += dwHeaderSize; + oldSeeker += dwHeaderSize; + + // Get new nt headers pointer + PIMAGE_NT_HEADERS ntHeaders = GetNTHeaders(pbNewPE); + // Get a pointer to the new section headers + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); + + // Skip the resource section in the old PE seeker. + oldSeeker += dwOldRsrcSize; + + // Save the old virtual size of the resource section + DWORD dwNewVirtualSize = RALIGN(dwRsrcSize, dwSecAlign); + DWORD dwOldVirtualSize = ConvertEndianness(sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize); + ALIGN(dwOldVirtualSize, dwSecAlign); + DWORD dwVAAdjustment = dwNewVirtualSize - dwOldVirtualSize; + + // Set the new size of the resource section (size aligned to FileAlignment) + sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = ConvertEndianness(dwRsrcSizeAligned); + // Set the virtual size as well (in memory) + sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = ConvertEndianness(dwRsrcSize); + (*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory))[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = ConvertEndianness(dwRsrcSize); + + // Set the new virtual size of the image + DWORD* pdwSizeOfImage = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfImage); + *pdwSizeOfImage = AlignVA(*GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, SizeOfHeaders)); + for (i = 0; i < wNumberOfSections; i++) { + DWORD dwSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize); + *pdwSizeOfImage = AlignVA(AdjustVA(*pdwSizeOfImage, dwSecSize)); + } + + // Set the new AddressOfEntryPoint if needed + DWORD* pdwAddressOfEntryPoint = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, AddressOfEntryPoint); + if (ConvertEndianness(*pdwAddressOfEntryPoint) > m_dwResourceSectionVA) + *pdwAddressOfEntryPoint = AdjustVA(*pdwAddressOfEntryPoint, dwVAAdjustment); + + // Set the new BaseOfCode if needed + DWORD* pdwBaseOfCode = GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, BaseOfCode); + if (ConvertEndianness(*pdwBaseOfCode) > m_dwResourceSectionVA) + *pdwBaseOfCode = AdjustVA(*pdwBaseOfCode, dwVAAdjustment); + + // Set the new BaseOfData if needed + if (ntHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + DWORD* pdwBaseOfData = &((PIMAGE_OPTIONAL_HEADER32)&ntHeaders->OptionalHeader)->BaseOfData; + if (*pdwBaseOfData > m_dwResourceSectionVA) + *pdwBaseOfData = AdjustVA(*pdwBaseOfData, dwVAAdjustment); + } + + // Refresh the headers of the sections that come after the resource section, and the data directory + DWORD dwNumberOfRvaAndSizes = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, NumberOfRvaAndSizes); + PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(ntHeaders->OptionalHeader, DataDirectory); + for (i = m_dwResourceSectionIndex + 1; i < wNumberOfSections; i++) { + if (sectionHeadersArray[i].PointerToRawData) { + AdjustVA(sectionHeadersArray[i].PointerToRawData, dwRsrcSizeAligned - dwOldRsrcSize); + } + + // We must find the right data directory entry before we change the virtual address + unsigned int uDataDirIdx = 0; + for (unsigned int j = 0; j < ConvertEndianness(dwNumberOfRvaAndSizes); j++) + if (pDataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) + uDataDirIdx = j; + + sectionHeadersArray[i].VirtualAddress = AdjustVA(sectionHeadersArray[i].VirtualAddress, dwVAAdjustment); + + // Change the virtual address in the data directory too + if (uDataDirIdx) + pDataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress; + } + + // Write the resource section + WriteRsrcSec(seeker); + // Advance the pointer + seeker += dwRsrcSizeAligned; + + // Copy everything that comes after the resource section (other sections and tacked data) + DWORD dwLeft = m_iSize - (oldSeeker - m_pbPE); + if (dwLeft) + CopyMemory(seeker, oldSeeker, dwLeft); + + seeker += dwLeft; + oldSeeker += dwLeft; + + /********************************************************** + * To add checksum to the header use MapFileAndCheckSum + **********************************************************/ + + // From now on, we are working on the new PE + // Freeing the old PE memory is up to the user + m_pbPE = pbNewPE; + m_iSize = dwSize; + m_ntHeaders = ntHeaders; + // We just wrote the resource section according to m_cResDir, so we don't need to rescan + // m_dwResourceSectionIndex and m_dwResourceSectionVA have also been left unchanged as + // we didn't move the resources section + + return 0; +} + +// This function scans exe sections and after find a match with given name +// increments it's virtual size (auto fixes image size based on section alignment, etc) +bool CResourceEditor::AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize) +{ + PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders); + + // Refresh the headers of the sections that come after the resource section, and the data directory + for (int i = 0; i < ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections); i++) { + if (!strcmp((LPCSTR)sectionHeadersArray[i].Name, pszSectionName)) { + sectionHeadersArray[i].Misc.VirtualSize = AlignVA(AdjustVA(sectionHeadersArray[i].Misc.VirtualSize, addsize)); + + sectionHeadersArray[i].Characteristics &= ConvertEndianness((DWORD) ~IMAGE_SCN_MEM_DISCARDABLE); + + // now fix any section after + for (int k = i + 1; k < ConvertEndianness(m_ntHeaders->FileHeader.NumberOfSections); k++, i++) { + DWORD dwLastSecVA = ConvertEndianness(sectionHeadersArray[i].VirtualAddress); + DWORD dwLastSecSize = ConvertEndianness(sectionHeadersArray[i].Misc.VirtualSize); + DWORD dwSecVA = AlignVA(ConvertEndianness(dwLastSecVA + dwLastSecSize)); + + sectionHeadersArray[k].VirtualAddress = dwSecVA; + + if (m_dwResourceSectionIndex == (DWORD) k) + { + // fix the resources virtual address if it changed + PIMAGE_DATA_DIRECTORY pDataDirectory = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, DataDirectory); + pDataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = dwSecVA; + m_dwResourceSectionVA = ConvertEndianness(dwSecVA); + } + } + + return true; + } + } + + return false; +} + +////////////////////////////////////////////////////////////////////// +// 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)); + WCHAR* szName; + PIMAGE_RESOURCE_DATA_ENTRY rde = NULL; + + // Go through all entries of this resource directory + int entries = ConvertEndianness(rdToScan->Header.NumberOfNamedEntries); + entries += ConvertEndianness(rdToScan->Header.NumberOfIdEntries); + + for (int i = 0; i < entries; i++) { + MY_IMAGE_RESOURCE_DIRECTORY_ENTRY rd = rdToScan->Entries[i]; + rd.UOffset.OffsetToData = ConvertEndianness(rd.UOffset.OffsetToData); + rd.UName.Name = ConvertEndianness(rd.UName.Name); + + // If this entry points to data entry get a pointer to it + if (!rd.UOffset.DirectoryOffset.DataIsDirectory) + rde = PIMAGE_RESOURCE_DATA_ENTRY(rd.UOffset.OffsetToData + (BYTE*)rdRoot); + + // If this entry has a name, translate it from Unicode + if (rd.UName.NameString.NameIsString) { + PIMAGE_RESOURCE_DIR_STRING_U rds = PIMAGE_RESOURCE_DIR_STRING_U(rd.UName.NameString.NameOffset + (char*)rdRoot); + + size_t nameSize = ConvertEndianness(rds->Length); + szName = new WCHAR[nameSize+1]; + winchar_strncpy(szName, rds->NameString, nameSize); + szName[nameSize] = 0; + } + // Else, set the name to this entry's id + else + szName = MAKEINTRESOURCEW(ConvertEndianness(rdToScan->Entries[i].UName.Id)); + + if (rd.UOffset.DirectoryOffset.DataIsDirectory) + { + rdc->AddEntry( + new CResourceDirectoryEntry( + szName, + ScanDirectory( + rdRoot, + PRESOURCE_DIRECTORY(rd.UOffset.DirectoryOffset.OffsetToDirectory + (LPBYTE)rdRoot) + ) + ) + ); + } + else + { + LPBYTE pbData = (LPBYTE)rdRoot + ConvertEndianness(rde->OffsetToData) - m_dwResourceSectionVA; + DWORD dwOffset = DWORD(pbData - m_pbPE); + + rdc->AddEntry( + new CResourceDirectoryEntry( + szName, + new CResourceDataEntry( + pbData, + ConvertEndianness(rde->Size), + ConvertEndianness(rde->CodePage), + dwOffset + ) + ) + ); + } + + // 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(); + + IMAGE_RESOURCE_DIRECTORY rdDir = crd->GetInfo(); + + rdDir.NumberOfNamedEntries = ConvertEndianness(rdDir.NumberOfNamedEntries); + rdDir.NumberOfIdEntries = ConvertEndianness(rdDir.NumberOfIdEntries); + + CopyMemory(seeker, &rdDir, 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()); + } + + MY_IMAGE_RESOURCE_DIRECTORY_ENTRY rDirE; + ZeroMemory(&rDirE, sizeof(rDirE)); + rDirE.UOffset.DirectoryOffset.DataIsDirectory = crd->GetEntry(i)->IsDataDirectory(); + rDirE.UName.Id = crd->GetEntry(i)->HasName() ? 0 : crd->GetEntry(i)->GetId(); + rDirE.UName.Id = ConvertEndianness(rDirE.UName.Id); + rDirE.UName.NameString.NameIsString = (crd->GetEntry(i)->HasName()) ? 1 : 0; + + CopyMemory(seeker, &rDirE, sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY)); + crd->GetEntry(i)->m_dwWrittenAt = DWORD(seeker); + seeker += sizeof(MY_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 = ConvertEndianness(cRDataE->GetCodePage()); + rDataE.Size = ConvertEndianness(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(); + + PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->UName.NameString.NameOffset = ConvertEndianness(DWORD(seeker) - DWORD(pbRsrcSec)); + + WCHAR* szName = cRDirE->GetName(); + WORD iLen = winchar_strlen(szName) + 1; + + *(WORD*)seeker = ConvertEndianness(iLen); + CopyMemory(seeker + sizeof(WORD), szName, iLen*sizeof(WCHAR)); + + seeker += RALIGN(iLen * sizeof(WCHAR) + sizeof(WORD), 4); + + delete [] szName; + + 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 = ConvertEndianness(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++) { + PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY rde = PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(resDir->GetEntry(i)->m_dwWrittenAt); + if (resDir->GetEntry(i)->IsDataDirectory()) { + rde->UOffset.DirectoryOffset.DataIsDirectory = 1; + rde->UOffset.DirectoryOffset.OffsetToDirectory = resDir->GetEntry(i)->GetSubDirectory()->m_dwWrittenAt - newResDirAt; + rde->UOffset.OffsetToData = ConvertEndianness(rde->UOffset.OffsetToData); + SetOffsets(resDir->GetEntry(i)->GetSubDirectory(), newResDirAt); + } + else { + rde->UOffset.OffsetToData = ConvertEndianness(resDir->GetEntry(i)->GetDataEntry()->m_dwWrittenAt - newResDirAt); + } + } +} + +// Adjusts a virtual address by a specific amount +DWORD CResourceEditor::AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment) { + dwVirtualAddress = ConvertEndianness(dwVirtualAddress); + dwVirtualAddress += dwAdjustment; + dwVirtualAddress = ConvertEndianness(dwVirtualAddress); + + return dwVirtualAddress; +} + +// Aligns a virtual address to the section alignment +DWORD CResourceEditor::AlignVA(DWORD dwVirtualAddress) { + DWORD dwSectionAlignment = *GetMemberFromOptionalHeader(m_ntHeaders->OptionalHeader, SectionAlignment); + DWORD dwAlignment = ConvertEndianness(dwSectionAlignment); + + dwVirtualAddress = ConvertEndianness(dwVirtualAddress); + dwVirtualAddress = RALIGN(dwVirtualAddress, dwAlignment); + dwVirtualAddress = ConvertEndianness(dwVirtualAddress); + + return dwVirtualAddress; +} + +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// 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(unsigned int i) { + if (m_vEntries.size() < i) + 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()) { + WCHAR* szEntName = entry->GetName(); + for (i = 0; i < m_rdDir.NumberOfNamedEntries; i++) { + WCHAR* szName = m_vEntries[i]->GetName(); + int cmp = winchar_strcmp(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--; + delete m_vEntries[i]; + 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(WCHAR* szName) { + if (IS_INTRESOURCE(szName)) + return Find((WORD) (DWORD) szName); + else + if (szName[0] == '#') + return Find(WORD(winchar_stoi(szName + 1))); + + for (unsigned int i = 0; i < m_vEntries.size(); i++) { + if (!m_vEntries[i]->HasName()) + continue; + + WCHAR* szEntName = m_vEntries[i]->GetName(); + int cmp = winchar_strcmp(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 (unsigned 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 (unsigned int i = 0; i < m_vEntries.size(); i++) { + dwSize += sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY); + if (m_vEntries[i]->HasName()) + dwSize += sizeof(IMAGE_RESOURCE_DIR_STRING_U) + (m_vEntries[i]->GetNameLength()+1)*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 (unsigned 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(WCHAR* szName, CResourceDirectory* rdSubDir) { + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; + m_wId = (WORD) (DWORD) szName; + } + else { + m_bHasName = true; + m_szName = winchar_strdup(szName); + } + m_bIsDataDirectory = true; + m_rdSubDir = rdSubDir; +} + +CResourceDirectoryEntry::CResourceDirectoryEntry(WCHAR* szName, CResourceDataEntry* rdeData) { + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; + m_wId = (WORD) (DWORD) szName; + } + else { + m_bHasName = true; + m_szName = winchar_strdup(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! +WCHAR* CResourceDirectoryEntry::GetName() { + if (!m_bHasName) + return 0; + return winchar_strdup(m_szName); +} + +int CResourceDirectoryEntry::GetNameLength() { + return winchar_strlen(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, DWORD dwOffset) { + m_pbData = 0; + SetData(pbData, dwSize, dwCodePage); + m_dwOffset = dwOffset; +} + +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; + m_dwOffset = DWORD(-1); // unset +} + +DWORD CResourceDataEntry::GetSize() { + return m_dwSize; +} + +DWORD CResourceDataEntry::GetCodePage() { + return m_dwCodePage; +} + +DWORD CResourceDataEntry::GetOffset() { + return m_dwOffset; +} diff --git a/Source/ResourceEditor.h b/Source/ResourceEditor.h index eb542c8..d821fe2 100755 --- a/Source/ResourceEditor.h +++ b/Source/ResourceEditor.h @@ -1,239 +1,243 @@ -/*
- * ResourceEditor.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2002-2007 Amir Szekely <kichik@users.sourceforge.net>
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#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
-
-
-#include <vector>
-
-#include "Platform.h"
-#ifdef _WIN32
-# include <WinNT.h>
-#else
-// all definitions for non Win32 platforms were taken from MinGW's free Win32 library
-# define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-# define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
-# pragma pack(4)
-typedef struct _IMAGE_RESOURCE_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- WORD NumberOfNamedEntries;
- WORD NumberOfIdEntries;
-} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY;
-typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
- DWORD OffsetToData;
- DWORD Size;
- DWORD CodePage;
- DWORD Reserved;
-} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY;
-typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
- WORD Length;
- CHAR NameString[1];
-} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING;
-typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
- WORD Length;
- WCHAR NameString[1];
-} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U;
-# pragma pack()
-#endif
-
-#pragma pack(4)
-typedef struct _MY_IMAGE_RESOURCE_DIRECTORY_ENTRY {
- union {
- struct {
-#ifndef __BIG_ENDIAN__
- DWORD NameOffset:31;
- DWORD NameIsString:1;
-#else
- DWORD NameIsString:1;
- DWORD NameOffset:31;
-#endif
- } NameString;
- DWORD Name;
- WORD Id;
- } UName;
- union {
- DWORD OffsetToData;
- struct {
-#ifndef __BIG_ENDIAN__
- DWORD OffsetToDirectory:31;
- DWORD DataIsDirectory:1;
-#else
- DWORD DataIsDirectory:1;
- DWORD OffsetToDirectory:31;
-#endif
- } DirectoryOffset;
- } UOffset;
-} MY_IMAGE_RESOURCE_DIRECTORY_ENTRY,*PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY;
-
-#pragma pack()
-
-#include <stdexcept>
-
-// classes
-class CResourceDirectory;
-class CResourceDirectoryEntry;
-class CResourceDataEntry;
-
-// Resource directory with entries
-typedef struct RESOURCE_DIRECTORY {
- IMAGE_RESOURCE_DIRECTORY Header;
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1];
-} *PRESOURCE_DIRECTORY;
-
-#define GetMemberFromOptionalHeader(optionalHeader, member) \
- ( (optionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? \
- &((PIMAGE_OPTIONAL_HEADER32)&optionalHeader)->member : \
- &((PIMAGE_OPTIONAL_HEADER64)&optionalHeader)->member \
- )
-class CResourceEditor {
-public:
- CResourceEditor(BYTE* pbPE, int iSize);
- virtual ~CResourceEditor();
-
- bool UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceW(WORD szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceW(WCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceA(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceA(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- bool UpdateResourceA(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize);
- BYTE* GetResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage);
- BYTE* GetResourceA(char* szType, char* szName, LANGID wLanguage);
- int GetResourceSizeW(WCHAR* szType, WCHAR* szName, LANGID wLanguage);
- int GetResourceSizeA(char* szType, char* szName, LANGID wLanguage);
- void FreeResource(BYTE* pbResource);
-
- bool AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize);
- DWORD Save(BYTE* pbBuf, DWORD &dwSize);
-
- // utitlity functions
- static PIMAGE_NT_HEADERS GetNTHeaders(BYTE* pbPE);
-
- static PRESOURCE_DIRECTORY GetResourceDirectory(
- BYTE* pbPE,
- DWORD dwSize,
- PIMAGE_NT_HEADERS ntHeaders,
- DWORD *pdwResSecVA = NULL,
- DWORD *pdwSectionIndex = NULL
- );
-
-private:
- BYTE* m_pbPE;
- int m_iSize;
-
- 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);
-
- DWORD AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment);
- DWORD AlignVA(DWORD dwVirtualAddress);
-};
-
-class CResourceDirectory {
-public:
- CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY prd);
- virtual ~CResourceDirectory();
-
- IMAGE_RESOURCE_DIRECTORY GetInfo();
-
- CResourceDirectoryEntry* GetEntry(unsigned int i);
- void AddEntry(CResourceDirectoryEntry* entry);
- void RemoveEntry(int i);
- int CountEntries();
- int Find(WCHAR* szName);
- int Find(WORD wId);
-
- DWORD GetSize();
-
- void Destroy();
-
- DWORD m_dwWrittenAt;
-
-private:
- IMAGE_RESOURCE_DIRECTORY m_rdDir;
- std::vector<CResourceDirectoryEntry*> m_vEntries;
-};
-
-class CResourceDirectoryEntry {
-public:
- CResourceDirectoryEntry(WCHAR* szName, CResourceDirectory* rdSubDir);
- CResourceDirectoryEntry(WCHAR* szName, CResourceDataEntry* rdeData);
- virtual ~CResourceDirectoryEntry();
-
- bool HasName();
- WCHAR* GetName();
- int GetNameLength();
-
- WORD GetId();
-
- bool IsDataDirectory();
- CResourceDirectory* GetSubDirectory();
-
- CResourceDataEntry* GetDataEntry();
-
- DWORD m_dwWrittenAt;
-
-private:
- bool m_bHasName;
- WCHAR* 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 // !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_)
+/* + * ResourceEditor.h + * + * This file is a part of NSIS. + * + * Copyright (C) 2002-2007 Amir Szekely <kichik@users.sourceforge.net> + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#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 + + +#include <vector> + +#include "Platform.h" +#ifdef _WIN32 +# include <WinNT.h> +#else +// all definitions for non Win32 platforms were taken from MinGW's free Win32 library +# define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +# define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 +# pragma pack(4) +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY; +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY; +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[1]; +} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING; +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + WORD Length; + WCHAR NameString[1]; +} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U; +# pragma pack() +#endif + +#pragma pack(4) +typedef struct _MY_IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { +#ifndef __BIG_ENDIAN__ + DWORD NameOffset:31; + DWORD NameIsString:1; +#else + DWORD NameIsString:1; + DWORD NameOffset:31; +#endif + } NameString; + DWORD Name; + WORD Id; + } UName; + union { + DWORD OffsetToData; + struct { +#ifndef __BIG_ENDIAN__ + DWORD OffsetToDirectory:31; + DWORD DataIsDirectory:1; +#else + DWORD DataIsDirectory:1; + DWORD OffsetToDirectory:31; +#endif + } DirectoryOffset; + } UOffset; +} MY_IMAGE_RESOURCE_DIRECTORY_ENTRY,*PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY; + +#pragma pack() + +#include <stdexcept> + +// classes +class CResourceDirectory; +class CResourceDirectoryEntry; +class CResourceDataEntry; + +// Resource directory with entries +typedef struct RESOURCE_DIRECTORY { + IMAGE_RESOURCE_DIRECTORY Header; + MY_IMAGE_RESOURCE_DIRECTORY_ENTRY Entries[1]; +} *PRESOURCE_DIRECTORY; + +#define GetMemberFromOptionalHeader(optionalHeader, member) \ + ( (optionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) ? \ + &((PIMAGE_OPTIONAL_HEADER32)&optionalHeader)->member : \ + &((PIMAGE_OPTIONAL_HEADER64)&optionalHeader)->member \ + ) +class CResourceEditor { +public: + CResourceEditor(BYTE* pbPE, int iSize); + virtual ~CResourceEditor(); + + bool UpdateResource(WORD szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceW(WORD szType, WCHAR* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceW(WCHAR* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceA(char* szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceA(WORD szType, char* szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + bool UpdateResourceA(char* szType, WORD szName, LANGID wLanguage, BYTE* lpData, DWORD dwSize); + BYTE* GetResourceW(WCHAR* szType, WCHAR* szName, LANGID wLanguage); + BYTE* GetResourceA(char* szType, char* szName, LANGID wLanguage); + int GetResourceSizeW(WCHAR* szType, WCHAR* szName, LANGID wLanguage); + int GetResourceSizeA(char* szType, char* szName, LANGID wLanguage); + DWORD GetResourceOffsetW(WCHAR* szType, WCHAR* szName, LANGID wLanguage); + DWORD GetResourceOffsetA(char* szType, char* szName, LANGID wLanguage); + void FreeResource(BYTE* pbResource); + + bool AddExtraVirtualSize2PESection(const char* pszSectionName, int addsize); + DWORD Save(BYTE* pbBuf, DWORD &dwSize); + + // utitlity functions + static PIMAGE_NT_HEADERS GetNTHeaders(BYTE* pbPE); + + static PRESOURCE_DIRECTORY GetResourceDirectory( + BYTE* pbPE, + DWORD dwSize, + PIMAGE_NT_HEADERS ntHeaders, + DWORD *pdwResSecVA = NULL, + DWORD *pdwSectionIndex = NULL + ); + +private: + BYTE* m_pbPE; + int m_iSize; + + 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); + + DWORD AdjustVA(DWORD dwVirtualAddress, DWORD dwAdjustment); + DWORD AlignVA(DWORD dwVirtualAddress); +}; + +class CResourceDirectory { +public: + CResourceDirectory(PIMAGE_RESOURCE_DIRECTORY prd); + virtual ~CResourceDirectory(); + + IMAGE_RESOURCE_DIRECTORY GetInfo(); + + CResourceDirectoryEntry* GetEntry(unsigned int i); + void AddEntry(CResourceDirectoryEntry* entry); + void RemoveEntry(int i); + int CountEntries(); + int Find(WCHAR* szName); + int Find(WORD wId); + + DWORD GetSize(); + + void Destroy(); + + DWORD m_dwWrittenAt; + +private: + IMAGE_RESOURCE_DIRECTORY m_rdDir; + std::vector<CResourceDirectoryEntry*> m_vEntries; +}; + +class CResourceDirectoryEntry { +public: + CResourceDirectoryEntry(WCHAR* szName, CResourceDirectory* rdSubDir); + CResourceDirectoryEntry(WCHAR* szName, CResourceDataEntry* rdeData); + virtual ~CResourceDirectoryEntry(); + + bool HasName(); + WCHAR* GetName(); + int GetNameLength(); + + WORD GetId(); + + bool IsDataDirectory(); + CResourceDirectory* GetSubDirectory(); + + CResourceDataEntry* GetDataEntry(); + + DWORD m_dwWrittenAt; + +private: + bool m_bHasName; + WCHAR* 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, DWORD dwOffset = DWORD(-1)); + ~CResourceDataEntry(); + + BYTE* GetData(); + + void SetData(BYTE* pbData, DWORD dwSize); + void SetData(BYTE* pbData, DWORD dwSize, DWORD dwCodePage); + + DWORD GetSize(); + DWORD GetCodePage(); + DWORD GetOffset(); + + DWORD m_dwWrittenAt; + +private: + BYTE* m_pbData; + DWORD m_dwSize; + DWORD m_dwCodePage; + DWORD m_dwOffset; +}; + +#endif // !defined(AFX_RESOURCEEDITOR_H__683BF710_E805_4093_975B_D5729186A89A__INCLUDED_) diff --git a/Source/ResourceVersionInfo.cpp b/Source/ResourceVersionInfo.cpp index b292459..5fac171 100755 --- a/Source/ResourceVersionInfo.cpp +++ b/Source/ResourceVersionInfo.cpp @@ -1,318 +1,318 @@ -/*
- * ResourceVersionInfo.cpp: implementation of the CResourceVersionInfo class.
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "ResourceVersionInfo.h"
-
-#include "Platform.h"
-#include "util.h"
-#include "winchar.h"
-
-#ifdef NSIS_SUPPORT_VERSION_INFO
-
-#ifndef VOS__WINDOWS32
-# define VOS__WINDOWS32 4
-#endif
-#ifndef VFT_APP
-# define VFT_APP 1
-#endif
-
-#ifndef _WIN32
-# include <iconv.h>
-#endif
-
-struct version_string_list
-{
- int codepage;
- LANGID lang_id;
- int name;
- DefineList *pChildStrings;
-};
-
-CVersionStrigList::~CVersionStrigList()
-{
- struct version_string_list *itr = (struct version_string_list *) gr.get();
- int i = gr.getlen() / sizeof(struct version_string_list);
-
- while (i--)
- {
- delete itr[i].pChildStrings;
- }
-}
-
-int CVersionStrigList::add(LANGID langid, int codepage)
-{
- char Buff[10];
- sprintf(Buff, "%04x", langid);
- int pos = SortedStringListND<struct version_string_list>::add(Buff);
- if (pos == -1) return false;
- ((struct version_string_list*)gr.get())[pos].pChildStrings = new DefineList;
- ((struct version_string_list*)gr.get())[pos].codepage = codepage;
- ((struct version_string_list*)gr.get())[pos].lang_id = langid;
- return pos;
-}
-
-LANGID CVersionStrigList::get_lang(int idx)
-{
- version_string_list *data=(version_string_list *)gr.get();
- return data[idx].lang_id;
-}
-
-int CVersionStrigList::get_codepage(int idx)
-{
- version_string_list *data=(version_string_list *)gr.get();
- return data[idx].codepage;
-}
-
-DefineList* CVersionStrigList::get_strings(int idx)
-{
- version_string_list *data=(version_string_list *)gr.get();
- return data[idx].pChildStrings;
-}
-
-int CVersionStrigList::find(LANGID lang_id, int codepage)
-{
- char Buff[10];
- sprintf(Buff, "%04x", lang_id);
- return SortedStringListND<struct version_string_list>::find(Buff);
-}
-
-int CVersionStrigList::getlen()
-{
- return strings.getlen();
-}
-
-int CVersionStrigList::getnum()
-{
- return gr.getlen()/sizeof(struct version_string_list);
-}
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-CResourceVersionInfo::CResourceVersionInfo()
-{
- memset(&m_FixedInfo, 0, sizeof(VS_FIXEDFILEINFO));
- m_FixedInfo.dwSignature = 0xFEEF04BD;
- m_FixedInfo.dwFileOS = VOS__WINDOWS32;
- m_FixedInfo.dwFileType = VFT_APP;
-}
-
-CResourceVersionInfo::~CResourceVersionInfo()
-{
-
-}
-
-void CResourceVersionInfo::SetFileFlags(int Value)
-{
- m_FixedInfo.dwFileFlags = (m_FixedInfo.dwFileFlags & ~(m_FixedInfo.dwFileFlagsMask)) || Value;
-}
-
-void CResourceVersionInfo::SetFileVersion(int HighPart, int LowPart)
-{
- m_FixedInfo.dwFileVersionLS = LowPart;
- m_FixedInfo.dwFileVersionMS = HighPart;
-}
-
-void CResourceVersionInfo::SetProductVersion(int HighPart, int LowPart)
-{
- m_FixedInfo.dwProductVersionLS = LowPart;
- m_FixedInfo.dwProductVersionMS = HighPart;
-}
-
-int GetVersionHeader (LPSTR &p, WORD &wLength, WORD &wValueLength, WORD &wType)
-{
- WCHAR *szKey;
- char * baseP;
-
- baseP = p;
- wLength = *(WORD*)p;
- p += sizeof(WORD);
- wValueLength = *(WORD*)p;
- p += sizeof(WORD);
- wType = *(WORD*)p;
- p += sizeof(WORD);
- szKey = (WCHAR*)p;
- p += (winchar_strlen(szKey) + 1) * sizeof (WCHAR);
- while ( ((long)p % 4) != 0 )
- p++;
- return p - baseP;
-}
-
-DWORD ZEROS = 0;
-
-void PadStream (GrowBuf &strm)
-{
- if ( (strm.getlen() % 4) != 0 )
- strm.add (&ZEROS, 4 - (strm.getlen() % 4));
-}
-
-void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wType, const WCHAR *key, void *value)
-{
- WORD valueLen;
- WORD keyLen;
-
- strm.add (&wLength, sizeof (wLength));
-
- strm.add (&wValueLength, sizeof (wValueLength));
- strm.add (&wType, sizeof (wType));
- keyLen = WORD((winchar_strlen(key) + 1) * sizeof (WCHAR));
- strm.add ((void*)key, keyLen);
-
- PadStream(strm);
-
- if ( wValueLength > 0 )
- {
- valueLen = wValueLength;
- if ( wType == 1 )
- valueLen = valueLen * WORD(sizeof (WCHAR));
- strm.add (value, valueLen);
- }
-}
-
-void CResourceVersionInfo::ExportToStream(GrowBuf &strm, int Index)
-{
- DWORD v;
- WORD wSize;
- int p, p1;
- WCHAR *KeyName, *KeyValue;
-
- strm.resize(0);
- KeyName = winchar_fromansi("VS_VERSION_INFO");
- SaveVersionHeader (strm, 0, sizeof (VS_FIXEDFILEINFO), 0, KeyName, &m_FixedInfo);
- delete [] KeyName;
-
- DefineList *pChildStrings = m_ChildStringLists.get_strings(Index);
- if ( pChildStrings->getnum() > 0 )
- {
- GrowBuf stringInfoStream;
- int codepage = m_ChildStringLists.get_codepage(Index);
- LANGID langid = m_ChildStringLists.get_lang(Index);
- char Buff[16];
- sprintf(Buff, "%04x%04x", langid, codepage);
- KeyName = winchar_fromansi(Buff, CP_ACP);
- SaveVersionHeader (stringInfoStream, 0, 0, 0, KeyName, &ZEROS);
- delete [] KeyName;
-
- for ( int i = 0; i < pChildStrings->getnum(); i++ )
- {
- PadStream (stringInfoStream);
-
- p = stringInfoStream.getlen();
- KeyName = winchar_fromansi(pChildStrings->getname(i), codepage);
- KeyValue = winchar_fromansi(pChildStrings->getvalue(i), codepage);
- SaveVersionHeader (stringInfoStream, 0, WORD(winchar_strlen(KeyValue) + 1), 1, KeyName, (void*)KeyValue);
- delete [] KeyName;
- delete [] KeyValue;
- wSize = WORD(stringInfoStream.getlen() - p);
-
- *(WORD*)((PBYTE)stringInfoStream.get()+p)=wSize;
- }
-
- wSize = WORD(stringInfoStream.getlen());
- *(WORD*)((PBYTE)stringInfoStream.get())=wSize;
-
- PadStream (strm);
- p = strm.getlen();
- KeyName = winchar_fromansi("StringFileInfo", CP_ACP);
- SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS);
- delete [] KeyName;
- strm.add (stringInfoStream.get(), stringInfoStream.getlen());
- wSize = WORD(strm.getlen() - p);
-
- *(WORD*)((PBYTE)strm.get()+p)=wSize;
- }
-
- // Show all languages avaiable using Var-Translations
- if ( m_ChildStringLists.getnum() > 0 )
- {
- PadStream (strm);
- p = strm.getlen();
- KeyName = winchar_fromansi("VarFileInfo", CP_ACP);
- SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS);
- delete [] KeyName;
- PadStream (strm);
-
- p1 = strm.getlen();
- KeyName = winchar_fromansi("Translation", CP_ACP);
- SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS);
- delete [] KeyName;
-
- // First add selected code language translation
- v = MAKELONG(m_ChildStringLists.get_lang(Index), m_ChildStringLists.get_codepage(Index));
- strm.add (&v, sizeof (v));
-
- for ( int k =0; k < m_ChildStringLists.getnum(); k++ )
- {
- if ( k != Index )
- {
- v = MAKELONG(m_ChildStringLists.get_lang(k), m_ChildStringLists.get_codepage(k));
- strm.add (&v, sizeof (v));
- }
- }
-
- wSize = WORD(strm.getlen() - p1);
- *(WORD*)((PBYTE)strm.get()+p1)=wSize;
- wSize = WORD(sizeof (int) * m_ChildStringLists.getnum());
- p1+=sizeof(WORD);
- *(WORD*)((PBYTE)strm.get()+p1)=wSize;
-
- wSize = WORD(strm.getlen() - p);
- *(WORD*)((PBYTE)strm.get()+p)=wSize;
- }
-
- wSize = WORD(strm.getlen());
- *(WORD*)((PBYTE)strm.get())=wSize;
-}
-
-// Returns 0 if success, 1 if already defined
-int CResourceVersionInfo::SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue)
-{
- int pos = m_ChildStringLists.find(lang_id, codepage);
- if ( pos == -1 )
- {
- pos = m_ChildStringLists.add(lang_id, codepage);
- }
- DefineList *pStrings = m_ChildStringLists.get_strings(pos);
- return pStrings->add(AKeyName, AValue);
-}
-
-int CResourceVersionInfo::GetStringTablesCount()
-{
- return m_ChildStringLists.getnum();
-}
-
-LANGID CResourceVersionInfo::GetLangID(int Index)
-{
- return m_ChildStringLists.get_lang(Index);
-}
-
-int CResourceVersionInfo::GetCodePage(int Index)
-{
- return m_ChildStringLists.get_codepage(Index);
-}
-
-char *CResourceVersionInfo::FindKey(LANGID LangID, int codepage, char *pKeyName)
-{
- int pos = m_ChildStringLists.find(LangID, codepage);
- if ( pos == -1 )
- {
- return NULL;
- }
- DefineList *pStrings = m_ChildStringLists.get_strings(pos);
- return pStrings->find(pKeyName);
-}
-
-#endif
+/* + * ResourceVersionInfo.cpp: implementation of the CResourceVersionInfo class. + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "ResourceVersionInfo.h" + +#include "Platform.h" +#include "util.h" +#include "winchar.h" + +#ifdef NSIS_SUPPORT_VERSION_INFO + +#ifndef VOS__WINDOWS32 +# define VOS__WINDOWS32 4 +#endif +#ifndef VFT_APP +# define VFT_APP 1 +#endif + +#ifndef _WIN32 +# include <iconv.h> +#endif + +struct version_string_list +{ + int codepage; + LANGID lang_id; + int name; + DefineList *pChildStrings; +}; + +CVersionStrigList::~CVersionStrigList() +{ + struct version_string_list *itr = (struct version_string_list *) gr.get(); + int i = gr.getlen() / sizeof(struct version_string_list); + + while (i--) + { + delete itr[i].pChildStrings; + } +} + +int CVersionStrigList::add(LANGID langid, int codepage) +{ + char Buff[10]; + sprintf(Buff, "%04x", langid); + int pos = SortedStringListND<struct version_string_list>::add(Buff); + if (pos == -1) return false; + ((struct version_string_list*)gr.get())[pos].pChildStrings = new DefineList; + ((struct version_string_list*)gr.get())[pos].codepage = codepage; + ((struct version_string_list*)gr.get())[pos].lang_id = langid; + return pos; +} + +LANGID CVersionStrigList::get_lang(int idx) +{ + version_string_list *data=(version_string_list *)gr.get(); + return data[idx].lang_id; +} + +int CVersionStrigList::get_codepage(int idx) +{ + version_string_list *data=(version_string_list *)gr.get(); + return data[idx].codepage; +} + +DefineList* CVersionStrigList::get_strings(int idx) +{ + version_string_list *data=(version_string_list *)gr.get(); + return data[idx].pChildStrings; +} + +int CVersionStrigList::find(LANGID lang_id, int codepage) +{ + char Buff[10]; + sprintf(Buff, "%04x", lang_id); + return SortedStringListND<struct version_string_list>::find(Buff); +} + +int CVersionStrigList::getlen() +{ + return strings.getlen(); +} + +int CVersionStrigList::getnum() +{ + return gr.getlen()/sizeof(struct version_string_list); +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +CResourceVersionInfo::CResourceVersionInfo() +{ + memset(&m_FixedInfo, 0, sizeof(VS_FIXEDFILEINFO)); + m_FixedInfo.dwSignature = 0xFEEF04BD; + m_FixedInfo.dwFileOS = VOS__WINDOWS32; + m_FixedInfo.dwFileType = VFT_APP; +} + +CResourceVersionInfo::~CResourceVersionInfo() +{ + +} + +void CResourceVersionInfo::SetFileFlags(int Value) +{ + m_FixedInfo.dwFileFlags = (m_FixedInfo.dwFileFlags & ~(m_FixedInfo.dwFileFlagsMask)) || Value; +} + +void CResourceVersionInfo::SetFileVersion(int HighPart, int LowPart) +{ + m_FixedInfo.dwFileVersionLS = LowPart; + m_FixedInfo.dwFileVersionMS = HighPart; +} + +void CResourceVersionInfo::SetProductVersion(int HighPart, int LowPart) +{ + m_FixedInfo.dwProductVersionLS = LowPart; + m_FixedInfo.dwProductVersionMS = HighPart; +} + +int GetVersionHeader (LPSTR &p, WORD &wLength, WORD &wValueLength, WORD &wType) +{ + WCHAR *szKey; + char * baseP; + + baseP = p; + wLength = *(WORD*)p; + p += sizeof(WORD); + wValueLength = *(WORD*)p; + p += sizeof(WORD); + wType = *(WORD*)p; + p += sizeof(WORD); + szKey = (WCHAR*)p; + p += (winchar_strlen(szKey) + 1) * sizeof (WCHAR); + while ( ((long)p % 4) != 0 ) + p++; + return p - baseP; +} + +DWORD ZEROS = 0; + +void PadStream (GrowBuf &strm) +{ + if ( (strm.getlen() % 4) != 0 ) + strm.add (&ZEROS, 4 - (strm.getlen() % 4)); +} + +void SaveVersionHeader (GrowBuf &strm, WORD wLength, WORD wValueLength, WORD wType, const WCHAR *key, void *value) +{ + WORD valueLen; + WORD keyLen; + + strm.add (&wLength, sizeof (wLength)); + + strm.add (&wValueLength, sizeof (wValueLength)); + strm.add (&wType, sizeof (wType)); + keyLen = WORD((winchar_strlen(key) + 1) * sizeof (WCHAR)); + strm.add ((void*)key, keyLen); + + PadStream(strm); + + if ( wValueLength > 0 ) + { + valueLen = wValueLength; + if ( wType == 1 ) + valueLen = valueLen * WORD(sizeof (WCHAR)); + strm.add (value, valueLen); + } +} + +void CResourceVersionInfo::ExportToStream(GrowBuf &strm, int Index) +{ + DWORD v; + WORD wSize; + int p, p1; + WCHAR *KeyName, *KeyValue; + + strm.resize(0); + KeyName = winchar_fromansi("VS_VERSION_INFO"); + SaveVersionHeader (strm, 0, sizeof (VS_FIXEDFILEINFO), 0, KeyName, &m_FixedInfo); + delete [] KeyName; + + DefineList *pChildStrings = m_ChildStringLists.get_strings(Index); + if ( pChildStrings->getnum() > 0 ) + { + GrowBuf stringInfoStream; + int codepage = m_ChildStringLists.get_codepage(Index); + LANGID langid = m_ChildStringLists.get_lang(Index); + char Buff[16]; + sprintf(Buff, "%04x%04x", langid, codepage); + KeyName = winchar_fromansi(Buff, CP_ACP); + SaveVersionHeader (stringInfoStream, 0, 0, 0, KeyName, &ZEROS); + delete [] KeyName; + + for ( int i = 0; i < pChildStrings->getnum(); i++ ) + { + PadStream (stringInfoStream); + + p = stringInfoStream.getlen(); + KeyName = winchar_fromansi(pChildStrings->getname(i), codepage); + KeyValue = winchar_fromansi(pChildStrings->getvalue(i), codepage); + SaveVersionHeader (stringInfoStream, 0, WORD(winchar_strlen(KeyValue) + 1), 1, KeyName, (void*)KeyValue); + delete [] KeyName; + delete [] KeyValue; + wSize = WORD(stringInfoStream.getlen() - p); + + *(WORD*)((PBYTE)stringInfoStream.get()+p)=wSize; + } + + wSize = WORD(stringInfoStream.getlen()); + *(WORD*)((PBYTE)stringInfoStream.get())=wSize; + + PadStream (strm); + p = strm.getlen(); + KeyName = winchar_fromansi("StringFileInfo", CP_ACP); + SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS); + delete [] KeyName; + strm.add (stringInfoStream.get(), stringInfoStream.getlen()); + wSize = WORD(strm.getlen() - p); + + *(WORD*)((PBYTE)strm.get()+p)=wSize; + } + + // Show all languages avaiable using Var-Translations + if ( m_ChildStringLists.getnum() > 0 ) + { + PadStream (strm); + p = strm.getlen(); + KeyName = winchar_fromansi("VarFileInfo", CP_ACP); + SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS); + delete [] KeyName; + PadStream (strm); + + p1 = strm.getlen(); + KeyName = winchar_fromansi("Translation", CP_ACP); + SaveVersionHeader (strm, 0, 0, 0, KeyName, &ZEROS); + delete [] KeyName; + + // First add selected code language translation + v = MAKELONG(m_ChildStringLists.get_lang(Index), m_ChildStringLists.get_codepage(Index)); + strm.add (&v, sizeof (v)); + + for ( int k =0; k < m_ChildStringLists.getnum(); k++ ) + { + if ( k != Index ) + { + v = MAKELONG(m_ChildStringLists.get_lang(k), m_ChildStringLists.get_codepage(k)); + strm.add (&v, sizeof (v)); + } + } + + wSize = WORD(strm.getlen() - p1); + *(WORD*)((PBYTE)strm.get()+p1)=wSize; + wSize = WORD(sizeof (int) * m_ChildStringLists.getnum()); + p1+=sizeof(WORD); + *(WORD*)((PBYTE)strm.get()+p1)=wSize; + + wSize = WORD(strm.getlen() - p); + *(WORD*)((PBYTE)strm.get()+p)=wSize; + } + + wSize = WORD(strm.getlen()); + *(WORD*)((PBYTE)strm.get())=wSize; +} + +// Returns 0 if success, 1 if already defined +int CResourceVersionInfo::SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue) +{ + int pos = m_ChildStringLists.find(lang_id, codepage); + if ( pos == -1 ) + { + pos = m_ChildStringLists.add(lang_id, codepage); + } + DefineList *pStrings = m_ChildStringLists.get_strings(pos); + return pStrings->add(AKeyName, AValue); +} + +int CResourceVersionInfo::GetStringTablesCount() +{ + return m_ChildStringLists.getnum(); +} + +LANGID CResourceVersionInfo::GetLangID(int Index) +{ + return m_ChildStringLists.get_lang(Index); +} + +int CResourceVersionInfo::GetCodePage(int Index) +{ + return m_ChildStringLists.get_codepage(Index); +} + +char *CResourceVersionInfo::FindKey(LANGID LangID, int codepage, char *pKeyName) +{ + int pos = m_ChildStringLists.find(LangID, codepage); + if ( pos == -1 ) + { + return NULL; + } + DefineList *pStrings = m_ChildStringLists.get_strings(pos); + return pStrings->find(pKeyName); +} + +#endif diff --git a/Source/ResourceVersionInfo.h b/Source/ResourceVersionInfo.h index 264ee3f..1f1c5ec 100755 --- a/Source/ResourceVersionInfo.h +++ b/Source/ResourceVersionInfo.h @@ -1,67 +1,67 @@ -/*
- * ResourceVersionInfo.h: interface for the CResourceVersionInfo class.
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#if !defined(AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_)
-#define AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include "exehead/config.h"
-#ifdef NSIS_SUPPORT_VERSION_INFO
-
-#include "Platform.h"
-#include "strlist.h"
-
-struct version_string_list;
-
-class CVersionStrigList : public SortedStringListND<struct version_string_list>
-{
-public:
- ~CVersionStrigList();
- int add(LANGID langid, int codepage);
- LANGID get_lang(int idx);
- int get_codepage(int idx);
- DefineList* get_strings(int idx);
- int find(LANGID lang_id, int codepage);
- int getlen();
- int getnum();
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////////
-class CResourceVersionInfo
-{
- VS_FIXEDFILEINFO m_FixedInfo;
- CVersionStrigList m_ChildStringLists;
-
-public:
- CResourceVersionInfo();
- virtual ~CResourceVersionInfo();
- int SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue);
- void SetFileFlags(int Value);
- void SetFileVersion(int HighPart, int LowPart);
- void SetProductVersion(int HighPart, int LowPart);
- void ExportToStream(GrowBuf &strm, int Index);
- int GetStringTablesCount();
- LANGID GetLangID(int Index);
- int GetCodePage(int Index);
- char *FindKey(LANGID LangID, int codepage, char *pKeyName);
-};
-
-#endif
-
-#endif // !defined(AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_)
+/* + * ResourceVersionInfo.h: interface for the CResourceVersionInfo class. + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#if !defined(AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_) +#define AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "exehead/config.h" +#ifdef NSIS_SUPPORT_VERSION_INFO + +#include "Platform.h" +#include "strlist.h" + +struct version_string_list; + +class CVersionStrigList : public SortedStringListND<struct version_string_list> +{ +public: + ~CVersionStrigList(); + int add(LANGID langid, int codepage); + LANGID get_lang(int idx); + int get_codepage(int idx); + DefineList* get_strings(int idx); + int find(LANGID lang_id, int codepage); + int getlen(); + int getnum(); +}; + +///////////////////////////////////////////////////////////////////////////////////////////// +class CResourceVersionInfo +{ + VS_FIXEDFILEINFO m_FixedInfo; + CVersionStrigList m_ChildStringLists; + +public: + CResourceVersionInfo(); + virtual ~CResourceVersionInfo(); + int SetKeyValue(LANGID lang_id, int codepage, char* AKeyName, char* AValue); + void SetFileFlags(int Value); + void SetFileVersion(int HighPart, int LowPart); + void SetProductVersion(int HighPart, int LowPart); + void ExportToStream(GrowBuf &strm, int Index); + int GetStringTablesCount(); + LANGID GetLangID(int Index); + int GetCodePage(int Index); + char *FindKey(LANGID LangID, int codepage, char *pKeyName); +}; + +#endif + +#endif // !defined(AFX_RESOURCEVERSIONINFO_H__80439ADA_49DA_4623_8DA9_1663FF356E76__INCLUDED_) diff --git a/Source/SConscript b/Source/SConscript index 5215c89..505e438 100755 --- a/Source/SConscript +++ b/Source/SConscript @@ -1,93 +1,94 @@ -target = 'makensis'
-
-pch = 'Platform.h'
-
-makensis_files = Split("""
- build.cpp
- clzma.cpp
- crc32.c
- DialogTemplate.cpp
- dirreader.cpp
- fileform.cpp
- growbuf.cpp
- lang.cpp
- lineparse.cpp
- makenssi.cpp
- manifest.cpp
- mmap.cpp
- Plugins.cpp
- ResourceEditor.cpp
- ResourceVersionInfo.cpp
- script.cpp
- ShConstants.cpp
- strlist.cpp
- tokens.cpp
- util.cpp
- winchar.cpp
- writer.cpp
-""")
-
-bzip2_files = Split("""
- bzip2/blocksort.c
- bzip2/bzlib.c
- bzip2/compress.c
- bzip2/huffman.c
-""")
-
-lzma_files = Split("""
- 7zip/7zGuids.cpp
- 7zip/7zip/Common/OutBuffer.cpp
- 7zip/7zip/Common/StreamUtils.cpp
- 7zip/7zip/Compress/LZ/LZInWindow.cpp
- 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp
- 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp
- 7zip/Common/Alloc.cpp
- 7zip/Common/CRC.cpp
-""")
-
-zlib_files = Split("""
- zlib/deflate.c
- zlib/trees.c
-""")
-
-libs = Split("""
- gdi32
- user32
- pthread
- iconv
-""")
-
-Import('env AddAvailableLibs')
-
-##### Use available libraries
-
-if env['PLATFORM'] == 'win32':
- # XXX will cause problems if makensis is cross compiled
- # on freebsd, libversion.a exists and gives trouble if linked
- libs += ['version']
-
-AddAvailableLibs(env, libs)
-
-##### Defines
-
-env.Append(CPPDEFINES = ['_WIN32_IE=0x0500'])
-
-##### Set PCH
-
-# XXX doesn't work
-#env['PCH'] = env.PCH(pch)[0]
-#env['PCHSTOP'] = pch
-
-##### LZMA specific defines
-
-lzma_env = env.Clone()
-lzma_env.Append(CPPDEFINES = ['COMPRESS_MF_BT'])
-lzma_files = lzma_env.Object(lzma_files)
-
-##### Compile makensis
-
-files = makensis_files + bzip2_files + lzma_files + zlib_files
-
-makensis = env.Program(target, files)
-
-Return('makensis')
+target = 'makensis' + +pch = 'Platform.h' + +makensis_files = Split(""" + build.cpp + clzma.cpp + crc32.c + DialogTemplate.cpp + dirreader.cpp + fileform.cpp + growbuf.cpp + icon.cpp + lang.cpp + lineparse.cpp + makenssi.cpp + manifest.cpp + mmap.cpp + Plugins.cpp + ResourceEditor.cpp + ResourceVersionInfo.cpp + script.cpp + ShConstants.cpp + strlist.cpp + tokens.cpp + util.cpp + winchar.cpp + writer.cpp +""") + +bzip2_files = Split(""" + bzip2/blocksort.c + bzip2/bzlib.c + bzip2/compress.c + bzip2/huffman.c +""") + +lzma_files = Split(""" + 7zip/7zGuids.cpp + 7zip/7zip/Common/OutBuffer.cpp + 7zip/7zip/Common/StreamUtils.cpp + 7zip/7zip/Compress/LZ/LZInWindow.cpp + 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp + 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp + 7zip/Common/Alloc.cpp + 7zip/Common/CRC.cpp +""") + +zlib_files = Split(""" + zlib/deflate.c + zlib/trees.c +""") + +libs = Split(""" + gdi32 + user32 + pthread + iconv +""") + +Import('env AddAvailableLibs') + +##### Use available libraries + +if env['PLATFORM'] == 'win32': + # XXX will cause problems if makensis is cross compiled + # on freebsd, libversion.a exists and gives trouble if linked + libs += ['version'] + +AddAvailableLibs(env, libs) + +##### Defines + +env.Append(CPPDEFINES = ['_WIN32_IE=0x0500']) + +##### Set PCH + +# XXX doesn't work +#env['PCH'] = env.PCH(pch)[0] +#env['PCHSTOP'] = pch + +##### LZMA specific defines + +lzma_env = env.Clone() +lzma_env.Append(CPPDEFINES = ['COMPRESS_MF_BT']) +lzma_files = lzma_env.Object(lzma_files) + +##### Compile makensis + +files = makensis_files + bzip2_files + lzma_files + zlib_files + +makensis = env.Program(target, files) + +Return('makensis') diff --git a/Source/ShConstants.cpp b/Source/ShConstants.cpp index 66f2a27..b3aa0fd 100755 --- a/Source/ShConstants.cpp +++ b/Source/ShConstants.cpp @@ -1,85 +1,85 @@ -/*
- * ShConstants.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "ShConstants.h"
-
-ConstantsStringList::ConstantsStringList()
-{
- index = 0;
-}
-
-int ConstantsStringList::add(const char *name, int value1, int value2)
-{
- int pos=SortedStringListND<struct constantstring>::add(name);
- if (pos == -1) return -1;
-
- ((struct constantstring*)gr.get())[pos].index = index;
- ((struct constantstring*)gr.get())[pos].pos = pos;
- ((struct constantstring*)gr.get())[pos].value1 = value1;
- ((struct constantstring*)gr.get())[pos].value2 = value2;
-
- int temp = index;
- index++;
-
- return temp;
-}
-
-int ConstantsStringList::get(char *name, int n_chars /*= -1*/)
-{
- int v=SortedStringListND<struct constantstring>::find(name, n_chars);
- if (v==-1) return -1;
- return (((struct constantstring*)gr.get())[v].index);
-}
-
-int ConstantsStringList::getnum()
-{
- return index;
-}
-
-int ConstantsStringList::get_value1(int idx)
-{
- int pos=get_internal_idx(idx);
- if (pos==-1) return -1;
- return (((struct constantstring*)gr.get())[pos].value1);
-}
-
-int ConstantsStringList::get_value2(int idx)
-{
- int pos=get_internal_idx(idx);
- if (pos==-1) return -1;
- return (((struct constantstring*)gr.get())[pos].value2);
-}
-
-char* ConstantsStringList::idx2name(int idx)
-{
- int pos=get_internal_idx(idx);
- if (pos==-1) return NULL;
- struct constantstring *data=(struct constantstring *)gr.get();
- return ((char*)strings.get() + data[pos].name);
-}
-
-int ConstantsStringList::get_internal_idx(int idx)
-{
- struct constantstring *data=(struct constantstring *)gr.get();
- for (int i = 0; i < index; i++)
- {
- if (data[i].index == idx)
- {
- return i;
- }
- }
- return -1;
-}
+/* + * ShConstants.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "ShConstants.h" + +ConstantsStringList::ConstantsStringList() +{ + index = 0; +} + +int ConstantsStringList::add(const char *name, int value1, int value2) +{ + int pos=SortedStringListND<struct constantstring>::add(name); + if (pos == -1) return -1; + + ((struct constantstring*)gr.get())[pos].index = index; + ((struct constantstring*)gr.get())[pos].pos = pos; + ((struct constantstring*)gr.get())[pos].value1 = value1; + ((struct constantstring*)gr.get())[pos].value2 = value2; + + int temp = index; + index++; + + return temp; +} + +int ConstantsStringList::get(char *name, int n_chars /*= -1*/) +{ + int v=SortedStringListND<struct constantstring>::find(name, n_chars); + if (v==-1) return -1; + return (((struct constantstring*)gr.get())[v].index); +} + +int ConstantsStringList::getnum() +{ + return index; +} + +int ConstantsStringList::get_value1(int idx) +{ + int pos=get_internal_idx(idx); + if (pos==-1) return -1; + return (((struct constantstring*)gr.get())[pos].value1); +} + +int ConstantsStringList::get_value2(int idx) +{ + int pos=get_internal_idx(idx); + if (pos==-1) return -1; + return (((struct constantstring*)gr.get())[pos].value2); +} + +char* ConstantsStringList::idx2name(int idx) +{ + int pos=get_internal_idx(idx); + if (pos==-1) return NULL; + struct constantstring *data=(struct constantstring *)gr.get(); + return ((char*)strings.get() + data[pos].name); +} + +int ConstantsStringList::get_internal_idx(int idx) +{ + struct constantstring *data=(struct constantstring *)gr.get(); + for (int i = 0; i < index; i++) + { + if (data[i].index == idx) + { + return i; + } + } + return -1; +} diff --git a/Source/ShConstants.h b/Source/ShConstants.h index 9875b51..2b2f2f3 100755 --- a/Source/ShConstants.h +++ b/Source/ShConstants.h @@ -1,47 +1,47 @@ -/*
- * ShConstants.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2003 Ramon
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___CONSTANTS___H_____
-#define ___CONSTANTS___H_____
-
-#include "strlist.h"
-
-struct constantstring {
- int name;
- int index;
- int pos;
- int value1;
- int value2;
-};
-
-class ConstantsStringList : public SortedStringListND<struct constantstring>
-{
- public:
- ConstantsStringList();
-
- int add(const char *name, int value1, int value2);
- int get(char *name, int n_chars = -1);
- int getnum();
- int get_value1(int idx);
- int get_value2(int idx);
- char *idx2name(int idx);
-
- private:
- int index;
- int get_internal_idx(int idx);
-};
-
-#endif
+/* + * ShConstants.h + * + * This file is a part of NSIS. + * + * Copyright (C) 2003 Ramon + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___CONSTANTS___H_____ +#define ___CONSTANTS___H_____ + +#include "strlist.h" + +struct constantstring { + int name; + int index; + int pos; + int value1; + int value2; +}; + +class ConstantsStringList : public SortedStringListND<struct constantstring> +{ + public: + ConstantsStringList(); + + int add(const char *name, int value1, int value2); + int get(char *name, int n_chars = -1); + int getnum(); + int get_value1(int idx); + int get_value2(int idx); + char *idx2name(int idx); + + private: + int index; + int get_internal_idx(int idx); +}; + +#endif diff --git a/Source/Tests/DialogTemplate.cpp b/Source/Tests/DialogTemplate.cpp index 5719943..6a0c1b3 100755 --- a/Source/Tests/DialogTemplate.cpp +++ b/Source/Tests/DialogTemplate.cpp @@ -1,47 +1,47 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../DialogTemplate.h"
-
-#include <stdlib.h>
-
-class CDialogTemplateTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( CDialogTemplateTest );
- CPPUNIT_TEST( testCorrectness );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testCorrectness() {
- unsigned char original_dialog[184] = {
- 1, 0, 255, 255, 0, 0, 0, 0, 0, 0,
- 0, 0, 72, 4, 0, 64, 3, 0, 0, 0, 0,
- 0, 10, 1, 130, 0, 0, 0, 0, 0, 0, 0,
- 8, 0, 0, 0, 0, 1, 77, 0, 83, 0, 32,
- 0, 83, 0, 104, 0, 101, 0, 108, 0, 108, 0,
- 32, 0, 68, 0, 108, 0, 103, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 80,
- 0, 0, 0, 0, 22, 0, 20, 0, 7, 4, 0,
- 0, 255, 255, 130, 0, 255, 255, 103, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 80, 25, 0, 0, 0, 241, 0, 23, 0,
- 238, 3, 0, 0, 255, 255, 130, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8,
- 161, 80, 0, 0, 24, 0, 10, 1, 105, 0, 232,
- 3, 0, 0, 82, 0, 105, 0, 99, 0, 104, 0,
- 69, 0, 100, 0, 105, 0, 116, 0, 50, 0, 48,
- 0, 65, 0, 0, 0, 0, 0, 0, 0
- };
-
- CDialogTemplate dt(original_dialog, 1252);
-
- DWORD dwSize;
- unsigned char *saved_dialog = dt.Save(dwSize);
-
- CPPUNIT_ASSERT_EQUAL( (DWORD) sizeof(original_dialog), dwSize );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(saved_dialog, original_dialog, dwSize) );
-
- delete [] saved_dialog;
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( CDialogTemplateTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../DialogTemplate.h" + +#include <stdlib.h> + +class CDialogTemplateTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( CDialogTemplateTest ); + CPPUNIT_TEST( testCorrectness ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testCorrectness() { + unsigned char original_dialog[184] = { + 1, 0, 255, 255, 0, 0, 0, 0, 0, 0, + 0, 0, 72, 4, 0, 64, 3, 0, 0, 0, 0, + 0, 10, 1, 130, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 1, 77, 0, 83, 0, 32, + 0, 83, 0, 104, 0, 101, 0, 108, 0, 108, 0, + 32, 0, 68, 0, 108, 0, 103, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 80, + 0, 0, 0, 0, 22, 0, 20, 0, 7, 4, 0, + 0, 255, 255, 130, 0, 255, 255, 103, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 80, 25, 0, 0, 0, 241, 0, 23, 0, + 238, 3, 0, 0, 255, 255, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, + 161, 80, 0, 0, 24, 0, 10, 1, 105, 0, 232, + 3, 0, 0, 82, 0, 105, 0, 99, 0, 104, 0, + 69, 0, 100, 0, 105, 0, 116, 0, 50, 0, 48, + 0, 65, 0, 0, 0, 0, 0, 0, 0 + }; + + CDialogTemplate dt(original_dialog, 1252); + + DWORD dwSize; + unsigned char *saved_dialog = dt.Save(dwSize); + + CPPUNIT_ASSERT_EQUAL( (DWORD) sizeof(original_dialog), dwSize ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(saved_dialog, original_dialog, dwSize) ); + + delete [] saved_dialog; + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( CDialogTemplateTest ); diff --git a/Source/Tests/ResourceEditor.cpp b/Source/Tests/ResourceEditor.cpp index 179f8b9..8bf5739 100755 --- a/Source/Tests/ResourceEditor.cpp +++ b/Source/Tests/ResourceEditor.cpp @@ -1,832 +1,832 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../ResourceEditor.h"
-
-#include <stdlib.h>
-
-class CResourceEditorTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( CResourceEditorTest );
- CPPUNIT_TEST( testCorrectness );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testCorrectness() {
- extern unsigned char original_pe[8704];
-
- CResourceEditor re(original_pe, sizeof(original_pe));
-
- DWORD size;
-
- // get size
- size = re.Save(NULL, size);
- unsigned char *saved_pe = new unsigned char[size];
-
- // save
- int rc = re.Save(saved_pe, size);
- CPPUNIT_ASSERT_EQUAL( rc, 0 );
-
- // compare
- CPPUNIT_ASSERT_EQUAL( (DWORD) sizeof(original_pe), size );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(saved_pe, original_pe, size) );
-
- delete [] saved_pe;
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( CResourceEditorTest );
-
-unsigned char original_pe[8704] = {
- 77, 90, 144, 0, 3, 0, 0, 0, 4, 0,
- 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0,
- 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 14,
- 31, 186, 14, 0, 180, 9, 205, 33, 184, 1, 76,
- 205, 33, 84, 104, 105, 115, 32, 112, 114, 111, 103,
- 114, 97, 109, 32, 99, 97, 110, 110, 111, 116, 32,
- 98, 101, 32, 114, 117, 110, 32, 105, 110, 32, 68,
- 79, 83, 32, 109, 111, 100, 101, 46, 13, 13, 10,
- 36, 0, 0, 0, 0, 0, 0, 0, 252, 249, 48,
- 199, 184, 152, 94, 148, 184, 152, 94, 148, 184, 152,
- 94, 148, 184, 152, 95, 148, 168, 152, 94, 148, 59,
- 144, 3, 148, 189, 152, 94, 148, 236, 187, 111, 148,
- 185, 152, 94, 148, 127, 158, 88, 148, 185, 152, 94,
- 148, 82, 105, 99, 104, 184, 152, 94, 148, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 80, 69, 0, 0, 76, 1, 4, 0,
- 86, 34, 23, 68, 0, 0, 0, 0, 0, 0, 0,
- 0, 224, 0, 15, 1, 11, 1, 6, 0, 0, 4,
- 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 126,
- 18, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0,
- 0, 0, 64, 0, 0, 16, 0, 0, 0, 2, 0,
- 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0,
- 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0,
- 4, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 0, 16, 0, 0, 16, 0, 0, 0, 0, 16,
- 0, 0, 16, 0, 0, 0, 0, 0, 0, 16, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72,
- 32, 0, 0, 60, 0, 0, 0, 0, 80, 0, 0,
- 168, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 32, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 116,
- 101, 120, 116, 0, 0, 0, 160, 2, 0, 0, 0,
- 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 32, 0, 0, 96, 46, 114, 100, 97, 116, 97,
- 0, 0, 240, 1, 0, 0, 0, 32, 0, 0, 0,
- 2, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0,
- 64, 46, 100, 97, 116, 97, 0, 0, 0, 100, 18,
- 0, 0, 0, 48, 0, 0, 0, 20, 0, 0, 0,
- 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 64, 0, 0, 192, 46, 114, 115,
- 114, 99, 0, 0, 0, 168, 3, 0, 0, 0, 80,
- 0, 0, 0, 4, 0, 0, 0, 30, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 64, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 139, 68, 36, 8, 129, 236, 12, 2, 0,
- 0, 45, 16, 1, 0, 0, 83, 85, 86, 87, 15,
- 132, 234, 1, 0, 0, 72, 15, 133, 79, 2, 0,
- 0, 139, 132, 36, 40, 2, 0, 0, 102, 61, 2,
- 0, 117, 28, 51, 219, 83, 255, 180, 36, 36, 2,
- 0, 0, 255, 21, 60, 32, 64, 0, 83, 255, 21,
- 56, 32, 64, 0, 233, 38, 2, 0, 0, 139, 200,
- 193, 233, 16, 102, 131, 249, 1, 15, 133, 178, 0,
- 0, 0, 51, 219, 190, 71, 1, 0, 0, 83, 83,
- 189, 234, 3, 0, 0, 86, 85, 255, 180, 36, 48,
- 2, 0, 0, 255, 21, 52, 32, 64, 0, 131, 248,
- 255, 15, 132, 241, 1, 0, 0, 83, 83, 191, 233,
- 3, 0, 0, 86, 87, 255, 180, 36, 48, 2, 0,
- 0, 255, 21, 52, 32, 64, 0, 131, 248, 255, 15,
- 132, 210, 1, 0, 0, 83, 83, 86, 87, 255, 180,
- 36, 48, 2, 0, 0, 139, 61, 52, 32, 64, 0,
- 255, 215, 15, 183, 4, 197, 104, 50, 64, 0, 83,
- 83, 86, 85, 255, 180, 36, 48, 2, 0, 0, 193,
- 224, 10, 137, 68, 36, 36, 255, 215, 15, 183, 4,
- 197, 0, 48, 64, 0, 139, 76, 36, 16, 11, 200,
- 141, 68, 36, 28, 81, 104, 84, 66, 64, 0, 80,
- 255, 21, 48, 32, 64, 0, 131, 196, 12, 141, 68,
- 36, 28, 80, 104, 235, 3, 0, 0, 255, 180, 36,
- 40, 2, 0, 0, 255, 21, 44, 32, 64, 0, 233,
- 101, 1, 0, 0, 102, 61, 1, 0, 15, 133, 91,
- 1, 0, 0, 51, 219, 190, 71, 1, 0, 0, 83,
- 83, 189, 234, 3, 0, 0, 86, 85, 255, 180, 36,
- 48, 2, 0, 0, 255, 21, 52, 32, 64, 0, 131,
- 248, 255, 15, 132, 53, 1, 0, 0, 83, 83, 191,
- 233, 3, 0, 0, 86, 87, 255, 180, 36, 48, 2,
- 0, 0, 255, 21, 52, 32, 64, 0, 131, 248, 255,
- 15, 132, 22, 1, 0, 0, 106, 16, 106, 2, 255,
- 21, 4, 32, 64, 0, 59, 195, 137, 68, 36, 16,
- 15, 132, 0, 1, 0, 0, 80, 255, 21, 0, 32,
- 64, 0, 83, 83, 86, 87, 255, 180, 36, 48, 2,
- 0, 0, 139, 61, 52, 32, 64, 0, 137, 68, 36,
- 44, 255, 215, 15, 183, 4, 197, 104, 50, 64, 0,
- 83, 83, 86, 85, 255, 180, 36, 48, 2, 0, 0,
- 193, 224, 10, 137, 68, 36, 40, 255, 215, 15, 183,
- 4, 197, 0, 48, 64, 0, 139, 76, 36, 20, 11,
- 200, 81, 104, 80, 66, 64, 0, 255, 116, 36, 32,
- 255, 21, 48, 32, 64, 0, 131, 196, 12, 255, 116,
- 36, 16, 255, 21, 16, 32, 64, 0, 255, 180, 36,
- 32, 2, 0, 0, 255, 21, 40, 32, 64, 0, 133,
- 192, 15, 132, 134, 0, 0, 0, 255, 21, 36, 32,
- 64, 0, 255, 116, 36, 16, 106, 1, 255, 21, 32,
- 32, 64, 0, 255, 21, 28, 32, 64, 0, 235, 108,
- 51, 219, 83, 83, 104, 128, 0, 0, 0, 255, 180,
- 36, 44, 2, 0, 0, 255, 21, 24, 32, 64, 0,
- 139, 53, 52, 32, 64, 0, 51, 255, 189, 234, 3,
- 0, 0, 255, 183, 4, 48, 64, 0, 83, 104, 67,
- 1, 0, 0, 85, 255, 180, 36, 48, 2, 0, 0,
- 255, 214, 131, 199, 8, 129, 255, 104, 2, 0, 0,
- 114, 223, 51, 237, 191, 233, 3, 0, 0, 255, 181,
- 108, 50, 64, 0, 83, 104, 67, 1, 0, 0, 87,
- 255, 180, 36, 48, 2, 0, 0, 255, 214, 131, 197,
- 8, 129, 253, 224, 2, 0, 0, 114, 223, 95, 94,
- 93, 51, 192, 91, 129, 196, 12, 2, 0, 0, 194,
- 16, 0, 106, 0, 104, 0, 16, 64, 0, 106, 0,
- 106, 101, 106, 0, 255, 21, 12, 32, 64, 0, 80,
- 255, 21, 64, 32, 64, 0, 106, 0, 255, 21, 8,
- 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 220, 32, 0, 0, 234, 32, 0, 0,
- 248, 32, 0, 0, 6, 33, 0, 0, 204, 32, 0,
- 0, 0, 0, 0, 0, 40, 33, 0, 0, 56, 33,
- 0, 0, 74, 33, 0, 0, 94, 33, 0, 0, 112,
- 33, 0, 0, 128, 33, 0, 0, 146, 33, 0, 0,
- 158, 33, 0, 0, 180, 33, 0, 0, 198, 33, 0,
- 0, 210, 33, 0, 0, 0, 0, 0, 0, 132, 32,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26,
- 33, 0, 0, 0, 32, 0, 0, 156, 32, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 228, 33, 0,
- 0, 24, 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 220, 32, 0, 0, 234, 32, 0, 0,
- 248, 32, 0, 0, 6, 33, 0, 0, 204, 32, 0,
- 0, 0, 0, 0, 0, 40, 33, 0, 0, 56, 33,
- 0, 0, 74, 33, 0, 0, 94, 33, 0, 0, 112,
- 33, 0, 0, 128, 33, 0, 0, 146, 33, 0, 0,
- 158, 33, 0, 0, 180, 33, 0, 0, 198, 33, 0,
- 0, 210, 33, 0, 0, 0, 0, 0, 0, 0, 2,
- 71, 108, 111, 98, 97, 108, 85, 110, 108, 111, 99,
- 107, 0, 0, 249, 1, 71, 108, 111, 98, 97, 108,
- 76, 111, 99, 107, 0, 0, 238, 1, 71, 108, 111,
- 98, 97, 108, 65, 108, 108, 111, 99, 0, 175, 0,
- 69, 120, 105, 116, 80, 114, 111, 99, 101, 115, 115,
- 0, 119, 1, 71, 101, 116, 77, 111, 100, 117, 108,
- 101, 72, 97, 110, 100, 108, 101, 65, 0, 0, 75,
- 69, 82, 78, 69, 76, 51, 50, 46, 100, 108, 108,
- 0, 0, 58, 2, 83, 101, 110, 100, 77, 101, 115,
- 115, 97, 103, 101, 65, 0, 0, 66, 0, 67, 108,
- 111, 115, 101, 67, 108, 105, 112, 98, 111, 97, 114,
- 100, 0, 0, 73, 2, 83, 101, 116, 67, 108, 105,
- 112, 98, 111, 97, 114, 100, 68, 97, 116, 97, 0,
- 0, 193, 0, 69, 109, 112, 116, 121, 67, 108, 105,
- 112, 98, 111, 97, 114, 100, 0, 0, 245, 1, 79,
- 112, 101, 110, 67, 108, 105, 112, 98, 111, 97, 114,
- 100, 0, 82, 2, 83, 101, 116, 68, 108, 103, 73,
- 116, 101, 109, 84, 101, 120, 116, 65, 0, 213, 2,
- 119, 115, 112, 114, 105, 110, 116, 102, 65, 0, 53,
- 2, 83, 101, 110, 100, 68, 108, 103, 73, 116, 101,
- 109, 77, 101, 115, 115, 97, 103, 101, 65, 0, 3,
- 2, 80, 111, 115, 116, 81, 117, 105, 116, 77, 101,
- 115, 115, 97, 103, 101, 0, 198, 0, 69, 110, 100,
- 68, 105, 97, 108, 111, 103, 0, 158, 0, 68, 105,
- 97, 108, 111, 103, 66, 111, 120, 80, 97, 114, 97,
- 109, 65, 0, 85, 83, 69, 82, 51, 50, 46, 100,
- 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 64, 66, 64, 0, 127, 0, 0, 0, 48,
- 66, 64, 0, 54, 0, 0, 0, 32, 66, 64, 0,
- 28, 0, 0, 0, 16, 66, 64, 0, 1, 0, 0,
- 0, 4, 66, 64, 0, 43, 0, 0, 0, 244, 65,
- 64, 0, 77, 0, 0, 0, 228, 65, 64, 0, 44,
- 0, 0, 0, 216, 65, 64, 0, 45, 0, 0, 0,
- 204, 65, 64, 0, 35, 0, 0, 0, 188, 65, 64,
- 0, 69, 0, 0, 0, 172, 65, 64, 0, 2, 0,
- 0, 0, 156, 65, 64, 0, 3, 0, 0, 0, 140,
- 65, 64, 0, 4, 0, 0, 0, 124, 65, 64, 0,
- 26, 0, 0, 0, 108, 65, 64, 0, 5, 0, 0,
- 0, 96, 65, 64, 0, 6, 0, 0, 0, 84, 65,
- 64, 0, 101, 0, 0, 0, 72, 65, 64, 0, 19,
- 0, 0, 0, 60, 65, 64, 0, 9, 0, 0, 0,
- 44, 65, 64, 0, 37, 0, 0, 0, 28, 65, 64,
- 0, 56, 0, 0, 0, 12, 65, 64, 0, 41, 0,
- 0, 0, 0, 65, 64, 0, 11, 0, 0, 0, 240,
- 64, 64, 0, 12, 0, 0, 0, 228, 64, 64, 0,
- 86, 0, 0, 0, 212, 64, 64, 0, 55, 0, 0,
- 0, 196, 64, 64, 0, 7, 0, 0, 0, 184, 64,
- 64, 0, 8, 0, 0, 0, 172, 64, 64, 0, 71,
- 0, 0, 0, 156, 64, 64, 0, 13, 0, 0, 0,
- 144, 64, 64, 0, 57, 0, 0, 0, 132, 64, 64,
- 0, 14, 0, 0, 0, 116, 64, 64, 0, 15, 0,
- 0, 0, 100, 64, 64, 0, 33, 0, 0, 0, 84,
- 64, 64, 0, 16, 0, 0, 0, 68, 64, 64, 0,
- 17, 0, 0, 0, 52, 64, 64, 0, 75, 0, 0,
- 0, 36, 64, 64, 0, 96, 0, 0, 0, 20, 64,
- 64, 0, 63, 0, 0, 0, 8, 64, 64, 0, 87,
- 0, 0, 0, 248, 63, 64, 0, 18, 0, 0, 0,
- 236, 63, 64, 0, 64, 0, 0, 0, 224, 63, 64,
- 0, 38, 0, 0, 0, 208, 63, 64, 0, 39, 0,
- 0, 0, 192, 63, 64, 0, 47, 0, 0, 0, 176,
- 63, 64, 0, 62, 0, 0, 0, 164, 63, 64, 0,
- 76, 0, 0, 0, 148, 63, 64, 0, 88, 0, 0,
- 0, 132, 63, 64, 0, 78, 0, 0, 0, 116, 63,
- 64, 0, 80, 0, 0, 0, 100, 63, 64, 0, 97,
- 0, 0, 0, 88, 63, 64, 0, 20, 0, 0, 0,
- 72, 63, 64, 0, 72, 0, 0, 0, 60, 63, 64,
- 0, 21, 0, 0, 0, 48, 63, 64, 0, 22, 0,
- 0, 0, 32, 63, 64, 0, 70, 0, 0, 0, 16,
- 63, 64, 0, 24, 0, 0, 0, 0, 63, 64, 0,
- 25, 0, 0, 0, 240, 62, 64, 0, 79, 0, 0,
- 0, 224, 62, 64, 0, 26, 0, 0, 0, 208, 62,
- 64, 0, 89, 0, 0, 0, 196, 62, 64, 0, 27,
- 0, 0, 0, 184, 62, 64, 0, 36, 0, 0, 0,
- 168, 62, 64, 0, 10, 0, 0, 0, 152, 62, 64,
- 0, 65, 0, 0, 0, 136, 62, 64, 0, 29, 0,
- 0, 0, 120, 62, 64, 0, 90, 0, 0, 0, 108,
- 62, 64, 0, 73, 0, 0, 0, 96, 62, 64, 0,
- 68, 0, 0, 0, 84, 62, 64, 0, 74, 0, 0,
- 0, 72, 62, 64, 0, 30, 0, 0, 0, 60, 62,
- 64, 0, 31, 0, 0, 0, 44, 62, 64, 0, 34,
- 0, 0, 0, 28, 62, 64, 0, 32, 0, 0, 0,
- 16, 62, 64, 0, 67, 0, 0, 0, 4, 62, 64,
- 0, 42, 0, 0, 0, 244, 61, 64, 0, 0, 0,
- 0, 0, 228, 61, 64, 0, 1, 0, 0, 0, 212,
- 61, 64, 0, 2, 0, 0, 0, 192, 61, 64, 0,
- 1, 0, 0, 0, 164, 61, 64, 0, 2, 0, 0,
- 0, 144, 61, 64, 0, 3, 0, 0, 0, 120, 61,
- 64, 0, 4, 0, 0, 0, 96, 61, 64, 0, 5,
- 0, 0, 0, 72, 61, 64, 0, 6, 0, 0, 0,
- 48, 61, 64, 0, 7, 0, 0, 0, 24, 61, 64,
- 0, 8, 0, 0, 0, 4, 61, 64, 0, 9, 0,
- 0, 0, 236, 60, 64, 0, 10, 0, 0, 0, 212,
- 60, 64, 0, 11, 0, 0, 0, 188, 60, 64, 0,
- 12, 0, 0, 0, 164, 60, 64, 0, 13, 0, 0,
- 0, 140, 60, 64, 0, 14, 0, 0, 0, 120, 60,
- 64, 0, 15, 0, 0, 0, 96, 60, 64, 0, 16,
- 0, 0, 0, 72, 60, 64, 0, 1, 0, 0, 0,
- 52, 60, 64, 0, 2, 0, 0, 0, 28, 60, 64,
- 0, 1, 0, 0, 0, 0, 60, 64, 0, 2, 0,
- 0, 0, 228, 59, 64, 0, 3, 0, 0, 0, 200,
- 59, 64, 0, 4, 0, 0, 0, 172, 59, 64, 0,
- 5, 0, 0, 0, 148, 59, 64, 0, 1, 0, 0,
- 0, 132, 59, 64, 0, 2, 0, 0, 0, 108, 59,
- 64, 0, 1, 0, 0, 0, 88, 59, 64, 0, 2,
- 0, 0, 0, 68, 59, 64, 0, 3, 0, 0, 0,
- 48, 59, 64, 0, 4, 0, 0, 0, 28, 59, 64,
- 0, 5, 0, 0, 0, 8, 59, 64, 0, 6, 0,
- 0, 0, 240, 58, 64, 0, 7, 0, 0, 0, 208,
- 58, 64, 0, 8, 0, 0, 0, 184, 58, 64, 0,
- 9, 0, 0, 0, 156, 58, 64, 0, 10, 0, 0,
- 0, 132, 58, 64, 0, 11, 0, 0, 0, 104, 58,
- 64, 0, 12, 0, 0, 0, 76, 58, 64, 0, 13,
- 0, 0, 0, 48, 58, 64, 0, 1, 0, 0, 0,
- 32, 58, 64, 0, 2, 0, 0, 0, 8, 58, 64,
- 0, 3, 0, 0, 0, 240, 57, 64, 0, 4, 0,
- 0, 0, 216, 57, 64, 0, 5, 0, 0, 0, 188,
- 57, 64, 0, 6, 0, 0, 0, 164, 57, 64, 0,
- 1, 0, 0, 0, 148, 57, 64, 0, 2, 0, 0,
- 0, 124, 57, 64, 0, 3, 0, 0, 0, 100, 57,
- 64, 0, 4, 0, 0, 0, 72, 57, 64, 0, 5,
- 0, 0, 0, 40, 57, 64, 0, 1, 0, 0, 0,
- 24, 57, 64, 0, 2, 0, 0, 0, 0, 57, 64,
- 0, 2, 0, 0, 0, 232, 56, 64, 0, 1, 0,
- 0, 0, 216, 56, 64, 0, 1, 0, 0, 0, 196,
- 56, 64, 0, 1, 0, 0, 0, 172, 56, 64, 0,
- 2, 0, 0, 0, 140, 56, 64, 0, 2, 0, 0,
- 0, 116, 56, 64, 0, 1, 0, 0, 0, 88, 56,
- 64, 0, 2, 0, 0, 0, 60, 56, 64, 0, 2,
- 0, 0, 0, 40, 56, 64, 0, 1, 0, 0, 0,
- 8, 56, 64, 0, 2, 0, 0, 0, 240, 55, 64,
- 0, 3, 0, 0, 0, 212, 55, 64, 0, 1, 0,
- 0, 0, 196, 55, 64, 0, 2, 0, 0, 0, 172,
- 55, 64, 0, 3, 0, 0, 0, 148, 55, 64, 0,
- 4, 0, 0, 0, 120, 55, 64, 0, 5, 0, 0,
- 0, 92, 55, 64, 0, 6, 0, 0, 0, 68, 55,
- 64, 0, 7, 0, 0, 0, 32, 55, 64, 0, 8,
- 0, 0, 0, 4, 55, 64, 0, 9, 0, 0, 0,
- 232, 54, 64, 0, 10, 0, 0, 0, 208, 54, 64,
- 0, 11, 0, 0, 0, 180, 54, 64, 0, 12, 0,
- 0, 0, 156, 54, 64, 0, 13, 0, 0, 0, 132,
- 54, 64, 0, 14, 0, 0, 0, 108, 54, 64, 0,
- 15, 0, 0, 0, 80, 54, 64, 0, 16, 0, 0,
- 0, 56, 54, 64, 0, 17, 0, 0, 0, 28, 54,
- 64, 0, 18, 0, 0, 0, 0, 54, 64, 0, 19,
- 0, 0, 0, 228, 53, 64, 0, 20, 0, 0, 0,
- 200, 53, 64, 0, 1, 0, 0, 0, 184, 53, 64,
- 0, 2, 0, 0, 0, 160, 53, 64, 0, 1, 0,
- 0, 0, 136, 53, 64, 0, 2, 0, 0, 0, 116,
- 53, 64, 0, 1, 0, 0, 0, 96, 53, 64, 0,
- 2, 0, 0, 0, 72, 53, 64, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 85, 90, 66, 69, 75, 95,
- 67, 89, 82, 73, 76, 76, 73, 67, 0, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 85, 90, 66, 69,
- 75, 95, 76, 65, 84, 73, 78, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 85, 82, 68, 85, 95, 73,
- 78, 68, 73, 65, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 85, 82, 68, 85, 95, 80, 65, 75,
- 73, 83, 84, 65, 78, 0, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 83, 87, 69, 68, 73, 83,
- 72, 95, 70, 73, 78, 76, 65, 78, 68, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 83, 87, 69, 68,
- 73, 83, 72, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 83, 80, 65, 78, 73, 83, 72, 95, 80, 85,
- 69, 82, 84, 79, 95, 82, 73, 67, 79, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 83, 80, 65, 78,
- 73, 83, 72, 95, 78, 73, 67, 65, 82, 65, 71,
- 85, 65, 0, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, 72,
- 79, 78, 68, 85, 82, 65, 83, 0, 0, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 83, 80, 65,
- 78, 73, 83, 72, 95, 69, 76, 95, 83, 65, 76,
- 86, 65, 68, 79, 82, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 95,
- 66, 79, 76, 73, 86, 73, 65, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 83, 80, 65, 78, 73, 83,
- 72, 95, 80, 65, 82, 65, 71, 85, 65, 89, 0,
- 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 83, 80, 65, 78, 73, 83, 72, 95, 85, 82, 85,
- 71, 85, 65, 89, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, 67,
- 72, 73, 76, 69, 0, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72,
- 95, 69, 67, 85, 65, 68, 79, 82, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 83, 80, 65, 78, 73,
- 83, 72, 95, 65, 82, 71, 69, 78, 84, 73, 78,
- 65, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 83, 80, 65, 78, 73, 83, 72, 95, 80, 69,
- 82, 85, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 95,
- 67, 79, 76, 79, 77, 66, 73, 65, 0, 0, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 83, 80,
- 65, 78, 73, 83, 72, 95, 86, 69, 78, 69, 90,
- 85, 69, 76, 65, 0, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72,
- 95, 68, 79, 77, 73, 78, 73, 67, 65, 78, 95,
- 82, 69, 80, 85, 66, 76, 73, 67, 0, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 83, 80, 65, 78,
- 73, 83, 72, 95, 80, 65, 78, 65, 77, 65, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 83, 80,
- 65, 78, 73, 83, 72, 95, 67, 79, 83, 84, 65,
- 95, 82, 73, 67, 65, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72,
- 95, 71, 85, 65, 84, 69, 77, 65, 76, 65, 0,
- 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 83,
- 80, 65, 78, 73, 83, 72, 95, 77, 79, 68, 69,
- 82, 78, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 83, 80, 65, 78, 73, 83, 72, 95, 77, 69,
- 88, 73, 67, 65, 78, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 83, 69, 82,
- 66, 73, 65, 78, 95, 67, 89, 82, 73, 76, 76,
- 73, 67, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 83, 69, 82, 66, 73, 65, 78, 95,
- 76, 65, 84, 73, 78, 0, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 80, 79, 82, 84, 85, 71,
- 85, 69, 83, 69, 95, 66, 82, 65, 90, 73, 76,
- 73, 65, 78, 0, 0, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 80, 79, 82, 84, 85, 71, 85,
- 69, 83, 69, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 78, 79, 82, 87, 69, 71, 73, 65, 78,
- 95, 78, 89, 78, 79, 82, 83, 75, 0, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 78, 79, 82,
- 87, 69, 71, 73, 65, 78, 95, 66, 79, 75, 77,
- 65, 76, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 78, 69, 80, 65, 76, 73, 95, 73,
- 78, 68, 73, 65, 0, 0, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 77, 65, 76, 65, 89, 95,
- 66, 82, 85, 78, 69, 73, 95, 68, 65, 82, 85,
- 83, 83, 65, 76, 65, 77, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 77, 65, 76, 65, 89, 95, 77,
- 65, 76, 65, 89, 83, 73, 65, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 76, 73, 84, 72, 85,
- 65, 78, 73, 65, 78, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 75, 79, 82, 69, 65, 78, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 75, 65,
- 83, 72, 77, 73, 82, 73, 95, 73, 78, 68, 73,
- 65, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 73, 84, 65, 76, 73, 65, 78, 95, 83, 87, 73,
- 83, 83, 0, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 73, 84, 65, 76, 73, 65, 78, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 71, 69, 82, 77,
- 65, 78, 95, 76, 73, 69, 67, 72, 84, 69, 78,
- 83, 84, 69, 73, 78, 0, 0, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 71, 69, 82, 77, 65,
- 78, 95, 76, 85, 88, 69, 77, 66, 79, 85, 82,
- 71, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 71, 69, 82, 77, 65, 78, 95, 65, 85, 83,
- 84, 82, 73, 65, 78, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 71, 69, 82, 77, 65, 78, 95, 83,
- 87, 73, 83, 83, 0, 0, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 71, 69, 82, 77, 65, 78,
- 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 70,
- 82, 69, 78, 67, 72, 95, 77, 79, 78, 65, 67,
- 79, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 70, 82, 69, 78, 67, 72, 95, 76, 85, 88,
- 69, 77, 66, 79, 85, 82, 71, 0, 0, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 70, 82, 69, 78,
- 67, 72, 95, 83, 87, 73, 83, 83, 0, 0, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 70, 82,
- 69, 78, 67, 72, 95, 67, 65, 78, 65, 68, 73,
- 65, 78, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 70, 82, 69, 78, 67, 72, 95, 66, 69, 76, 71,
- 73, 65, 78, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 70, 82, 69, 78, 67, 72, 0, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 69, 78, 71, 76,
- 73, 83, 72, 95, 80, 72, 73, 76, 73, 80, 80,
- 73, 78, 69, 83, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, 90,
- 73, 77, 66, 65, 66, 87, 69, 0, 0, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 69, 78, 71,
- 76, 73, 83, 72, 95, 84, 82, 73, 78, 73, 68,
- 65, 68, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 69, 78, 71, 76, 73, 83, 72, 95,
- 66, 69, 76, 73, 90, 69, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 69, 78, 71, 76, 73, 83,
- 72, 95, 67, 65, 82, 73, 66, 66, 69, 65, 78,
- 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 69, 78, 71, 76, 73, 83, 72, 95, 74, 65, 77,
- 65, 73, 67, 65, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, 83,
- 79, 85, 84, 72, 95, 65, 70, 82, 73, 67, 65,
- 0, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 69, 78, 71, 76, 73, 83, 72, 95, 69, 73,
- 82, 69, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 69, 78, 71, 76, 73, 83, 72, 95,
- 78, 90, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 69, 78, 71, 76, 73, 83, 72, 95, 67, 65,
- 78, 0, 83, 85, 66, 76, 65, 78, 71, 95, 69,
- 78, 71, 76, 73, 83, 72, 95, 65, 85, 83, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 69, 78, 71,
- 76, 73, 83, 72, 95, 85, 75, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 69, 78, 71, 76, 73,
- 83, 72, 95, 85, 83, 0, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 68, 85, 84, 67, 72, 95, 66,
- 69, 76, 71, 73, 65, 78, 0, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 68, 85, 84, 67, 72,
- 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 67, 72, 73, 78, 69, 83, 69, 95, 77, 65, 67,
- 65, 85, 0, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 67, 72, 73, 78, 69, 83, 69, 95, 83,
- 73, 78, 71, 65, 80, 79, 82, 69, 0, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 67, 72, 73,
- 78, 69, 83, 69, 95, 72, 79, 78, 71, 75, 79,
- 78, 71, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 67, 72, 73, 78, 69, 83, 69, 95,
- 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 67, 72,
- 73, 78, 69, 83, 69, 95, 84, 82, 65, 68, 73,
- 84, 73, 79, 78, 65, 76, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 65, 90, 69, 82, 73, 95, 67,
- 89, 82, 73, 76, 76, 73, 67, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 65, 90, 69, 82, 73,
- 95, 76, 65, 84, 73, 78, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 65, 82, 65, 66, 73, 67, 95,
- 81, 65, 84, 65, 82, 0, 0, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73,
- 67, 95, 66, 65, 72, 82, 65, 73, 78, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 65, 82, 65,
- 66, 73, 67, 95, 85, 65, 69, 0, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73,
- 67, 95, 75, 85, 87, 65, 73, 84, 0, 0, 0,
- 83, 85, 66, 76, 65, 78, 71, 95, 65, 82, 65,
- 66, 73, 67, 95, 76, 69, 66, 65, 78, 79, 78,
- 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 65,
- 82, 65, 66, 73, 67, 95, 74, 79, 82, 68, 65,
- 78, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71,
- 95, 65, 82, 65, 66, 73, 67, 95, 83, 89, 82,
- 73, 65, 0, 0, 0, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 65, 82, 65, 66, 73, 67, 95, 89,
- 69, 77, 69, 78, 0, 0, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, 67,
- 95, 79, 77, 65, 78, 0, 83, 85, 66, 76, 65,
- 78, 71, 95, 65, 82, 65, 66, 73, 67, 95, 84,
- 85, 78, 73, 83, 73, 65, 0, 0, 83, 85, 66,
- 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, 67,
- 95, 77, 79, 82, 79, 67, 67, 79, 0, 0, 83,
- 85, 66, 76, 65, 78, 71, 95, 65, 82, 65, 66,
- 73, 67, 95, 65, 76, 71, 69, 82, 73, 65, 0,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 65, 82,
- 65, 66, 73, 67, 95, 76, 73, 66, 89, 65, 0,
- 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 65, 82, 65, 66, 73, 67, 95, 69, 71, 89, 80,
- 84, 0, 0, 0, 0, 83, 85, 66, 76, 65, 78,
- 71, 95, 65, 82, 65, 66, 73, 67, 95, 73, 82,
- 65, 81, 0, 83, 85, 66, 76, 65, 78, 71, 95,
- 65, 82, 65, 66, 73, 67, 95, 83, 65, 85, 68,
- 73, 95, 65, 82, 65, 66, 73, 65, 0, 83, 85,
- 66, 76, 65, 78, 71, 95, 83, 89, 83, 95, 68,
- 69, 70, 65, 85, 76, 84, 0, 83, 85, 66, 76,
- 65, 78, 71, 95, 68, 69, 70, 65, 85, 76, 84,
- 0, 83, 85, 66, 76, 65, 78, 71, 95, 78, 69,
- 85, 84, 82, 65, 76, 0, 76, 65, 78, 71, 95,
- 86, 73, 69, 84, 78, 65, 77, 69, 83, 69, 0,
- 76, 65, 78, 71, 95, 85, 90, 66, 69, 75, 0,
- 0, 76, 65, 78, 71, 95, 85, 82, 68, 85, 0,
- 0, 0, 76, 65, 78, 71, 95, 85, 75, 82, 65,
- 73, 78, 73, 65, 78, 0, 0, 76, 65, 78, 71,
- 95, 84, 85, 82, 75, 73, 83, 72, 0, 0, 0,
- 0, 76, 65, 78, 71, 95, 84, 72, 65, 73, 0,
- 0, 0, 76, 65, 78, 71, 95, 84, 69, 76, 85,
- 71, 85, 0, 76, 65, 78, 71, 95, 84, 65, 84,
- 65, 82, 0, 0, 76, 65, 78, 71, 95, 84, 65,
- 77, 73, 76, 0, 0, 76, 65, 78, 71, 95, 83,
- 89, 82, 73, 65, 67, 0, 76, 65, 78, 71, 95,
- 83, 87, 69, 68, 73, 83, 72, 0, 0, 0, 0,
- 76, 65, 78, 71, 95, 83, 87, 65, 72, 73, 76,
- 73, 0, 0, 0, 0, 76, 65, 78, 71, 95, 83,
- 80, 65, 78, 73, 83, 72, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 83, 76, 79, 86, 69, 78, 73,
- 65, 78, 0, 0, 76, 65, 78, 71, 95, 83, 76,
- 79, 86, 65, 75, 0, 76, 65, 78, 71, 95, 83,
- 73, 78, 68, 72, 73, 0, 76, 65, 78, 71, 95,
- 83, 69, 82, 66, 73, 65, 78, 0, 0, 0, 0,
- 76, 65, 78, 71, 95, 83, 65, 78, 83, 75, 82,
- 73, 84, 0, 0, 0, 76, 65, 78, 71, 95, 82,
- 85, 83, 83, 73, 65, 78, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 82, 79, 77, 65, 78, 73, 65,
- 78, 0, 0, 0, 76, 65, 78, 71, 95, 80, 85,
- 78, 74, 65, 66, 73, 0, 0, 0, 0, 76, 65,
- 78, 71, 95, 80, 79, 82, 84, 85, 71, 85, 69,
- 83, 69, 0, 76, 65, 78, 71, 95, 80, 79, 76,
- 73, 83, 72, 0, 76, 65, 78, 71, 95, 79, 82,
- 73, 89, 65, 0, 0, 76, 65, 78, 71, 95, 78,
- 79, 82, 87, 69, 71, 73, 65, 78, 0, 0, 76,
- 65, 78, 71, 95, 78, 69, 80, 65, 76, 73, 0,
- 76, 65, 78, 71, 95, 77, 79, 78, 71, 79, 76,
- 73, 65, 78, 0, 0, 76, 65, 78, 71, 95, 77,
- 65, 82, 65, 84, 72, 73, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 77, 65, 78, 73, 80, 85, 82,
- 73, 0, 0, 0, 76, 65, 78, 71, 95, 77, 65,
- 76, 65, 89, 65, 76, 65, 77, 0, 0, 76, 65,
- 78, 71, 95, 77, 65, 76, 65, 89, 0, 0, 76,
- 65, 78, 71, 95, 77, 65, 67, 69, 68, 79, 78,
- 73, 65, 78, 0, 76, 65, 78, 71, 95, 76, 73,
- 84, 72, 85, 65, 78, 73, 65, 78, 0, 76, 65,
- 78, 71, 95, 76, 65, 84, 86, 73, 65, 78, 0,
- 0, 0, 0, 76, 65, 78, 71, 95, 75, 89, 82,
- 71, 89, 90, 0, 76, 65, 78, 71, 95, 75, 79,
- 82, 69, 65, 78, 0, 76, 65, 78, 71, 95, 75,
- 79, 78, 75, 65, 78, 73, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 75, 65, 90, 65, 75, 0, 0,
- 76, 65, 78, 71, 95, 75, 65, 83, 72, 77, 73,
- 82, 73, 0, 0, 0, 76, 65, 78, 71, 95, 75,
- 65, 78, 78, 65, 68, 65, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 74, 65, 80, 65, 78, 69, 83,
- 69, 0, 0, 0, 76, 65, 78, 71, 95, 73, 84,
- 65, 76, 73, 65, 78, 0, 0, 0, 0, 76, 65,
- 78, 71, 95, 73, 78, 68, 79, 78, 69, 83, 73,
- 65, 78, 0, 76, 65, 78, 71, 95, 73, 67, 69,
- 76, 65, 78, 68, 73, 67, 0, 0, 76, 65, 78,
- 71, 95, 72, 85, 78, 71, 65, 82, 73, 65, 78,
- 0, 0, 76, 65, 78, 71, 95, 72, 73, 78, 68,
- 73, 0, 0, 76, 65, 78, 71, 95, 72, 69, 66,
- 82, 69, 87, 0, 76, 65, 78, 71, 95, 71, 85,
- 74, 65, 82, 65, 84, 73, 0, 0, 0, 76, 65,
- 78, 71, 95, 71, 82, 69, 69, 75, 0, 0, 76,
- 65, 78, 71, 95, 71, 69, 82, 77, 65, 78, 0,
- 76, 65, 78, 71, 95, 71, 69, 79, 82, 71, 73,
- 65, 78, 0, 0, 0, 76, 65, 78, 71, 95, 71,
- 65, 76, 73, 67, 73, 65, 78, 0, 0, 0, 76,
- 65, 78, 71, 95, 70, 82, 69, 78, 67, 72, 0,
- 76, 65, 78, 71, 95, 70, 73, 78, 78, 73, 83,
- 72, 0, 0, 0, 0, 76, 65, 78, 71, 95, 70,
- 65, 82, 83, 73, 0, 0, 76, 65, 78, 71, 95,
- 70, 65, 69, 82, 79, 69, 83, 69, 0, 0, 0,
- 76, 65, 78, 71, 95, 69, 83, 84, 79, 78, 73,
- 65, 78, 0, 0, 0, 76, 65, 78, 71, 95, 69,
- 78, 71, 76, 73, 83, 72, 0, 0, 0, 0, 76,
- 65, 78, 71, 95, 68, 85, 84, 67, 72, 0, 0,
- 76, 65, 78, 71, 95, 68, 73, 86, 69, 72, 73,
- 0, 76, 65, 78, 71, 95, 68, 65, 78, 73, 83,
- 72, 0, 76, 65, 78, 71, 95, 67, 90, 69, 67,
- 72, 0, 0, 76, 65, 78, 71, 95, 67, 82, 79,
- 65, 84, 73, 65, 78, 0, 0, 0, 76, 65, 78,
- 71, 95, 67, 72, 73, 78, 69, 83, 69, 0, 0,
- 0, 0, 76, 65, 78, 71, 95, 67, 65, 84, 65,
- 76, 65, 78, 0, 0, 0, 0, 76, 65, 78, 71,
- 95, 66, 85, 76, 71, 65, 82, 73, 65, 78, 0,
- 0, 76, 65, 78, 71, 95, 66, 69, 78, 71, 65,
- 76, 73, 0, 0, 0, 0, 76, 65, 78, 71, 95,
- 66, 69, 76, 65, 82, 85, 83, 73, 65, 78, 0,
- 76, 65, 78, 71, 95, 66, 65, 83, 81, 85, 69,
- 0, 76, 65, 78, 71, 95, 65, 90, 69, 82, 73,
- 0, 0, 76, 65, 78, 71, 95, 65, 83, 83, 65,
- 77, 69, 83, 69, 0, 0, 0, 76, 65, 78, 71,
- 95, 65, 82, 77, 69, 78, 73, 65, 78, 0, 0,
- 0, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73,
- 67, 0, 76, 65, 78, 71, 95, 65, 76, 66, 65,
- 78, 73, 65, 78, 0, 0, 0, 76, 65, 78, 71,
- 95, 65, 70, 82, 73, 75, 65, 65, 78, 83, 0,
- 0, 76, 65, 78, 71, 95, 73, 78, 86, 65, 82,
- 73, 65, 78, 84, 0, 0, 76, 65, 78, 71, 95,
- 78, 69, 85, 84, 82, 65, 76, 0, 0, 0, 0,
- 37, 117, 0, 0, 76, 97, 110, 103, 117, 97, 103,
- 101, 32, 73, 68, 58, 32, 37, 100, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 0,
- 0, 32, 0, 0, 128, 24, 0, 0, 0, 56, 0,
- 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 101, 0, 0, 0,
- 80, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
- 0, 0, 104, 0, 0, 128, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 9, 4, 0, 0, 128, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 9, 4, 0, 0, 144, 0, 0, 0, 160,
- 80, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 136, 81, 0, 0, 25, 2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 8,
- 200, 128, 0, 0, 0, 0, 5, 0, 0, 0, 0,
- 0, 135, 0, 75, 0, 0, 0, 0, 0, 77, 0,
- 97, 0, 107, 0, 101, 0, 76, 0, 97, 0, 110,
- 0, 103, 0, 73, 0, 68, 0, 0, 0, 8, 0,
- 77, 0, 83, 0, 32, 0, 83, 0, 97, 0, 110,
- 0, 115, 0, 32, 0, 83, 0, 101, 0, 114, 0,
- 105, 0, 102, 0, 0, 0, 0, 0, 3, 0, 33,
- 80, 0, 0, 0, 0, 7, 0, 7, 0, 121, 0,
- 100, 0, 234, 3, 255, 255, 133, 0, 0, 0, 0,
- 0, 0, 0, 3, 0, 33, 80, 0, 0, 0, 0,
- 7, 0, 24, 0, 121, 0, 100, 0, 233, 3, 255,
- 255, 133, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 1, 80, 0, 0, 0, 0, 78, 0, 54, 0, 50,
- 0, 14, 0, 1, 0, 255, 255, 128, 0, 67, 0,
- 111, 0, 112, 0, 121, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 80, 0, 0, 0, 0, 7, 0,
- 54, 0, 50, 0, 14, 0, 2, 0, 255, 255, 128,
- 0, 69, 0, 120, 0, 105, 0, 116, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 2, 80, 0, 0, 0,
- 0, 7, 0, 41, 0, 121, 0, 8, 0, 235, 3,
- 255, 255, 130, 0, 0, 0, 0, 0, 0, 0, 60,
- 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111,
- 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99,
- 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45,
- 56, 34, 32, 115, 116, 97, 110, 100, 97, 108, 111,
- 110, 101, 61, 34, 121, 101, 115, 34, 63, 62, 13,
- 10, 60, 97, 115, 115, 101, 109, 98, 108, 121, 32,
- 120, 109, 108, 110, 115, 61, 34, 117, 114, 110, 58,
- 115, 99, 104, 101, 109, 97, 115, 45, 109, 105, 99,
- 114, 111, 115, 111, 102, 116, 45, 99, 111, 109, 58,
- 97, 115, 109, 46, 118, 49, 34, 32, 109, 97, 110,
- 105, 102, 101, 115, 116, 86, 101, 114, 115, 105, 111,
- 110, 61, 34, 49, 46, 48, 34, 62, 13, 10, 60,
- 97, 115, 115, 101, 109, 98, 108, 121, 73, 100, 101,
- 110, 116, 105, 116, 121, 32, 118, 101, 114, 115, 105,
- 111, 110, 61, 34, 49, 46, 48, 46, 48, 46, 48,
- 34, 32, 112, 114, 111, 99, 101, 115, 115, 111, 114,
- 65, 114, 99, 104, 105, 116, 101, 99, 116, 117, 114,
- 101, 61, 34, 88, 56, 54, 34, 32, 110, 97, 109,
- 101, 61, 34, 78, 117, 108, 108, 115, 111, 102, 116,
- 46, 78, 83, 73, 83, 46, 77, 97, 107, 101, 76,
- 97, 110, 103, 73, 100, 34, 32, 116, 121, 112, 101,
- 61, 34, 119, 105, 110, 51, 50, 34, 47, 62, 13,
- 10, 60, 100, 101, 115, 99, 114, 105, 112, 116, 105,
- 111, 110, 62, 77, 97, 107, 101, 76, 97, 110, 103,
- 73, 100, 60, 47, 100, 101, 115, 99, 114, 105, 112,
- 116, 105, 111, 110, 62, 13, 10, 60, 100, 101, 112,
- 101, 110, 100, 101, 110, 99, 121, 62, 13, 10, 60,
- 100, 101, 112, 101, 110, 100, 101, 110, 116, 65, 115,
- 115, 101, 109, 98, 108, 121, 62, 13, 10, 60, 97,
- 115, 115, 101, 109, 98, 108, 121, 73, 100, 101, 110,
- 116, 105, 116, 121, 32, 116, 121, 112, 101, 61, 34,
- 119, 105, 110, 51, 50, 34, 32, 110, 97, 109, 101,
- 61, 34, 77, 105, 99, 114, 111, 115, 111, 102, 116,
- 46, 87, 105, 110, 100, 111, 119, 115, 46, 67, 111,
- 109, 109, 111, 110, 45, 67, 111, 110, 116, 114, 111,
- 108, 115, 34, 32, 118, 101, 114, 115, 105, 111, 110,
- 61, 34, 54, 46, 48, 46, 48, 46, 48, 34, 32,
- 112, 114, 111, 99, 101, 115, 115, 111, 114, 65, 114,
- 99, 104, 105, 116, 101, 99, 116, 117, 114, 101, 61,
- 34, 88, 56, 54, 34, 32, 112, 117, 98, 108, 105,
- 99, 75, 101, 121, 84, 111, 107, 101, 110, 61, 34,
- 54, 53, 57, 53, 98, 54, 52, 49, 52, 52, 99,
- 99, 102, 49, 100, 102, 34, 32, 108, 97, 110, 103,
- 117, 97, 103, 101, 61, 34, 42, 34, 32, 47, 62,
- 13, 10, 60, 47, 100, 101, 112, 101, 110, 100, 101,
- 110, 116, 65, 115, 115, 101, 109, 98, 108, 121, 62,
- 13, 10, 60, 47, 100, 101, 112, 101, 110, 100, 101,
- 110, 99, 121, 62, 13, 10, 60, 47, 97, 115, 115,
- 101, 109, 98, 108, 121, 62, 13, 10, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0
-};
+#include <cppunit/extensions/HelperMacros.h> +#include "../ResourceEditor.h" + +#include <stdlib.h> + +class CResourceEditorTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( CResourceEditorTest ); + CPPUNIT_TEST( testCorrectness ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testCorrectness() { + extern unsigned char original_pe[8704]; + + CResourceEditor re(original_pe, sizeof(original_pe)); + + DWORD size; + + // get size + size = re.Save(NULL, size); + unsigned char *saved_pe = new unsigned char[size]; + + // save + int rc = re.Save(saved_pe, size); + CPPUNIT_ASSERT_EQUAL( rc, 0 ); + + // compare + CPPUNIT_ASSERT_EQUAL( (DWORD) sizeof(original_pe), size ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(saved_pe, original_pe, size) ); + + delete [] saved_pe; + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( CResourceEditorTest ); + +unsigned char original_pe[8704] = { + 77, 90, 144, 0, 3, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, + 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 14, + 31, 186, 14, 0, 180, 9, 205, 33, 184, 1, 76, + 205, 33, 84, 104, 105, 115, 32, 112, 114, 111, 103, + 114, 97, 109, 32, 99, 97, 110, 110, 111, 116, 32, + 98, 101, 32, 114, 117, 110, 32, 105, 110, 32, 68, + 79, 83, 32, 109, 111, 100, 101, 46, 13, 13, 10, + 36, 0, 0, 0, 0, 0, 0, 0, 252, 249, 48, + 199, 184, 152, 94, 148, 184, 152, 94, 148, 184, 152, + 94, 148, 184, 152, 95, 148, 168, 152, 94, 148, 59, + 144, 3, 148, 189, 152, 94, 148, 236, 187, 111, 148, + 185, 152, 94, 148, 127, 158, 88, 148, 185, 152, 94, + 148, 82, 105, 99, 104, 184, 152, 94, 148, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 69, 0, 0, 76, 1, 4, 0, + 86, 34, 23, 68, 0, 0, 0, 0, 0, 0, 0, + 0, 224, 0, 15, 1, 11, 1, 6, 0, 0, 4, + 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 126, + 18, 0, 0, 0, 16, 0, 0, 0, 32, 0, 0, + 0, 0, 64, 0, 0, 16, 0, 0, 0, 2, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 16, 0, 0, 16, 0, 0, 0, 0, 16, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 32, 0, 0, 60, 0, 0, 0, 0, 80, 0, 0, + 168, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 116, + 101, 120, 116, 0, 0, 0, 160, 2, 0, 0, 0, + 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 96, 46, 114, 100, 97, 116, 97, + 0, 0, 240, 1, 0, 0, 0, 32, 0, 0, 0, + 2, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, + 64, 46, 100, 97, 116, 97, 0, 0, 0, 100, 18, + 0, 0, 0, 48, 0, 0, 0, 20, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 64, 0, 0, 192, 46, 114, 115, + 114, 99, 0, 0, 0, 168, 3, 0, 0, 0, 80, + 0, 0, 0, 4, 0, 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 139, 68, 36, 8, 129, 236, 12, 2, 0, + 0, 45, 16, 1, 0, 0, 83, 85, 86, 87, 15, + 132, 234, 1, 0, 0, 72, 15, 133, 79, 2, 0, + 0, 139, 132, 36, 40, 2, 0, 0, 102, 61, 2, + 0, 117, 28, 51, 219, 83, 255, 180, 36, 36, 2, + 0, 0, 255, 21, 60, 32, 64, 0, 83, 255, 21, + 56, 32, 64, 0, 233, 38, 2, 0, 0, 139, 200, + 193, 233, 16, 102, 131, 249, 1, 15, 133, 178, 0, + 0, 0, 51, 219, 190, 71, 1, 0, 0, 83, 83, + 189, 234, 3, 0, 0, 86, 85, 255, 180, 36, 48, + 2, 0, 0, 255, 21, 52, 32, 64, 0, 131, 248, + 255, 15, 132, 241, 1, 0, 0, 83, 83, 191, 233, + 3, 0, 0, 86, 87, 255, 180, 36, 48, 2, 0, + 0, 255, 21, 52, 32, 64, 0, 131, 248, 255, 15, + 132, 210, 1, 0, 0, 83, 83, 86, 87, 255, 180, + 36, 48, 2, 0, 0, 139, 61, 52, 32, 64, 0, + 255, 215, 15, 183, 4, 197, 104, 50, 64, 0, 83, + 83, 86, 85, 255, 180, 36, 48, 2, 0, 0, 193, + 224, 10, 137, 68, 36, 36, 255, 215, 15, 183, 4, + 197, 0, 48, 64, 0, 139, 76, 36, 16, 11, 200, + 141, 68, 36, 28, 81, 104, 84, 66, 64, 0, 80, + 255, 21, 48, 32, 64, 0, 131, 196, 12, 141, 68, + 36, 28, 80, 104, 235, 3, 0, 0, 255, 180, 36, + 40, 2, 0, 0, 255, 21, 44, 32, 64, 0, 233, + 101, 1, 0, 0, 102, 61, 1, 0, 15, 133, 91, + 1, 0, 0, 51, 219, 190, 71, 1, 0, 0, 83, + 83, 189, 234, 3, 0, 0, 86, 85, 255, 180, 36, + 48, 2, 0, 0, 255, 21, 52, 32, 64, 0, 131, + 248, 255, 15, 132, 53, 1, 0, 0, 83, 83, 191, + 233, 3, 0, 0, 86, 87, 255, 180, 36, 48, 2, + 0, 0, 255, 21, 52, 32, 64, 0, 131, 248, 255, + 15, 132, 22, 1, 0, 0, 106, 16, 106, 2, 255, + 21, 4, 32, 64, 0, 59, 195, 137, 68, 36, 16, + 15, 132, 0, 1, 0, 0, 80, 255, 21, 0, 32, + 64, 0, 83, 83, 86, 87, 255, 180, 36, 48, 2, + 0, 0, 139, 61, 52, 32, 64, 0, 137, 68, 36, + 44, 255, 215, 15, 183, 4, 197, 104, 50, 64, 0, + 83, 83, 86, 85, 255, 180, 36, 48, 2, 0, 0, + 193, 224, 10, 137, 68, 36, 40, 255, 215, 15, 183, + 4, 197, 0, 48, 64, 0, 139, 76, 36, 20, 11, + 200, 81, 104, 80, 66, 64, 0, 255, 116, 36, 32, + 255, 21, 48, 32, 64, 0, 131, 196, 12, 255, 116, + 36, 16, 255, 21, 16, 32, 64, 0, 255, 180, 36, + 32, 2, 0, 0, 255, 21, 40, 32, 64, 0, 133, + 192, 15, 132, 134, 0, 0, 0, 255, 21, 36, 32, + 64, 0, 255, 116, 36, 16, 106, 1, 255, 21, 32, + 32, 64, 0, 255, 21, 28, 32, 64, 0, 235, 108, + 51, 219, 83, 83, 104, 128, 0, 0, 0, 255, 180, + 36, 44, 2, 0, 0, 255, 21, 24, 32, 64, 0, + 139, 53, 52, 32, 64, 0, 51, 255, 189, 234, 3, + 0, 0, 255, 183, 4, 48, 64, 0, 83, 104, 67, + 1, 0, 0, 85, 255, 180, 36, 48, 2, 0, 0, + 255, 214, 131, 199, 8, 129, 255, 104, 2, 0, 0, + 114, 223, 51, 237, 191, 233, 3, 0, 0, 255, 181, + 108, 50, 64, 0, 83, 104, 67, 1, 0, 0, 87, + 255, 180, 36, 48, 2, 0, 0, 255, 214, 131, 197, + 8, 129, 253, 224, 2, 0, 0, 114, 223, 95, 94, + 93, 51, 192, 91, 129, 196, 12, 2, 0, 0, 194, + 16, 0, 106, 0, 104, 0, 16, 64, 0, 106, 0, + 106, 101, 106, 0, 255, 21, 12, 32, 64, 0, 80, + 255, 21, 64, 32, 64, 0, 106, 0, 255, 21, 8, + 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 220, 32, 0, 0, 234, 32, 0, 0, + 248, 32, 0, 0, 6, 33, 0, 0, 204, 32, 0, + 0, 0, 0, 0, 0, 40, 33, 0, 0, 56, 33, + 0, 0, 74, 33, 0, 0, 94, 33, 0, 0, 112, + 33, 0, 0, 128, 33, 0, 0, 146, 33, 0, 0, + 158, 33, 0, 0, 180, 33, 0, 0, 198, 33, 0, + 0, 210, 33, 0, 0, 0, 0, 0, 0, 132, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, + 33, 0, 0, 0, 32, 0, 0, 156, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 228, 33, 0, + 0, 24, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 220, 32, 0, 0, 234, 32, 0, 0, + 248, 32, 0, 0, 6, 33, 0, 0, 204, 32, 0, + 0, 0, 0, 0, 0, 40, 33, 0, 0, 56, 33, + 0, 0, 74, 33, 0, 0, 94, 33, 0, 0, 112, + 33, 0, 0, 128, 33, 0, 0, 146, 33, 0, 0, + 158, 33, 0, 0, 180, 33, 0, 0, 198, 33, 0, + 0, 210, 33, 0, 0, 0, 0, 0, 0, 0, 2, + 71, 108, 111, 98, 97, 108, 85, 110, 108, 111, 99, + 107, 0, 0, 249, 1, 71, 108, 111, 98, 97, 108, + 76, 111, 99, 107, 0, 0, 238, 1, 71, 108, 111, + 98, 97, 108, 65, 108, 108, 111, 99, 0, 175, 0, + 69, 120, 105, 116, 80, 114, 111, 99, 101, 115, 115, + 0, 119, 1, 71, 101, 116, 77, 111, 100, 117, 108, + 101, 72, 97, 110, 100, 108, 101, 65, 0, 0, 75, + 69, 82, 78, 69, 76, 51, 50, 46, 100, 108, 108, + 0, 0, 58, 2, 83, 101, 110, 100, 77, 101, 115, + 115, 97, 103, 101, 65, 0, 0, 66, 0, 67, 108, + 111, 115, 101, 67, 108, 105, 112, 98, 111, 97, 114, + 100, 0, 0, 73, 2, 83, 101, 116, 67, 108, 105, + 112, 98, 111, 97, 114, 100, 68, 97, 116, 97, 0, + 0, 193, 0, 69, 109, 112, 116, 121, 67, 108, 105, + 112, 98, 111, 97, 114, 100, 0, 0, 245, 1, 79, + 112, 101, 110, 67, 108, 105, 112, 98, 111, 97, 114, + 100, 0, 82, 2, 83, 101, 116, 68, 108, 103, 73, + 116, 101, 109, 84, 101, 120, 116, 65, 0, 213, 2, + 119, 115, 112, 114, 105, 110, 116, 102, 65, 0, 53, + 2, 83, 101, 110, 100, 68, 108, 103, 73, 116, 101, + 109, 77, 101, 115, 115, 97, 103, 101, 65, 0, 3, + 2, 80, 111, 115, 116, 81, 117, 105, 116, 77, 101, + 115, 115, 97, 103, 101, 0, 198, 0, 69, 110, 100, + 68, 105, 97, 108, 111, 103, 0, 158, 0, 68, 105, + 97, 108, 111, 103, 66, 111, 120, 80, 97, 114, 97, + 109, 65, 0, 85, 83, 69, 82, 51, 50, 46, 100, + 108, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 64, 66, 64, 0, 127, 0, 0, 0, 48, + 66, 64, 0, 54, 0, 0, 0, 32, 66, 64, 0, + 28, 0, 0, 0, 16, 66, 64, 0, 1, 0, 0, + 0, 4, 66, 64, 0, 43, 0, 0, 0, 244, 65, + 64, 0, 77, 0, 0, 0, 228, 65, 64, 0, 44, + 0, 0, 0, 216, 65, 64, 0, 45, 0, 0, 0, + 204, 65, 64, 0, 35, 0, 0, 0, 188, 65, 64, + 0, 69, 0, 0, 0, 172, 65, 64, 0, 2, 0, + 0, 0, 156, 65, 64, 0, 3, 0, 0, 0, 140, + 65, 64, 0, 4, 0, 0, 0, 124, 65, 64, 0, + 26, 0, 0, 0, 108, 65, 64, 0, 5, 0, 0, + 0, 96, 65, 64, 0, 6, 0, 0, 0, 84, 65, + 64, 0, 101, 0, 0, 0, 72, 65, 64, 0, 19, + 0, 0, 0, 60, 65, 64, 0, 9, 0, 0, 0, + 44, 65, 64, 0, 37, 0, 0, 0, 28, 65, 64, + 0, 56, 0, 0, 0, 12, 65, 64, 0, 41, 0, + 0, 0, 0, 65, 64, 0, 11, 0, 0, 0, 240, + 64, 64, 0, 12, 0, 0, 0, 228, 64, 64, 0, + 86, 0, 0, 0, 212, 64, 64, 0, 55, 0, 0, + 0, 196, 64, 64, 0, 7, 0, 0, 0, 184, 64, + 64, 0, 8, 0, 0, 0, 172, 64, 64, 0, 71, + 0, 0, 0, 156, 64, 64, 0, 13, 0, 0, 0, + 144, 64, 64, 0, 57, 0, 0, 0, 132, 64, 64, + 0, 14, 0, 0, 0, 116, 64, 64, 0, 15, 0, + 0, 0, 100, 64, 64, 0, 33, 0, 0, 0, 84, + 64, 64, 0, 16, 0, 0, 0, 68, 64, 64, 0, + 17, 0, 0, 0, 52, 64, 64, 0, 75, 0, 0, + 0, 36, 64, 64, 0, 96, 0, 0, 0, 20, 64, + 64, 0, 63, 0, 0, 0, 8, 64, 64, 0, 87, + 0, 0, 0, 248, 63, 64, 0, 18, 0, 0, 0, + 236, 63, 64, 0, 64, 0, 0, 0, 224, 63, 64, + 0, 38, 0, 0, 0, 208, 63, 64, 0, 39, 0, + 0, 0, 192, 63, 64, 0, 47, 0, 0, 0, 176, + 63, 64, 0, 62, 0, 0, 0, 164, 63, 64, 0, + 76, 0, 0, 0, 148, 63, 64, 0, 88, 0, 0, + 0, 132, 63, 64, 0, 78, 0, 0, 0, 116, 63, + 64, 0, 80, 0, 0, 0, 100, 63, 64, 0, 97, + 0, 0, 0, 88, 63, 64, 0, 20, 0, 0, 0, + 72, 63, 64, 0, 72, 0, 0, 0, 60, 63, 64, + 0, 21, 0, 0, 0, 48, 63, 64, 0, 22, 0, + 0, 0, 32, 63, 64, 0, 70, 0, 0, 0, 16, + 63, 64, 0, 24, 0, 0, 0, 0, 63, 64, 0, + 25, 0, 0, 0, 240, 62, 64, 0, 79, 0, 0, + 0, 224, 62, 64, 0, 26, 0, 0, 0, 208, 62, + 64, 0, 89, 0, 0, 0, 196, 62, 64, 0, 27, + 0, 0, 0, 184, 62, 64, 0, 36, 0, 0, 0, + 168, 62, 64, 0, 10, 0, 0, 0, 152, 62, 64, + 0, 65, 0, 0, 0, 136, 62, 64, 0, 29, 0, + 0, 0, 120, 62, 64, 0, 90, 0, 0, 0, 108, + 62, 64, 0, 73, 0, 0, 0, 96, 62, 64, 0, + 68, 0, 0, 0, 84, 62, 64, 0, 74, 0, 0, + 0, 72, 62, 64, 0, 30, 0, 0, 0, 60, 62, + 64, 0, 31, 0, 0, 0, 44, 62, 64, 0, 34, + 0, 0, 0, 28, 62, 64, 0, 32, 0, 0, 0, + 16, 62, 64, 0, 67, 0, 0, 0, 4, 62, 64, + 0, 42, 0, 0, 0, 244, 61, 64, 0, 0, 0, + 0, 0, 228, 61, 64, 0, 1, 0, 0, 0, 212, + 61, 64, 0, 2, 0, 0, 0, 192, 61, 64, 0, + 1, 0, 0, 0, 164, 61, 64, 0, 2, 0, 0, + 0, 144, 61, 64, 0, 3, 0, 0, 0, 120, 61, + 64, 0, 4, 0, 0, 0, 96, 61, 64, 0, 5, + 0, 0, 0, 72, 61, 64, 0, 6, 0, 0, 0, + 48, 61, 64, 0, 7, 0, 0, 0, 24, 61, 64, + 0, 8, 0, 0, 0, 4, 61, 64, 0, 9, 0, + 0, 0, 236, 60, 64, 0, 10, 0, 0, 0, 212, + 60, 64, 0, 11, 0, 0, 0, 188, 60, 64, 0, + 12, 0, 0, 0, 164, 60, 64, 0, 13, 0, 0, + 0, 140, 60, 64, 0, 14, 0, 0, 0, 120, 60, + 64, 0, 15, 0, 0, 0, 96, 60, 64, 0, 16, + 0, 0, 0, 72, 60, 64, 0, 1, 0, 0, 0, + 52, 60, 64, 0, 2, 0, 0, 0, 28, 60, 64, + 0, 1, 0, 0, 0, 0, 60, 64, 0, 2, 0, + 0, 0, 228, 59, 64, 0, 3, 0, 0, 0, 200, + 59, 64, 0, 4, 0, 0, 0, 172, 59, 64, 0, + 5, 0, 0, 0, 148, 59, 64, 0, 1, 0, 0, + 0, 132, 59, 64, 0, 2, 0, 0, 0, 108, 59, + 64, 0, 1, 0, 0, 0, 88, 59, 64, 0, 2, + 0, 0, 0, 68, 59, 64, 0, 3, 0, 0, 0, + 48, 59, 64, 0, 4, 0, 0, 0, 28, 59, 64, + 0, 5, 0, 0, 0, 8, 59, 64, 0, 6, 0, + 0, 0, 240, 58, 64, 0, 7, 0, 0, 0, 208, + 58, 64, 0, 8, 0, 0, 0, 184, 58, 64, 0, + 9, 0, 0, 0, 156, 58, 64, 0, 10, 0, 0, + 0, 132, 58, 64, 0, 11, 0, 0, 0, 104, 58, + 64, 0, 12, 0, 0, 0, 76, 58, 64, 0, 13, + 0, 0, 0, 48, 58, 64, 0, 1, 0, 0, 0, + 32, 58, 64, 0, 2, 0, 0, 0, 8, 58, 64, + 0, 3, 0, 0, 0, 240, 57, 64, 0, 4, 0, + 0, 0, 216, 57, 64, 0, 5, 0, 0, 0, 188, + 57, 64, 0, 6, 0, 0, 0, 164, 57, 64, 0, + 1, 0, 0, 0, 148, 57, 64, 0, 2, 0, 0, + 0, 124, 57, 64, 0, 3, 0, 0, 0, 100, 57, + 64, 0, 4, 0, 0, 0, 72, 57, 64, 0, 5, + 0, 0, 0, 40, 57, 64, 0, 1, 0, 0, 0, + 24, 57, 64, 0, 2, 0, 0, 0, 0, 57, 64, + 0, 2, 0, 0, 0, 232, 56, 64, 0, 1, 0, + 0, 0, 216, 56, 64, 0, 1, 0, 0, 0, 196, + 56, 64, 0, 1, 0, 0, 0, 172, 56, 64, 0, + 2, 0, 0, 0, 140, 56, 64, 0, 2, 0, 0, + 0, 116, 56, 64, 0, 1, 0, 0, 0, 88, 56, + 64, 0, 2, 0, 0, 0, 60, 56, 64, 0, 2, + 0, 0, 0, 40, 56, 64, 0, 1, 0, 0, 0, + 8, 56, 64, 0, 2, 0, 0, 0, 240, 55, 64, + 0, 3, 0, 0, 0, 212, 55, 64, 0, 1, 0, + 0, 0, 196, 55, 64, 0, 2, 0, 0, 0, 172, + 55, 64, 0, 3, 0, 0, 0, 148, 55, 64, 0, + 4, 0, 0, 0, 120, 55, 64, 0, 5, 0, 0, + 0, 92, 55, 64, 0, 6, 0, 0, 0, 68, 55, + 64, 0, 7, 0, 0, 0, 32, 55, 64, 0, 8, + 0, 0, 0, 4, 55, 64, 0, 9, 0, 0, 0, + 232, 54, 64, 0, 10, 0, 0, 0, 208, 54, 64, + 0, 11, 0, 0, 0, 180, 54, 64, 0, 12, 0, + 0, 0, 156, 54, 64, 0, 13, 0, 0, 0, 132, + 54, 64, 0, 14, 0, 0, 0, 108, 54, 64, 0, + 15, 0, 0, 0, 80, 54, 64, 0, 16, 0, 0, + 0, 56, 54, 64, 0, 17, 0, 0, 0, 28, 54, + 64, 0, 18, 0, 0, 0, 0, 54, 64, 0, 19, + 0, 0, 0, 228, 53, 64, 0, 20, 0, 0, 0, + 200, 53, 64, 0, 1, 0, 0, 0, 184, 53, 64, + 0, 2, 0, 0, 0, 160, 53, 64, 0, 1, 0, + 0, 0, 136, 53, 64, 0, 2, 0, 0, 0, 116, + 53, 64, 0, 1, 0, 0, 0, 96, 53, 64, 0, + 2, 0, 0, 0, 72, 53, 64, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 85, 90, 66, 69, 75, 95, + 67, 89, 82, 73, 76, 76, 73, 67, 0, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 85, 90, 66, 69, + 75, 95, 76, 65, 84, 73, 78, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 85, 82, 68, 85, 95, 73, + 78, 68, 73, 65, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 85, 82, 68, 85, 95, 80, 65, 75, + 73, 83, 84, 65, 78, 0, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 83, 87, 69, 68, 73, 83, + 72, 95, 70, 73, 78, 76, 65, 78, 68, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 83, 87, 69, 68, + 73, 83, 72, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 83, 80, 65, 78, 73, 83, 72, 95, 80, 85, + 69, 82, 84, 79, 95, 82, 73, 67, 79, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 83, 80, 65, 78, + 73, 83, 72, 95, 78, 73, 67, 65, 82, 65, 71, + 85, 65, 0, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, 72, + 79, 78, 68, 85, 82, 65, 83, 0, 0, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 83, 80, 65, + 78, 73, 83, 72, 95, 69, 76, 95, 83, 65, 76, + 86, 65, 68, 79, 82, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, + 66, 79, 76, 73, 86, 73, 65, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, + 72, 95, 80, 65, 82, 65, 71, 85, 65, 89, 0, + 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 83, 80, 65, 78, 73, 83, 72, 95, 85, 82, 85, + 71, 85, 65, 89, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, 67, + 72, 73, 76, 69, 0, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, + 95, 69, 67, 85, 65, 68, 79, 82, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 83, 80, 65, 78, 73, + 83, 72, 95, 65, 82, 71, 69, 78, 84, 73, 78, + 65, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 83, 80, 65, 78, 73, 83, 72, 95, 80, 69, + 82, 85, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 95, + 67, 79, 76, 79, 77, 66, 73, 65, 0, 0, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 83, 80, + 65, 78, 73, 83, 72, 95, 86, 69, 78, 69, 90, + 85, 69, 76, 65, 0, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, + 95, 68, 79, 77, 73, 78, 73, 67, 65, 78, 95, + 82, 69, 80, 85, 66, 76, 73, 67, 0, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 83, 80, 65, 78, + 73, 83, 72, 95, 80, 65, 78, 65, 77, 65, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 83, 80, + 65, 78, 73, 83, 72, 95, 67, 79, 83, 84, 65, + 95, 82, 73, 67, 65, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, + 95, 71, 85, 65, 84, 69, 77, 65, 76, 65, 0, + 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 83, + 80, 65, 78, 73, 83, 72, 95, 77, 79, 68, 69, + 82, 78, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 83, 80, 65, 78, 73, 83, 72, 95, 77, 69, + 88, 73, 67, 65, 78, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 83, 80, 65, 78, 73, 83, 72, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 83, 69, 82, + 66, 73, 65, 78, 95, 67, 89, 82, 73, 76, 76, + 73, 67, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 83, 69, 82, 66, 73, 65, 78, 95, + 76, 65, 84, 73, 78, 0, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 80, 79, 82, 84, 85, 71, + 85, 69, 83, 69, 95, 66, 82, 65, 90, 73, 76, + 73, 65, 78, 0, 0, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 80, 79, 82, 84, 85, 71, 85, + 69, 83, 69, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 78, 79, 82, 87, 69, 71, 73, 65, 78, + 95, 78, 89, 78, 79, 82, 83, 75, 0, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 78, 79, 82, + 87, 69, 71, 73, 65, 78, 95, 66, 79, 75, 77, + 65, 76, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 78, 69, 80, 65, 76, 73, 95, 73, + 78, 68, 73, 65, 0, 0, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 77, 65, 76, 65, 89, 95, + 66, 82, 85, 78, 69, 73, 95, 68, 65, 82, 85, + 83, 83, 65, 76, 65, 77, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 77, 65, 76, 65, 89, 95, 77, + 65, 76, 65, 89, 83, 73, 65, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 76, 73, 84, 72, 85, + 65, 78, 73, 65, 78, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 75, 79, 82, 69, 65, 78, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 75, 65, + 83, 72, 77, 73, 82, 73, 95, 73, 78, 68, 73, + 65, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 73, 84, 65, 76, 73, 65, 78, 95, 83, 87, 73, + 83, 83, 0, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 73, 84, 65, 76, 73, 65, 78, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 71, 69, 82, 77, + 65, 78, 95, 76, 73, 69, 67, 72, 84, 69, 78, + 83, 84, 69, 73, 78, 0, 0, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 71, 69, 82, 77, 65, + 78, 95, 76, 85, 88, 69, 77, 66, 79, 85, 82, + 71, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 71, 69, 82, 77, 65, 78, 95, 65, 85, 83, + 84, 82, 73, 65, 78, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 71, 69, 82, 77, 65, 78, 95, 83, + 87, 73, 83, 83, 0, 0, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 71, 69, 82, 77, 65, 78, + 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 70, + 82, 69, 78, 67, 72, 95, 77, 79, 78, 65, 67, + 79, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 70, 82, 69, 78, 67, 72, 95, 76, 85, 88, + 69, 77, 66, 79, 85, 82, 71, 0, 0, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 70, 82, 69, 78, + 67, 72, 95, 83, 87, 73, 83, 83, 0, 0, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 70, 82, + 69, 78, 67, 72, 95, 67, 65, 78, 65, 68, 73, + 65, 78, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 70, 82, 69, 78, 67, 72, 95, 66, 69, 76, 71, + 73, 65, 78, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 70, 82, 69, 78, 67, 72, 0, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 69, 78, 71, 76, + 73, 83, 72, 95, 80, 72, 73, 76, 73, 80, 80, + 73, 78, 69, 83, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, 90, + 73, 77, 66, 65, 66, 87, 69, 0, 0, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 69, 78, 71, + 76, 73, 83, 72, 95, 84, 82, 73, 78, 73, 68, + 65, 68, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, + 66, 69, 76, 73, 90, 69, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 69, 78, 71, 76, 73, 83, + 72, 95, 67, 65, 82, 73, 66, 66, 69, 65, 78, + 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 69, 78, 71, 76, 73, 83, 72, 95, 74, 65, 77, + 65, 73, 67, 65, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, 83, + 79, 85, 84, 72, 95, 65, 70, 82, 73, 67, 65, + 0, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 69, 78, 71, 76, 73, 83, 72, 95, 69, 73, + 82, 69, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 69, 78, 71, 76, 73, 83, 72, 95, + 78, 90, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 69, 78, 71, 76, 73, 83, 72, 95, 67, 65, + 78, 0, 83, 85, 66, 76, 65, 78, 71, 95, 69, + 78, 71, 76, 73, 83, 72, 95, 65, 85, 83, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 69, 78, 71, + 76, 73, 83, 72, 95, 85, 75, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 69, 78, 71, 76, 73, + 83, 72, 95, 85, 83, 0, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 68, 85, 84, 67, 72, 95, 66, + 69, 76, 71, 73, 65, 78, 0, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 68, 85, 84, 67, 72, + 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 67, 72, 73, 78, 69, 83, 69, 95, 77, 65, 67, + 65, 85, 0, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 67, 72, 73, 78, 69, 83, 69, 95, 83, + 73, 78, 71, 65, 80, 79, 82, 69, 0, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 67, 72, 73, + 78, 69, 83, 69, 95, 72, 79, 78, 71, 75, 79, + 78, 71, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 67, 72, 73, 78, 69, 83, 69, 95, + 83, 73, 77, 80, 76, 73, 70, 73, 69, 68, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 67, 72, + 73, 78, 69, 83, 69, 95, 84, 82, 65, 68, 73, + 84, 73, 79, 78, 65, 76, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 65, 90, 69, 82, 73, 95, 67, + 89, 82, 73, 76, 76, 73, 67, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 65, 90, 69, 82, 73, + 95, 76, 65, 84, 73, 78, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 65, 82, 65, 66, 73, 67, 95, + 81, 65, 84, 65, 82, 0, 0, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, + 67, 95, 66, 65, 72, 82, 65, 73, 78, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 65, 82, 65, + 66, 73, 67, 95, 85, 65, 69, 0, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, + 67, 95, 75, 85, 87, 65, 73, 84, 0, 0, 0, + 83, 85, 66, 76, 65, 78, 71, 95, 65, 82, 65, + 66, 73, 67, 95, 76, 69, 66, 65, 78, 79, 78, + 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, 65, + 82, 65, 66, 73, 67, 95, 74, 79, 82, 68, 65, + 78, 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, + 95, 65, 82, 65, 66, 73, 67, 95, 83, 89, 82, + 73, 65, 0, 0, 0, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 65, 82, 65, 66, 73, 67, 95, 89, + 69, 77, 69, 78, 0, 0, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, 67, + 95, 79, 77, 65, 78, 0, 83, 85, 66, 76, 65, + 78, 71, 95, 65, 82, 65, 66, 73, 67, 95, 84, + 85, 78, 73, 83, 73, 65, 0, 0, 83, 85, 66, + 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, 67, + 95, 77, 79, 82, 79, 67, 67, 79, 0, 0, 83, + 85, 66, 76, 65, 78, 71, 95, 65, 82, 65, 66, + 73, 67, 95, 65, 76, 71, 69, 82, 73, 65, 0, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 65, 82, + 65, 66, 73, 67, 95, 76, 73, 66, 89, 65, 0, + 0, 0, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 65, 82, 65, 66, 73, 67, 95, 69, 71, 89, 80, + 84, 0, 0, 0, 0, 83, 85, 66, 76, 65, 78, + 71, 95, 65, 82, 65, 66, 73, 67, 95, 73, 82, + 65, 81, 0, 83, 85, 66, 76, 65, 78, 71, 95, + 65, 82, 65, 66, 73, 67, 95, 83, 65, 85, 68, + 73, 95, 65, 82, 65, 66, 73, 65, 0, 83, 85, + 66, 76, 65, 78, 71, 95, 83, 89, 83, 95, 68, + 69, 70, 65, 85, 76, 84, 0, 83, 85, 66, 76, + 65, 78, 71, 95, 68, 69, 70, 65, 85, 76, 84, + 0, 83, 85, 66, 76, 65, 78, 71, 95, 78, 69, + 85, 84, 82, 65, 76, 0, 76, 65, 78, 71, 95, + 86, 73, 69, 84, 78, 65, 77, 69, 83, 69, 0, + 76, 65, 78, 71, 95, 85, 90, 66, 69, 75, 0, + 0, 76, 65, 78, 71, 95, 85, 82, 68, 85, 0, + 0, 0, 76, 65, 78, 71, 95, 85, 75, 82, 65, + 73, 78, 73, 65, 78, 0, 0, 76, 65, 78, 71, + 95, 84, 85, 82, 75, 73, 83, 72, 0, 0, 0, + 0, 76, 65, 78, 71, 95, 84, 72, 65, 73, 0, + 0, 0, 76, 65, 78, 71, 95, 84, 69, 76, 85, + 71, 85, 0, 76, 65, 78, 71, 95, 84, 65, 84, + 65, 82, 0, 0, 76, 65, 78, 71, 95, 84, 65, + 77, 73, 76, 0, 0, 76, 65, 78, 71, 95, 83, + 89, 82, 73, 65, 67, 0, 76, 65, 78, 71, 95, + 83, 87, 69, 68, 73, 83, 72, 0, 0, 0, 0, + 76, 65, 78, 71, 95, 83, 87, 65, 72, 73, 76, + 73, 0, 0, 0, 0, 76, 65, 78, 71, 95, 83, + 80, 65, 78, 73, 83, 72, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 83, 76, 79, 86, 69, 78, 73, + 65, 78, 0, 0, 76, 65, 78, 71, 95, 83, 76, + 79, 86, 65, 75, 0, 76, 65, 78, 71, 95, 83, + 73, 78, 68, 72, 73, 0, 76, 65, 78, 71, 95, + 83, 69, 82, 66, 73, 65, 78, 0, 0, 0, 0, + 76, 65, 78, 71, 95, 83, 65, 78, 83, 75, 82, + 73, 84, 0, 0, 0, 76, 65, 78, 71, 95, 82, + 85, 83, 83, 73, 65, 78, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 82, 79, 77, 65, 78, 73, 65, + 78, 0, 0, 0, 76, 65, 78, 71, 95, 80, 85, + 78, 74, 65, 66, 73, 0, 0, 0, 0, 76, 65, + 78, 71, 95, 80, 79, 82, 84, 85, 71, 85, 69, + 83, 69, 0, 76, 65, 78, 71, 95, 80, 79, 76, + 73, 83, 72, 0, 76, 65, 78, 71, 95, 79, 82, + 73, 89, 65, 0, 0, 76, 65, 78, 71, 95, 78, + 79, 82, 87, 69, 71, 73, 65, 78, 0, 0, 76, + 65, 78, 71, 95, 78, 69, 80, 65, 76, 73, 0, + 76, 65, 78, 71, 95, 77, 79, 78, 71, 79, 76, + 73, 65, 78, 0, 0, 76, 65, 78, 71, 95, 77, + 65, 82, 65, 84, 72, 73, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 77, 65, 78, 73, 80, 85, 82, + 73, 0, 0, 0, 76, 65, 78, 71, 95, 77, 65, + 76, 65, 89, 65, 76, 65, 77, 0, 0, 76, 65, + 78, 71, 95, 77, 65, 76, 65, 89, 0, 0, 76, + 65, 78, 71, 95, 77, 65, 67, 69, 68, 79, 78, + 73, 65, 78, 0, 76, 65, 78, 71, 95, 76, 73, + 84, 72, 85, 65, 78, 73, 65, 78, 0, 76, 65, + 78, 71, 95, 76, 65, 84, 86, 73, 65, 78, 0, + 0, 0, 0, 76, 65, 78, 71, 95, 75, 89, 82, + 71, 89, 90, 0, 76, 65, 78, 71, 95, 75, 79, + 82, 69, 65, 78, 0, 76, 65, 78, 71, 95, 75, + 79, 78, 75, 65, 78, 73, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 75, 65, 90, 65, 75, 0, 0, + 76, 65, 78, 71, 95, 75, 65, 83, 72, 77, 73, + 82, 73, 0, 0, 0, 76, 65, 78, 71, 95, 75, + 65, 78, 78, 65, 68, 65, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 74, 65, 80, 65, 78, 69, 83, + 69, 0, 0, 0, 76, 65, 78, 71, 95, 73, 84, + 65, 76, 73, 65, 78, 0, 0, 0, 0, 76, 65, + 78, 71, 95, 73, 78, 68, 79, 78, 69, 83, 73, + 65, 78, 0, 76, 65, 78, 71, 95, 73, 67, 69, + 76, 65, 78, 68, 73, 67, 0, 0, 76, 65, 78, + 71, 95, 72, 85, 78, 71, 65, 82, 73, 65, 78, + 0, 0, 76, 65, 78, 71, 95, 72, 73, 78, 68, + 73, 0, 0, 76, 65, 78, 71, 95, 72, 69, 66, + 82, 69, 87, 0, 76, 65, 78, 71, 95, 71, 85, + 74, 65, 82, 65, 84, 73, 0, 0, 0, 76, 65, + 78, 71, 95, 71, 82, 69, 69, 75, 0, 0, 76, + 65, 78, 71, 95, 71, 69, 82, 77, 65, 78, 0, + 76, 65, 78, 71, 95, 71, 69, 79, 82, 71, 73, + 65, 78, 0, 0, 0, 76, 65, 78, 71, 95, 71, + 65, 76, 73, 67, 73, 65, 78, 0, 0, 0, 76, + 65, 78, 71, 95, 70, 82, 69, 78, 67, 72, 0, + 76, 65, 78, 71, 95, 70, 73, 78, 78, 73, 83, + 72, 0, 0, 0, 0, 76, 65, 78, 71, 95, 70, + 65, 82, 83, 73, 0, 0, 76, 65, 78, 71, 95, + 70, 65, 69, 82, 79, 69, 83, 69, 0, 0, 0, + 76, 65, 78, 71, 95, 69, 83, 84, 79, 78, 73, + 65, 78, 0, 0, 0, 76, 65, 78, 71, 95, 69, + 78, 71, 76, 73, 83, 72, 0, 0, 0, 0, 76, + 65, 78, 71, 95, 68, 85, 84, 67, 72, 0, 0, + 76, 65, 78, 71, 95, 68, 73, 86, 69, 72, 73, + 0, 76, 65, 78, 71, 95, 68, 65, 78, 73, 83, + 72, 0, 76, 65, 78, 71, 95, 67, 90, 69, 67, + 72, 0, 0, 76, 65, 78, 71, 95, 67, 82, 79, + 65, 84, 73, 65, 78, 0, 0, 0, 76, 65, 78, + 71, 95, 67, 72, 73, 78, 69, 83, 69, 0, 0, + 0, 0, 76, 65, 78, 71, 95, 67, 65, 84, 65, + 76, 65, 78, 0, 0, 0, 0, 76, 65, 78, 71, + 95, 66, 85, 76, 71, 65, 82, 73, 65, 78, 0, + 0, 76, 65, 78, 71, 95, 66, 69, 78, 71, 65, + 76, 73, 0, 0, 0, 0, 76, 65, 78, 71, 95, + 66, 69, 76, 65, 82, 85, 83, 73, 65, 78, 0, + 76, 65, 78, 71, 95, 66, 65, 83, 81, 85, 69, + 0, 76, 65, 78, 71, 95, 65, 90, 69, 82, 73, + 0, 0, 76, 65, 78, 71, 95, 65, 83, 83, 65, + 77, 69, 83, 69, 0, 0, 0, 76, 65, 78, 71, + 95, 65, 82, 77, 69, 78, 73, 65, 78, 0, 0, + 0, 76, 65, 78, 71, 95, 65, 82, 65, 66, 73, + 67, 0, 76, 65, 78, 71, 95, 65, 76, 66, 65, + 78, 73, 65, 78, 0, 0, 0, 76, 65, 78, 71, + 95, 65, 70, 82, 73, 75, 65, 65, 78, 83, 0, + 0, 76, 65, 78, 71, 95, 73, 78, 86, 65, 82, + 73, 65, 78, 84, 0, 0, 76, 65, 78, 71, 95, + 78, 69, 85, 84, 82, 65, 76, 0, 0, 0, 0, + 37, 117, 0, 0, 76, 97, 110, 103, 117, 97, 103, + 101, 32, 73, 68, 58, 32, 37, 100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 5, 0, 0, + 0, 32, 0, 0, 128, 24, 0, 0, 0, 56, 0, + 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 101, 0, 0, 0, + 80, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 104, 0, 0, 128, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 9, 4, 0, 0, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 9, 4, 0, 0, 144, 0, 0, 0, 160, + 80, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 81, 0, 0, 25, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 8, + 200, 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 135, 0, 75, 0, 0, 0, 0, 0, 77, 0, + 97, 0, 107, 0, 101, 0, 76, 0, 97, 0, 110, + 0, 103, 0, 73, 0, 68, 0, 0, 0, 8, 0, + 77, 0, 83, 0, 32, 0, 83, 0, 97, 0, 110, + 0, 115, 0, 32, 0, 83, 0, 101, 0, 114, 0, + 105, 0, 102, 0, 0, 0, 0, 0, 3, 0, 33, + 80, 0, 0, 0, 0, 7, 0, 7, 0, 121, 0, + 100, 0, 234, 3, 255, 255, 133, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 33, 80, 0, 0, 0, 0, + 7, 0, 24, 0, 121, 0, 100, 0, 233, 3, 255, + 255, 133, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 80, 0, 0, 0, 0, 78, 0, 54, 0, 50, + 0, 14, 0, 1, 0, 255, 255, 128, 0, 67, 0, + 111, 0, 112, 0, 121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 80, 0, 0, 0, 0, 7, 0, + 54, 0, 50, 0, 14, 0, 2, 0, 255, 255, 128, + 0, 69, 0, 120, 0, 105, 0, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 80, 0, 0, 0, + 0, 7, 0, 41, 0, 121, 0, 8, 0, 235, 3, + 255, 255, 130, 0, 0, 0, 0, 0, 0, 0, 60, + 63, 120, 109, 108, 32, 118, 101, 114, 115, 105, 111, + 110, 61, 34, 49, 46, 48, 34, 32, 101, 110, 99, + 111, 100, 105, 110, 103, 61, 34, 85, 84, 70, 45, + 56, 34, 32, 115, 116, 97, 110, 100, 97, 108, 111, + 110, 101, 61, 34, 121, 101, 115, 34, 63, 62, 13, + 10, 60, 97, 115, 115, 101, 109, 98, 108, 121, 32, + 120, 109, 108, 110, 115, 61, 34, 117, 114, 110, 58, + 115, 99, 104, 101, 109, 97, 115, 45, 109, 105, 99, + 114, 111, 115, 111, 102, 116, 45, 99, 111, 109, 58, + 97, 115, 109, 46, 118, 49, 34, 32, 109, 97, 110, + 105, 102, 101, 115, 116, 86, 101, 114, 115, 105, 111, + 110, 61, 34, 49, 46, 48, 34, 62, 13, 10, 60, + 97, 115, 115, 101, 109, 98, 108, 121, 73, 100, 101, + 110, 116, 105, 116, 121, 32, 118, 101, 114, 115, 105, + 111, 110, 61, 34, 49, 46, 48, 46, 48, 46, 48, + 34, 32, 112, 114, 111, 99, 101, 115, 115, 111, 114, + 65, 114, 99, 104, 105, 116, 101, 99, 116, 117, 114, + 101, 61, 34, 88, 56, 54, 34, 32, 110, 97, 109, + 101, 61, 34, 78, 117, 108, 108, 115, 111, 102, 116, + 46, 78, 83, 73, 83, 46, 77, 97, 107, 101, 76, + 97, 110, 103, 73, 100, 34, 32, 116, 121, 112, 101, + 61, 34, 119, 105, 110, 51, 50, 34, 47, 62, 13, + 10, 60, 100, 101, 115, 99, 114, 105, 112, 116, 105, + 111, 110, 62, 77, 97, 107, 101, 76, 97, 110, 103, + 73, 100, 60, 47, 100, 101, 115, 99, 114, 105, 112, + 116, 105, 111, 110, 62, 13, 10, 60, 100, 101, 112, + 101, 110, 100, 101, 110, 99, 121, 62, 13, 10, 60, + 100, 101, 112, 101, 110, 100, 101, 110, 116, 65, 115, + 115, 101, 109, 98, 108, 121, 62, 13, 10, 60, 97, + 115, 115, 101, 109, 98, 108, 121, 73, 100, 101, 110, + 116, 105, 116, 121, 32, 116, 121, 112, 101, 61, 34, + 119, 105, 110, 51, 50, 34, 32, 110, 97, 109, 101, + 61, 34, 77, 105, 99, 114, 111, 115, 111, 102, 116, + 46, 87, 105, 110, 100, 111, 119, 115, 46, 67, 111, + 109, 109, 111, 110, 45, 67, 111, 110, 116, 114, 111, + 108, 115, 34, 32, 118, 101, 114, 115, 105, 111, 110, + 61, 34, 54, 46, 48, 46, 48, 46, 48, 34, 32, + 112, 114, 111, 99, 101, 115, 115, 111, 114, 65, 114, + 99, 104, 105, 116, 101, 99, 116, 117, 114, 101, 61, + 34, 88, 56, 54, 34, 32, 112, 117, 98, 108, 105, + 99, 75, 101, 121, 84, 111, 107, 101, 110, 61, 34, + 54, 53, 57, 53, 98, 54, 52, 49, 52, 52, 99, + 99, 102, 49, 100, 102, 34, 32, 108, 97, 110, 103, + 117, 97, 103, 101, 61, 34, 42, 34, 32, 47, 62, + 13, 10, 60, 47, 100, 101, 112, 101, 110, 100, 101, + 110, 116, 65, 115, 115, 101, 109, 98, 108, 121, 62, + 13, 10, 60, 47, 100, 101, 112, 101, 110, 100, 101, + 110, 99, 121, 62, 13, 10, 60, 47, 97, 115, 115, + 101, 109, 98, 108, 121, 62, 13, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/Source/Tests/SConscript b/Source/Tests/SConscript index 49cdc41..b6c510b 100755 --- a/Source/Tests/SConscript +++ b/Source/Tests/SConscript @@ -1,161 +1,161 @@ -target = 'test'
-
-tests = Split("""
- compression.cpp
- decompress.cpp
- DialogTemplate.cpp
- endian.cpp
- mmap.cpp
- ResourceEditor.cpp
- specmatch.cpp
- textrunner.cpp
- winchar.cpp
-""")
-
-required = Split("""
- DialogTemplate.cpp
- dirreader.cpp
- growbuf.cpp
- mmap.cpp
- ResourceEditor.cpp
- util.cpp
- winchar.cpp
-""")
-
-required_exehead = Split("""
- Tests/memcpy.c
-""")
-
-lzma_files = Split("""
- clzma.cpp
- 7zip/7zGuids.cpp
- 7zip/7zip/Common/OutBuffer.cpp
- 7zip/7zip/Common/StreamUtils.cpp
- 7zip/7zip/Compress/LZ/LZInWindow.cpp
- 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp
- 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp
- 7zip/Common/Alloc.cpp
- 7zip/Common/CRC.cpp
- 7zip/LZMADecode.c
-""")
-
-required += lzma_files
-
-bzip2_files = Split("""
- bzip2/blocksort.c
- bzip2/bzlib.c
- bzip2/compress.c
- bzip2/huffman.c
-""")
-
-bzip2_exehead_files = Split("""
- bzip2/bzlib.c
- bzip2/decompress.c
-""")
-
-required += bzip2_files
-required_exehead += bzip2_exehead_files
-
-zlib_files = Split("""
- zlib/deflate.c
- zlib/trees.c
-""")
-
-zlib_exehead_files = Split("""
- zlib/INFBLOCK.C
-""")
-
-required += zlib_files
-required_exehead += zlib_exehead_files
-
-cppunitlibs = Split("""
- cppunit
-""")
-
-extralibs = Split("""
- dl
- gdi32
- iconv
- pthread
- user32
-""")
-
-scripts = Split("""
- preprocessor.nsi
-""")
-
-Import('env AddAvailableLibs')
-
-# Test scripts
-env.TestScript(scripts)
-
-# Use available libraries
-if env['PLATFORM'] == 'win32':
- # XXX will cause problems if tests are cross compiled
- # on freebsd, libversion.a exists and gives trouble if linked
- extralibs += ['version']
-
-AddAvailableLibs(env, extralibs)
-
-# compile using msvcrt (that's how cppunit.lib is built)
-if 'msvc' in env['TOOLS'] or 'mstoolkit' in env['TOOLS']:
- env.Append(CCFLAGS = ['/MD'])
-
-# uses exceptions
-env.Append(CCFLAGS = ['$EXCEPTION_FLAG'])
-
-# for lzma
-env.Append(CPPDEFINES = ['COMPRESS_MF_BT'])
-
-# test for CppUnit
-conf = env.Configure()
-cppunit = conf.CheckLibWithHeader(cppunitlibs, 'cppunit/extensions/HelperMacros.h', 'C++')
-conf.Finish()
-
-if cppunit:
-
- # compile files from parent directory
- required_obj = []
-
- for i in required:
- b = 'required/%s' % i.split('.')[0]
- s = '#Source/%s' % i
- o = env.Object(b, s)
-
- required_obj.append(o)
-
- # exehead files special treatment
- exehead_env = env.Clone()
- exehead_env.Append(CCFLAGS = ['$C_FLAG'])
- exehead_env.Append(
- CPPDEFINES = [
- 'EXEHEAD',
- 'NSIS_COMPRESS_USE_ZLIB' # just so config.h won't complain
- ]
- )
-
- for i in required_exehead:
- b = 'required/exehead/%s' % i.split('.')[0]
- s = '#Source/%s' % i
- o = exehead_env.Object(b, s)
-
- required_obj.append(o)
-
- # build test program
- tests = env.Program(target, tests + required_obj)
-
- # alias running the test to 'test'
- test = env.Alias('test-code', [tests], tests[0].abspath)
-
- # always test when asked to
- AlwaysBuild(test)
-
-else:
-
- # no CppUnit
- def err(target, source, env):
- print '*** error: CppUnit must be installed for testing!'
- return 1
-
- cmd = env.Command(target, [tests], Action(err, ''))
- env.Alias('test-code', cmd)
+target = 'test' + +tests = Split(""" + compression.cpp + decompress.cpp + DialogTemplate.cpp + endian.cpp + mmap.cpp + ResourceEditor.cpp + specmatch.cpp + textrunner.cpp + winchar.cpp +""") + +required = Split(""" + DialogTemplate.cpp + dirreader.cpp + growbuf.cpp + mmap.cpp + ResourceEditor.cpp + util.cpp + winchar.cpp +""") + +required_exehead = Split(""" + Tests/memcpy.c +""") + +lzma_files = Split(""" + clzma.cpp + 7zip/7zGuids.cpp + 7zip/7zip/Common/OutBuffer.cpp + 7zip/7zip/Common/StreamUtils.cpp + 7zip/7zip/Compress/LZ/LZInWindow.cpp + 7zip/7zip/Compress/LZMA/LZMAEncoder.cpp + 7zip/7zip/Compress/RangeCoder/RangeCoderBit.cpp + 7zip/Common/Alloc.cpp + 7zip/Common/CRC.cpp + 7zip/LZMADecode.c +""") + +required += lzma_files + +bzip2_files = Split(""" + bzip2/blocksort.c + bzip2/bzlib.c + bzip2/compress.c + bzip2/huffman.c +""") + +bzip2_exehead_files = Split(""" + bzip2/bzlib.c + bzip2/decompress.c +""") + +required += bzip2_files +required_exehead += bzip2_exehead_files + +zlib_files = Split(""" + zlib/deflate.c + zlib/trees.c +""") + +zlib_exehead_files = Split(""" + zlib/INFBLOCK.C +""") + +required += zlib_files +required_exehead += zlib_exehead_files + +cppunitlibs = Split(""" + cppunit +""") + +extralibs = Split(""" + dl + gdi32 + iconv + pthread + user32 +""") + +scripts = Split(""" + preprocessor.nsi +""") + +Import('env AddAvailableLibs') + +# Test scripts +env.TestScript(scripts) + +# Use available libraries +if env['PLATFORM'] == 'win32': + # XXX will cause problems if tests are cross compiled + # on freebsd, libversion.a exists and gives trouble if linked + extralibs += ['version'] + +AddAvailableLibs(env, extralibs) + +# compile using msvcrt (that's how cppunit.lib is built) +if 'msvc' in env['TOOLS'] or 'mstoolkit' in env['TOOLS']: + env.Append(CCFLAGS = ['/MD']) + +# uses exceptions +env.Append(CCFLAGS = ['$EXCEPTION_FLAG']) + +# for lzma +env.Append(CPPDEFINES = ['COMPRESS_MF_BT']) + +# test for CppUnit +conf = env.Configure() +cppunit = conf.CheckLibWithHeader(cppunitlibs, 'cppunit/extensions/HelperMacros.h', 'C++') +conf.Finish() + +if cppunit: + + # compile files from parent directory + required_obj = [] + + for i in required: + b = 'required/%s' % i.split('.')[0] + s = '#Source/%s' % i + o = env.Object(b, s) + + required_obj.append(o) + + # exehead files special treatment + exehead_env = env.Clone() + exehead_env.Append(CCFLAGS = ['$C_FLAG']) + exehead_env.Append( + CPPDEFINES = [ + 'EXEHEAD', + 'NSIS_COMPRESS_USE_ZLIB' # just so config.h won't complain + ] + ) + + for i in required_exehead: + b = 'required/exehead/%s' % i.split('.')[0] + s = '#Source/%s' % i + o = exehead_env.Object(b, s) + + required_obj.append(o) + + # build test program + tests = env.Program(target, tests + required_obj) + + # alias running the test to 'test' + test = env.Alias('test-code', [tests], tests[0].abspath) + + # always test when asked to + AlwaysBuild(test) + +else: + + # no CppUnit + def err(target, source, env): + print '*** error: CppUnit must be installed for testing!' + return 1 + + cmd = env.Command(target, [tests], Action(err, '')) + env.Alias('test-code', cmd) diff --git a/Source/Tests/compression.cpp b/Source/Tests/compression.cpp index 09f7987..746a7d9 100755 --- a/Source/Tests/compression.cpp +++ b/Source/Tests/compression.cpp @@ -1,154 +1,154 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../Platform.h"
-#include "../growbuf.h"
-
-#include <stdlib.h>
-#include <time.h>
-
-#include "decompress.h"
-
-#include "../cbzip2.h"
-#include "../clzma.h"
-#include "../czlib.h"
-
-class CompressionTest : public CppUnit::TestFixture {
-
-public:
- void randData(IGrowBuf &buf, int kb) {
- srand(time(0));
-
- for (int i = 0; i < kb; i++) {
- int r = rand();
- for (size_t j = 0; j < 1024/sizeof(int); j++) {
- buf.add(&r, sizeof(int));
- }
- }
- }
-
- // compressor must be initialized!
- void compress(ICompressor &compressor, IGrowBuf& in, IGrowBuf& out) {
- compressor.SetNextIn((char *) in.get(), in.getlen());
-
- int ret;
-
- do {
- char outbuf[1024];
- compressor.SetNextOut(outbuf, sizeof(outbuf));
-
- ret = compressor.Compress(C_FINISH);
-
- CPPUNIT_ASSERT_MESSAGE( compressor.GetErrStr(ret) , ret >= 0 );
-
- out.add(outbuf, sizeof(outbuf) - compressor.GetAvailOut());
- } while (ret == 0);
- }
-
- typedef void (*decompressInitPtr)(void *);
- typedef int (*decompressWorkPtr)(void *);
-
- void decompress(IDecompressor& decompressor, IGrowBuf& in, IGrowBuf& out) {
- decompressor.init();
- decompressor.setNextIn(in.get(), in.getlen());
-
- int ret;
-
- do {
- char outbuf[1024];
- decompressor.setNextOut(outbuf, sizeof(outbuf));
-
- ret = decompressor.decompress();
-
- CPPUNIT_ASSERT( ret >= 0 );
-
- out.add(outbuf, sizeof(outbuf) - decompressor.getAvailOut());
-
- } while (ret == 0);
-
- }
-
- // compressor must be initialized!
- void testCompressDecompress(int size_kb, ICompressor &compressor, IDecompressor& decompressor) {
- GrowBuf data;
- GrowBuf compressed;
- GrowBuf decompressed;
-
- randData(data, size_kb);
-
- compress(compressor, data, compressed);
- decompress(decompressor, compressed, decompressed);
-
- CPPUNIT_ASSERT_MESSAGE( "decompressed data is smaller", data.getlen() <= decompressed.getlen() );
- CPPUNIT_ASSERT_MESSAGE( "decompressed data is larger", data.getlen() >= decompressed.getlen() );
- CPPUNIT_ASSERT_MESSAGE( "decompressed data is different", !memcmp(data.get(), decompressed.get(), data.getlen()) );
- }
-
- void testCompressDecompress(ICompressor &compressor, IDecompressor& decompressor) {
- CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK );
- testCompressDecompress(1, compressor, decompressor);
-
- CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK );
- testCompressDecompress(1024, compressor, decompressor);
-
- CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK );
- testCompressDecompress(8*1024, compressor, decompressor);
-
- CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK );
- testCompressDecompress(32*1024, compressor, decompressor);
- }
-
-};
-
-class bzip2CompressionTest : public CompressionTest {
-
- CPPUNIT_TEST_SUITE( bzip2CompressionTest );
- CPPUNIT_TEST( test );
- CPPUNIT_TEST_SUITE_END();
-
-public:
-
- void test() {
- CBzip2 compressor;
- bzip2Decompressor decompressor;
-
- testCompressDecompress(compressor, decompressor);
- }
-
-};
-
-class lzmaCompressionTest : public CompressionTest {
-
- CPPUNIT_TEST_SUITE( lzmaCompressionTest );
- CPPUNIT_TEST( test );
- CPPUNIT_TEST_SUITE_END();
-
-public:
-
- void test() {
- CLZMA compressor;
- lzmaDecompressor decompressor;
-
- testCompressDecompress(compressor, decompressor);
- }
-
-};
-
-class zlibCompressionTest : public CompressionTest {
-
- CPPUNIT_TEST_SUITE( zlibCompressionTest );
- CPPUNIT_TEST( test );
- CPPUNIT_TEST_SUITE_END();
-
-public:
-
- void test() {
- CZlib compressor;
- zlibDecompressor decompressor;
-
- testCompressDecompress(compressor, decompressor);
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( bzip2CompressionTest );
-CPPUNIT_TEST_SUITE_REGISTRATION( lzmaCompressionTest );
-CPPUNIT_TEST_SUITE_REGISTRATION( zlibCompressionTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../Platform.h" +#include "../growbuf.h" + +#include <stdlib.h> +#include <time.h> + +#include "decompress.h" + +#include "../cbzip2.h" +#include "../clzma.h" +#include "../czlib.h" + +class CompressionTest : public CppUnit::TestFixture { + +public: + void randData(IGrowBuf &buf, int kb) { + srand(time(0)); + + for (int i = 0; i < kb; i++) { + int r = rand(); + for (size_t j = 0; j < 1024/sizeof(int); j++) { + buf.add(&r, sizeof(int)); + } + } + } + + // compressor must be initialized! + void compress(ICompressor &compressor, IGrowBuf& in, IGrowBuf& out) { + compressor.SetNextIn((char *) in.get(), in.getlen()); + + int ret; + + do { + char outbuf[1024]; + compressor.SetNextOut(outbuf, sizeof(outbuf)); + + ret = compressor.Compress(C_FINISH); + + CPPUNIT_ASSERT_MESSAGE( compressor.GetErrStr(ret) , ret >= 0 ); + + out.add(outbuf, sizeof(outbuf) - compressor.GetAvailOut()); + } while (ret == 0); + } + + typedef void (*decompressInitPtr)(void *); + typedef int (*decompressWorkPtr)(void *); + + void decompress(IDecompressor& decompressor, IGrowBuf& in, IGrowBuf& out) { + decompressor.init(); + decompressor.setNextIn(in.get(), in.getlen()); + + int ret; + + do { + char outbuf[1024]; + decompressor.setNextOut(outbuf, sizeof(outbuf)); + + ret = decompressor.decompress(); + + CPPUNIT_ASSERT( ret >= 0 ); + + out.add(outbuf, sizeof(outbuf) - decompressor.getAvailOut()); + + } while (ret == 0); + + } + + // compressor must be initialized! + void testCompressDecompress(int size_kb, ICompressor &compressor, IDecompressor& decompressor) { + GrowBuf data; + GrowBuf compressed; + GrowBuf decompressed; + + randData(data, size_kb); + + compress(compressor, data, compressed); + decompress(decompressor, compressed, decompressed); + + CPPUNIT_ASSERT_MESSAGE( "decompressed data is smaller", data.getlen() <= decompressed.getlen() ); + CPPUNIT_ASSERT_MESSAGE( "decompressed data is larger", data.getlen() >= decompressed.getlen() ); + CPPUNIT_ASSERT_MESSAGE( "decompressed data is different", !memcmp(data.get(), decompressed.get(), data.getlen()) ); + } + + void testCompressDecompress(ICompressor &compressor, IDecompressor& decompressor) { + CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK ); + testCompressDecompress(1, compressor, decompressor); + + CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK ); + testCompressDecompress(1024, compressor, decompressor); + + CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK ); + testCompressDecompress(8*1024, compressor, decompressor); + + CPPUNIT_ASSERT( compressor.Init(9, 1 << 23) == C_OK ); + testCompressDecompress(32*1024, compressor, decompressor); + } + +}; + +class bzip2CompressionTest : public CompressionTest { + + CPPUNIT_TEST_SUITE( bzip2CompressionTest ); + CPPUNIT_TEST( test ); + CPPUNIT_TEST_SUITE_END(); + +public: + + void test() { + CBzip2 compressor; + bzip2Decompressor decompressor; + + testCompressDecompress(compressor, decompressor); + } + +}; + +class lzmaCompressionTest : public CompressionTest { + + CPPUNIT_TEST_SUITE( lzmaCompressionTest ); + CPPUNIT_TEST( test ); + CPPUNIT_TEST_SUITE_END(); + +public: + + void test() { + CLZMA compressor; + lzmaDecompressor decompressor; + + testCompressDecompress(compressor, decompressor); + } + +}; + +class zlibCompressionTest : public CompressionTest { + + CPPUNIT_TEST_SUITE( zlibCompressionTest ); + CPPUNIT_TEST( test ); + CPPUNIT_TEST_SUITE_END(); + +public: + + void test() { + CZlib compressor; + zlibDecompressor decompressor; + + testCompressDecompress(compressor, decompressor); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( bzip2CompressionTest ); +CPPUNIT_TEST_SUITE_REGISTRATION( lzmaCompressionTest ); +CPPUNIT_TEST_SUITE_REGISTRATION( zlibCompressionTest ); diff --git a/Source/Tests/decompress.cpp b/Source/Tests/decompress.cpp index 8f27f7b..45c570b 100755 --- a/Source/Tests/decompress.cpp +++ b/Source/Tests/decompress.cpp @@ -1,62 +1,62 @@ -#include "decompress.h"
-
-#include <string.h> // for memset
-
-#define EXEHEAD
-#define NSIS_CONFIG_COMPRESSION_SUPPORT
-
-extern "C" {
-#define NSIS_COMPRESS_USE_BZIP2
-#include "../bzip2/bzlib.h"
-#undef NSIS_COMPRESS_USE_BZIP2
-
-#define NSIS_COMPRESS_USE_LZMA
-#include "../7zip/LZMADecode.h"
-#undef NSIS_COMPRESS_USE_LZMA
-
-#define NSIS_COMPRESS_USE_ZLIB
-#include "../zlib/ZLIB.H"
-#undef NSIS_COMPRESS_USE_ZLIB
-}
-
-#define DECOMPRESSOR(name, type, initf, dec, u) \
- name::name() { \
- vs = new type; \
- memset(vs, 0, sizeof(type)); \
- } \
- \
- name::~name() { \
- delete (type *) vs; \
- vs = 0; \
- } \
- \
- void name::setNextIn(void *buffer, int size) { \
- type *s = (type *) vs; \
- s->next_in = (u *) buffer; \
- s->avail_in = size; \
- } \
- \
- void name::setNextOut(void *buffer, int size) { \
- type *s = (type *) vs; \
- s->next_out = (u *) buffer; \
- s->avail_out = size; \
- } \
- \
- int name::getAvailOut() { \
- type *s = (type *) vs; \
- return s->avail_out; \
- } \
- \
- void name::init() { \
- type *s = (type *) vs; \
- initf(s); \
- } \
- \
- int name::decompress() { \
- type *s = (type *) vs; \
- return dec(s); \
- }
-
-DECOMPRESSOR(lzmaDecompressor, lzma_stream, lzmaInit, lzmaDecode, unsigned char);
-DECOMPRESSOR(bzip2Decompressor, DState, BZ2_bzDecompressInit, BZ2_bzDecompress, char);
-DECOMPRESSOR(zlibDecompressor, z_stream, inflateReset, inflate, unsigned char);
+#include "decompress.h" + +#include <string.h> // for memset + +#define EXEHEAD +#define NSIS_CONFIG_COMPRESSION_SUPPORT + +extern "C" { +#define NSIS_COMPRESS_USE_BZIP2 +#include "../bzip2/bzlib.h" +#undef NSIS_COMPRESS_USE_BZIP2 + +#define NSIS_COMPRESS_USE_LZMA +#include "../7zip/LZMADecode.h" +#undef NSIS_COMPRESS_USE_LZMA + +#define NSIS_COMPRESS_USE_ZLIB +#include "../zlib/ZLIB.H" +#undef NSIS_COMPRESS_USE_ZLIB +} + +#define DECOMPRESSOR(name, type, initf, dec, u) \ + name::name() { \ + vs = new type; \ + memset(vs, 0, sizeof(type)); \ + } \ + \ + name::~name() { \ + delete (type *) vs; \ + vs = 0; \ + } \ + \ + void name::setNextIn(void *buffer, int size) { \ + type *s = (type *) vs; \ + s->next_in = (u *) buffer; \ + s->avail_in = size; \ + } \ + \ + void name::setNextOut(void *buffer, int size) { \ + type *s = (type *) vs; \ + s->next_out = (u *) buffer; \ + s->avail_out = size; \ + } \ + \ + int name::getAvailOut() { \ + type *s = (type *) vs; \ + return s->avail_out; \ + } \ + \ + void name::init() { \ + type *s = (type *) vs; \ + initf(s); \ + } \ + \ + int name::decompress() { \ + type *s = (type *) vs; \ + return dec(s); \ + } + +DECOMPRESSOR(lzmaDecompressor, lzma_stream, lzmaInit, lzmaDecode, unsigned char); +DECOMPRESSOR(bzip2Decompressor, DState, BZ2_bzDecompressInit, BZ2_bzDecompress, char); +DECOMPRESSOR(zlibDecompressor, z_stream, inflateReset, inflate, unsigned char); diff --git a/Source/Tests/decompress.h b/Source/Tests/decompress.h index 4f0e492..6fb2a76 100755 --- a/Source/Tests/decompress.h +++ b/Source/Tests/decompress.h @@ -1,66 +1,66 @@ -class IDecompressor {
-public:
-
- virtual ~IDecompressor() {};
-
- virtual void init() = 0;
- virtual void setNextIn(void *buffer, int size) = 0;
- virtual void setNextOut(void *buffer, int size) = 0;
- virtual int getAvailOut() = 0;
- virtual int decompress() = 0;
-
-};
-
-class lzmaDecompressor : public IDecompressor {
-public:
-
- lzmaDecompressor();
- virtual ~lzmaDecompressor();
-
- virtual void init();
- virtual void setNextIn(void *buffer, int size);
- virtual void setNextOut(void *buffer, int size);
- virtual int getAvailOut();
- virtual int decompress();
-
-private:
-
- void *vs;
-
-};
-
-class bzip2Decompressor : public IDecompressor {
-public:
-
- bzip2Decompressor();
- virtual ~bzip2Decompressor();
-
- virtual void init();
- virtual void setNextIn(void *buffer, int size);
- virtual void setNextOut(void *buffer, int size);
- virtual int getAvailOut();
- virtual int decompress();
-
-private:
-
- void *vs;
-
-};
-
-class zlibDecompressor : public IDecompressor {
-public:
-
- zlibDecompressor();
- virtual ~zlibDecompressor();
-
- virtual void init();
- virtual void setNextIn(void *buffer, int size);
- virtual void setNextOut(void *buffer, int size);
- virtual int getAvailOut();
- virtual int decompress();
-
-private:
-
- void *vs;
-
-};
+class IDecompressor { +public: + + virtual ~IDecompressor() {}; + + virtual void init() = 0; + virtual void setNextIn(void *buffer, int size) = 0; + virtual void setNextOut(void *buffer, int size) = 0; + virtual int getAvailOut() = 0; + virtual int decompress() = 0; + +}; + +class lzmaDecompressor : public IDecompressor { +public: + + lzmaDecompressor(); + virtual ~lzmaDecompressor(); + + virtual void init(); + virtual void setNextIn(void *buffer, int size); + virtual void setNextOut(void *buffer, int size); + virtual int getAvailOut(); + virtual int decompress(); + +private: + + void *vs; + +}; + +class bzip2Decompressor : public IDecompressor { +public: + + bzip2Decompressor(); + virtual ~bzip2Decompressor(); + + virtual void init(); + virtual void setNextIn(void *buffer, int size); + virtual void setNextOut(void *buffer, int size); + virtual int getAvailOut(); + virtual int decompress(); + +private: + + void *vs; + +}; + +class zlibDecompressor : public IDecompressor { +public: + + zlibDecompressor(); + virtual ~zlibDecompressor(); + + virtual void init(); + virtual void setNextIn(void *buffer, int size); + virtual void setNextOut(void *buffer, int size); + virtual int getAvailOut(); + virtual int decompress(); + +private: + + void *vs; + +}; diff --git a/Source/Tests/endian.cpp b/Source/Tests/endian.cpp index ed9b2e2..c1912d5 100755 --- a/Source/Tests/endian.cpp +++ b/Source/Tests/endian.cpp @@ -1,56 +1,56 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../Platform.h"
-
-class EndianTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( EndianTest );
- CPPUNIT_TEST( testSwapEndian );
- CPPUNIT_TEST( testFixEndian16 );
- CPPUNIT_TEST( testFixEndian32 );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testSwapEndian() {
- CPPUNIT_ASSERT_EQUAL( (int)0x78563412, (int)SWAP_ENDIAN_INT32(0x12345678) );
- CPPUNIT_ASSERT_EQUAL( (int)0xFFFFFFFF, (int)SWAP_ENDIAN_INT32(0xFFFFFFFF) );
- CPPUNIT_ASSERT_EQUAL( (int)0, (int)SWAP_ENDIAN_INT32(0) );
- CPPUNIT_ASSERT_EQUAL( (int)0x3412, (int)SWAP_ENDIAN_INT16(0x1234) );
- CPPUNIT_ASSERT_EQUAL( (int)0xFFFF, (int)SWAP_ENDIAN_INT16(0xFFFF) );
- CPPUNIT_ASSERT_EQUAL( (int)0, (int)SWAP_ENDIAN_INT16(0) );
- }
-
- void testFixEndian32() {
- int i=1;
- int actual = 0x12345678;
- FIX_ENDIAN_INT32_INPLACE(actual);
- int expected;
- if (((char*)&i)[0] == 1) {
- // little endian
- expected = 0x12345678;
- }
- else {
- // big endian
- expected = 0x78563412;
- }
- CPPUNIT_ASSERT_EQUAL(expected, actual);
- }
-
- void testFixEndian16() {
- int i=1;
- int actual = 0x1234;
- FIX_ENDIAN_INT16_INPLACE(actual);
- int expected;
- if (((char*)&i)[0] == 1) {
- // little endian
- expected = 0x1234;
- }
- else {
- // big endian
- expected = 0x3412;
- }
- CPPUNIT_ASSERT_EQUAL(expected, actual);
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( EndianTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../Platform.h" + +class EndianTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( EndianTest ); + CPPUNIT_TEST( testSwapEndian ); + CPPUNIT_TEST( testFixEndian16 ); + CPPUNIT_TEST( testFixEndian32 ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testSwapEndian() { + CPPUNIT_ASSERT_EQUAL( (int)0x78563412, (int)SWAP_ENDIAN_INT32(0x12345678) ); + CPPUNIT_ASSERT_EQUAL( (int)0xFFFFFFFF, (int)SWAP_ENDIAN_INT32(0xFFFFFFFF) ); + CPPUNIT_ASSERT_EQUAL( (int)0, (int)SWAP_ENDIAN_INT32(0) ); + CPPUNIT_ASSERT_EQUAL( (int)0x3412, (int)SWAP_ENDIAN_INT16(0x1234) ); + CPPUNIT_ASSERT_EQUAL( (int)0xFFFF, (int)SWAP_ENDIAN_INT16(0xFFFF) ); + CPPUNIT_ASSERT_EQUAL( (int)0, (int)SWAP_ENDIAN_INT16(0) ); + } + + void testFixEndian32() { + int i=1; + int actual = 0x12345678; + FIX_ENDIAN_INT32_INPLACE(actual); + int expected; + if (((char*)&i)[0] == 1) { + // little endian + expected = 0x12345678; + } + else { + // big endian + expected = 0x78563412; + } + CPPUNIT_ASSERT_EQUAL(expected, actual); + } + + void testFixEndian16() { + int i=1; + int actual = 0x1234; + FIX_ENDIAN_INT16_INPLACE(actual); + int expected; + if (((char*)&i)[0] == 1) { + // little endian + expected = 0x1234; + } + else { + // big endian + expected = 0x3412; + } + CPPUNIT_ASSERT_EQUAL(expected, actual); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( EndianTest ); diff --git a/Source/Tests/memcpy.c b/Source/Tests/memcpy.c index f2828e8..0c590e8 100755 --- a/Source/Tests/memcpy.c +++ b/Source/Tests/memcpy.c @@ -1,11 +1,11 @@ -#include "../Platform.h"
-
-void NSISCALL 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++;
- }
-}
+#include "../Platform.h" + +void NSISCALL 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++; + } +} diff --git a/Source/Tests/mmap.cpp b/Source/Tests/mmap.cpp index b1088f4..c2d267b 100755 --- a/Source/Tests/mmap.cpp +++ b/Source/Tests/mmap.cpp @@ -1,74 +1,74 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../mmap.h"
-
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-using namespace std; // for std::min
-
-int g_display_errors = 1;
-FILE *g_output = stderr;
-
-void quit() {
- fprintf(g_output, "MMap quit\n");
-}
-
-class MMapTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( MMapTest );
- CPPUNIT_TEST( testMMapFile );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testMMapFile() {
- size_t i;
- const int BUF_SIZE = 50000; // 50MB
-
- // resize
-
- MMapFile mmap;
- mmap.resize(BUF_SIZE);
- CPPUNIT_ASSERT_EQUAL( BUF_SIZE, mmap.getsize() );
-
- // set content
-
- char *buf = (char *) mmap.get(0, BUF_SIZE);
-
- for (i = 0; i < BUF_SIZE; i++) {
- buf[i] = i % 256;
- }
-
- mmap.release();
-
- // test content and get(), getmore()
-
- srand(time(NULL));
-
- for (i = 0; i < 100; i++) {
- int offset1 = rand() % BUF_SIZE;
- int size1 = rand() % (BUF_SIZE - offset1);
- char *p1 = (char *) mmap.get(offset1, size1);
-
- int offset2 = rand() % BUF_SIZE;
- int size2 = rand() % (BUF_SIZE - offset2);
- char *p2 = (char *) mmap.getmore(offset2, size2);
-
- int j;
-
- for (j = 0; j < size1; j++) {
- CPPUNIT_ASSERT_EQUAL( p1[j], char((offset1 + j) % 256) );
- }
-
- for (j = 0; j < size2; j++) {
- CPPUNIT_ASSERT_EQUAL( p2[j], char((offset2 + j) % 256) );
- }
-
- mmap.release();
- mmap.release(p2, size2);
- }
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( MMapTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../mmap.h" + +#include <time.h> +#include <stdlib.h> +#include <stdio.h> + +using namespace std; // for std::min + +int g_display_errors = 1; +FILE *g_output = stderr; + +void quit() { + fprintf(g_output, "MMap quit\n"); +} + +class MMapTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( MMapTest ); + CPPUNIT_TEST( testMMapFile ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testMMapFile() { + size_t i; + const int BUF_SIZE = 50000; // 50MB + + // resize + + MMapFile mmap; + mmap.resize(BUF_SIZE); + CPPUNIT_ASSERT_EQUAL( BUF_SIZE, mmap.getsize() ); + + // set content + + char *buf = (char *) mmap.get(0, BUF_SIZE); + + for (i = 0; i < BUF_SIZE; i++) { + buf[i] = i % 256; + } + + mmap.release(); + + // test content and get(), getmore() + + srand(time(NULL)); + + for (i = 0; i < 100; i++) { + int offset1 = rand() % BUF_SIZE; + int size1 = rand() % (BUF_SIZE - offset1); + char *p1 = (char *) mmap.get(offset1, size1); + + int offset2 = rand() % BUF_SIZE; + int size2 = rand() % (BUF_SIZE - offset2); + char *p2 = (char *) mmap.getmore(offset2, size2); + + int j; + + for (j = 0; j < size1; j++) { + CPPUNIT_ASSERT_EQUAL( p1[j], char((offset1 + j) % 256) ); + } + + for (j = 0; j < size2; j++) { + CPPUNIT_ASSERT_EQUAL( p2[j], char((offset2 + j) % 256) ); + } + + mmap.release(); + mmap.release(p2, size2); + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( MMapTest ); diff --git a/Source/Tests/preprocessor.nsi b/Source/Tests/preprocessor.nsi index 751fdce..9f25c9b 100755 --- a/Source/Tests/preprocessor.nsi +++ b/Source/Tests/preprocessor.nsi @@ -1,224 +1,224 @@ -!ifndef file_is_included
-!define file_is_included
-
-Name preprocessor
-OutFile preprocessor.exe
-
-!ifdef some_define_that_doesnt_exist
-this should not be executed, so no error should be raised
-/*
-code inside comments should not be executed
-!ifdef
-*/
-# invalid preprocessor should be ignored
-!hello
-!endif
-
-!ifdef d1
-!error "d1 is not defined!"
-!else ifdef d2
-!error "d2 is not defined!"
-!else
-# this should be compiled
-!endif
-
-!define d1
-
-!ifdef d1
-# this should be compiled
-!else ifdef d2
-!error "d2 is not defined!"
-!else
-!error "d1 is defined!"
-!endif
-
-!undef d1
-!define d2
-
-!ifdef d1
-!error "d1 is not defined!"
-!else ifdef d2
-# this should be compiled
-!else
-!error "d2 is defined!"
-!endif
-
-!ifdef some_define_that_doesnt_exist
-the next !endif should be part of this line\
-!endif
-!\
-e\
-n\
-d\
-i\
-f
-
-!if 0
-/*
-this shouldn't be compiled
-!endif
-*/
-!endif
-
-# tests for !if statement
-!if 'test' == 'test'
- !if 1 <= 2
- !if ! 100 < 99.99
- !if 2.2 > 1.12
- !if ! 23 >= 37
- !if 1 && 1
- !if ! 0 || 0
-
- # this should be compiled
-
- !else
- !error "!if ! 0 || 0 is true!"
- !endif
- !else
- !error "!if 1 && 1 is true!"
- !endif
- !else
- !error "!if ! 23 >= 37 is true!"
- !endif
- !else
- !error "!if 2.2 > 1.12 is true!"
- !endif
- !else
- !error "!if ! 100 < 99.99 is true!"
- !endif
- !else
- !error "!if 1 <= 2 is true!"
- !endif
-!else
- !error "!if 'test' == 'test' is true!"
-!endif
-
-; testing of two math functions and a macro hack :)
-!define increase "!insertmacro increase"
-!macro increase DEFINE
- !define /math ${DEFINE}_MACROTEMP ${${DEFINE}} + 1
- !undef ${DEFINE}
- !define ${DEFINE} ${${DEFINE}_MACROTEMP}
- !undef ${DEFINE}_MACROTEMP
-!macroend
-
-!define number1 1 # 1
-!define /math number2 2 + 3
-!define /math number3 ${number2} - ${number1}
-${increase} number3
-!define /math number4 2 * ${number3}
-!define /math number5 ${number4} % 3
-
-!if ${number1} != 1
- !error "number1 != 1"
-!endif
-
-!if ${number2} != 5
- !error "number2 != 5"
-!endif
-
-!if ${number3} != 5
- !error "number3 != 5"
-!endif
-
-!if ${number4} != 10
- !error "number4 != 10"
-!endif
-
-!if ${number5} != 1
- !error "number5 != 1"
-!endif
-
-; end math functions
-
-# this should just give a warning, not an error
-!include /NONFATAL file_that_doesnt_exist.nsh
-
-# this should include this file just one time.
-!include preprocessor.nsi
-
-Section
-Return
-WriteUninstaller uninst.exe # avoid warning
-SectionEnd
-
-# test scopes
-
-!macro TEST_SCOPE scope def should_exist
-
- !if ${should_exist} == y
- !ifndef ${def}
- !error "${def} not defined in ${scope} scope"
- !endif
- !else
- !ifdef ${def}
- !error "${def} defined in ${scope} scope"
- !endif
- !endif
-
-!macroend
-
-!macro TEST_SCOPES scope global section function pageex uninstall
-
- !insertmacro TEST_SCOPE "${scope}" __GLOBAL__ ${global}
- !insertmacro TEST_SCOPE "${scope}" __SECTION__ ${section}
- !insertmacro TEST_SCOPE "${scope}" __FUNCTION__ ${function}
- !insertmacro TEST_SCOPE "${scope}" __PAGEEX__ ${pageex}
- !insertmacro TEST_SCOPE "${scope}" __UNINSTALL__ ${uninstall}
-
-!macroend
-
-!insertmacro TEST_SCOPES "global" y n n n n
-
-Section test
-!insertmacro TEST_SCOPES "section" n y n n n
-!if ${__SECTION__} != test
- !error "invalid __SECTION__ value"
-!endif
-SectionEnd
-
-Section un.test
-!insertmacro TEST_SCOPES "uninstall section" n y n n y
-!if ${__SECTION__} != test
- !error "invalid __SECTION__ value"
-!endif
-SectionEnd
-
-Function test
-Call test # avoid warning
-!insertmacro TEST_SCOPES "function" n n y n n
-!if ${__FUNCTION__} != test
- !error "invalid __FUNCTION__ value"
-!endif
-FunctionEnd
-
-Function un.test
-Call un.test # avoid warning
-!insertmacro TEST_SCOPES "uninstall function" n n y n y
-!if ${__FUNCTION__} != test
- !error "invalid __FUNCTION__ value"
-!endif
-FunctionEnd
-
-PageEx instfiles
-!insertmacro TEST_SCOPES "pageex" n n n y n
-!if ${__PAGEEX__} != instfiles
- !error "invalid __PAGEEX__ value"
-!endif
-PageExEnd
-
-PageEx un.instfiles
-!insertmacro TEST_SCOPES "uninstall pageex" n n n y y
-!if ${__PAGEEX__} != instfiles
- !error "invalid __PAGEEX__ value"
-!endif
-PageExEnd
-
-!insertmacro TEST_SCOPES "global" y n n n n
-
-!else
-
-# this should just give a warning, not an error
-!include /NONFATAL another_file_that_doesnt_exist.nsh
-
-!endif
+!ifndef file_is_included +!define file_is_included + +Name preprocessor +OutFile preprocessor.exe + +!ifdef some_define_that_doesnt_exist +this should not be executed, so no error should be raised +/* +code inside comments should not be executed +!ifdef +*/ +# invalid preprocessor should be ignored +!hello +!endif + +!ifdef d1 +!error "d1 is not defined!" +!else ifdef d2 +!error "d2 is not defined!" +!else +# this should be compiled +!endif + +!define d1 + +!ifdef d1 +# this should be compiled +!else ifdef d2 +!error "d2 is not defined!" +!else +!error "d1 is defined!" +!endif + +!undef d1 +!define d2 + +!ifdef d1 +!error "d1 is not defined!" +!else ifdef d2 +# this should be compiled +!else +!error "d2 is defined!" +!endif + +!ifdef some_define_that_doesnt_exist +the next !endif should be part of this line\ +!endif +!\ +e\ +n\ +d\ +i\ +f + +!if 0 +/* +this shouldn't be compiled +!endif +*/ +!endif + +# tests for !if statement +!if 'test' == 'test' + !if 1 <= 2 + !if ! 100 < 99.99 + !if 2.2 > 1.12 + !if ! 23 >= 37 + !if 1 && 1 + !if ! 0 || 0 + + # this should be compiled + + !else + !error "!if ! 0 || 0 is true!" + !endif + !else + !error "!if 1 && 1 is true!" + !endif + !else + !error "!if ! 23 >= 37 is true!" + !endif + !else + !error "!if 2.2 > 1.12 is true!" + !endif + !else + !error "!if ! 100 < 99.99 is true!" + !endif + !else + !error "!if 1 <= 2 is true!" + !endif +!else + !error "!if 'test' == 'test' is true!" +!endif + +; testing of two math functions and a macro hack :) +!define increase "!insertmacro increase" +!macro increase DEFINE + !define /math ${DEFINE}_MACROTEMP ${${DEFINE}} + 1 + !undef ${DEFINE} + !define ${DEFINE} ${${DEFINE}_MACROTEMP} + !undef ${DEFINE}_MACROTEMP +!macroend + +!define number1 1 # 1 +!define /math number2 2 + 3 +!define /math number3 ${number2} - ${number1} +${increase} number3 +!define /math number4 2 * ${number3} +!define /math number5 ${number4} % 3 + +!if ${number1} != 1 + !error "number1 != 1" +!endif + +!if ${number2} != 5 + !error "number2 != 5" +!endif + +!if ${number3} != 5 + !error "number3 != 5" +!endif + +!if ${number4} != 10 + !error "number4 != 10" +!endif + +!if ${number5} != 1 + !error "number5 != 1" +!endif + +; end math functions + +# this should just give a warning, not an error +!include /NONFATAL file_that_doesnt_exist.nsh + +# this should include this file just one time. +!include preprocessor.nsi + +Section +Return +WriteUninstaller uninst.exe # avoid warning +SectionEnd + +# test scopes + +!macro TEST_SCOPE scope def should_exist + + !if ${should_exist} == y + !ifndef ${def} + !error "${def} not defined in ${scope} scope" + !endif + !else + !ifdef ${def} + !error "${def} defined in ${scope} scope" + !endif + !endif + +!macroend + +!macro TEST_SCOPES scope global section function pageex uninstall + + !insertmacro TEST_SCOPE "${scope}" __GLOBAL__ ${global} + !insertmacro TEST_SCOPE "${scope}" __SECTION__ ${section} + !insertmacro TEST_SCOPE "${scope}" __FUNCTION__ ${function} + !insertmacro TEST_SCOPE "${scope}" __PAGEEX__ ${pageex} + !insertmacro TEST_SCOPE "${scope}" __UNINSTALL__ ${uninstall} + +!macroend + +!insertmacro TEST_SCOPES "global" y n n n n + +Section test +!insertmacro TEST_SCOPES "section" n y n n n +!if ${__SECTION__} != test + !error "invalid __SECTION__ value" +!endif +SectionEnd + +Section un.test +!insertmacro TEST_SCOPES "uninstall section" n y n n y +!if ${__SECTION__} != test + !error "invalid __SECTION__ value" +!endif +SectionEnd + +Function test +Call test # avoid warning +!insertmacro TEST_SCOPES "function" n n y n n +!if ${__FUNCTION__} != test + !error "invalid __FUNCTION__ value" +!endif +FunctionEnd + +Function un.test +Call un.test # avoid warning +!insertmacro TEST_SCOPES "uninstall function" n n y n y +!if ${__FUNCTION__} != test + !error "invalid __FUNCTION__ value" +!endif +FunctionEnd + +PageEx instfiles +!insertmacro TEST_SCOPES "pageex" n n n y n +!if ${__PAGEEX__} != instfiles + !error "invalid __PAGEEX__ value" +!endif +PageExEnd + +PageEx un.instfiles +!insertmacro TEST_SCOPES "uninstall pageex" n n n y y +!if ${__PAGEEX__} != instfiles + !error "invalid __PAGEEX__ value" +!endif +PageExEnd + +!insertmacro TEST_SCOPES "global" y n n n n + +!else + +# this should just give a warning, not an error +!include /NONFATAL another_file_that_doesnt_exist.nsh + +!endif diff --git a/Source/Tests/root.txt b/Source/Tests/root.txt index e3629ef..3e09f16 100755 --- a/Source/Tests/root.txt +++ b/Source/Tests/root.txt @@ -1,6 +1,6 @@ -this is a list of bugs related to root directories, which can not yet be tested automatically
-
-* bug #1331292 - browsing for root network directory disables next button
-
-* root with space after it, without AllowRootDirInstall
- http://forums.winamp.com/showthread.php?threadid=222727
+this is a list of bugs related to root directories, which can not yet be tested automatically + +* bug #1331292 - browsing for root network directory disables next button + +* root with space after it, without AllowRootDirInstall + http://forums.winamp.com/showthread.php?threadid=222727 diff --git a/Source/Tests/specmatch.cpp b/Source/Tests/specmatch.cpp index a68555c..56a79c7 100755 --- a/Source/Tests/specmatch.cpp +++ b/Source/Tests/specmatch.cpp @@ -1,45 +1,45 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../dirreader.h"
-
-#include <string>
-
-using namespace std;
-
-class SpecTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( SpecTest );
- CPPUNIT_TEST( testMatches );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testMatches() {
- testMatch("test.exe", "test.exe", true);
- testMatch("test", "test", true);
- testMatch("test.exe", "test.*", true);
- testMatch("test", "test.*", true);
- testMatch("test", "????", true);
- testMatch("test", "???", false);
- testMatch("test", "*.exe", false);
- testMatch("test.exe.bat", "*.exe", false);
- testMatch("test.exe.bat", "*.bat", true);
- testMatch("test.exe.bat", "*t", true);
- testMatch("test.exe.bat", "*", true);
- testMatch("test.exe.bat", "*x*", true);
- testMatch("test.exe.exe", "*.*", true);
- testMatch("test.exe.bat", "*.b*", true);
- testMatch("test.exe.bat", "tes?.*.bat", true);
- testMatch("test.exe.bat", "tes?.*bat", true);
- testMatch("test.exe.bat", "tes?.*bat***.", true);
- testMatch("test.exe", "????.*", true);
- testMatch("testing.exe", "????.*", false);
- }
-
-private:
-
- void testMatch(string name, string spec, bool result) {
- CPPUNIT_ASSERT_EQUAL( dir_reader::matches(name, spec), result );
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( SpecTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../dirreader.h" + +#include <string> + +using namespace std; + +class SpecTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( SpecTest ); + CPPUNIT_TEST( testMatches ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testMatches() { + testMatch("test.exe", "test.exe", true); + testMatch("test", "test", true); + testMatch("test.exe", "test.*", true); + testMatch("test", "test.*", true); + testMatch("test", "????", true); + testMatch("test", "???", false); + testMatch("test", "*.exe", false); + testMatch("test.exe.bat", "*.exe", false); + testMatch("test.exe.bat", "*.bat", true); + testMatch("test.exe.bat", "*t", true); + testMatch("test.exe.bat", "*", true); + testMatch("test.exe.bat", "*x*", true); + testMatch("test.exe.exe", "*.*", true); + testMatch("test.exe.bat", "*.b*", true); + testMatch("test.exe.bat", "tes?.*.bat", true); + testMatch("test.exe.bat", "tes?.*bat", true); + testMatch("test.exe.bat", "tes?.*bat***.", true); + testMatch("test.exe", "????.*", true); + testMatch("testing.exe", "????.*", false); + } + +private: + + void testMatch(string name, string spec, bool result) { + CPPUNIT_ASSERT_EQUAL( dir_reader::matches(name, spec), result ); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( SpecTest ); diff --git a/Source/Tests/textrunner.cpp b/Source/Tests/textrunner.cpp index 4c5179f..171a578 100755 --- a/Source/Tests/textrunner.cpp +++ b/Source/Tests/textrunner.cpp @@ -1,22 +1,22 @@ -#include <cppunit/CompilerOutputter.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-#include <cppunit/ui/text/TestRunner.h>
-
-int main(int argc, char* argv[])
-{
- // Get the top level suite from the registry
- CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
-
- // Adds the test to the list of test to run
- CppUnit::TextUi::TestRunner runner;
- runner.addTest( suite );
-
- // Change the default outputter to a compiler error format outputter
- runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(),
- std::cerr ) );
- // Run the tests.
- bool wasSucessful = runner.run();
-
- // Return error code 1 if the one of test failed.
- return wasSucessful ? 0 : 1;
-}
+#include <cppunit/CompilerOutputter.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> + +int main(int argc, char* argv[]) +{ + // Get the top level suite from the registry + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + + // Adds the test to the list of test to run + CppUnit::TextUi::TestRunner runner; + runner.addTest( suite ); + + // Change the default outputter to a compiler error format outputter + runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), + std::cerr ) ); + // Run the tests. + bool wasSucessful = runner.run(); + + // Return error code 1 if the one of test failed. + return wasSucessful ? 0 : 1; +} diff --git a/Source/Tests/winchar.cpp b/Source/Tests/winchar.cpp index 99934a9..a7df1e4 100755 --- a/Source/Tests/winchar.cpp +++ b/Source/Tests/winchar.cpp @@ -1,129 +1,129 @@ -#include <cppunit/extensions/HelperMacros.h>
-#include "../winchar.h"
-
-#include <time.h>
-#include <stdlib.h>
-
-// macro for fixing endianity
-#define _x(x) FIX_ENDIAN_INT16(WCHAR(x))
-
-class WinCharTest : public CppUnit::TestFixture {
-
- CPPUNIT_TEST_SUITE( WinCharTest );
- CPPUNIT_TEST( testFromAnsi );
- CPPUNIT_TEST( testToAnsi );
- CPPUNIT_TEST( testStrCpy );
- CPPUNIT_TEST( testStrNCpy );
- CPPUNIT_TEST( testStrLen );
- CPPUNIT_TEST( testStrCmp );
- CPPUNIT_TEST( testStrDup );
- CPPUNIT_TEST( testStoi );
- CPPUNIT_TEST_SUITE_END();
-
-public:
- void testFromAnsi() {
- WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 };
- WCHAR *dyn = winchar_fromansi("test");
-
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(test, dyn, 5) );
-
- delete [] dyn;
- }
-
- void testToAnsi() {
- WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 };
- char *dyn = winchar_toansi(test);
-
- CPPUNIT_ASSERT_EQUAL( 0, strcmp("test", dyn) );
-
- delete [] dyn;
- }
-
- void testStrCpy() {
- WCHAR a[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 };
- WCHAR b[5];
-
- CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strcpy(b, a) );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(a, b, 5) );
- }
-
- void testStrNCpy() {
- WCHAR a1[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 };
- WCHAR b[5];
-
- CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a1, 5) );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(a1, b, 5 * sizeof(WCHAR)) );
-
- WCHAR a2[] = { _x('t'), _x('e'), 0, 0, 0 };
-
- CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a2, 5) );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(a2, b, 5 * sizeof(WCHAR)) );
-
- CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a1, 2) );
- CPPUNIT_ASSERT_EQUAL( 0, memcmp(a2, b, 5 * sizeof(WCHAR)) );
- }
-
- void testStrLen() {
- WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 };
-
- CPPUNIT_ASSERT_EQUAL( (size_t) 4, winchar_strlen(test) );
- }
-
- static int simplifyNumber(int n) {
- if (n < 0)
- return -1;
- if (n > 0)
- return 1;
- return 0;
- }
-
- void testStrCmp() {
- char a[] = "a";
- WCHAR wa[] = { _x('a'), 0 };
- char b[] = "b";
- WCHAR wb[] = { _x('b'), 0 };
- char empty[] = "";
- WCHAR wempty[] = { 0 };
-
- #define TEST_STR_CMP(x, y) \
- CPPUNIT_ASSERT_EQUAL(\
- simplifyNumber(strcmp(x, y)), \
- simplifyNumber(winchar_strcmp(w##x, w##y)) \
- )
-
- TEST_STR_CMP(a, b);
- TEST_STR_CMP(b, a);
- TEST_STR_CMP(a, a);
- TEST_STR_CMP(b, b);
- TEST_STR_CMP(a, empty);
- TEST_STR_CMP(empty, b);
- TEST_STR_CMP(empty, empty);
- }
-
- void testStrDup() {
- WCHAR a[] = { _x('a'), _x('b'), _x('c'), 0 };
-
- WCHAR *b = winchar_strdup(a);
-
- CPPUNIT_ASSERT_EQUAL( 0, winchar_strcmp(a, b) );
-
- delete [] b;
- }
-
- void testStoi() {
- srand(time(0));
-
- for (int i = 0; i < 1000; i++)
- {
- int r = rand();
- char s[128];
- sprintf(s, "%d", r);
- WCHAR *ws = winchar_fromansi(s);
- CPPUNIT_ASSERT_EQUAL( r, winchar_stoi(ws) );
- delete [] ws;
- }
- }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION( WinCharTest );
+#include <cppunit/extensions/HelperMacros.h> +#include "../winchar.h" + +#include <time.h> +#include <stdlib.h> + +// macro for fixing endianity +#define _x(x) FIX_ENDIAN_INT16(WCHAR(x)) + +class WinCharTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE( WinCharTest ); + CPPUNIT_TEST( testFromAnsi ); + CPPUNIT_TEST( testToAnsi ); + CPPUNIT_TEST( testStrCpy ); + CPPUNIT_TEST( testStrNCpy ); + CPPUNIT_TEST( testStrLen ); + CPPUNIT_TEST( testStrCmp ); + CPPUNIT_TEST( testStrDup ); + CPPUNIT_TEST( testStoi ); + CPPUNIT_TEST_SUITE_END(); + +public: + void testFromAnsi() { + WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 }; + WCHAR *dyn = winchar_fromansi("test"); + + CPPUNIT_ASSERT_EQUAL( 0, memcmp(test, dyn, 5) ); + + delete [] dyn; + } + + void testToAnsi() { + WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 }; + char *dyn = winchar_toansi(test); + + CPPUNIT_ASSERT_EQUAL( 0, strcmp("test", dyn) ); + + delete [] dyn; + } + + void testStrCpy() { + WCHAR a[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 }; + WCHAR b[5]; + + CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strcpy(b, a) ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(a, b, 5) ); + } + + void testStrNCpy() { + WCHAR a1[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 }; + WCHAR b[5]; + + CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a1, 5) ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(a1, b, 5 * sizeof(WCHAR)) ); + + WCHAR a2[] = { _x('t'), _x('e'), 0, 0, 0 }; + + CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a2, 5) ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(a2, b, 5 * sizeof(WCHAR)) ); + + CPPUNIT_ASSERT_EQUAL( (WCHAR*) b, (WCHAR*) winchar_strncpy(b, a1, 2) ); + CPPUNIT_ASSERT_EQUAL( 0, memcmp(a2, b, 5 * sizeof(WCHAR)) ); + } + + void testStrLen() { + WCHAR test[] = { _x('t'), _x('e'), _x('s'), _x('t'), 0 }; + + CPPUNIT_ASSERT_EQUAL( (size_t) 4, winchar_strlen(test) ); + } + + static int simplifyNumber(int n) { + if (n < 0) + return -1; + if (n > 0) + return 1; + return 0; + } + + void testStrCmp() { + char a[] = "a"; + WCHAR wa[] = { _x('a'), 0 }; + char b[] = "b"; + WCHAR wb[] = { _x('b'), 0 }; + char empty[] = ""; + WCHAR wempty[] = { 0 }; + + #define TEST_STR_CMP(x, y) \ + CPPUNIT_ASSERT_EQUAL(\ + simplifyNumber(strcmp(x, y)), \ + simplifyNumber(winchar_strcmp(w##x, w##y)) \ + ) + + TEST_STR_CMP(a, b); + TEST_STR_CMP(b, a); + TEST_STR_CMP(a, a); + TEST_STR_CMP(b, b); + TEST_STR_CMP(a, empty); + TEST_STR_CMP(empty, b); + TEST_STR_CMP(empty, empty); + } + + void testStrDup() { + WCHAR a[] = { _x('a'), _x('b'), _x('c'), 0 }; + + WCHAR *b = winchar_strdup(a); + + CPPUNIT_ASSERT_EQUAL( 0, winchar_strcmp(a, b) ); + + delete [] b; + } + + void testStoi() { + srand(time(0)); + + for (int i = 0; i < 1000; i++) + { + int r = rand(); + char s[128]; + sprintf(s, "%d", r); + WCHAR *ws = winchar_fromansi(s); + CPPUNIT_ASSERT_EQUAL( r, winchar_stoi(ws) ); + delete [] ws; + } + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION( WinCharTest ); diff --git a/Source/afxres.h b/Source/afxres.h index b9e682f..bf6fa63 100755 --- a/Source/afxres.h +++ b/Source/afxres.h @@ -1,21 +1,21 @@ -/*
- * afxres.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-
-#ifndef IDC_STATIC
-#define IDC_STATIC -1
-#endif
+/* + * afxres.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/Source/boost/checked_delete.hpp b/Source/boost/checked_delete.hpp index adf3991..d7f5212 100755 --- a/Source/boost/checked_delete.hpp +++ b/Source/boost/checked_delete.hpp @@ -1,71 +1,71 @@ -#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
-#define BOOST_CHECKED_DELETE_HPP_INCLUDED
-
-// MS compatible compilers support #pragma once
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-//
-// boost/checked_delete.hpp
-//
-// Copyright (c) 1999, 2000, 2001, 2002 boost.org
-// Copyright (c) 2002, 2003 Peter Dimov
-// Copyright (c) 2003 Daniel Frey
-// Copyright (c) 2003 Howard Hinnant
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
-//
-
-namespace boost
-{
-
-// verify that types are complete for increased safety
-
-template<class T> inline void checked_delete(T * x)
-{
- // intentionally complex - simplification causes regressions
- typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
- (void) sizeof(type_must_be_complete);
- delete x;
-}
-
-template<class T> inline void checked_array_delete(T * x)
-{
- typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
- (void) sizeof(type_must_be_complete);
- delete [] x;
-}
-
-template<class T> struct checked_deleter
-{
- typedef void result_type;
- typedef T * argument_type;
-
- void operator()(T * x) const
- {
- // boost:: disables ADL
- boost::checked_delete(x);
- }
-};
-
-template<class T> struct checked_array_deleter
-{
- typedef void result_type;
- typedef T * argument_type;
-
- void operator()(T * x) const
- {
- boost::checked_array_delete(x);
- }
-};
-
-} // namespace boost
-
-#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
+#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED +#define BOOST_CHECKED_DELETE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/checked_delete.hpp +// +// Copyright (c) 1999, 2000, 2001, 2002 boost.org +// Copyright (c) 2002, 2003 Peter Dimov +// Copyright (c) 2003 Daniel Frey +// Copyright (c) 2003 Howard Hinnant +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/utility/checked_delete.html for documentation. +// + +namespace boost +{ + +// verify that types are complete for increased safety + +template<class T> inline void checked_delete(T * x) +{ + // intentionally complex - simplification causes regressions + typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; + (void) sizeof(type_must_be_complete); + delete x; +} + +template<class T> inline void checked_array_delete(T * x) +{ + typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; + (void) sizeof(type_must_be_complete); + delete [] x; +} + +template<class T> struct checked_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + // boost:: disables ADL + boost::checked_delete(x); + } +}; + +template<class T> struct checked_array_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + boost::checked_array_delete(x); + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED diff --git a/Source/boost/detail/workaround.hpp b/Source/boost/detail/workaround.hpp index 3121928..0d5a2b2 100755 --- a/Source/boost/detail/workaround.hpp +++ b/Source/boost/detail/workaround.hpp @@ -1,74 +1,74 @@ -// Copyright David Abrahams 2002. Permission to copy, use,
-// modify, sell and distribute this software is granted provided this
-// copyright notice appears in all copies. This software is provided
-// "as is" without express or implied warranty, and with no claim as
-// to its suitability for any purpose.
-#ifndef WORKAROUND_DWA2002126_HPP
-# define WORKAROUND_DWA2002126_HPP
-
-// Compiler/library version workaround macro
-//
-// Usage:
-//
-// #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
-// ... // workaround code here
-// #endif
-//
-// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the
-// first argument must be undefined or expand to a numeric
-// value. The above expands to:
-//
-// (BOOST_MSVC) != 0 && (BOOST_MSVC) <= 1200
-//
-// When used for workarounds that apply to the latest known version
-// and all earlier versions of a compiler, the following convention
-// should be observed:
-//
-// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301))
-//
-// The version number in this case corresponds to the last version in
-// which the workaround was known to have been required. When
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro
-// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates
-// the workaround for any version of the compiler. When
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or
-// error will be issued if the compiler version exceeds the argument
-// to BOOST_TESTED_AT(). This can be used to locate workarounds which
-// may be obsoleted by newer versions.
-
-# ifndef BOOST_STRICT_CONFIG
-
-# define BOOST_WORKAROUND(symbol, test) \
- ((symbol != 0) && (1 % (( (symbol test) ) + 1)))
-// ^ ^ ^ ^
-// The extra level of parenthesis nesting above, along with the
-// BOOST_OPEN_PAREN indirection below, is required to satisfy the
-// broken preprocessor in MWCW 8.3 and earlier.
-//
-// The basic mechanism works as follows:
-// (symbol test) + 1 => if (symbol test) then 2 else 1
-// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0
-//
-// The complication with % is for cooperation with BOOST_TESTED_AT().
-// When "test" is BOOST_TESTED_AT(x) and
-// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined,
-//
-// symbol test => if (symbol <= x) then 1 else -1
-// (symbol test) + 1 => if (symbol <= x) then 2 else 0
-// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero
-//
-
-# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS
-# define BOOST_OPEN_PAREN (
-# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1
-# else
-# define BOOST_TESTED_AT(value) != ((value)-(value))
-# endif
-
-# else
-
-# define BOOST_WORKAROUND(symbol, test) 0
-
-# endif
-
-#endif // WORKAROUND_DWA2002126_HPP
+// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef WORKAROUND_DWA2002126_HPP +# define WORKAROUND_DWA2002126_HPP + +// Compiler/library version workaround macro +// +// Usage: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +// ... // workaround code here +// #endif +// +// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the +// first argument must be undefined or expand to a numeric +// value. The above expands to: +// +// (BOOST_MSVC) != 0 && (BOOST_MSVC) <= 1200 +// +// When used for workarounds that apply to the latest known version +// and all earlier versions of a compiler, the following convention +// should be observed: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301)) +// +// The version number in this case corresponds to the last version in +// which the workaround was known to have been required. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro +// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates +// the workaround for any version of the compiler. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or +// error will be issued if the compiler version exceeds the argument +// to BOOST_TESTED_AT(). This can be used to locate workarounds which +// may be obsoleted by newer versions. + +# ifndef BOOST_STRICT_CONFIG + +# define BOOST_WORKAROUND(symbol, test) \ + ((symbol != 0) && (1 % (( (symbol test) ) + 1))) +// ^ ^ ^ ^ +// The extra level of parenthesis nesting above, along with the +// BOOST_OPEN_PAREN indirection below, is required to satisfy the +// broken preprocessor in MWCW 8.3 and earlier. +// +// The basic mechanism works as follows: +// (symbol test) + 1 => if (symbol test) then 2 else 1 +// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0 +// +// The complication with % is for cooperation with BOOST_TESTED_AT(). +// When "test" is BOOST_TESTED_AT(x) and +// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined, +// +// symbol test => if (symbol <= x) then 1 else -1 +// (symbol test) + 1 => if (symbol <= x) then 2 else 0 +// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero +// + +# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS +# define BOOST_OPEN_PAREN ( +# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1 +# else +# define BOOST_TESTED_AT(value) != ((value)-(value)) +# endif + +# else + +# define BOOST_WORKAROUND(symbol, test) 0 + +# endif + +#endif // WORKAROUND_DWA2002126_HPP diff --git a/Source/boost/scoped_array.hpp b/Source/boost/scoped_array.hpp index eb61ad7..e217bae 100755 --- a/Source/boost/scoped_array.hpp +++ b/Source/boost/scoped_array.hpp @@ -1,122 +1,122 @@ -#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
-#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
-
-// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
-// Copyright (c) 2001, 2002 Peter Dimov
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-// http://www.boost.org/libs/smart_ptr/scoped_array.htm
-//
-
-
-// From Boost 1.31.0, http://www.boost.org
-// Modified by Ori Peleg for use in NSIS, to reduce the required Boost includes
-
-#include "checked_delete.hpp"
-#include "detail/workaround.hpp"
-
-#include <cstddef> // for std::ptrdiff_t
-
-namespace boost
-{
-
-// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
-// is guaranteed, either on destruction of the scoped_array or via an explicit
-// reset(). Use shared_array or std::vector if your needs are more complex.
-
-template<class T> class scoped_array // noncopyable
-{
-private:
-
- T * ptr;
-
- scoped_array(scoped_array const &);
- scoped_array & operator=(scoped_array const &);
-
- typedef scoped_array<T> this_type;
-
-public:
-
- typedef T element_type;
-
- explicit scoped_array(T * p = 0) : ptr(p) // never throws
- {
- }
-
- ~scoped_array() // never throws
- {
- boost::checked_array_delete(ptr);
- }
-
- void reset(T * p = 0) // never throws
- {
- assert(p == 0 || p != ptr); // catch self-reset errors
- this_type(p).swap(*this);
- }
-
- T & operator[](std::ptrdiff_t i) const // never throws
- {
- assert(ptr != 0);
- assert(i >= 0);
- return ptr[i];
- }
-
- T * get() const // never throws
- {
- return ptr;
- }
-
- // implicit conversion to "bool"
-
-#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
-
- operator bool () const
- {
- return ptr != 0;
- }
-
-#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
- typedef T * (this_type::*unspecified_bool_type)() const;
-
- operator unspecified_bool_type() const // never throws
- {
- return ptr == 0? 0: &this_type::get;
- }
-
-#else
-
- typedef T * this_type::*unspecified_bool_type;
-
- operator unspecified_bool_type() const // never throws
- {
- return ptr == 0? 0: &this_type::ptr;
- }
-
-#endif
-
- bool operator! () const // never throws
- {
- return ptr == 0;
- }
-
- void swap(scoped_array & b) // never throws
- {
- T * tmp = b.ptr;
- b.ptr = ptr;
- ptr = tmp;
- }
-
-};
-
-template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
-{
- a.swap(b);
-}
-
-} // namespace boost
-
-#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
+#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/scoped_array.htm +// + + +// From Boost 1.31.0, http://www.boost.org +// Modified by Ori Peleg for use in NSIS, to reduce the required Boost includes + +#include "checked_delete.hpp" +#include "detail/workaround.hpp" + +#include <cstddef> // for std::ptrdiff_t + +namespace boost +{ + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template<class T> class scoped_array // noncopyable +{ +private: + + T * ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + typedef scoped_array<T> this_type; + +public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) : ptr(p) // never throws + { + } + + ~scoped_array() // never throws + { + boost::checked_array_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + assert(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + assert(ptr != 0); + assert(i >= 0); + return ptr[i]; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_array & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + +}; + +template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/Source/boost/scoped_ptr.hpp b/Source/boost/scoped_ptr.hpp index eb00c6b..836c197 100755 --- a/Source/boost/scoped_ptr.hpp +++ b/Source/boost/scoped_ptr.hpp @@ -1,137 +1,137 @@ -#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
-#define BOOST_SCOPED_PTR_HPP_INCLUDED
-
-// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
-// Copyright (c) 2001, 2002 Peter Dimov
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
-//
-
-// From Boost 1.31.0, http://www.boost.org
-// Modified by Ori Peleg for use in NSIS, to reduce the required Boost includes
-
-#include <cassert>
-#include "checked_delete.hpp"
-#include "detail/workaround.hpp"
-
-#include <memory> // for std::auto_ptr
-
-namespace boost
-{
-
-// scoped_ptr mimics a built-in pointer except that it guarantees deletion
-// of the object pointed to, either on destruction of the scoped_ptr or via
-// an explicit reset(). scoped_ptr is a simple solution for simple needs;
-// use shared_ptr or std::auto_ptr if your needs are more complex.
-
-template<class T> class scoped_ptr // noncopyable
-{
-private:
-
- T * ptr;
-
- scoped_ptr(scoped_ptr const &);
- scoped_ptr & operator=(scoped_ptr const &);
-
- typedef scoped_ptr<T> this_type;
-
-public:
-
- typedef T element_type;
-
- explicit scoped_ptr(T * p = 0): ptr(p) // never throws
- {
- }
-
- explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release()) // never throws
- {
- }
-
- ~scoped_ptr() // never throws
- {
- boost::checked_delete(ptr);
- }
-
- void reset(T * p = 0) // never throws
- {
- assert(p == 0 || p != ptr); // catch self-reset errors
- this_type(p).swap(*this);
- }
-
- T & operator*() const // never throws
- {
- assert(ptr != 0);
- return *ptr;
- }
-
- T * operator->() const // never throws
- {
- assert(ptr != 0);
- return ptr;
- }
-
- T * get() const // never throws
- {
- return ptr;
- }
-
- // implicit conversion to "bool"
-
-#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
-
- operator bool () const
- {
- return ptr != 0;
- }
-
-#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
- typedef T * (this_type::*unspecified_bool_type)() const;
-
- operator unspecified_bool_type() const // never throws
- {
- return ptr == 0? 0: &this_type::get;
- }
-
-#else
- typedef T * this_type::*unspecified_bool_type;
-
- operator unspecified_bool_type() const // never throws
- {
- return ptr == 0? 0: &this_type::ptr;
- }
-
-#endif
-
- bool operator! () const // never throws
- {
- return ptr == 0;
- }
-
- void swap(scoped_ptr & b) // never throws
- {
- T * tmp = b.ptr;
- b.ptr = ptr;
- ptr = tmp;
- }
-};
-
-template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
-{
- a.swap(b);
-}
-
-// get_pointer(p) is a generic way to say p.get()
-
-template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
-{
- return p.get();
-}
-
-} // namespace boost
-
-#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
+#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm +// + +// From Boost 1.31.0, http://www.boost.org +// Modified by Ori Peleg for use in NSIS, to reduce the required Boost includes + +#include <cassert> +#include "checked_delete.hpp" +#include "detail/workaround.hpp" + +#include <memory> // for std::auto_ptr + +namespace boost +{ + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template<class T> class scoped_ptr // noncopyable +{ +private: + + T * ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr<T> this_type; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0): ptr(p) // never throws + { + } + + explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release()) // never throws + { + } + + ~scoped_ptr() // never throws + { + boost::checked_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + assert(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const // never throws + { + assert(ptr != 0); + return *ptr; + } + + T * operator->() const // never throws + { + assert(ptr != 0); + return ptr; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return ptr != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + +#else + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::ptr; + } + +#endif + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_ptr & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } +}; + +template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws +{ + a.swap(b); +} + +// get_pointer(p) is a generic way to say p.get() + +template<class T> inline T * get_pointer(scoped_ptr<T> const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/Source/build.cpp b/Source/build.cpp index b9caba1..f512f65 100755 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -1,3471 +1,3491 @@ -/*
- * build.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <stdio.h>
-#include "exehead/config.h"
-
-#include "version.h"
-
-#include "build.h"
-#include "util.h"
-#include "fileform.h"
-#include "writer.h"
-#include "crc32.h"
-#include "manifest.h"
-
-#include <stdexcept>
-
-#include "exehead/resource.h"
-#include "ResourceEditor.h"
-#include "DialogTemplate.h"
-#include "ResourceVersionInfo.h"
-
-#ifndef _WIN32
-# include <locale.h>
-# include <unistd.h>
-# include <limits.h>
-# include <stdlib.h>
-# include <stdarg.h>
-#endif
-
-#include <cassert> // for assert
-
-#define RET_UNLESS_OK( function_rc ) do { \
- int rc = (function_rc); \
- if ( rc != PS_OK) \
- return rc; \
-} while (false)
-
-using namespace std;
-
-namespace { // begin anonymous namespace
-
-bool isSimpleChar(char ch)
-{
- return (ch == '.' ) || (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
-}
-
-} // end of anonymous namespace
-
-void CEXEBuild::define(const char *p, const char *v)
-{
- definedlist.add(p,v);
-}
-
-CEXEBuild::~CEXEBuild()
-{
- free(m_unicon_data);
-
- delete [] m_exehead;
-
- int nlt = lang_tables.getlen() / sizeof(LanguageTable);
- LanguageTable *nla = (LanguageTable*)lang_tables.get();
-
- for (int i = 0; i < nlt; i++) {
- DeleteLangTable(nla+i);
- }
-}
-
-CEXEBuild::CEXEBuild() :
- m_exehead(0),
- m_exehead_size(0)
-{
- linecnt = 0;
- fp = 0;
- curfilename = 0;
-
- display_info=1;
- display_script=1;
- display_errors=1;
- display_warnings=1;
-
- cur_ifblock=NULL;
- last_line_had_slash=0;
- inside_comment=false;
- multiple_entries_instruction=0;
-
- build_include_depth=0;
-
- has_called_write_output=false;
-
- ns_func.add("",0); // make sure offset 0 is special on these (i.e. never used by a label)
- ns_label.add("",0);
-
- definedlist.add("NSIS_VERSION", NSIS_VERSION);
-
- // automatically generated header file containing all defines
-#include "defines.h"
-
- // no longer optional
- definedlist.add("NSIS_SUPPORT_STANDARD_PREDEFINES");
- definedlist.add("NSIS_SUPPORT_NAMED_USERVARS");
- definedlist.add("NSIS_SUPPORT_LANG_IN_STRINGS");
-
-#ifdef _WIN32
- definedlist.add("NSIS_WIN32_MAKENSIS");
-#endif
-
- db_opt_save=db_comp_save=db_full_size=db_opt_save_u=db_comp_save_u=db_full_size_u=0;
-
- // Added by Amir Szekely 31st July 2002
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- compressor = &zlib_compressor;
-#endif
- build_compressor_set = false;
- build_compressor_final = false;
-#ifdef NSIS_ZLIB_COMPRESS_WHOLE
- build_compress_whole = true;
-#else
- build_compress_whole = false;
-#endif
- build_compress=1;
- build_compress_level=9;
- build_compress_dict_size=1<<23;
-
- cur_entries=&build_entries;
- cur_instruction_entry_map=&build_instruction_entry_map;
- cur_datablock=&build_datablock;
- cur_datablock_cache=&build_datablock_cache;
- cur_functions=&build_functions;
- cur_labels=&build_labels;
- cur_sections=&build_sections;
- cur_header=&build_header;
- cur_strlist=&build_strlist;
- cur_langtables=&build_langtables;
- cur_ctlcolors=&build_ctlcolors;
- cur_pages=&build_pages;
- cur_page=0;
- cur_page_type=-1;
-
- build_filebuflen=32<<20; // 32mb
-
- sectiongroup_open_cnt=0;
- build_cursection_isfunc=0;
- build_cursection=NULL;
- // init public data.
- build_packname[0]=build_packcmd[0]=build_output_filename[0]=0;
-
- // Added by ramon 23 May 2003
- build_allowskipfiles=1;
-
- // Added by ramon 6 jun 2003
-#ifdef NSIS_SUPPORT_VERSION_INFO
- version_product_v[0]=0;
-#endif
-
- build_overwrite=build_last_overwrite=0;
- build_crcchk=1;
- build_datesave=1;
- build_optimize_datablock=1;
-
- memset(&build_header,-1,sizeof(build_header));
-
- build_header.install_reg_rootkey=0;
- build_header.flags=CH_FLAGS_NO_ROOT_DIR;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- build_header.lb_bg=RGB(0,0,0);
- build_header.lb_fg=RGB(0,255,0);
-#endif
-#ifdef NSIS_CONFIG_LICENSEPAGE
- build_header.license_bg=-COLOR_BTNFACE;
-#endif
- build_header.install_directory_ptr=0;
- build_header.install_directory_auto_append=0;
- build_header.install_reg_key_ptr=0;
- build_header.install_reg_value_ptr=0;
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- memset(build_header.install_types,0,sizeof(build_header.install_types));
-#endif
- memset(&build_header.blocks,0,sizeof(build_header.blocks));
-
- uninstall_mode=0;
- uninstall_size_full=0;
- uninstall_size=-1;
-
- memset(&build_uninst,-1,sizeof(build_uninst));
-
- build_header.install_reg_rootkey=0;
- build_uninst.flags=0;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- build_uninst.lb_bg=RGB(0,0,0);
- build_uninst.lb_fg=RGB(0,255,0);
-#endif
-#ifdef NSIS_CONFIG_LICENSEPAGE
- build_uninst.license_bg=-COLOR_BTNFACE;
-#endif
- build_uninst.install_directory_ptr=0;
- build_uninst.install_directory_auto_append=0;
- build_uninst.install_reg_key_ptr=0;
- build_uninst.install_reg_value_ptr=0;
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- memset(build_uninst.install_types,0,sizeof(build_uninst.install_types));
-#endif
- memset(&build_uninst.blocks,0,sizeof(build_uninst.blocks));
-
- uninstaller_writes_used=0;
-
- build_strlist.add("",0);
- ubuild_strlist.add("",0);
-
- build_langstring_num=0;
- ubuild_langstring_num=0;
-
- build_font[0]=0;
- build_font_size=0;
-
- m_unicon_data=NULL;
- m_unicon_size=0;
-
- branding_image_found=false;
-
- no_space_texts=false;
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- build_plugin_unload=0;
- plugins_processed=0;
-#endif
-
- last_used_lang=NSIS_DEFAULT_LANG;
-
- res_editor=0;
-
- manifest_comctl = manifest::comctl_old;
- manifest_exec_level = manifest::exec_level_none;
-
- enable_last_page_cancel=0;
- uenable_last_page_cancel=0;
-
- license_res_id=IDD_LICENSE;
-
- disable_window_icon=0;
-
- notify_hwnd=0;
-
-#ifdef NSIS_SUPPORT_BGBG
- bg_default_font.lfHeight=40;
- bg_default_font.lfWidth=0;
- bg_default_font.lfEscapement=0;
- bg_default_font.lfOrientation=0;
- bg_default_font.lfWeight=FW_BOLD;
- bg_default_font.lfItalic=TRUE;
- bg_default_font.lfUnderline=FALSE;
- bg_default_font.lfStrikeOut=FALSE;
- bg_default_font.lfCharSet=DEFAULT_CHARSET;
- bg_default_font.lfOutPrecision=OUT_DEFAULT_PRECIS;
- bg_default_font.lfClipPrecision=CLIP_DEFAULT_PRECIS;
- bg_default_font.lfQuality=DEFAULT_QUALITY;
- bg_default_font.lfPitchAndFamily=DEFAULT_PITCH;
- strncpy(bg_default_font.lfFaceName,"Times New Roman",LF_FACESIZE);
- memcpy(&bg_font,&bg_default_font,sizeof(LOGFONT));
-#endif
-
- defcodepage_set=false;
- uDefCodePage=CP_ACP;
-
- InitLangTables();
-
- // Register static user variables $0, $1 and so on
- // with ONE of reference count, to avoid warning on this vars
- char Aux[3];
- int i;
- for (i = 0; i < 10; i++) // 0 - 9
- {
- sprintf(Aux, "%d", i);
- m_UserVarNames.add(Aux,1);
- }
- for (i = 0; i < 10; i++) // 10 - 19
- {
- sprintf(Aux, "R%d", i);
- m_UserVarNames.add(Aux,1);
- }
- m_UserVarNames.add("CMDLINE",1); // 20 everything before here doesn't have trailing slash removal
- m_UserVarNames.add("INSTDIR",1); // 21
- m_UserVarNames.add("OUTDIR",1); // 22
- m_UserVarNames.add("EXEDIR",1); // 23
- m_UserVarNames.add("LANGUAGE",1); // 24
- m_UserVarNames.add("TEMP",-1); // 25
- m_UserVarNames.add("PLUGINSDIR",-1); // 26
- m_UserVarNames.add("EXEPATH",-1); // 27
- m_UserVarNames.add("EXEFILE",-1); // 28
- m_UserVarNames.add("HWNDPARENT",-1); // 29
- m_UserVarNames.add("_CLICK",-1); // 30
- m_UserVarNames.add("_OUTDIR",1); // 31
-
- m_iBaseVarsNum = m_UserVarNames.getnum();
-
- m_ShellConstants.add("WINDIR",CSIDL_WINDOWS,CSIDL_WINDOWS);
- m_ShellConstants.add("SYSDIR",CSIDL_SYSTEM,CSIDL_SYSTEM);
- m_ShellConstants.add("SMPROGRAMS",CSIDL_PROGRAMS, CSIDL_COMMON_PROGRAMS);
- m_ShellConstants.add("SMSTARTUP",CSIDL_STARTUP, CSIDL_COMMON_STARTUP);
- m_ShellConstants.add("DESKTOP",CSIDL_DESKTOPDIRECTORY, CSIDL_COMMON_DESKTOPDIRECTORY);
- m_ShellConstants.add("STARTMENU",CSIDL_STARTMENU, CSIDL_COMMON_STARTMENU);
- m_ShellConstants.add("QUICKLAUNCH", CSIDL_APPDATA, CSIDL_APPDATA);
- m_ShellConstants.add("DOCUMENTS",CSIDL_PERSONAL, CSIDL_COMMON_DOCUMENTS);
- m_ShellConstants.add("SENDTO",CSIDL_SENDTO, CSIDL_SENDTO);
- m_ShellConstants.add("RECENT",CSIDL_RECENT, CSIDL_RECENT);
- m_ShellConstants.add("FAVORITES",CSIDL_FAVORITES, CSIDL_COMMON_FAVORITES);
- m_ShellConstants.add("MUSIC",CSIDL_MYMUSIC, CSIDL_COMMON_MUSIC);
- m_ShellConstants.add("PICTURES",CSIDL_MYPICTURES, CSIDL_COMMON_PICTURES);
- m_ShellConstants.add("VIDEOS",CSIDL_MYVIDEO, CSIDL_COMMON_VIDEO);
- m_ShellConstants.add("NETHOOD", CSIDL_NETHOOD, CSIDL_NETHOOD);
- m_ShellConstants.add("FONTS", CSIDL_FONTS, CSIDL_FONTS);
- m_ShellConstants.add("TEMPLATES", CSIDL_TEMPLATES, CSIDL_COMMON_TEMPLATES);
- m_ShellConstants.add("APPDATA", CSIDL_APPDATA, CSIDL_COMMON_APPDATA);
- m_ShellConstants.add("LOCALAPPDATA", CSIDL_LOCAL_APPDATA, CSIDL_LOCAL_APPDATA);
- m_ShellConstants.add("PRINTHOOD", CSIDL_PRINTHOOD, CSIDL_PRINTHOOD);
- //m_ShellConstants.add("ALTSTARTUP", CSIDL_ALTSTARTUP, CSIDL_COMMON_ALTSTARTUP);
- m_ShellConstants.add("INTERNET_CACHE", CSIDL_INTERNET_CACHE, CSIDL_INTERNET_CACHE);
- m_ShellConstants.add("COOKIES", CSIDL_COOKIES, CSIDL_COOKIES);
- m_ShellConstants.add("HISTORY", CSIDL_HISTORY, CSIDL_HISTORY);
- m_ShellConstants.add("PROFILE", CSIDL_PROFILE, CSIDL_PROFILE);
- m_ShellConstants.add("ADMINTOOLS", CSIDL_ADMINTOOLS, CSIDL_COMMON_ADMINTOOLS);
- m_ShellConstants.add("RESOURCES", CSIDL_RESOURCES, CSIDL_RESOURCES);
- m_ShellConstants.add("RESOURCES_LOCALIZED", CSIDL_RESOURCES_LOCALIZED, CSIDL_RESOURCES_LOCALIZED);
- m_ShellConstants.add("CDBURN_AREA", CSIDL_CDBURN_AREA, CSIDL_CDBURN_AREA);
-
- unsigned int program_files = add_string("ProgramFilesDir", 0);
- unsigned int program_files_def = add_string("C:\\Program Files");
-
- if ((program_files >= 0x40) || (program_files_def >= 0xFF))
- {
- // see Source\exehead\util.c for implementation details
- // basically, it knows it needs to get folders from the registry when the 0x80 is on
- ERROR_MSG("Internal compiler error: too many strings added to strings block before adding shell constants!\n");
- throw out_of_range("Internal compiler error: too many strings added to strings block before adding shell constants!");
- }
-
- m_ShellConstants.add("PROGRAMFILES", 0x80 | program_files, program_files_def);
- m_ShellConstants.add("PROGRAMFILES32", 0x80 | program_files, program_files_def);
- m_ShellConstants.add("PROGRAMFILES64", 0xC0 | program_files, program_files_def);
-
- unsigned int common_files = add_string("CommonFilesDir", 0);
- unsigned int common_files_def = add_string("$PROGRAMFILES\\Common Files");
-
- if ((common_files > 0x40) || (common_files_def > 0xFF))
- {
- ERROR_MSG("Internal compiler error: too many strings added to strings block before adding shell constants!\n");
- throw out_of_range("Internal compiler error: too many strings added to strings block before adding shell constants!");
- }
-
- m_ShellConstants.add("COMMONFILES", 0x80 | common_files, common_files_def);
- m_ShellConstants.add("COMMONFILES32", 0x80 | common_files, common_files_def);
- m_ShellConstants.add("COMMONFILES64", 0xC0 | common_files, common_files_def);
-
- set_uninstall_mode(1);
-
- unsigned int uprogram_files = add_string("ProgramFilesDir", 0);
- unsigned int uprogram_files_def = add_string("C:\\Program Files");
- unsigned int ucommon_files = add_string("CommonFilesDir", 0);
- unsigned int ucommon_files_def = add_string("$PROGRAMFILES\\Common Files");
-
- if (uprogram_files != program_files
- || uprogram_files_def != program_files_def
- || ucommon_files != common_files
- || ucommon_files_def != common_files_def)
- {
- ERROR_MSG("Internal compiler error: installer's shell constants are different than uninstallers!\n");
- throw out_of_range("Internal compiler error: installer's shell constants are different than uninstallers!");
- }
-
- set_uninstall_mode(0);
-
- set_code_type_predefines();
-}
-
-void CEXEBuild::initialize(const char *makensis_path)
-{
- string nsis_dir;
- const char *dir = getenv("NSISDIR");
- if (dir) nsis_dir = dir;
- else {
-#ifndef NSIS_CONFIG_CONST_DATA_PATH
- nsis_dir = get_executable_dir(makensis_path);
-#else
- nsis_dir = PREFIX_DATA;
-#endif
- }
- definedlist.add("NSISDIR", nsis_dir.c_str());
-
- string includes_dir = nsis_dir;
- includes_dir += PLATFORM_PATH_SEPARATOR_STR"Include";
- include_dirs.add(includes_dir.c_str(),0);
-
- stubs_dir = nsis_dir;
- stubs_dir += PLATFORM_PATH_SEPARATOR_STR"Stubs";
-
- if (set_compressor("zlib", false) != PS_OK)
- {
- throw runtime_error("error setting default stub");
- }
-
- string uninst = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + "uninst";
- m_unicon_data = generate_uninstall_icon_data(uninst.c_str(), m_unicon_size);
- if (!m_unicon_data)
- {
- throw runtime_error("invalid default uninstall icon");
- }
-}
-
-
-int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); }
-
-// returns offset in stringblock
-int CEXEBuild::add_string(const char *string, int process/*=1*/, WORD codepage/*=CP_ACP*/)
-{
- if (!string || !*string) return 0;
-
- if (*string == '$' && *(string+1) == '(') {
- int idx = 0;
- char *cp = strdup(string+2);
- char *p = strchr(cp, ')');
- if (p && p[1] == '\0' ) { // if string is only a language str identifier
- *p = 0;
- idx = DefineLangString(cp, process);
- }
- free(cp);
- if (idx < 0) return idx;
- }
-
- if (!process) return cur_strlist->add(string,2);
-
- char buf[NSIS_MAX_STRLEN*4];
- preprocess_string(buf,string,codepage);
- return cur_strlist->add(buf,2);
-}
-
-int CEXEBuild::add_intstring(const int i) // returns offset in stringblock
-{
- char i_str[1024];
- wsprintf(i_str, "%d", i);
- return add_string(i_str);
-}
-
-// based on Dave Laundon's code
-int CEXEBuild::preprocess_string(char *out, const char *in, WORD codepage/*=CP_ACP*/)
-{
- const char *p=in;
- while (*p)
- {
- const char *np = CharNextExA(codepage, p, 0);
- if (np - p > 1) // multibyte char
- {
- int l = np - p;
- while (l--)
- {
- unsigned char i = (unsigned char)*p++;
- if (i >= NS_CODES_START) {
- *out++ = (char)NS_SKIP_CODE;
- }
- *out++=(char)i;
- }
- continue;
- }
-
- unsigned char i = (unsigned char)*p;
-
- p=np;
-
- // Test for characters extending into the variable codes
- if (i >= NS_CODES_START) {
- *out++ = (char)NS_SKIP_CODE;
- }
- else if (i == '$')
- {
- if (*p == '$')
- p++; // Can simply convert $$ to $ now
- else
- {
- {
- bool bProceced=false;
- if ( *p )
- {
- const char *pUserVarName = p;
- while (isSimpleChar(*pUserVarName))
- pUserVarName++;
-
- while (pUserVarName > p)
- {
- if (m_ShellConstants.get((char*)p, pUserVarName-p) >= 0)
- break; // Upps it's a shell constant
-
- int idxUserVar = m_UserVarNames.get((char*)p, pUserVarName-p);
- if (idxUserVar >= 0)
- {
- // Well, using variables inside string formating doens't mean
- // using the variable, beacuse it will be always an empty string
- // which is also memory wasting
- // So the line below must be commented !??
- //m_UserVarNames.inc_reference(idxUserVar);
- *out++ = (char) NS_VAR_CODE; // Named user variable;
- WORD w = FIX_ENDIAN_INT16(CODE_SHORT(idxUserVar));
- memcpy(out, &w, sizeof(WORD));
- out += sizeof(WORD);
- p += pUserVarName-p;
- bProceced = true;
- break;
- }
- pUserVarName--;
- }
- }
- if (!bProceced && *p)
- {
- const char *pShellConstName = p;
- while (isSimpleChar(*pShellConstName))
- pShellConstName++;
-
- while (pShellConstName > p)
- {
- int idxConst = m_ShellConstants.get((char*)p, pShellConstName - p);
- if (idxConst >= 0)
- {
- int CSIDL_Value_current = m_ShellConstants.get_value1(idxConst);
- int CSIDL_Value_all = m_ShellConstants.get_value2(idxConst);
- *out++=(char)NS_SHELL_CODE; // Constant code identifier
- *out++=(char)CSIDL_Value_current;
- *out++=(char)CSIDL_Value_all;
- p = pShellConstName;
- bProceced = true;
- break;
- }
- pShellConstName--;
- }
- }
- if ( !bProceced && *p == '(' )
- {
- int idx = -1;
- char *cp = strdup(p+1);
- char *pos = strchr(cp, ')');
- if (pos)
- {
- *pos = 0;
- idx = DefineLangString(cp);
- if (idx < 0)
- {
- *out++ = (char)NS_LANG_CODE; // Next word is lang-string Identifier
- WORD w = FIX_ENDIAN_INT16(CODE_SHORT(-idx-1));
- memcpy(out, &w, sizeof(WORD));
- out += sizeof(WORD);
- p += strlen(cp) + 2;
- bProceced = true;
- }
- }
- free(cp);
- }
- if ( bProceced )
- continue;
- else
- {
- char tbuf[64];
- char cBracket = '\0';
- bool bDoWarning = true;
-
- if ( *p == '[' )
- cBracket = ']';
- else if ( *p == '(' )
- cBracket = ')';
- else if ( *p == '{' )
- cBracket = '}';
-
- strncpy(tbuf,p,63);
- tbuf[63]=0;
-
- if ( cBracket != 0 )
- {
- if (strchr(tbuf,cBracket)) (strchr(tbuf,cBracket)+1)[0]=0;
- if ( tbuf[0] == '{' && tbuf[strlen(tbuf)-1] == '}' )
- {
- char *tstIfDefine = strdup(tbuf+1);
- tstIfDefine[strlen(tstIfDefine)-1] = '\0';
- bDoWarning = definedlist.find(tstIfDefine) == NULL;
- }
- }
- else
- {
- if (strstr(tbuf," ")) strstr(tbuf," ")[0]=0;
- }
- if ( bDoWarning )
- warning_fl("unknown variable/constant \"%s\" detected, ignoring",tbuf);
- i = '$';
- }
- }
- }
- }
- *out++=(char)i;
- }
- *out=0;
- return 0;
-}
-
-// what it does is, when you pass it the offset of the last item added, it will determine if
-// that data is already present in the datablock, and if so, reference it instead (and shorten
-// the datablock as necessary). Reduces overhead if you want to add files to a couple places.
-// Woo, an optimizing installer generator, now we're styling.
-
-int CEXEBuild::datablock_optimize(int start_offset, int first_int)
-{
- int this_len = cur_datablock->getlen() - start_offset;
-
- cached_db_size this_size = {first_int, start_offset};
- cur_datablock_cache->add(&this_size, sizeof(cached_db_size));
-
- if (!build_optimize_datablock || this_len < (int) sizeof(int))
- return start_offset;
-
- MMapBuf *db = (MMapBuf *) cur_datablock;
- db->setro(TRUE);
-
- cached_db_size *db_sizes = (cached_db_size *) cur_datablock_cache->get();
- int db_sizes_num = cur_datablock_cache->getlen() / sizeof(cached_db_size);
- db_sizes_num--; // don't compare with the one we just added
-
- for (int i = 0; i < db_sizes_num; i++)
- {
- if (db_sizes[i].first_int == first_int)
- {
- int pos = db_sizes[i].start_offset;
- int left = this_len;
- while (left > 0)
- {
- int l = min(left, build_filebuflen);
- void *newstuff = db->get(start_offset + this_len - left, l);
- void *oldstuff = db->getmore(pos + this_len - left, l);
-
- int res = memcmp(newstuff, oldstuff, l);
-
- db->release(oldstuff, l);
- db->release();
-
- if (res)
- {
- break;
- }
-
- left -= l;
- }
-
- if (!left)
- {
- db_opt_save += this_len;
- db->resize(max(start_offset, pos + this_len));
- db->setro(FALSE);
- cur_datablock_cache->resize(cur_datablock_cache->getlen() - sizeof(cached_db_size));
- return pos;
- }
- }
- }
-
- db->setro(FALSE);
-
- return start_offset;
-}
-
-int CEXEBuild::add_db_data(IMMap *mmap) // returns offset
-{
- build_compressor_set = true;
-
- int done = 0;
-
- if (!mmap)
- {
- ERROR_MSG("Error: add_db_data() called with invalid mapped file\n");
- return -1;
- }
-
- int length = mmap->getsize();
-
- if (length < 0)
- {
- ERROR_MSG("Error: add_db_data() called with length=%d\n", length);
- return -1;
- }
-
- MMapBuf *db = (MMapBuf *) cur_datablock;
-
- int st = db->getlen();
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (length && !build_compress_whole && build_compress)
- {
- // grow datablock so that there is room to compress into
- int bufferlen = length + 1024 + length / 4; // give a nice 25% extra space
- db->resize(st + bufferlen + sizeof(int));
-
- int n = compressor->Init(build_compress_level, build_compress_dict_size);
- if (n != C_OK)
- {
- ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n);
- extern void quit(); quit();
- }
-
- int avail_in = length;
- int avail_out = bufferlen;
- int ret;
- while (avail_in > 0)
- {
- int in_len = min(build_filebuflen, avail_in);
- int out_len = min(build_filebuflen, avail_out);
-
- compressor->SetNextIn((char *) mmap->get(length - avail_in, in_len), in_len);
- compressor->SetNextOut((char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len), out_len);
- if ((ret = compressor->Compress(0)) < 0)
- {
- ERROR_MSG("Error: add_db_data() - compress() failed(%s [%d])\n", compressor->GetErrStr(ret), ret);
- return -1;
- }
- mmap->release();
- db->flush(out_len);
- db->release();
- avail_in -= in_len - compressor->GetAvailIn();
- avail_out -= out_len - compressor->GetAvailOut();
-
- if (!avail_out)
- // not enough space in the output buffer - no compression is better
- break;
- }
-
- // if not enough space in the output buffer - no compression is better
- if (avail_out)
- {
- char *out;
-
- char a;
- compressor->SetNextIn(&a,0);
-
- do
- {
- int out_len = min(build_filebuflen, avail_out);
-
- out = (char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len);
-
- compressor->SetNextOut(out, out_len);
- if ((ret = compressor->Compress(C_FINISH)) < 0)
- {
- ERROR_MSG("Error: add_db_data() - compress() failed(%s [%d])\n", compressor->GetErrStr(ret), ret);
- return -1;
- }
-
- db->flush(out_len);
- db->release();
-
- avail_out -= out_len - compressor->GetAvailOut();
- }
- while (compressor->GetNextOut() - out > 0 && avail_out > 0);
-
- compressor->End();
-
- int used = bufferlen - avail_out;
-
- // never store compressed if output buffer is full (compression increased the size...)
- if (avail_out && (build_compress == 2 || used < length))
- {
- done=1;
- db->resize(st + used + sizeof(int));
-
- *(int*)db->get(st, sizeof(int)) = FIX_ENDIAN_INT32(used | 0x80000000);
- db->release();
-
- int nst = datablock_optimize(st, used | 0x80000000);
- if (nst == st) db_comp_save += length - used;
- else st = nst;
- }
- }
- else
- compressor->End();
- }
-#endif // NSIS_CONFIG_COMPRESSION_SUPPORT
-
- if (!done)
- {
- db->resize(st + length + sizeof(int));
- int *plen = (int *) db->get(st, sizeof(int));
- *plen = FIX_ENDIAN_INT32(length);
- db->release();
-
- int left = length;
- while (left > 0)
- {
- int l = min(build_filebuflen, left);
- int *p = (int *) db->get(st + sizeof(int) + length - left, l);
- memcpy(p, mmap->get(length - left, l), l);
- db->flush(l);
- db->release();
- mmap->release();
- left -= l;
- }
-
- st = datablock_optimize(st, length);
- }
-
- db_full_size += length + sizeof(int);
-
- return st;
-}
-
-int CEXEBuild::add_db_data(const char *data, int length) // returns offset
-{
- MMapFake fakemap;
- fakemap.set(data, length);
- return add_db_data(&fakemap);
-}
-
-int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // returns offset
-{
- build_compressor_set=true;
-
- int done=0;
-
- if (length < 0)
- {
- ERROR_MSG("Error: add_data() called with length=%d\n",length);
- return -1;
- }
-
- int st=dblock->getlen();
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (!build_compress_whole && build_compress)
- {
- // grow datablock so that there is room to compress into
- int bufferlen=length+1024+length/4; // give a nice 25% extra space
- dblock->resize(st+bufferlen+sizeof(int));
-
- int n = compressor->Init(build_compress_level, build_compress_dict_size);
- if (n != C_OK)
- {
- ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n);
- extern void quit(); quit();
- }
-
- compressor->SetNextIn((char*)data, length);
- compressor->SetNextOut((char*)dblock->get() + st + sizeof(int), bufferlen);
-
- compressor->Compress(C_FINISH);
-
- int used=bufferlen-compressor->GetAvailOut();
-
- // never store compressed if output buffer is full
- if (compressor->GetAvailOut() && (build_compress == 2 || used < length))
- {
- done=1;
- dblock->resize(st+used+sizeof(int));
-
- *((int*)((char *)dblock->get()+st)) = FIX_ENDIAN_INT32(used|0x80000000);
- }
- compressor->End();
- }
-#endif // NSIS_CONFIG_COMPRESSION_SUPPORT
-
- if (!done)
- {
- dblock->resize(st);
- int rl = FIX_ENDIAN_INT32(length);
- dblock->add(&rl,sizeof(int));
- dblock->add(data,length);
- }
-
- return st;
-}
-
-int CEXEBuild::add_label(const char *name)
-{
- if (!build_cursection)
- {
- ERROR_MSG("Error: Label declaration not valid outside of function/section\n");
- return PS_ERROR;
- }
- if ((name[0] >= '0' && name[0] <= '9') || name[0] == '-' || name[0] == ' ' || name[0] == ':')
- {
- ERROR_MSG("Error: labels must not begin with 0-9, -, :, or a space.\n");
- return PS_ERROR;
- }
-
- int cs=build_cursection->code;
- int ce=cs+build_cursection->code_size;
-
- char *p=strdup(name);
- if (p[strlen(p)-1] == ':') p[strlen(p)-1]=0;
- int offs=ns_label.add(p,0);
- free(p);
-
- int n=cur_labels->getlen()/sizeof(section);
- if (n)
- {
- section *t=(section*)cur_labels->get();
- while (n--)
- {
- if ((*name == '.' || (t->code >= cs && t->code <= ce)) &&
- t->name_ptr==offs)
- {
- if (*name == '.') ERROR_MSG("Error: global label \"%s\" already declared\n",name);
- else
- {
- char *t = "section";
- if (build_cursection_isfunc)
- t = "function";
- ERROR_MSG("Error: label \"%s\" already declared in %s\n",name,t);
- }
- return PS_ERROR;
- }
- t++;
- }
- }
-
- section s={0};
- s.name_ptr = offs;
- s.code = ce;
- cur_labels->add(&s,sizeof(s));
-
- return PS_OK;
-}
-
-int CEXEBuild::add_function(const char *funname)
-{
- if (build_cursection_isfunc)
- {
- ERROR_MSG("Error: Function open when creating function (use FunctionEnd first)\n");
- return PS_ERROR;
- }
- if (build_cursection)
- {
- ERROR_MSG("Error: Section open when creating function (use SectionEnd first)\n");
- return PS_ERROR;
- }
- if (cur_page)
- {
- ERROR_MSG("Error: PageEx open when creating function (use PageExEnd first)\n");
- return PS_ERROR;
- }
- if (!funname[0])
- {
- ERROR_MSG("Error: Function must have a name\n");
- return PS_ERROR;
- }
-
- set_uninstall_mode(!strnicmp(funname,"un.",3));
-
- int addr=ns_func.add(funname,0);
- int x;
- int n=cur_functions->getlen()/sizeof(section);
- section *tmp=(section*)cur_functions->get();
- for (x = 0; x < n; x ++)
- {
- if (tmp[x].name_ptr == addr)
- {
- ERROR_MSG("Error: Function named \"%s\" already exists.\n",funname);
- return PS_ERROR;
- }
- }
-
- cur_functions->resize((n+1)*sizeof(section));
- build_cursection=((section*)cur_functions->get())+n;
- build_cursection_isfunc=1;
- build_cursection->name_ptr=addr;
- build_cursection->code=cur_entries->getlen()/sizeof(entry);
- build_cursection->code_size=0;
- build_cursection->install_types=0;
- build_cursection->flags=0;
- build_cursection->size_kb=0;
- memset(build_cursection->name,0,sizeof(build_cursection->name));
-
- if (uninstall_mode)
- set_code_type_predefines(funname+3);
- else
- set_code_type_predefines(funname);
-
- return PS_OK;
-}
-
-int CEXEBuild::function_end()
-{
- if (!build_cursection_isfunc)
- {
- ERROR_MSG("Error: No function open, FunctionEnd called\n");
- return PS_ERROR;
- }
- // add ret.
- add_entry_direct(EW_RET);
-
- build_cursection_isfunc=0;
- build_cursection=NULL;
-
- set_uninstall_mode(0);
-
- set_code_type_predefines();
- return PS_OK;
-}
-
-
-int CEXEBuild::section_add_flags(int flags)
-{
- if (!build_cursection || build_cursection_isfunc)
- {
- ERROR_MSG("Error: can't modify flags when no section is open\n");
- return PS_ERROR;
- }
- build_cursection->flags |= flags;
- return PS_OK;
-}
-
-int CEXEBuild::section_add_install_type(int inst_type)
-{
- if (!build_cursection || build_cursection_isfunc)
- {
- ERROR_MSG("Error: can't modify flags when no section is open\n");
- return PS_ERROR;
- }
- if (build_cursection->install_types == ~0)
- build_cursection->install_types = 0;
- build_cursection->install_types |= inst_type;
- return PS_OK;
-}
-
-void CEXEBuild::section_add_size_kb(int kb)
-{
- if (build_cursection)
- {
- build_cursection->size_kb+=kb;
- }
-}
-
-int CEXEBuild::section_end()
-{
- if (build_cursection_isfunc)
- {
- ERROR_MSG("Error: SectionEnd specified in function (not section)\n");
- return PS_ERROR;
- }
- if (!build_cursection)
- {
- ERROR_MSG("Error: SectionEnd specified and no sections open\n");
- return PS_ERROR;
- }
- add_entry_direct(EW_RET);
- build_cursection->code_size--;
- build_cursection=NULL;
- if (!sectiongroup_open_cnt)
- set_uninstall_mode(0);
-
- set_code_type_predefines();
- return PS_OK;
-}
-
-int CEXEBuild::add_section(const char *secname, const char *defname, int expand/*=0*/)
-{
- if (build_cursection_isfunc)
- {
- ERROR_MSG("Error: Section can't create section (already in function, use FunctionEnd first)\n");
- return PS_ERROR;
- }
- if (cur_page) {
- ERROR_MSG("Error: PageEx already open, call PageExEnd first\n");
- return PS_ERROR;
- }
- if (build_cursection)
- {
- ERROR_MSG("Error: Section already open, call SectionEnd first\n");
- return PS_ERROR;
- }
-
- section new_section;
- new_section.flags = SF_SELECTED;
- new_section.flags |= expand ? SF_EXPAND : 0;
- new_section.code_size = 0;
- new_section.size_kb = 0;
-
- char *name = (char*)secname;
-
- if (secname[0] == '-')
- {
- if (secname[1])
- {
- new_section.flags |= SF_SECGRP;
- name++;
- }
- else
- new_section.flags |= SF_SECGRPEND;
- }
-
- if (name[0] == '!')
- {
- name++;
- new_section.flags |= SF_BOLD;
- }
-
- int old_uninstall_mode = uninstall_mode;
-
- set_uninstall_mode(0);
-
- if (!strnicmp(name, "un.", 3))
- {
- set_uninstall_mode(1);
- name += 3;
- }
-
- if (!stricmp(name, "uninstall"))
- {
- set_uninstall_mode(1);
- }
-
- if ((new_section.flags & SF_SECGRPEND) && sectiongroup_open_cnt && old_uninstall_mode)
- {
- set_uninstall_mode(1);
- }
-
- if (sectiongroup_open_cnt)
- {
- if (uninstall_mode != old_uninstall_mode)
- {
- ERROR_MSG("Error: Can't create %s section in %s section group (use SectionGroupEnd first)\n", uninstall_mode ? "uninstaller" : "installer", old_uninstall_mode ? "uninstaller" : "installer");
- return PS_ERROR;
- }
- }
-
- new_section.code = cur_entries->getlen() / sizeof(entry);
-
- new_section.install_types = *name ? 0 : ~0;
- new_section.name_ptr = add_string(name);
- memset(&new_section.name,0,sizeof(new_section.name));
-
- cur_sections->add(&new_section, sizeof(section));
- build_cursection = (section *) cur_sections->get() + cur_header->blocks[NB_SECTIONS].num;
-
- if (defname[0])
- {
- char buf[1024];
- wsprintf(buf, "%d", cur_header->blocks[NB_SECTIONS].num);
- if (definedlist.add(defname, buf))
- {
- ERROR_MSG("Error: \"%s\" already defined, can't assign section index!\n", defname);
- return PS_ERROR;
- }
- }
-
- cur_header->blocks[NB_SECTIONS].num++;
-
- if (new_section.flags & (SF_SECGRP | SF_SECGRPEND))
- {
- add_entry_direct(EW_RET);
- build_cursection->code_size = 0;
-
- build_cursection = 0;
-
- if (new_section.flags & SF_SECGRPEND)
- {
- sectiongroup_open_cnt--;
- if (sectiongroup_open_cnt < 0)
- {
- ERROR_MSG("SectionGroupEnd: no SectionGroups are open\n");
- return PS_ERROR;
- }
- if (!sectiongroup_open_cnt)
- {
- set_uninstall_mode(0);
- }
- }
- else
- sectiongroup_open_cnt++;
- }
-
- set_code_type_predefines(name);
-
- return PS_OK;
-}
-
-int CEXEBuild::add_entry(const entry *ent)
-{
- if (!build_cursection && !uninstall_mode)
- {
- ERROR_MSG("Error: Can't add entry, no section or function is open!\n");
- return PS_ERROR;
- }
-
- cur_entries->add(ent,sizeof(entry));
- cur_instruction_entry_map->add(&multiple_entries_instruction,sizeof(int));
- build_cursection->code_size++;
- cur_header->blocks[NB_ENTRIES].num++;
-
- multiple_entries_instruction=1;
-
- return PS_OK;
-}
-
-int CEXEBuild::add_entry_direct(int which, int o0, int o1, int o2, int o3, int o4, int o5 /*o#=0*/)
-{
- entry ent;
- ent.which = which;
- ent.offsets[0] = o0;
- ent.offsets[1] = o1;
- ent.offsets[2] = o2;
- ent.offsets[3] = o3;
- ent.offsets[4] = o4;
- ent.offsets[5] = o5;
- return add_entry(&ent);
-}
-
-int CEXEBuild::resolve_jump_int(const char *fn, int *a, int offs, int start, int end)
-{
- if (*a > 0)
- {
- char *lname=(char*)ns_label.get()+*a;
- if (lname[0] == '-' || lname[0]=='+')
- {
- int jump = atoi(lname);
- int *skip_map = (int *) cur_instruction_entry_map->get();
- int maxoffs = cur_instruction_entry_map->getlen() / (int) sizeof(int);
-
- int direction = 1;
- if (jump < 0)
- direction = -1;
-
- for (; jump != 0; jump -= direction)
- {
- offs += direction;
- if (offs >= 0 && offs < maxoffs)
- {
- while (skip_map[offs])
- {
- offs += direction;
- }
- }
- }
-
- *a = offs + 1;
- }
- else
- {
- section *s = (section*)cur_labels->get();
- int n=cur_labels->getlen()/sizeof(section);
- while (n-->0)
- {
- if ((*lname == '.' || (s->code >= start && s->code <= end)) && s->name_ptr == *a)
- {
- *a = s->code+1; // jumps are to the absolute position, +1 (to differentiate between no jump, and jumping to offset 0)
- s->flags++;
- return 0;
- }
- s++;
- }
-
- ERROR_MSG("Error: could not resolve label \"%s\" in %s\n",lname,fn);
- return 1;
- }
- }
- else if (*a < 0) // to jump to a user variable target, -variable_index-1 is already stored.
- {
- }
- // otherwise, *a is 0, which means no jump and we also leave it intact
- return 0;
-}
-
-int CEXEBuild::resolve_call_int(const char *fn, const char *str, int fptr, int *ofs)
-{
- if (fptr < 0) return 0;
- int nf=cur_functions->getlen()/sizeof(section);
- section *sec=(section *)cur_functions->get();
- while (nf-- > 0)
- {
- if (sec->name_ptr>0 && sec->name_ptr == fptr)
- {
- ofs[0]=sec->code;
- sec->flags++;
- return 0;
- }
- sec++;
- }
- ERROR_MSG("Error: resolving %s function \"%s\" in %s\n",str,(char*)ns_func.get()+fptr,fn);
- ERROR_MSG("Note: uninstall functions must begin with \"un.\", and install functions must not\n");
- return 1;
-}
-
-int CEXEBuild::resolve_instruction(const char *fn, const char *str, entry *w, int offs, int start, int end)
-{
- if (w->which == EW_NOP)
- {
- if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1;
- }
-#ifdef NSIS_SUPPORT_MESSAGEBOX
- else if (w->which == EW_MESSAGEBOX)
- {
- if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[5],offs,start,end)) return 1;
- }
-#endif
- else if (w->which == EW_IFFILEEXISTS)
- {
- if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1;
- }
- else if (w->which == EW_IFFLAG)
- {
- if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1;
- }
-#ifdef NSIS_SUPPORT_STROPTS
- else if (w->which == EW_STRCMP)
- {
- if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1;
- }
-#endif
-#ifdef NSIS_SUPPORT_INTOPTS
- else if (w->which == EW_INTCMP)
- {
- if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[4],offs,start,end)) return 1;
- }
-#endif
-#ifdef NSIS_SUPPORT_HWNDS
- else if (w->which == EW_ISWINDOW)
- {
- if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1;
- if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1;
- }
-#endif
- else if (w->which == EW_CALL)
- {
- if (w->offsets[0] >= 0 && w->offsets[1]) // get as jump
- {
- if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1;
- }
- else
- {
- if (w->offsets[0] >= 0 && resolve_call_int(fn,str,w->offsets[0],w->offsets)) return 1;
- // if w->offsets[0] >= 0, EW_CALL requires that it 1-based.
- // otherwise, if < 0, it needs an increment anyway (since it
- // was encoded with a -2 base, to prevent it looking like an
- // empty string "")
- w->offsets[0]++;
- }
- }
-#ifdef NSIS_SUPPORT_STROPTS
- else if (w->which == EW_GETFUNCTIONADDR)
- {
- if (w->offsets[1] < 0)
- {
- ERROR_MSG("Error: GetFunctionAddress requires a real function to get address of.\n");
- return 1;
- }
-
- if (resolve_call_int(fn,str,w->offsets[1],&w->offsets[1])) return 1;
-
- w->which=EW_ASSIGNVAR;
- w->offsets[1]=add_intstring(w->offsets[1]+1); // +1 here to make 1-based.
- }
- else if (w->which == EW_GETLABELADDR)
- {
- if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1;
- w->which=EW_ASSIGNVAR;
- w->offsets[1]=add_intstring(w->offsets[1]);
- }
-#endif
- return 0;
-}
-
-int CEXEBuild::resolve_coderefs(const char *str)
-{
- // resolve jumps&calls
- {
- section *sec=(section *)cur_functions->get();
- int l=cur_functions->getlen()/sizeof(section);
- entry *w=(entry *)cur_entries->get();
- while (l-- > 0)
- {
- int x;
- for (x = sec->code; x < sec->code+sec->code_size; x ++)
- {
- char fname[1024];
- wsprintf(fname,"function \"%s\"",ns_func.get()+sec->name_ptr);
- if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) return 1;
- }
- sec++;
- }
-
- int cnt=0;
- sec=(section *)cur_sections->get();
- l=cur_sections->getlen()/sizeof(section);
- while (l-- > 0)
- {
- int x=sec->name_ptr;
- char fname[1024];
- const char *section_name;
- if (x < 0)
- {
- // lang string
- section_name = "$(lang string)";
- }
- else
- {
- // normal string
- section_name = cur_strlist->get() + x;
- }
- if (x) wsprintf(fname,"%s section \"%s\" (%d)",str,section_name,cnt);
- else wsprintf(fname,"unnamed %s section (%d)",str,cnt);
- for (x = sec->code; x < sec->code+sec->code_size; x ++)
- {
- if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size))
- return 1;
- }
- sec++;
- cnt++;
- }
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (cur_pages->getlen()) {
- page *p=(page *)cur_pages->get();
- int i = 0;
- while (i < cur_header->blocks[NB_PAGES].num) {
- char pagestr[1024];
- wsprintf(pagestr, "%s pages", str);
- if (resolve_call_int(pagestr,p->dlg_id?"pre-page":"create-page",p->prefunc,&p->prefunc)) return 1;
- if (resolve_call_int(pagestr,"show-page",p->showfunc,&p->showfunc)) return 1;
- if (resolve_call_int(pagestr,"leave-page",p->leavefunc,&p->leavefunc)) return 1;
- p++;
- i++;
- }
- }
-#endif
-#endif
- }
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // resolve callbacks
- {
- struct {
- char *name;
- int *p;
- } callbacks[] = {
- {"%s.onInit", &cur_header->code_onInit},
- {"%s.on%sInstSuccess", &cur_header->code_onInstSuccess},
- {"%s.on%sInstFailed", &cur_header->code_onInstFailed},
- {"%s.onUserAbort", &cur_header->code_onUserAbort},
- {"%s.onVerifyInstDir", &cur_header->code_onVerifyInstDir},
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- {"%s.onGUIInit", &cur_header->code_onGUIInit},
- {"%s.onGUIEnd", &cur_header->code_onGUIEnd},
- {"%s.onMouseOverSection", &cur_header->code_onMouseOverSection},
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- {"%s.onSelChange", &cur_header->code_onSelChange},
-#endif//NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_SUPPORT_REBOOT
- {"%s.onRebootFailed", &cur_header->code_onRebootFailed},
-#endif//NSIS_SUPPORT_REBOOT
- {0, 0}
- };
-
- for (int i = 0; callbacks[i].name; i++) {
- const char *un = uninstall_mode ? "un" : "";
- char fname[1024];
- wsprintf(fname, callbacks[i].name, un, un);
- char cbstr[1024];
- wsprintf(cbstr, "%s callback", str);
- char cbstr2[1024];
- wsprintf(cbstr2, "%s.callbacks", un);
-
- if (resolve_call_int(cbstr,cbstr2,ns_func.find(fname,0),callbacks[i].p))
- return PS_ERROR;
- }
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
- // optimize unused functions
- {
- section *sec=(section *)cur_functions->get();
- int l=cur_functions->getlen()/sizeof(section);
- entry *w=(entry*)cur_entries->get();
- while (l-- > 0)
- {
- if (sec->name_ptr)
- {
- if (!sec->flags)
- {
- if (sec->code_size>0)
- {
- warning("%s function \"%s\" not referenced - zeroing code (%d-%d) out\n",str,
- ns_func.get()+sec->name_ptr,
- sec->code,sec->code+sec->code_size);
- memset(w+sec->code,0,sec->code_size*sizeof(entry));
- }
- }
- }
- sec++;
- }
- }
-
- // give warnings on unused labels
- {
- section *t=(section*)cur_labels->get();
- int n=cur_labels->getlen()/sizeof(section);
- while (n-->0)
- {
- if (!t->flags)
- {
- char *n=(char*)ns_label.get()+t->name_ptr;
- if (*n == '.') warning("global label \"%s\" not used",n);
- else warning("label \"%s\" not used",n);
- }
- t++;
- }
- }
-
- return 0;
-}
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-int CEXEBuild::add_page(int type)
-{
- page pg = {
- 0,
- 0,
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- -1,
- -1,
- -1,
-#endif
- 0,
- };
-
-#ifndef NSIS_CONFIG_LICENSEPAGE
- if (type == PAGE_LICENSE)
- {
- ERROR_MSG("Error: can't add license page, NSIS_CONFIG_LICENSEPAGE not defined.\n");
- return PS_ERROR;
- }
-#endif
-#ifndef NSIS_CONFIG_COMPONENTPAGE
- if (type == PAGE_COMPONENTS)
- {
- ERROR_MSG("Error: can't add components page, NSIS_CONFIG_COMPONENTPAGE not defined.\n");
- return PS_ERROR;
- }
-#endif
-#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (type == PAGE_COMPONENTS)
- {
- ERROR_MSG("Error: can't add uninstConfirm page, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n");
- return PS_ERROR;
- }
-#endif
-
- struct {
- int wndproc_id;
- int dlg_id;
- char *name;
- } ids[] = {
- {PWP_CUSTOM, 0, "custom"}, // custom
-#ifdef NSIS_CONFIG_LICENSEPAGE
- {PWP_LICENSE, IDD_LICENSE, "license"}, // license
-#else
- {0, IDD_LICENSE, "license"}, // license
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- {PWP_SELCOM, IDD_SELCOM, "components"}, // components
-#else
- {0, IDD_SELCOM, "components"}, // components
-#endif
- {PWP_DIR, IDD_DIR, "directory"}, // directory
- {PWP_INSTFILES, IDD_INSTFILES, "instfiles"}, // instfiles
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- {PWP_UNINST, IDD_UNINST, "uninstConfirm"}, // uninstConfirm
-#else
- {0, IDD_UNINST, "uninstConfirm"}, // uninstConfirm
-#endif
- {PWP_COMPLETED, -1, NULL} // completed
- };
-
- pg.wndproc_id = ids[type].wndproc_id;
- pg.dlg_id = ids[type].dlg_id;
-
- cur_pages->add(&pg,sizeof(page));
-
- cur_page = (page *)cur_pages->get() + cur_header->blocks[NB_PAGES].num++;
-
- cur_page_type = type;
-
- set_code_type_predefines(ids[type].name);
- return PS_OK;
-}
-
-int CEXEBuild::page_end()
-{
- cur_page = 0;
-
- set_code_type_predefines();
- return PS_OK;
-}
-#endif
-
-#ifdef NSIS_SUPPORT_VERSION_INFO
-int CEXEBuild::AddVersionInfo()
-{
- GrowBuf VerInfoStream;
-
- if ( rVersionInfo.GetStringTablesCount() > 0 )
- {
- if ( !version_product_v[0] )
- {
- ERROR_MSG("Error: VIProductVersion is required when other version information functions are used.\n");
- return PS_ERROR;
- }
- else
- {
- int imm, iml, ilm, ill;
- if ( sscanf(version_product_v, "%d.%d.%d.%d", &imm, &iml, &ilm, &ill) != 4 )
- {
- ERROR_MSG("Error: invalid VIProductVersion format, should be X.X.X.X\n");
- return PS_ERROR;
- }
- rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
- rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm));
-
- try
- {
- init_res_editor();
- for ( int i = 0; i < rVersionInfo.GetStringTablesCount(); i++ )
- {
- LANGID lang_id = rVersionInfo.GetLangID(i);
- int code_page = rVersionInfo.GetCodePage(i);
-
- char *lang_name = GetLangNameAndCP(lang_id);
-
- if ( !rVersionInfo.FindKey(lang_id, code_page, "FileVersion") )
- warning("Generating version information for language \"%04d-%s\" without standard key \"FileVersion\"", lang_id, lang_name);
- if ( !rVersionInfo.FindKey(lang_id, code_page, "FileDescription") )
- warning("Generating version information for language \"%04d-%s\" without standard key \"FileDescription\"", lang_id, lang_name);
- if ( !rVersionInfo.FindKey(lang_id, code_page, "LegalCopyright") )
- warning("Generating version information for language \"%04d-%s\" without standard key \"LegalCopyright\"", lang_id, lang_name);
-
- rVersionInfo.ExportToStream(VerInfoStream, i);
- res_editor->UpdateResourceA(RT_VERSION, 1, lang_id, (BYTE*)VerInfoStream.get(), VerInfoStream.getlen());
- }
- }
- catch (exception& err) {
- ERROR_MSG("Error adding version information: %s\n", err.what());
- return PS_ERROR;
- }
- }
- }
-
- return PS_OK;
-}
-#endif // NSIS_SUPPORT_VERSION_INFO
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-int CEXEBuild::ProcessPages()
-{
- SCRIPT_MSG("Processing pages... ");
-
- int license_normal=0;
- int license_fsrb=0;
- int license_fscb=0;
- int selcom=0;
- int dir=0, dir_used;
- int uninstconfirm=0;
- int instlog=0, instlog_used;
- int main=0;
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
-again:
-#endif
-
- dir_used = 0;
- instlog_used = 0;
-
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if ((cur_header->flags & (CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) == 0)
-#endif
- {
- main++;
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
-#define LS(inst, uninst) (uninstall_mode ? uninst : inst)
-#else
-#define LS(inst, uninst) inst
-#endif
-
- DefineInnerLangString(NLF_BRANDING);
-
- if (!cur_pages->getlen()) {
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode) {
- if (HasUserDefined(NLF_UNINST_TEXT)) {
- add_page(PAGE_UNINSTCONFIRM);
- page_end();
- }
- add_page(PAGE_INSTFILES);
- page_end();
- add_page(PAGE_COMPLETED);
- page_end();
- }
- else
-#endif
- {
-#ifdef NSIS_CONFIG_LICENSEPAGE
- if (HasUserDefined(NLF_LICENSE_TEXT) && HasUserDefined(NLF_LICENSE_DATA)) {
- add_page(PAGE_LICENSE);
- page_end();
- }
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- if (HasUserDefined(NLF_COMP_TEXT)) {
- add_page(PAGE_COMPONENTS);
- page_end();
- }
-#endif
- if (HasUserDefined(NLF_DIR_TEXT)) {
- add_page(PAGE_DIRECTORY);
- page_end();
- }
- add_page(PAGE_INSTFILES);
- page_end();
- add_page(PAGE_COMPLETED);
- page_end();
- }
- }
- // start processing the pages
- {
- int i = 0;
- page *p = (page *) cur_pages->get();
-
- for (i = 0; i < cur_header->blocks[NB_PAGES].num; i++, p++) {
- page *pp = 0;
-
- if (i) {
- pp = p - 1;
-
- // set back button
- p->flags |= PF_BACK_SHOW;
- if (pp->wndproc_id != PWP_COMPLETED && p->wndproc_id != PWP_COMPLETED && p->wndproc_id != PWP_INSTFILES)
- p->flags |= PF_BACK_ENABLE;
- if (!p->back)
- p->back = DefineInnerLangString(NLF_BTN_BACK);
-
- // set previous page's next button
- if (!pp->next) {
- int str = 0;
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- if (pp->wndproc_id == PWP_LICENSE && (!(pp->flags & PF_LICENSE_FORCE_SELECTION) || HasUserDefined(NLF_BTN_LICENSE)))
- str = NLF_BTN_LICENSE;
- else
-#endif
- if (p->wndproc_id == PWP_INSTFILES)
- str = LS(NLF_BTN_INSTALL, NLF_BTN_UNINSTALL);
- else
- str = NLF_BTN_NEXT;
-
- pp->next = DefineInnerLangString(str);
- }
-
- // set previous page's click next text
- if (!pp->clicknext) {
- int str = 0;
-
- if (p->wndproc_id == PWP_INSTFILES)
- str = LS(NLF_CLICK_INSTALL, NLF_CLICK_UNINSTALL);
- else
- str = NLF_CLICK_NEXT;
-
- pp->clicknext = DefineInnerLangString(str);
- }
- }
-
- // enable next button
- if (p->wndproc_id != PWP_INSTFILES)
- p->flags |= PF_NEXT_ENABLE;
-
- // set cancel button
- if (!p->cancel)
- p->cancel = DefineInnerLangString(NLF_BTN_CANCEL);
- if (p->wndproc_id != PWP_INSTFILES && p->wndproc_id != PWP_COMPLETED)
- p->flags |= PF_CANCEL_ENABLE;
-
- // set caption
- struct {
- int caption;
- int ucaption;
- } captions[] = {
-#ifdef NSIS_CONFIG_LICENSEPAGE
- {NLF_SUBCAPTION_LICENSE, NLF_SUBCAPTION_LICENSE},
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- {NLF_SUBCAPTION_OPTIONS, NLF_SUBCAPTION_OPTIONS},
-#endif
- {NLF_SUBCAPTION_DIR, NLF_SUBCAPTION_DIR},
- {NLF_SUBCAPTION_INSTFILES, NLF_USUBCAPTION_INSTFILES},
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- {NLF_USUBCAPTION_CONFIRM, NLF_USUBCAPTION_CONFIRM},
-#endif
- {NLF_SUBCAPTION_COMPLETED, NLF_USUBCAPTION_COMPLETED}
- };
-
- if (!p->caption && p->wndproc_id != PWP_CUSTOM) {
- p->caption = DefineInnerLangString(LS(captions[p->wndproc_id].caption, captions[p->wndproc_id].ucaption));
- }
-
- // set texts
- switch (p->dlg_id) {
-#ifdef NSIS_CONFIG_LICENSEPAGE
- case IDD_LICENSE:
- case IDD_LICENSE_FSRB:
- case IDD_LICENSE_FSCB:
- {
- if (!(p->flags & PF_PAGE_EX))
- p->dlg_id = license_res_id;
- if (!(p->flags & (PF_LICENSE_FORCE_SELECTION | PF_LICENSE_NO_FORCE_SELECTION)))
- p->dlg_id = license_res_id;
-
- p->flags |= PF_NO_NEXT_FOCUS;
-
- if (!p->parms[1])
- p->parms[1] = DefineInnerLangString(NLF_LICENSE_DATA, 0);
-
- if (p->dlg_id == IDD_LICENSE) {
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT, NLF_ULICENSE_TEXT));
-
- license_normal++;
- }
- else if (p->dlg_id == IDD_LICENSE_FSCB) {
- p->flags |= PF_LICENSE_FORCE_SELECTION;
-
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT_FSCB, NLF_ULICENSE_TEXT_FSCB));
- if (!p->parms[2])
- p->parms[2] = DefineInnerLangString(NLF_BTN_LICENSE_AGREE);
-
- license_fscb++;
- }
- else if (p->dlg_id == IDD_LICENSE_FSRB) {
- p->flags |= PF_LICENSE_FORCE_SELECTION;
-
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT_FSRB, NLF_ULICENSE_TEXT_FSRB));
- if (!p->parms[2])
- p->parms[2] = DefineInnerLangString(NLF_BTN_LICENSE_AGREE);
- if (!p->parms[3])
- p->parms[3] = DefineInnerLangString(NLF_BTN_LICENSE_DISAGREE);
-
- license_fsrb++;
- }
- break;
- }
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- case IDD_SELCOM:
- {
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(LS(NLF_COMP_TEXT, NLF_UCOMP_TEXT));
- if (!p->parms[1])
- p->parms[1] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT1, NLF_UCOMP_SUBTEXT1));
- if (!p->parms[2])
- p->parms[2] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT2, NLF_UCOMP_SUBTEXT2));
- if (!p->parms[3] && !uninstall_mode && HasUserDefined(NLF_COMP_SUBTEXT1))
- p->parms[3] = p->parms[1];
- if (!p->parms[4] && !uninstall_mode && HasUserDefined(NLF_COMP_SUBTEXT2))
- p->parms[4] = p->parms[2];
- else if (!p->parms[4])
- p->parms[4] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT1_NO_INST_TYPES, NLF_UCOMP_SUBTEXT1_NO_INST_TYPES));
-
- DefineInnerLangString(NLF_SPACE_REQ);
- DefineInnerLangString(NLF_BYTE);
- DefineInnerLangString(NLF_KILO);
- DefineInnerLangString(NLF_MEGA);
- DefineInnerLangString(NLF_GIGA);
-
- selcom++;
- break;
- }
-#endif
- case IDD_DIR:
- {
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(LS(NLF_DIR_TEXT, NLF_UDIR_TEXT));
- if (!p->parms[1])
- p->parms[1] = DefineInnerLangString(LS(NLF_DIR_SUBTEXT, NLF_UDIR_SUBTEXT));
- if (!p->parms[2])
- p->parms[2] = DefineInnerLangString(NLF_BTN_BROWSE);
- if (!p->parms[3])
- p->parms[3] = DefineInnerLangString(LS(NLF_DIR_BROWSETEXT, NLF_UDIR_BROWSETEXT));
- if (!p->parms[4])
- p->parms[4] = m_UserVarNames.get("INSTDIR");
- else
- p->parms[4]--;
-
- DefineInnerLangString(NLF_SPACE_AVAIL);
- DefineInnerLangString(NLF_SPACE_REQ);
- DefineInnerLangString(NLF_BYTE);
- DefineInnerLangString(NLF_KILO);
- DefineInnerLangString(NLF_MEGA);
- DefineInnerLangString(NLF_GIGA);
-#ifdef NSIS_CONFIG_LOG
- DefineInnerLangString(NLF_LOG_INSTALL_PROCESS);
-#endif
-
- dir++;
- break;
- }
- case IDD_INSTFILES:
- {
- if (!p->parms[1])
- p->parms[1] = DefineInnerLangString(NLF_BTN_DETAILS);
- if (!p->parms[2])
- p->parms[2] = DefineInnerLangString(NLF_COMPLETED);
-
- DefineInnerLangString(NLF_COPY_DETAILS);
-
- instlog++;
- instlog_used++;
- break;
- }
- case IDD_UNINST:
- {
- if (!p->parms[0])
- p->parms[0] = DefineInnerLangString(NLF_UNINST_TEXT);
- if (!p->parms[1])
- p->parms[1] = DefineInnerLangString(NLF_UNINST_SUBTEXT);
- if (!p->parms[4])
- p->parms[4] = m_UserVarNames.get("INSTDIR");
- else
- p->parms[4]--;
-
- uninstconfirm++;
- break;
- }
- }
-
- p->flags &= ~PF_PAGE_EX;
- }
-
- p--;
-
- if (!p->next)
- p->next = DefineInnerLangString(NLF_BTN_CLOSE);
- if (p->wndproc_id == PWP_COMPLETED)
- (p-1)->next = DefineInnerLangString(NLF_BTN_CLOSE);
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode) {
- if (!uenable_last_page_cancel && instlog_used)
- p->flags &= ~PF_CANCEL_ENABLE;
- }
- else
-#endif
- {
- if (!enable_last_page_cancel && instlog_used)
- p->flags &= ~PF_CANCEL_ENABLE;
- }
-
- if (!instlog_used) {
- warning("%sage instfiles not used, no sections will be executed!", uninstall_mode ? "Uninstall p" : "P");
- }
- }
- }
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!uninstall_mode) {
- set_uninstall_mode(1);
- goto again;
- }
- else
- set_uninstall_mode(0);
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-
-
- SCRIPT_MSG("Done!\n");
-
-#define REMOVE_ICON(id) if (disable_window_icon) { \
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \
- if (dlg) { \
- CDialogTemplate dt(dlg,uDefCodePage); \
- res_editor->FreeResource(dlg); \
- if (dt.RemoveItem(IDC_ULICON)) { \
- DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \
- DialogItemTemplate* prog = dt.GetItem(IDC_PROGRESS); \
- if (text) { \
- text->sWidth += text->sX; \
- text->sX = 0; \
- } \
- if (prog) { \
- prog->sWidth += prog->sX; \
- prog->sX = 0; \
- } \
- \
- DWORD dwSize; \
- dlg = dt.Save(dwSize); \
- res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, dlg, dwSize); \
- delete [] dlg; \
- } \
- } \
- }
-
- try {
- SCRIPT_MSG("Removing unused resources... ");
- init_res_editor();
-#ifdef NSIS_CONFIG_LICENSEPAGE
- if (!license_normal) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_LICENSE);
- if (!license_fsrb) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE_FSRB, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_LICENSE_FSRB);
- if (!license_fscb) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE_FSCB, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_LICENSE_FSCB);
-#endif // NSIS_CONFIG_LICENSEPAGE
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- if (!selcom) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_SELCOM, NSIS_DEFAULT_LANG, 0, 0);
- res_editor->UpdateResourceA(RT_BITMAP, IDB_BITMAP1, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_SELCOM);
-#endif // NSIS_CONFIG_COMPONENTPAGE
- if (!dir) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_DIR, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_DIR);
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!uninstconfirm) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_UNINST, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_UNINST);
-#endif // NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!instlog) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG, 0, 0);
- }
- else REMOVE_ICON(IDD_INSTFILES);
- if (!main) {
- res_editor->UpdateResourceA(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, 0, 0);
- if (!build_compress_whole && !build_crcchk)
- res_editor->UpdateResourceA(RT_DIALOG, IDD_VERIFY, NSIS_DEFAULT_LANG, 0, 0);
- }
-
- SCRIPT_MSG("Done!\n");
- }
- catch (exception& err) {
- ERROR_MSG("\nError: %s\n", err.what());
- return PS_ERROR;
- }
-
- return PS_OK;
-}
-#endif // NSIS_CONFIG_VISIBLE_SUPPORT
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
-void CEXEBuild::PrepareInstTypes()
-{
- if (!(cur_header->flags & CH_FLAGS_NO_CUSTOM))
- cur_header->install_types[NSIS_MAX_INST_TYPES] = DefineInnerLangString(NLF_COMP_CUSTOM);
-
- // set insttype list for RO sections that didn't use SectionIn
- int i = cur_header->blocks[NB_SECTIONS].num;
- section *sections = (section *) cur_sections->get();
-
- while (i--)
- {
- if (sections[i].flags & SF_RO && !sections[i].install_types)
- sections[i].install_types = ~0;
- }
-
- // set selection to first insttype
- if (cur_header->install_types[0])
- {
- int i = cur_header->blocks[NB_SECTIONS].num;
- section *sections = (section *) cur_sections->get();
-
- // if /o was used abort since the user did his manual choice
- while (i--)
- if ((sections[i].flags & SF_SELECTED) == 0)
- return;
-
- i = cur_header->blocks[NB_SECTIONS].num;
-
- while (i--)
- if ((sections[i].install_types & 1) == 0)
- sections[i].flags &= ~SF_SELECTED;
- }
-}
-#endif
-
-void CEXEBuild::AddStandardStrings()
-{
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode)
- {
- cur_header->str_uninstchild = add_string("$TEMP\\$1u_.exe");
- cur_header->str_uninstcmd = add_string("\"$TEMP\\$1u_.exe\" $0 _?=$INSTDIR\\");
- }
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- cur_header->str_wininit = add_string("$WINDIR\\wininit.ini");
-#endif//NSIS_SUPPORT_MOVEONREBOOT
-}
-
-void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf)
-{
- GrowBuf blocks_buf;
- growbuf_writer_sink sink(&blocks_buf);
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- cur_header->blocks[NB_PAGES].offset = sizeof(header) + blocks_buf.getlen();
- page_writer::write_block(cur_pages, &sink);
-#endif
-
- cur_header->blocks[NB_SECTIONS].offset = sizeof(header) + blocks_buf.getlen();
- section_writer::write_block(cur_sections, &sink);
-
- cur_header->blocks[NB_ENTRIES].offset = sizeof(header) + blocks_buf.getlen();
- entry_writer::write_block(cur_entries, &sink);
-
- cur_header->blocks[NB_STRINGS].offset = sizeof(header) + blocks_buf.getlen();
- blocks_buf.add(cur_strlist->get(), cur_strlist->getlen());
-
- cur_header->blocks[NB_LANGTABLES].offset = sizeof(header) + blocks_buf.getlen();
- lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size);
-
- cur_header->blocks[NB_CTLCOLORS].offset = sizeof(header) + blocks_buf.getlen();
- ctlcolors_writer::write_block(cur_ctlcolors, &sink);
-
-#ifdef NSIS_SUPPORT_BGBG
- if (cur_header->bg_color1 != -1)
- {
- bg_font.lfFaceName[LF_FACESIZE-1] = 0;
-
- cur_header->blocks[NB_BGFONT].offset = sizeof(header) + blocks_buf.getlen();
-
- LOGFONT_writer w(&sink);
- w.write(&bg_font);
- }
-#endif
-
- growbuf_writer_sink sink2(hdrbuf);
- header_writer header(&sink2);
- header.write(cur_header);
-
- sink2.write_growbuf(&blocks_buf);
-}
-
-int CEXEBuild::SetVarsSection()
-{
- try {
- init_res_editor();
-
- VerifyDeclaredUserVarRefs(&m_UserVarNames);
- int MaxUserVars = m_UserVarNames.getnum();
- // -1 because the default size is 1
- if (!res_editor->AddExtraVirtualSize2PESection(NSIS_VARS_SECTION, (MaxUserVars - 1) * sizeof(NSIS_STRING)))
- {
- ERROR_MSG("Internal compiler error #12346: invalid exehead cannot find section \"%s\"!\n", NSIS_VARS_SECTION);
- return PS_ERROR;
- }
- }
- catch (exception& err) {
- ERROR_MSG("\nError: %s\n", err.what());
- return PS_ERROR;
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::SetManifest()
-{
- try {
- init_res_editor();
-
- string manifest = manifest::generate(manifest_comctl, manifest_exec_level);
-
- if (manifest == "")
- return PS_OK;
-
- res_editor->UpdateResourceA(MAKEINTRESOURCE(24), MAKEINTRESOURCE(1), NSIS_DEFAULT_LANG, (LPBYTE) manifest.c_str(), manifest.length());
- }
- catch (exception& err) {
- ERROR_MSG("Error while setting manifest: %s\n", err.what());
- return PS_ERROR;
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::check_write_output_errors() const
-{
- if (has_called_write_output)
- {
- ERROR_MSG("Error (write_output): write_output already called, can't continue\n");
- return PS_ERROR;
- }
-
- if (!build_output_filename[0])
- {
- ERROR_MSG("Error: invalid script: never had OutFile command\n");
- return PS_ERROR;
- }
-
- if (!build_sections.getlen())
- {
- ERROR_MSG("Error: invalid script: no sections specified\n");
- return PS_ERROR;
- }
-
- if (!build_entries.getlen())
- {
- ERROR_MSG("Error: invalid script: no entries specified\n");
- return PS_ERROR;
- }
-
- if (build_cursection)
- {
- ERROR_MSG("Error: Section left open at EOF\n");
- return PS_ERROR;
- }
-
- if (sectiongroup_open_cnt)
- {
- ERROR_MSG("Error: SectionGroup left open at EOF\n");
- return PS_ERROR;
- }
-
- if (cur_page)
- {
- ERROR_MSG("Error: PageEx left open at EOF\n");
- return PS_ERROR;
- }
-
- // deal with functions, for both install and uninstall modes.
- if (build_cursection_isfunc)
- {
- ERROR_MSG("Error: Function left open at EOF\n");
- return PS_ERROR;
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::prepare_uninstaller() {
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (ubuild_entries.getlen())
- {
- if (!uninstaller_writes_used)
- {
- warning("Uninstaller script code found but WriteUninstaller never used - no uninstaller will be created.");
- return PS_OK;
- }
-
- build_uninst.flags|=build_header.flags&(CH_FLAGS_PROGRESS_COLORED|CH_FLAGS_NO_ROOT_DIR);
-
- set_uninstall_mode(1);
-
- DefineInnerLangString(NLF_UCAPTION);
-
- if (resolve_coderefs("uninstall"))
- return PS_ERROR;
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- // set sections to the first insttype
- PrepareInstTypes();
-#endif
-
- // Add standard strings to string table
- AddStandardStrings();
-
- set_uninstall_mode(0);
- }
- else if (uninstaller_writes_used)
- {
- ERROR_MSG("Error: no Uninstall section specified, but WriteUninstaller used %d time(s)\n",uninstaller_writes_used);
- return PS_ERROR;
- }
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
- return PS_OK;
-}
-
-int CEXEBuild::pack_exe_header()
-{
- if (!(build_packname[0] && build_packcmd[0])) {
- // header not asked to be packed
- return PS_OK;
- }
-
- // write out exe header, pack, read back in, and
- // update the header info
- FILE *tmpfile=FOPEN(build_packname,"wb");
- if (!tmpfile)
- {
- ERROR_MSG("Error: writing temporary file \"%s\" for pack\n",build_packname);
- return PS_ERROR;
- }
- fwrite(m_exehead,1,m_exehead_size,tmpfile);
- fclose(tmpfile);
- if (sane_system(build_packcmd) == -1)
- {
- remove(build_packname);
- ERROR_MSG("Error: calling packer on \"%s\"\n",build_packname);
- return PS_ERROR;
- }
-
- int result = update_exehead(build_packname);
- remove(build_packname);
-
- if (result != PS_OK)
- {
- ERROR_MSG("Error: reading temporary file \"%s\" after pack\n",build_packname);
- return result;
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::write_output(void)
-{
-#ifndef NSIS_CONFIG_CRC_SUPPORT
- build_crcchk=0;
-#endif
-
- RET_UNLESS_OK( check_write_output_errors() );
-
- has_called_write_output=true;
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- RET_UNLESS_OK( add_plugins_dir_initializer() );
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
-
-#ifdef NSIS_SUPPORT_VERSION_INFO
- RET_UNLESS_OK( AddVersionInfo() );
-#endif //NSIS_SUPPORT_VERSION_INFO
-
- RET_UNLESS_OK( prepare_uninstaller() );
-
- DefineInnerLangString(NLF_CAPTION);
- if (resolve_coderefs("install"))
- return PS_ERROR;
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- // set sections to the first insttype
- PrepareInstTypes();
-#endif
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- RET_UNLESS_OK( ProcessPages() );
-#endif //NSIS_CONFIG_VISIBLE_SUPPORT
-
- // Generate language tables
- RET_UNLESS_OK( GenerateLangTables() );
-
- // Setup user variables PE section
- RET_UNLESS_OK( SetVarsSection() );
-
- // Set XML manifest
- RET_UNLESS_OK( SetManifest() );
-
- // Add standard strings to string table
- AddStandardStrings();
-
- try {
- // Save all changes to the exe header
- close_res_editor();
- }
- catch (exception& err) {
- ERROR_MSG("\nError: %s\n", err.what());
- return PS_ERROR;
- }
-
- RET_UNLESS_OK( pack_exe_header() );
-
-
- build_optimize_datablock=0;
-
- int data_block_size_before_uninst = build_datablock.getlen();
-
- RET_UNLESS_OK( uninstall_generate() );
-
- crc32_t crc=0;
-
- {
- string full_path = get_full_path(build_output_filename);
- notify(MAKENSIS_NOTIFY_OUTPUT, full_path.c_str());
- INFO_MSG("\nOutput: \"%s\"\n", full_path.c_str());
- }
-
- FILE *fp = FOPEN(build_output_filename,"w+b");
- if (!fp)
- {
- ERROR_MSG("Can't open output file\n");
- return PS_ERROR;
- }
-
- if (fwrite(m_exehead,1,m_exehead_size,fp) != m_exehead_size)
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",m_exehead_size);
- fclose(fp);
- return PS_ERROR;
- }
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- #ifdef NSIS_CONFIG_CRC_ANAL
- crc=CRC32(crc,m_exehead,m_exehead_size);
- #else
- crc=CRC32(crc,m_exehead+512,m_exehead_size-512);
- #endif
-#endif
-
- firstheader fh={0,};
- fh.nsinst[0]=FH_INT1;
- fh.nsinst[1]=FH_INT2;
- fh.nsinst[2]=FH_INT3;
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- fh.flags=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC);
-#else
- fh.flags=0;
-#endif
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT;
-#endif
- fh.siginfo=FH_SIG;
-
- int installinfo_compressed;
- int fd_start = 0;
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (build_compress_whole)
- {
- int n = compressor->Init(build_compress_level, build_compress_dict_size);
- if (n != C_OK)
- {
- ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n);
- return PS_ERROR;
- }
- }
-#endif
-
- {
- GrowBuf ihd;
- {
- GrowBuf hdrcomp;
-
- PrepareHeaders(&hdrcomp);
-
- if (add_data((char*)hdrcomp.get(),hdrcomp.getlen(),&ihd) < 0)
- return PS_ERROR;
-
- fh.length_of_header=hdrcomp.getlen();
- installinfo_compressed=ihd.getlen();
- }
-
- if (!build_compress_whole)
- fh.length_of_all_following_data=ihd.getlen()+build_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
- else
- fd_start=ftell(fp);
-
- try
- {
- file_writer_sink sink(fp);
- firstheader_writer w(&sink);
- w.write(&fh);
- }
- catch (...)
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(fh));
- fclose(fp);
- return PS_ERROR;
- }
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (build_compress_whole) {
- if (deflateToFile(fp,(char*)ihd.get(),ihd.getlen()))
- {
- fclose(fp);
- return PS_ERROR;
- }
- }
- else
-#endif
- {
- if (fwrite(ihd.get(),1,ihd.getlen(),fp) != (unsigned int)ihd.getlen())
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",ihd.getlen());
- fclose(fp);
- return PS_ERROR;
- }
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- crc_writer_sink crc_sink((crc32_t *) &crc);
- firstheader_writer w(&crc_sink);
- w.write(&fh);
-
- crc=CRC32(crc,(unsigned char*)ihd.get(),ihd.getlen());
-#endif
- }
- }
-
- INFO_MSG("Install: ");
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- int np=build_header.blocks[NB_PAGES].num;
- INFO_MSG("%d page%s (%d bytes), ",np,np==1?"":"s",np*sizeof(page));
-#endif
- {
- int ns=build_sections.getlen()/sizeof(section);
- section *s=(section*)build_sections.get();
- int x;
- int req=0;
- for (x = 1; x < ns; x ++)
- {
- if (!s[x].name_ptr || s[x].flags & SF_RO) req++;
- }
- INFO_MSG("%d section%s",ns,ns==1?"":"s");
- if (req)
- {
- INFO_MSG(" (%d required)",req);
- }
- INFO_MSG(" (%d bytes), ", build_sections.getlen());
- }
- int ne=build_header.blocks[NB_ENTRIES].num;
- INFO_MSG("%d instruction%s (%d bytes), ",ne,ne==1?"":"s",ne*sizeof(entry));
- int ns=build_strlist.getnum();
- INFO_MSG("%d string%s (%d bytes), ",ns,ns==1?"":"s",build_strlist.getlen());
- int nlt=build_header.blocks[NB_LANGTABLES].num;
- INFO_MSG("%d language table%s (%d bytes).\n",nlt,nlt==1?"":"s",build_langtables.getlen());
- if (ubuild_entries.getlen())
- {
- INFO_MSG("Uninstall: ");
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- np=build_uninst.blocks[NB_PAGES].num;
- INFO_MSG("%d page%s (%d bytes), \n",np,np==1?"":"s",ubuild_pages.getlen());
-#endif
- {
- int ns=ubuild_sections.getlen()/sizeof(section);
- section *s=(section*)ubuild_sections.get();
- int x;
- int req=0;
- for (x = 1; x < ns; x ++)
- {
- if (!s[x].name_ptr || s[x].flags & SF_RO) req++;
- }
- INFO_MSG("%d section%s",ns,ns==1?"":"s");
- if (req)
- {
- INFO_MSG(" (%d required)",req);
- }
- INFO_MSG(" (%d bytes), ", ubuild_sections.getlen());
- }
- ne=build_uninst.blocks[NB_ENTRIES].num;
- INFO_MSG("%d instruction%s (%d bytes), ",ne,ne==1?"":"s",ubuild_entries.getlen());
- ns=ubuild_strlist.getnum();
- INFO_MSG("%d string%s (%d bytes), ",ns,ns==1?"":"s",ubuild_strlist.getlen());
- nlt=build_uninst.blocks[NB_LANGTABLES].num;
- INFO_MSG("%d language table%s (%d bytes).\n",nlt,nlt==1?"":"s",ubuild_langtables.getlen());
- }
-
-
- if (db_opt_save)
- {
- int total_out_size_estimate=
- m_exehead_size+sizeof(fh)+build_datablock.getlen()+(build_crcchk?sizeof(crc32_t):0);
- int pc=(int)(((INT64)db_opt_save*1000)/(db_opt_save+total_out_size_estimate));
- INFO_MSG("Datablock optimizer saved %d bytes (~%d.%d%%).\n",db_opt_save,
- pc/10,pc%10);
- }
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- INFO_MSG("\nUsing %s%s compression.\n\n", compressor->GetName(), build_compress_whole?" (compress whole)":"");
-#endif
-
- unsigned int total_usize=m_exehead_original_size;
-
- INFO_MSG("EXE header size: %10d / %d bytes\n",m_exehead_size,m_exehead_original_size);
-
- if (build_compress_whole) {
- INFO_MSG("Install code: (%d bytes)\n",
- sizeof(fh)+fh.length_of_header);
- }
- else {
- INFO_MSG("Install code: %10d / %d bytes\n",
- sizeof(fh)+installinfo_compressed,
- sizeof(fh)+fh.length_of_header);
- }
-
- total_usize+=sizeof(fh)+fh.length_of_header;
-
- {
- int dbsize, dbsizeu;
- dbsize = build_datablock.getlen();
- if (uninstall_size>0) dbsize-=uninstall_size;
-
- if (build_compress_whole) {
- dbsizeu=dbsize;
- INFO_MSG("Install data: (%d bytes)\n",dbsizeu);
- }
- else {
- dbsizeu = db_full_size - uninstall_size_full;
- INFO_MSG("Install data: %10d / %d bytes\n",dbsize,dbsizeu);
- }
- total_usize+=dbsizeu;
- }
-
- if (uninstall_size>=0)
- {
- if (build_compress_whole)
- INFO_MSG("Uninstall code+data: (%d bytes)\n",uninstall_size_full);
- else
- INFO_MSG("Uninstall code+data: %6d / %d bytes\n",uninstall_size,uninstall_size_full);
- total_usize+=uninstall_size_full;
- }
-
- if (build_compress_whole) {
- INFO_MSG("Compressed data: ");
- }
-
- if (build_datablock.getlen())
- {
- build_datablock.setro(TRUE);
- int dbl = build_datablock.getlen();
- int left = dbl;
- while (left > 0)
- {
- int l = min(build_filebuflen, left);
- char *dbptr = (char *) build_datablock.get(dbl - left, l);
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (build_compress_whole)
- {
- if (deflateToFile(fp,dbptr,l))
- {
- fclose(fp);
- return PS_ERROR;
- }
- }
- else
-#endif
- {
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- crc=CRC32(crc,(unsigned char *)dbptr,l);
-#endif
- if ((int)fwrite(dbptr,1,l,fp) != l)
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",l);
- fclose(fp);
- return PS_ERROR;
- }
- fflush(fp);
- }
- build_datablock.release();
- left -= l;
- }
- build_datablock.setro(FALSE);
- build_datablock.clear();
- }
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (build_compress_whole)
- {
- if (deflateToFile(fp,NULL,0))
- {
- fclose(fp);
- return PS_ERROR;
- }
- compressor->End();
-
- unsigned fend = ftell(fp);
-
- fh.length_of_all_following_data=ftell(fp)-fd_start+(build_crcchk?sizeof(crc32_t):0);
- INFO_MSG(
- "%10d / %d bytes\n",
- ftell(fp) - fd_start,
- data_block_size_before_uninst + fh.length_of_header + sizeof(firstheader) + uninstall_size_full
- );
-
- fseek(fp,fd_start,SEEK_SET);
-
- try
- {
- file_writer_sink sink(fp);
- firstheader_writer w(&sink);
- w.write(&fh);
- }
- catch (...)
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(fh));
- fclose(fp);
- return PS_ERROR;
- }
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- if (build_crcchk)
- {
- // check rest of CRC
- fseek(fp,fd_start,SEEK_SET);
- for (;;)
- {
- char buf[32768];
- int l=fread(buf,1,sizeof(buf),fp);
- if (!l) break;
- crc=CRC32(crc,(unsigned char *)buf,l);
- }
- }
-#endif
- fseek(fp,fend,SEEK_SET); // reset eof flag
- }
-#endif
-
- if (build_crcchk)
- {
- total_usize+=sizeof(int);
- int rcrc = FIX_ENDIAN_INT32(crc);
- if (fwrite(&rcrc,1,sizeof(crc32_t),fp) != sizeof(crc32_t))
- {
- ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(crc32_t));
- fclose(fp);
- return PS_ERROR;
- }
- INFO_MSG("CRC (0x%08X): 4 / 4 bytes\n",crc);
- }
- INFO_MSG("\n");
- {
- UINT pc=(UINT)(((UINT64)ftell(fp)*1000)/(total_usize));
- INFO_MSG("Total size: %10u / %u bytes (%u.%u%%)\n",
- ftell(fp),total_usize,pc/10,pc%10);
- }
- fclose(fp);
- print_warnings();
- return PS_OK;
-}
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
-int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush
-{
- build_compressor_set=true;
-
- char obuf[65536];
- bool flush=false;
- compressor->SetNextIn(buf,len);
- if (!buf||!len)
- {
- char a;
- compressor->SetNextIn(&a,0);
- flush=C_FINISH;
- }
- for (;;)
- {
- compressor->SetNextOut(obuf,sizeof(obuf));
- int ret=compressor->Compress(flush);
- if (ret<0 && (ret!=-1 || !flush))
- {
- ERROR_MSG("Error: deflateToFile: deflate() failed(%s [%d])\n", compressor->GetErrStr(ret), ret);
- return 1;
- }
- int l=compressor->GetNextOut()-obuf;
- if (l)
- {
- if (fwrite(obuf,1,l,fp) != (unsigned)l)
- {
- ERROR_MSG("Error: deflateToFile fwrite(%d) failed\n",l);
- return 1;
- }
- fflush(fp);
- }
- if (!compressor->GetAvailIn() && (!flush || !l)) break;
- }
- return 0;
-}
-#endif
-
-int CEXEBuild::uninstall_generate()
-{
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (ubuild_entries.getlen() && uninstaller_writes_used)
- {
- SCRIPT_MSG("Generating uninstaller... ");
-
- firstheader fh={0,};
-
- GrowBuf uhd;
- {
- GrowBuf udata;
-
- set_uninstall_mode(1);
-
- PrepareHeaders(&udata);
-
- fh.length_of_header=udata.getlen();
- int err=add_data((char*)udata.get(),udata.getlen(),&uhd);
- set_uninstall_mode(0);
- if (err < 0) return PS_ERROR;
- }
-
- crc32_t crc=0;
-
- // Get offsets of icons to replace for uninstall
- // Also makes sure that the icons are there and in the right size.
- if (generate_unicons_offsets(m_exehead, m_exehead_size, m_unicon_data) == 0)
- return PS_ERROR;
-
- entry *ent = (entry *) build_entries.get();
- if (!ent)
- return PS_ERROR;
- int ents = build_header.blocks[NB_ENTRIES].num;
- int uns = uninstaller_writes_used;
- int uninstdata_offset = build_datablock.getlen();
- while (ents--)
- {
- if (ent->which == EW_WRITEUNINSTALLER)
- {
- ent->offsets[1] = uninstdata_offset;
- ent->offsets[2] = m_unicon_size;
- uns--;
- if (!uns)
- break;
- }
- ent++;
- }
-
- if (add_db_data((char *)m_unicon_data,m_unicon_size) < 0)
- return PS_ERROR;
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- {
- // "create" the uninstaller
- LPBYTE uninst_header = (LPBYTE) malloc(m_exehead_size);
- if (!uninst_header)
- return PS_ERROR;
-
- memcpy(uninst_header, m_exehead, m_exehead_size);
-
- // patch the icons
- LPBYTE seeker = m_unicon_data;
- while (*seeker) {
- DWORD dwSize = FIX_ENDIAN_INT32(*(LPDWORD) seeker);
- seeker += sizeof(DWORD);
- DWORD dwOffset = FIX_ENDIAN_INT32(*(LPDWORD) seeker);
- seeker += sizeof(DWORD);
- memcpy(uninst_header + dwOffset, seeker, dwSize);
- seeker += dwSize;
- }
-
-#ifdef NSIS_CONFIG_CRC_ANAL
- crc=CRC32(crc, uninst_header, m_exehead_size);
-#else
- crc=CRC32(crc, uninst_header + 512, m_exehead_size - 512);
-#endif
-
- free(uninst_header);
- }
-#endif
- fh.nsinst[0]=FH_INT1;
- fh.nsinst[1]=FH_INT2;
- fh.nsinst[2]=FH_INT3;
- fh.flags=FH_FLAGS_UNINSTALL;
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- fh.flags|=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC);
-#endif
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if (build_uninst.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT;
-#endif
- fh.siginfo=FH_SIG;
- fh.length_of_all_following_data=
- uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0);
-
- MMapBuf udata;
-
- {
- growbuf_writer_sink sink(&udata);
- firstheader_writer w(&sink);
- w.write(&fh);
- }
-
- ubuild_datablock.setro(TRUE);
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (build_compress_whole) {
- // compress uninstaller too
- {
- char obuf[65536];
- int n = compressor->Init(build_compress_level, build_compress_dict_size);
- if (n != C_OK)
- {
- ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n);
- extern void quit(); quit();
- }
-
- compressor->SetNextIn((char*)uhd.get(), uhd.getlen());
- while (compressor->GetAvailIn())
- {
- compressor->SetNextOut(obuf, sizeof(obuf));
- compressor->Compress(0);
- if (compressor->GetNextOut() - obuf > 0)
- {
- udata.add(obuf, compressor->GetNextOut() - obuf);
- }
- }
-
- int avail_in = ubuild_datablock.getlen();
- int in_pos = 0;
- while (avail_in > 0) {
- int l = min(avail_in, build_filebuflen);
-
- char *p = (char*)ubuild_datablock.get(in_pos, l);
- compressor->SetNextIn(p, l);
-
- while (compressor->GetAvailIn())
- {
- compressor->SetNextOut(obuf, sizeof(obuf));
- compressor->Compress(0);
- if (compressor->GetNextOut() - obuf > 0)
- udata.add(obuf, compressor->GetNextOut() - obuf);
- }
-
- ubuild_datablock.release();
-
- avail_in -= l;
- in_pos += l;
- }
-
- for (;;)
- {
- compressor->SetNextOut(obuf, sizeof(obuf));
- compressor->Compress(C_FINISH);
- if (compressor->GetNextOut() - obuf > 0)
- udata.add(obuf, compressor->GetNextOut() - obuf);
- else break;
- }
- compressor->End();
- }
-
- firstheader *_fh=(firstheader *)udata.get(0, sizeof(firstheader));
- _fh->length_of_all_following_data=FIX_ENDIAN_INT32(udata.getlen()+(build_crcchk?sizeof(crc32_t):0));
- udata.release();
- }
- else
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
- {
- udata.add(uhd.get(), uhd.getlen());
-
- int st = udata.getlen();
- int length = ubuild_datablock.getlen();
- int left = length;
- udata.resize(st + left);
- while (left > 0)
- {
- int l = min(build_filebuflen, left);
- void *p = ubuild_datablock.get(length - left, l);
- memcpy(udata.get(st + length - left, l), p, l);
- udata.flush(l);
- udata.release();
- ubuild_datablock.release();
- left -= l;
- }
- }
-
- ubuild_datablock.clear();
-
- udata.setro(TRUE);
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- if (build_crcchk)
- {
- int pos = 0;
- int left = udata.getlen();
- while (left > 0)
- {
- int l = min(build_filebuflen, left);
- crc = CRC32(crc, (unsigned char *) udata.get(pos, l), l);
- udata.release();
- pos += l;
- left -= l;
- }
- udata.setro(FALSE);
- FIX_ENDIAN_INT32_INPLACE(crc);
- udata.add(&crc, sizeof(crc));
- udata.setro(TRUE);
- }
-#endif
-
- if (add_db_data(&udata) < 0)
- return PS_ERROR;
-
- udata.clear();
-
- //uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int);
- uninstall_size_full=fh.length_of_all_following_data+m_unicon_size;
-
- // compressed size
- uninstall_size=build_datablock.getlen()-uninstdata_offset;
-
- SCRIPT_MSG("Done!\n");
- }
-#endif
- return PS_OK;
-}
-
-#define SWAP(x,y,i) { i _ii; _ii=x; x=y; y=_ii; }
-
-void CEXEBuild::set_uninstall_mode(int un)
-{
- if (un != uninstall_mode)
- {
- uninstall_mode=un;
- if (un)
- {
- cur_datablock=&ubuild_datablock;
- cur_datablock_cache=&ubuild_datablock_cache;
- cur_entries=&ubuild_entries;
- cur_instruction_entry_map=&ubuild_instruction_entry_map;
- cur_functions=&ubuild_functions;
- cur_labels=&ubuild_labels;
- cur_pages=&ubuild_pages;
- cur_sections=&ubuild_sections;
- cur_header=&build_uninst;
- cur_strlist=&ubuild_strlist;
- cur_langtables=&ubuild_langtables;
- cur_ctlcolors=&ubuild_ctlcolors;
-
- definedlist.add("__UNINSTALL__");
- }
- else
- {
- cur_datablock=&build_datablock;
- cur_datablock_cache=&build_datablock_cache;
- cur_entries=&build_entries;
- cur_instruction_entry_map=&build_instruction_entry_map;
- cur_functions=&build_functions;
- cur_labels=&build_labels;
- cur_pages=&build_pages;
- cur_sections=&build_sections;
- cur_header=&build_header;
- cur_strlist=&build_strlist;
- cur_langtables=&build_langtables;
- cur_ctlcolors=&build_ctlcolors;
-
- definedlist.del("__UNINSTALL__");
- }
-
- SWAP(db_opt_save_u,db_opt_save,int);
- SWAP(db_comp_save_u,db_comp_save,int);
- SWAP(db_full_size_u,db_full_size,int);
- }
-}
-
-extern FILE *g_output;
-
-void CEXEBuild::warning(const char *s, ...)
-{
- char buf[NSIS_MAX_STRLEN*10];
- va_list val;
- va_start(val,s);
-#ifdef _WIN32
- vsprintf(buf,s,val);
-#else
- vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val);
-#endif
- va_end(val);
- m_warnings.add(buf,0);
- notify(MAKENSIS_NOTIFY_WARNING,buf);
- if (display_warnings)
- {
- fprintf(g_output,"warning: %s\n",buf);
- fflush(g_output);
- }
-}
-
-void CEXEBuild::warning_fl(const char *s, ...)
-{
- char buf[NSIS_MAX_STRLEN*10];
- va_list val;
- va_start(val,s);
-#ifdef _WIN32
- vsprintf(buf,s,val);
-#else
- vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val);
-#endif
- va_end(val);
- sprintf(buf+strlen(buf)," (%s:%d)",curfilename,linecnt);
- m_warnings.add(buf,0);
- notify(MAKENSIS_NOTIFY_WARNING,buf);
- if (display_warnings)
- {
- fprintf(g_output,"warning: %s\n",buf);
- fflush(g_output);
- }
-}
-
-void CEXEBuild::ERROR_MSG(const char *s, ...) const
-{
- if (display_errors || notify_hwnd)
- {
- char buf[NSIS_MAX_STRLEN*10];
- va_list val;
- va_start(val,s);
-#ifdef _WIN32
- vsprintf(buf,s,val);
-#else
- vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val);
-#endif
- va_end(val);
- notify(MAKENSIS_NOTIFY_ERROR,buf);
- if (display_errors)
- {
- fprintf(g_output,"%s",buf);
- fflush(g_output);
- }
- }
-}
-
-void CEXEBuild::SCRIPT_MSG(const char *s, ...) const
-{
- if (display_script)
- {
- va_list val;
- va_start(val,s);
- vfprintf(g_output,s,val);
- va_end(val);
- fflush(g_output);
- }
-}
-
-void CEXEBuild::INFO_MSG(const char *s, ...) const
-{
- if (display_info)
- {
- va_list val;
- va_start(val,s);
- vfprintf(g_output,s,val);
- va_end(val);
- fflush(g_output);
- }
-}
-
-void CEXEBuild::print_warnings()
-{
- int nw=0,x=m_warnings.getlen();
- if (!x || !display_warnings) return;
- char *p=m_warnings.get();
- while (x>0) if (!p[--x]) nw++;
- fprintf(g_output,"\n%d warning%s:\n",nw,nw==1?"":"s");
- for (x = 0; x < nw; x ++)
- {
- fprintf(g_output," %s\n",p);
- p+=strlen(p)+1;
- }
- fflush(g_output);
-}
-
-void CEXEBuild::notify(notify_e code, const char *data) const
-{
-#ifdef _WIN32
- if (notify_hwnd)
- {
- COPYDATASTRUCT cds = {(DWORD)code, strlen(data)+1, (void *) data};
- SendMessage(notify_hwnd, WM_COPYDATA, 0, (LPARAM)&cds);
- }
-#endif
-}
-
-// Added by Ximon Eighteen 5th August 2002
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
-void CEXEBuild::build_plugin_table(void)
-{
- if (plugins_processed)
- return;
- plugins_processed=1;
-
- plugin_used = false;
- uninst_plugin_used = false;
- string searchPath = definedlist.find("NSISDIR");
- searchPath += PLATFORM_PATH_SEPARATOR_STR"Plugins";
- INFO_MSG("Processing plugin dlls: \"%s" PLATFORM_PATH_SEPARATOR_STR "*.dll\"\n",searchPath.c_str());
- m_plugins.FindCommands(searchPath, display_info?true:false);
- INFO_MSG("\n");
-}
-
-#define FLAG_OFFSET(flag) (FIELD_OFFSET(exec_flags, flag)/sizeof(int))
-
-int CEXEBuild::add_plugins_dir_initializer(void)
-{
- if (!plugin_used && !uninst_plugin_used) return PS_OK;
-
- SCRIPT_MSG("Adding plug-ins initializing function... ");
-
- bool uninstall = !plugin_used;
-
- int ret;
- int zero_offset;
-
- int var_zero;
- var_zero=m_UserVarNames.get("0");
-
-again:
- // Function [un.]Initialize_____Plugins
- ret=add_function(uninstall?"un.Initialize_____Plugins":"Initialize_____Plugins");
- if (ret != PS_OK) return ret;
-
- // don't move this, depends on [un.]
- zero_offset=add_string("$0");
-
- // SetDetailsPrint none
- ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), add_intstring(6));
- if (ret != PS_OK) return ret;
-
- // StrCmp $PLUGINSDIR ""
- ret=add_entry_direct(EW_STRCMP, add_string("$PLUGINSDIR"), 0, 0, ns_label.add("Initialize_____Plugins_done",0));
- if (ret != PS_OK) return ret;
- // Push $0
- ret=add_entry_direct(EW_PUSHPOP, zero_offset);
- if (ret != PS_OK) return ret;
- // ClearErrors
- ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(exec_error));
- if (ret != PS_OK) return ret;
- // GetTempFileName $0
- ret=add_entry_direct(EW_GETTEMPFILENAME, var_zero, add_string("$TEMP"));
- if (ret != PS_OK) return ret;
- // Delete $0 [simple, nothing that could clash with special temp permissions]
- ret=add_entry_direct(EW_DELETEFILE, zero_offset, DEL_SIMPLE);
- if (ret != PS_OK) return ret;
- // CraeteDirectory $0 - a dir instead of that temp file
- ret=add_entry_direct(EW_CREATEDIR, zero_offset);
- if (ret != PS_OK) return ret;
- // IfErrors Initialize_____Plugins_error - detect errors
- ret=add_entry_direct(EW_IFFLAG, ns_label.add("Initialize_____Plugins_error",0), 0, FLAG_OFFSET(exec_error));
- if (ret != PS_OK) return ret;
- // Copy $0 to $PLUGINSDIR
- ret=add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("PLUGINSDIR"), zero_offset);
- if (ret != PS_OK) return ret;
- // Pop $0
- ret=add_entry_direct(EW_PUSHPOP, var_zero, 1);
- if (ret != PS_OK) return ret;
-
- // done
- if (add_label("Initialize_____Plugins_done")) return PS_ERROR;
- // Return
- ret=add_entry_direct(EW_RET);
- if (ret != PS_OK) return ret;
-
- // error
- if (add_label("Initialize_____Plugins_error")) return PS_ERROR;
- // error message box
- ret=add_entry_direct(EW_MESSAGEBOX, MB_OK|MB_ICONSTOP|(IDOK<<21), add_string("Error! Can't initialize plug-ins directory. Please try again later."));
- if (ret != PS_OK) return ret;
- // Quit
- ret=add_entry_direct(EW_QUIT);
- if (ret != PS_OK) return ret;
-
- // FunctionEnd
- ret=function_end();
- if (ret != PS_OK) return ret;
-
- if (uninst_plugin_used && !uninstall) {
- uninstall = true;
- goto again;
- }
-
- SCRIPT_MSG("Done!\n");
-
- return PS_OK;
-}
-#endif // NSIS_CONFIG_PLUGIN_SUPPORT
-
-void CEXEBuild::init_res_editor()
-{
- build_compressor_set = true;
- if (!res_editor)
- res_editor = new CResourceEditor(m_exehead, m_exehead_size);
-}
-
-void CEXEBuild::close_res_editor()
-{
- if (!res_editor) return;
- DWORD newsize;
-
- // get size
- newsize = res_editor->Save(NULL, newsize);
- unsigned char *new_header = new unsigned char[newsize];
-
- // save
- int rc = res_editor->Save(new_header, newsize);
- assert(rc == 0);
-
- update_exehead(new_header, newsize);
-
- // TODO: resource-controlling class
- delete [] new_header;
-
- delete res_editor;
- res_editor=0;
-}
-
-int CEXEBuild::DeclaredUserVar(const char *szVarName)
-{
- if (m_ShellConstants.get((char*)szVarName) >= 0)
- {
- ERROR_MSG("Error: name \"%s\" in use by constant\n", szVarName);
- return PS_ERROR;
- }
-
- int idxUserVar = m_UserVarNames.get((char*)szVarName);
- if (idxUserVar >= 0)
- {
- ERROR_MSG("Error: variable \"%s\" already declared\n", szVarName);
- return PS_ERROR;
- }
- const char *pVarName = szVarName;
- int iVarLen = strlen(szVarName);
-
- if (iVarLen > 60)
- {
- ERROR_MSG("Error: variable name too long!\n");
- return PS_ERROR;
- }
- else if (!iVarLen)
- {
- ERROR_MSG("Error: variable with empty name!\n");
- return PS_ERROR;
- }
- else
- {
- while (*pVarName)
- {
- if (!isSimpleChar(*pVarName))
- {
- ERROR_MSG("Error: invalid characters in variable name \"%s\", use only characters [a-z][A-Z][0-9] and '_'\n", szVarName);
- return PS_ERROR;
- }
- pVarName++;
- }
- }
-
- m_UserVarNames.add(szVarName);
- if (m_UserVarNames.getnum() > MAX_CODED)
- {
- ERROR_MSG("Error: too many user variables declared. Maximum allowed is %u.\n", MAX_CODED - m_iBaseVarsNum);
- return PS_ERROR;
- }
- return PS_OK;
-}
-
-
-int CEXEBuild::GetUserVarIndex(LineParser &line, int token)
-{
- char *p = line.gettoken_str(token);
- if ( *p == '$' && *(p+1) )
- {
- int idxUserVar = m_UserVarNames.get((char *)p+1);
- if (idxUserVar >= 0 && m_UserVarNames.get_reference(idxUserVar) >= 0)
- {
- m_UserVarNames.inc_reference(idxUserVar);
- return idxUserVar;
- }
- else
- {
- int idxConst = m_ShellConstants.get((char *)p+1);
- if (idxConst >= 0)
- {
- ERROR_MSG("Error: cannot change constants : %s\n", p);
- }
- }
- }
- return -1;
-}
-
-void CEXEBuild::VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList)
-{
- for (int i = m_iBaseVarsNum; i < pVarsStringList->getnum(); i++)
- {
- if (!pVarsStringList->get_reference(i))
- {
- warning("Variable \"%s\" not referenced or never set, wasting memory!", pVarsStringList->idx2name(i));
- }
- }
-}
-
-int CEXEBuild::set_compressor(const string& compressor, const bool solid) {
- string stub = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + compressor;
- if (solid)
- stub += "_solid";
-
- return update_exehead(stub, &m_exehead_original_size);
-}
-
-int CEXEBuild::update_exehead(const string& file, size_t *size/*=NULL*/) {
- FILE *tmpfile = fopen(file.c_str(), "rb");
- if (!tmpfile)
- {
- ERROR_MSG("Error: opening stub \"%s\"\n", file.c_str());
- return PS_ERROR;
- }
-
- fseek(tmpfile, 0, SEEK_END);
- size_t exehead_size = ftell(tmpfile);
-
- unsigned char *exehead = new unsigned char[exehead_size];
- fseek(tmpfile, 0, SEEK_SET);
- if (fread(exehead, 1, exehead_size, tmpfile) != exehead_size)
- {
- ERROR_MSG("Error: reading stub \"%s\"\n", file.c_str());
- fclose(tmpfile);
- delete [] exehead;
- return PS_ERROR;
- }
- fclose(tmpfile);
-
- update_exehead(exehead, exehead_size);
-
- if (size)
- *size = exehead_size;
-
- delete [] exehead;
-
- return PS_OK;
-}
-
-void CEXEBuild::update_exehead(const unsigned char *new_exehead, size_t new_size) {
- assert(m_exehead != new_exehead);
-
- // align exehead to 512
- m_exehead_size = align_to_512(new_size);
-
- delete [] m_exehead;
- m_exehead = new unsigned char[m_exehead_size];
-
- // copy exehead
- memcpy(m_exehead, new_exehead, new_size);
-
- // zero rest of exehead
- memset(m_exehead + new_size, 0, m_exehead_size - new_size);
-}
-
-void CEXEBuild::set_code_type_predefines(const char *value)
-{
- definedlist.del("__SECTION__");
- definedlist.del("__FUNCTION__");
- definedlist.del("__PAGEEX__");
- definedlist.del("__GLOBAL__");
-
- switch (GetCurrentTokenPlace())
- {
- case TP_SEC:
- definedlist.add("__SECTION__", value==NULL?"":value);
- break;
- case TP_FUNC:
- definedlist.add("__FUNCTION__", value==NULL?"":value);
- break;
- case TP_PAGEEX:
- definedlist.add("__PAGEEX__", value==NULL?"":value);
- break;
- default:
- definedlist.add("__GLOBAL__");
- }
-}
-
+/* + * build.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <stdio.h> +#include "exehead/config.h" + +#include "version.h" + +#include "build.h" +#include "util.h" +#include "fileform.h" +#include "writer.h" +#include "crc32.h" +#include "manifest.h" +#include "icon.h" + +#include <stdexcept> + +#include "exehead/resource.h" +#include "ResourceEditor.h" +#include "DialogTemplate.h" +#include "ResourceVersionInfo.h" + +#ifndef _WIN32 +# include <locale.h> +# include <unistd.h> +# include <limits.h> +# include <stdlib.h> +# include <stdarg.h> +#endif + +#include <cassert> // for assert + +#define RET_UNLESS_OK( function_rc ) do { \ + int rc = (function_rc); \ + if ( rc != PS_OK) \ + return rc; \ +} while (false) + +using namespace std; + +namespace { // begin anonymous namespace + +bool isSimpleChar(char ch) +{ + return (ch == '.' ) || (ch == '_' ) || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); +} + +} // end of anonymous namespace + +void CEXEBuild::define(const char *p, const char *v) +{ + definedlist.add(p,v); +} + +CEXEBuild::~CEXEBuild() +{ + free_loaded_icon(installer_icon); + free_loaded_icon(uninstaller_icon); + + delete [] m_exehead; + + int nlt = lang_tables.getlen() / sizeof(LanguageTable); + LanguageTable *nla = (LanguageTable*)lang_tables.get(); + + for (int i = 0; i < nlt; i++) { + DeleteLangTable(nla+i); + } +} + +CEXEBuild::CEXEBuild() : + m_exehead(0), + m_exehead_size(0) +{ + linecnt = 0; + fp = 0; + curfilename = 0; + + display_info=1; + display_script=1; + display_errors=1; + display_warnings=1; + + cur_ifblock=NULL; + last_line_had_slash=0; + inside_comment=false; + multiple_entries_instruction=0; + + build_include_depth=0; + + has_called_write_output=false; + + ns_func.add("",0); // make sure offset 0 is special on these (i.e. never used by a label) + ns_label.add("",0); + + definedlist.add("NSIS_VERSION", NSIS_VERSION); + + // automatically generated header file containing all defines +#include "defines.h" + + // no longer optional + definedlist.add("NSIS_SUPPORT_STANDARD_PREDEFINES"); + definedlist.add("NSIS_SUPPORT_NAMED_USERVARS"); + definedlist.add("NSIS_SUPPORT_LANG_IN_STRINGS"); + +#ifdef _WIN32 + definedlist.add("NSIS_WIN32_MAKENSIS"); +#endif + + db_opt_save=db_comp_save=db_full_size=db_opt_save_u=db_comp_save_u=db_full_size_u=0; + + // Added by Amir Szekely 31st July 2002 +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + compressor = &zlib_compressor; +#endif + build_compressor_set = false; + build_compressor_final = false; +#ifdef NSIS_ZLIB_COMPRESS_WHOLE + build_compress_whole = true; +#else + build_compress_whole = false; +#endif + build_compress=1; + build_compress_level=9; + build_compress_dict_size=1<<23; + + cur_entries=&build_entries; + cur_instruction_entry_map=&build_instruction_entry_map; + cur_datablock=&build_datablock; + cur_datablock_cache=&build_datablock_cache; + cur_functions=&build_functions; + cur_labels=&build_labels; + cur_sections=&build_sections; + cur_header=&build_header; + cur_strlist=&build_strlist; + cur_langtables=&build_langtables; + cur_ctlcolors=&build_ctlcolors; + cur_pages=&build_pages; + cur_page=0; + cur_page_type=-1; + + build_filebuflen=32<<20; // 32mb + + sectiongroup_open_cnt=0; + build_cursection_isfunc=0; + build_cursection=NULL; + // init public data. + build_packname[0]=build_packcmd[0]=build_output_filename[0]=0; + + // Added by ramon 23 May 2003 + build_allowskipfiles=1; + + // Added by ramon 6 jun 2003 +#ifdef NSIS_SUPPORT_VERSION_INFO + version_product_v[0]=0; +#endif + + build_overwrite=build_last_overwrite=0; + build_crcchk=1; + build_datesave=1; + build_optimize_datablock=1; + + memset(&build_header,-1,sizeof(build_header)); + + build_header.install_reg_rootkey=0; + build_header.flags=CH_FLAGS_NO_ROOT_DIR; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + build_header.lb_bg=RGB(0,0,0); + build_header.lb_fg=RGB(0,255,0); +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE + build_header.license_bg=-COLOR_BTNFACE; +#endif + build_header.install_directory_ptr=0; + build_header.install_directory_auto_append=0; + build_header.install_reg_key_ptr=0; + build_header.install_reg_value_ptr=0; +#ifdef NSIS_CONFIG_COMPONENTPAGE + memset(build_header.install_types,0,sizeof(build_header.install_types)); +#endif + memset(&build_header.blocks,0,sizeof(build_header.blocks)); + + uninstall_mode=0; + uninstall_size_full=0; + uninstall_size=-1; + + memset(&build_uninst,-1,sizeof(build_uninst)); + + build_header.install_reg_rootkey=0; + build_uninst.flags=0; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + build_uninst.lb_bg=RGB(0,0,0); + build_uninst.lb_fg=RGB(0,255,0); +#endif +#ifdef NSIS_CONFIG_LICENSEPAGE + build_uninst.license_bg=-COLOR_BTNFACE; +#endif + build_uninst.install_directory_ptr=0; + build_uninst.install_directory_auto_append=0; + build_uninst.install_reg_key_ptr=0; + build_uninst.install_reg_value_ptr=0; +#ifdef NSIS_CONFIG_COMPONENTPAGE + memset(build_uninst.install_types,0,sizeof(build_uninst.install_types)); +#endif + memset(&build_uninst.blocks,0,sizeof(build_uninst.blocks)); + + uninstaller_writes_used=0; + + build_strlist.add("",0); + ubuild_strlist.add("",0); + + build_langstring_num=0; + ubuild_langstring_num=0; + + build_font[0]=0; + build_font_size=0; + + m_unicon_size=0; + + branding_image_found=false; + + no_space_texts=false; + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + build_plugin_unload=0; + plugins_processed=0; +#endif + + last_used_lang=NSIS_DEFAULT_LANG; + + res_editor=0; + + manifest_comctl = manifest::comctl_old; + manifest_exec_level = manifest::exec_level_none; + + enable_last_page_cancel=0; + uenable_last_page_cancel=0; + + license_res_id=IDD_LICENSE; + + disable_window_icon=0; + + notify_hwnd=0; + +#ifdef NSIS_SUPPORT_BGBG + bg_default_font.lfHeight=40; + bg_default_font.lfWidth=0; + bg_default_font.lfEscapement=0; + bg_default_font.lfOrientation=0; + bg_default_font.lfWeight=FW_BOLD; + bg_default_font.lfItalic=TRUE; + bg_default_font.lfUnderline=FALSE; + bg_default_font.lfStrikeOut=FALSE; + bg_default_font.lfCharSet=DEFAULT_CHARSET; + bg_default_font.lfOutPrecision=OUT_DEFAULT_PRECIS; + bg_default_font.lfClipPrecision=CLIP_DEFAULT_PRECIS; + bg_default_font.lfQuality=DEFAULT_QUALITY; + bg_default_font.lfPitchAndFamily=DEFAULT_PITCH; + strncpy(bg_default_font.lfFaceName,"Times New Roman",LF_FACESIZE); + memcpy(&bg_font,&bg_default_font,sizeof(LOGFONT)); +#endif + + defcodepage_set=false; + uDefCodePage=CP_ACP; + + InitLangTables(); + + // Register static user variables $0, $1 and so on + // with ONE of reference count, to avoid warning on this vars + char Aux[3]; + int i; + for (i = 0; i < 10; i++) // 0 - 9 + { + sprintf(Aux, "%d", i); + m_UserVarNames.add(Aux,1); + } + for (i = 0; i < 10; i++) // 10 - 19 + { + sprintf(Aux, "R%d", i); + m_UserVarNames.add(Aux,1); + } + m_UserVarNames.add("CMDLINE",1); // 20 everything before here doesn't have trailing slash removal + m_UserVarNames.add("INSTDIR",1); // 21 + m_UserVarNames.add("OUTDIR",1); // 22 + m_UserVarNames.add("EXEDIR",1); // 23 + m_UserVarNames.add("LANGUAGE",1); // 24 + m_UserVarNames.add("TEMP",-1); // 25 + m_UserVarNames.add("PLUGINSDIR",-1); // 26 + m_UserVarNames.add("EXEPATH",-1); // 27 + m_UserVarNames.add("EXEFILE",-1); // 28 + m_UserVarNames.add("HWNDPARENT",-1); // 29 + m_UserVarNames.add("_CLICK",-1); // 30 + m_UserVarNames.add("_OUTDIR",1); // 31 + + m_iBaseVarsNum = m_UserVarNames.getnum(); + + m_ShellConstants.add("WINDIR",CSIDL_WINDOWS,CSIDL_WINDOWS); + m_ShellConstants.add("SYSDIR",CSIDL_SYSTEM,CSIDL_SYSTEM); + m_ShellConstants.add("SMPROGRAMS",CSIDL_PROGRAMS, CSIDL_COMMON_PROGRAMS); + m_ShellConstants.add("SMSTARTUP",CSIDL_STARTUP, CSIDL_COMMON_STARTUP); + m_ShellConstants.add("DESKTOP",CSIDL_DESKTOPDIRECTORY, CSIDL_COMMON_DESKTOPDIRECTORY); + m_ShellConstants.add("STARTMENU",CSIDL_STARTMENU, CSIDL_COMMON_STARTMENU); + m_ShellConstants.add("QUICKLAUNCH", CSIDL_APPDATA, CSIDL_APPDATA); + m_ShellConstants.add("DOCUMENTS",CSIDL_PERSONAL, CSIDL_COMMON_DOCUMENTS); + m_ShellConstants.add("SENDTO",CSIDL_SENDTO, CSIDL_SENDTO); + m_ShellConstants.add("RECENT",CSIDL_RECENT, CSIDL_RECENT); + m_ShellConstants.add("FAVORITES",CSIDL_FAVORITES, CSIDL_COMMON_FAVORITES); + m_ShellConstants.add("MUSIC",CSIDL_MYMUSIC, CSIDL_COMMON_MUSIC); + m_ShellConstants.add("PICTURES",CSIDL_MYPICTURES, CSIDL_COMMON_PICTURES); + m_ShellConstants.add("VIDEOS",CSIDL_MYVIDEO, CSIDL_COMMON_VIDEO); + m_ShellConstants.add("NETHOOD", CSIDL_NETHOOD, CSIDL_NETHOOD); + m_ShellConstants.add("FONTS", CSIDL_FONTS, CSIDL_FONTS); + m_ShellConstants.add("TEMPLATES", CSIDL_TEMPLATES, CSIDL_COMMON_TEMPLATES); + m_ShellConstants.add("APPDATA", CSIDL_APPDATA, CSIDL_COMMON_APPDATA); + m_ShellConstants.add("LOCALAPPDATA", CSIDL_LOCAL_APPDATA, CSIDL_LOCAL_APPDATA); + m_ShellConstants.add("PRINTHOOD", CSIDL_PRINTHOOD, CSIDL_PRINTHOOD); + //m_ShellConstants.add("ALTSTARTUP", CSIDL_ALTSTARTUP, CSIDL_COMMON_ALTSTARTUP); + m_ShellConstants.add("INTERNET_CACHE", CSIDL_INTERNET_CACHE, CSIDL_INTERNET_CACHE); + m_ShellConstants.add("COOKIES", CSIDL_COOKIES, CSIDL_COOKIES); + m_ShellConstants.add("HISTORY", CSIDL_HISTORY, CSIDL_HISTORY); + m_ShellConstants.add("PROFILE", CSIDL_PROFILE, CSIDL_PROFILE); + m_ShellConstants.add("ADMINTOOLS", CSIDL_ADMINTOOLS, CSIDL_COMMON_ADMINTOOLS); + m_ShellConstants.add("RESOURCES", CSIDL_RESOURCES, CSIDL_RESOURCES); + m_ShellConstants.add("RESOURCES_LOCALIZED", CSIDL_RESOURCES_LOCALIZED, CSIDL_RESOURCES_LOCALIZED); + m_ShellConstants.add("CDBURN_AREA", CSIDL_CDBURN_AREA, CSIDL_CDBURN_AREA); + + unsigned int program_files = add_string("ProgramFilesDir", 0); + unsigned int program_files_def = add_string("C:\\Program Files"); + + if ((program_files >= 0x40) || (program_files_def >= 0xFF)) + { + // see Source\exehead\util.c for implementation details + // basically, it knows it needs to get folders from the registry when the 0x80 is on + ERROR_MSG("Internal compiler error: too many strings added to strings block before adding shell constants!\n"); + throw out_of_range("Internal compiler error: too many strings added to strings block before adding shell constants!"); + } + + m_ShellConstants.add("PROGRAMFILES", 0x80 | program_files, program_files_def); + m_ShellConstants.add("PROGRAMFILES32", 0x80 | program_files, program_files_def); + m_ShellConstants.add("PROGRAMFILES64", 0xC0 | program_files, program_files_def); + + unsigned int common_files = add_string("CommonFilesDir", 0); + unsigned int common_files_def = add_string("$PROGRAMFILES\\Common Files"); + + if ((common_files > 0x40) || (common_files_def > 0xFF)) + { + ERROR_MSG("Internal compiler error: too many strings added to strings block before adding shell constants!\n"); + throw out_of_range("Internal compiler error: too many strings added to strings block before adding shell constants!"); + } + + m_ShellConstants.add("COMMONFILES", 0x80 | common_files, common_files_def); + m_ShellConstants.add("COMMONFILES32", 0x80 | common_files, common_files_def); + m_ShellConstants.add("COMMONFILES64", 0xC0 | common_files, common_files_def); + + set_uninstall_mode(1); + + unsigned int uprogram_files = add_string("ProgramFilesDir", 0); + unsigned int uprogram_files_def = add_string("C:\\Program Files"); + unsigned int ucommon_files = add_string("CommonFilesDir", 0); + unsigned int ucommon_files_def = add_string("$PROGRAMFILES\\Common Files"); + + if (uprogram_files != program_files + || uprogram_files_def != program_files_def + || ucommon_files != common_files + || ucommon_files_def != common_files_def) + { + ERROR_MSG("Internal compiler error: installer's shell constants are different than uninstallers!\n"); + throw out_of_range("Internal compiler error: installer's shell constants are different than uninstallers!"); + } + + set_uninstall_mode(0); + + set_code_type_predefines(); +} + +void CEXEBuild::initialize(const char *makensis_path) +{ + string nsis_dir; + const char *dir = getenv("NSISDIR"); + if (dir) nsis_dir = dir; + else { +#ifndef NSIS_CONFIG_CONST_DATA_PATH + nsis_dir = get_executable_dir(makensis_path); +#else + nsis_dir = PREFIX_DATA; +#endif + } + definedlist.add("NSISDIR", nsis_dir.c_str()); + + string includes_dir = nsis_dir; + includes_dir += PLATFORM_PATH_SEPARATOR_STR"Include"; + include_dirs.add(includes_dir.c_str(),0); + + stubs_dir = nsis_dir; + stubs_dir += PLATFORM_PATH_SEPARATOR_STR"Stubs"; + + if (set_compressor("zlib", false) != PS_OK) + { + throw runtime_error("error setting default stub"); + } + + string uninst = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + "uninst"; + uninstaller_icon = load_icon_file(uninst.c_str()); +} + + +int CEXEBuild::getcurdbsize() { return cur_datablock->getlen(); } + +// returns offset in stringblock +int CEXEBuild::add_string(const char *string, int process/*=1*/, WORD codepage/*=CP_ACP*/) +{ + if (!string || !*string) return 0; + + if (*string == '$' && *(string+1) == '(') { + int idx = 0; + char *cp = strdup(string+2); + char *p = strchr(cp, ')'); + if (p && p[1] == '\0' ) { // if string is only a language str identifier + *p = 0; + idx = DefineLangString(cp, process); + } + free(cp); + if (idx < 0) return idx; + } + + if (!process) return cur_strlist->add(string,2); + + char buf[NSIS_MAX_STRLEN*4]; + preprocess_string(buf,string,codepage); + return cur_strlist->add(buf,2); +} + +int CEXEBuild::add_intstring(const int i) // returns offset in stringblock +{ + char i_str[1024]; + wsprintf(i_str, "%d", i); + return add_string(i_str); +} + +// based on Dave Laundon's code +int CEXEBuild::preprocess_string(char *out, const char *in, WORD codepage/*=CP_ACP*/) +{ + const char *p=in; + while (*p) + { + const char *np = CharNextExA(codepage, p, 0); + if (np - p > 1) // multibyte char + { + int l = np - p; + while (l--) + { + unsigned char i = (unsigned char)*p++; + if (i >= NS_CODES_START) { + *out++ = (char)NS_SKIP_CODE; + } + *out++=(char)i; + } + continue; + } + + unsigned char i = (unsigned char)*p; + + p=np; + + // Test for characters extending into the variable codes + if (i >= NS_CODES_START) { + *out++ = (char)NS_SKIP_CODE; + } + else if (i == '$') + { + if (*p == '$') + p++; // Can simply convert $$ to $ now + else + { + { + bool bProceced=false; + if ( *p ) + { + const char *pUserVarName = p; + while (isSimpleChar(*pUserVarName)) + pUserVarName++; + + while (pUserVarName > p) + { + if (m_ShellConstants.get((char*)p, pUserVarName-p) >= 0) + break; // Upps it's a shell constant + + int idxUserVar = m_UserVarNames.get((char*)p, pUserVarName-p); + if (idxUserVar >= 0) + { + // Well, using variables inside string formating doens't mean + // using the variable, beacuse it will be always an empty string + // which is also memory wasting + // So the line below must be commented !?? + //m_UserVarNames.inc_reference(idxUserVar); + *out++ = (char) NS_VAR_CODE; // Named user variable; + WORD w = FIX_ENDIAN_INT16(CODE_SHORT(idxUserVar)); + memcpy(out, &w, sizeof(WORD)); + out += sizeof(WORD); + p += pUserVarName-p; + bProceced = true; + break; + } + pUserVarName--; + } + } + if (!bProceced && *p) + { + const char *pShellConstName = p; + while (isSimpleChar(*pShellConstName)) + pShellConstName++; + + while (pShellConstName > p) + { + int idxConst = m_ShellConstants.get((char*)p, pShellConstName - p); + if (idxConst >= 0) + { + int CSIDL_Value_current = m_ShellConstants.get_value1(idxConst); + int CSIDL_Value_all = m_ShellConstants.get_value2(idxConst); + *out++=(char)NS_SHELL_CODE; // Constant code identifier + *out++=(char)CSIDL_Value_current; + *out++=(char)CSIDL_Value_all; + p = pShellConstName; + bProceced = true; + break; + } + pShellConstName--; + } + } + if ( !bProceced && *p == '(' ) + { + int idx = -1; + char *cp = strdup(p+1); + char *pos = strchr(cp, ')'); + if (pos) + { + *pos = 0; + idx = DefineLangString(cp); + if (idx < 0) + { + *out++ = (char)NS_LANG_CODE; // Next word is lang-string Identifier + WORD w = FIX_ENDIAN_INT16(CODE_SHORT(-idx-1)); + memcpy(out, &w, sizeof(WORD)); + out += sizeof(WORD); + p += strlen(cp) + 2; + bProceced = true; + } + } + free(cp); + } + if ( bProceced ) + continue; + else + { + char tbuf[64]; + char cBracket = '\0'; + bool bDoWarning = true; + + if ( *p == '[' ) + cBracket = ']'; + else if ( *p == '(' ) + cBracket = ')'; + else if ( *p == '{' ) + cBracket = '}'; + + strncpy(tbuf,p,63); + tbuf[63]=0; + + if ( cBracket != 0 ) + { + if (strchr(tbuf,cBracket)) (strchr(tbuf,cBracket)+1)[0]=0; + if ( tbuf[0] == '{' && tbuf[strlen(tbuf)-1] == '}' ) + { + char *tstIfDefine = strdup(tbuf+1); + tstIfDefine[strlen(tstIfDefine)-1] = '\0'; + bDoWarning = definedlist.find(tstIfDefine) == NULL; + } + } + else + { + if (strstr(tbuf," ")) strstr(tbuf," ")[0]=0; + } + if ( bDoWarning ) + warning_fl("unknown variable/constant \"%s\" detected, ignoring",tbuf); + i = '$'; + } + } + } + } + *out++=(char)i; + } + *out=0; + return 0; +} + +// what it does is, when you pass it the offset of the last item added, it will determine if +// that data is already present in the datablock, and if so, reference it instead (and shorten +// the datablock as necessary). Reduces overhead if you want to add files to a couple places. +// Woo, an optimizing installer generator, now we're styling. + +int CEXEBuild::datablock_optimize(int start_offset, int first_int) +{ + int this_len = cur_datablock->getlen() - start_offset; + + cached_db_size this_size = {first_int, start_offset}; + cur_datablock_cache->add(&this_size, sizeof(cached_db_size)); + + if (!build_optimize_datablock || this_len < (int) sizeof(int)) + return start_offset; + + MMapBuf *db = (MMapBuf *) cur_datablock; + db->setro(TRUE); + + cached_db_size *db_sizes = (cached_db_size *) cur_datablock_cache->get(); + int db_sizes_num = cur_datablock_cache->getlen() / sizeof(cached_db_size); + db_sizes_num--; // don't compare with the one we just added + + for (int i = 0; i < db_sizes_num; i++) + { + if (db_sizes[i].first_int == first_int) + { + int pos = db_sizes[i].start_offset; + int left = this_len; + while (left > 0) + { + int l = min(left, build_filebuflen); + void *newstuff = db->get(start_offset + this_len - left, l); + void *oldstuff = db->getmore(pos + this_len - left, l); + + int res = memcmp(newstuff, oldstuff, l); + + db->release(oldstuff, l); + db->release(); + + if (res) + { + break; + } + + left -= l; + } + + if (!left) + { + db_opt_save += this_len; + db->resize(max(start_offset, pos + this_len)); + db->setro(FALSE); + cur_datablock_cache->resize(cur_datablock_cache->getlen() - sizeof(cached_db_size)); + return pos; + } + } + } + + db->setro(FALSE); + + return start_offset; +} + +int CEXEBuild::add_db_data(IMMap *mmap) // returns offset +{ + build_compressor_set = true; + + int done = 0; + + if (!mmap) + { + ERROR_MSG("Error: add_db_data() called with invalid mapped file\n"); + return -1; + } + + int length = mmap->getsize(); + + if (length < 0) + { + ERROR_MSG("Error: add_db_data() called with length=%d\n", length); + return -1; + } + + MMapBuf *db = (MMapBuf *) cur_datablock; + + int st = db->getlen(); + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (length && !build_compress_whole && build_compress) + { + // grow datablock so that there is room to compress into + int bufferlen = length + 1024 + length / 4; // give a nice 25% extra space + db->resize(st + bufferlen + sizeof(int)); + + int n = compressor->Init(build_compress_level, build_compress_dict_size); + if (n != C_OK) + { + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n); + extern void quit(); quit(); + } + + int avail_in = length; + int avail_out = bufferlen; + int ret; + while (avail_in > 0) + { + int in_len = min(build_filebuflen, avail_in); + int out_len = min(build_filebuflen, avail_out); + + compressor->SetNextIn((char *) mmap->get(length - avail_in, in_len), in_len); + compressor->SetNextOut((char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len), out_len); + if ((ret = compressor->Compress(0)) < 0) + { + ERROR_MSG("Error: add_db_data() - compress() failed(%s [%d])\n", compressor->GetErrStr(ret), ret); + return -1; + } + mmap->release(); + db->flush(out_len); + db->release(); + avail_in -= in_len - compressor->GetAvailIn(); + avail_out -= out_len - compressor->GetAvailOut(); + + if (!avail_out) + // not enough space in the output buffer - no compression is better + break; + } + + // if not enough space in the output buffer - no compression is better + if (avail_out) + { + char *out; + + char a; + compressor->SetNextIn(&a,0); + + do + { + int out_len = min(build_filebuflen, avail_out); + + out = (char *) db->get(st + sizeof(int) + bufferlen - avail_out, out_len); + + compressor->SetNextOut(out, out_len); + if ((ret = compressor->Compress(C_FINISH)) < 0) + { + ERROR_MSG("Error: add_db_data() - compress() failed(%s [%d])\n", compressor->GetErrStr(ret), ret); + return -1; + } + + db->flush(out_len); + db->release(); + + avail_out -= out_len - compressor->GetAvailOut(); + } + while (compressor->GetNextOut() - out > 0 && avail_out > 0); + + compressor->End(); + + int used = bufferlen - avail_out; + + // never store compressed if output buffer is full (compression increased the size...) + if (avail_out && (build_compress == 2 || used < length)) + { + done=1; + db->resize(st + used + sizeof(int)); + + *(int*)db->get(st, sizeof(int)) = FIX_ENDIAN_INT32(used | 0x80000000); + db->release(); + + int nst = datablock_optimize(st, used | 0x80000000); + if (nst == st) db_comp_save += length - used; + else st = nst; + } + } + else + compressor->End(); + } +#endif // NSIS_CONFIG_COMPRESSION_SUPPORT + + if (!done) + { + db->resize(st + length + sizeof(int)); + int *plen = (int *) db->get(st, sizeof(int)); + *plen = FIX_ENDIAN_INT32(length); + db->release(); + + int left = length; + while (left > 0) + { + int l = min(build_filebuflen, left); + int *p = (int *) db->get(st + sizeof(int) + length - left, l); + memcpy(p, mmap->get(length - left, l), l); + db->flush(l); + db->release(); + mmap->release(); + left -= l; + } + + st = datablock_optimize(st, length); + } + + db_full_size += length + sizeof(int); + + return st; +} + +int CEXEBuild::add_db_data(const char *data, int length) // returns offset +{ + MMapFake fakemap; + fakemap.set(data, length); + return add_db_data(&fakemap); +} + +int CEXEBuild::add_data(const char *data, int length, IGrowBuf *dblock) // returns offset +{ + build_compressor_set=true; + + int done=0; + + if (length < 0) + { + ERROR_MSG("Error: add_data() called with length=%d\n",length); + return -1; + } + + int st=dblock->getlen(); + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (!build_compress_whole && build_compress) + { + // grow datablock so that there is room to compress into + int bufferlen=length+1024+length/4; // give a nice 25% extra space + dblock->resize(st+bufferlen+sizeof(int)); + + int n = compressor->Init(build_compress_level, build_compress_dict_size); + if (n != C_OK) + { + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n); + extern void quit(); quit(); + } + + compressor->SetNextIn((char*)data, length); + compressor->SetNextOut((char*)dblock->get() + st + sizeof(int), bufferlen); + + compressor->Compress(C_FINISH); + + int used=bufferlen-compressor->GetAvailOut(); + + // never store compressed if output buffer is full + if (compressor->GetAvailOut() && (build_compress == 2 || used < length)) + { + done=1; + dblock->resize(st+used+sizeof(int)); + + *((int*)((char *)dblock->get()+st)) = FIX_ENDIAN_INT32(used|0x80000000); + } + compressor->End(); + } +#endif // NSIS_CONFIG_COMPRESSION_SUPPORT + + if (!done) + { + dblock->resize(st); + int rl = FIX_ENDIAN_INT32(length); + dblock->add(&rl,sizeof(int)); + dblock->add(data,length); + } + + return st; +} + +int CEXEBuild::add_label(const char *name) +{ + if (!build_cursection) + { + ERROR_MSG("Error: Label declaration not valid outside of function/section\n"); + return PS_ERROR; + } + if ((name[0] >= '0' && name[0] <= '9') || name[0] == '-' || name[0] == ' ' || name[0] == ':') + { + ERROR_MSG("Error: labels must not begin with 0-9, -, :, or a space.\n"); + return PS_ERROR; + } + + int cs=build_cursection->code; + int ce=cs+build_cursection->code_size; + + char *p=strdup(name); + if (p[strlen(p)-1] == ':') p[strlen(p)-1]=0; + int offs=ns_label.add(p,0); + free(p); + + int n=cur_labels->getlen()/sizeof(section); + if (n) + { + section *t=(section*)cur_labels->get(); + while (n--) + { + if ((*name == '.' || (t->code >= cs && t->code <= ce)) && + t->name_ptr==offs) + { + if (*name == '.') ERROR_MSG("Error: global label \"%s\" already declared\n",name); + else + { + char *t = "section"; + if (build_cursection_isfunc) + t = "function"; + ERROR_MSG("Error: label \"%s\" already declared in %s\n",name,t); + } + return PS_ERROR; + } + t++; + } + } + + section s={0}; + s.name_ptr = offs; + s.code = ce; + cur_labels->add(&s,sizeof(s)); + + return PS_OK; +} + +int CEXEBuild::add_function(const char *funname) +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Function open when creating function (use FunctionEnd first)\n"); + return PS_ERROR; + } + if (build_cursection) + { + ERROR_MSG("Error: Section open when creating function (use SectionEnd first)\n"); + return PS_ERROR; + } + if (cur_page) + { + ERROR_MSG("Error: PageEx open when creating function (use PageExEnd first)\n"); + return PS_ERROR; + } + if (!funname[0]) + { + ERROR_MSG("Error: Function must have a name\n"); + return PS_ERROR; + } + + set_uninstall_mode(!strnicmp(funname,"un.",3)); + + int addr=ns_func.add(funname,0); + int x; + int n=cur_functions->getlen()/sizeof(section); + section *tmp=(section*)cur_functions->get(); + for (x = 0; x < n; x ++) + { + if (tmp[x].name_ptr == addr) + { + ERROR_MSG("Error: Function named \"%s\" already exists.\n",funname); + return PS_ERROR; + } + } + + cur_functions->resize((n+1)*sizeof(section)); + build_cursection=((section*)cur_functions->get())+n; + build_cursection_isfunc=1; + build_cursection->name_ptr=addr; + build_cursection->code=cur_entries->getlen()/sizeof(entry); + build_cursection->code_size=0; + build_cursection->install_types=0; + build_cursection->flags=0; + build_cursection->size_kb=0; + memset(build_cursection->name,0,sizeof(build_cursection->name)); + + if (uninstall_mode) + set_code_type_predefines(funname+3); + else + set_code_type_predefines(funname); + + return PS_OK; +} + +int CEXEBuild::function_end() +{ + if (!build_cursection_isfunc) + { + ERROR_MSG("Error: No function open, FunctionEnd called\n"); + return PS_ERROR; + } + // add ret. + add_entry_direct(EW_RET); + + build_cursection_isfunc=0; + build_cursection=NULL; + + set_uninstall_mode(0); + + set_code_type_predefines(); + return PS_OK; +} + + +int CEXEBuild::section_add_flags(int flags) +{ + if (!build_cursection || build_cursection_isfunc) + { + ERROR_MSG("Error: can't modify flags when no section is open\n"); + return PS_ERROR; + } + build_cursection->flags |= flags; + return PS_OK; +} + +int CEXEBuild::section_add_install_type(int inst_type) +{ + if (!build_cursection || build_cursection_isfunc) + { + ERROR_MSG("Error: can't modify flags when no section is open\n"); + return PS_ERROR; + } + if (build_cursection->install_types == ~0) + build_cursection->install_types = 0; + build_cursection->install_types |= inst_type; + return PS_OK; +} + +void CEXEBuild::section_add_size_kb(int kb) +{ + if (build_cursection) + { + build_cursection->size_kb+=kb; + } +} + +int CEXEBuild::section_end() +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: SectionEnd specified in function (not section)\n"); + return PS_ERROR; + } + if (!build_cursection) + { + ERROR_MSG("Error: SectionEnd specified and no sections open\n"); + return PS_ERROR; + } + add_entry_direct(EW_RET); + build_cursection->code_size--; + build_cursection=NULL; + if (!sectiongroup_open_cnt) + set_uninstall_mode(0); + + set_code_type_predefines(); + return PS_OK; +} + +int CEXEBuild::add_section(const char *secname, const char *defname, int expand/*=0*/) +{ + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Section can't create section (already in function, use FunctionEnd first)\n"); + return PS_ERROR; + } + if (cur_page) { + ERROR_MSG("Error: PageEx already open, call PageExEnd first\n"); + return PS_ERROR; + } + if (build_cursection) + { + ERROR_MSG("Error: Section already open, call SectionEnd first\n"); + return PS_ERROR; + } + + section new_section; + new_section.flags = SF_SELECTED; + new_section.flags |= expand ? SF_EXPAND : 0; + new_section.code_size = 0; + new_section.size_kb = 0; + + char *name = (char*)secname; + + if (secname[0] == '-') + { + if (secname[1]) + { + new_section.flags |= SF_SECGRP; + name++; + } + else + new_section.flags |= SF_SECGRPEND; + } + + if (name[0] == '!') + { + name++; + new_section.flags |= SF_BOLD; + } + + int old_uninstall_mode = uninstall_mode; + + set_uninstall_mode(0); + + if (!strnicmp(name, "un.", 3)) + { + set_uninstall_mode(1); + name += 3; + } + + if (!stricmp(name, "uninstall")) + { + set_uninstall_mode(1); + } + + if ((new_section.flags & SF_SECGRPEND) && sectiongroup_open_cnt && old_uninstall_mode) + { + set_uninstall_mode(1); + } + + if (sectiongroup_open_cnt) + { + if (uninstall_mode != old_uninstall_mode) + { + ERROR_MSG("Error: Can't create %s section in %s section group (use SectionGroupEnd first)\n", uninstall_mode ? "uninstaller" : "installer", old_uninstall_mode ? "uninstaller" : "installer"); + return PS_ERROR; + } + } + + new_section.code = cur_entries->getlen() / sizeof(entry); + + new_section.install_types = *name ? 0 : ~0; + new_section.name_ptr = add_string(name); + memset(&new_section.name,0,sizeof(new_section.name)); + + cur_sections->add(&new_section, sizeof(section)); + build_cursection = (section *) cur_sections->get() + cur_header->blocks[NB_SECTIONS].num; + + if (defname[0]) + { + char buf[1024]; + wsprintf(buf, "%d", cur_header->blocks[NB_SECTIONS].num); + if (definedlist.add(defname, buf)) + { + ERROR_MSG("Error: \"%s\" already defined, can't assign section index!\n", defname); + return PS_ERROR; + } + } + + cur_header->blocks[NB_SECTIONS].num++; + + if (new_section.flags & (SF_SECGRP | SF_SECGRPEND)) + { + add_entry_direct(EW_RET); + build_cursection->code_size = 0; + + build_cursection = 0; + + if (new_section.flags & SF_SECGRPEND) + { + sectiongroup_open_cnt--; + if (sectiongroup_open_cnt < 0) + { + ERROR_MSG("SectionGroupEnd: no SectionGroups are open\n"); + return PS_ERROR; + } + if (!sectiongroup_open_cnt) + { + set_uninstall_mode(0); + } + } + else + sectiongroup_open_cnt++; + } + + set_code_type_predefines(name); + + return PS_OK; +} + +int CEXEBuild::add_entry(const entry *ent) +{ + if (!build_cursection && !uninstall_mode) + { + ERROR_MSG("Error: Can't add entry, no section or function is open!\n"); + return PS_ERROR; + } + + cur_entries->add(ent,sizeof(entry)); + cur_instruction_entry_map->add(&multiple_entries_instruction,sizeof(int)); + build_cursection->code_size++; + cur_header->blocks[NB_ENTRIES].num++; + + multiple_entries_instruction=1; + + return PS_OK; +} + +int CEXEBuild::add_entry_direct(int which, int o0, int o1, int o2, int o3, int o4, int o5 /*o#=0*/) +{ + entry ent; + ent.which = which; + ent.offsets[0] = o0; + ent.offsets[1] = o1; + ent.offsets[2] = o2; + ent.offsets[3] = o3; + ent.offsets[4] = o4; + ent.offsets[5] = o5; + return add_entry(&ent); +} + +int CEXEBuild::resolve_jump_int(const char *fn, int *a, int offs, int start, int end) +{ + if (*a > 0) + { + char *lname=(char*)ns_label.get()+*a; + if (lname[0] == '-' || lname[0]=='+') + { + int jump = atoi(lname); + int *skip_map = (int *) cur_instruction_entry_map->get(); + int maxoffs = cur_instruction_entry_map->getlen() / (int) sizeof(int); + + int direction = 1; + if (jump < 0) + direction = -1; + + for (; jump != 0; jump -= direction) + { + offs += direction; + if (offs >= 0 && offs < maxoffs) + { + while (skip_map[offs]) + { + offs += direction; + } + } + } + + *a = offs + 1; + } + else + { + section *s = (section*)cur_labels->get(); + int n=cur_labels->getlen()/sizeof(section); + while (n-->0) + { + if ((*lname == '.' || (s->code >= start && s->code <= end)) && s->name_ptr == *a) + { + *a = s->code+1; // jumps are to the absolute position, +1 (to differentiate between no jump, and jumping to offset 0) + s->flags++; + return 0; + } + s++; + } + + ERROR_MSG("Error: could not resolve label \"%s\" in %s\n",lname,fn); + return 1; + } + } + else if (*a < 0) // to jump to a user variable target, -variable_index-1 is already stored. + { + } + // otherwise, *a is 0, which means no jump and we also leave it intact + return 0; +} + +int CEXEBuild::resolve_call_int(const char *fn, const char *str, int fptr, int *ofs) +{ + if (fptr < 0) return 0; + int nf=cur_functions->getlen()/sizeof(section); + section *sec=(section *)cur_functions->get(); + while (nf-- > 0) + { + if (sec->name_ptr>0 && sec->name_ptr == fptr) + { + ofs[0]=sec->code; + sec->flags++; + return 0; + } + sec++; + } + ERROR_MSG("Error: resolving %s function \"%s\" in %s\n",str,(char*)ns_func.get()+fptr,fn); + ERROR_MSG("Note: uninstall functions must begin with \"un.\", and install functions must not\n"); + return 1; +} + +int CEXEBuild::resolve_instruction(const char *fn, const char *str, entry *w, int offs, int start, int end) +{ + if (w->which == EW_NOP) + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + } +#ifdef NSIS_SUPPORT_MESSAGEBOX + else if (w->which == EW_MESSAGEBOX) + { + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[5],offs,start,end)) return 1; + } +#endif + else if (w->which == EW_IFFILEEXISTS) + { + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + } + else if (w->which == EW_IFFLAG) + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + } +#ifdef NSIS_SUPPORT_STROPTS + else if (w->which == EW_STRCMP) + { + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + } +#endif +#ifdef NSIS_SUPPORT_INTOPTS + else if (w->which == EW_INTCMP) + { + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[3],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[4],offs,start,end)) return 1; + } +#endif +#ifdef NSIS_SUPPORT_HWNDS + else if (w->which == EW_ISWINDOW) + { + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + if (resolve_jump_int(fn,&w->offsets[2],offs,start,end)) return 1; + } +#endif + else if (w->which == EW_CALL) + { + if (w->offsets[0] >= 0 && w->offsets[1]) // get as jump + { + if (resolve_jump_int(fn,&w->offsets[0],offs,start,end)) return 1; + } + else + { + if (w->offsets[0] >= 0 && resolve_call_int(fn,str,w->offsets[0],w->offsets)) return 1; + // if w->offsets[0] >= 0, EW_CALL requires that it 1-based. + // otherwise, if < 0, it needs an increment anyway (since it + // was encoded with a -2 base, to prevent it looking like an + // empty string "") + w->offsets[0]++; + } + } +#ifdef NSIS_SUPPORT_STROPTS + else if (w->which == EW_GETFUNCTIONADDR) + { + if (w->offsets[1] < 0) + { + ERROR_MSG("Error: GetFunctionAddress requires a real function to get address of.\n"); + return 1; + } + + if (resolve_call_int(fn,str,w->offsets[1],&w->offsets[1])) return 1; + + w->which=EW_ASSIGNVAR; + w->offsets[1]=add_intstring(w->offsets[1]+1); // +1 here to make 1-based. + } + else if (w->which == EW_GETLABELADDR) + { + if (resolve_jump_int(fn,&w->offsets[1],offs,start,end)) return 1; + w->which=EW_ASSIGNVAR; + w->offsets[1]=add_intstring(w->offsets[1]); + } +#endif + return 0; +} + +int CEXEBuild::resolve_coderefs(const char *str) +{ + // resolve jumps&calls + { + section *sec=(section *)cur_functions->get(); + int l=cur_functions->getlen()/sizeof(section); + entry *w=(entry *)cur_entries->get(); + while (l-- > 0) + { + int x; + for (x = sec->code; x < sec->code+sec->code_size; x ++) + { + char fname[1024]; + wsprintf(fname,"function \"%s\"",ns_func.get()+sec->name_ptr); + if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) return 1; + } + sec++; + } + + int cnt=0; + sec=(section *)cur_sections->get(); + l=cur_sections->getlen()/sizeof(section); + while (l-- > 0) + { + int x=sec->name_ptr; + char fname[1024]; + const char *section_name; + if (x < 0) + { + // lang string + section_name = "$(lang string)"; + } + else + { + // normal string + section_name = cur_strlist->get() + x; + } + if (x) wsprintf(fname,"%s section \"%s\" (%d)",str,section_name,cnt); + else wsprintf(fname,"unnamed %s section (%d)",str,cnt); + for (x = sec->code; x < sec->code+sec->code_size; x ++) + { + if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) + return 1; + } + sec++; + cnt++; + } +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (cur_pages->getlen()) { + page *p=(page *)cur_pages->get(); + int i = 0; + while (i < cur_header->blocks[NB_PAGES].num) { + char pagestr[1024]; + wsprintf(pagestr, "%s pages", str); + if (resolve_call_int(pagestr,p->dlg_id?"pre-page":"create-page",p->prefunc,&p->prefunc)) return 1; + if (resolve_call_int(pagestr,"show-page",p->showfunc,&p->showfunc)) return 1; + if (resolve_call_int(pagestr,"leave-page",p->leavefunc,&p->leavefunc)) return 1; + p++; + i++; + } + } +#endif +#endif + } + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // resolve callbacks + { + struct { + char *name; + int *p; + } callbacks[] = { + {"%s.onInit", &cur_header->code_onInit}, + {"%s.on%sInstSuccess", &cur_header->code_onInstSuccess}, + {"%s.on%sInstFailed", &cur_header->code_onInstFailed}, + {"%s.onUserAbort", &cur_header->code_onUserAbort}, + {"%s.onVerifyInstDir", &cur_header->code_onVerifyInstDir}, +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + {"%s.onGUIInit", &cur_header->code_onGUIInit}, + {"%s.onGUIEnd", &cur_header->code_onGUIEnd}, + {"%s.onMouseOverSection", &cur_header->code_onMouseOverSection}, +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT +#ifdef NSIS_CONFIG_COMPONENTPAGE + {"%s.onSelChange", &cur_header->code_onSelChange}, +#endif//NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_SUPPORT_REBOOT + {"%s.onRebootFailed", &cur_header->code_onRebootFailed}, +#endif//NSIS_SUPPORT_REBOOT + {0, 0} + }; + + for (int i = 0; callbacks[i].name; i++) { + const char *un = uninstall_mode ? "un" : ""; + char fname[1024]; + wsprintf(fname, callbacks[i].name, un, un); + char cbstr[1024]; + wsprintf(cbstr, "%s callback", str); + char cbstr2[1024]; + wsprintf(cbstr2, "%s.callbacks", un); + + if (resolve_call_int(cbstr,cbstr2,ns_func.find(fname,0),callbacks[i].p)) + return PS_ERROR; + } + } +#endif//NSIS_SUPPORT_CODECALLBACKS + + // optimize unused functions + { + section *sec=(section *)cur_functions->get(); + int l=cur_functions->getlen()/sizeof(section); + entry *w=(entry*)cur_entries->get(); + while (l-- > 0) + { + if (sec->name_ptr) + { + if (!sec->flags) + { + if (sec->code_size>0) + { + warning("%s function \"%s\" not referenced - zeroing code (%d-%d) out\n",str, + ns_func.get()+sec->name_ptr, + sec->code,sec->code+sec->code_size); + memset(w+sec->code,0,sec->code_size*sizeof(entry)); + } + } + } + sec++; + } + } + + // give warnings on unused labels + { + section *t=(section*)cur_labels->get(); + int n=cur_labels->getlen()/sizeof(section); + while (n-->0) + { + if (!t->flags) + { + char *n=(char*)ns_label.get()+t->name_ptr; + if (*n == '.') warning("global label \"%s\" not used",n); + else warning("label \"%s\" not used",n); + } + t++; + } + } + + return 0; +} + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +int CEXEBuild::add_page(int type) +{ + page pg = { + 0, + 0, +#ifdef NSIS_SUPPORT_CODECALLBACKS + -1, + -1, + -1, +#endif + 0, + }; + +#ifndef NSIS_CONFIG_LICENSEPAGE + if (type == PAGE_LICENSE) + { + ERROR_MSG("Error: can't add license page, NSIS_CONFIG_LICENSEPAGE not defined.\n"); + return PS_ERROR; + } +#endif +#ifndef NSIS_CONFIG_COMPONENTPAGE + if (type == PAGE_COMPONENTS) + { + ERROR_MSG("Error: can't add components page, NSIS_CONFIG_COMPONENTPAGE not defined.\n"); + return PS_ERROR; + } +#endif +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + if (type == PAGE_COMPONENTS) + { + ERROR_MSG("Error: can't add uninstConfirm page, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n"); + return PS_ERROR; + } +#endif + + struct { + int wndproc_id; + int dlg_id; + char *name; + } ids[] = { + {PWP_CUSTOM, 0, "custom"}, // custom +#ifdef NSIS_CONFIG_LICENSEPAGE + {PWP_LICENSE, IDD_LICENSE, "license"}, // license +#else + {0, IDD_LICENSE, "license"}, // license +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + {PWP_SELCOM, IDD_SELCOM, "components"}, // components +#else + {0, IDD_SELCOM, "components"}, // components +#endif + {PWP_DIR, IDD_DIR, "directory"}, // directory + {PWP_INSTFILES, IDD_INSTFILES, "instfiles"}, // instfiles +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + {PWP_UNINST, IDD_UNINST, "uninstConfirm"}, // uninstConfirm +#else + {0, IDD_UNINST, "uninstConfirm"}, // uninstConfirm +#endif + {PWP_COMPLETED, -1, NULL} // completed + }; + + pg.wndproc_id = ids[type].wndproc_id; + pg.dlg_id = ids[type].dlg_id; + + cur_pages->add(&pg,sizeof(page)); + + cur_page = (page *)cur_pages->get() + cur_header->blocks[NB_PAGES].num++; + + cur_page_type = type; + + set_code_type_predefines(ids[type].name); + return PS_OK; +} + +int CEXEBuild::page_end() +{ + cur_page = 0; + + set_code_type_predefines(); + return PS_OK; +} +#endif + +#ifdef NSIS_SUPPORT_VERSION_INFO +int CEXEBuild::AddVersionInfo() +{ + GrowBuf VerInfoStream; + + if ( rVersionInfo.GetStringTablesCount() > 0 ) + { + if ( !version_product_v[0] ) + { + ERROR_MSG("Error: VIProductVersion is required when other version information functions are used.\n"); + return PS_ERROR; + } + else + { + int imm, iml, ilm, ill; + if ( sscanf(version_product_v, "%d.%d.%d.%d", &imm, &iml, &ilm, &ill) != 4 ) + { + ERROR_MSG("Error: invalid VIProductVersion format, should be X.X.X.X\n"); + return PS_ERROR; + } + rVersionInfo.SetFileVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm)); + rVersionInfo.SetProductVersion(MAKELONG(iml, imm),MAKELONG(ill, ilm)); + + try + { + init_res_editor(); + for ( int i = 0; i < rVersionInfo.GetStringTablesCount(); i++ ) + { + LANGID lang_id = rVersionInfo.GetLangID(i); + int code_page = rVersionInfo.GetCodePage(i); + + char *lang_name = GetLangNameAndCP(lang_id); + + if ( !rVersionInfo.FindKey(lang_id, code_page, "FileVersion") ) + warning("Generating version information for language \"%04d-%s\" without standard key \"FileVersion\"", lang_id, lang_name); + if ( !rVersionInfo.FindKey(lang_id, code_page, "FileDescription") ) + warning("Generating version information for language \"%04d-%s\" without standard key \"FileDescription\"", lang_id, lang_name); + if ( !rVersionInfo.FindKey(lang_id, code_page, "LegalCopyright") ) + warning("Generating version information for language \"%04d-%s\" without standard key \"LegalCopyright\"", lang_id, lang_name); + + rVersionInfo.ExportToStream(VerInfoStream, i); + res_editor->UpdateResourceA(RT_VERSION, 1, lang_id, (BYTE*)VerInfoStream.get(), VerInfoStream.getlen()); + } + } + catch (exception& err) { + ERROR_MSG("Error adding version information: %s\n", err.what()); + return PS_ERROR; + } + } + } + + return PS_OK; +} +#endif // NSIS_SUPPORT_VERSION_INFO + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +int CEXEBuild::ProcessPages() +{ + SCRIPT_MSG("Processing pages... "); + + int license_normal=0; + int license_fsrb=0; + int license_fscb=0; + int selcom=0; + int dir=0, dir_used; + int uninstconfirm=0; + int instlog=0, instlog_used; + int main=0; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +again: +#endif + + dir_used = 0; + instlog_used = 0; + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if ((cur_header->flags & (CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) == 0) +#endif + { + main++; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +#define LS(inst, uninst) (uninstall_mode ? uninst : inst) +#else +#define LS(inst, uninst) inst +#endif + + DefineInnerLangString(NLF_BRANDING); + + if (!cur_pages->getlen()) { +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode) { + if (HasUserDefined(NLF_UNINST_TEXT)) { + add_page(PAGE_UNINSTCONFIRM); + page_end(); + } + add_page(PAGE_INSTFILES); + page_end(); + add_page(PAGE_COMPLETED); + page_end(); + } + else +#endif + { +#ifdef NSIS_CONFIG_LICENSEPAGE + if (HasUserDefined(NLF_LICENSE_TEXT) && HasUserDefined(NLF_LICENSE_DATA)) { + add_page(PAGE_LICENSE); + page_end(); + } +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (HasUserDefined(NLF_COMP_TEXT)) { + add_page(PAGE_COMPONENTS); + page_end(); + } +#endif + if (HasUserDefined(NLF_DIR_TEXT)) { + add_page(PAGE_DIRECTORY); + page_end(); + } + add_page(PAGE_INSTFILES); + page_end(); + add_page(PAGE_COMPLETED); + page_end(); + } + } + // start processing the pages + { + int i = 0; + page *p = (page *) cur_pages->get(); + + for (i = 0; i < cur_header->blocks[NB_PAGES].num; i++, p++) { + page *pp = 0; + + if (i) { + pp = p - 1; + + // set back button + p->flags |= PF_BACK_SHOW; + if (pp->wndproc_id != PWP_COMPLETED && p->wndproc_id != PWP_COMPLETED && p->wndproc_id != PWP_INSTFILES) + p->flags |= PF_BACK_ENABLE; + if (!p->back) + p->back = DefineInnerLangString(NLF_BTN_BACK); + + // set previous page's next button + if (!pp->next) { + int str = 0; + +#ifdef NSIS_CONFIG_LICENSEPAGE + if (pp->wndproc_id == PWP_LICENSE && (!(pp->flags & PF_LICENSE_FORCE_SELECTION) || HasUserDefined(NLF_BTN_LICENSE))) + str = NLF_BTN_LICENSE; + else +#endif + if (p->wndproc_id == PWP_INSTFILES) + str = LS(NLF_BTN_INSTALL, NLF_BTN_UNINSTALL); + else + str = NLF_BTN_NEXT; + + pp->next = DefineInnerLangString(str); + } + + // set previous page's click next text + if (!pp->clicknext) { + int str = 0; + + if (p->wndproc_id == PWP_INSTFILES) + str = LS(NLF_CLICK_INSTALL, NLF_CLICK_UNINSTALL); + else + str = NLF_CLICK_NEXT; + + pp->clicknext = DefineInnerLangString(str); + } + } + + // enable next button + if (p->wndproc_id != PWP_INSTFILES) + p->flags |= PF_NEXT_ENABLE; + + // set cancel button + if (!p->cancel) + p->cancel = DefineInnerLangString(NLF_BTN_CANCEL); + if (p->wndproc_id != PWP_INSTFILES && p->wndproc_id != PWP_COMPLETED) + p->flags |= PF_CANCEL_ENABLE; + + // set caption + struct { + int caption; + int ucaption; + } captions[] = { +#ifdef NSIS_CONFIG_LICENSEPAGE + {NLF_SUBCAPTION_LICENSE, NLF_SUBCAPTION_LICENSE}, +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + {NLF_SUBCAPTION_OPTIONS, NLF_SUBCAPTION_OPTIONS}, +#endif + {NLF_SUBCAPTION_DIR, NLF_SUBCAPTION_DIR}, + {NLF_SUBCAPTION_INSTFILES, NLF_USUBCAPTION_INSTFILES}, +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + {NLF_USUBCAPTION_CONFIRM, NLF_USUBCAPTION_CONFIRM}, +#endif + {NLF_SUBCAPTION_COMPLETED, NLF_USUBCAPTION_COMPLETED} + }; + + if (!p->caption && p->wndproc_id != PWP_CUSTOM) { + p->caption = DefineInnerLangString(LS(captions[p->wndproc_id].caption, captions[p->wndproc_id].ucaption)); + } + + // set texts + switch (p->dlg_id) { +#ifdef NSIS_CONFIG_LICENSEPAGE + case IDD_LICENSE: + case IDD_LICENSE_FSRB: + case IDD_LICENSE_FSCB: + { + if (!(p->flags & PF_PAGE_EX)) + p->dlg_id = license_res_id; + if (!(p->flags & (PF_LICENSE_FORCE_SELECTION | PF_LICENSE_NO_FORCE_SELECTION))) + p->dlg_id = license_res_id; + + p->flags |= PF_NO_NEXT_FOCUS; + + if (!p->parms[1]) + p->parms[1] = DefineInnerLangString(NLF_LICENSE_DATA, 0); + + if (p->dlg_id == IDD_LICENSE) { + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT, NLF_ULICENSE_TEXT)); + + license_normal++; + } + else if (p->dlg_id == IDD_LICENSE_FSCB) { + p->flags |= PF_LICENSE_FORCE_SELECTION; + + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT_FSCB, NLF_ULICENSE_TEXT_FSCB)); + if (!p->parms[2]) + p->parms[2] = DefineInnerLangString(NLF_BTN_LICENSE_AGREE); + + license_fscb++; + } + else if (p->dlg_id == IDD_LICENSE_FSRB) { + p->flags |= PF_LICENSE_FORCE_SELECTION; + + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(LS(NLF_LICENSE_TEXT_FSRB, NLF_ULICENSE_TEXT_FSRB)); + if (!p->parms[2]) + p->parms[2] = DefineInnerLangString(NLF_BTN_LICENSE_AGREE); + if (!p->parms[3]) + p->parms[3] = DefineInnerLangString(NLF_BTN_LICENSE_DISAGREE); + + license_fsrb++; + } + break; + } +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + case IDD_SELCOM: + { + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(LS(NLF_COMP_TEXT, NLF_UCOMP_TEXT)); + if (!p->parms[1]) + p->parms[1] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT1, NLF_UCOMP_SUBTEXT1)); + if (!p->parms[2]) + p->parms[2] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT2, NLF_UCOMP_SUBTEXT2)); + if (!p->parms[3] && !uninstall_mode && HasUserDefined(NLF_COMP_SUBTEXT1)) + p->parms[3] = p->parms[1]; + if (!p->parms[4] && !uninstall_mode && HasUserDefined(NLF_COMP_SUBTEXT2)) + p->parms[4] = p->parms[2]; + else if (!p->parms[4]) + p->parms[4] = DefineInnerLangString(LS(NLF_COMP_SUBTEXT1_NO_INST_TYPES, NLF_UCOMP_SUBTEXT1_NO_INST_TYPES)); + + DefineInnerLangString(NLF_SPACE_REQ); + DefineInnerLangString(NLF_BYTE); + DefineInnerLangString(NLF_KILO); + DefineInnerLangString(NLF_MEGA); + DefineInnerLangString(NLF_GIGA); + + selcom++; + break; + } +#endif + case IDD_DIR: + { + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(LS(NLF_DIR_TEXT, NLF_UDIR_TEXT)); + if (!p->parms[1]) + p->parms[1] = DefineInnerLangString(LS(NLF_DIR_SUBTEXT, NLF_UDIR_SUBTEXT)); + if (!p->parms[2]) + p->parms[2] = DefineInnerLangString(NLF_BTN_BROWSE); + if (!p->parms[3]) + p->parms[3] = DefineInnerLangString(LS(NLF_DIR_BROWSETEXT, NLF_UDIR_BROWSETEXT)); + if (!p->parms[4]) + p->parms[4] = m_UserVarNames.get("INSTDIR"); + else + p->parms[4]--; + + DefineInnerLangString(NLF_SPACE_AVAIL); + DefineInnerLangString(NLF_SPACE_REQ); + DefineInnerLangString(NLF_BYTE); + DefineInnerLangString(NLF_KILO); + DefineInnerLangString(NLF_MEGA); + DefineInnerLangString(NLF_GIGA); +#ifdef NSIS_CONFIG_LOG + DefineInnerLangString(NLF_LOG_INSTALL_PROCESS); +#endif + + dir++; + break; + } + case IDD_INSTFILES: + { + if (!p->parms[1]) + p->parms[1] = DefineInnerLangString(NLF_BTN_DETAILS); + if (!p->parms[2]) + p->parms[2] = DefineInnerLangString(NLF_COMPLETED); + + DefineInnerLangString(NLF_COPY_DETAILS); + + instlog++; + instlog_used++; + break; + } + case IDD_UNINST: + { + if (!p->parms[0]) + p->parms[0] = DefineInnerLangString(NLF_UNINST_TEXT); + if (!p->parms[1]) + p->parms[1] = DefineInnerLangString(NLF_UNINST_SUBTEXT); + if (!p->parms[4]) + p->parms[4] = m_UserVarNames.get("INSTDIR"); + else + p->parms[4]--; + + uninstconfirm++; + break; + } + } + + p->flags &= ~PF_PAGE_EX; + } + + p--; + + if (!p->next) + p->next = DefineInnerLangString(NLF_BTN_CLOSE); + if (p->wndproc_id == PWP_COMPLETED) + (p-1)->next = DefineInnerLangString(NLF_BTN_CLOSE); + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode) { + if (!uenable_last_page_cancel && instlog_used) + p->flags &= ~PF_CANCEL_ENABLE; + } + else +#endif + { + if (!enable_last_page_cancel && instlog_used) + p->flags &= ~PF_CANCEL_ENABLE; + } + + if (!instlog_used) { + warning("%sage instfiles not used, no sections will be executed!", uninstall_mode ? "Uninstall p" : "P"); + } + } + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!uninstall_mode) { + set_uninstall_mode(1); + goto again; + } + else + set_uninstall_mode(0); +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT + + + SCRIPT_MSG("Done!\n"); + +#define REMOVE_ICON(id) if (disable_window_icon) { \ + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \ + if (dlg) { \ + CDialogTemplate dt(dlg,uDefCodePage); \ + res_editor->FreeResource(dlg); \ + if (dt.RemoveItem(IDC_ULICON)) { \ + DialogItemTemplate* text = dt.GetItem(IDC_INTROTEXT); \ + DialogItemTemplate* prog = dt.GetItem(IDC_PROGRESS); \ + if (text) { \ + text->sWidth += text->sX; \ + text->sX = 0; \ + } \ + if (prog) { \ + prog->sWidth += prog->sX; \ + prog->sX = 0; \ + } \ + \ + DWORD dwSize; \ + dlg = dt.Save(dwSize); \ + res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, dlg, dwSize); \ + delete [] dlg; \ + } \ + } \ + } + + try { + SCRIPT_MSG("Removing unused resources... "); + init_res_editor(); +#ifdef NSIS_CONFIG_LICENSEPAGE + if (!license_normal) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_LICENSE); + if (!license_fsrb) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE_FSRB, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_LICENSE_FSRB); + if (!license_fscb) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_LICENSE_FSCB, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_LICENSE_FSCB); +#endif // NSIS_CONFIG_LICENSEPAGE +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (!selcom) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_SELCOM, NSIS_DEFAULT_LANG, 0, 0); + res_editor->UpdateResourceA(RT_BITMAP, IDB_BITMAP1, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_SELCOM); +#endif // NSIS_CONFIG_COMPONENTPAGE + if (!dir) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_DIR, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_DIR); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!uninstconfirm) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_UNINST, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_UNINST); +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT + if (!instlog) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_INSTFILES, NSIS_DEFAULT_LANG, 0, 0); + } + else REMOVE_ICON(IDD_INSTFILES); + if (!main) { + res_editor->UpdateResourceA(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, 0, 0); + if (!build_compress_whole && !build_crcchk) + res_editor->UpdateResourceA(RT_DIALOG, IDD_VERIFY, NSIS_DEFAULT_LANG, 0, 0); + } + + SCRIPT_MSG("Done!\n"); + } + catch (exception& err) { + ERROR_MSG("\nError: %s\n", err.what()); + return PS_ERROR; + } + + return PS_OK; +} +#endif // NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_COMPONENTPAGE +void CEXEBuild::PrepareInstTypes() +{ + if (!(cur_header->flags & CH_FLAGS_NO_CUSTOM)) + cur_header->install_types[NSIS_MAX_INST_TYPES] = DefineInnerLangString(NLF_COMP_CUSTOM); + + // set insttype list for RO sections that didn't use SectionIn + int i = cur_header->blocks[NB_SECTIONS].num; + section *sections = (section *) cur_sections->get(); + + while (i--) + { + if (sections[i].flags & SF_RO && !sections[i].install_types) + sections[i].install_types = ~0; + } + + // set selection to first insttype + if (cur_header->install_types[0]) + { + int i = cur_header->blocks[NB_SECTIONS].num; + section *sections = (section *) cur_sections->get(); + + // if /o was used abort since the user did his manual choice + while (i--) + if ((sections[i].flags & SF_SELECTED) == 0) + return; + + i = cur_header->blocks[NB_SECTIONS].num; + + while (i--) + if ((sections[i].install_types & 1) == 0) + sections[i].flags &= ~SF_SELECTED; + } +} +#endif + +void CEXEBuild::AddStandardStrings() +{ +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode) + { + cur_header->str_uninstchild = add_string("$TEMP\\$1u_.exe"); + cur_header->str_uninstcmd = add_string("\"$TEMP\\$1u_.exe\" $0 _?=$INSTDIR\\"); + } +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_SUPPORT_MOVEONREBOOT + cur_header->str_wininit = add_string("$WINDIR\\wininit.ini"); +#endif//NSIS_SUPPORT_MOVEONREBOOT +} + +void CEXEBuild::PrepareHeaders(IGrowBuf *hdrbuf) +{ + GrowBuf blocks_buf; + growbuf_writer_sink sink(&blocks_buf); + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + cur_header->blocks[NB_PAGES].offset = sizeof(header) + blocks_buf.getlen(); + page_writer::write_block(cur_pages, &sink); +#endif + + cur_header->blocks[NB_SECTIONS].offset = sizeof(header) + blocks_buf.getlen(); + section_writer::write_block(cur_sections, &sink); + + cur_header->blocks[NB_ENTRIES].offset = sizeof(header) + blocks_buf.getlen(); + entry_writer::write_block(cur_entries, &sink); + + cur_header->blocks[NB_STRINGS].offset = sizeof(header) + blocks_buf.getlen(); + blocks_buf.add(cur_strlist->get(), cur_strlist->getlen()); + + cur_header->blocks[NB_LANGTABLES].offset = sizeof(header) + blocks_buf.getlen(); + lang_table_writer::write_block(cur_langtables, &sink, cur_header->langtable_size); + + cur_header->blocks[NB_CTLCOLORS].offset = sizeof(header) + blocks_buf.getlen(); + ctlcolors_writer::write_block(cur_ctlcolors, &sink); + +#ifdef NSIS_SUPPORT_BGBG + if (cur_header->bg_color1 != -1) + { + bg_font.lfFaceName[LF_FACESIZE-1] = 0; + + cur_header->blocks[NB_BGFONT].offset = sizeof(header) + blocks_buf.getlen(); + + LOGFONT_writer w(&sink); + w.write(&bg_font); + } +#endif + + growbuf_writer_sink sink2(hdrbuf); + header_writer header(&sink2); + header.write(cur_header); + + sink2.write_growbuf(&blocks_buf); +} + +int CEXEBuild::SetVarsSection() +{ + try { + init_res_editor(); + + VerifyDeclaredUserVarRefs(&m_UserVarNames); + int MaxUserVars = m_UserVarNames.getnum(); + // -1 because the default size is 1 + if (!res_editor->AddExtraVirtualSize2PESection(NSIS_VARS_SECTION, (MaxUserVars - 1) * sizeof(NSIS_STRING))) + { + ERROR_MSG("Internal compiler error #12346: invalid exehead cannot find section \"%s\"!\n", NSIS_VARS_SECTION); + return PS_ERROR; + } + } + catch (exception& err) { + ERROR_MSG("\nError: %s\n", err.what()); + return PS_ERROR; + } + + return PS_OK; +} + +int CEXEBuild::SetManifest() +{ + try { + init_res_editor(); + + string manifest = manifest::generate(manifest_comctl, manifest_exec_level); + + if (manifest == "") + return PS_OK; + + res_editor->UpdateResourceA(MAKEINTRESOURCE(24), MAKEINTRESOURCE(1), NSIS_DEFAULT_LANG, (LPBYTE) manifest.c_str(), manifest.length()); + } + catch (exception& err) { + ERROR_MSG("Error while setting manifest: %s\n", err.what()); + return PS_ERROR; + } + + return PS_OK; +} + +int CEXEBuild::check_write_output_errors() const +{ + if (has_called_write_output) + { + ERROR_MSG("Error (write_output): write_output already called, can't continue\n"); + return PS_ERROR; + } + + if (!build_output_filename[0]) + { + ERROR_MSG("Error: invalid script: never had OutFile command\n"); + return PS_ERROR; + } + + if (!build_sections.getlen()) + { + ERROR_MSG("Error: invalid script: no sections specified\n"); + return PS_ERROR; + } + + if (!build_entries.getlen()) + { + ERROR_MSG("Error: invalid script: no entries specified\n"); + return PS_ERROR; + } + + if (build_cursection) + { + ERROR_MSG("Error: Section left open at EOF\n"); + return PS_ERROR; + } + + if (sectiongroup_open_cnt) + { + ERROR_MSG("Error: SectionGroup left open at EOF\n"); + return PS_ERROR; + } + + if (cur_page) + { + ERROR_MSG("Error: PageEx left open at EOF\n"); + return PS_ERROR; + } + + // deal with functions, for both install and uninstall modes. + if (build_cursection_isfunc) + { + ERROR_MSG("Error: Function left open at EOF\n"); + return PS_ERROR; + } + + return PS_OK; +} + +int CEXEBuild::prepare_uninstaller() { +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (ubuild_entries.getlen()) + { + if (!uninstaller_writes_used) + { + warning("Uninstaller script code found but WriteUninstaller never used - no uninstaller will be created."); + return PS_OK; + } + + build_uninst.flags|=build_header.flags&(CH_FLAGS_PROGRESS_COLORED|CH_FLAGS_NO_ROOT_DIR); + + set_uninstall_mode(1); + + DefineInnerLangString(NLF_UCAPTION); + + if (resolve_coderefs("uninstall")) + return PS_ERROR; + +#ifdef NSIS_CONFIG_COMPONENTPAGE + // set sections to the first insttype + PrepareInstTypes(); +#endif + + // Add standard strings to string table + AddStandardStrings(); + + set_uninstall_mode(0); + } + else if (uninstaller_writes_used) + { + ERROR_MSG("Error: no Uninstall section specified, but WriteUninstaller used %d time(s)\n",uninstaller_writes_used); + return PS_ERROR; + } +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT + return PS_OK; +} + +int CEXEBuild::pack_exe_header() +{ + if (!(build_packname[0] && build_packcmd[0])) { + // header not asked to be packed + return PS_OK; + } + + // write out exe header, pack, read back in, and + // update the header info + FILE *tmpfile=FOPEN(build_packname,"wb"); + if (!tmpfile) + { + ERROR_MSG("Error: writing temporary file \"%s\" for pack\n",build_packname); + return PS_ERROR; + } + fwrite(m_exehead,1,m_exehead_size,tmpfile); + fclose(tmpfile); + if (sane_system(build_packcmd) == -1) + { + remove(build_packname); + ERROR_MSG("Error: calling packer on \"%s\"\n",build_packname); + return PS_ERROR; + } + + int result = update_exehead(build_packname); + remove(build_packname); + + if (result != PS_OK) + { + ERROR_MSG("Error: reading temporary file \"%s\" after pack\n",build_packname); + return result; + } + + return PS_OK; +} + +int CEXEBuild::write_output(void) +{ +#ifndef NSIS_CONFIG_CRC_SUPPORT + build_crcchk=0; +#endif + + RET_UNLESS_OK( check_write_output_errors() ); + + has_called_write_output=true; + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + RET_UNLESS_OK( add_plugins_dir_initializer() ); +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + +#ifdef NSIS_SUPPORT_VERSION_INFO + RET_UNLESS_OK( AddVersionInfo() ); +#endif //NSIS_SUPPORT_VERSION_INFO + + RET_UNLESS_OK( prepare_uninstaller() ); + + DefineInnerLangString(NLF_CAPTION); + if (resolve_coderefs("install")) + return PS_ERROR; + +#ifdef NSIS_CONFIG_COMPONENTPAGE + // set sections to the first insttype + PrepareInstTypes(); +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + RET_UNLESS_OK( ProcessPages() ); +#endif //NSIS_CONFIG_VISIBLE_SUPPORT + + // Generate language tables + RET_UNLESS_OK( GenerateLangTables() ); + + // Setup user variables PE section + RET_UNLESS_OK( SetVarsSection() ); + + // Set XML manifest + RET_UNLESS_OK( SetManifest() ); + + // Add standard strings to string table + AddStandardStrings(); + + try { + // Load icon from exe, if needed + if (installer_icon.empty()) + { + init_res_editor(); + installer_icon = load_icon_res(res_editor, IDI_ICON2); + } + + // Set icon + set_icon(res_editor, IDI_ICON2, installer_icon, uninstaller_icon); + + // Save all changes to the exe header + close_res_editor(); + } + catch (exception& err) { + ERROR_MSG("\nError: %s\n", err.what()); + return PS_ERROR; + } + + RET_UNLESS_OK( pack_exe_header() ); + + + build_optimize_datablock=0; + + int data_block_size_before_uninst = build_datablock.getlen(); + + RET_UNLESS_OK( uninstall_generate() ); + + crc32_t crc=0; + + { + string full_path = get_full_path(build_output_filename); + notify(MAKENSIS_NOTIFY_OUTPUT, full_path.c_str()); + INFO_MSG("\nOutput: \"%s\"\n", full_path.c_str()); + } + + FILE *fp = FOPEN(build_output_filename,"w+b"); + if (!fp) + { + ERROR_MSG("Can't open output file\n"); + return PS_ERROR; + } + + if (fwrite(m_exehead,1,m_exehead_size,fp) != m_exehead_size) + { + ERROR_MSG("Error: can't write %d bytes to output\n",m_exehead_size); + fclose(fp); + return PS_ERROR; + } + +#ifdef NSIS_CONFIG_CRC_SUPPORT + #ifdef NSIS_CONFIG_CRC_ANAL + crc=CRC32(crc,m_exehead,m_exehead_size); + #else + crc=CRC32(crc,m_exehead+512,m_exehead_size-512); + #endif +#endif + + firstheader fh={0,}; + fh.nsinst[0]=FH_INT1; + fh.nsinst[1]=FH_INT2; + fh.nsinst[2]=FH_INT3; + +#ifdef NSIS_CONFIG_CRC_SUPPORT + fh.flags=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC); +#else + fh.flags=0; +#endif +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT; +#endif + fh.siginfo=FH_SIG; + + int installinfo_compressed; + int fd_start = 0; + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (build_compress_whole) + { + int n = compressor->Init(build_compress_level, build_compress_dict_size); + if (n != C_OK) + { + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n); + return PS_ERROR; + } + } +#endif + + { + GrowBuf ihd; + { + GrowBuf hdrcomp; + + PrepareHeaders(&hdrcomp); + + if (add_data((char*)hdrcomp.get(),hdrcomp.getlen(),&ihd) < 0) + return PS_ERROR; + + fh.length_of_header=hdrcomp.getlen(); + installinfo_compressed=ihd.getlen(); + } + + if (!build_compress_whole) + fh.length_of_all_following_data=ihd.getlen()+build_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0); + else + fd_start=ftell(fp); + + try + { + file_writer_sink sink(fp); + firstheader_writer w(&sink); + w.write(&fh); + } + catch (...) + { + ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(fh)); + fclose(fp); + return PS_ERROR; + } + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (build_compress_whole) { + if (deflateToFile(fp,(char*)ihd.get(),ihd.getlen())) + { + fclose(fp); + return PS_ERROR; + } + } + else +#endif + { + if (fwrite(ihd.get(),1,ihd.getlen(),fp) != (unsigned int)ihd.getlen()) + { + ERROR_MSG("Error: can't write %d bytes to output\n",ihd.getlen()); + fclose(fp); + return PS_ERROR; + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + crc_writer_sink crc_sink((crc32_t *) &crc); + firstheader_writer w(&crc_sink); + w.write(&fh); + + crc=CRC32(crc,(unsigned char*)ihd.get(),ihd.getlen()); +#endif + } + } + + INFO_MSG("Install: "); +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + int np=build_header.blocks[NB_PAGES].num; + INFO_MSG("%d page%s (%d bytes), ",np,np==1?"":"s",np*sizeof(page)); +#endif + { + int ns=build_sections.getlen()/sizeof(section); + section *s=(section*)build_sections.get(); + int x; + int req=0; + for (x = 1; x < ns; x ++) + { + if (!s[x].name_ptr || s[x].flags & SF_RO) req++; + } + INFO_MSG("%d section%s",ns,ns==1?"":"s"); + if (req) + { + INFO_MSG(" (%d required)",req); + } + INFO_MSG(" (%d bytes), ", build_sections.getlen()); + } + int ne=build_header.blocks[NB_ENTRIES].num; + INFO_MSG("%d instruction%s (%d bytes), ",ne,ne==1?"":"s",ne*sizeof(entry)); + int ns=build_strlist.getnum(); + INFO_MSG("%d string%s (%d bytes), ",ns,ns==1?"":"s",build_strlist.getlen()); + int nlt=build_header.blocks[NB_LANGTABLES].num; + INFO_MSG("%d language table%s (%d bytes).\n",nlt,nlt==1?"":"s",build_langtables.getlen()); + if (ubuild_entries.getlen()) + { + INFO_MSG("Uninstall: "); +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + np=build_uninst.blocks[NB_PAGES].num; + INFO_MSG("%d page%s (%d bytes), \n",np,np==1?"":"s",ubuild_pages.getlen()); +#endif + { + int ns=ubuild_sections.getlen()/sizeof(section); + section *s=(section*)ubuild_sections.get(); + int x; + int req=0; + for (x = 1; x < ns; x ++) + { + if (!s[x].name_ptr || s[x].flags & SF_RO) req++; + } + INFO_MSG("%d section%s",ns,ns==1?"":"s"); + if (req) + { + INFO_MSG(" (%d required)",req); + } + INFO_MSG(" (%d bytes), ", ubuild_sections.getlen()); + } + ne=build_uninst.blocks[NB_ENTRIES].num; + INFO_MSG("%d instruction%s (%d bytes), ",ne,ne==1?"":"s",ubuild_entries.getlen()); + ns=ubuild_strlist.getnum(); + INFO_MSG("%d string%s (%d bytes), ",ns,ns==1?"":"s",ubuild_strlist.getlen()); + nlt=build_uninst.blocks[NB_LANGTABLES].num; + INFO_MSG("%d language table%s (%d bytes).\n",nlt,nlt==1?"":"s",ubuild_langtables.getlen()); + } + + + if (db_opt_save) + { + int total_out_size_estimate= + m_exehead_size+sizeof(fh)+build_datablock.getlen()+(build_crcchk?sizeof(crc32_t):0); + int pc=(int)(((INT64)db_opt_save*1000)/(db_opt_save+total_out_size_estimate)); + INFO_MSG("Datablock optimizer saved %d bytes (~%d.%d%%).\n",db_opt_save, + pc/10,pc%10); + } + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + INFO_MSG("\nUsing %s%s compression.\n\n", compressor->GetName(), build_compress_whole?" (compress whole)":""); +#endif + + unsigned int total_usize=m_exehead_original_size; + + INFO_MSG("EXE header size: %10d / %d bytes\n",m_exehead_size,m_exehead_original_size); + + if (build_compress_whole) { + INFO_MSG("Install code: (%d bytes)\n", + sizeof(fh)+fh.length_of_header); + } + else { + INFO_MSG("Install code: %10d / %d bytes\n", + sizeof(fh)+installinfo_compressed, + sizeof(fh)+fh.length_of_header); + } + + total_usize+=sizeof(fh)+fh.length_of_header; + + { + int dbsize, dbsizeu; + dbsize = build_datablock.getlen(); + if (uninstall_size>0) dbsize-=uninstall_size; + + if (build_compress_whole) { + dbsizeu=dbsize; + INFO_MSG("Install data: (%d bytes)\n",dbsizeu); + } + else { + dbsizeu = db_full_size - uninstall_size_full; + INFO_MSG("Install data: %10d / %d bytes\n",dbsize,dbsizeu); + } + total_usize+=dbsizeu; + } + + if (uninstall_size>=0) + { + if (build_compress_whole) + INFO_MSG("Uninstall code+data: (%d bytes)\n",uninstall_size_full); + else + INFO_MSG("Uninstall code+data: %6d / %d bytes\n",uninstall_size,uninstall_size_full); + total_usize+=uninstall_size_full; + } + + if (build_compress_whole) { + INFO_MSG("Compressed data: "); + } + + if (build_datablock.getlen()) + { + build_datablock.setro(TRUE); + int dbl = build_datablock.getlen(); + int left = dbl; + while (left > 0) + { + int l = min(build_filebuflen, left); + char *dbptr = (char *) build_datablock.get(dbl - left, l); +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (build_compress_whole) + { + if (deflateToFile(fp,dbptr,l)) + { + fclose(fp); + return PS_ERROR; + } + } + else +#endif + { +#ifdef NSIS_CONFIG_CRC_SUPPORT + crc=CRC32(crc,(unsigned char *)dbptr,l); +#endif + if ((int)fwrite(dbptr,1,l,fp) != l) + { + ERROR_MSG("Error: can't write %d bytes to output\n",l); + fclose(fp); + return PS_ERROR; + } + fflush(fp); + } + build_datablock.release(); + left -= l; + } + build_datablock.setro(FALSE); + build_datablock.clear(); + } +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (build_compress_whole) + { + if (deflateToFile(fp,NULL,0)) + { + fclose(fp); + return PS_ERROR; + } + compressor->End(); + + unsigned fend = ftell(fp); + + fh.length_of_all_following_data=ftell(fp)-fd_start+(build_crcchk?sizeof(crc32_t):0); + INFO_MSG( + "%10d / %d bytes\n", + ftell(fp) - fd_start, + data_block_size_before_uninst + fh.length_of_header + sizeof(firstheader) + uninstall_size_full + ); + + fseek(fp,fd_start,SEEK_SET); + + try + { + file_writer_sink sink(fp); + firstheader_writer w(&sink); + w.write(&fh); + } + catch (...) + { + ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(fh)); + fclose(fp); + return PS_ERROR; + } + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (build_crcchk) + { + // check rest of CRC + fseek(fp,fd_start,SEEK_SET); + for (;;) + { + char buf[32768]; + int l=fread(buf,1,sizeof(buf),fp); + if (!l) break; + crc=CRC32(crc,(unsigned char *)buf,l); + } + } +#endif + fseek(fp,fend,SEEK_SET); // reset eof flag + } +#endif + + if (build_crcchk) + { + total_usize+=sizeof(int); + int rcrc = FIX_ENDIAN_INT32(crc); + if (fwrite(&rcrc,1,sizeof(crc32_t),fp) != sizeof(crc32_t)) + { + ERROR_MSG("Error: can't write %d bytes to output\n",sizeof(crc32_t)); + fclose(fp); + return PS_ERROR; + } + INFO_MSG("CRC (0x%08X): 4 / 4 bytes\n",crc); + } + INFO_MSG("\n"); + { + UINT pc=(UINT)(((UINT64)ftell(fp)*1000)/(total_usize)); + INFO_MSG("Total size: %10u / %u bytes (%u.%u%%)\n", + ftell(fp),total_usize,pc/10,pc%10); + } + fclose(fp); + print_warnings(); + return PS_OK; +} + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +int CEXEBuild::deflateToFile(FILE *fp, char *buf, int len) // len==0 to flush +{ + build_compressor_set=true; + + char obuf[65536]; + bool flush=false; + compressor->SetNextIn(buf,len); + if (!buf||!len) + { + char a; + compressor->SetNextIn(&a,0); + flush=C_FINISH; + } + for (;;) + { + compressor->SetNextOut(obuf,sizeof(obuf)); + int ret=compressor->Compress(flush); + if (ret<0 && (ret!=-1 || !flush)) + { + ERROR_MSG("Error: deflateToFile: deflate() failed(%s [%d])\n", compressor->GetErrStr(ret), ret); + return 1; + } + int l=compressor->GetNextOut()-obuf; + if (l) + { + if (fwrite(obuf,1,l,fp) != (unsigned)l) + { + ERROR_MSG("Error: deflateToFile fwrite(%d) failed\n",l); + return 1; + } + fflush(fp); + } + if (!compressor->GetAvailIn() && (!flush || !l)) break; + } + return 0; +} +#endif + +int CEXEBuild::uninstall_generate() +{ +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (ubuild_entries.getlen() && uninstaller_writes_used) + { + SCRIPT_MSG("Generating uninstaller... "); + + firstheader fh={0,}; + + GrowBuf uhd; + { + GrowBuf udata; + + set_uninstall_mode(1); + + PrepareHeaders(&udata); + + fh.length_of_header=udata.getlen(); + int err=add_data((char*)udata.get(),udata.getlen(),&uhd); + set_uninstall_mode(0); + if (err < 0) return PS_ERROR; + } + + crc32_t crc=0; + + // Get offsets of icons to replace for uninstall + // Also makes sure that the icons are there and in the right size. + LPBYTE unicon_data = generate_uninstall_icon_data(installer_icon, uninstaller_icon, m_unicon_size); + if (generate_unicons_offsets(m_exehead, m_exehead_size, unicon_data, IDI_ICON2) == 0) + { + delete [] unicon_data; + return PS_ERROR; + } + + entry *ent = (entry *) build_entries.get(); + if (!ent) + { + delete [] unicon_data; + return PS_ERROR; + } + + int ents = build_header.blocks[NB_ENTRIES].num; + int uns = uninstaller_writes_used; + int uninstdata_offset = build_datablock.getlen(); + while (ents--) + { + if (ent->which == EW_WRITEUNINSTALLER) + { + ent->offsets[1] = uninstdata_offset; + ent->offsets[2] = m_unicon_size; + uns--; + if (!uns) + break; + } + ent++; + } + + if (add_db_data((char *)unicon_data,m_unicon_size) < 0) + { + delete [] unicon_data; + return PS_ERROR; + } + +#ifdef NSIS_CONFIG_CRC_SUPPORT + { + // "create" the uninstaller + LPBYTE uninst_header = (LPBYTE) malloc(m_exehead_size); + if (!uninst_header) + return PS_ERROR; + + memcpy(uninst_header, m_exehead, m_exehead_size); + + // patch the icons + LPBYTE seeker = unicon_data; + while (*seeker) { + DWORD dwSize = FIX_ENDIAN_INT32(*(LPDWORD) seeker); + seeker += sizeof(DWORD); + DWORD dwOffset = FIX_ENDIAN_INT32(*(LPDWORD) seeker); + seeker += sizeof(DWORD); + memcpy(uninst_header + dwOffset, seeker, dwSize); + seeker += dwSize; + } + + delete [] unicon_data; + +#ifdef NSIS_CONFIG_CRC_ANAL + crc=CRC32(crc, uninst_header, m_exehead_size); +#else + crc=CRC32(crc, uninst_header + 512, m_exehead_size - 512); +#endif + + free(uninst_header); + } +#endif + fh.nsinst[0]=FH_INT1; + fh.nsinst[1]=FH_INT2; + fh.nsinst[2]=FH_INT3; + fh.flags=FH_FLAGS_UNINSTALL; +#ifdef NSIS_CONFIG_CRC_SUPPORT + fh.flags|=(build_crcchk?(build_crcchk==2?FH_FLAGS_FORCE_CRC:0):FH_FLAGS_NO_CRC); +#endif +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_uninst.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) fh.flags |= FH_FLAGS_SILENT; +#endif + fh.siginfo=FH_SIG; + fh.length_of_all_following_data= + uhd.getlen()+ubuild_datablock.getlen()+(int)sizeof(firstheader)+(build_crcchk?sizeof(crc32_t):0); + + MMapBuf udata; + + { + growbuf_writer_sink sink(&udata); + firstheader_writer w(&sink); + w.write(&fh); + } + + ubuild_datablock.setro(TRUE); + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (build_compress_whole) { + // compress uninstaller too + { + char obuf[65536]; + int n = compressor->Init(build_compress_level, build_compress_dict_size); + if (n != C_OK) + { + ERROR_MSG("Internal compiler error #12345: deflateInit() failed(%s [%d]).\n", compressor->GetErrStr(n), n); + extern void quit(); quit(); + } + + compressor->SetNextIn((char*)uhd.get(), uhd.getlen()); + while (compressor->GetAvailIn()) + { + compressor->SetNextOut(obuf, sizeof(obuf)); + compressor->Compress(0); + if (compressor->GetNextOut() - obuf > 0) + { + udata.add(obuf, compressor->GetNextOut() - obuf); + } + } + + int avail_in = ubuild_datablock.getlen(); + int in_pos = 0; + while (avail_in > 0) { + int l = min(avail_in, build_filebuflen); + + char *p = (char*)ubuild_datablock.get(in_pos, l); + compressor->SetNextIn(p, l); + + while (compressor->GetAvailIn()) + { + compressor->SetNextOut(obuf, sizeof(obuf)); + compressor->Compress(0); + if (compressor->GetNextOut() - obuf > 0) + udata.add(obuf, compressor->GetNextOut() - obuf); + } + + ubuild_datablock.release(); + + avail_in -= l; + in_pos += l; + } + + for (;;) + { + compressor->SetNextOut(obuf, sizeof(obuf)); + compressor->Compress(C_FINISH); + if (compressor->GetNextOut() - obuf > 0) + udata.add(obuf, compressor->GetNextOut() - obuf); + else break; + } + compressor->End(); + } + + firstheader *_fh=(firstheader *)udata.get(0, sizeof(firstheader)); + _fh->length_of_all_following_data=FIX_ENDIAN_INT32(udata.getlen()+(build_crcchk?sizeof(crc32_t):0)); + udata.release(); + } + else +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + { + udata.add(uhd.get(), uhd.getlen()); + + int st = udata.getlen(); + int length = ubuild_datablock.getlen(); + int left = length; + udata.resize(st + left); + while (left > 0) + { + int l = min(build_filebuflen, left); + void *p = ubuild_datablock.get(length - left, l); + memcpy(udata.get(st + length - left, l), p, l); + udata.flush(l); + udata.release(); + ubuild_datablock.release(); + left -= l; + } + } + + ubuild_datablock.clear(); + + udata.setro(TRUE); + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (build_crcchk) + { + int pos = 0; + int left = udata.getlen(); + while (left > 0) + { + int l = min(build_filebuflen, left); + crc = CRC32(crc, (unsigned char *) udata.get(pos, l), l); + udata.release(); + pos += l; + left -= l; + } + udata.setro(FALSE); + FIX_ENDIAN_INT32_INPLACE(crc); + udata.add(&crc, sizeof(crc)); + udata.setro(TRUE); + } +#endif + + if (add_db_data(&udata) < 0) + return PS_ERROR; + + udata.clear(); + + //uninstall_size_full=fh.length_of_all_following_data + sizeof(int) + unicondata_size - 32 + sizeof(int); + uninstall_size_full=fh.length_of_all_following_data+m_unicon_size; + + // compressed size + uninstall_size=build_datablock.getlen()-uninstdata_offset; + + SCRIPT_MSG("Done!\n"); + } +#endif + return PS_OK; +} + +#define SWAP(x,y,i) { i _ii; _ii=x; x=y; y=_ii; } + +void CEXEBuild::set_uninstall_mode(int un) +{ + if (un != uninstall_mode) + { + uninstall_mode=un; + if (un) + { + cur_datablock=&ubuild_datablock; + cur_datablock_cache=&ubuild_datablock_cache; + cur_entries=&ubuild_entries; + cur_instruction_entry_map=&ubuild_instruction_entry_map; + cur_functions=&ubuild_functions; + cur_labels=&ubuild_labels; + cur_pages=&ubuild_pages; + cur_sections=&ubuild_sections; + cur_header=&build_uninst; + cur_strlist=&ubuild_strlist; + cur_langtables=&ubuild_langtables; + cur_ctlcolors=&ubuild_ctlcolors; + + definedlist.add("__UNINSTALL__"); + } + else + { + cur_datablock=&build_datablock; + cur_datablock_cache=&build_datablock_cache; + cur_entries=&build_entries; + cur_instruction_entry_map=&build_instruction_entry_map; + cur_functions=&build_functions; + cur_labels=&build_labels; + cur_pages=&build_pages; + cur_sections=&build_sections; + cur_header=&build_header; + cur_strlist=&build_strlist; + cur_langtables=&build_langtables; + cur_ctlcolors=&build_ctlcolors; + + definedlist.del("__UNINSTALL__"); + } + + SWAP(db_opt_save_u,db_opt_save,int); + SWAP(db_comp_save_u,db_comp_save,int); + SWAP(db_full_size_u,db_full_size,int); + } +} + +extern FILE *g_output; + +void CEXEBuild::warning(const char *s, ...) +{ + char buf[NSIS_MAX_STRLEN*10]; + va_list val; + va_start(val,s); +#ifdef _WIN32 + vsprintf(buf,s,val); +#else + vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val); +#endif + va_end(val); + m_warnings.add(buf,0); + notify(MAKENSIS_NOTIFY_WARNING,buf); + if (display_warnings) + { + fprintf(g_output,"warning: %s\n",buf); + fflush(g_output); + } +} + +void CEXEBuild::warning_fl(const char *s, ...) +{ + char buf[NSIS_MAX_STRLEN*10]; + va_list val; + va_start(val,s); +#ifdef _WIN32 + vsprintf(buf,s,val); +#else + vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val); +#endif + va_end(val); + sprintf(buf+strlen(buf)," (%s:%d)",curfilename,linecnt); + m_warnings.add(buf,0); + notify(MAKENSIS_NOTIFY_WARNING,buf); + if (display_warnings) + { + fprintf(g_output,"warning: %s\n",buf); + fflush(g_output); + } +} + +void CEXEBuild::ERROR_MSG(const char *s, ...) const +{ + if (display_errors || notify_hwnd) + { + char buf[NSIS_MAX_STRLEN*10]; + va_list val; + va_start(val,s); +#ifdef _WIN32 + vsprintf(buf,s,val); +#else + vsnprintf(buf,NSIS_MAX_STRLEN*10,s,val); +#endif + va_end(val); + notify(MAKENSIS_NOTIFY_ERROR,buf); + if (display_errors) + { + fprintf(g_output,"%s",buf); + fflush(g_output); + } + } +} + +void CEXEBuild::SCRIPT_MSG(const char *s, ...) const +{ + if (display_script) + { + va_list val; + va_start(val,s); + vfprintf(g_output,s,val); + va_end(val); + fflush(g_output); + } +} + +void CEXEBuild::INFO_MSG(const char *s, ...) const +{ + if (display_info) + { + va_list val; + va_start(val,s); + vfprintf(g_output,s,val); + va_end(val); + fflush(g_output); + } +} + +void CEXEBuild::print_warnings() +{ + int nw=0,x=m_warnings.getlen(); + if (!x || !display_warnings) return; + char *p=m_warnings.get(); + while (x>0) if (!p[--x]) nw++; + fprintf(g_output,"\n%d warning%s:\n",nw,nw==1?"":"s"); + for (x = 0; x < nw; x ++) + { + fprintf(g_output," %s\n",p); + p+=strlen(p)+1; + } + fflush(g_output); +} + +void CEXEBuild::notify(notify_e code, const char *data) const +{ +#ifdef _WIN32 + if (notify_hwnd) + { + COPYDATASTRUCT cds = {(DWORD)code, strlen(data)+1, (void *) data}; + SendMessage(notify_hwnd, WM_COPYDATA, 0, (LPARAM)&cds); + } +#endif +} + +// Added by Ximon Eighteen 5th August 2002 +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT +void CEXEBuild::build_plugin_table(void) +{ + if (plugins_processed) + return; + plugins_processed=1; + + plugin_used = false; + uninst_plugin_used = false; + string searchPath = definedlist.find("NSISDIR"); + searchPath += PLATFORM_PATH_SEPARATOR_STR"Plugins"; + INFO_MSG("Processing plugin dlls: \"%s" PLATFORM_PATH_SEPARATOR_STR "*.dll\"\n",searchPath.c_str()); + m_plugins.FindCommands(searchPath, display_info?true:false); + INFO_MSG("\n"); +} + +#define FLAG_OFFSET(flag) (FIELD_OFFSET(exec_flags, flag)/sizeof(int)) + +int CEXEBuild::add_plugins_dir_initializer(void) +{ + if (!plugin_used && !uninst_plugin_used) return PS_OK; + + SCRIPT_MSG("Adding plug-ins initializing function... "); + + bool uninstall = !plugin_used; + + int ret; + int zero_offset; + + int var_zero; + var_zero=m_UserVarNames.get("0"); + +again: + // Function [un.]Initialize_____Plugins + ret=add_function(uninstall?"un.Initialize_____Plugins":"Initialize_____Plugins"); + if (ret != PS_OK) return ret; + + // don't move this, depends on [un.] + zero_offset=add_string("$0"); + + // SetDetailsPrint none + ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), add_intstring(6)); + if (ret != PS_OK) return ret; + + // StrCmp $PLUGINSDIR "" + ret=add_entry_direct(EW_STRCMP, add_string("$PLUGINSDIR"), 0, 0, ns_label.add("Initialize_____Plugins_done",0)); + if (ret != PS_OK) return ret; + // Push $0 + ret=add_entry_direct(EW_PUSHPOP, zero_offset); + if (ret != PS_OK) return ret; + // ClearErrors + ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(exec_error)); + if (ret != PS_OK) return ret; + // GetTempFileName $0 + ret=add_entry_direct(EW_GETTEMPFILENAME, var_zero, add_string("$TEMP")); + if (ret != PS_OK) return ret; + // Delete $0 [simple, nothing that could clash with special temp permissions] + ret=add_entry_direct(EW_DELETEFILE, zero_offset, DEL_SIMPLE); + if (ret != PS_OK) return ret; + // CraeteDirectory $0 - a dir instead of that temp file + ret=add_entry_direct(EW_CREATEDIR, zero_offset); + if (ret != PS_OK) return ret; + // IfErrors Initialize_____Plugins_error - detect errors + ret=add_entry_direct(EW_IFFLAG, ns_label.add("Initialize_____Plugins_error",0), 0, FLAG_OFFSET(exec_error)); + if (ret != PS_OK) return ret; + // Copy $0 to $PLUGINSDIR + ret=add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("PLUGINSDIR"), zero_offset); + if (ret != PS_OK) return ret; + // Pop $0 + ret=add_entry_direct(EW_PUSHPOP, var_zero, 1); + if (ret != PS_OK) return ret; + + // done + if (add_label("Initialize_____Plugins_done")) return PS_ERROR; + // Return + ret=add_entry_direct(EW_RET); + if (ret != PS_OK) return ret; + + // error + if (add_label("Initialize_____Plugins_error")) return PS_ERROR; + // error message box + ret=add_entry_direct(EW_MESSAGEBOX, MB_OK|MB_ICONSTOP|(IDOK<<21), add_string("Error! Can't initialize plug-ins directory. Please try again later.")); + if (ret != PS_OK) return ret; + // Quit + ret=add_entry_direct(EW_QUIT); + if (ret != PS_OK) return ret; + + // FunctionEnd + ret=function_end(); + if (ret != PS_OK) return ret; + + if (uninst_plugin_used && !uninstall) { + uninstall = true; + goto again; + } + + SCRIPT_MSG("Done!\n"); + + return PS_OK; +} +#endif // NSIS_CONFIG_PLUGIN_SUPPORT + +void CEXEBuild::init_res_editor() +{ + build_compressor_set = true; + if (!res_editor) + res_editor = new CResourceEditor(m_exehead, m_exehead_size); +} + +void CEXEBuild::close_res_editor() +{ + if (!res_editor) return; + DWORD newsize; + + // get size + newsize = res_editor->Save(NULL, newsize); + unsigned char *new_header = new unsigned char[newsize]; + + // save + int rc = res_editor->Save(new_header, newsize); + assert(rc == 0); + + update_exehead(new_header, newsize); + + // TODO: resource-controlling class + delete [] new_header; + + delete res_editor; + res_editor=0; +} + +int CEXEBuild::DeclaredUserVar(const char *szVarName) +{ + if (m_ShellConstants.get((char*)szVarName) >= 0) + { + ERROR_MSG("Error: name \"%s\" in use by constant\n", szVarName); + return PS_ERROR; + } + + int idxUserVar = m_UserVarNames.get((char*)szVarName); + if (idxUserVar >= 0) + { + ERROR_MSG("Error: variable \"%s\" already declared\n", szVarName); + return PS_ERROR; + } + const char *pVarName = szVarName; + int iVarLen = strlen(szVarName); + + if (iVarLen > 60) + { + ERROR_MSG("Error: variable name too long!\n"); + return PS_ERROR; + } + else if (!iVarLen) + { + ERROR_MSG("Error: variable with empty name!\n"); + return PS_ERROR; + } + else + { + while (*pVarName) + { + if (!isSimpleChar(*pVarName)) + { + ERROR_MSG("Error: invalid characters in variable name \"%s\", use only characters [a-z][A-Z][0-9] and '_'\n", szVarName); + return PS_ERROR; + } + pVarName++; + } + } + + m_UserVarNames.add(szVarName); + if (m_UserVarNames.getnum() > MAX_CODED) + { + ERROR_MSG("Error: too many user variables declared. Maximum allowed is %u.\n", MAX_CODED - m_iBaseVarsNum); + return PS_ERROR; + } + return PS_OK; +} + + +int CEXEBuild::GetUserVarIndex(LineParser &line, int token) +{ + char *p = line.gettoken_str(token); + if ( *p == '$' && *(p+1) ) + { + int idxUserVar = m_UserVarNames.get((char *)p+1); + if (idxUserVar >= 0 && m_UserVarNames.get_reference(idxUserVar) >= 0) + { + m_UserVarNames.inc_reference(idxUserVar); + return idxUserVar; + } + else + { + int idxConst = m_ShellConstants.get((char *)p+1); + if (idxConst >= 0) + { + ERROR_MSG("Error: cannot change constants : %s\n", p); + } + } + } + return -1; +} + +void CEXEBuild::VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList) +{ + for (int i = m_iBaseVarsNum; i < pVarsStringList->getnum(); i++) + { + if (!pVarsStringList->get_reference(i)) + { + warning("Variable \"%s\" not referenced or never set, wasting memory!", pVarsStringList->idx2name(i)); + } + } +} + +int CEXEBuild::set_compressor(const string& compressor, const bool solid) { + string stub = stubs_dir + PLATFORM_PATH_SEPARATOR_STR + compressor; + if (solid) + stub += "_solid"; + + return update_exehead(stub, &m_exehead_original_size); +} + +int CEXEBuild::update_exehead(const string& file, size_t *size/*=NULL*/) { + FILE *tmpfile = fopen(file.c_str(), "rb"); + if (!tmpfile) + { + ERROR_MSG("Error: opening stub \"%s\"\n", file.c_str()); + return PS_ERROR; + } + + fseek(tmpfile, 0, SEEK_END); + size_t exehead_size = ftell(tmpfile); + + unsigned char *exehead = new unsigned char[exehead_size]; + fseek(tmpfile, 0, SEEK_SET); + if (fread(exehead, 1, exehead_size, tmpfile) != exehead_size) + { + ERROR_MSG("Error: reading stub \"%s\"\n", file.c_str()); + fclose(tmpfile); + delete [] exehead; + return PS_ERROR; + } + fclose(tmpfile); + + update_exehead(exehead, exehead_size); + + if (size) + *size = exehead_size; + + delete [] exehead; + + return PS_OK; +} + +void CEXEBuild::update_exehead(const unsigned char *new_exehead, size_t new_size) { + assert(m_exehead != new_exehead); + + // align exehead to 512 + m_exehead_size = align_to_512(new_size); + + delete [] m_exehead; + m_exehead = new unsigned char[m_exehead_size]; + + // copy exehead + memcpy(m_exehead, new_exehead, new_size); + + // zero rest of exehead + memset(m_exehead + new_size, 0, m_exehead_size - new_size); +} + +void CEXEBuild::set_code_type_predefines(const char *value) +{ + definedlist.del("__SECTION__"); + definedlist.del("__FUNCTION__"); + definedlist.del("__PAGEEX__"); + definedlist.del("__GLOBAL__"); + + switch (GetCurrentTokenPlace()) + { + case TP_SEC: + definedlist.add("__SECTION__", value==NULL?"":value); + break; + case TP_FUNC: + definedlist.add("__FUNCTION__", value==NULL?"":value); + break; + case TP_PAGEEX: + definedlist.add("__PAGEEX__", value==NULL?"":value); + break; + default: + definedlist.add("__GLOBAL__"); + } +} + diff --git a/Source/build.h b/Source/build.h index 6c41a45..1defd58 100755 --- a/Source/build.h +++ b/Source/build.h @@ -1,415 +1,418 @@ -/*
- * build.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _BUILD_H_
-#define _BUILD_H_
-
-#include "strlist.h"
-#include "lineparse.h"
-#include "lang.h"
-#include "ResourceEditor.h"
-#include "ResourceVersionInfo.h"
-#include "uservars.h"
-#include "ShConstants.h"
-#include "mmap.h"
-#include "manifest.h"
-
-#include "exehead/fileform.h"
-#include "exehead/config.h"
-
-#include <string>
-#include <set>
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
-// Added by Sunil Kamath 11 June 2003
-# include <time.h>
-# include <sys/stat.h>
-#endif
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
-// Changed by Amir Szekely 31st July 2002
-#include "compressor.h"
-#include "czlib.h"
-#include "cbzip2.h"
-#include "clzma.h"
-
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
-# include "Plugins.h"
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
-
-#define PS_OK 0
-#define PS_EOF 1
-#define PS_ERROR 50
-#define PS_WARNING 100
-
-// token placement
-#define TP_SEC 1
-#define TP_FUNC 2
-#define TP_CODE (TP_SEC | TP_FUNC)
-#define TP_GLOBAL 4
-#define TP_PAGEEX 8
-#define TP_PG (TP_GLOBAL | TP_PAGEEX)
-#define TP_ALL (TP_CODE | TP_PG)
-
-enum notify_e {
- MAKENSIS_NOTIFY_SCRIPT,
- MAKENSIS_NOTIFY_WARNING,
- MAKENSIS_NOTIFY_ERROR,
- MAKENSIS_NOTIFY_OUTPUT
-};
-
-#define PAGE_CUSTOM 0
-#define PAGE_LICENSE 1
-#define PAGE_COMPONENTS 2
-#define PAGE_DIRECTORY 3
-#define PAGE_INSTFILES 4
-#define PAGE_UNINSTCONFIRM 5
-#define PAGE_COMPLETED 6
-
-class CEXEBuild {
- public:
- CEXEBuild();
- void initialize(const char *makensis_path);
- ~CEXEBuild();
-
- // to add a warning to the compiler's warning list.
- void warning(const char *s, ...);
- // warning with file name and line count
- void warning_fl(const char *s, ...);
-
- // to add a defined thing.
- void define(const char *p, const char *v="");
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- // Added by Ximon Eighteen 5th August 2002
- void build_plugin_table(void);
- int plugins_processed;
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
-
-
- // 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 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;
-
- int linecnt;
- char *curfilename;
- FILE *fp;
-
- HWND notify_hwnd;
- void notify(notify_e code, const char *data) const;
-
- private:
- int check_write_output_errors() const;
- int prepare_uninstaller();
- int pack_exe_header();
-
- int set_compressor(const std::string& compressor, const bool solid);
- int update_exehead(const std::string& file, size_t *size=NULL);
- void update_exehead(const unsigned char *new_exehead, size_t new_size);
-
- // tokens.cpp
- bool is_valid_token(char *s);
- int get_commandtoken(char *s, int *np, int *op, int *pos);
- int GetCurrentTokenPlace();
- int IsTokenPlacedRight(int pos, char *tok);
-
- // script.cpp
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- char* set_file_predefine(char *);
- void restore_file_predefine(char *);
- char* set_timestamp_predefine(char *);
- void restore_timestamp_predefine(char *);
- char* set_line_predefine(int, BOOL);
- void restore_line_predefine(char *);
- void set_date_time_predefines();
- void del_date_time_predefines();
-#endif
- int parseScript();
- int includeScript(char *f);
- int MacroExists(const char *macroname);
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
- void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines = false);
-#else
- void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist);
-#endif
- int doParse(const char *str);
- int doCommand(int which_token, LineParser &line);
-
- int do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char
- *name_override=0, int generatecode=1, int *data_handle=0,
- const std::set<std::string>& excluded=std::set<std::string>(),
- const std::string& basedir=std::string(""), bool dir_created=false);
- int add_file(const std::string& dir, const std::string& file, int attrib, const char
- *name_override, int generatecode, int *data_handle);
- int do_add_file_create_dir(const std::string& local_dir, const std::string& dir, int attrib=0);
-
- GrowBuf m_linebuild; // used for concatenating lines
-
- // used by doParse to do preprocessing
- struct ifblock
- {
- int hasexeced;
- int elseused;
- int ignore;
- int inherited_ignore;
- } *cur_ifblock;
-
- TinyGrowBuf build_preprocessor_data;
-
- void start_ifblock();
- void end_ifblock();
- int num_ifblock();
-
- int last_line_had_slash;
- bool inside_comment;
- int multiple_entries_instruction;
-
- void ERROR_MSG(const char *s, ...) const;
- void SCRIPT_MSG(const char *s, ...) const;
- void INFO_MSG(const char *s, ...) const;
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- int add_plugins_dir_initializer(void);
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
-
- // build.cpp functions used mostly by script.cpp
- void set_code_type_predefines(const char *value = NULL);
- int getcurdbsize();
- int add_section(const char *secname, const char *defname, int expand=0);
- 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 section_add_install_type(int inst_type);
- int add_page(int type);
- int page_end();
- int add_label(const char *name);
- int add_entry(const entry *ent);
- int add_entry_direct(int which, int o0=0, int o1=0, int o2=0, int o3=0, int o4=0, int o5=0);
- int add_db_data(IMMap *map); // returns offset
- int add_db_data(const char *data, int length); // returns offset
- int add_data(const char *data, int length, IGrowBuf *dblock); // returns offset
- int add_string(const char *string, int process=1, WORD codepage=CP_ACP); // returns offset (in string table)
- int add_intstring(const int i); // returns offset in stringblock
-
- int preprocess_string(char *out, const char *in, WORD codepage=CP_ACP);
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- // Added by Ximon Eighteen 5th August 2002
- Plugins m_plugins;
- bool plugin_used;
- bool uninst_plugin_used;
- int build_plugin_unload;
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
-
- // build.cpp functions used mostly within build.cpp
- int datablock_optimize(int start_offset, int first_int);
- void printline(int l);
- int process_jump(LineParser &line, int wt, int *offs);
-
- int AddVersionInfo();
- int ProcessPages();
- void PrepareInstTypes();
- void AddStandardStrings();
- void PrepareHeaders(IGrowBuf *hdrbuf);
- int SetVarsSection();
- int SetManifest();
-
- 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);
-
- // lang.cpp functions and variables
- void InitLangTables();
- LanguageTable *GetLangTable(LANGID &lang, bool create = true);
- char *GetLangNameAndCP(LANGID lang, unsigned int *codepage = NULL);
- int DefineLangString(char *name, int process=-1);
- int DefineInnerLangString(int id, int process=-1);
- int SetLangString(char *name, LANGID lang, char *string);
- int SetInnerString(int id, char *string);
- int GenerateLangTable(LanguageTable *lt, int num_lang_tables);
- int GenerateLangTables();
- void FillLanguageTable(LanguageTable *table);
- int HasUserDefined(int id) {
- const char *us = UserInnerStrings.get(id);
- return us && *us;
- };
-
- LanguageTable *LoadLangFile(char *filename);
- void DeleteLangTable(LanguageTable *table);
-
- NLFRef NLFRefs[NLF_STRINGS];
- bool keep_ref;
- StringsArray UserInnerStrings;
- bool defcodepage_set;
- GrowBuf lang_tables;
- LANGID last_used_lang;
- LangStringList build_langstrings;
- int build_langstring_num, ubuild_langstring_num;
- char build_font[1024];
- int build_font_size;
-
- unsigned int uDefCodePage;
-
- // pages stuff
- int license_res_id;
- page *cur_page;
- int cur_page_type;
- int enable_last_page_cancel, uenable_last_page_cancel;
-
- int disable_window_icon;
-
- // User variables stuff
- int GetUserVarIndex(LineParser &line, int token);
- // Added by ramon 3 jun 2003
- UserVarsStringList m_UserVarNames;
- int m_iBaseVarsNum;
- int DeclaredUserVar(const char *VarName);
- void VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList);
-
- ConstantsStringList m_ShellConstants;
-
- // a whole bunch O data.
-
- std::string stubs_dir;
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- ICompressor *compressor;
- CZlib zlib_compressor;
- CBzip2 bzip2_compressor;
- CLZMA lzma_compressor;
-#endif
- bool build_compressor_set;
- bool build_compressor_final;
- bool build_compress_whole;
- int build_compress;
- int build_compress_level;
- int build_compress_dict_size;
-
- bool no_space_texts;
-
- bool has_called_write_output;
-
- char build_packname[1024], build_packcmd[1024];
- int build_overwrite, build_last_overwrite, build_crcchk,
- build_datesave, build_optimize_datablock,
- build_allowskipfiles; // Added by ramon 23 May 2003
-
- header build_header, build_uninst, *cur_header;
- int uninstall_mode;
- int uninstall_size,uninstall_size_full;
- int uninstaller_writes_used;
-
- char build_output_filename[1024];
-
- int build_include_depth;
-
- // Added by ramon 6 jun 2003
-#ifdef NSIS_SUPPORT_VERSION_INFO
- CResourceVersionInfo rVersionInfo;
- char version_product_v[1024];
-#endif
-
- int sectiongroup_open_cnt;
- FastStringList 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;
-
- FastStringList include_dirs;
-
- StringList ns_func; // function namespace
- StringList ns_label; // label namespace
-
- int build_cursection_isfunc;
- section *build_cursection;
- TinyGrowBuf build_sections, ubuild_sections, *cur_sections;
- GrowBuf build_entries,ubuild_entries, *cur_entries;
- GrowBuf build_instruction_entry_map,ubuild_instruction_entry_map, *cur_instruction_entry_map;
- TinyGrowBuf build_functions, ubuild_functions, *cur_functions;
- TinyGrowBuf build_labels, ubuild_labels, *cur_labels;
- StringList build_strlist, ubuild_strlist, *cur_strlist;
- GrowBuf build_langtables, ubuild_langtables, *cur_langtables;
- TinyGrowBuf build_pages, ubuild_pages, *cur_pages;
- TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors;
-
- // don't forget to update the cache after updating the datablock
- // see datablock_optimize for an example
- MMapBuf build_datablock, ubuild_datablock;
- TinyGrowBuf build_datablock_cache, ubuild_datablock_cache;
- IGrowBuf *cur_datablock, *cur_datablock_cache;
- struct cached_db_size
- {
- int first_int; // size | (compressed ? 0x80000000 : 0)
- int start_offset;
- };
-
- int build_filebuflen;
-
- TinyGrowBuf verbose_stack;
-
- unsigned char *m_exehead;
- size_t m_exehead_size;
- size_t m_exehead_original_size;
-
- bool branding_image_found;
- WORD branding_image_id;
- unsigned char *m_unicon_data;
- size_t m_unicon_size;
-
-#ifdef NSIS_SUPPORT_BGBG
- LOGFONT bg_font;
- LOGFONT bg_default_font;
-#endif
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- int deflateToFile(FILE *fp, char *buf, int len); // len==0 to flush
-#endif
-
- manifest::comctl manifest_comctl;
- manifest::exec_level manifest_exec_level;
-
- CResourceEditor *res_editor;
- void init_res_editor();
- void close_res_editor();
-};
-
-#endif //_BUILD_H_
+/* + * build.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _BUILD_H_ +#define _BUILD_H_ + +#include "strlist.h" +#include "lineparse.h" +#include "lang.h" +#include "ResourceEditor.h" +#include "ResourceVersionInfo.h" +#include "uservars.h" +#include "ShConstants.h" +#include "mmap.h" +#include "manifest.h" +#include "icon.h" + +#include "exehead/fileform.h" +#include "exehead/config.h" + +#include <string> +#include <set> + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES +// Added by Sunil Kamath 11 June 2003 +# include <time.h> +# include <sys/stat.h> +#endif + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +// Changed by Amir Szekely 31st July 2002 +#include "compressor.h" +#include "czlib.h" +#include "cbzip2.h" +#include "clzma.h" + +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT +# include "Plugins.h" +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + +#define PS_OK 0 +#define PS_EOF 1 +#define PS_ERROR 50 +#define PS_WARNING 100 + +// token placement +#define TP_SEC 1 +#define TP_FUNC 2 +#define TP_CODE (TP_SEC | TP_FUNC) +#define TP_GLOBAL 4 +#define TP_PAGEEX 8 +#define TP_PG (TP_GLOBAL | TP_PAGEEX) +#define TP_ALL (TP_CODE | TP_PG) + +enum notify_e { + MAKENSIS_NOTIFY_SCRIPT, + MAKENSIS_NOTIFY_WARNING, + MAKENSIS_NOTIFY_ERROR, + MAKENSIS_NOTIFY_OUTPUT +}; + +#define PAGE_CUSTOM 0 +#define PAGE_LICENSE 1 +#define PAGE_COMPONENTS 2 +#define PAGE_DIRECTORY 3 +#define PAGE_INSTFILES 4 +#define PAGE_UNINSTCONFIRM 5 +#define PAGE_COMPLETED 6 + +class CEXEBuild { + public: + CEXEBuild(); + void initialize(const char *makensis_path); + ~CEXEBuild(); + + // to add a warning to the compiler's warning list. + void warning(const char *s, ...); + // warning with file name and line count + void warning_fl(const char *s, ...); + + // to add a defined thing. + void define(const char *p, const char *v=""); + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + // Added by Ximon Eighteen 5th August 2002 + void build_plugin_table(void); + int plugins_processed; +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + + + // 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 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; + + int linecnt; + char *curfilename; + FILE *fp; + + HWND notify_hwnd; + void notify(notify_e code, const char *data) const; + + private: + int check_write_output_errors() const; + int prepare_uninstaller(); + int pack_exe_header(); + + int set_compressor(const std::string& compressor, const bool solid); + int update_exehead(const std::string& file, size_t *size=NULL); + void update_exehead(const unsigned char *new_exehead, size_t new_size); + + // tokens.cpp + bool is_valid_token(char *s); + int get_commandtoken(char *s, int *np, int *op, int *pos); + int GetCurrentTokenPlace(); + int IsTokenPlacedRight(int pos, char *tok); + + // script.cpp +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + char* set_file_predefine(char *); + void restore_file_predefine(char *); + char* set_timestamp_predefine(char *); + void restore_timestamp_predefine(char *); + char* set_line_predefine(int, BOOL); + void restore_line_predefine(char *); + void set_date_time_predefines(); + void del_date_time_predefines(); +#endif + int parseScript(); + int includeScript(char *f); + int MacroExists(const char *macroname); +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines = false); +#else + void ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist); +#endif + int doParse(const char *str); + int doCommand(int which_token, LineParser &line); + + int do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char + *name_override=0, int generatecode=1, int *data_handle=0, + const std::set<std::string>& excluded=std::set<std::string>(), + const std::string& basedir=std::string(""), bool dir_created=false); + int add_file(const std::string& dir, const std::string& file, int attrib, const char + *name_override, int generatecode, int *data_handle); + int do_add_file_create_dir(const std::string& local_dir, const std::string& dir, int attrib=0); + + GrowBuf m_linebuild; // used for concatenating lines + + // used by doParse to do preprocessing + struct ifblock + { + int hasexeced; + int elseused; + int ignore; + int inherited_ignore; + } *cur_ifblock; + + TinyGrowBuf build_preprocessor_data; + + void start_ifblock(); + void end_ifblock(); + int num_ifblock(); + + int last_line_had_slash; + bool inside_comment; + int multiple_entries_instruction; + + void ERROR_MSG(const char *s, ...) const; + void SCRIPT_MSG(const char *s, ...) const; + void INFO_MSG(const char *s, ...) const; + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + int add_plugins_dir_initializer(void); +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + + // build.cpp functions used mostly by script.cpp + void set_code_type_predefines(const char *value = NULL); + int getcurdbsize(); + int add_section(const char *secname, const char *defname, int expand=0); + 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 section_add_install_type(int inst_type); + int add_page(int type); + int page_end(); + int add_label(const char *name); + int add_entry(const entry *ent); + int add_entry_direct(int which, int o0=0, int o1=0, int o2=0, int o3=0, int o4=0, int o5=0); + int add_db_data(IMMap *map); // returns offset + int add_db_data(const char *data, int length); // returns offset + int add_data(const char *data, int length, IGrowBuf *dblock); // returns offset + int add_string(const char *string, int process=1, WORD codepage=CP_ACP); // returns offset (in string table) + int add_intstring(const int i); // returns offset in stringblock + + int preprocess_string(char *out, const char *in, WORD codepage=CP_ACP); + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + // Added by Ximon Eighteen 5th August 2002 + Plugins m_plugins; + bool plugin_used; + bool uninst_plugin_used; + int build_plugin_unload; +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + + // build.cpp functions used mostly within build.cpp + int datablock_optimize(int start_offset, int first_int); + void printline(int l); + int process_jump(LineParser &line, int wt, int *offs); + + int AddVersionInfo(); + int ProcessPages(); + void PrepareInstTypes(); + void AddStandardStrings(); + void PrepareHeaders(IGrowBuf *hdrbuf); + int SetVarsSection(); + int SetManifest(); + + 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); + + // lang.cpp functions and variables + void InitLangTables(); + LanguageTable *GetLangTable(LANGID &lang, bool create = true); + char *GetLangNameAndCP(LANGID lang, unsigned int *codepage = NULL); + int DefineLangString(char *name, int process=-1); + int DefineInnerLangString(int id, int process=-1); + int SetLangString(char *name, LANGID lang, char *string); + int SetInnerString(int id, char *string); + int GenerateLangTable(LanguageTable *lt, int num_lang_tables); + int GenerateLangTables(); + void FillLanguageTable(LanguageTable *table); + int HasUserDefined(int id) { + const char *us = UserInnerStrings.get(id); + return us && *us; + }; + + LanguageTable *LoadLangFile(char *filename); + void DeleteLangTable(LanguageTable *table); + + NLFRef NLFRefs[NLF_STRINGS]; + bool keep_ref; + StringsArray UserInnerStrings; + bool defcodepage_set; + GrowBuf lang_tables; + LANGID last_used_lang; + LangStringList build_langstrings; + int build_langstring_num, ubuild_langstring_num; + char build_font[1024]; + int build_font_size; + + unsigned int uDefCodePage; + + // pages stuff + int license_res_id; + page *cur_page; + int cur_page_type; + int enable_last_page_cancel, uenable_last_page_cancel; + + int disable_window_icon; + + // User variables stuff + int GetUserVarIndex(LineParser &line, int token); + // Added by ramon 3 jun 2003 + UserVarsStringList m_UserVarNames; + int m_iBaseVarsNum; + int DeclaredUserVar(const char *VarName); + void VerifyDeclaredUserVarRefs(UserVarsStringList *pVarsStringList); + + ConstantsStringList m_ShellConstants; + + // a whole bunch O data. + + std::string stubs_dir; + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + ICompressor *compressor; + CZlib zlib_compressor; + CBzip2 bzip2_compressor; + CLZMA lzma_compressor; +#endif + bool build_compressor_set; + bool build_compressor_final; + bool build_compress_whole; + int build_compress; + int build_compress_level; + int build_compress_dict_size; + + bool no_space_texts; + + bool has_called_write_output; + + char build_packname[1024], build_packcmd[1024]; + int build_overwrite, build_last_overwrite, build_crcchk, + build_datesave, build_optimize_datablock, + build_allowskipfiles; // Added by ramon 23 May 2003 + + header build_header, build_uninst, *cur_header; + int uninstall_mode; + int uninstall_size,uninstall_size_full; + int uninstaller_writes_used; + + char build_output_filename[1024]; + + int build_include_depth; + + // Added by ramon 6 jun 2003 +#ifdef NSIS_SUPPORT_VERSION_INFO + CResourceVersionInfo rVersionInfo; + char version_product_v[1024]; +#endif + + int sectiongroup_open_cnt; + FastStringList 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; + + FastStringList include_dirs; + + StringList ns_func; // function namespace + StringList ns_label; // label namespace + + int build_cursection_isfunc; + section *build_cursection; + TinyGrowBuf build_sections, ubuild_sections, *cur_sections; + GrowBuf build_entries,ubuild_entries, *cur_entries; + GrowBuf build_instruction_entry_map,ubuild_instruction_entry_map, *cur_instruction_entry_map; + TinyGrowBuf build_functions, ubuild_functions, *cur_functions; + TinyGrowBuf build_labels, ubuild_labels, *cur_labels; + StringList build_strlist, ubuild_strlist, *cur_strlist; + GrowBuf build_langtables, ubuild_langtables, *cur_langtables; + TinyGrowBuf build_pages, ubuild_pages, *cur_pages; + TinyGrowBuf build_ctlcolors, ubuild_ctlcolors, *cur_ctlcolors; + + // don't forget to update the cache after updating the datablock + // see datablock_optimize for an example + MMapBuf build_datablock, ubuild_datablock; + TinyGrowBuf build_datablock_cache, ubuild_datablock_cache; + IGrowBuf *cur_datablock, *cur_datablock_cache; + struct cached_db_size + { + int first_int; // size | (compressed ? 0x80000000 : 0) + int start_offset; + }; + + int build_filebuflen; + + TinyGrowBuf verbose_stack; + + unsigned char *m_exehead; + size_t m_exehead_size; + size_t m_exehead_original_size; + + bool branding_image_found; + WORD branding_image_id; + + IconGroup installer_icon; + IconGroup uninstaller_icon; + size_t m_unicon_size; + +#ifdef NSIS_SUPPORT_BGBG + LOGFONT bg_font; + LOGFONT bg_default_font; +#endif + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + int deflateToFile(FILE *fp, char *buf, int len); // len==0 to flush +#endif + + manifest::comctl manifest_comctl; + manifest::exec_level manifest_exec_level; + + CResourceEditor *res_editor; + void init_res_editor(); + void close_res_editor(); +}; + +#endif //_BUILD_H_ diff --git a/Source/bzip2/blocksort.c b/Source/bzip2/blocksort.c index 6c2fa34..d752a1a 100755 --- a/Source/bzip2/blocksort.c +++ b/Source/bzip2/blocksort.c @@ -1,1109 +1,1109 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "bzlib.h"
-
-/*-------------------------------------------------------------*/
-/*--- Block sorting machinery ---*/
-/*--- blocksort.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
- This file is a part of bzip2 and/or libbzip2, a program and
- library for lossless, block-sorting data compression.
-
- Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Julian Seward, Cambridge, UK.
- jseward@acm.org
- bzip2/libbzip2 version 1.0 of 21 March 2000
-
- This program is based on (at least) the work of:
- Mike Burrows
- David Wheeler
- Peter Fenwick
- Alistair Moffat
- Radford Neal
- Ian H. Witten
- Robert Sedgewick
- Jon L. Bentley
-
- For more information on these sources, see the manual.
-
- To get some idea how the block sorting algorithms in this file
- work, read my paper
- On the Performance of BWT Sorting Algorithms
- in Proceedings of the IEEE Data Compression Conference 2000,
- Snowbird, Utah, USA, 27-30 March 2000. The main sort in this
- file implements the algorithm called cache in the paper.
---*/
-
-/*---------------------------------------------*/
-/*--- Fallback O(N log(N)^2) sorting ---*/
-/*--- algorithm, for repetitive blocks ---*/
-/*---------------------------------------------*/
-
-/*---------------------------------------------*/
-static void fallbackSimpleSort ( UInt32* fmap,
- UInt32* eclass,
- Int32 lo,
- Int32 hi )
-{
- Int32 i, j, tmp;
- UInt32 ec_tmp;
-
- if (lo == hi) return;
-
- if (hi - lo > 3) {
- for ( i = hi-4; i >= lo; i-- ) {
- tmp = fmap[i];
- ec_tmp = eclass[tmp];
- for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 )
- fmap[j-4] = fmap[j];
- fmap[j-4] = tmp;
- }
- }
-
- for ( i = hi-1; i >= lo; i-- ) {
- tmp = fmap[i];
- ec_tmp = eclass[tmp];
- for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ )
- fmap[j-1] = fmap[j];
- fmap[j-1] = tmp;
- }
-}
-
-
-/*---------------------------------------------*/
-#define fswap(zz1, zz2) \
- { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
-
-#define fvswap(zzp1, zzp2, zzn) \
-{ \
- Int32 yyp1 = (zzp1); \
- Int32 yyp2 = (zzp2); \
- Int32 yyn = (zzn); \
- while (yyn > 0) { \
- fswap(fmap[yyp1], fmap[yyp2]); \
- yyp1++; yyp2++; yyn--; \
- } \
-}
-
-
-#define fmin(a,b) ((a) < (b)) ? (a) : (b)
-
-#define fpush(lz,hz) { stackLo[sp] = lz; \
- stackHi[sp] = hz; \
- sp++; }
-
-#define fpop(lz,hz) { sp--; \
- lz = stackLo[sp]; \
- hz = stackHi[sp]; }
-
-#define FALLBACK_QSORT_SMALL_THRESH 10
-#define FALLBACK_QSORT_STACK_SIZE 100
-
-
-static
-void fallbackQSort3 ( UInt32* fmap,
- UInt32* eclass,
- Int32 loSt,
- Int32 hiSt )
-{
- Int32 unLo, unHi, ltLo, gtHi, n, m;
- Int32 sp, lo, hi;
- UInt32 med, r, r3;
- Int32 stackLo[FALLBACK_QSORT_STACK_SIZE];
- Int32 stackHi[FALLBACK_QSORT_STACK_SIZE];
-
- r = 0;
-
- sp = 0;
- fpush ( loSt, hiSt );
-
- while (sp > 0) {
-
- AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 );
-
- fpop ( lo, hi );
- if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
- fallbackSimpleSort ( fmap, eclass, lo, hi );
- continue;
- }
-
- /* Random partitioning. Median of 3 sometimes fails to
- avoid bad cases. Median of 9 seems to help but
- looks rather expensive. This too seems to work but
- is cheaper. Guidance for the magic constants
- 7621 and 32768 is taken from Sedgewick's algorithms
- book, chapter 35.
- */
- r = ((r * 7621) + 1) % 32768;
- r3 = r % 3;
- if (r3 == 0) med = eclass[fmap[lo]]; else
- if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else
- med = eclass[fmap[hi]];
-
- unLo = ltLo = lo;
- unHi = gtHi = hi;
-
- while (1) {
- while (1) {
- if (unLo > unHi) break;
- n = (Int32)eclass[fmap[unLo]] - (Int32)med;
- if (n == 0) {
- fswap(fmap[unLo], fmap[ltLo]);
- ltLo++; unLo++;
- continue;
- };
- if (n > 0) break;
- unLo++;
- }
- while (1) {
- if (unLo > unHi) break;
- n = (Int32)eclass[fmap[unHi]] - (Int32)med;
- if (n == 0) {
- fswap(fmap[unHi], fmap[gtHi]);
- gtHi--; unHi--;
- continue;
- };
- if (n < 0) break;
- unHi--;
- }
- if (unLo > unHi) break;
- fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--;
- }
-
- AssertD ( unHi == unLo-1, "fallbackQSort3(2)" );
-
- if (gtHi < ltLo) continue;
-
- n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n);
- m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m);
-
- n = lo + unLo - ltLo - 1;
- m = hi - (gtHi - unHi) + 1;
-
- if (n - lo > hi - m) {
- fpush ( lo, n );
- fpush ( m, hi );
- } else {
- fpush ( m, hi );
- fpush ( lo, n );
- }
- }
-}
-
-#undef fmin
-#undef fpush
-#undef fpop
-#undef fswap
-#undef fvswap
-#undef FALLBACK_QSORT_SMALL_THRESH
-#undef FALLBACK_QSORT_STACK_SIZE
-
-
-/*---------------------------------------------*/
-/* Pre:
- nblock > 0
- eclass exists for [0 .. nblock-1]
- ((UChar*)eclass) [0 .. nblock-1] holds block
- ptr exists for [0 .. nblock-1]
-
- Post:
- ((UChar*)eclass) [0 .. nblock-1] holds block
- All other areas of eclass destroyed
- fmap [0 .. nblock-1] holds sorted order
- bhtab [ 0 .. 2+(nblock/32) ] destroyed
-*/
-
-#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
-#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
-#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
-#define WORD_BH(zz) bhtab[(zz) >> 5]
-#define UNALIGNED_BH(zz) ((zz) & 0x01f)
-
-static
-void fallbackSort ( UInt32* fmap,
- UInt32* eclass,
- UInt32* bhtab,
- Int32 nblock)
-{
- Int32 ftab[257];
- Int32 ftabCopy[256];
- Int32 H, i, j, k, l, r, cc, cc1;
- Int32 nNotDone;
- Int32 nBhtab;
- UChar* eclass8 = (UChar*)eclass;
-
- /*--
- Initial 1-char radix sort to generate
- initial fmap and initial BH bits.
- --*/
- for (i = 0; i < 257; i++) ftab[i] = 0;
- for (i = 0; i < nblock; i++) ftab[eclass8[i]]++;
- for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i];
- for (i = 1; i < 257; i++) ftab[i] += ftab[i-1];
-
- for (i = 0; i < nblock; i++) {
- j = eclass8[i];
- k = ftab[j] - 1;
- ftab[j] = k;
- fmap[k] = i;
- }
-
- nBhtab = 2 + (nblock / 32);
- for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
- for (i = 0; i < 256; i++) SET_BH(ftab[i]);
-
- /*--
- Inductively refine the buckets. Kind-of an
- "exponential radix sort" (!), inspired by the
- Manber-Myers suffix array construction algorithm.
- --*/
-
- /*-- set sentinel bits for block-end detection --*/
- for (i = 0; i < 32; i++) {
- SET_BH(nblock + 2*i);
- CLEAR_BH(nblock + 2*i + 1);
- }
-
- /*-- the log(N) loop --*/
- H = 1;
- while (1) {
-
- j = 0;
- for (i = 0; i < nblock; i++) {
- if (ISSET_BH(i)) j = i;
- k = fmap[i] - H; if (k < 0) k += nblock;
- eclass[k] = j;
- }
-
- nNotDone = 0;
- r = -1;
- while (1) {
-
- /*-- find the next non-singleton bucket --*/
- k = r + 1;
- while (ISSET_BH(k) && UNALIGNED_BH(k)) k++;
- if (ISSET_BH(k)) {
- while (WORD_BH(k) == 0xffffffff) k += 32;
- while (ISSET_BH(k)) k++;
- }
- l = k - 1;
- if (l >= nblock) break;
- while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++;
- if (!ISSET_BH(k)) {
- while (WORD_BH(k) == 0x00000000) k += 32;
- while (!ISSET_BH(k)) k++;
- }
- r = k - 1;
- if (r >= nblock) break;
-
- /*-- now [l, r] bracket current bucket --*/
- if (r > l) {
- nNotDone += (r - l + 1);
- fallbackQSort3 ( fmap, eclass, l, r );
-
- /*-- scan bucket and generate header bits-- */
- cc = -1;
- for (i = l; i <= r; i++) {
- cc1 = eclass[fmap[i]];
- if (cc != cc1) { SET_BH(i); cc = cc1; };
- }
- }
- }
-
- H *= 2;
- if (H > nblock || nNotDone == 0) break;
- }
-
- /*--
- Reconstruct the original block in
- eclass8 [0 .. nblock-1], since the
- previous phase destroyed it.
- --*/
- j = 0;
- for (i = 0; i < nblock; i++) {
- while (ftabCopy[j] == 0) j++;
- ftabCopy[j]--;
- eclass8[fmap[i]] = (UChar)j;
- }
- AssertH ( j < 256, 1005 );
-}
-
-#undef SET_BH
-#undef CLEAR_BH
-#undef ISSET_BH
-#undef WORD_BH
-#undef UNALIGNED_BH
-
-
-/*---------------------------------------------*/
-/*--- The main, O(N^2 log(N)) sorting ---*/
-/*--- algorithm. Faster for "normal" ---*/
-/*--- non-repetitive blocks. ---*/
-/*---------------------------------------------*/
-
-/*---------------------------------------------*/
-static Bool mainGtU ( UInt32 i1,
- UInt32 i2,
- UChar* block,
- UInt16* quadrant,
- UInt32 nblock,
- Int32* budget )
-{
- Int32 k;
- UChar c1, c2;
- UInt16 s1, s2;
-
- AssertD ( i1 != i2, "mainGtU" );
- /* 1 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 2 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 3 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 4 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 5 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 6 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 7 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 8 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 9 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 10 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 11 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
- /* 12 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- i1++; i2++;
-
- k = nblock + 8;
-
- do {
- /* 1 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 2 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 3 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 4 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 5 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 6 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 7 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
- /* 8 */
- c1 = block[i1]; c2 = block[i2];
- if (c1 != c2) return (c1 > c2);
- s1 = quadrant[i1]; s2 = quadrant[i2];
- if (s1 != s2) return (s1 > s2);
- i1++; i2++;
-
- if (i1 >= nblock) i1 -= nblock;
- if (i2 >= nblock) i2 -= nblock;
-
- k -= 8;
- (*budget)--;
- }
- while (k >= 0);
-
- return False;
-}
-
-
-/*---------------------------------------------*/
-/*--
- Knuth's increments seem to work better
- than Incerpi-Sedgewick here. Possibly
- because the number of elems to sort is
- usually small, typically <= 20.
---*/
-static
-Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
- 9841, 29524, 88573, 265720,
- 797161, 2391484 };
-
-static
-void mainSimpleSort ( UInt32* ptr,
- UChar* block,
- UInt16* quadrant,
- Int32 nblock,
- Int32 lo,
- Int32 hi,
- Int32 d,
- Int32* budget )
-{
- Int32 i, j, h, bigN, hp;
- UInt32 v;
-
- bigN = hi - lo + 1;
- if (bigN < 2) return;
-
- hp = 0;
- while (incs[hp] < bigN) hp++;
- hp--;
-
- for (; hp >= 0; hp--) {
- h = incs[hp];
-
- i = lo + h;
- while (True) {
-
- /*-- copy 1 --*/
- if (i > hi) break;
- v = ptr[i];
- j = i;
- while ( mainGtU (
- ptr[j-h]+d, v+d, block, quadrant, nblock, budget
- ) ) {
- ptr[j] = ptr[j-h];
- j = j - h;
- if (j <= (lo + h - 1)) break;
- }
- ptr[j] = v;
- i++;
-
- /*-- copy 2 --*/
- if (i > hi) break;
- v = ptr[i];
- j = i;
- while ( mainGtU (
- ptr[j-h]+d, v+d, block, quadrant, nblock, budget
- ) ) {
- ptr[j] = ptr[j-h];
- j = j - h;
- if (j <= (lo + h - 1)) break;
- }
- ptr[j] = v;
- i++;
-
- /*-- copy 3 --*/
- if (i > hi) break;
- v = ptr[i];
- j = i;
- while ( mainGtU (
- ptr[j-h]+d, v+d, block, quadrant, nblock, budget
- ) ) {
- ptr[j] = ptr[j-h];
- j = j - h;
- if (j <= (lo + h - 1)) break;
- }
- ptr[j] = v;
- i++;
-
- if (*budget < 0) return;
- }
- }
-}
-
-
-/*---------------------------------------------*/
-/*--
- The following is an implementation of
- an elegant 3-way quicksort for strings,
- described in a paper "Fast Algorithms for
- Sorting and Searching Strings", by Robert
- Sedgewick and Jon L. Bentley.
---*/
-
-#define mswap(zz1, zz2) \
- { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; }
-
-#define mvswap(zzp1, zzp2, zzn) \
-{ \
- Int32 yyp1 = (zzp1); \
- Int32 yyp2 = (zzp2); \
- Int32 yyn = (zzn); \
- while (yyn > 0) { \
- mswap(ptr[yyp1], ptr[yyp2]); \
- yyp1++; yyp2++; yyn--; \
- } \
-}
-
-static
-UChar mmed3 ( UChar a, UChar b, UChar c )
-{
- UChar t;
- if (a > b) { t = a; a = b; b = t; };
- if (b > c) {
- b = c;
- if (a > b) b = a;
- }
- return b;
-}
-
-#define mmin(a,b) ((a) < (b)) ? (a) : (b)
-
-#define mpush(lz,hz,dz) { stackLo[sp] = lz; \
- stackHi[sp] = hz; \
- stackD [sp] = dz; \
- sp++; }
-
-#define mpop(lz,hz,dz) { sp--; \
- lz = stackLo[sp]; \
- hz = stackHi[sp]; \
- dz = stackD [sp]; }
-
-
-#define mnextsize(az) (nextHi[az]-nextLo[az])
-
-#define mnextswap(az,bz) \
- { Int32 tz; \
- tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
- tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
- tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; }
-
-
-#define MAIN_QSORT_SMALL_THRESH 20
-#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
-#define MAIN_QSORT_STACK_SIZE 100
-
-static
-void mainQSort3 ( UInt32* ptr,
- UChar* block,
- UInt16* quadrant,
- Int32 nblock,
- Int32 loSt,
- Int32 hiSt,
- Int32 dSt,
- Int32* budget )
-{
- Int32 unLo, unHi, ltLo, gtHi, n, m, med;
- Int32 sp, lo, hi, d;
-
- Int32 stackLo[MAIN_QSORT_STACK_SIZE];
- Int32 stackHi[MAIN_QSORT_STACK_SIZE];
- Int32 stackD [MAIN_QSORT_STACK_SIZE];
-
- Int32 nextLo[3];
- Int32 nextHi[3];
- Int32 nextD [3];
-
- sp = 0;
- mpush ( loSt, hiSt, dSt );
-
- while (sp > 0) {
-
- AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 );
-
- mpop ( lo, hi, d );
- if (hi - lo < MAIN_QSORT_SMALL_THRESH ||
- d > MAIN_QSORT_DEPTH_THRESH) {
- mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget );
- if (*budget < 0) return;
- continue;
- }
-
- med = (Int32)
- mmed3 ( block[ptr[ lo ]+d],
- block[ptr[ hi ]+d],
- block[ptr[ (lo+hi)>>1 ]+d] );
-
- unLo = ltLo = lo;
- unHi = gtHi = hi;
-
- while (True) {
- while (True) {
- if (unLo > unHi) break;
- n = ((Int32)block[ptr[unLo]+d]) - med;
- if (n == 0) {
- mswap(ptr[unLo], ptr[ltLo]);
- ltLo++; unLo++; continue;
- };
- if (n > 0) break;
- unLo++;
- }
- while (True) {
- if (unLo > unHi) break;
- n = ((Int32)block[ptr[unHi]+d]) - med;
- if (n == 0) {
- mswap(ptr[unHi], ptr[gtHi]);
- gtHi--; unHi--; continue;
- };
- if (n < 0) break;
- unHi--;
- }
- if (unLo > unHi) break;
- mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--;
- }
-
- AssertD ( unHi == unLo-1, "mainQSort3(2)" );
-
- if (gtHi < ltLo) {
- mpush(lo, hi, d+1 );
- continue;
- }
-
- n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n);
- m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m);
-
- n = lo + unLo - ltLo - 1;
- m = hi - (gtHi - unHi) + 1;
-
- nextLo[0] = lo; nextHi[0] = n; nextD[0] = d;
- nextLo[1] = m; nextHi[1] = hi; nextD[1] = d;
- nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
-
- if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
- if (mnextsize(1) < mnextsize(2)) mnextswap(1,2);
- if (mnextsize(0) < mnextsize(1)) mnextswap(0,1);
-
- AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" );
- AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" );
-
- mpush (nextLo[0], nextHi[0], nextD[0]);
- mpush (nextLo[1], nextHi[1], nextD[1]);
- mpush (nextLo[2], nextHi[2], nextD[2]);
- }
-}
-
-#undef mswap
-#undef mvswap
-#undef mpush
-#undef mpop
-#undef mmin
-#undef mnextsize
-#undef mnextswap
-#undef MAIN_QSORT_SMALL_THRESH
-#undef MAIN_QSORT_DEPTH_THRESH
-#undef MAIN_QSORT_STACK_SIZE
-
-
-/*---------------------------------------------*/
-/* Pre:
- nblock > N_OVERSHOOT
- block32 exists for [0 .. nblock-1 +N_OVERSHOOT]
- ((UChar*)block32) [0 .. nblock-1] holds block
- ptr exists for [0 .. nblock-1]
-
- Post:
- ((UChar*)block32) [0 .. nblock-1] holds block
- All other areas of block32 destroyed
- ftab [0 .. 65536 ] destroyed
- ptr [0 .. nblock-1] holds sorted order
- if (*budget < 0), sorting was abandoned
-*/
-
-#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
-#define SETMASK (1 << 21)
-#define CLEARMASK (~(SETMASK))
-
-static
-void mainSort ( UInt32* ptr,
- UChar* block,
- UInt16* quadrant,
- UInt32* ftab,
- Int32 nblock,
- Int32* budget )
-{
- Int32 i, j, k, ss, sb;
- Int32 runningOrder[256];
- Bool bigDone[256];
- Int32 copyStart[256];
- Int32 copyEnd [256];
- UChar c1;
- Int32 numQSorted;
- UInt16 s;
-
- /*-- set up the 2-byte frequency table --*/
- for (i = 65536; i >= 0; i--) ftab[i] = 0;
-
- j = block[0] << 8;
- i = nblock-1;
- for (; i >= 3; i -= 4) {
- quadrant[i] = 0;
- j = (j >> 8) | ( ((UInt16)block[i]) << 8);
- ftab[j]++;
- quadrant[i-1] = 0;
- j = (j >> 8) | ( ((UInt16)block[i-1]) << 8);
- ftab[j]++;
- quadrant[i-2] = 0;
- j = (j >> 8) | ( ((UInt16)block[i-2]) << 8);
- ftab[j]++;
- quadrant[i-3] = 0;
- j = (j >> 8) | ( ((UInt16)block[i-3]) << 8);
- ftab[j]++;
- }
- for (; i >= 0; i--) {
- quadrant[i] = 0;
- j = (j >> 8) | ( ((UInt16)block[i]) << 8);
- ftab[j]++;
- }
-
- /*-- (emphasises close relationship of block & quadrant) --*/
- for (i = 0; i < BZ_N_OVERSHOOT; i++) {
- block [nblock+i] = block[i];
- quadrant[nblock+i] = 0;
- }
-
- /*-- Complete the initial radix sort --*/
- for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1];
-
- s = block[0] << 8;
- i = nblock-1;
- for (; i >= 3; i -= 4) {
- s = (s >> 8) | (block[i] << 8);
- j = ftab[s] -1;
- ftab[s] = j;
- ptr[j] = i;
- s = (s >> 8) | (block[i-1] << 8);
- j = ftab[s] -1;
- ftab[s] = j;
- ptr[j] = i-1;
- s = (s >> 8) | (block[i-2] << 8);
- j = ftab[s] -1;
- ftab[s] = j;
- ptr[j] = i-2;
- s = (s >> 8) | (block[i-3] << 8);
- j = ftab[s] -1;
- ftab[s] = j;
- ptr[j] = i-3;
- }
- for (; i >= 0; i--) {
- s = (s >> 8) | (block[i] << 8);
- j = ftab[s] -1;
- ftab[s] = j;
- ptr[j] = i;
- }
-
- /*--
- Now ftab contains the first loc of every small bucket.
- Calculate the running order, from smallest to largest
- big bucket.
- --*/
- for (i = 0; i <= 255; i++) {
- bigDone [i] = False;
- runningOrder[i] = i;
- }
-
- {
- Int32 vv;
- Int32 h = 1;
- do h = 3 * h + 1; while (h <= 256);
- do {
- h = h / 3;
- for (i = h; i <= 255; i++) {
- vv = runningOrder[i];
- j = i;
- while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) {
- runningOrder[j] = runningOrder[j-h];
- j = j - h;
- if (j <= (h - 1)) goto zero;
- }
- zero:
- runningOrder[j] = vv;
- }
- } while (h != 1);
- }
-
- /*--
- The main sorting loop.
- --*/
-
- numQSorted = 0;
-
- for (i = 0; i <= 255; i++) {
-
- /*--
- Process big buckets, starting with the least full.
- Basically this is a 3-step process in which we call
- mainQSort3 to sort the small buckets [ss, j], but
- also make a big effort to avoid the calls if we can.
- --*/
- ss = runningOrder[i];
-
- /*--
- Step 1:
- Complete the big bucket [ss] by quicksorting
- any unsorted small buckets [ss, j], for j != ss.
- Hopefully previous pointer-scanning phases have already
- completed many of the small buckets [ss, j], so
- we don't have to sort them at all.
- --*/
- for (j = 0; j <= 255; j++) {
- if (j != ss) {
- sb = (ss << 8) + j;
- if ( ! (ftab[sb] & SETMASK) ) {
- Int32 lo = ftab[sb] & CLEARMASK;
- Int32 hi = (ftab[sb+1] & CLEARMASK) - 1;
- if (hi > lo) {
- mainQSort3 (
- ptr, block, quadrant, nblock,
- lo, hi, BZ_N_RADIX, budget
- );
- numQSorted += (hi - lo + 1);
- if (*budget < 0) return;
- }
- }
- ftab[sb] |= SETMASK;
- }
- }
-
- AssertH ( !bigDone[ss], 1006 );
-
- /*--
- Step 2:
- Now scan this big bucket [ss] so as to synthesise the
- sorted order for small buckets [t, ss] for all t,
- including, magically, the bucket [ss,ss] too.
- This will avoid doing Real Work in subsequent Step 1's.
- --*/
- {
- for (j = 0; j <= 255; j++) {
- copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK;
- copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
- }
- for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) {
- k = ptr[j]-1; if (k < 0) k += nblock;
- c1 = block[k];
- if (!bigDone[c1])
- ptr[ copyStart[c1]++ ] = k;
- }
- for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) {
- k = ptr[j]-1; if (k < 0) k += nblock;
- c1 = block[k];
- if (!bigDone[c1])
- ptr[ copyEnd[c1]-- ] = k;
- }
- }
-
- AssertH ( copyStart[ss]-1 == copyEnd[ss], 1007 );
-
- for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK;
-
- /*--
- Step 3:
- The [ss] big bucket is now done. Record this fact,
- and update the quadrant descriptors. Remember to
- update quadrants in the overshoot area too, if
- necessary. The "if (i < 255)" test merely skips
- this updating for the last bucket processed, since
- updating for the last bucket is pointless.
-
- The quadrant array provides a way to incrementally
- cache sort orderings, as they appear, so as to
- make subsequent comparisons in fullGtU() complete
- faster. For repetitive blocks this makes a big
- difference (but not big enough to be able to avoid
- the fallback sorting mechanism, exponential radix sort).
-
- The precise meaning is: at all times:
-
- for 0 <= i < nblock and 0 <= j <= nblock
-
- if block[i] != block[j],
-
- then the relative values of quadrant[i] and
- quadrant[j] are meaningless.
-
- else {
- if quadrant[i] < quadrant[j]
- then the string starting at i lexicographically
- precedes the string starting at j
-
- else if quadrant[i] > quadrant[j]
- then the string starting at j lexicographically
- precedes the string starting at i
-
- else
- the relative ordering of the strings starting
- at i and j has not yet been determined.
- }
- --*/
- bigDone[ss] = True;
-
- if (i < 255) {
- Int32 bbStart = ftab[ss << 8] & CLEARMASK;
- Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
- Int32 shifts = 0;
-
- while ((bbSize >> shifts) > 65534) shifts++;
-
- for (j = bbSize-1; j >= 0; j--) {
- Int32 a2update = ptr[bbStart + j];
- UInt16 qVal = (UInt16)(j >> shifts);
- quadrant[a2update] = qVal;
- if (a2update < BZ_N_OVERSHOOT)
- quadrant[a2update + nblock] = qVal;
- }
- AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 );
- }
-
- }
-}
-
-#undef BIGFREQ
-#undef SETMASK
-#undef CLEARMASK
-
-
-/*---------------------------------------------*/
-/* Pre:
- nblock > 0
- arr2 exists for [0 .. nblock-1 +N_OVERSHOOT]
- ((UChar*)arr2) [0 .. nblock-1] holds block
- arr1 exists for [0 .. nblock-1]
-
- Post:
- ((UChar*)arr2) [0 .. nblock-1] holds block
- All other areas of block destroyed
- ftab [ 0 .. 65536 ] destroyed
- arr1 [0 .. nblock-1] holds sorted order
-*/
-void BZ2_blockSort ( EState* s )
-{
- UInt32* ptr = s->ptr;
- UChar* block = s->block;
- UInt32* ftab = s->ftab;
- Int32 nblock = s->nblock;
- Int32 wfact = s->workFactor;
- UInt16* quadrant;
- Int32 budget;
- Int32 budgetInit;
- Int32 i;
-
- if (nblock < 10000) {
- fallbackSort ( s->arr1, s->arr2, ftab, nblock );
- } else {
- /* Calculate the location for quadrant, remembering to get
- the alignment right. Assumes that &(block[0]) is at least
- 2-byte aligned -- this should be ok since block is really
- the first section of arr2.
- */
- i = nblock+BZ_N_OVERSHOOT;
- if (i & 1) i++;
- quadrant = (UInt16*)(&(block[i]));
-
- /* (wfact-1) / 3 puts the default-factor-30
- transition point at very roughly the same place as
- with v0.1 and v0.9.0.
- Not that it particularly matters any more, since the
- resulting compressed stream is now the same regardless
- of whether or not we use the main sort or fallback sort.
- */
- if (wfact < 1 ) wfact = 1;
- if (wfact > 100) wfact = 100;
- budgetInit = nblock * ((wfact-1) / 3);
- budget = budgetInit;
-
- mainSort ( ptr, block, quadrant, ftab, nblock, &budget );
- if (budget < 0) {
- fallbackSort ( s->arr1, s->arr2, ftab, nblock );
- }
- }
-
- s->origPtr = -1;
- for (i = 0; i < s->nblock; i++)
- if (ptr[i] == 0)
- { s->origPtr = i; break; };
-
- AssertH( s->origPtr != -1, 1003 );
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end blocksort.c ---*/
-/*-------------------------------------------------------------*/
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "bzlib.h" + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. + + To get some idea how the block sorting algorithms in this file + work, read my paper + On the Performance of BWT Sorting Algorithms + in Proceedings of the IEEE Data Compression Conference 2000, + Snowbird, Utah, USA, 27-30 March 2000. The main sort in this + file implements the algorithm called cache in the paper. +--*/ + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( copyStart[ss]-1 == copyEnd[ss], 1007 ); + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, &budget ); + if (budget < 0) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/bzlib.c b/Source/bzip2/bzlib.c index 4aec93a..8fba030 100755 --- a/Source/bzip2/bzlib.c +++ b/Source/bzip2/bzlib.c @@ -1,621 +1,621 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "bzlib.h"
-
-/*-------------------------------------------------------------*/
-/*--- 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.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 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;
- 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 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 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
-
-#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE
-/*---------------------------------------------------*/
-
-Int32 NSISCALL 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;
-}
-
-
-static
-void NSISCALL unRLE_obuf_to_output_SMALL ( DState* s )
-{
- UChar k1;
- while (True) {
- /* try to finish existing run */
- while (True) {
- if (s->avail_out == 0) return;
- if (s->state_out_len == 0) break;
- *( (UChar*)(s->next_out) ) = s->state_out_ch;
- s->state_out_len--;
- s->next_out++;
- s->avail_out--;
- }
-
- /* 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 NSISCALL unRLE_obuf_to_output_FAST ( DState* s )
-{
- UChar k1;
-
- /* restore */
- 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_tPos = s->tPos;
-
- char* cs_next_out = s->next_out;
- unsigned int cs_avail_out = s->avail_out;
- /* end restore */
-
- UInt32* c_tt = s->tt;
- 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;
- 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;
- 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:
- 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->tPos = c_tPos;
- s->next_out = cs_next_out;
- s->avail_out = cs_avail_out;
- /* end save */
-}
-
-#endif
-
-
-/*---------------------------------------------------*/
-int NSISCALL BZ2_bzDecompress( DState *s )
-{
- 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;
- }
- }
-}
-
-
-
-#endif
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "bzlib.h" + +/*-------------------------------------------------------------*/ +/*--- 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.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 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; + 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 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 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 + +#ifdef NSIS_COMPRESS_BZIP2_SMALLMODE +/*---------------------------------------------------*/ + +Int32 NSISCALL 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; +} + + +static +void NSISCALL unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + while (True) { + /* try to finish existing run */ + while (True) { + if (s->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->next_out) ) = s->state_out_ch; + s->state_out_len--; + s->next_out++; + s->avail_out--; + } + + /* 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 NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + /* restore */ + 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_tPos = s->tPos; + + char* cs_next_out = s->next_out; + unsigned int cs_avail_out = s->avail_out; + /* end restore */ + + UInt32* c_tt = s->tt; + 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; + 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; + 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: + 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->tPos = c_tPos; + s->next_out = cs_next_out; + s->avail_out = cs_avail_out; + /* end save */ +} + +#endif + + +/*---------------------------------------------------*/ +int NSISCALL BZ2_bzDecompress( DState *s ) +{ + 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; + } + } +} + + + +#endif diff --git a/Source/bzip2/bzlib.h b/Source/bzip2/bzlib.h index 2554364..c5a5c37 100755 --- a/Source/bzip2/bzlib.h +++ b/Source/bzip2/bzlib.h @@ -1,444 +1,444 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/*-------------------------------------------------------------*/
-/*--- 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
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "../exehead/config.h"
-#include "../Platform.h"
-
-#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)
-
-/*-- 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))
-
-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)
-
-#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) /* */
-
-#ifndef EXEHEAD
-
-#define BZALLOC(items) malloc(items)
-#define BZFREE(addr) { if (addr) free(addr); }
-#define mini_memcpy memcpy
-
-typedef struct {
- char *next_in;
- unsigned int avail_in;
-
- char *next_out;
- unsigned int avail_out;
-
- void *state;
-} bz_stream;
-
-/*-- Core (low-level) library functions --*/
-
-extern int BZ2_bzCompressInit(
- bz_stream* strm,
- int blockSize100k,
- int verbosity,
- int workFactor
- );
-
-extern int BZ2_bzCompress( bz_stream* strm, int action );
-extern int BZ2_bzCompressEnd(bz_stream* strm );
-
-/*-- 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;
-
- /* 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 );
-
-#else//EXEHEAD
-
-/*-- 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
-
-
-
-/* save area for scalars in the main decompress code */
-typedef struct {
- 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;
-} DState_save;
-
-/*-- Structure holding all the decompression-side stuff. --*/
-
-typedef struct {
- /* pointer back to the struct bz_stream */
- char *next_in;
- unsigned int avail_in;
-
- char *next_out;
- unsigned int avail_out;
-
- /* state indicator for this stream */
- char state;
-
- UChar state_out_ch;
- Int32 state_out_len;
- Int32 nblock_used;
- Int32 k0;
- UInt32 tPos;
-
- /* the buffer for bit stream reading */
- UInt32 bsBuff;
- Int32 bsLive;
-
- /* for undoing the Burrows-Wheeler transform */
- Int32 origPtr;
- Int32 unzftab[256];
- Int32 cftab[257];
- Int32 cftabCopy[257];
-
-#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE
- /* for undoing the Burrows-Wheeler transform (FAST) */
- UInt32 tt[ NSIS_COMPRESS_BZIP2_LEVEL * 100000 ];
-#else
- /* for undoing the Burrows-Wheeler transform (SMALL) */
- UInt16 ll16 [ NSIS_COMPRESS_BZIP2_LEVEL*100000 ];
- UChar ll4 [((1 + NSIS_COMPRESS_BZIP2_LEVEL*100000) >> 1) ];
-#endif
-
- /* 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 */
- DState_save save;
-} DState;
-
-
-#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE
-/*-- 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;
-
-
-#else//NSIS_COMPRESS_BZIP2_SMALLMODE
-
-#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);
-
-extern Int32 BZ2_indexIntoF( Int32, Int32* );
-
-#endif//smallmode
-
-/*-- externs for decompression. --*/
-extern Int32 NSISCALL BZ2_decompress ( DState* );
-
-extern void NSISCALL BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
- Int32, Int32, Int32 );
-
-
-#define BZ2_bzDecompressInit(s) { (s)->state = BZ_X_BLKHDR_1; (s)->bsLive = 0; }
-int NSISCALL BZ2_bzDecompress(DState *s);
-
-#endif//EXEHEAD
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/*-------------------------------------------------------------*/
-/*--- end bzlib.h ---*/
-/*-------------------------------------------------------------*/
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/*-------------------------------------------------------------*/ +/*--- 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 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../exehead/config.h" +#include "../Platform.h" + +#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) + +/*-- 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)) + +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) + +#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) /* */ + +#ifndef EXEHEAD + +#define BZALLOC(items) malloc(items) +#define BZFREE(addr) { if (addr) free(addr); } +#define mini_memcpy memcpy + +typedef struct { + char *next_in; + unsigned int avail_in; + + char *next_out; + unsigned int avail_out; + + void *state; +} bz_stream; + +/*-- Core (low-level) library functions --*/ + +extern int BZ2_bzCompressInit( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +extern int BZ2_bzCompress( bz_stream* strm, int action ); +extern int BZ2_bzCompressEnd(bz_stream* strm ); + +/*-- 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; + + /* 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 ); + +#else//EXEHEAD + +/*-- 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 + + + +/* save area for scalars in the main decompress code */ +typedef struct { + 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; +} DState_save; + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef struct { + /* pointer back to the struct bz_stream */ + char *next_in; + unsigned int avail_in; + + char *next_out; + unsigned int avail_out; + + /* state indicator for this stream */ + char state; + + UChar state_out_ch; + Int32 state_out_len; + Int32 nblock_used; + Int32 k0; + UInt32 tPos; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + Int32 unzftab[256]; + Int32 cftab[257]; + Int32 cftabCopy[257]; + +#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 tt[ NSIS_COMPRESS_BZIP2_LEVEL * 100000 ]; +#else + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 ll16 [ NSIS_COMPRESS_BZIP2_LEVEL*100000 ]; + UChar ll4 [((1 + NSIS_COMPRESS_BZIP2_LEVEL*100000) >> 1) ]; +#endif + + /* 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 */ + DState_save save; +} DState; + + +#ifndef NSIS_COMPRESS_BZIP2_SMALLMODE +/*-- 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; + + +#else//NSIS_COMPRESS_BZIP2_SMALLMODE + +#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); + +extern Int32 BZ2_indexIntoF( Int32, Int32* ); + +#endif//smallmode + +/*-- externs for decompression. --*/ +extern Int32 NSISCALL BZ2_decompress ( DState* ); + +extern void NSISCALL BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#define BZ2_bzDecompressInit(s) { (s)->state = BZ_X_BLKHDR_1; (s)->bsLive = 0; } +int NSISCALL BZ2_bzDecompress(DState *s); + +#endif//EXEHEAD + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/compress.c b/Source/bzip2/compress.c index 67485f4..6263c5f 100755 --- a/Source/bzip2/compress.c +++ b/Source/bzip2/compress.c @@ -1,669 +1,669 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/*-------------------------------------------------------------*/
-/*--- 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.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 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 );
-
- 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 );
- bsFinishWrite ( s );
- }
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end compress.c ---*/
-/*-------------------------------------------------------------*/
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/*-------------------------------------------------------------*/ +/*--- 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.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 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 ); + + 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 ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/decompress.c b/Source/bzip2/decompress.c index 675c186..bf00a67 100755 --- a/Source/bzip2/decompress.c +++ b/Source/bzip2/decompress.c @@ -1,534 +1,534 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "bzlib.h"
-
-/*-------------------------------------------------------------*/
-/*--- 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.
---*/
-
-
-/*---------------------------------------------------*/
-#define RETURN(rrr) \
- { retVal = rrr; goto save_state_and_return; };
-
-
-static int NSISCALL __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;
- return 0;
- }
- if (s->avail_in == 0) return 1;
- s->bsBuff = (s->bsBuff << 8) | ((UInt32) (*((UChar*)(s->next_in))));
- s->bsLive += 8;
- s->next_in++;
- s->avail_in--;
- }
-}
-
-#define GET_BITS(lll,vvv,nnn) \
- case lll: s->state = lll; \
- if (__mygetbits(&vvv,nnn,s)) RETURN(BZ_OK)
-
-#define GET_UCHAR(lll,uuu) \
- GET_BITS(lll,uuu,8)
-
-#define GET_BIT(lll,uuu) \
- GET_BITS(lll,uuu,1)
-
-static int NSISCALL getmtf1(DState_save *sv,DState* s)
-{
- if (sv->groupPos == 0) {
- sv->groupNo++;
- if (sv->groupNo >= sv->nSelectors) return 1;
- sv->groupPos = BZ_G_SIZE;
- sv->gSel = s->selector[sv->groupNo];
- sv->gMinlen = s->minLens[sv->gSel];
- sv->gLimit = &(s->limit[sv->gSel][0]);
- sv->gPerm = &(s->perm[sv->gSel][0]);
- sv->gBase = &(s->base[sv->gSel][0]);
- }
- sv->groupPos--;
- sv->zn = sv->gMinlen;
- return 0;
-}
-
-/*---------------------------------------------------*/
-#define GET_MTF_VAL(label1,label2,lval) \
-{ \
- if (getmtf1(&sv,s)) RETURN(BZ_DATA_ERROR); \
- GET_BITS(label1, zvec, zn); \
- for (;;) { \
- 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 NSISCALL BZ2_decompress ( DState* s )
-{
- Int32 uc;
- Int32 retVal;
- Int32 minLen, maxLen;
-
- /* stuff that needs to be saved/restored */
- DState_save sv;
-
- /*restore from the save area*/
- sv=s->save;//mini_memcpy(&sv, &(s->save), sizeof(sv));
-
- #define i (sv.i)
- #define j (sv.j)
- #define t (sv.t)
- #define alphaSize (sv.alphaSize)
- #define nGroups (sv.nGroups)
- #define nSelectors (sv.nSelectors)
- #define EOB (sv.EOB)
- #define groupNo (sv.groupNo)
- #define groupPos (sv.groupPos)
- #define nextSym (sv.nextSym)
- #define nblockMAX (sv.nblockMAX)
- #define nblock (sv.nblock)
- #define es (sv.es)
- #define N (sv.N)
- #define curr (sv.curr)
- #define zt (sv.zt)
- #define zn (sv.zn)
- #define zvec (sv.zvec)
- #define zj (sv.zj)
- #define gSel (sv.gSel)
- #define gMinlen (sv.gMinlen)
- #define gLimit (sv.gLimit)
- #define gBase (sv.gBase)
- #define gPerm (sv.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->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;
- }
- {
- Int32 qi;
- s->nInUse = 0;
- for (qi = 0; qi < 256; qi++)
- if (s->inUse[qi])
- s->seqToUnseq[s->nInUse++] = qi;
- }
-
- 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 = 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;
- while (nextSym == BZ_RUNA || nextSym == BZ_RUNB)
- {
- if (nextSym == BZ_RUNA) es += N;
- N = N << 1;
- if (nextSym == BZ_RUNB) es += N;
- GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
- }
-
- 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;
- 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;
- 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=sv; //mini_memcpy(&(s->save), &sv, sizeof(sv));
-
- #undef i
- #undef j
- #undef t
- #undef alphaSize
- #undef nGroups
- #undef nSelectors
- #undef EOB
- #undef groupNo
- #undef groupPos
- #undef nextSym
- #undef nblockMAX
- #undef nblock
- #undef es
- #undef N
- #undef curr
- #undef zt
- #undef zn
- #undef zvec
- #undef zj
- #undef gSel
- #undef gMinlen
- #undef gLimit
- #undef gBase
- #undef gPerm
-
- return retVal;
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end decompress.c ---*/
-/*-------------------------------------------------------------*/
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "bzlib.h" + +/*-------------------------------------------------------------*/ +/*--- 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. +--*/ + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + + +static int NSISCALL __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; + return 0; + } + if (s->avail_in == 0) return 1; + s->bsBuff = (s->bsBuff << 8) | ((UInt32) (*((UChar*)(s->next_in)))); + s->bsLive += 8; + s->next_in++; + s->avail_in--; + } +} + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + if (__mygetbits(&vvv,nnn,s)) RETURN(BZ_OK) + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +static int NSISCALL getmtf1(DState_save *sv,DState* s) +{ + if (sv->groupPos == 0) { + sv->groupNo++; + if (sv->groupNo >= sv->nSelectors) return 1; + sv->groupPos = BZ_G_SIZE; + sv->gSel = s->selector[sv->groupNo]; + sv->gMinlen = s->minLens[sv->gSel]; + sv->gLimit = &(s->limit[sv->gSel][0]); + sv->gPerm = &(s->perm[sv->gSel][0]); + sv->gBase = &(s->base[sv->gSel][0]); + } + sv->groupPos--; + sv->zn = sv->gMinlen; + return 0; +} + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (getmtf1(&sv,s)) RETURN(BZ_DATA_ERROR); \ + GET_BITS(label1, zvec, zn); \ + for (;;) { \ + 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 NSISCALL BZ2_decompress ( DState* s ) +{ + Int32 uc; + Int32 retVal; + Int32 minLen, maxLen; + + /* stuff that needs to be saved/restored */ + DState_save sv; + + /*restore from the save area*/ + sv=s->save;//mini_memcpy(&sv, &(s->save), sizeof(sv)); + + #define i (sv.i) + #define j (sv.j) + #define t (sv.t) + #define alphaSize (sv.alphaSize) + #define nGroups (sv.nGroups) + #define nSelectors (sv.nSelectors) + #define EOB (sv.EOB) + #define groupNo (sv.groupNo) + #define groupPos (sv.groupPos) + #define nextSym (sv.nextSym) + #define nblockMAX (sv.nblockMAX) + #define nblock (sv.nblock) + #define es (sv.es) + #define N (sv.N) + #define curr (sv.curr) + #define zt (sv.zt) + #define zn (sv.zn) + #define zvec (sv.zvec) + #define zj (sv.zj) + #define gSel (sv.gSel) + #define gMinlen (sv.gMinlen) + #define gLimit (sv.gLimit) + #define gBase (sv.gBase) + #define gPerm (sv.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->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; + } + { + Int32 qi; + s->nInUse = 0; + for (qi = 0; qi < 256; qi++) + if (s->inUse[qi]) + s->seqToUnseq[s->nInUse++] = qi; + } + + 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 = 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; + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB) + { + if (nextSym == BZ_RUNA) es += N; + N = N << 1; + if (nextSym == BZ_RUNB) es += N; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + + 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; + 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; + 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=sv; //mini_memcpy(&(s->save), &sv, sizeof(sv)); + + #undef i + #undef j + #undef t + #undef alphaSize + #undef nGroups + #undef nSelectors + #undef EOB + #undef groupNo + #undef groupPos + #undef nextSym + #undef nblockMAX + #undef nblock + #undef es + #undef N + #undef curr + #undef zt + #undef zn + #undef zvec + #undef zj + #undef gSel + #undef gMinlen + #undef gLimit + #undef gBase + #undef gPerm + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/bzip2/huffman.c b/Source/bzip2/huffman.c index d36ccb0..1273e60 100755 --- a/Source/bzip2/huffman.c +++ b/Source/bzip2/huffman.c @@ -1,244 +1,244 @@ -/*
- * This file is a part of the bzip2 compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.bzip.org/
- *
- * This modification is not compatible with the original bzip2.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "bzlib.h"
-
-/*-------------------------------------------------------------*/
-/*--- 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.
---*/
-
-#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 NSISCALL
-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 ---*/
-/*-------------------------------------------------------------*/
+/* + * This file is a part of the bzip2 compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.bzip.org/ + * + * This modification is not compatible with the original bzip2. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "bzlib.h" + +/*-------------------------------------------------------------*/ +/*--- 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. +--*/ + +#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 NSISCALL +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 ---*/ +/*-------------------------------------------------------------*/ diff --git a/Source/cbzip2.h b/Source/cbzip2.h index 840af93..638b16c 100755 --- a/Source/cbzip2.h +++ b/Source/cbzip2.h @@ -1,99 +1,99 @@ -/*
- * cbzip2.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __CBZIP2_H__
-#define __CBZIP2_H__
-
-#include "compressor.h"
-#include "bzip2/bzlib.h"
-
-class CBzip2 : public ICompressor {
- public:
- virtual ~CBzip2() {}
-
- int Init(int level, unsigned int dict_size) {
- last_ret = !BZ_STREAM_END;
- 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) {
- // act like zlib when it comes to stream ending
- if (last_ret == BZ_STREAM_END && finish)
- return C_FINISHED;
- last_ret = BZ2_bzCompress(stream, finish?BZ_FINISH:0);
-
- if (last_ret < 0)
- return last_ret;
-
- return C_OK;
- }
-
- 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;
- }
-
- const char* GetName() {
- return "bzip2";
- }
-
- const char* GetErrStr(int err) {
- switch (err)
- {
- case BZ_SEQUENCE_ERROR:
- return "sequence error - bad call";
- case BZ_PARAM_ERROR:
- return "parameter error - bad call";
- case BZ_MEM_ERROR:
- return "not enough memory";
- case BZ_CONFIG_ERROR:
- return "config error";
- default:
- return "unknown error";
- }
- }
-
- private:
- bz_stream *stream;
- int last_ret;
-};
-
-#endif
+/* + * cbzip2.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __CBZIP2_H__ +#define __CBZIP2_H__ + +#include "compressor.h" +#include "bzip2/bzlib.h" + +class CBzip2 : public ICompressor { + public: + virtual ~CBzip2() {} + + int Init(int level, unsigned int dict_size) { + last_ret = !BZ_STREAM_END; + 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) { + // act like zlib when it comes to stream ending + if (last_ret == BZ_STREAM_END && finish) + return C_FINISHED; + last_ret = BZ2_bzCompress(stream, finish?BZ_FINISH:0); + + if (last_ret < 0) + return last_ret; + + return C_OK; + } + + 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; + } + + const char* GetName() { + return "bzip2"; + } + + const char* GetErrStr(int err) { + switch (err) + { + case BZ_SEQUENCE_ERROR: + return "sequence error - bad call"; + case BZ_PARAM_ERROR: + return "parameter error - bad call"; + case BZ_MEM_ERROR: + return "not enough memory"; + case BZ_CONFIG_ERROR: + return "config error"; + default: + return "unknown error"; + } + } + + private: + bz_stream *stream; + int last_ret; +}; + +#endif diff --git a/Source/clzma.cpp b/Source/clzma.cpp index 366b179..2714055 100755 --- a/Source/clzma.cpp +++ b/Source/clzma.cpp @@ -1,464 +1,464 @@ -/*
- * clzma.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include <algorithm> // for std::min
-#include "clzma.h"
-
-using namespace std;
-
-#ifndef _WIN32
-struct evnet_t
-{
- pthread_cond_t cond;
- pthread_mutex_t mutex;
- bool signaled;
-};
-
-HANDLE CreateEvent(void *, BOOL, BOOL, char *)
-{
- evnet_t *event = (evnet_t *) malloc(sizeof(evnet_t));
- if (!event)
- return 0;
- if (pthread_cond_init(&event->cond, NULL))
- {
- free(event);
- return 0;
- }
- if (pthread_mutex_init(&event->mutex, NULL))
- {
- pthread_cond_destroy(&event->cond);
- free(event);
- return 0;
- }
- event->signaled = false;
- return (HANDLE) event;
-}
-
-BOOL SetEvent(HANDLE _event)
-{
- evnet_t *event = (evnet_t *) _event;
- if (pthread_mutex_lock(&event->mutex))
- return FALSE;
- event->signaled = true;
- pthread_cond_signal(&event->cond);
- if (pthread_mutex_unlock(&event->mutex))
- return FALSE;
- return TRUE;
-}
-
-BOOL ResetEvent(HANDLE _event)
-{
- evnet_t *event = (evnet_t *) _event;
- if (pthread_mutex_lock(&event->mutex))
- return FALSE;
- event->signaled = false;
- if (pthread_mutex_unlock(&event->mutex))
- return FALSE;
- return TRUE;
-}
-
-BOOL CloseHandle(HANDLE _event)
-{
- BOOL ret = TRUE;
- evnet_t *event = (evnet_t *) _event;
- if (!event)
- return FALSE;
- if (pthread_cond_destroy(&event->cond))
- ret = FALSE;
- if (pthread_mutex_destroy(&event->mutex))
- ret = FALSE;
- free(event);
- return ret;
-}
-
-#define WAIT_OBJECT_0 0
-#define INFINITE 0
-DWORD WaitForSingleObject(HANDLE _event, DWORD) {
- DWORD ret = WAIT_OBJECT_0;
- evnet_t *event = (evnet_t *) _event;
- if (pthread_mutex_lock(&event->mutex))
- return !WAIT_OBJECT_0;
- if (!event->signaled)
- {
- if (pthread_cond_wait(&event->cond, &event->mutex))
- {
- ret = !WAIT_OBJECT_0;
- }
- }
- event->signaled = false;
- pthread_mutex_unlock(&event->mutex);
- return ret;
-}
-
-#define WaitForMultipleObjects(x, list, y, t) WaitForSingleObject(list[0], t)
-
-#endif
-
-#ifdef _WIN32
-DWORD CLZMA::lzmaCompressThread(LPVOID lpParameter)
-#else
-void* CLZMA::lzmaCompressThread(void *lpParameter)
-#endif
-{
- CLZMA *Compressor = (CLZMA *) lpParameter;
- if (!Compressor)
- return 0;
-
- Compressor->CompressReal();
- return 0;
-}
-
-int CLZMA::ConvertError(HRESULT result)
-{
- if (result != S_OK)
- {
- if (result == E_OUTOFMEMORY)
- return LZMA_MEM_ERROR;
- else
- return LZMA_IO_ERROR;
- }
- return C_OK;
-}
-
-CLZMA::CLZMA(): _encoder(NULL)
-{
- _encoder = new NCompress::NLZMA::CEncoder();
- _encoder->SetWriteEndMarkerMode(true);
-#ifdef _WIN32
- hCompressionThread = NULL;
-#else
- hCompressionThread = 0;
-#endif
- hNeedIOEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- hIOReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- finish = FALSE;
- compressor_finished = TRUE;
- hCompressionThread = 0;
- SetNextOut(NULL, 0);
- SetNextIn(NULL, 0);
-
- AddRef(); // will be manually deleted, not released
-}
-
-CLZMA::~CLZMA()
-{
- End();
- if (hNeedIOEvent)
- {
- CloseHandle(hNeedIOEvent);
- hNeedIOEvent = NULL;
- }
- if (hIOReadyEvent)
- {
- CloseHandle(hIOReadyEvent);
- hIOReadyEvent = NULL;
- }
- if (_encoder)
- {
- delete _encoder;
- _encoder = NULL;
- }
-}
-
-int CLZMA::Init(int level, unsigned int dicSize)
-{
- End();
-
- compressor_finished = FALSE;
- finish = FALSE;
- res = C_OK;
-
- if (!hNeedIOEvent || !hIOReadyEvent)
- {
- return LZMA_INIT_ERROR;
- }
-
- ResetEvent(hNeedIOEvent);
- ResetEvent(hIOReadyEvent);
-
- res = C_OK;
-
- PROPID propdIDs [] =
- {
- NCoderPropID::kAlgorithm,
- NCoderPropID::kDictionarySize,
- NCoderPropID::kNumFastBytes
- };
- const int kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]);
- PROPVARIANT props[kNumProps];
- // NCoderPropID::kAlgorithm
- props[0].vt = VT_UI4;
- props[0].ulVal = 2;
- // NCoderPropID::kDictionarySize
- props[1].vt = VT_UI4;
- props[1].ulVal = dicSize;
- // NCoderPropID::kNumFastBytes
- props[2].vt = VT_UI4;
- props[2].ulVal = 64;
- if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0)
- return LZMA_INIT_ERROR;
- return _encoder->SetStreams(this, this, 0, 0) == S_OK ? C_OK : LZMA_INIT_ERROR;
-}
-
-int CLZMA::End()
-{
- // has compressor not finished?
- if (hCompressionThread && !compressor_finished)
- {
- // kill compression thread
- avail_in = 0;
- avail_out = 0;
- compressor_finished = TRUE;
-
- SetEvent(hIOReadyEvent);
-#ifdef _WIN32
- WaitForSingleObject(hCompressionThread, INFINITE);
-#else
- pthread_join(hCompressionThread, NULL);
-#endif
- }
- if (hCompressionThread)
- {
-#ifdef _WIN32
- CloseHandle(hCompressionThread);
- hCompressionThread = NULL;
-#else
- pthread_detach(hCompressionThread);
- hCompressionThread = 0;
-#endif
- }
- SetNextOut(NULL, 0);
- SetNextIn(NULL, 0);
- return C_OK;
-}
-
-int CLZMA::CompressReal()
-{
- try
- {
- HRESULT hResult = _encoder->WriteCoderProperties(this);
- if (hResult == S_OK)
- {
- while (true)
- {
- UINT64 inSize, outSize;
- INT32 finished;
- hResult = _encoder->CodeOneBlock(&inSize, &outSize, &finished);
- if (hResult != S_OK && res == C_OK)
- res = ConvertError(hResult);
- if (res != C_OK)
- break;
- if (finished)
- {
- res = C_FINISHED;
- break;
- }
- }
- }
- else
- {
- if (res == C_OK)
- res = ConvertError(hResult);
- }
- }
- catch (...)
- {
- if (res == C_OK)
- res = LZMA_IO_ERROR;
- }
-
- compressor_finished = TRUE;
- SetEvent(hNeedIOEvent);
- return C_OK;
-}
-
-int CLZMA::Compress(bool flush)
-{
- if (compressor_finished)
- {
- // act like zlib when it comes to stream ending
- if (flush)
- return C_OK;
- else
- return LZMA_BAD_CALL;
- }
-
- finish = flush;
-
- if (!hCompressionThread)
- {
-#ifdef _WIN32
- DWORD dwThreadId;
-
- hCompressionThread = CreateThread(0, 0, lzmaCompressThread, (LPVOID) this, 0, &dwThreadId);
- if (!hCompressionThread)
-#else
- if (pthread_create(&hCompressionThread, NULL, lzmaCompressThread, (LPVOID) this))
-#endif
- return LZMA_INIT_ERROR;
- }
- else
- {
- SetEvent(hIOReadyEvent);
- }
-
- HANDLE waitList[2] = {hNeedIOEvent, (HANDLE) hCompressionThread};
- if (WaitForMultipleObjects(2, waitList, FALSE, INFINITE) != WAIT_OBJECT_0)
- {
- // thread ended or WaitForMultipleObjects failed
- compressor_finished = TRUE;
- SetEvent(hIOReadyEvent);
- return LZMA_THREAD_ERROR;
- }
-
- if (compressor_finished)
- {
- return res;
- }
-
- return C_OK;
-}
-
-void CLZMA::GetMoreIO()
-{
- SetEvent(hNeedIOEvent);
- if (WaitForSingleObject(hIOReadyEvent, INFINITE) != WAIT_OBJECT_0)
- {
- compressor_finished = TRUE;
- res = LZMA_THREAD_ERROR;
- }
-}
-
-HRESULT CLZMA::Read(void *data, UINT32 size, UINT32 *processedSize)
-{
- return ReadPart(data, size, processedSize);
-}
-
-HRESULT CLZMA::ReadPart(void *data, UINT32 size, UINT32 *processedSize)
-{
- if (processedSize)
- *processedSize = 0;
- while (size)
- {
- if (!avail_in)
- {
- if (finish)
- {
- return S_OK;
- }
- GetMoreIO();
- if (!avail_in)
- {
- if (finish)
- {
- return S_OK;
- }
- return E_ABORT;
- }
- if (compressor_finished)
- return E_ABORT;
- }
- UINT32 l = min(size, avail_in);
- memcpy(data, next_in, l);
- avail_in -= l;
- size -= l;
- next_in += l;
- data = LPBYTE(data) + l;
- if (processedSize)
- *processedSize += l;
- }
- return S_OK;
-}
-
-HRESULT CLZMA::Write(const void *data, UINT32 size, UINT32 *processedSize)
-{
- return WritePart(data, size, processedSize);
-}
-
-HRESULT CLZMA::WritePart(const void *data, UINT32 size, UINT32 *processedSize)
-{
- if (processedSize)
- *processedSize = 0;
- while (size)
- {
- if (!avail_out)
- {
- GetMoreIO();
- if (!avail_out)
- return E_ABORT;
- }
- UINT32 l = min(size, avail_out);
- memcpy(next_out, data, l);
- avail_out -= l;
- size -= l;
- next_out += l;
- data = LPBYTE(data) + l;
- if (processedSize)
- *processedSize += l;
- }
- return S_OK;
-}
-
-void CLZMA::SetNextIn(char *in, unsigned int size)
-{
- next_in = (LPBYTE) in;
- avail_in = size;
-}
-
-void CLZMA::SetNextOut(char *out, unsigned int size)
-{
- next_out = (LPBYTE) out;
- avail_out = size;
-}
-
-char* CLZMA::GetNextOut()
-{
- return (char *) next_out;
-}
-
-unsigned int CLZMA::GetAvailIn()
-{
- return avail_in;
-}
-
-unsigned int CLZMA::GetAvailOut()
-{
- return avail_out;
-}
-
-const char* CLZMA::GetName()
-{
- return "lzma";
-}
-
-const char* CLZMA::GetErrStr(int err)
-{
- switch (err)
- {
- case LZMA_BAD_CALL:
- return "bad call";
- case LZMA_INIT_ERROR:
- return "initialization failed";
- case LZMA_THREAD_ERROR:
- return "thread synchronization error";
- case LZMA_IO_ERROR:
- return "input/output error";
- case LZMA_MEM_ERROR:
- return "not enough memory";
- default:
- return "unknown error";
- }
-}
+/* + * clzma.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include <algorithm> // for std::min +#include "clzma.h" + +using namespace std; + +#ifndef _WIN32 +struct evnet_t +{ + pthread_cond_t cond; + pthread_mutex_t mutex; + bool signaled; +}; + +HANDLE CreateEvent(void *, BOOL, BOOL, char *) +{ + evnet_t *event = (evnet_t *) malloc(sizeof(evnet_t)); + if (!event) + return 0; + if (pthread_cond_init(&event->cond, NULL)) + { + free(event); + return 0; + } + if (pthread_mutex_init(&event->mutex, NULL)) + { + pthread_cond_destroy(&event->cond); + free(event); + return 0; + } + event->signaled = false; + return (HANDLE) event; +} + +BOOL SetEvent(HANDLE _event) +{ + evnet_t *event = (evnet_t *) _event; + if (pthread_mutex_lock(&event->mutex)) + return FALSE; + event->signaled = true; + pthread_cond_signal(&event->cond); + if (pthread_mutex_unlock(&event->mutex)) + return FALSE; + return TRUE; +} + +BOOL ResetEvent(HANDLE _event) +{ + evnet_t *event = (evnet_t *) _event; + if (pthread_mutex_lock(&event->mutex)) + return FALSE; + event->signaled = false; + if (pthread_mutex_unlock(&event->mutex)) + return FALSE; + return TRUE; +} + +BOOL CloseHandle(HANDLE _event) +{ + BOOL ret = TRUE; + evnet_t *event = (evnet_t *) _event; + if (!event) + return FALSE; + if (pthread_cond_destroy(&event->cond)) + ret = FALSE; + if (pthread_mutex_destroy(&event->mutex)) + ret = FALSE; + free(event); + return ret; +} + +#define WAIT_OBJECT_0 0 +#define INFINITE 0 +DWORD WaitForSingleObject(HANDLE _event, DWORD) { + DWORD ret = WAIT_OBJECT_0; + evnet_t *event = (evnet_t *) _event; + if (pthread_mutex_lock(&event->mutex)) + return !WAIT_OBJECT_0; + if (!event->signaled) + { + if (pthread_cond_wait(&event->cond, &event->mutex)) + { + ret = !WAIT_OBJECT_0; + } + } + event->signaled = false; + pthread_mutex_unlock(&event->mutex); + return ret; +} + +#define WaitForMultipleObjects(x, list, y, t) WaitForSingleObject(list[0], t) + +#endif + +#ifdef _WIN32 +DWORD CLZMA::lzmaCompressThread(LPVOID lpParameter) +#else +void* CLZMA::lzmaCompressThread(void *lpParameter) +#endif +{ + CLZMA *Compressor = (CLZMA *) lpParameter; + if (!Compressor) + return 0; + + Compressor->CompressReal(); + return 0; +} + +int CLZMA::ConvertError(HRESULT result) +{ + if (result != S_OK) + { + if (result == E_OUTOFMEMORY) + return LZMA_MEM_ERROR; + else + return LZMA_IO_ERROR; + } + return C_OK; +} + +CLZMA::CLZMA(): _encoder(NULL) +{ + _encoder = new NCompress::NLZMA::CEncoder(); + _encoder->SetWriteEndMarkerMode(true); +#ifdef _WIN32 + hCompressionThread = NULL; +#else + hCompressionThread = 0; +#endif + hNeedIOEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + hIOReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + finish = FALSE; + compressor_finished = TRUE; + hCompressionThread = 0; + SetNextOut(NULL, 0); + SetNextIn(NULL, 0); + + AddRef(); // will be manually deleted, not released +} + +CLZMA::~CLZMA() +{ + End(); + if (hNeedIOEvent) + { + CloseHandle(hNeedIOEvent); + hNeedIOEvent = NULL; + } + if (hIOReadyEvent) + { + CloseHandle(hIOReadyEvent); + hIOReadyEvent = NULL; + } + if (_encoder) + { + delete _encoder; + _encoder = NULL; + } +} + +int CLZMA::Init(int level, unsigned int dicSize) +{ + End(); + + compressor_finished = FALSE; + finish = FALSE; + res = C_OK; + + if (!hNeedIOEvent || !hIOReadyEvent) + { + return LZMA_INIT_ERROR; + } + + ResetEvent(hNeedIOEvent); + ResetEvent(hIOReadyEvent); + + res = C_OK; + + PROPID propdIDs [] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kDictionarySize, + NCoderPropID::kNumFastBytes + }; + const int kNumProps = sizeof(propdIDs) / sizeof(propdIDs[0]); + PROPVARIANT props[kNumProps]; + // NCoderPropID::kAlgorithm + props[0].vt = VT_UI4; + props[0].ulVal = 2; + // NCoderPropID::kDictionarySize + props[1].vt = VT_UI4; + props[1].ulVal = dicSize; + // NCoderPropID::kNumFastBytes + props[2].vt = VT_UI4; + props[2].ulVal = 64; + if (_encoder->SetCoderProperties(propdIDs, props, kNumProps) != 0) + return LZMA_INIT_ERROR; + return _encoder->SetStreams(this, this, 0, 0) == S_OK ? C_OK : LZMA_INIT_ERROR; +} + +int CLZMA::End() +{ + // has compressor not finished? + if (hCompressionThread && !compressor_finished) + { + // kill compression thread + avail_in = 0; + avail_out = 0; + compressor_finished = TRUE; + + SetEvent(hIOReadyEvent); +#ifdef _WIN32 + WaitForSingleObject(hCompressionThread, INFINITE); +#else + pthread_join(hCompressionThread, NULL); +#endif + } + if (hCompressionThread) + { +#ifdef _WIN32 + CloseHandle(hCompressionThread); + hCompressionThread = NULL; +#else + pthread_detach(hCompressionThread); + hCompressionThread = 0; +#endif + } + SetNextOut(NULL, 0); + SetNextIn(NULL, 0); + return C_OK; +} + +int CLZMA::CompressReal() +{ + try + { + HRESULT hResult = _encoder->WriteCoderProperties(this); + if (hResult == S_OK) + { + while (true) + { + UINT64 inSize, outSize; + INT32 finished; + hResult = _encoder->CodeOneBlock(&inSize, &outSize, &finished); + if (hResult != S_OK && res == C_OK) + res = ConvertError(hResult); + if (res != C_OK) + break; + if (finished) + { + res = C_FINISHED; + break; + } + } + } + else + { + if (res == C_OK) + res = ConvertError(hResult); + } + } + catch (...) + { + if (res == C_OK) + res = LZMA_IO_ERROR; + } + + compressor_finished = TRUE; + SetEvent(hNeedIOEvent); + return C_OK; +} + +int CLZMA::Compress(bool flush) +{ + if (compressor_finished) + { + // act like zlib when it comes to stream ending + if (flush) + return C_OK; + else + return LZMA_BAD_CALL; + } + + finish = flush; + + if (!hCompressionThread) + { +#ifdef _WIN32 + DWORD dwThreadId; + + hCompressionThread = CreateThread(0, 0, lzmaCompressThread, (LPVOID) this, 0, &dwThreadId); + if (!hCompressionThread) +#else + if (pthread_create(&hCompressionThread, NULL, lzmaCompressThread, (LPVOID) this)) +#endif + return LZMA_INIT_ERROR; + } + else + { + SetEvent(hIOReadyEvent); + } + + HANDLE waitList[2] = {hNeedIOEvent, (HANDLE) hCompressionThread}; + if (WaitForMultipleObjects(2, waitList, FALSE, INFINITE) != WAIT_OBJECT_0) + { + // thread ended or WaitForMultipleObjects failed + compressor_finished = TRUE; + SetEvent(hIOReadyEvent); + return LZMA_THREAD_ERROR; + } + + if (compressor_finished) + { + return res; + } + + return C_OK; +} + +void CLZMA::GetMoreIO() +{ + SetEvent(hNeedIOEvent); + if (WaitForSingleObject(hIOReadyEvent, INFINITE) != WAIT_OBJECT_0) + { + compressor_finished = TRUE; + res = LZMA_THREAD_ERROR; + } +} + +HRESULT CLZMA::Read(void *data, UINT32 size, UINT32 *processedSize) +{ + return ReadPart(data, size, processedSize); +} + +HRESULT CLZMA::ReadPart(void *data, UINT32 size, UINT32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + while (size) + { + if (!avail_in) + { + if (finish) + { + return S_OK; + } + GetMoreIO(); + if (!avail_in) + { + if (finish) + { + return S_OK; + } + return E_ABORT; + } + if (compressor_finished) + return E_ABORT; + } + UINT32 l = min(size, avail_in); + memcpy(data, next_in, l); + avail_in -= l; + size -= l; + next_in += l; + data = LPBYTE(data) + l; + if (processedSize) + *processedSize += l; + } + return S_OK; +} + +HRESULT CLZMA::Write(const void *data, UINT32 size, UINT32 *processedSize) +{ + return WritePart(data, size, processedSize); +} + +HRESULT CLZMA::WritePart(const void *data, UINT32 size, UINT32 *processedSize) +{ + if (processedSize) + *processedSize = 0; + while (size) + { + if (!avail_out) + { + GetMoreIO(); + if (!avail_out) + return E_ABORT; + } + UINT32 l = min(size, avail_out); + memcpy(next_out, data, l); + avail_out -= l; + size -= l; + next_out += l; + data = LPBYTE(data) + l; + if (processedSize) + *processedSize += l; + } + return S_OK; +} + +void CLZMA::SetNextIn(char *in, unsigned int size) +{ + next_in = (LPBYTE) in; + avail_in = size; +} + +void CLZMA::SetNextOut(char *out, unsigned int size) +{ + next_out = (LPBYTE) out; + avail_out = size; +} + +char* CLZMA::GetNextOut() +{ + return (char *) next_out; +} + +unsigned int CLZMA::GetAvailIn() +{ + return avail_in; +} + +unsigned int CLZMA::GetAvailOut() +{ + return avail_out; +} + +const char* CLZMA::GetName() +{ + return "lzma"; +} + +const char* CLZMA::GetErrStr(int err) +{ + switch (err) + { + case LZMA_BAD_CALL: + return "bad call"; + case LZMA_INIT_ERROR: + return "initialization failed"; + case LZMA_THREAD_ERROR: + return "thread synchronization error"; + case LZMA_IO_ERROR: + return "input/output error"; + case LZMA_MEM_ERROR: + return "not enough memory"; + default: + return "unknown error"; + } +} diff --git a/Source/clzma.h b/Source/clzma.h index 677cf78..ac90339 100755 --- a/Source/clzma.h +++ b/Source/clzma.h @@ -1,103 +1,103 @@ -/*
- * clzma.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __CLZMA_H__
-#define __CLZMA_H__
-
-#include "Platform.h"
-
-#ifndef _WIN32
-# include <pthread.h>
-#endif
-
-#include "compressor.h"
-#include "7zip/7zip/IStream.h"
-#include "7zip/7zip/Compress/LZMA/LZMAEncoder.h"
-#include "7zip/Common/MyCom.h"
-#include "7zip/Common/Defs.h"
-
-#define LZMA_BAD_CALL -1
-#define LZMA_INIT_ERROR -2
-#define LZMA_THREAD_ERROR -3
-#define LZMA_IO_ERROR -4
-#define LZMA_MEM_ERROR -5
-
-class CLZMA:
- public ICompressor,
- public ISequentialInStream,
- public ISequentialOutStream,
- public CMyUnknownImp
-{
-private:
- NCompress::NLZMA::CEncoder *_encoder;
-
-#ifdef _WIN32
- HANDLE hCompressionThread;
-#else
- pthread_t hCompressionThread;
-#endif
- HANDLE hNeedIOEvent;
- HANDLE hIOReadyEvent;
-
- BYTE *next_in; /* next input byte */
- UINT avail_in; /* number of bytes available at next_in */
-
- BYTE *next_out; /* next output byte should be put there */
- UINT avail_out; /* remaining free space at next_out */
-
- int res;
-
- BOOL finish;
- BOOL compressor_finished;
-
- int ConvertError(HRESULT result);
-
- void GetMoreIO();
- int CompressReal();
-
-#ifdef _WIN32
- static DWORD WINAPI lzmaCompressThread(LPVOID lpParameter);
-#else
- static void* lzmaCompressThread(void *lpParameter);
-#endif
-
-public:
- MY_UNKNOWN_IMP
-
- CLZMA();
- virtual ~CLZMA();
-
- virtual int Init(int level, unsigned int dicSize);
- virtual int End();
- virtual int Compress(bool flush);
-
- STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize);
- STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize);
- STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
- STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
-
- virtual void SetNextIn(char *in, unsigned int size);
- virtual void SetNextOut(char *out, unsigned int size);
-
- virtual char *GetNextOut();
- virtual unsigned int GetAvailIn();
- virtual unsigned int GetAvailOut();
- virtual const char *GetName();
-
- virtual const char* GetErrStr(int err);
-};
-
-#endif
+/* + * clzma.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __CLZMA_H__ +#define __CLZMA_H__ + +#include "Platform.h" + +#ifndef _WIN32 +# include <pthread.h> +#endif + +#include "compressor.h" +#include "7zip/7zip/IStream.h" +#include "7zip/7zip/Compress/LZMA/LZMAEncoder.h" +#include "7zip/Common/MyCom.h" +#include "7zip/Common/Defs.h" + +#define LZMA_BAD_CALL -1 +#define LZMA_INIT_ERROR -2 +#define LZMA_THREAD_ERROR -3 +#define LZMA_IO_ERROR -4 +#define LZMA_MEM_ERROR -5 + +class CLZMA: + public ICompressor, + public ISequentialInStream, + public ISequentialOutStream, + public CMyUnknownImp +{ +private: + NCompress::NLZMA::CEncoder *_encoder; + +#ifdef _WIN32 + HANDLE hCompressionThread; +#else + pthread_t hCompressionThread; +#endif + HANDLE hNeedIOEvent; + HANDLE hIOReadyEvent; + + BYTE *next_in; /* next input byte */ + UINT avail_in; /* number of bytes available at next_in */ + + BYTE *next_out; /* next output byte should be put there */ + UINT avail_out; /* remaining free space at next_out */ + + int res; + + BOOL finish; + BOOL compressor_finished; + + int ConvertError(HRESULT result); + + void GetMoreIO(); + int CompressReal(); + +#ifdef _WIN32 + static DWORD WINAPI lzmaCompressThread(LPVOID lpParameter); +#else + static void* lzmaCompressThread(void *lpParameter); +#endif + +public: + MY_UNKNOWN_IMP + + CLZMA(); + virtual ~CLZMA(); + + virtual int Init(int level, unsigned int dicSize); + virtual int End(); + virtual int Compress(bool flush); + + STDMETHOD(Read)(void *data, UINT32 size, UINT32 *processedSize); + STDMETHOD(ReadPart)(void *data, UINT32 size, UINT32 *processedSize); + STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize); + STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize); + + virtual void SetNextIn(char *in, unsigned int size); + virtual void SetNextOut(char *out, unsigned int size); + + virtual char *GetNextOut(); + virtual unsigned int GetAvailIn(); + virtual unsigned int GetAvailOut(); + virtual const char *GetName(); + + virtual const char* GetErrStr(int err); +}; + +#endif diff --git a/Source/compressor.h b/Source/compressor.h index aae7569..49524a0 100755 --- a/Source/compressor.h +++ b/Source/compressor.h @@ -1,46 +1,46 @@ -/*
- * compressor.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __COMPRESSOR_H__
-#define __COMPRESSOR_H__
-
-#define C_OK 0
-#define C_FINISHED 1
-
-#define C_FINISH true
-
-class ICompressor {
- public:
- virtual ~ICompressor() {}
-
- virtual int Init(int level, unsigned int dict_size) = 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;
-
- virtual const char* GetName() = 0;
-
- virtual const char* GetErrStr(int err) = 0;
-};
-
-#endif
+/* + * compressor.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __COMPRESSOR_H__ +#define __COMPRESSOR_H__ + +#define C_OK 0 +#define C_FINISHED 1 + +#define C_FINISH true + +class ICompressor { + public: + virtual ~ICompressor() {} + + virtual int Init(int level, unsigned int dict_size) = 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; + + virtual const char* GetName() = 0; + + virtual const char* GetErrStr(int err) = 0; +}; + +#endif diff --git a/Source/crc32.c b/Source/crc32.c index eb3a988..e8fabf9 100755 --- a/Source/crc32.c +++ b/Source/crc32.c @@ -1,47 +1,47 @@ -/*
- * crc32.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include "crc32.h"
-#include "exehead/config.h"
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-
-// this is based on the (slow,small) CRC32 implementation from zlib.
-crc32_t NSISCALL CRC32(crc32_t crc, const unsigned char *buf, unsigned int len)
-{
- static crc32_t crc_table[256];
-
- if (!crc_table[1])
- {
- crc32_t c;
- int n, k;
-
- for (n = 0; n < 256; n++)
- {
- c = (crc32_t)n;
- for (k = 0; k < 8; k++) c = (c >> 1) ^ (c & 1 ? 0xedb88320L : 0);
- crc_table[n] = c;
- }
- }
-
- crc = crc ^ 0xffffffffL;
- while (len-- > 0) {
- crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
- }
- return crc ^ 0xffffffffL;
-}
-
-#endif
+/* + * crc32.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include "crc32.h" +#include "exehead/config.h" +#ifdef NSIS_CONFIG_CRC_SUPPORT + +// this is based on the (slow,small) CRC32 implementation from zlib. +crc32_t NSISCALL CRC32(crc32_t crc, const unsigned char *buf, unsigned int len) +{ + static crc32_t crc_table[256]; + + if (!crc_table[1]) + { + crc32_t c; + int n, k; + + for (n = 0; n < 256; n++) + { + c = (crc32_t)n; + for (k = 0; k < 8; k++) c = (c >> 1) ^ (c & 1 ? 0xedb88320L : 0); + crc_table[n] = c; + } + } + + crc = crc ^ 0xffffffffL; + while (len-- > 0) { + crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8); + } + return crc ^ 0xffffffffL; +} + +#endif diff --git a/Source/crc32.h b/Source/crc32.h index 8245b6f..92fb7c9 100755 --- a/Source/crc32.h +++ b/Source/crc32.h @@ -1,29 +1,29 @@ -/*
- * crc32.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-
-#ifndef ___CRC32__H___
-#define ___CRC32__H___
-
-typedef UINT32 crc32_t;
-
-#ifdef __cplusplus
-extern "C"
-#endif
-crc32_t NSISCALL CRC32(crc32_t crc, const unsigned char *buf, unsigned int len);
-
-#endif//!___CRC32__H___
+/* + * crc32.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" + +#ifndef ___CRC32__H___ +#define ___CRC32__H___ + +typedef UINT32 crc32_t; + +#ifdef __cplusplus +extern "C" +#endif +crc32_t NSISCALL CRC32(crc32_t crc, const unsigned char *buf, unsigned int len); + +#endif//!___CRC32__H___ diff --git a/Source/czlib.h b/Source/czlib.h index 7d1b3e9..c929dea 100755 --- a/Source/czlib.h +++ b/Source/czlib.h @@ -1,91 +1,91 @@ -/*
- * czlib.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __CZLIB_H__
-#define __CZLIB_H__
-
-#include "compressor.h"
-#include "zlib/ZLIB.H"
-
-class CZlib : public ICompressor {
- public:
- virtual ~CZlib() {}
-
- int Init(int level, unsigned int dict_size) {
- 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;
- }
-
- const char* GetName() {
- return "zlib";
- }
-
- const char* GetErrStr(int err) {
- switch (err)
- {
- case Z_STREAM_ERROR:
- return "invalid stream - bad call";
- case Z_DATA_ERROR:
- return "data error";
- case Z_MEM_ERROR:
- return "not enough memory";
- case Z_BUF_ERROR:
- return "buffer error - bad call";
- case Z_VERSION_ERROR:
- return "version error";
- default:
- return "unknown error";
- }
- }
-
- private:
- z_stream *stream;
-};
-
-#endif
+/* + * czlib.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __CZLIB_H__ +#define __CZLIB_H__ + +#include "compressor.h" +#include "zlib/ZLIB.H" + +class CZlib : public ICompressor { + public: + virtual ~CZlib() {} + + int Init(int level, unsigned int dict_size) { + 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; + } + + const char* GetName() { + return "zlib"; + } + + const char* GetErrStr(int err) { + switch (err) + { + case Z_STREAM_ERROR: + return "invalid stream - bad call"; + case Z_DATA_ERROR: + return "data error"; + case Z_MEM_ERROR: + return "not enough memory"; + case Z_BUF_ERROR: + return "buffer error - bad call"; + case Z_VERSION_ERROR: + return "version error"; + default: + return "unknown error"; + } + } + + private: + z_stream *stream; +}; + +#endif diff --git a/Source/dirreader.cpp b/Source/dirreader.cpp index f6b9052..5dd0616 100755 --- a/Source/dirreader.cpp +++ b/Source/dirreader.cpp @@ -1,244 +1,244 @@ -/*
- * dirreader.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include "dirreader.h"
-#include <string>
-#include <set>
-
-#include <string.h> // for stricmp()
-#include <ctype.h> // for tolower()
-
-using namespace std;
-
-dir_reader::dir_reader() {
- exclude(".");
- exclude("..");
-}
-
-const set<string>& dir_reader::files() {
- return m_files;
-}
-
-const set<string>& dir_reader::dirs() {
- return m_dirs;
-}
-
-void dir_reader::exclude(const string& spec) {
- if (spec.find_first_of("?*") != string::npos) {
- m_wildcard_excluded.insert(spec);
- } else {
- m_excluded.insert(spec);
- }
-}
-
-void dir_reader::exclude(const set<string>& specs) {
- iterator i = specs.begin();
- iterator e = specs.end();
-
- for (; i != e; i++) {
- exclude(*i);
- }
-}
-
-bool dir_reader::matches(const string& name, const string& spec) {
- string::const_iterator name_itr = name.begin();
- string::const_iterator name_end = name.end();
-
- string::const_iterator spec_itr = spec.begin();
- string::const_iterator spec_end = spec.end();
-
- string::const_iterator last_good_spec = spec_end;
- string::const_iterator last_good_name = name_end;
-
- while (name_itr != name_end && spec_itr != spec_end) {
- switch (*spec_itr) {
- case '?':
- // question mark mathes one char
- name_itr++;
- spec_itr++;
- break;
-
- case '*':
- // double asterisk is the same as a single asterisk
- while (*spec_itr == '*') {
- spec_itr++;
- // asterisk at the end of the spec matches the end of the name
- if (spec_itr == spec_end)
- return true;
- }
-
- // remember last good name and spec for prematurely stopped asterisk
- last_good_spec = spec_itr;
- last_good_name = name_itr;
-
- break;
-
- default:
- if (::tolower(*name_itr) != ::tolower(*spec_itr)) {
- if (last_good_spec != spec_end) {
- // matched wrong part of the name, try again
- spec_itr = last_good_spec;
- name_itr = ++last_good_name;
- } else {
- // no match and no asterisk to use
- return false;
- }
- } else {
- // remember last good name for prematurely stopped asterisk
- last_good_name = name_itr;
-
- spec_itr++;
- name_itr++;
-
- if (spec_itr == spec_end && name_itr != name_end && last_good_spec != spec_end) {
- // asterisk hasn't matched enough, keep matching
- spec_itr = last_good_spec;
- }
- }
- break;
- }
- }
-
- // skip any redundant asterisks and periods at the end of the name
- while (spec_itr != spec_end) {
- if (*spec_itr != '.' && *spec_itr != '*') {
- break;
- }
- spec_itr++;
- }
-
- // return true only if managed to match everything
- return name_itr == name_end && spec_itr == spec_end;
-}
-
-void dir_reader::add_file(const string& file) {
- if (!is_excluded(file)) {
- m_files.insert(file);
- }
-}
-
-void dir_reader::add_dir(const string& dir) {
- if (!is_excluded(dir)) {
- m_dirs.insert(dir);
- }
-}
-
-bool dir_reader::is_excluded(const string& name) const {
- iterator i = m_excluded.begin();
- iterator e = m_excluded.end();
-
- for (; i != e; i++) {
- if (!::stricmp(name.c_str(), i->c_str())) {
- return true;
- }
- }
-
- i = m_wildcard_excluded.begin();
- e = m_wildcard_excluded.end();
-
- for (; i != e; i++) {
- if (matches(name, *i)) {
- return true;
- }
- }
-
- return false;
-}
-
-#ifdef _WIN32
-
-class win32_dir_reader : public dir_reader {
-public:
-
- virtual void read(const string& dir) {
- WIN32_FIND_DATA fd;
-
- string spec = dir + PLATFORM_PATH_SEPARATOR_STR + "*.*";
-
- HANDLE h = ::FindFirstFile(spec.c_str(), &fd);
- if (h != INVALID_HANDLE_VALUE) {
- do {
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- dir_reader::add_dir(fd.cFileName);
- } else {
- dir_reader::add_file(fd.cFileName);
- }
- } while (::FindNextFile(h, &fd));
- ::FindClose(h);
- }
- }
-
-};
-
-#else
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-
-class posix_dir_reader : public dir_reader {
-public:
-
- virtual void read(const string& dir) {
- //convert(dir);
-
- DIR *dip = ::opendir(dir.c_str());
- if (dip) {
- dirent *dit;
- while ((dit = ::readdir(dip))) {
- struct stat st;
- string file = dir + PLATFORM_PATH_SEPARATOR_STR + dit->d_name;
-
- if (!stat(file.c_str(), &st)) {
- if (S_ISDIR(st.st_mode)) {
- dir_reader::add_dir(dit->d_name);
- } else {
- dir_reader::add_file(dit->d_name);
- }
- }
- }
- ::closedir(dip);
- }
- }
-
-private:
-
- void convert(string& path) {
- string::size_type pos = path.find('\\');
- while (pos != string::npos) {
- path[pos] = '/';
- pos = path.find('\\');
- }
-
- /* Replace drive letter X: by /x */
- if (path[1] == ':') {
- path[1] = ::tolower(path[0]);
- path[0] = '/';
- }
- }
-
-};
-
-#endif
-
-dir_reader* new_dir_reader() {
-#ifdef _WIN32
- return new win32_dir_reader();
-#else
- return new posix_dir_reader();
-#endif
-}
+/* + * dirreader.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include "dirreader.h" +#include <string> +#include <set> + +#include <string.h> // for stricmp() +#include <ctype.h> // for tolower() + +using namespace std; + +dir_reader::dir_reader() { + exclude("."); + exclude(".."); +} + +const set<string>& dir_reader::files() { + return m_files; +} + +const set<string>& dir_reader::dirs() { + return m_dirs; +} + +void dir_reader::exclude(const string& spec) { + if (spec.find_first_of("?*") != string::npos) { + m_wildcard_excluded.insert(spec); + } else { + m_excluded.insert(spec); + } +} + +void dir_reader::exclude(const set<string>& specs) { + iterator i = specs.begin(); + iterator e = specs.end(); + + for (; i != e; i++) { + exclude(*i); + } +} + +bool dir_reader::matches(const string& name, const string& spec) { + string::const_iterator name_itr = name.begin(); + string::const_iterator name_end = name.end(); + + string::const_iterator spec_itr = spec.begin(); + string::const_iterator spec_end = spec.end(); + + string::const_iterator last_good_spec = spec_end; + string::const_iterator last_good_name = name_end; + + while (name_itr != name_end && spec_itr != spec_end) { + switch (*spec_itr) { + case '?': + // question mark mathes one char + name_itr++; + spec_itr++; + break; + + case '*': + // double asterisk is the same as a single asterisk + while (*spec_itr == '*') { + spec_itr++; + // asterisk at the end of the spec matches the end of the name + if (spec_itr == spec_end) + return true; + } + + // remember last good name and spec for prematurely stopped asterisk + last_good_spec = spec_itr; + last_good_name = name_itr; + + break; + + default: + if (::tolower(*name_itr) != ::tolower(*spec_itr)) { + if (last_good_spec != spec_end) { + // matched wrong part of the name, try again + spec_itr = last_good_spec; + name_itr = ++last_good_name; + } else { + // no match and no asterisk to use + return false; + } + } else { + // remember last good name for prematurely stopped asterisk + last_good_name = name_itr; + + spec_itr++; + name_itr++; + + if (spec_itr == spec_end && name_itr != name_end && last_good_spec != spec_end) { + // asterisk hasn't matched enough, keep matching + spec_itr = last_good_spec; + } + } + break; + } + } + + // skip any redundant asterisks and periods at the end of the name + while (spec_itr != spec_end) { + if (*spec_itr != '.' && *spec_itr != '*') { + break; + } + spec_itr++; + } + + // return true only if managed to match everything + return name_itr == name_end && spec_itr == spec_end; +} + +void dir_reader::add_file(const string& file) { + if (!is_excluded(file)) { + m_files.insert(file); + } +} + +void dir_reader::add_dir(const string& dir) { + if (!is_excluded(dir)) { + m_dirs.insert(dir); + } +} + +bool dir_reader::is_excluded(const string& name) const { + iterator i = m_excluded.begin(); + iterator e = m_excluded.end(); + + for (; i != e; i++) { + if (!::stricmp(name.c_str(), i->c_str())) { + return true; + } + } + + i = m_wildcard_excluded.begin(); + e = m_wildcard_excluded.end(); + + for (; i != e; i++) { + if (matches(name, *i)) { + return true; + } + } + + return false; +} + +#ifdef _WIN32 + +class win32_dir_reader : public dir_reader { +public: + + virtual void read(const string& dir) { + WIN32_FIND_DATA fd; + + string spec = dir + PLATFORM_PATH_SEPARATOR_STR + "*.*"; + + HANDLE h = ::FindFirstFile(spec.c_str(), &fd); + if (h != INVALID_HANDLE_VALUE) { + do { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + dir_reader::add_dir(fd.cFileName); + } else { + dir_reader::add_file(fd.cFileName); + } + } while (::FindNextFile(h, &fd)); + ::FindClose(h); + } + } + +}; + +#else + +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> + +class posix_dir_reader : public dir_reader { +public: + + virtual void read(const string& dir) { + //convert(dir); + + DIR *dip = ::opendir(dir.c_str()); + if (dip) { + dirent *dit; + while ((dit = ::readdir(dip))) { + struct stat st; + string file = dir + PLATFORM_PATH_SEPARATOR_STR + dit->d_name; + + if (!stat(file.c_str(), &st)) { + if (S_ISDIR(st.st_mode)) { + dir_reader::add_dir(dit->d_name); + } else { + dir_reader::add_file(dit->d_name); + } + } + } + ::closedir(dip); + } + } + +private: + + void convert(string& path) { + string::size_type pos = path.find('\\'); + while (pos != string::npos) { + path[pos] = '/'; + pos = path.find('\\'); + } + + /* Replace drive letter X: by /x */ + if (path[1] == ':') { + path[1] = ::tolower(path[0]); + path[0] = '/'; + } + } + +}; + +#endif + +dir_reader* new_dir_reader() { +#ifdef _WIN32 + return new win32_dir_reader(); +#else + return new posix_dir_reader(); +#endif +} diff --git a/Source/dirreader.h b/Source/dirreader.h index c0bcbb4..d7426a8 100755 --- a/Source/dirreader.h +++ b/Source/dirreader.h @@ -1,56 +1,56 @@ -/*
- * dirreader.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <string>
-#include <set>
-
-class dir_reader {
-public:
-
- typedef std::set<std::string>::const_iterator iterator;
-
- dir_reader();
- virtual ~dir_reader() {}
-
- virtual void read(const std::string& dir) = 0;
-
- virtual const std::set<std::string>& files();
- virtual const std::set<std::string>& dirs();
-
- virtual void exclude(const std::string& spec);
- virtual void exclude(const std::set<std::string>& specs);
-
- static bool matches(const std::string& name, const std::string& spec);
-
-protected:
-
- virtual void add_file(const std::string& file);
- virtual void add_dir(const std::string& dir);
-
- virtual bool is_excluded(const std::string& name) const;
-
-private:
-
- std::set<std::string> m_excluded;
- std::set<std::string> m_wildcard_excluded;
-
- std::set<std::string> m_files;
- std::set<std::string> m_dirs;
-
-};
-
-dir_reader* new_dir_reader();
+/* + * dirreader.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <string> +#include <set> + +class dir_reader { +public: + + typedef std::set<std::string>::const_iterator iterator; + + dir_reader(); + virtual ~dir_reader() {} + + virtual void read(const std::string& dir) = 0; + + virtual const std::set<std::string>& files(); + virtual const std::set<std::string>& dirs(); + + virtual void exclude(const std::string& spec); + virtual void exclude(const std::set<std::string>& specs); + + static bool matches(const std::string& name, const std::string& spec); + +protected: + + virtual void add_file(const std::string& file); + virtual void add_dir(const std::string& dir); + + virtual bool is_excluded(const std::string& name) const; + +private: + + std::set<std::string> m_excluded; + std::set<std::string> m_wildcard_excluded; + + std::set<std::string> m_files; + std::set<std::string> m_dirs; + +}; + +dir_reader* new_dir_reader(); diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c index 26cdd4f..5c91796 100755 --- a/Source/exehead/Main.c +++ b/Source/exehead/Main.c @@ -1,348 +1,348 @@ -/*
- * main.c: executable header main code
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include <shlobj.h>
-#include <shellapi.h>
-#include "resource.h"
-#include "util.h"
-#include "fileform.h"
-#include "state.h"
-#include "ui.h"
-#include "lang.h"
-#include "state.h"
-#include "exec.h"
-
-#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
-
-char g_caption[NSIS_MAX_STRLEN*2];
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-HWND g_hwnd;
-HANDLE g_hInstance;
-#endif
-
-void NSISCALL CleanUp();
-
-char *ValidateTempDir()
-{
- validate_filename(state_temp_dir);
- if (!validpathspec(state_temp_dir))
- return NULL;
- addtrailingslash(state_temp_dir);
- CreateDirectory(state_temp_dir, NULL);
- // state_language is used as a temp var here
- return my_GetTempFileName(state_language, state_temp_dir);
-}
-
-void *g_SHGetFolderPath;
-
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow)
-{
- int ret = 0;
- const char *m_Err = _LANG_ERRORWRITINGTEMP;
-
- int cl_flags = 0;
-
- char *realcmds;
- char seekchar=' ';
- char *cmdline;
-
- InitCommonControls();
-
- SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
-
-#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
- {
- extern HRESULT g_hres;
- g_hres=OleInitialize(NULL);
- }
-#endif
-
- // load shfolder.dll before any script code is executed to avoid
- // weird situations where SetOutPath or even the extraction of
- // shfolder.dll will cause unexpected behavior.
- //
- // this also prevents the following:
- //
- // SetOutPath "C:\Program Files\NSIS" # maybe read from reg
- // File shfolder.dll
- // Delete $PROGRAMFILES\shfolder.dll # can't be deleted, as the
- // # new shfolder.dll is used
- // # to find its own path.
- g_SHGetFolderPath = myGetProcAddress(MGA_SHGetFolderPathA);
-
- {
- // workaround for bug #1008632
- // http://sourceforge.net/tracker/index.php?func=detail&aid=1008632&group_id=22049&atid=373085
- //
- // without this, SHGetSpecialFolderLocation doesn't always recognize
- // some special folders, like the desktop folder for all users, on
- // Windows 9x. unlike SHGetSpecialFolderPath, which is not available
- // on all versions of Windows, SHGetSpecialFolderLocation doesn't try
- // too hard to make sure the caller gets what he asked for. so we give
- // it a little push in the right direction by doing part of the work
- // for it.
- //
- // part of what SHGetFileInfo does, is to convert a path into an idl.
- // to do this conversion, it first needs to initialize the list of
- // special idls, which are exactly the idls we use to get the paths
- // of special folders (CSIDL_*).
-
- SHFILEINFO shfi;
- SHGetFileInfo("", 0, &shfi, sizeof(SHFILEINFO), 0);
- }
-
- mystrcpy(g_caption,_LANG_GENERIC_ERROR);
-
- mystrcpy(state_command_line, GetCommandLine());
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- g_hInstance = GetModuleHandle(NULL);
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-
- cmdline = state_command_line;
- if (*cmdline == '\"') seekchar = *cmdline++;
-
- cmdline=findchar(cmdline, seekchar);
- cmdline=CharNext(cmdline);
- realcmds=cmdline;
-
- while (*cmdline)
- {
- // skip over any spaces
- while (*cmdline == ' ') cmdline++;
-
- // get char we should look for to get the next parm
- seekchar = ' ';
- if (cmdline[0] == '\"')
- {
- cmdline++;
- seekchar = '\"';
- }
-
- // is it a switch?
- if (cmdline[0] == '/')
- {
- cmdline++;
-
-// this only works with spaces because they have just one bit on
-#define END_OF_ARG(c) (((c)|' ')==' ')
-
-#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT)
- if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1]))
- cl_flags |= FH_FLAGS_SILENT;
-#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- if (*(LPDWORD)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4]))
- cl_flags |= FH_FLAGS_NO_CRC;
-#endif//NSIS_CONFIG_CRC_SUPPORT
-
- if (*(LPDWORD)(cmdline-2) == CHAR4_TO_DWORD(' ', '/', 'D','='))
- {
- *(LPDWORD)(cmdline-2)=0; // keep this from being passed to uninstaller if necessary
- mystrcpy(state_install_directory,cmdline+2);
- break; // /D= must always be last
- }
- }
-
- // skip over our parm
- cmdline = findchar(cmdline, seekchar);
- // skip the quote
- if (*cmdline == '\"')
- cmdline++;
- }
-
- GetTempPath(NSIS_MAX_STRLEN, state_temp_dir);
- if (!ValidateTempDir())
- {
- GetWindowsDirectory(state_temp_dir, NSIS_MAX_STRLEN - 5); // leave space for \Temp
- mystrcat(state_temp_dir, "\\Temp");
- if (!ValidateTempDir())
- {
- goto end;
- }
- }
- DeleteFile(state_language);
-
- m_Err = loadHeaders(cl_flags);
- if (m_Err) goto end;
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (g_is_uninstaller)
- {
- char *p = findchar(state_command_line, 0);
-
- // state_command_line has state_install_directory right after it in memory, so reading
- // a bit over state_command_line won't do any harm
- while (p >= state_command_line && *(LPDWORD)p != CHAR4_TO_DWORD(' ', '_', '?', '=')) p--;
-
- m_Err = _LANG_UNINSTINITERROR;
-
- if (p >= state_command_line)
- {
- *p=0; // terminate before "_?="
- p+=4; // skip over " _?="
- if (is_valid_instpath(p))
- {
- mystrcpy(state_install_directory, p);
- mystrcpy(state_output_directory, p);
- m_Err = 0;
- }
- else
- {
- goto end;
- }
- }
- else
- {
- int x;
-
- mystrcat(state_temp_dir,"~nsu.tmp");
-
- // check if already running from uninstaller temp dir
- // this prevents recursive uninstaller calls
- if (!lstrcmpi(state_temp_dir,state_exe_directory))
- goto end;
-
- CreateDirectory(state_temp_dir,NULL);
- SetCurrentDirectory(state_temp_dir);
-
- if (!state_install_directory[0])
- mystrcpy(state_install_directory,state_exe_directory);
-
- mystrcpy(g_usrvars[0], realcmds);
- *(LPWORD)g_usrvars[1] = CHAR2_TO_WORD('A',0);
-
- for (x = 0; x < 26; x ++)
- {
- static char buf2[NSIS_MAX_STRLEN];
-
- GetNSISString(buf2,g_header->str_uninstchild); // $TEMP\$1u_.exe
-
- DeleteFile(buf2); // clean up after all the other ones if they are there
-
- if (m_Err) // not done yet
- {
- // copy file
- if (CopyFile(state_exe_path,buf2,TRUE))
- {
- HANDLE hProc;
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- MoveFileOnReboot(buf2,NULL);
-#endif
- GetNSISString(buf2,g_header->str_uninstcmd); // '"$TEMP\$1u_.exe" $0 _?=$INSTDIR\'
- hProc=myCreateProcess(buf2);
- if (hProc)
- {
- CloseHandle(hProc);
- // success
- m_Err = 0;
- }
- }
- }
- g_usrvars[1][0]++;
- }
-
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- MoveFileOnReboot(state_temp_dir,NULL);
-#endif
-
- goto end;
- }
- }
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-
- g_exec_flags.errlvl = -1;
- ret = ui_doinstall();
-
-#ifdef NSIS_CONFIG_LOG
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
- log_write(1);
-#endif//!NSIS_CONFIG_LOG_ODS && !NSIS_CONFIG_LOG_STDOUT
-#endif//NSIS_CONFIG_LOG
-end:
-
- CleanUp();
-
-#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
- OleUninitialize();
-#endif
-
- if (m_Err)
- {
- my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 21));
- ExitProcess(2);
- return 0;
- }
-
-#ifdef NSIS_SUPPORT_REBOOT
- if (g_exec_flags.reboot_called)
- {
- BOOL (WINAPI *OPT)(HANDLE, DWORD,PHANDLE);
- BOOL (WINAPI *LPV)(LPCTSTR,LPCTSTR,PLUID);
- BOOL (WINAPI *ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
- OPT=myGetProcAddress(MGA_OpenProcessToken);
- LPV=myGetProcAddress(MGA_LookupPrivilegeValueA);
- ATP=myGetProcAddress(MGA_AdjustTokenPrivileges);
- if (OPT && LPV && ATP)
- {
- HANDLE hToken;
- TOKEN_PRIVILEGES tkp;
- if (OPT(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- {
- LPV(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- ATP(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
- }
- }
-
- if (!ExitWindowsEx(EWX_REBOOT,0))
- ExecuteCallbackFunction(CB_ONREBOOTFAILED);
- }
-#endif//NSIS_SUPPORT_REBOOT
-
- if (g_exec_flags.errlvl != -1)
- ret = g_exec_flags.errlvl;
-
- ExitProcess(ret);
- return 0;
-}
-
-void NSISCALL CleanUp()
-{
- if (g_db_hFile != INVALID_HANDLE_VALUE)
- {
- CloseHandle(g_db_hFile);
- g_db_hFile = INVALID_HANDLE_VALUE;
- }
-#ifdef NSIS_COMPRESS_WHOLE
- if (dbd_hFile != INVALID_HANDLE_VALUE)
- {
- CloseHandle(dbd_hFile);
- dbd_hFile = INVALID_HANDLE_VALUE;
- }
-#endif
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- // Clean up after plug-ins
- myDelete(state_plugins_dir, DEL_DIR | DEL_RECURSE | DEL_REBOOT);
-#endif // NSIS_CONFIG_PLUGIN_SUPPORT
-}
+/* + * main.c: executable header main code + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include <shlobj.h> +#include <shellapi.h> +#include "resource.h" +#include "util.h" +#include "fileform.h" +#include "state.h" +#include "ui.h" +#include "lang.h" +#include "state.h" +#include "exec.h" + +#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 + +char g_caption[NSIS_MAX_STRLEN*2]; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +HWND g_hwnd; +HANDLE g_hInstance; +#endif + +void NSISCALL CleanUp(); + +char *ValidateTempDir() +{ + validate_filename(state_temp_dir); + if (!validpathspec(state_temp_dir)) + return NULL; + addtrailingslash(state_temp_dir); + CreateDirectory(state_temp_dir, NULL); + // state_language is used as a temp var here + return my_GetTempFileName(state_language, state_temp_dir); +} + +void *g_SHGetFolderPath; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdParam, int nCmdShow) +{ + int ret = 0; + const char *m_Err = _LANG_ERRORWRITINGTEMP; + + int cl_flags = 0; + + char *realcmds; + char seekchar=' '; + char *cmdline; + + InitCommonControls(); + + SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); + +#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT) + { + extern HRESULT g_hres; + g_hres=OleInitialize(NULL); + } +#endif + + // load shfolder.dll before any script code is executed to avoid + // weird situations where SetOutPath or even the extraction of + // shfolder.dll will cause unexpected behavior. + // + // this also prevents the following: + // + // SetOutPath "C:\Program Files\NSIS" # maybe read from reg + // File shfolder.dll + // Delete $PROGRAMFILES\shfolder.dll # can't be deleted, as the + // # new shfolder.dll is used + // # to find its own path. + g_SHGetFolderPath = myGetProcAddress(MGA_SHGetFolderPathA); + + { + // workaround for bug #1008632 + // http://sourceforge.net/tracker/index.php?func=detail&aid=1008632&group_id=22049&atid=373085 + // + // without this, SHGetSpecialFolderLocation doesn't always recognize + // some special folders, like the desktop folder for all users, on + // Windows 9x. unlike SHGetSpecialFolderPath, which is not available + // on all versions of Windows, SHGetSpecialFolderLocation doesn't try + // too hard to make sure the caller gets what he asked for. so we give + // it a little push in the right direction by doing part of the work + // for it. + // + // part of what SHGetFileInfo does, is to convert a path into an idl. + // to do this conversion, it first needs to initialize the list of + // special idls, which are exactly the idls we use to get the paths + // of special folders (CSIDL_*). + + SHFILEINFO shfi; + SHGetFileInfo("", 0, &shfi, sizeof(SHFILEINFO), 0); + } + + mystrcpy(g_caption,_LANG_GENERIC_ERROR); + + mystrcpy(state_command_line, GetCommandLine()); + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + g_hInstance = GetModuleHandle(NULL); +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + + cmdline = state_command_line; + if (*cmdline == '\"') seekchar = *cmdline++; + + cmdline=findchar(cmdline, seekchar); + cmdline=CharNext(cmdline); + realcmds=cmdline; + + while (*cmdline) + { + // skip over any spaces + while (*cmdline == ' ') cmdline++; + + // get char we should look for to get the next parm + seekchar = ' '; + if (cmdline[0] == '\"') + { + cmdline++; + seekchar = '\"'; + } + + // is it a switch? + if (cmdline[0] == '/') + { + cmdline++; + +// this only works with spaces because they have just one bit on +#define END_OF_ARG(c) (((c)|' ')==' ') + +#if defined(NSIS_CONFIG_VISIBLE_SUPPORT) && defined(NSIS_CONFIG_SILENT_SUPPORT) + if (cmdline[0] == 'S' && END_OF_ARG(cmdline[1])) + cl_flags |= FH_FLAGS_SILENT; +#endif//NSIS_CONFIG_SILENT_SUPPORT && NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (*(LPDWORD)cmdline == CHAR4_TO_DWORD('N','C','R','C') && END_OF_ARG(cmdline[4])) + cl_flags |= FH_FLAGS_NO_CRC; +#endif//NSIS_CONFIG_CRC_SUPPORT + + if (*(LPDWORD)(cmdline-2) == CHAR4_TO_DWORD(' ', '/', 'D','=')) + { + *(LPDWORD)(cmdline-2)=0; // keep this from being passed to uninstaller if necessary + mystrcpy(state_install_directory,cmdline+2); + break; // /D= must always be last + } + } + + // skip over our parm + cmdline = findchar(cmdline, seekchar); + // skip the quote + if (*cmdline == '\"') + cmdline++; + } + + GetTempPath(NSIS_MAX_STRLEN, state_temp_dir); + if (!ValidateTempDir()) + { + GetWindowsDirectory(state_temp_dir, NSIS_MAX_STRLEN - 5); // leave space for \Temp + mystrcat(state_temp_dir, "\\Temp"); + if (!ValidateTempDir()) + { + goto end; + } + } + DeleteFile(state_language); + + m_Err = loadHeaders(cl_flags); + if (m_Err) goto end; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (g_is_uninstaller) + { + char *p = findchar(state_command_line, 0); + + // state_command_line has state_install_directory right after it in memory, so reading + // a bit over state_command_line won't do any harm + while (p >= state_command_line && *(LPDWORD)p != CHAR4_TO_DWORD(' ', '_', '?', '=')) p--; + + m_Err = _LANG_UNINSTINITERROR; + + if (p >= state_command_line) + { + *p=0; // terminate before "_?=" + p+=4; // skip over " _?=" + if (is_valid_instpath(p)) + { + mystrcpy(state_install_directory, p); + mystrcpy(state_output_directory, p); + m_Err = 0; + } + else + { + goto end; + } + } + else + { + int x; + + mystrcat(state_temp_dir,"~nsu.tmp"); + + // check if already running from uninstaller temp dir + // this prevents recursive uninstaller calls + if (!lstrcmpi(state_temp_dir,state_exe_directory)) + goto end; + + CreateDirectory(state_temp_dir,NULL); + SetCurrentDirectory(state_temp_dir); + + if (!state_install_directory[0]) + mystrcpy(state_install_directory,state_exe_directory); + + mystrcpy(g_usrvars[0], realcmds); + *(LPWORD)g_usrvars[1] = CHAR2_TO_WORD('A',0); + + for (x = 0; x < 26; x ++) + { + static char buf2[NSIS_MAX_STRLEN]; + + GetNSISString(buf2,g_header->str_uninstchild); // $TEMP\$1u_.exe + + DeleteFile(buf2); // clean up after all the other ones if they are there + + if (m_Err) // not done yet + { + // copy file + if (CopyFile(state_exe_path,buf2,TRUE)) + { + HANDLE hProc; +#ifdef NSIS_SUPPORT_MOVEONREBOOT + MoveFileOnReboot(buf2,NULL); +#endif + GetNSISString(buf2,g_header->str_uninstcmd); // '"$TEMP\$1u_.exe" $0 _?=$INSTDIR\' + hProc=myCreateProcess(buf2); + if (hProc) + { + CloseHandle(hProc); + // success + m_Err = 0; + } + } + } + g_usrvars[1][0]++; + } + +#ifdef NSIS_SUPPORT_MOVEONREBOOT + MoveFileOnReboot(state_temp_dir,NULL); +#endif + + goto end; + } + } +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT + + g_exec_flags.errlvl = -1; + ret = ui_doinstall(); + +#ifdef NSIS_CONFIG_LOG +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) + log_write(1); +#endif//!NSIS_CONFIG_LOG_ODS && !NSIS_CONFIG_LOG_STDOUT +#endif//NSIS_CONFIG_LOG +end: + + CleanUp(); + +#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT) + OleUninitialize(); +#endif + + if (m_Err) + { + my_MessageBox(m_Err, MB_OK | MB_ICONSTOP | (IDOK << 21)); + ExitProcess(2); + return 0; + } + +#ifdef NSIS_SUPPORT_REBOOT + if (g_exec_flags.reboot_called) + { + BOOL (WINAPI *OPT)(HANDLE, DWORD,PHANDLE); + BOOL (WINAPI *LPV)(LPCTSTR,LPCTSTR,PLUID); + BOOL (WINAPI *ATP)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD); + OPT=myGetProcAddress(MGA_OpenProcessToken); + LPV=myGetProcAddress(MGA_LookupPrivilegeValueA); + ATP=myGetProcAddress(MGA_AdjustTokenPrivileges); + if (OPT && LPV && ATP) + { + HANDLE hToken; + TOKEN_PRIVILEGES tkp; + if (OPT(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + LPV(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ATP(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); + } + } + + if (!ExitWindowsEx(EWX_REBOOT,0)) + ExecuteCallbackFunction(CB_ONREBOOTFAILED); + } +#endif//NSIS_SUPPORT_REBOOT + + if (g_exec_flags.errlvl != -1) + ret = g_exec_flags.errlvl; + + ExitProcess(ret); + return 0; +} + +void NSISCALL CleanUp() +{ + if (g_db_hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(g_db_hFile); + g_db_hFile = INVALID_HANDLE_VALUE; + } +#ifdef NSIS_COMPRESS_WHOLE + if (dbd_hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(dbd_hFile); + dbd_hFile = INVALID_HANDLE_VALUE; + } +#endif +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + // Clean up after plug-ins + myDelete(state_plugins_dir, DEL_DIR | DEL_RECURSE | DEL_REBOOT); +#endif // NSIS_CONFIG_PLUGIN_SUPPORT +} diff --git a/Source/exehead/SConscript b/Source/exehead/SConscript index 9baa3bb..b004c79 100755 --- a/Source/exehead/SConscript +++ b/Source/exehead/SConscript @@ -1,101 +1,101 @@ -files = Split("""
- bgbg.c
- components.c
- exec.c
- fileform.c
- Main.c
- Ui.c
- util.c
- #Source/crc32.c
-""")
-
-resources = Split("""
- resource.rc
-""")
-
-resource_files = Split("""
- nsis.ico
- uninst.ico
- bitmap1.bmp
-""")
-
-bzip2_files = Split("""
- #Source/bzip2/bzlib.c
- #Source/bzip2/decompress.c
- #Source/bzip2/huffman.c
-""")
-
-lzma_files = Split("""
- #Source/7zip/LZMADecode.c
-""")
-
-zlib_files = Split("""
- #Source/zlib/INFBLOCK.C
-""")
-
-libs = Split("""
- kernel32
- user32
- gdi32
- shell32
- advapi32
- comdlg32
- comctl32
- ole32
- version
- uuid
-""")
-
-Import('env compression solid_compression')
-
-### Defines
-
-env.Append(CPPDEFINES = ['EXEHEAD'])
-env.Append(CPPDEFINES = ['WIN32_LEAN_AND_MEAN'])
-env.Append(CPPDEFINES = ['_WIN32_IE=0x0500'])
-
-### Some other settings
-
-if 'NSIS_CONFIG_LOG_STDOUT' in env['NSIS_CPPDEFINES']:
- env.Append(LINKFLAGS = env['SUBSYS_CON'])
-
-### Compression specific configuration
-
-if compression == 'bzip2':
- env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_BZIP2'])
- files += bzip2_files
-elif compression == 'lzma':
- env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_LZMA'])
- env.Append(CPPDEFINES = ['LZMACALL=__fastcall'])
- files += lzma_files
-elif compression == 'zlib':
- env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_ZLIB'])
- env.Append(CPPDEFINES = ['ZEXPORT=__stdcall'])
- files += zlib_files
-
-if solid_compression:
- env.Append(CPPDEFINES = ['NSIS_COMPRESS_WHOLE'])
-
-### Build with no sub-build-directories
-
-objs = []
-
-def basename(file):
- return file.split('/')[-1].split('.')[0]
-
-for file in files:
- objs.append(env.Object(target = basename(file), source = file))
-
-### Resources
-
-res = env.RES(resources)
-env.Depends(res, resource_files)
-objs = objs + res
-
-### Build stub
-
-stub = env.Program(target = 'stub_' + compression, source = objs, LIBS = libs)
-
-### Return stub
-
-Return('stub')
+files = Split(""" + bgbg.c + components.c + exec.c + fileform.c + Main.c + Ui.c + util.c + #Source/crc32.c +""") + +resources = Split(""" + resource.rc +""") + +resource_files = Split(""" + nsis.ico + uninst.ico + bitmap1.bmp +""") + +bzip2_files = Split(""" + #Source/bzip2/bzlib.c + #Source/bzip2/decompress.c + #Source/bzip2/huffman.c +""") + +lzma_files = Split(""" + #Source/7zip/LZMADecode.c +""") + +zlib_files = Split(""" + #Source/zlib/INFBLOCK.C +""") + +libs = Split(""" + kernel32 + user32 + gdi32 + shell32 + advapi32 + comdlg32 + comctl32 + ole32 + version + uuid +""") + +Import('env compression solid_compression') + +### Defines + +env.Append(CPPDEFINES = ['EXEHEAD']) +env.Append(CPPDEFINES = ['WIN32_LEAN_AND_MEAN']) +env.Append(CPPDEFINES = ['_WIN32_IE=0x0500']) + +### Some other settings + +if 'NSIS_CONFIG_LOG_STDOUT' in env['NSIS_CPPDEFINES']: + env.Append(LINKFLAGS = env['SUBSYS_CON']) + +### Compression specific configuration + +if compression == 'bzip2': + env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_BZIP2']) + files += bzip2_files +elif compression == 'lzma': + env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_LZMA']) + env.Append(CPPDEFINES = ['LZMACALL=__fastcall']) + files += lzma_files +elif compression == 'zlib': + env.Append(CPPDEFINES = ['NSIS_COMPRESS_USE_ZLIB']) + env.Append(CPPDEFINES = ['ZEXPORT=__stdcall']) + files += zlib_files + +if solid_compression: + env.Append(CPPDEFINES = ['NSIS_COMPRESS_WHOLE']) + +### Build with no sub-build-directories + +objs = [] + +def basename(file): + return file.split('/')[-1].split('.')[0] + +for file in files: + objs.append(env.Object(target = basename(file), source = file)) + +### Resources + +res = env.RES(resources) +env.Depends(res, resource_files) +objs = objs + res + +### Build stub + +stub = env.Program(target = 'stub_' + compression, source = objs, LIBS = libs) + +### Return stub + +Return('stub') diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index 65f5f5f..7f9ce03 100755 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -1,1692 +1,1692 @@ -/*
- * Ui.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft, Jeff Doozan and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include <windowsx.h>
-#include <shlobj.h>
-#include <shellapi.h>
-#include <shlwapi.h>
-
-#include "../Platform.h"
-
-#include "resource.h"
-
-#include "fileform.h"
-#include "state.h"
-#include "util.h"
-#include "ui.h"
-#include "exec.h"
-#include "lang.h"
-#include "components.h"
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-HICON g_hIcon;
-#endif
-
-int dlg_offset;
-int ui_dlg_visible=0; // At start main window is not visible
-int g_quit_flag; // set when Quit has been called (meaning bail out ASAP)
-
-#if NSIS_MAX_INST_TYPES > 32 || NSIS_MAX_INST_TYPES < 1
-#error invalid value for NSIS_MAX_INST_TYPES
-#endif
-
-int progress_bar_pos, progress_bar_len;
-
-#if NSIS_MAX_STRLEN < 1024
-static char g_tmp[4096];
-#else
-static char g_tmp[NSIS_MAX_STRLEN * 4];
-#endif
-
-static int m_page=-1,m_retcode,m_delta;
-static page *g_this_page;
-
-#define NOTIFY_BYE_BYE 'x'
-
-static void NSISCALL outernotify(int delta) {
- if (delta==NOTIFY_BYE_BYE)
- g_quit_flag++;
- SendMessage(g_hwnd,WM_NOTIFY_OUTER_NEXT,(WPARAM)delta,0);
-}
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
-#ifdef NSIS_CONFIG_LICENSEPAGE
-static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-#endif
-static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-
-static DWORD WINAPI install_thread(LPVOID p);
-
-void NSISCALL CleanUp();
-
-HWND insthwnd, insthwnd2, insthwndbutton;
-
-HWND m_curwnd;
-static HWND m_bgwnd, m_hwndOK, m_hwndCancel;
-
-static BOOL NSISCALL SetDlgItemTextFromLang_(HWND dlg, int id, int lid) {
- return my_SetDialogItemText(dlg,id+1000,GetNSISStringTT(lid));
-}
-
-static void NSISCALL SetNextDef()
-{
- SendMessage(g_exec_flags.abort ? m_hwndCancel : m_hwndOK, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
-}
-
-static void NSISCALL EnableNext(BOOL e)
-{
- EnableWindow(m_hwndOK, e);
-}
-
-static void NSISCALL SetActiveCtl(HWND hCtl)
-{
- SendMessage(g_hwnd, WM_NEXTDLGCTL, (WPARAM) hCtl, TRUE);
-}
-
-static void NSISCALL NotifyCurWnd(UINT uNotifyCode)
-{
- if (m_curwnd)
- SendMessage(m_curwnd, uNotifyCode, 0, 0);
-}
-
-#define SetDlgItemTextFromLang(dlg,id,lid) SetDlgItemTextFromLang_(dlg,(id)-1000,lid)
-
-#define SetUITextFromLang(it,la) SetDlgItemTextFromLang_(hwndDlg,(it)-1000,la)
-#define SetUITextNT(it,text) my_SetDialogItemText(hwndDlg,it,text)
-#define GetUIText(it,s) my_GetDialogItemText(it,s)
-#define GetUIItem(it) GetDlgItem(hwndDlg,it)
-
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
-#define HandleStaticBkColor() _HandleStaticBkColor(uMsg, wParam, lParam)
-static BOOL NSISCALL _HandleStaticBkColor(UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- if ((uMsg - WM_CTLCOLOREDIT) <= (WM_CTLCOLORSTATIC - WM_CTLCOLOREDIT))
- {
- ctlcolors *c = (ctlcolors *)GetWindowLong((HWND)lParam, GWL_USERDATA);
-
- if (c) {
- COLORREF text;
- LOGBRUSH lh;
-
- text = c->text;
- if (c->flags & CC_TEXT_SYS)
- text = GetSysColor(text);
- if (c->flags & CC_TEXT)
- SetTextColor((HDC)wParam, text);
-
- SetBkMode((HDC)wParam, c->bkmode);
-
- lh.lbColor = c->bkc;
- if (c->flags & CC_BK_SYS)
- lh.lbColor = GetSysColor(lh.lbColor);
- if (c->flags & CC_BK)
- SetBkColor((HDC)wParam, lh.lbColor);
-
- if (c->flags & CC_BKB)
- {
- lh.lbStyle = c->lbStyle;
- if (c->bkb)
- DeleteObject(c->bkb);
- c->bkb = CreateBrushIndirect(&lh);
- }
-
- return (BOOL)c->bkb;
- }
- }
- return 0;
-}
-#else
-#define HandleStaticBkColor() 0
-#endif//!NSIS_CONFIG_ENHANCEDUI_SUPPORT
-
-#ifdef NSIS_CONFIG_LOG
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
-void NSISCALL build_g_logfile()
-{
- mystrcat(addtrailingslash(mystrcpy(g_log_file,state_install_directory)),"install.log");
-}
-#endif
-#endif
-
-int *cur_langtable;
-
-static void NSISCALL set_language()
-{
- LANGID lang_mask=(LANGID)~0;
- LANGID lang=myatoi(state_language);
- char *language_table=0;
- int lang_num;
- int *selected_langtable=0;
-
-lang_again:
- lang_num=g_blocks[NB_LANGTABLES].num;
- while (lang_num--) {
- language_table=((char*)g_blocks[NB_LANGTABLES].offset)+lang_num*g_header->langtable_size;
- if (!((lang ^ *(LANGID*)language_table) & lang_mask)) {
- dlg_offset=*(int*)(language_table+sizeof(LANGID));
- g_exec_flags.rtl=*(int*)(language_table+sizeof(LANGID)+sizeof(int));
- selected_langtable=(int*)(language_table+sizeof(LANGID)+2*sizeof(int));
- break;
- }
- }
- if (!selected_langtable) {
- if (lang_mask == (LANGID)~0)
- lang_mask=0x3ff; // primary lang
- else // we already tried once and we still don't have a language table
- lang_mask=0; // first lang
- goto lang_again;
- }
-
- cur_langtable = selected_langtable;
-
- myitoa(state_language, *(LANGID*)language_table);
- {
- char *caption = GetNSISString(g_caption,LANG_CAPTION);
-#ifdef NSIS_SUPPORT_BGBG
- my_SetWindowText(m_bgwnd, caption);
-#endif
- }
-
- // reload section names
- {
- section *sec = g_sections;
- int x = num_sections;
-
- while (x--)
- {
- if (sec->name_ptr)
- {
- GetNSISString(sec->name, sec->name_ptr);
- }
- sec++;
- }
- }
-}
-
-FORCE_INLINE int NSISCALL ui_doinstall(void)
-{
- header *header = g_header;
- static WNDCLASS wc; // richedit subclassing and bgbg creation
-
- // detect default language
- // more information at:
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_0xrn.asp
-
- LANGID (WINAPI *GUDUIL)();
-
- GUDUIL = myGetProcAddress(MGA_GetUserDefaultUILanguage);
- if (GUDUIL)
- {
- // Windows ME/2000+
- myitoa(state_language, GUDUIL());
- }
- else
- {
- static const char reg_9x_locale[] = "Control Panel\\Desktop\\ResourceLocale";
- static const char reg_nt_locale_key[] = ".DEFAULT\\Control Panel\\International";
- const char *reg_nt_locale_val = ®_9x_locale[30]; // = "Locale" with opt
-
- *(DWORD*)state_language = CHAR4_TO_DWORD('0', 'x', 0, 0);
-
- {
- // Windows 9x
- myRegGetStr(HKEY_CURRENT_USER, reg_9x_locale, NULL, g_tmp, 0);
- }
-
- if (!g_tmp[0])
- {
- // Windows NT
- // This key exists on 9x as well, so it's only read if ResourceLocale wasn't found
- myRegGetStr(HKEY_USERS, reg_nt_locale_key, reg_nt_locale_val, g_tmp, 0);
- }
-
- mystrcat(state_language, g_tmp);
- }
-
- // set default language
- set_language();
-
- // initialize auto close flag
- g_exec_flags.autoclose=g_flags&CH_FLAGS_AUTO_CLOSE;
-
- // read install directory from registry
- if (!is_valid_instpath(state_install_directory))
- {
- if (header->install_reg_key_ptr)
- {
- myRegGetStr(
- (HKEY)header->install_reg_rootkey,
- GetNSISStringNP(header->install_reg_key_ptr),
- GetNSISStringNP(header->install_reg_value_ptr),
- ps_tmpbuf,
- 0
- );
- if (ps_tmpbuf[0])
- {
- char *p=ps_tmpbuf;
- char *e;
- if (p[0]=='\"')
- {
- char *p2;
- p++;
- p2 = findchar(p, '"');
- *p2 = 0;
- }
- // p is the path now, check for .exe extension
-
- e=p+mystrlen(p)-4;
- if (e > p)
- {
- // if filename ends in .exe, and is not a directory, remove the filename
- if (!lstrcmpi(e, ".exe")) // check extension
- {
- DWORD d;
- d=GetFileAttributes(p);
- if (d == INVALID_FILE_ATTRIBUTES || !(d&FILE_ATTRIBUTE_DIRECTORY))
- {
- // if there is no back-slash, the string will become empty, but that's ok because
- // it would make an invalid instdir anyway
- trimslashtoend(p);
- }
- }
- }
-
- mystrcpy(state_install_directory,addtrailingslash(p));
- }
- }
- }
- if (!is_valid_instpath(state_install_directory))
- {
- GetNSISString(state_install_directory,header->install_directory_ptr);
- }
-
-#ifdef NSIS_CONFIG_LOG
- if (g_flags & CH_FLAGS_SILENT_LOG && !g_is_uninstaller)
- {
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
- build_g_logfile();
-#endif
- log_dolog=1;
- }
-#endif
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- g_hIcon=LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_ICON2),IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_SHARED);
-#ifdef NSIS_SUPPORT_BGBG
- if (header->bg_color1 != -1)
- {
- DWORD cn = CHAR4_TO_DWORD('_', 'N', 'b', 0);
- RECT vp;
- extern LRESULT CALLBACK BG_WndProc(HWND, UINT, WPARAM, LPARAM);
- wc.lpfnWndProc = BG_WndProc;
- wc.hInstance = g_hInstance;
- wc.hIcon = g_hIcon;
- //wc.hCursor = LoadCursor(NULL,IDC_ARROW);
- wc.lpszClassName = (LPCSTR)&cn;
-
- if (!RegisterClass(&wc)) return 0;
-
- SystemParametersInfo(SPI_GETWORKAREA, 0, &vp, 0);
-
- m_bgwnd = CreateWindowEx(WS_EX_TOOLWINDOW,(LPCSTR)&cn,0,WS_POPUP,
- vp.left,vp.top,vp.right-vp.left,vp.bottom-vp.top,0,NULL,g_hInstance,NULL);
- }
-
-#endif//NSIS_SUPPORT_BGBG
-
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // Select language
- if (ExecuteCallbackFunction(CB_ONINIT)) return 2;
- set_language();
-#endif
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if (!g_exec_flags.silent)
-#endif//NSIS_CONFIG_SILENT_SUPPORT
- {
-#ifdef NSIS_SUPPORT_BGBG
- ShowWindow(m_bgwnd, SW_SHOW);
-#endif//NSIS_SUPPORT_BGBG
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- { // load richedit DLL
- static const char riched20[]="RichEd20";
- static const char riched32[]="RichEd32";
- static const char richedit20a[]="RichEdit20A";
- static const char richedit[]="RichEdit";
- if (!LoadLibrary(riched20))
- {
- LoadLibrary(riched32);
- }
-
- // make richedit20a point to RICHEDIT
- if (!GetClassInfo(NULL,richedit20a,&wc))
- {
- GetClassInfo(NULL,richedit,&wc);
- wc.lpszClassName = richedit20a;
- RegisterClass(&wc);
- }
- }
-#endif
-
- {
- int ret=DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_INST+dlg_offset),0,DialogProc);
-#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT)
- ExecuteCallbackFunction(CB_ONGUIEND);
-#endif
- return ret;
- }
- }
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- else
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- {
- if (install_thread(NULL))
- {
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (!g_quit_flag) ExecuteCallbackFunction(CB_ONINSTFAILED);
-#endif//NSIS_SUPPORT_CODECALLBACKS
- return 2;
- }
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- ExecuteCallbackFunction(CB_ONINSTSUCCESS);
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
- return 0;
- }
-#endif//NSIS_CONFIG_SILENT_SUPPORT
-}
-
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
-{
- if (uMsg==BFFM_INITIALIZED)
- {
- my_GetDialogItemText(IDC_DIR,(char*)lpData);
- SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,lpData);
- }
- if (uMsg==BFFM_SELCHANGED)
- {
- SendMessage(
- hwnd,
- BFFM_ENABLEOK,
- 0,
- SHGetPathFromIDList((LPITEMIDLIST)lParam,(char*)lpData)
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- && !ExecuteCallbackFunction(CB_ONVERIFYINSTDIR)
-#endif
- );
- }
- return 0;
-}
-
-BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT)
- {
- page *this_page;
- static DLGPROC winprocs[]=
- {
-#ifdef NSIS_CONFIG_LICENSEPAGE
- LicenseProc,
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- SelProc,
-#endif
- DirProc,
- InstProc,
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- UninstProc
-#endif
- };
-
- m_delta = wParam;
-
- if (uMsg == WM_INITDIALOG)
- {
- g_hwnd=hwndDlg;
- m_hwndOK=GetDlgItem(hwndDlg,IDOK);
- m_hwndCancel=GetDlgItem(hwndDlg,IDCANCEL);
- SetDlgItemTextFromLang(hwndDlg,IDC_VERSTR,LANG_BRANDING);
- SetClassLong(hwndDlg,GCL_HICON,(long)g_hIcon);
- // use the following line instead of the above, if .rdata needs shirking
- //SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)g_hIcon);
-#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT)
- g_quit_flag = ExecuteCallbackFunction(CB_ONGUIINIT);
-#endif
- //ShowWindow(hwndDlg, SW_SHOW);
- m_delta = 1;
- }
-
- this_page=g_pages+m_page;
-
- if (m_page>=0) {
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // Call leave function. If Abort used don't move to the next page.
- // But if quit called we must exit now
- if (m_delta==1) if (ExecuteCodeSegment(this_page->leavefunc,NULL)) {
- SendMessage(m_curwnd, WM_IN_UPDATEMSG, 0, 1);
- return !g_quit_flag;
- }
-#endif
-
- // if the last page was a custom page, wait for it to finish by itself.
- // if it doesn't, it's a BAD plugin.
- // plugins should react to WM_NOTIFY_OUTER_NEXT.
- if (!this_page->dlg_id) return 0;
- }
-
- NotifyCurWnd(WM_NOTIFY_INIGO_MONTOYA);
-
-nextPage:
- m_page+=m_delta;
- this_page+=m_delta;
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (m_page==g_blocks[NB_PAGES].num) ExecuteCallbackFunction(CB_ONINSTSUCCESS);
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
- if (g_quit_flag || (unsigned int)m_page >= (unsigned int)g_blocks[NB_PAGES].num)
- {
- DestroyWindow(m_curwnd);
- g_hwnd = 0;
- EndDialog(hwndDlg,m_retcode);
- }
- else
- {
- HWND hwndtmp;
-
- int pflags = this_page->flags;
-
- GetNSISString(state_click_next, this_page->clicknext);
- SetDlgItemTextFromLang(hwndDlg, IDOK, this_page->next);
- SetDlgItemTextFromLang(hwndDlg, IDC_BACK, this_page->back);
- SetDlgItemTextFromLang(hwndDlg, IDCANCEL, this_page->cancel);
-
- hwndtmp = GetDlgItem(hwndDlg, IDC_BACK);
-
- if (g_exec_flags.abort)
- {
- pflags &= ~(PF_BACK_ENABLE | PF_NEXT_ENABLE);
- pflags |= PF_CANCEL_ENABLE;
- }
-
- ShowWindow(hwndtmp, pflags & PF_BACK_SHOW);// SW_HIDE = 0, PF_BACK_SHOW = SW_SHOWNA = 8
- EnableWindow(hwndtmp, pflags & PF_BACK_ENABLE);
- EnableNext(pflags & PF_NEXT_ENABLE);
- EnableWindow(m_hwndCancel, pflags & PF_CANCEL_ENABLE);
-
- if (pflags & PF_CANCEL_ENABLE)
- EnableMenuItem(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED);
- else
- EnableMenuItem(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
-
- SendMessage(hwndtmp, BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
-
- if (g_exec_flags.abort)
- {
- SendMessage(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
- SetActiveCtl(m_hwndCancel);
- }
- else
- {
- SetActiveCtl(m_hwndOK);
- }
-
- mystrcpy(g_tmp,g_caption);
- GetNSISString(g_tmp+mystrlen(g_tmp),this_page->caption);
- my_SetWindowText(hwndDlg,g_tmp);
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // custom page or user used abort in prefunc
- if (ExecuteCodeSegment(this_page->prefunc, NULL) || !this_page->dlg_id) {
- goto nextPage;
- }
-#endif //NSIS_SUPPORT_CODECALLBACKS
-
- if (this_page->wndproc_id != PWP_COMPLETED)
- {
- DestroyWindow(m_curwnd);
- }
- else {
- if (!g_exec_flags.abort && g_exec_flags.autoclose)
- goto nextPage;
- // no need to go to skipPage because PWP_COMPLETED always follows PWP_INSTFILES
- return FALSE;
- }
-
- // update g_this_page for the dialog proc
- g_this_page=this_page;
-
- if (this_page->dlg_id > 0) // NSIS page
- {
- m_curwnd=CreateDialogParam(
- g_hInstance,
- MAKEINTRESOURCE(this_page->dlg_id+dlg_offset),
- hwndDlg,winprocs[this_page->wndproc_id],(LPARAM)this_page
- );
- if (m_curwnd)
- {
- RECT r;
-
- SetDlgItemTextFromLang(m_curwnd,IDC_INTROTEXT,this_page->parms[0]);
-
- GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r);
- ScreenToClient(hwndDlg,(LPPOINT)&r);
- SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- ExecuteCodeSegment(this_page->showfunc,NULL);
- if (g_quit_flag)
- return FALSE;
-#endif //NSIS_SUPPORT_CODECALLBACKS
- ShowWindow(m_curwnd,SW_SHOWNA);
- NotifyCurWnd(WM_NOTIFY_START);
- }
- }
- }
-
-skipPage:
-
- if (!ui_dlg_visible && m_curwnd)
- {
- ShowWindow(hwndDlg, SW_SHOWDEFAULT);
- ui_dlg_visible = 1;
- }
-
- return FALSE;
- }
-
-#ifdef NSIS_SUPPORT_BGBG
- if (uMsg == WM_WINDOWPOSCHANGED)
- {
- SetWindowPos(m_bgwnd, hwndDlg, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
- }
- if (uMsg == WM_SIZE) {
- ShowWindow(m_bgwnd, wParam == SIZE_MINIMIZED ? SW_HIDE : SW_SHOW);
- }
-#endif //NSIS_SUPPORT_BGBG
-
- if (uMsg == WM_NOTIFY_CUSTOM_READY) {
- DestroyWindow(m_curwnd);
- m_curwnd = (HWND)wParam;
- goto skipPage;
- }
- if (uMsg == WM_QUERYENDSESSION)
- {
- SetWindowLong(hwndDlg, DWL_MSGRESULT, FALSE);
- return TRUE;
- }
- if (uMsg == WM_COMMAND)
- {
- int id = LOWORD(wParam);
- HWND hCtl = GetDlgItem(hwndDlg, id); // lParam might be NULL
- if (hCtl)
- {
- SendMessage(hCtl, BM_SETSTATE, FALSE, 0);
- if (!IsWindowEnabled(hCtl))
- return 0;
- }
-
- if (id == IDOK)
- {
- outernotify(1);
- }
- else if (id == IDC_BACK && m_page>0)
- {
- outernotify(-1);
- }
- else if (id == IDCANCEL)
- {
- if (g_exec_flags.abort)
- {
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- ExecuteCallbackFunction(CB_ONINSTFAILED);
-#endif//NSIS_SUPPORT_CODECALLBACKS
- m_retcode=2;
- outernotify(NOTIFY_BYE_BYE);
- }
- else
- {
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (!ExecuteCallbackFunction(CB_ONUSERABORT))
-#endif//NSIS_SUPPORT_CODECALLBACKS
- {
- m_retcode=1;
- outernotify(NOTIFY_BYE_BYE);
- }
- }
- }
- else
- {
- // Forward WM_COMMANDs to inner dialogs, can be custom ones.
- // Without this, enter on buttons in inner dialogs won't work.
- SendMessage(m_curwnd, WM_COMMAND, wParam, lParam);
- }
- }
- return HandleStaticBkColor();
-}
-
-#define this_page ((page*)lParam)
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
-
-#define _RICHEDIT_VER 0x0200
-#include <richedit.h>
-#undef _RICHEDIT_VER
-static DWORD dwRead;
-DWORD CALLBACK StreamLicense(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
-{
- lstrcpyn(pbBuff,(char*)dwCookie+dwRead,cb);
- *pcb=mystrlen(pbBuff);
- dwRead+=*pcb;
- return 0;
-}
-
-static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- page *m_this_page=g_this_page;
- HWND hwLicense;
- static int ignoreWMCommand;
-
- if (uMsg == WM_INITDIALOG)
- {
- char *l = (char *)GetNSISStringNP(GetNSISTab(this_page->parms[1]));
- int lt = *l;
- EDITSTREAM es = {
- (DWORD)(++l),
- 0,
- StreamLicense
- };
-
- int selected = (this_page->flags & PF_LICENSE_SELECTED) | !(this_page->flags & PF_LICENSE_FORCE_SELECTION);
-
- SetUITextFromLang(IDC_LICENSEAGREE,this_page->parms[2]);
- SetUITextFromLang(IDC_LICENSEDISAGREE,this_page->parms[3]);
- CheckDlgButton(hwndDlg,IDC_LICENSEAGREE+!selected,BST_CHECKED);
- EnableNext(selected);
-
- hwLicense=GetUIItem(IDC_EDIT1);
- SetActiveCtl(hwLicense);
- SendMessage(hwLicense,EM_AUTOURLDETECT,TRUE,0);
-#define lbg g_header->license_bg
- SendMessage(hwLicense,EM_SETBKGNDCOLOR,0,lbg>=0?lbg:GetSysColor(-lbg));
-#undef lbg
- SendMessage(hwLicense,EM_SETEVENTMASK,0,ENM_LINK|ENM_KEYEVENTS); //XGE 8th September 2002 Or'd in ENM_KEYEVENTS
- dwRead=0;
- SendMessage(hwLicense,EM_EXLIMITTEXT,0,mystrlen(l));
- SendMessage(hwLicense,EM_STREAMIN,lt,(LPARAM)&es);
- ignoreWMCommand = 0;
- return FALSE;
- }
- if (uMsg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && !ignoreWMCommand) {
- if (m_this_page->flags & PF_LICENSE_FORCE_SELECTION) {
- int is = SendMessage(GetUIItem(IDC_LICENSEAGREE), BM_GETCHECK, 0, 0) & BST_CHECKED;
- m_this_page->flags &= ~PF_LICENSE_SELECTED;
- m_this_page->flags |= is;
- EnableNext(is);
- SetNextDef();
- }
- }
- if (uMsg == WM_NOTIFY) {
- hwLicense=GetUIItem(IDC_EDIT1);
- #define nmhdr ((NMHDR *)lParam)
- #define enlink ((ENLINK *)lParam)
- #define msgfilter ((MSGFILTER *)lParam)
- if (nmhdr->code==EN_LINK) {
- if (enlink->msg==WM_LBUTTONDOWN) {
- TEXTRANGE tr = {
- {
- enlink->chrg.cpMin,
- enlink->chrg.cpMax,
- },
- ps_tmpbuf
- };
- if (tr.chrg.cpMax-tr.chrg.cpMin < sizeof(ps_tmpbuf)) {
- SendMessage(hwLicense,EM_GETTEXTRANGE,0,(LPARAM)&tr);
- SetCursor(LoadCursor(0, IDC_WAIT));
- ShellExecute(hwndDlg,"open",tr.lpstrText,NULL,NULL,SW_SHOWNORMAL);
- SetCursor(LoadCursor(0, IDC_ARROW));
- }
- }
- }
- //Ximon Eighteen 8th September 2002 Capture return key presses in the rich
- //edit control now that the control gets the focus rather than the default
- //push button. When the user presses return ask the outer dialog to move
- //the installer onto the next page. MSDN docs say return non-zero if the
- //rich edit control should NOT process this message, hence the return 1.
- //
- //This is required because the RichEdit control is eating all the key hits.
- //It does try to release some and convert VK_ESCAPE to WM_CLOSE, VK_ENTER
- //to a push on the default button and VM_TAB to WM_NEXTDLGCTL. But sadly it
- //it sends all of these messages to its parent instead of just letting the
- //dialog manager handle them. Instead of properly handling WM_GETDLGCODE,
- //it mimics the dialog manager.
- if (nmhdr->code==EN_MSGFILTER)
- {
- if (msgfilter->msg==WM_KEYDOWN)
- {
- if (msgfilter->wParam==VK_RETURN) {
- SendMessage(g_hwnd, WM_COMMAND, IDOK, 0);
- }
- if (msgfilter->wParam==VK_ESCAPE) {
- SendMessage(g_hwnd, WM_CLOSE, 0, 0);
- }
- return 1;
- }
- }
- #undef nmhdr
- #undef enlink
- #undef msgfilter
- }
- if (uMsg == WM_NOTIFY_INIGO_MONTOYA)
- {
- ignoreWMCommand++;
- }
- return HandleStaticBkColor();
-}
-#endif
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
-static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- if (uMsg == WM_INITDIALOG)
- {
- SetUITextFromLang(IDC_UNINSTFROM,this_page->parms[1]);
- SetUITextNT(IDC_EDIT1,g_usrvars[this_page->parms[4]]);
- }
- return HandleStaticBkColor();
-}
-#endif
-
-
-static void NSISCALL SetSizeText(int dlgItem, int prefix, unsigned kb)
-{
- char scalestr[32], byte[32];
- unsigned sh = 20;
- int scale = LANG_GIGA;
-
- if (kb < 1024 * 1024) { sh = 10; scale = LANG_MEGA; }
- if (kb < 1024) { sh = 0; scale = LANG_KILO; }
-
- if (kb < (0xFFFFFFFF - ((1 << 20) / 20))) // check for overflow
- kb += (1 << sh) / 20; // round numbers for better display (e.g. 1.59 => 1.6)
-
- wsprintf(
- GetNSISString(g_tmp, prefix) + mystrlen(g_tmp),
- "%u.%u%s%s",
- kb >> sh,
- (((kb & 0x00FFFFFF) * 10) >> sh) % 10, // 0x00FFFFFF mask is used to
- // prevent overflow that causes
- // bad results
- GetNSISString(scalestr, scale),
- GetNSISString(byte, LANG_BYTE)
- );
-
- my_SetDialogItemText(m_curwnd,dlgItem,g_tmp);
-}
-
-static int NSISCALL _sumsecsfield(int idx)
-{
- int total = 0;
- int x = num_sections;
- section *s = g_sections;
- while (x--)
- {
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- if (s->flags & SF_SELECTED)
-#endif
- total += ((int *)s)[idx];
- s++;
- }
- return total;
-}
-
-#define sumsecsfield(x) _sumsecsfield(SECTION_OFFSET(x))
-
-static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- static int dontsetdefstyle;
- page *thispage = g_this_page;
- char *dir = g_usrvars[thispage->parms[4]];
- int browse_text = thispage->parms[3];
- if (uMsg == WM_NOTIFY_INIGO_MONTOYA)
- {
- GetUIText(IDC_DIR,dir);
- validate_filename(dir);
-#ifdef NSIS_CONFIG_LOG
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
- build_g_logfile();
-#endif
- if (GetUIItem(IDC_CHECK1) != NULL)
- log_dolog = IsDlgButtonChecked(hwndDlg,IDC_CHECK1);
-#endif
- }
- if (uMsg == WM_INITDIALOG)
- {
- HWND hDir = GetUIItem(IDC_DIR);
-
-#ifdef NSIS_CONFIG_LOG
- if (GetAsyncKeyState(VK_SHIFT)&0x8000)
- {
- HWND h=GetUIItem(IDC_CHECK1);
- SetUITextFromLang(IDC_CHECK1,LANG_LOG_INSTALL_PROCESS);
- ShowWindow(h,SW_SHOWNA);
- }
-#endif
- if (validpathspec(dir) && !skip_root(dir))
- addtrailingslash(dir);
-
- // workaround for bug #1209843
- //
- // m_curwnd is only updated once WM_INITDIALOG returns.
- // my_SetWindowText triggers an EN_CHANGE message that
- // triggers a WM_IN_UPDATEMSG message that uses m_curwnd
- // to get the selected directory (GetUIText).
- // because m_curwnd is still outdated, dir varialble is
- // filled with an empty string. by default, dir points
- // to $INSTDIR.
- //
- // to solve this, m_curwnd is manually set to the correct
- // window handle.
-
- m_curwnd=hwndDlg;
-
- my_SetWindowText(hDir,dir);
- SetUITextFromLang(IDC_BROWSE,this_page->parms[2]);
- SetUITextFromLang(IDC_SELDIRTEXT,this_page->parms[1]);
- SetActiveCtl(hDir);
-
- {
- typedef HRESULT (WINAPI *SHAutoCompletePtr)(HWND, DWORD);
- SHAutoCompletePtr fSHAutoComplete;
- fSHAutoComplete = (SHAutoCompletePtr) myGetProcAddress(MGA_SHAutoComplete);
- if (fSHAutoComplete)
- {
- fSHAutoComplete(hDir, SHACF_FILESYSTEM);
- }
- }
- }
- if (uMsg == WM_COMMAND)
- {
- int id=LOWORD(wParam);
- if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE)
- {
- uMsg = WM_IN_UPDATEMSG;
- }
- if (id == IDC_BROWSE)
- {
- static char bt[NSIS_MAX_STRLEN];
- BROWSEINFO bi = {0,};
- ITEMIDLIST *idlist;
- bi.hwndOwner = hwndDlg;
- bi.pszDisplayName = g_tmp;
- bi.lpfn = BrowseCallbackProc;
- bi.lParam = (LPARAM)dir;
- bi.lpszTitle = GetNSISString(bt, browse_text);
- bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
- idlist = SHBrowseForFolder(&bi);
- if (idlist)
- {
- // free idlist
- CoTaskMemFree(idlist);
-
- addtrailingslash(dir);
-
- if (g_header->install_directory_auto_append &&
- dir == state_install_directory) // only append to $INSTDIR (bug #1174184)
- {
- const char *post_str = ps_tmpbuf;
- GetNSISStringTT(g_header->install_directory_auto_append);
- // display name gives just the folder name
- if (lstrcmpi(post_str, g_tmp))
- {
- mystrcat(dir, post_str);
- }
- }
-
- dontsetdefstyle++;
- SetUITextNT(IDC_DIR,dir);
- }
- else
- {
- uMsg = WM_IN_UPDATEMSG;
- }
- }
- }
- if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START)
- {
- static char s[NSIS_MAX_STRLEN];
- char *p;
- int error = 0;
- int available_set = 0;
- unsigned total, available = 0xFFFFFFFF;
-
- GetUIText(IDC_DIR,dir);
- if (!is_valid_instpath(dir))
- error = NSIS_INSTDIR_INVALID;
-
- mystrcpy(s,dir);
- p=skip_root(s);
- if (p)
- *p=0;
-
- // Test for and use the GetDiskFreeSpaceEx API
- {
- BOOL (WINAPI *GDFSE)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) =
- myGetProcAddress(MGA_GetDiskFreeSpaceExA);
- if (GDFSE)
- {
- ULARGE_INTEGER available64;
- ULARGE_INTEGER a, b;
- if (GDFSE(s, &available64, &a, &b))
- {
-#ifndef _NSIS_NO_INT64_SHR
- available = (int)(available64.QuadPart >> 10);
-#else
- available = (int)(Int64ShrlMod32(available64.QuadPart, 10));
-#endif
- available_set++;
- }
- }
- }
-
- if (!available_set)
- {
- // GetDiskFreeSpaceEx is not available
- DWORD spc, bps, fc, tc;
- if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc))
- {
- available = (int)MulDiv(bps * spc, fc, 1 << 10);
- available_set++;
- }
- }
-
- total = (unsigned) sumsecsfield(size_kb);
-
- if (available < total)
- error = NSIS_INSTDIR_NOT_ENOUGH_SPACE;
-
- if (LANG_STR_TAB(LANG_SPACE_REQ)) {
- SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,total);
- if (available_set)
- SetSizeText(IDC_SPACEAVAILABLE,LANG_SPACE_AVAIL,available);
- else
- SetUITextNT(IDC_SPACEAVAILABLE,"");
- }
-
- g_exec_flags.instdir_error = error;
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (!error)
- error = ExecuteCallbackFunction(CB_ONVERIFYINSTDIR);
-#endif
-
- if (thispage->flags & PF_DIR_NO_BTN_DISABLE)
- error = 0;
-
- EnableNext(!error);
- if (!error && !dontsetdefstyle)
- SetNextDef();
- dontsetdefstyle = 0;
- }
- return HandleStaticBkColor();
-}
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
-
-static void FORCE_INLINE NSISCALL RefreshComponents(HWND hwTree, HTREEITEM *items)
-{
- TVITEM item;
- int i, flags, state;
- section *sec;
-
- item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED | TVIS_BOLD;
-
- for (i = 0, sec = g_sections; i < num_sections; i++, sec++)
- {
- if (!items[i])
- {
- continue;
- }
-
- flags = sec->flags;
-
- item.hItem = items[i];
-
- item.mask = TVIF_STATE;
-
- if (flags & SF_NAMECHG)
- {
- item.mask |= TVIF_TEXT;
- item.pszText = sec->name;
- sec->flags &= ~SF_NAMECHG;
- }
-
- if (flags & SF_PSELECTED)
- {
- state = 3;
- }
- else
- {
- state = 1 + (flags & SF_SELECTED); // SF_SELECTED == 1
- if (flags & SF_RO) state += 3;
- }
-
- item.state = (flags & SF_BOLD) << 1; // (SF_BOLD << 1) == 16 == TVIS_BOLD
- item.state |= flags & SF_EXPAND; // TVIS_EXPANDED == SF_EXPAND
- item.state |= INDEXTOSTATEIMAGEMASK(state);
-
- // TVE_COLLAPSE = 1, TVE_EXPAND = 2
- TreeView_Expand(hwTree, item.hItem, TVE_COLLAPSE + ((flags & SF_EXPAND) / SF_EXPAND));
-
- TreeView_SetItem(hwTree, &item);
- }
-
- // workaround for bug #1397031
- //
- // windows 95 doesn't erase the background of the state image
- // before it draws a new one. because of this parts of the old
- // state image will show where the new state image is masked.
- //
- // to solve this, the following line forces the background to
- // be erased. sadly, this redraws the entire control. it might
- // be a good idea to figure out where the state images are and
- // redraw only those.
-
- InvalidateRect(hwTree, NULL, TRUE);
-}
-
-int NSISCALL TreeGetSelectedSection(HWND tree, BOOL mouse)
-{
- HTREEITEM hItem = TreeView_GetSelection(tree);
- TVITEM item;
-
- if (mouse)
- {
- TVHITTESTINFO ht;
- DWORD dwpos = GetMessagePos();
-
- ht.pt.x = GET_X_LPARAM(dwpos);
- ht.pt.y = GET_Y_LPARAM(dwpos);
- ScreenToClient(tree, &ht.pt);
-
- TreeView_HitTest(tree, &ht);
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
- if (!(ht.flags & TVHT_ONITEMSTATEICON))
-#else
- if (!(ht.flags & (TVHT_ONITEMSTATEICON|TVHT_ONITEMLABEL|TVHT_ONITEMRIGHT|TVHT_ONITEM)))
-#endif
- return -1;
-
- hItem = ht.hItem;
- }
-
- item.mask = TVIF_PARAM;
- item.hItem = hItem;
- TreeView_GetItem(tree, &item);
-
- return (int) item.lParam;
-}
-
-static LONG oldTreeWndProc;
-static LPARAM last_selected_tree_item;
-static DWORD WINAPI newTreeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- if (uMsg == WM_CHAR && wParam == VK_SPACE) {
- NotifyCurWnd(WM_TREEVIEW_KEYHACK);
- return 0;
- }
-#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT)
-#ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
- if (uMsg == WM_MOUSEMOVE) {
- if (IsWindowVisible(hwnd)) {
- lParam = TreeGetSelectedSection(hwnd, TRUE);
- uMsg = WM_NOTIFY_SELCHANGE;
- }
- }
-#endif
- if (uMsg == WM_NOTIFY_SELCHANGE) {
- if (last_selected_tree_item != lParam)
- {
- last_selected_tree_item = lParam;
-
- mystrcpy(g_tmp, g_usrvars[0]);
-
- myitoa(g_usrvars[0], lParam);
-
- ExecuteCallbackFunction(CB_ONMOUSEOVERSECTION);
-
- mystrcpy(g_usrvars[0], g_tmp);
- }
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT
- return CallWindowProc((WNDPROC)oldTreeWndProc,hwnd,uMsg,wParam,lParam);
-}
-
-static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- static HTREEITEM *hTreeItems;
- static HIMAGELIST hImageList;
- HWND hwndCombo1 = GetUIItem(IDC_COMBO1);
- HWND hwndTree1 = GetUIItem(IDC_TREE1);
- extern HWND g_SectionHack;
- section *sections=g_sections;
- int *install_types=g_header->install_types;
- if (uMsg == WM_INITDIALOG)
- {
- int doLines=0;
- HTREEITEM Par;
- HBITMAP hBMcheck1;
- int x, lastGoodX, i, noCombo=2;
-
- g_SectionHack=hwndDlg;
-
- hTreeItems=(HTREEITEM*)GlobalAlloc(GPTR,sizeof(HTREEITEM)*num_sections);
-
- hBMcheck1=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
-
- last_selected_tree_item=-1;
- oldTreeWndProc=SetWindowLong(hwndTree1,GWL_WNDPROC,(long)newTreeWndProc);
-
- hImageList = ImageList_Create(16,16, ILC_COLOR32|ILC_MASK, 6, 0);
- ImageList_AddMasked(hImageList,hBMcheck1,RGB(255,0,255));
-
- TreeView_SetImageList(hwndTree1, hImageList, TVSIL_STATE);
-
- if (TreeView_GetItemHeight(hwndTree1) < 16)
- TreeView_SetItemHeight(hwndTree1, 16);
-
- DeleteObject(hBMcheck1);
-
- for (i = 0; i < NSIS_MAX_INST_TYPES+1; i++)
- {
- if (install_types[i])
- {
- int j;
- if (i != NSIS_MAX_INST_TYPES) noCombo = 0;
- j=SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetNSISStringTT(install_types[i]));
- SendMessage(hwndCombo1,CB_SETITEMDATA,j,i);
- }
- }
-
- SetUITextFromLang(IDC_TEXT1,this_page->parms[1+noCombo]);
- SetUITextFromLang(IDC_TEXT2,this_page->parms[2+noCombo]);
-
- Par=NULL;
-
- for (lastGoodX = x = 0; x < num_sections; x ++)
- {
- section *sec=sections+x;
-
- if (sec->name[0])
- {
- TVINSERTSTRUCT tv;
-
- tv.hParent = Par;
- tv.hInsertAfter = TVI_LAST;
- tv.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
- tv.item.stateMask = TVIS_EXPANDED;
- tv.item.lParam = x;
- tv.item.pszText = sec->name;
-
- tv.item.state = sec->flags & SF_EXPAND; // TVIS_EXPANDED == SF_EXPAND
-
- if (sec->flags & SF_SECGRP)
- {
- tv.item.mask |= TVIF_CHILDREN;
- tv.item.cChildren = 1;
- Par = hTreeItems[x] = TreeView_InsertItem(hwndTree1, &tv);
- doLines = 1;
- }
- else if (sec->flags & SF_SECGRPEND)
- {
- Par = TreeView_GetParent(hwndTree1, Par);
- }
- else
- {
- lastGoodX = x;
- hTreeItems[x] = TreeView_InsertItem(hwndTree1, &tv);
- }
- }
- }
-
- if (!doLines)
- {
- SetWindowLong(hwndTree1,GWL_STYLE,GetWindowLong(hwndTree1,GWL_STYLE)&~(TVS_LINESATROOT));
- }
-
- if (!noCombo)
- {
- ShowWindow(hwndCombo1, SW_SHOW);
- SetActiveCtl(hwndCombo1);
- }
- else
- SetActiveCtl(hwndTree1);
- }
-
- if (uMsg == WM_NOTIFY_START)
- {
- wParam = 0;
- lParam = 1;
- uMsg = WM_IN_UPDATEMSG;
- }
-
- if (uMsg == WM_NOTIFY || uMsg == WM_TREEVIEW_KEYHACK)
- {
- LPNMHDR lpnmh = (LPNMHDR) lParam;
- if (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->idFrom == IDC_TREE1)
- {
- if (!(g_flags&CH_FLAGS_NO_CUSTOM) && (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->code == NM_CLICK))
- {
- int secid = TreeGetSelectedSection(hwndTree1, uMsg != WM_TREEVIEW_KEYHACK);
-
- if (secid >= 0)
- {
- int flags = sections[secid].flags;
-
- if ((flags & SF_RO) == 0)
- {
- if ((flags & SF_PSELECTED))
- {
- flags ^= SF_TOGGLED;
-
- if (flags & SF_TOGGLED)
- {
- flags |= SF_SELECTED;
- }
- else
- {
- flags &= ~SF_SELECTED;
- }
- }
- else
- {
- flags ^= SF_SELECTED;
- }
-
- sections[secid].flags = flags;
-
- SectionFlagsChanged(secid);
-
- wParam = 1;
- lParam = !(g_flags & CH_FLAGS_COMP_ONLY_ON_CUSTOM);
- uMsg = WM_IN_UPDATEMSG;
- }
- } // was valid click
- } // was click or hack
-#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT)
- if (lpnmh)
- {
- if (lpnmh->code == TVN_SELCHANGED)
- {
- SendMessage(hwndTree1, WM_NOTIFY_SELCHANGE, 0, ((LPNMTREEVIEW)lpnmh)->itemNew.lParam);
- }
- if (lpnmh->code == TVN_ITEMEXPANDED)
- {
- LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lpnmh;
- if (pnmtv->action == TVE_EXPAND)
- sections[pnmtv->itemNew.lParam].flags |= SF_EXPAND;
- else
- sections[pnmtv->itemNew.lParam].flags &= ~SF_EXPAND;
- }
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT
- }
- }
-
- if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_COMBO1 && HIWORD(wParam) == CBN_SELCHANGE)
- {
- int t = SendMessage(hwndCombo1,CB_GETCURSEL,0,0);
- if (t != CB_ERR)
- {
- int whichcfg = SendMessage(hwndCombo1, CB_GETITEMDATA, t, 0);
-
- if (whichcfg == CB_ERR || !install_types[whichcfg])
- whichcfg = NSIS_MAX_INST_TYPES;
-
- SetInstType(whichcfg);
-
- SendMessage(hwndDlg, WM_NOTIFY_INSTTYPE_CHANGED, 0, whichcfg);
-
- wParam = 1;
- lParam = 0;
- uMsg = WM_IN_UPDATEMSG;
- }
- }
-
- if (uMsg == WM_MOUSEMOVE)
- {
- SendMessage(hwndTree1, WM_MOUSEMOVE, 0, 0);
- }
-
- if (uMsg == WM_NOTIFY_INIGO_MONTOYA)
- {
- if (hImageList) ImageList_Destroy(hImageList);
- if (hTreeItems) GlobalFree(hTreeItems);
- hImageList = NULL;
- hTreeItems = NULL;
- g_SectionHack = NULL;
- }
-
- if (uMsg == WM_IN_UPDATEMSG)
- {
- RefreshSectionGroups();
-
-#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_COMPONENTPAGE)
- if (wParam)
- {
- ExecuteCallbackFunction(CB_ONSELCHANGE);
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_COMPONENTPAGE
-
- if (lParam)
- {
- int i, cbi;
- int inst_type = GetInstType(hTreeItems);
- SetInstType(inst_type);
-
- for (i = 0, cbi = 0; i < inst_type; i++)
- {
- if (install_types[i])
- {
- cbi++;
- }
- }
-
- SendMessage(hwndCombo1, CB_SETCURSEL, cbi, 0);
-
- lParam = inst_type;
- uMsg = WM_NOTIFY_INSTTYPE_CHANGED;
- }
-
- RefreshSectionGroups();
- RefreshComponents(hwndTree1, hTreeItems);
-
- if (LANG_STR_TAB(LANG_SPACE_REQ)) {
- SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,sumsecsfield(size_kb));
- }
- }
-
- if (uMsg == WM_NOTIFY_INSTTYPE_CHANGED)
- {
- if (g_flags & CH_FLAGS_COMP_ONLY_ON_CUSTOM)
- {
- int c = (lParam == NSIS_MAX_INST_TYPES ? 1 : 0) << 3;// SW_SHOWNA=8, SW_HIDE=0
- ShowWindow(hwndTree1, c);
- ShowWindow(GetUIItem(IDC_TEXT2), c);
- }
- }
-
- return HandleStaticBkColor();
-}
-#endif//NSIS_CONFIG_COMPONENTPAGE
-
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-
-void NSISCALL update_status_text(int strtab, const char *text) {
- static char tmp[NSIS_MAX_STRLEN*2];
- LVITEM new_item;
- HWND linsthwnd = insthwnd;
- if (linsthwnd)
- {
- int updateflag = g_exec_flags.status_update;
- int tmplen;
-
- if (!(updateflag & 1))
- GetNSISString(tmp, strtab);
-
- tmplen = mystrlen(tmp);
-
- if (text)
- {
- if (tmplen + mystrlen(text) >= sizeof(tmp)) return;
- mystrcat(tmp, text);
- }
-
- if ((updateflag & 4) == 0) my_SetWindowText(insthwnd2, tmp);
- if ((updateflag & 2) == 0)
- {
- new_item.mask = LVIF_TEXT;
- new_item.pszText = tmp;
- new_item.iItem = ListView_GetItemCount(linsthwnd) - (updateflag & 1);
- new_item.iSubItem = 0;
- // LVM_INSERTITEM - LVM_SETITEM = 1
- SendMessage(linsthwnd, LVM_INSERTITEM - (updateflag & 1), 0, (LPARAM) &new_item);
- ListView_EnsureVisible(linsthwnd, new_item.iItem, 0);
- }
-
- if (updateflag & 1)
- tmp[tmplen] = 0;
- }
-}
-
-static DWORD WINAPI install_thread(LPVOID p)
-{
- int m_inst_sec=num_sections;
- HWND progresswnd = (HWND)p;
- section *s = g_sections;
-
-#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
- {
- extern HRESULT g_hres;
- g_hres|=OleInitialize(NULL);
- }
-#endif
-
- // workaround for bug #1400995
- //
- // for an unexplained reason, MessageBox with MB_TOPMOST
- // will fail, if no other messages were sent from this
- // thread to the GUI thread before it.
- //
- // the source of the problem couldn't be found, so a
- // WM_NULL is sent to work around it.
-
- NotifyCurWnd(WM_NULL);
-
- while (m_inst_sec--)
- {
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- if (s->flags&SF_SELECTED)
-#endif
- {
- log_printf2("Section: \"%s\"",s->name);
- if (ExecuteCodeSegment(s->code,progresswnd))
- {
- g_exec_flags.abort++;
- break;
- }
- }
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- else
- {
- log_printf2("Skipping section: \"%s\"",s->name);
- }
-#endif
- s++;
- }
- NotifyCurWnd(WM_NOTIFY_INSTPROC_DONE);
-
-#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
- OleUninitialize();
-#endif
-
- return g_exec_flags.abort;
-}
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-
-static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- HWND linsthwnd=insthwnd;
- if (uMsg == WM_INITDIALOG)
- {
- RECT r;
- LVCOLUMN lvc = {LVCF_WIDTH, 0, -1, 0, 0, -1};
- int lb_bg=g_header->lb_bg,lb_fg=g_header->lb_fg;
-
- insthwndbutton=GetUIItem(IDC_SHOWDETAILS);
- insthwnd2=GetUIItem(IDC_INTROTEXT);
- linsthwnd=insthwnd=GetUIItem(IDC_LIST1);
-
- SetActiveCtl(insthwndbutton);
-
- progress_bar_len=sumsecsfield(code_size);
- progress_bar_pos=0;
-
- log_printf3("New install of \"%s\" to \"%s\"",GetNSISStringTT(LANG_NAME),state_install_directory);
-
- GetClientRect(linsthwnd, &r);
- lvc.cx = r.right - GetSystemMetrics(SM_CXHSCROLL);
- ListView_InsertColumn(linsthwnd, 0, &lvc);
-
- ListView_SetExtendedListViewStyleEx(linsthwnd, LVS_EX_LABELTIP, LVS_EX_LABELTIP);
- if (lb_bg >= 0) {
- ListView_SetBkColor(linsthwnd, lb_bg);
- ListView_SetTextBkColor(linsthwnd, lb_bg);
- }
- if (lb_fg >= 0) {
- ListView_SetTextColor(linsthwnd, lb_fg);
- }
- SetUITextFromLang(IDC_SHOWDETAILS,this_page->parms[1]);
- if (g_flags&(CH_FLAGS_DETAILS_SHOWDETAILS|CH_FLAGS_DETAILS_NEVERSHOW))
- {
- ShowWindow(insthwndbutton,SW_HIDE);
- if (!(g_flags&CH_FLAGS_DETAILS_NEVERSHOW)) ShowWindow(linsthwnd,SW_SHOWNA);
- else insthwndbutton=NULL;
- SetActiveCtl(insthwnd2);
- }
-
- {
- HWND progresswnd=GetUIItem(IDC_PROGRESS);
- SendMessage(progresswnd,PBM_SETRANGE,0,MAKELPARAM(0,30000));
- if (g_flags&CH_FLAGS_PROGRESS_COLORED)
- {
- SendMessage(progresswnd,PBM_SETBARCOLOR,0,lb_fg);
- SendMessage(progresswnd,PBM_SETBKCOLOR,0,lb_bg);
- }
- }
-
- return FALSE;
- }
- if (uMsg == WM_NOTIFY_START) {
- DWORD id;
- CloseHandle(CreateThread(NULL,0,install_thread,GetUIItem(IDC_PROGRESS),0,&id));
- }
- if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_SHOWDETAILS)
- {
- ShowWindow(insthwndbutton,SW_HIDE);
- ShowWindow(linsthwnd,SW_SHOWNA);
- SetActiveCtl(linsthwnd);
- }
- if (uMsg == WM_NOTIFY_INSTPROC_DONE)
- {
- if (g_quit_flag)
- {
- m_retcode=2;
- outernotify(NOTIFY_BYE_BYE);
- }
- else
- {
- ShowWindow(g_hwnd,SW_SHOWNA);
- if (!g_exec_flags.abort)
- update_status_text(g_this_page->parms[2],0);
- outernotify(1);
- }
- }
- //>>>Ximon Eighteen aka Sunjammer 30th August 2002
- //+++Popup "Copy Details To Clipboard" menu when RMB clicked in DetailView
- if (uMsg == WM_CONTEXTMENU && wParam == (WPARAM) linsthwnd)
- {
- int count = ListView_GetItemCount(linsthwnd);
- if (count > 0)
- {
- HMENU menu = CreatePopupMenu();
- POINT pt;
- AppendMenu(menu,MF_STRING,1,GetNSISStringTT(LANG_COPYDETAILS));
- if (lParam == ((UINT)-1))
- {
- RECT r;
- GetWindowRect(linsthwnd, &r);
- pt.x = r.left;
- pt.y = r.top;
- }
- else
- {
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- }
- if (1==TrackPopupMenu(
- menu,
- TPM_NONOTIFY|TPM_RETURNCMD,
- pt.x,
- pt.y,
- 0,hwndDlg,0))
- {
- int i,total = 1; // 1 for the null char
- LVITEM item;
- HGLOBAL memory;
- LPTSTR ptr;//,endPtr;
-
- // 1st pass - determine clipboard memory required.
- item.iSubItem = 0;
- item.pszText = g_tmp;
- item.cchTextMax = sizeof(g_tmp) - 1;
- i = count;
- while (i--)
- // Add 2 for the CR/LF combination that must follow every line.
- total += 2+SendMessage(linsthwnd,LVM_GETITEMTEXT,i,(LPARAM)&item);
-
- // 2nd pass - store detail view strings on the clipboard
- // Clipboard MSDN docs say mem must be GMEM_MOVEABLE
- OpenClipboard(0);
- EmptyClipboard();
- memory = GlobalAlloc(GHND,total);
- ptr = GlobalLock(memory);
- //endPtr = ptr+total-2; // -2 to allow for CR/LF
- i = 0;
- do {
- item.pszText = ptr;
- ptr += SendMessage(linsthwnd,LVM_GETITEMTEXT,i,(LPARAM)&item);
- *(WORD*)ptr = CHAR2_TO_WORD('\r','\n');
- ptr+=2;
- } while (++i < count);
- // memory is auto zeroed when allocated with GHND - *ptr = 0;
- GlobalUnlock(memory);
- SetClipboardData(CF_TEXT,memory);
- CloseClipboard();
- }
- }
- return FALSE;
- }
- //<<<
- return HandleStaticBkColor();
-}
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
+/* + * Ui.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft, Jeff Doozan and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include <windowsx.h> +#include <shlobj.h> +#include <shellapi.h> +#include <shlwapi.h> + +#include "../Platform.h" + +#include "resource.h" + +#include "fileform.h" +#include "state.h" +#include "util.h" +#include "ui.h" +#include "exec.h" +#include "lang.h" +#include "components.h" + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +HICON g_hIcon; +#endif + +int dlg_offset; +int ui_dlg_visible=0; // At start main window is not visible +int g_quit_flag; // set when Quit has been called (meaning bail out ASAP) + +#if NSIS_MAX_INST_TYPES > 32 || NSIS_MAX_INST_TYPES < 1 +#error invalid value for NSIS_MAX_INST_TYPES +#endif + +int progress_bar_pos, progress_bar_len; + +#if NSIS_MAX_STRLEN < 1024 +static char g_tmp[4096]; +#else +static char g_tmp[NSIS_MAX_STRLEN * 4]; +#endif + +static int m_page=-1,m_retcode,m_delta; +static page *g_this_page; + +#define NOTIFY_BYE_BYE 'x' + +static void NSISCALL outernotify(int delta) { + if (delta==NOTIFY_BYE_BYE) + g_quit_flag++; + SendMessage(g_hwnd,WM_NOTIFY_OUTER_NEXT,(WPARAM)delta,0); +} + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); +#ifdef NSIS_CONFIG_LICENSEPAGE +static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif +static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +static DWORD WINAPI install_thread(LPVOID p); + +void NSISCALL CleanUp(); + +HWND insthwnd, insthwnd2, insthwndbutton; + +HWND m_curwnd; +static HWND m_bgwnd, m_hwndOK, m_hwndCancel; + +static BOOL NSISCALL SetDlgItemTextFromLang_(HWND dlg, int id, int lid) { + return my_SetDialogItemText(dlg,id+1000,GetNSISStringTT(lid)); +} + +static void NSISCALL SetNextDef() +{ + SendMessage(g_exec_flags.abort ? m_hwndCancel : m_hwndOK, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); +} + +static void NSISCALL EnableNext(BOOL e) +{ + EnableWindow(m_hwndOK, e); +} + +static void NSISCALL SetActiveCtl(HWND hCtl) +{ + SendMessage(g_hwnd, WM_NEXTDLGCTL, (WPARAM) hCtl, TRUE); +} + +static void NSISCALL NotifyCurWnd(UINT uNotifyCode) +{ + if (m_curwnd) + SendMessage(m_curwnd, uNotifyCode, 0, 0); +} + +#define SetDlgItemTextFromLang(dlg,id,lid) SetDlgItemTextFromLang_(dlg,(id)-1000,lid) + +#define SetUITextFromLang(it,la) SetDlgItemTextFromLang_(hwndDlg,(it)-1000,la) +#define SetUITextNT(it,text) my_SetDialogItemText(hwndDlg,it,text) +#define GetUIText(it,s) my_GetDialogItemText(it,s) +#define GetUIItem(it) GetDlgItem(hwndDlg,it) + +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT +#define HandleStaticBkColor() _HandleStaticBkColor(uMsg, wParam, lParam) +static BOOL NSISCALL _HandleStaticBkColor(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if ((uMsg - WM_CTLCOLOREDIT) <= (WM_CTLCOLORSTATIC - WM_CTLCOLOREDIT)) + { + ctlcolors *c = (ctlcolors *)GetWindowLong((HWND)lParam, GWL_USERDATA); + + if (c) { + COLORREF text; + LOGBRUSH lh; + + text = c->text; + if (c->flags & CC_TEXT_SYS) + text = GetSysColor(text); + if (c->flags & CC_TEXT) + SetTextColor((HDC)wParam, text); + + SetBkMode((HDC)wParam, c->bkmode); + + lh.lbColor = c->bkc; + if (c->flags & CC_BK_SYS) + lh.lbColor = GetSysColor(lh.lbColor); + if (c->flags & CC_BK) + SetBkColor((HDC)wParam, lh.lbColor); + + if (c->flags & CC_BKB) + { + lh.lbStyle = c->lbStyle; + if (c->bkb) + DeleteObject(c->bkb); + c->bkb = CreateBrushIndirect(&lh); + } + + return (BOOL)c->bkb; + } + } + return 0; +} +#else +#define HandleStaticBkColor() 0 +#endif//!NSIS_CONFIG_ENHANCEDUI_SUPPORT + +#ifdef NSIS_CONFIG_LOG +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) +void NSISCALL build_g_logfile() +{ + mystrcat(addtrailingslash(mystrcpy(g_log_file,state_install_directory)),"install.log"); +} +#endif +#endif + +int *cur_langtable; + +static void NSISCALL set_language() +{ + LANGID lang_mask=(LANGID)~0; + LANGID lang=myatoi(state_language); + char *language_table=0; + int lang_num; + int *selected_langtable=0; + +lang_again: + lang_num=g_blocks[NB_LANGTABLES].num; + while (lang_num--) { + language_table=((char*)g_blocks[NB_LANGTABLES].offset)+lang_num*g_header->langtable_size; + if (!((lang ^ *(LANGID*)language_table) & lang_mask)) { + dlg_offset=*(int*)(language_table+sizeof(LANGID)); + g_exec_flags.rtl=*(int*)(language_table+sizeof(LANGID)+sizeof(int)); + selected_langtable=(int*)(language_table+sizeof(LANGID)+2*sizeof(int)); + break; + } + } + if (!selected_langtable) { + if (lang_mask == (LANGID)~0) + lang_mask=0x3ff; // primary lang + else // we already tried once and we still don't have a language table + lang_mask=0; // first lang + goto lang_again; + } + + cur_langtable = selected_langtable; + + myitoa(state_language, *(LANGID*)language_table); + { + char *caption = GetNSISString(g_caption,LANG_CAPTION); +#ifdef NSIS_SUPPORT_BGBG + my_SetWindowText(m_bgwnd, caption); +#endif + } + + // reload section names + { + section *sec = g_sections; + int x = num_sections; + + while (x--) + { + if (sec->name_ptr) + { + GetNSISString(sec->name, sec->name_ptr); + } + sec++; + } + } +} + +FORCE_INLINE int NSISCALL ui_doinstall(void) +{ + header *header = g_header; + static WNDCLASS wc; // richedit subclassing and bgbg creation + + // detect default language + // more information at: + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_0xrn.asp + + LANGID (WINAPI *GUDUIL)(); + + GUDUIL = myGetProcAddress(MGA_GetUserDefaultUILanguage); + if (GUDUIL) + { + // Windows ME/2000+ + myitoa(state_language, GUDUIL()); + } + else + { + static const char reg_9x_locale[] = "Control Panel\\Desktop\\ResourceLocale"; + static const char reg_nt_locale_key[] = ".DEFAULT\\Control Panel\\International"; + const char *reg_nt_locale_val = ®_9x_locale[30]; // = "Locale" with opt + + *(DWORD*)state_language = CHAR4_TO_DWORD('0', 'x', 0, 0); + + { + // Windows 9x + myRegGetStr(HKEY_CURRENT_USER, reg_9x_locale, NULL, g_tmp, 0); + } + + if (!g_tmp[0]) + { + // Windows NT + // This key exists on 9x as well, so it's only read if ResourceLocale wasn't found + myRegGetStr(HKEY_USERS, reg_nt_locale_key, reg_nt_locale_val, g_tmp, 0); + } + + mystrcat(state_language, g_tmp); + } + + // set default language + set_language(); + + // initialize auto close flag + g_exec_flags.autoclose=g_flags&CH_FLAGS_AUTO_CLOSE; + + // read install directory from registry + if (!is_valid_instpath(state_install_directory)) + { + if (header->install_reg_key_ptr) + { + myRegGetStr( + (HKEY)header->install_reg_rootkey, + GetNSISStringNP(header->install_reg_key_ptr), + GetNSISStringNP(header->install_reg_value_ptr), + ps_tmpbuf, + 0 + ); + if (ps_tmpbuf[0]) + { + char *p=ps_tmpbuf; + char *e; + if (p[0]=='\"') + { + char *p2; + p++; + p2 = findchar(p, '"'); + *p2 = 0; + } + // p is the path now, check for .exe extension + + e=p+mystrlen(p)-4; + if (e > p) + { + // if filename ends in .exe, and is not a directory, remove the filename + if (!lstrcmpi(e, ".exe")) // check extension + { + DWORD d; + d=GetFileAttributes(p); + if (d == INVALID_FILE_ATTRIBUTES || !(d&FILE_ATTRIBUTE_DIRECTORY)) + { + // if there is no back-slash, the string will become empty, but that's ok because + // it would make an invalid instdir anyway + trimslashtoend(p); + } + } + } + + mystrcpy(state_install_directory,addtrailingslash(p)); + } + } + } + if (!is_valid_instpath(state_install_directory)) + { + GetNSISString(state_install_directory,header->install_directory_ptr); + } + +#ifdef NSIS_CONFIG_LOG + if (g_flags & CH_FLAGS_SILENT_LOG && !g_is_uninstaller) + { +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) + build_g_logfile(); +#endif + log_dolog=1; + } +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + g_hIcon=LoadImage(g_hInstance,MAKEINTRESOURCE(IDI_ICON2),IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_SHARED); +#ifdef NSIS_SUPPORT_BGBG + if (header->bg_color1 != -1) + { + DWORD cn = CHAR4_TO_DWORD('_', 'N', 'b', 0); + RECT vp; + extern LRESULT CALLBACK BG_WndProc(HWND, UINT, WPARAM, LPARAM); + wc.lpfnWndProc = BG_WndProc; + wc.hInstance = g_hInstance; + wc.hIcon = g_hIcon; + //wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.lpszClassName = (LPCSTR)&cn; + + if (!RegisterClass(&wc)) return 0; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &vp, 0); + + m_bgwnd = CreateWindowEx(WS_EX_TOOLWINDOW,(LPCSTR)&cn,0,WS_POPUP, + vp.left,vp.top,vp.right-vp.left,vp.bottom-vp.top,0,NULL,g_hInstance,NULL); + } + +#endif//NSIS_SUPPORT_BGBG + +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // Select language + if (ExecuteCallbackFunction(CB_ONINIT)) return 2; + set_language(); +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (!g_exec_flags.silent) +#endif//NSIS_CONFIG_SILENT_SUPPORT + { +#ifdef NSIS_SUPPORT_BGBG + ShowWindow(m_bgwnd, SW_SHOW); +#endif//NSIS_SUPPORT_BGBG + +#ifdef NSIS_CONFIG_LICENSEPAGE + { // load richedit DLL + static const char riched20[]="RichEd20"; + static const char riched32[]="RichEd32"; + static const char richedit20a[]="RichEdit20A"; + static const char richedit[]="RichEdit"; + if (!LoadLibrary(riched20)) + { + LoadLibrary(riched32); + } + + // make richedit20a point to RICHEDIT + if (!GetClassInfo(NULL,richedit20a,&wc)) + { + GetClassInfo(NULL,richedit,&wc); + wc.lpszClassName = richedit20a; + RegisterClass(&wc); + } + } +#endif + + { + int ret=DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_INST+dlg_offset),0,DialogProc); +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) + ExecuteCallbackFunction(CB_ONGUIEND); +#endif + return ret; + } + } +#endif//NSIS_CONFIG_VISIBLE_SUPPORT +#ifdef NSIS_CONFIG_SILENT_SUPPORT +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + else +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + { + if (install_thread(NULL)) + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (!g_quit_flag) ExecuteCallbackFunction(CB_ONINSTFAILED); +#endif//NSIS_SUPPORT_CODECALLBACKS + return 2; + } +#ifdef NSIS_SUPPORT_CODECALLBACKS + ExecuteCallbackFunction(CB_ONINSTSUCCESS); +#endif//NSIS_SUPPORT_CODECALLBACKS + + return 0; + } +#endif//NSIS_CONFIG_SILENT_SUPPORT +} + + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +static int CALLBACK WINAPI BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + if (uMsg==BFFM_INITIALIZED) + { + my_GetDialogItemText(IDC_DIR,(char*)lpData); + SendMessage(hwnd,BFFM_SETSELECTION,(WPARAM)1,lpData); + } + if (uMsg==BFFM_SELCHANGED) + { + SendMessage( + hwnd, + BFFM_ENABLEOK, + 0, + SHGetPathFromIDList((LPITEMIDLIST)lParam,(char*)lpData) +#ifdef NSIS_SUPPORT_CODECALLBACKS + && !ExecuteCallbackFunction(CB_ONVERIFYINSTDIR) +#endif + ); + } + return 0; +} + +BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_INITDIALOG || uMsg == WM_NOTIFY_OUTER_NEXT) + { + page *this_page; + static DLGPROC winprocs[]= + { +#ifdef NSIS_CONFIG_LICENSEPAGE + LicenseProc, +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + SelProc, +#endif + DirProc, + InstProc, +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + UninstProc +#endif + }; + + m_delta = wParam; + + if (uMsg == WM_INITDIALOG) + { + g_hwnd=hwndDlg; + m_hwndOK=GetDlgItem(hwndDlg,IDOK); + m_hwndCancel=GetDlgItem(hwndDlg,IDCANCEL); + SetDlgItemTextFromLang(hwndDlg,IDC_VERSTR,LANG_BRANDING); + SetClassLong(hwndDlg,GCL_HICON,(long)g_hIcon); + // use the following line instead of the above, if .rdata needs shirking + //SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)g_hIcon); +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) + g_quit_flag = ExecuteCallbackFunction(CB_ONGUIINIT); +#endif + //ShowWindow(hwndDlg, SW_SHOW); + m_delta = 1; + } + + this_page=g_pages+m_page; + + if (m_page>=0) { +#ifdef NSIS_SUPPORT_CODECALLBACKS + // Call leave function. If Abort used don't move to the next page. + // But if quit called we must exit now + if (m_delta==1) if (ExecuteCodeSegment(this_page->leavefunc,NULL)) { + SendMessage(m_curwnd, WM_IN_UPDATEMSG, 0, 1); + return !g_quit_flag; + } +#endif + + // if the last page was a custom page, wait for it to finish by itself. + // if it doesn't, it's a BAD plugin. + // plugins should react to WM_NOTIFY_OUTER_NEXT. + if (!this_page->dlg_id) return 0; + } + + NotifyCurWnd(WM_NOTIFY_INIGO_MONTOYA); + +nextPage: + m_page+=m_delta; + this_page+=m_delta; + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (m_page==g_blocks[NB_PAGES].num) ExecuteCallbackFunction(CB_ONINSTSUCCESS); +#endif//NSIS_SUPPORT_CODECALLBACKS + + if (g_quit_flag || (unsigned int)m_page >= (unsigned int)g_blocks[NB_PAGES].num) + { + DestroyWindow(m_curwnd); + g_hwnd = 0; + EndDialog(hwndDlg,m_retcode); + } + else + { + HWND hwndtmp; + + int pflags = this_page->flags; + + GetNSISString(state_click_next, this_page->clicknext); + SetDlgItemTextFromLang(hwndDlg, IDOK, this_page->next); + SetDlgItemTextFromLang(hwndDlg, IDC_BACK, this_page->back); + SetDlgItemTextFromLang(hwndDlg, IDCANCEL, this_page->cancel); + + hwndtmp = GetDlgItem(hwndDlg, IDC_BACK); + + if (g_exec_flags.abort) + { + pflags &= ~(PF_BACK_ENABLE | PF_NEXT_ENABLE); + pflags |= PF_CANCEL_ENABLE; + } + + ShowWindow(hwndtmp, pflags & PF_BACK_SHOW);// SW_HIDE = 0, PF_BACK_SHOW = SW_SHOWNA = 8 + EnableWindow(hwndtmp, pflags & PF_BACK_ENABLE); + EnableNext(pflags & PF_NEXT_ENABLE); + EnableWindow(m_hwndCancel, pflags & PF_CANCEL_ENABLE); + + if (pflags & PF_CANCEL_ENABLE) + EnableMenuItem(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); + else + EnableMenuItem(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); + + SendMessage(hwndtmp, BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + + if (g_exec_flags.abort) + { + SendMessage(hwndDlg, DM_SETDEFID, IDCANCEL, 0); + SetActiveCtl(m_hwndCancel); + } + else + { + SetActiveCtl(m_hwndOK); + } + + mystrcpy(g_tmp,g_caption); + GetNSISString(g_tmp+mystrlen(g_tmp),this_page->caption); + my_SetWindowText(hwndDlg,g_tmp); + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // custom page or user used abort in prefunc + if (ExecuteCodeSegment(this_page->prefunc, NULL) || !this_page->dlg_id) { + goto nextPage; + } +#endif //NSIS_SUPPORT_CODECALLBACKS + + if (this_page->wndproc_id != PWP_COMPLETED) + { + DestroyWindow(m_curwnd); + } + else { + if (!g_exec_flags.abort && g_exec_flags.autoclose) + goto nextPage; + // no need to go to skipPage because PWP_COMPLETED always follows PWP_INSTFILES + return FALSE; + } + + // update g_this_page for the dialog proc + g_this_page=this_page; + + if (this_page->dlg_id > 0) // NSIS page + { + m_curwnd=CreateDialogParam( + g_hInstance, + MAKEINTRESOURCE(this_page->dlg_id+dlg_offset), + hwndDlg,winprocs[this_page->wndproc_id],(LPARAM)this_page + ); + if (m_curwnd) + { + RECT r; + + SetDlgItemTextFromLang(m_curwnd,IDC_INTROTEXT,this_page->parms[0]); + + GetWindowRect(GetDlgItem(hwndDlg,IDC_CHILDRECT),&r); + ScreenToClient(hwndDlg,(LPPOINT)&r); + SetWindowPos(m_curwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); +#ifdef NSIS_SUPPORT_CODECALLBACKS + ExecuteCodeSegment(this_page->showfunc,NULL); + if (g_quit_flag) + return FALSE; +#endif //NSIS_SUPPORT_CODECALLBACKS + ShowWindow(m_curwnd,SW_SHOWNA); + NotifyCurWnd(WM_NOTIFY_START); + } + } + } + +skipPage: + + if (!ui_dlg_visible && m_curwnd) + { + ShowWindow(hwndDlg, SW_SHOWDEFAULT); + ui_dlg_visible = 1; + } + + return FALSE; + } + +#ifdef NSIS_SUPPORT_BGBG + if (uMsg == WM_WINDOWPOSCHANGED) + { + SetWindowPos(m_bgwnd, hwndDlg, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + } + if (uMsg == WM_SIZE) { + ShowWindow(m_bgwnd, wParam == SIZE_MINIMIZED ? SW_HIDE : SW_SHOW); + } +#endif //NSIS_SUPPORT_BGBG + + if (uMsg == WM_NOTIFY_CUSTOM_READY) { + DestroyWindow(m_curwnd); + m_curwnd = (HWND)wParam; + goto skipPage; + } + if (uMsg == WM_QUERYENDSESSION) + { + SetWindowLong(hwndDlg, DWL_MSGRESULT, FALSE); + return TRUE; + } + if (uMsg == WM_COMMAND) + { + int id = LOWORD(wParam); + HWND hCtl = GetDlgItem(hwndDlg, id); // lParam might be NULL + if (hCtl) + { + SendMessage(hCtl, BM_SETSTATE, FALSE, 0); + if (!IsWindowEnabled(hCtl)) + return 0; + } + + if (id == IDOK) + { + outernotify(1); + } + else if (id == IDC_BACK && m_page>0) + { + outernotify(-1); + } + else if (id == IDCANCEL) + { + if (g_exec_flags.abort) + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + ExecuteCallbackFunction(CB_ONINSTFAILED); +#endif//NSIS_SUPPORT_CODECALLBACKS + m_retcode=2; + outernotify(NOTIFY_BYE_BYE); + } + else + { +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (!ExecuteCallbackFunction(CB_ONUSERABORT)) +#endif//NSIS_SUPPORT_CODECALLBACKS + { + m_retcode=1; + outernotify(NOTIFY_BYE_BYE); + } + } + } + else + { + // Forward WM_COMMANDs to inner dialogs, can be custom ones. + // Without this, enter on buttons in inner dialogs won't work. + SendMessage(m_curwnd, WM_COMMAND, wParam, lParam); + } + } + return HandleStaticBkColor(); +} + +#define this_page ((page*)lParam) + +#ifdef NSIS_CONFIG_LICENSEPAGE + +#define _RICHEDIT_VER 0x0200 +#include <richedit.h> +#undef _RICHEDIT_VER +static DWORD dwRead; +DWORD CALLBACK StreamLicense(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + lstrcpyn(pbBuff,(char*)dwCookie+dwRead,cb); + *pcb=mystrlen(pbBuff); + dwRead+=*pcb; + return 0; +} + +static BOOL CALLBACK LicenseProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + page *m_this_page=g_this_page; + HWND hwLicense; + static int ignoreWMCommand; + + if (uMsg == WM_INITDIALOG) + { + char *l = (char *)GetNSISStringNP(GetNSISTab(this_page->parms[1])); + int lt = *l; + EDITSTREAM es = { + (DWORD)(++l), + 0, + StreamLicense + }; + + int selected = (this_page->flags & PF_LICENSE_SELECTED) | !(this_page->flags & PF_LICENSE_FORCE_SELECTION); + + SetUITextFromLang(IDC_LICENSEAGREE,this_page->parms[2]); + SetUITextFromLang(IDC_LICENSEDISAGREE,this_page->parms[3]); + CheckDlgButton(hwndDlg,IDC_LICENSEAGREE+!selected,BST_CHECKED); + EnableNext(selected); + + hwLicense=GetUIItem(IDC_EDIT1); + SetActiveCtl(hwLicense); + SendMessage(hwLicense,EM_AUTOURLDETECT,TRUE,0); +#define lbg g_header->license_bg + SendMessage(hwLicense,EM_SETBKGNDCOLOR,0,lbg>=0?lbg:GetSysColor(-lbg)); +#undef lbg + SendMessage(hwLicense,EM_SETEVENTMASK,0,ENM_LINK|ENM_KEYEVENTS); //XGE 8th September 2002 Or'd in ENM_KEYEVENTS + dwRead=0; + SendMessage(hwLicense,EM_EXLIMITTEXT,0,mystrlen(l)); + SendMessage(hwLicense,EM_STREAMIN,lt,(LPARAM)&es); + ignoreWMCommand = 0; + return FALSE; + } + if (uMsg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && !ignoreWMCommand) { + if (m_this_page->flags & PF_LICENSE_FORCE_SELECTION) { + int is = SendMessage(GetUIItem(IDC_LICENSEAGREE), BM_GETCHECK, 0, 0) & BST_CHECKED; + m_this_page->flags &= ~PF_LICENSE_SELECTED; + m_this_page->flags |= is; + EnableNext(is); + SetNextDef(); + } + } + if (uMsg == WM_NOTIFY) { + hwLicense=GetUIItem(IDC_EDIT1); + #define nmhdr ((NMHDR *)lParam) + #define enlink ((ENLINK *)lParam) + #define msgfilter ((MSGFILTER *)lParam) + if (nmhdr->code==EN_LINK) { + if (enlink->msg==WM_LBUTTONDOWN) { + TEXTRANGE tr = { + { + enlink->chrg.cpMin, + enlink->chrg.cpMax, + }, + ps_tmpbuf + }; + if (tr.chrg.cpMax-tr.chrg.cpMin < sizeof(ps_tmpbuf)) { + SendMessage(hwLicense,EM_GETTEXTRANGE,0,(LPARAM)&tr); + SetCursor(LoadCursor(0, IDC_WAIT)); + ShellExecute(hwndDlg,"open",tr.lpstrText,NULL,NULL,SW_SHOWNORMAL); + SetCursor(LoadCursor(0, IDC_ARROW)); + } + } + } + //Ximon Eighteen 8th September 2002 Capture return key presses in the rich + //edit control now that the control gets the focus rather than the default + //push button. When the user presses return ask the outer dialog to move + //the installer onto the next page. MSDN docs say return non-zero if the + //rich edit control should NOT process this message, hence the return 1. + // + //This is required because the RichEdit control is eating all the key hits. + //It does try to release some and convert VK_ESCAPE to WM_CLOSE, VK_ENTER + //to a push on the default button and VM_TAB to WM_NEXTDLGCTL. But sadly it + //it sends all of these messages to its parent instead of just letting the + //dialog manager handle them. Instead of properly handling WM_GETDLGCODE, + //it mimics the dialog manager. + if (nmhdr->code==EN_MSGFILTER) + { + if (msgfilter->msg==WM_KEYDOWN) + { + if (msgfilter->wParam==VK_RETURN) { + SendMessage(g_hwnd, WM_COMMAND, IDOK, 0); + } + if (msgfilter->wParam==VK_ESCAPE) { + SendMessage(g_hwnd, WM_CLOSE, 0, 0); + } + return 1; + } + } + #undef nmhdr + #undef enlink + #undef msgfilter + } + if (uMsg == WM_NOTIFY_INIGO_MONTOYA) + { + ignoreWMCommand++; + } + return HandleStaticBkColor(); +} +#endif + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +static BOOL CALLBACK UninstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_INITDIALOG) + { + SetUITextFromLang(IDC_UNINSTFROM,this_page->parms[1]); + SetUITextNT(IDC_EDIT1,g_usrvars[this_page->parms[4]]); + } + return HandleStaticBkColor(); +} +#endif + + +static void NSISCALL SetSizeText(int dlgItem, int prefix, unsigned kb) +{ + char scalestr[32], byte[32]; + unsigned sh = 20; + int scale = LANG_GIGA; + + if (kb < 1024 * 1024) { sh = 10; scale = LANG_MEGA; } + if (kb < 1024) { sh = 0; scale = LANG_KILO; } + + if (kb < (0xFFFFFFFF - ((1 << 20) / 20))) // check for overflow + kb += (1 << sh) / 20; // round numbers for better display (e.g. 1.59 => 1.6) + + wsprintf( + GetNSISString(g_tmp, prefix) + mystrlen(g_tmp), + "%u.%u%s%s", + kb >> sh, + (((kb & 0x00FFFFFF) * 10) >> sh) % 10, // 0x00FFFFFF mask is used to + // prevent overflow that causes + // bad results + GetNSISString(scalestr, scale), + GetNSISString(byte, LANG_BYTE) + ); + + my_SetDialogItemText(m_curwnd,dlgItem,g_tmp); +} + +static int NSISCALL _sumsecsfield(int idx) +{ + int total = 0; + int x = num_sections; + section *s = g_sections; + while (x--) + { +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (s->flags & SF_SELECTED) +#endif + total += ((int *)s)[idx]; + s++; + } + return total; +} + +#define sumsecsfield(x) _sumsecsfield(SECTION_OFFSET(x)) + +static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static int dontsetdefstyle; + page *thispage = g_this_page; + char *dir = g_usrvars[thispage->parms[4]]; + int browse_text = thispage->parms[3]; + if (uMsg == WM_NOTIFY_INIGO_MONTOYA) + { + GetUIText(IDC_DIR,dir); + validate_filename(dir); +#ifdef NSIS_CONFIG_LOG +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) + build_g_logfile(); +#endif + if (GetUIItem(IDC_CHECK1) != NULL) + log_dolog = IsDlgButtonChecked(hwndDlg,IDC_CHECK1); +#endif + } + if (uMsg == WM_INITDIALOG) + { + HWND hDir = GetUIItem(IDC_DIR); + +#ifdef NSIS_CONFIG_LOG + if (GetAsyncKeyState(VK_SHIFT)&0x8000) + { + HWND h=GetUIItem(IDC_CHECK1); + SetUITextFromLang(IDC_CHECK1,LANG_LOG_INSTALL_PROCESS); + ShowWindow(h,SW_SHOWNA); + } +#endif + if (validpathspec(dir) && !skip_root(dir)) + addtrailingslash(dir); + + // workaround for bug #1209843 + // + // m_curwnd is only updated once WM_INITDIALOG returns. + // my_SetWindowText triggers an EN_CHANGE message that + // triggers a WM_IN_UPDATEMSG message that uses m_curwnd + // to get the selected directory (GetUIText). + // because m_curwnd is still outdated, dir varialble is + // filled with an empty string. by default, dir points + // to $INSTDIR. + // + // to solve this, m_curwnd is manually set to the correct + // window handle. + + m_curwnd=hwndDlg; + + my_SetWindowText(hDir,dir); + SetUITextFromLang(IDC_BROWSE,this_page->parms[2]); + SetUITextFromLang(IDC_SELDIRTEXT,this_page->parms[1]); + SetActiveCtl(hDir); + + { + typedef HRESULT (WINAPI *SHAutoCompletePtr)(HWND, DWORD); + SHAutoCompletePtr fSHAutoComplete; + fSHAutoComplete = (SHAutoCompletePtr) myGetProcAddress(MGA_SHAutoComplete); + if (fSHAutoComplete) + { + fSHAutoComplete(hDir, SHACF_FILESYSTEM); + } + } + } + if (uMsg == WM_COMMAND) + { + int id=LOWORD(wParam); + if (id == IDC_DIR && HIWORD(wParam) == EN_CHANGE) + { + uMsg = WM_IN_UPDATEMSG; + } + if (id == IDC_BROWSE) + { + static char bt[NSIS_MAX_STRLEN]; + BROWSEINFO bi = {0,}; + ITEMIDLIST *idlist; + bi.hwndOwner = hwndDlg; + bi.pszDisplayName = g_tmp; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)dir; + bi.lpszTitle = GetNSISString(bt, browse_text); + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + idlist = SHBrowseForFolder(&bi); + if (idlist) + { + // free idlist + CoTaskMemFree(idlist); + + addtrailingslash(dir); + + if (g_header->install_directory_auto_append && + dir == state_install_directory) // only append to $INSTDIR (bug #1174184) + { + const char *post_str = ps_tmpbuf; + GetNSISStringTT(g_header->install_directory_auto_append); + // display name gives just the folder name + if (lstrcmpi(post_str, g_tmp)) + { + mystrcat(dir, post_str); + } + } + + dontsetdefstyle++; + SetUITextNT(IDC_DIR,dir); + } + else + { + uMsg = WM_IN_UPDATEMSG; + } + } + } + if (uMsg == WM_IN_UPDATEMSG || uMsg == WM_NOTIFY_START) + { + static char s[NSIS_MAX_STRLEN]; + char *p; + int error = 0; + int available_set = 0; + unsigned total, available = 0xFFFFFFFF; + + GetUIText(IDC_DIR,dir); + if (!is_valid_instpath(dir)) + error = NSIS_INSTDIR_INVALID; + + mystrcpy(s,dir); + p=skip_root(s); + if (p) + *p=0; + + // Test for and use the GetDiskFreeSpaceEx API + { + BOOL (WINAPI *GDFSE)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER) = + myGetProcAddress(MGA_GetDiskFreeSpaceExA); + if (GDFSE) + { + ULARGE_INTEGER available64; + ULARGE_INTEGER a, b; + if (GDFSE(s, &available64, &a, &b)) + { +#ifndef _NSIS_NO_INT64_SHR + available = (int)(available64.QuadPart >> 10); +#else + available = (int)(Int64ShrlMod32(available64.QuadPart, 10)); +#endif + available_set++; + } + } + } + + if (!available_set) + { + // GetDiskFreeSpaceEx is not available + DWORD spc, bps, fc, tc; + if (GetDiskFreeSpace(s, &spc, &bps, &fc, &tc)) + { + available = (int)MulDiv(bps * spc, fc, 1 << 10); + available_set++; + } + } + + total = (unsigned) sumsecsfield(size_kb); + + if (available < total) + error = NSIS_INSTDIR_NOT_ENOUGH_SPACE; + + if (LANG_STR_TAB(LANG_SPACE_REQ)) { + SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,total); + if (available_set) + SetSizeText(IDC_SPACEAVAILABLE,LANG_SPACE_AVAIL,available); + else + SetUITextNT(IDC_SPACEAVAILABLE,""); + } + + g_exec_flags.instdir_error = error; + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (!error) + error = ExecuteCallbackFunction(CB_ONVERIFYINSTDIR); +#endif + + if (thispage->flags & PF_DIR_NO_BTN_DISABLE) + error = 0; + + EnableNext(!error); + if (!error && !dontsetdefstyle) + SetNextDef(); + dontsetdefstyle = 0; + } + return HandleStaticBkColor(); +} + +#ifdef NSIS_CONFIG_COMPONENTPAGE + +static void FORCE_INLINE NSISCALL RefreshComponents(HWND hwTree, HTREEITEM *items) +{ + TVITEM item; + int i, flags, state; + section *sec; + + item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED | TVIS_BOLD; + + for (i = 0, sec = g_sections; i < num_sections; i++, sec++) + { + if (!items[i]) + { + continue; + } + + flags = sec->flags; + + item.hItem = items[i]; + + item.mask = TVIF_STATE; + + if (flags & SF_NAMECHG) + { + item.mask |= TVIF_TEXT; + item.pszText = sec->name; + sec->flags &= ~SF_NAMECHG; + } + + if (flags & SF_PSELECTED) + { + state = 3; + } + else + { + state = 1 + (flags & SF_SELECTED); // SF_SELECTED == 1 + if (flags & SF_RO) state += 3; + } + + item.state = (flags & SF_BOLD) << 1; // (SF_BOLD << 1) == 16 == TVIS_BOLD + item.state |= flags & SF_EXPAND; // TVIS_EXPANDED == SF_EXPAND + item.state |= INDEXTOSTATEIMAGEMASK(state); + + // TVE_COLLAPSE = 1, TVE_EXPAND = 2 + TreeView_Expand(hwTree, item.hItem, TVE_COLLAPSE + ((flags & SF_EXPAND) / SF_EXPAND)); + + TreeView_SetItem(hwTree, &item); + } + + // workaround for bug #1397031 + // + // windows 95 doesn't erase the background of the state image + // before it draws a new one. because of this parts of the old + // state image will show where the new state image is masked. + // + // to solve this, the following line forces the background to + // be erased. sadly, this redraws the entire control. it might + // be a good idea to figure out where the state images are and + // redraw only those. + + InvalidateRect(hwTree, NULL, TRUE); +} + +int NSISCALL TreeGetSelectedSection(HWND tree, BOOL mouse) +{ + HTREEITEM hItem = TreeView_GetSelection(tree); + TVITEM item; + + if (mouse) + { + TVHITTESTINFO ht; + DWORD dwpos = GetMessagePos(); + + ht.pt.x = GET_X_LPARAM(dwpos); + ht.pt.y = GET_Y_LPARAM(dwpos); + ScreenToClient(tree, &ht.pt); + + TreeView_HitTest(tree, &ht); + +#ifdef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE + if (!(ht.flags & TVHT_ONITEMSTATEICON)) +#else + if (!(ht.flags & (TVHT_ONITEMSTATEICON|TVHT_ONITEMLABEL|TVHT_ONITEMRIGHT|TVHT_ONITEM))) +#endif + return -1; + + hItem = ht.hItem; + } + + item.mask = TVIF_PARAM; + item.hItem = hItem; + TreeView_GetItem(tree, &item); + + return (int) item.lParam; +} + +static LONG oldTreeWndProc; +static LPARAM last_selected_tree_item; +static DWORD WINAPI newTreeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CHAR && wParam == VK_SPACE) { + NotifyCurWnd(WM_TREEVIEW_KEYHACK); + return 0; + } +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) +#ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE + if (uMsg == WM_MOUSEMOVE) { + if (IsWindowVisible(hwnd)) { + lParam = TreeGetSelectedSection(hwnd, TRUE); + uMsg = WM_NOTIFY_SELCHANGE; + } + } +#endif + if (uMsg == WM_NOTIFY_SELCHANGE) { + if (last_selected_tree_item != lParam) + { + last_selected_tree_item = lParam; + + mystrcpy(g_tmp, g_usrvars[0]); + + myitoa(g_usrvars[0], lParam); + + ExecuteCallbackFunction(CB_ONMOUSEOVERSECTION); + + mystrcpy(g_usrvars[0], g_tmp); + } + } +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT + return CallWindowProc((WNDPROC)oldTreeWndProc,hwnd,uMsg,wParam,lParam); +} + +static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HTREEITEM *hTreeItems; + static HIMAGELIST hImageList; + HWND hwndCombo1 = GetUIItem(IDC_COMBO1); + HWND hwndTree1 = GetUIItem(IDC_TREE1); + extern HWND g_SectionHack; + section *sections=g_sections; + int *install_types=g_header->install_types; + if (uMsg == WM_INITDIALOG) + { + int doLines=0; + HTREEITEM Par; + HBITMAP hBMcheck1; + int x, lastGoodX, i, noCombo=2; + + g_SectionHack=hwndDlg; + + hTreeItems=(HTREEITEM*)GlobalAlloc(GPTR,sizeof(HTREEITEM)*num_sections); + + hBMcheck1=LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_BITMAP1)); + + last_selected_tree_item=-1; + oldTreeWndProc=SetWindowLong(hwndTree1,GWL_WNDPROC,(long)newTreeWndProc); + + hImageList = ImageList_Create(16,16, ILC_COLOR32|ILC_MASK, 6, 0); + ImageList_AddMasked(hImageList,hBMcheck1,RGB(255,0,255)); + + TreeView_SetImageList(hwndTree1, hImageList, TVSIL_STATE); + + if (TreeView_GetItemHeight(hwndTree1) < 16) + TreeView_SetItemHeight(hwndTree1, 16); + + DeleteObject(hBMcheck1); + + for (i = 0; i < NSIS_MAX_INST_TYPES+1; i++) + { + if (install_types[i]) + { + int j; + if (i != NSIS_MAX_INST_TYPES) noCombo = 0; + j=SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetNSISStringTT(install_types[i])); + SendMessage(hwndCombo1,CB_SETITEMDATA,j,i); + } + } + + SetUITextFromLang(IDC_TEXT1,this_page->parms[1+noCombo]); + SetUITextFromLang(IDC_TEXT2,this_page->parms[2+noCombo]); + + Par=NULL; + + for (lastGoodX = x = 0; x < num_sections; x ++) + { + section *sec=sections+x; + + if (sec->name[0]) + { + TVINSERTSTRUCT tv; + + tv.hParent = Par; + tv.hInsertAfter = TVI_LAST; + tv.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + tv.item.stateMask = TVIS_EXPANDED; + tv.item.lParam = x; + tv.item.pszText = sec->name; + + tv.item.state = sec->flags & SF_EXPAND; // TVIS_EXPANDED == SF_EXPAND + + if (sec->flags & SF_SECGRP) + { + tv.item.mask |= TVIF_CHILDREN; + tv.item.cChildren = 1; + Par = hTreeItems[x] = TreeView_InsertItem(hwndTree1, &tv); + doLines = 1; + } + else if (sec->flags & SF_SECGRPEND) + { + Par = TreeView_GetParent(hwndTree1, Par); + } + else + { + lastGoodX = x; + hTreeItems[x] = TreeView_InsertItem(hwndTree1, &tv); + } + } + } + + if (!doLines) + { + SetWindowLong(hwndTree1,GWL_STYLE,GetWindowLong(hwndTree1,GWL_STYLE)&~(TVS_LINESATROOT)); + } + + if (!noCombo) + { + ShowWindow(hwndCombo1, SW_SHOW); + SetActiveCtl(hwndCombo1); + } + else + SetActiveCtl(hwndTree1); + } + + if (uMsg == WM_NOTIFY_START) + { + wParam = 0; + lParam = 1; + uMsg = WM_IN_UPDATEMSG; + } + + if (uMsg == WM_NOTIFY || uMsg == WM_TREEVIEW_KEYHACK) + { + LPNMHDR lpnmh = (LPNMHDR) lParam; + if (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->idFrom == IDC_TREE1) + { + if (!(g_flags&CH_FLAGS_NO_CUSTOM) && (uMsg == WM_TREEVIEW_KEYHACK || lpnmh->code == NM_CLICK)) + { + int secid = TreeGetSelectedSection(hwndTree1, uMsg != WM_TREEVIEW_KEYHACK); + + if (secid >= 0) + { + int flags = sections[secid].flags; + + if ((flags & SF_RO) == 0) + { + if ((flags & SF_PSELECTED)) + { + flags ^= SF_TOGGLED; + + if (flags & SF_TOGGLED) + { + flags |= SF_SELECTED; + } + else + { + flags &= ~SF_SELECTED; + } + } + else + { + flags ^= SF_SELECTED; + } + + sections[secid].flags = flags; + + SectionFlagsChanged(secid); + + wParam = 1; + lParam = !(g_flags & CH_FLAGS_COMP_ONLY_ON_CUSTOM); + uMsg = WM_IN_UPDATEMSG; + } + } // was valid click + } // was click or hack +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_ENHANCEDUI_SUPPORT) + if (lpnmh) + { + if (lpnmh->code == TVN_SELCHANGED) + { + SendMessage(hwndTree1, WM_NOTIFY_SELCHANGE, 0, ((LPNMTREEVIEW)lpnmh)->itemNew.lParam); + } + if (lpnmh->code == TVN_ITEMEXPANDED) + { + LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lpnmh; + if (pnmtv->action == TVE_EXPAND) + sections[pnmtv->itemNew.lParam].flags |= SF_EXPAND; + else + sections[pnmtv->itemNew.lParam].flags &= ~SF_EXPAND; + } + } +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_ENHANCEDUI_SUPPORT + } + } + + if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_COMBO1 && HIWORD(wParam) == CBN_SELCHANGE) + { + int t = SendMessage(hwndCombo1,CB_GETCURSEL,0,0); + if (t != CB_ERR) + { + int whichcfg = SendMessage(hwndCombo1, CB_GETITEMDATA, t, 0); + + if (whichcfg == CB_ERR || !install_types[whichcfg]) + whichcfg = NSIS_MAX_INST_TYPES; + + SetInstType(whichcfg); + + SendMessage(hwndDlg, WM_NOTIFY_INSTTYPE_CHANGED, 0, whichcfg); + + wParam = 1; + lParam = 0; + uMsg = WM_IN_UPDATEMSG; + } + } + + if (uMsg == WM_MOUSEMOVE) + { + SendMessage(hwndTree1, WM_MOUSEMOVE, 0, 0); + } + + if (uMsg == WM_NOTIFY_INIGO_MONTOYA) + { + if (hImageList) ImageList_Destroy(hImageList); + if (hTreeItems) GlobalFree(hTreeItems); + hImageList = NULL; + hTreeItems = NULL; + g_SectionHack = NULL; + } + + if (uMsg == WM_IN_UPDATEMSG) + { + RefreshSectionGroups(); + +#if defined(NSIS_SUPPORT_CODECALLBACKS) && defined(NSIS_CONFIG_COMPONENTPAGE) + if (wParam) + { + ExecuteCallbackFunction(CB_ONSELCHANGE); + } +#endif//NSIS_SUPPORT_CODECALLBACKS && NSIS_CONFIG_COMPONENTPAGE + + if (lParam) + { + int i, cbi; + int inst_type = GetInstType(hTreeItems); + SetInstType(inst_type); + + for (i = 0, cbi = 0; i < inst_type; i++) + { + if (install_types[i]) + { + cbi++; + } + } + + SendMessage(hwndCombo1, CB_SETCURSEL, cbi, 0); + + lParam = inst_type; + uMsg = WM_NOTIFY_INSTTYPE_CHANGED; + } + + RefreshSectionGroups(); + RefreshComponents(hwndTree1, hTreeItems); + + if (LANG_STR_TAB(LANG_SPACE_REQ)) { + SetSizeText(IDC_SPACEREQUIRED,LANG_SPACE_REQ,sumsecsfield(size_kb)); + } + } + + if (uMsg == WM_NOTIFY_INSTTYPE_CHANGED) + { + if (g_flags & CH_FLAGS_COMP_ONLY_ON_CUSTOM) + { + int c = (lParam == NSIS_MAX_INST_TYPES ? 1 : 0) << 3;// SW_SHOWNA=8, SW_HIDE=0 + ShowWindow(hwndTree1, c); + ShowWindow(GetUIItem(IDC_TEXT2), c); + } + } + + return HandleStaticBkColor(); +} +#endif//NSIS_CONFIG_COMPONENTPAGE + +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +void NSISCALL update_status_text(int strtab, const char *text) { + static char tmp[NSIS_MAX_STRLEN*2]; + LVITEM new_item; + HWND linsthwnd = insthwnd; + if (linsthwnd) + { + int updateflag = g_exec_flags.status_update; + int tmplen; + + if (!(updateflag & 1)) + GetNSISString(tmp, strtab); + + tmplen = mystrlen(tmp); + + if (text) + { + if (tmplen + mystrlen(text) >= sizeof(tmp)) return; + mystrcat(tmp, text); + } + + if ((updateflag & 4) == 0) my_SetWindowText(insthwnd2, tmp); + if ((updateflag & 2) == 0) + { + new_item.mask = LVIF_TEXT; + new_item.pszText = tmp; + new_item.iItem = ListView_GetItemCount(linsthwnd) - (updateflag & 1); + new_item.iSubItem = 0; + // LVM_INSERTITEM - LVM_SETITEM = 1 + SendMessage(linsthwnd, LVM_INSERTITEM - (updateflag & 1), 0, (LPARAM) &new_item); + ListView_EnsureVisible(linsthwnd, new_item.iItem, 0); + } + + if (updateflag & 1) + tmp[tmplen] = 0; + } +} + +static DWORD WINAPI install_thread(LPVOID p) +{ + int m_inst_sec=num_sections; + HWND progresswnd = (HWND)p; + section *s = g_sections; + +#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT) + { + extern HRESULT g_hres; + g_hres|=OleInitialize(NULL); + } +#endif + + // workaround for bug #1400995 + // + // for an unexplained reason, MessageBox with MB_TOPMOST + // will fail, if no other messages were sent from this + // thread to the GUI thread before it. + // + // the source of the problem couldn't be found, so a + // WM_NULL is sent to work around it. + + NotifyCurWnd(WM_NULL); + + while (m_inst_sec--) + { +#ifdef NSIS_CONFIG_COMPONENTPAGE + if (s->flags&SF_SELECTED) +#endif + { + log_printf2("Section: \"%s\"",s->name); + if (ExecuteCodeSegment(s->code,progresswnd)) + { + g_exec_flags.abort++; + break; + } + } +#ifdef NSIS_CONFIG_COMPONENTPAGE + else + { + log_printf2("Skipping section: \"%s\"",s->name); + } +#endif + s++; + } + NotifyCurWnd(WM_NOTIFY_INSTPROC_DONE); + +#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT) + OleUninitialize(); +#endif + + return g_exec_flags.abort; +} + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + +static BOOL CALLBACK InstProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + HWND linsthwnd=insthwnd; + if (uMsg == WM_INITDIALOG) + { + RECT r; + LVCOLUMN lvc = {LVCF_WIDTH, 0, -1, 0, 0, -1}; + int lb_bg=g_header->lb_bg,lb_fg=g_header->lb_fg; + + insthwndbutton=GetUIItem(IDC_SHOWDETAILS); + insthwnd2=GetUIItem(IDC_INTROTEXT); + linsthwnd=insthwnd=GetUIItem(IDC_LIST1); + + SetActiveCtl(insthwndbutton); + + progress_bar_len=sumsecsfield(code_size); + progress_bar_pos=0; + + log_printf3("New install of \"%s\" to \"%s\"",GetNSISStringTT(LANG_NAME),state_install_directory); + + GetClientRect(linsthwnd, &r); + lvc.cx = r.right - GetSystemMetrics(SM_CXHSCROLL); + ListView_InsertColumn(linsthwnd, 0, &lvc); + + ListView_SetExtendedListViewStyleEx(linsthwnd, LVS_EX_LABELTIP, LVS_EX_LABELTIP); + if (lb_bg >= 0) { + ListView_SetBkColor(linsthwnd, lb_bg); + ListView_SetTextBkColor(linsthwnd, lb_bg); + } + if (lb_fg >= 0) { + ListView_SetTextColor(linsthwnd, lb_fg); + } + SetUITextFromLang(IDC_SHOWDETAILS,this_page->parms[1]); + if (g_flags&(CH_FLAGS_DETAILS_SHOWDETAILS|CH_FLAGS_DETAILS_NEVERSHOW)) + { + ShowWindow(insthwndbutton,SW_HIDE); + if (!(g_flags&CH_FLAGS_DETAILS_NEVERSHOW)) ShowWindow(linsthwnd,SW_SHOWNA); + else insthwndbutton=NULL; + SetActiveCtl(insthwnd2); + } + + { + HWND progresswnd=GetUIItem(IDC_PROGRESS); + SendMessage(progresswnd,PBM_SETRANGE,0,MAKELPARAM(0,30000)); + if (g_flags&CH_FLAGS_PROGRESS_COLORED) + { + SendMessage(progresswnd,PBM_SETBARCOLOR,0,lb_fg); + SendMessage(progresswnd,PBM_SETBKCOLOR,0,lb_bg); + } + } + + return FALSE; + } + if (uMsg == WM_NOTIFY_START) { + DWORD id; + CloseHandle(CreateThread(NULL,0,install_thread,GetUIItem(IDC_PROGRESS),0,&id)); + } + if (uMsg == WM_COMMAND && LOWORD(wParam) == IDC_SHOWDETAILS) + { + ShowWindow(insthwndbutton,SW_HIDE); + ShowWindow(linsthwnd,SW_SHOWNA); + SetActiveCtl(linsthwnd); + } + if (uMsg == WM_NOTIFY_INSTPROC_DONE) + { + if (g_quit_flag) + { + m_retcode=2; + outernotify(NOTIFY_BYE_BYE); + } + else + { + ShowWindow(g_hwnd,SW_SHOWNA); + if (!g_exec_flags.abort) + update_status_text(g_this_page->parms[2],0); + outernotify(1); + } + } + //>>>Ximon Eighteen aka Sunjammer 30th August 2002 + //+++Popup "Copy Details To Clipboard" menu when RMB clicked in DetailView + if (uMsg == WM_CONTEXTMENU && wParam == (WPARAM) linsthwnd) + { + int count = ListView_GetItemCount(linsthwnd); + if (count > 0) + { + HMENU menu = CreatePopupMenu(); + POINT pt; + AppendMenu(menu,MF_STRING,1,GetNSISStringTT(LANG_COPYDETAILS)); + if (lParam == ((UINT)-1)) + { + RECT r; + GetWindowRect(linsthwnd, &r); + pt.x = r.left; + pt.y = r.top; + } + else + { + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + } + if (1==TrackPopupMenu( + menu, + TPM_NONOTIFY|TPM_RETURNCMD, + pt.x, + pt.y, + 0,hwndDlg,0)) + { + int i,total = 1; // 1 for the null char + LVITEM item; + HGLOBAL memory; + LPTSTR ptr;//,endPtr; + + // 1st pass - determine clipboard memory required. + item.iSubItem = 0; + item.pszText = g_tmp; + item.cchTextMax = sizeof(g_tmp) - 1; + i = count; + while (i--) + // Add 2 for the CR/LF combination that must follow every line. + total += 2+SendMessage(linsthwnd,LVM_GETITEMTEXT,i,(LPARAM)&item); + + // 2nd pass - store detail view strings on the clipboard + // Clipboard MSDN docs say mem must be GMEM_MOVEABLE + OpenClipboard(0); + EmptyClipboard(); + memory = GlobalAlloc(GHND,total); + ptr = GlobalLock(memory); + //endPtr = ptr+total-2; // -2 to allow for CR/LF + i = 0; + do { + item.pszText = ptr; + ptr += SendMessage(linsthwnd,LVM_GETITEMTEXT,i,(LPARAM)&item); + *(WORD*)ptr = CHAR2_TO_WORD('\r','\n'); + ptr+=2; + } while (++i < count); + // memory is auto zeroed when allocated with GHND - *ptr = 0; + GlobalUnlock(memory); + SetClipboardData(CF_TEXT,memory); + CloseClipboard(); + } + } + return FALSE; + } + //<<< + return HandleStaticBkColor(); +} +#endif//NSIS_CONFIG_VISIBLE_SUPPORT diff --git a/Source/exehead/afxres.h b/Source/exehead/afxres.h index 7a74b25..70bd1e4 100755 --- a/Source/exehead/afxres.h +++ b/Source/exehead/afxres.h @@ -1,21 +1,21 @@ -/*
- * afxres.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-
-#ifndef IDC_STATIC
-#define IDC_STATIC -1
-#endif
+/* + * afxres.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/Source/exehead/bgbg.c b/Source/exehead/bgbg.c index 9851f2b..42da5e1 100755 --- a/Source/exehead/bgbg.c +++ b/Source/exehead/bgbg.c @@ -1,99 +1,99 @@ -/*
- * bgbg.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include "resource.h"
-#include "config.h"
-#include "fileform.h"
-#include "state.h"
-#include "ui.h"
-#include "util.h"
-
-#ifdef NSIS_SUPPORT_BGBG
-
-#define c1 header->bg_color1
-#define c2 header->bg_color2
-
-LRESULT CALLBACK BG_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg)
- {
- case WM_WINDOWPOSCHANGING:
- {
- LPWINDOWPOS wp = (LPWINDOWPOS) lParam;
- wp->flags |= SWP_NOACTIVATE;
- wp->hwndInsertAfter = g_hwnd;
- break;
- }
- case WM_PAINT:
- {
- header *header = g_header;
-
- PAINTSTRUCT ps;
- HDC hdc=BeginPaint(hwnd,&ps);
- RECT r;
- LOGBRUSH lh;
- int ry;
-
- lh.lbStyle = BS_SOLID;
-
- GetClientRect(hwnd,&r);
- // this portion by Drew Davidson, drewdavidson@mindspring.com
- ry=r.bottom;
- r.bottom=0;
-
- // JF: made slower, reduced to 4 pixels high, because I like how it looks better/
- while (r.top < ry)
- {
- int rv,gv,bv;
- HBRUSH brush;
- rv = (GetRValue(c2) * r.top + GetRValue(c1) * (ry-r.top)) / ry;
- gv = (GetGValue(c2) * r.top + GetGValue(c1) * (ry-r.top)) / ry;
- bv = (GetBValue(c2) * r.top + GetBValue(c1) * (ry-r.top)) / ry;
- lh.lbColor = RGB(rv,gv,bv);
- brush = CreateBrushIndirect(&lh);
- // note that we don't need to do "SelectObject(hdc, brush)"
- // because FillRect lets us specify the brush as a parameter.
- r.bottom+=4;
- FillRect(hdc, &r, brush);
- DeleteObject(brush);
- r.top+=4;
- }
-
- if (header->bg_textcolor != -1)
- {
- HFONT newFont = CreateFontIndirect((LOGFONT *) header->blocks[NB_BGFONT].offset);
- if (newFont)
- {
- HFONT oldFont;
- r.left=16;
- r.top=8;
- SetBkMode(hdc,TRANSPARENT);
- SetTextColor(hdc,header->bg_textcolor);
- oldFont = SelectObject(hdc,newFont);
- DrawText(hdc,g_caption,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOPREFIX);
- SelectObject(hdc,oldFont);
- DeleteObject(newFont);
- }
- }
- EndPaint(hwnd,&ps);
- }
- return 0;
- }
- return DefWindowProc(hwnd,uMsg,wParam,lParam);
-}
-
-#endif //NSIS_SUPPORT_BGBG
+/* + * bgbg.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include "resource.h" +#include "config.h" +#include "fileform.h" +#include "state.h" +#include "ui.h" +#include "util.h" + +#ifdef NSIS_SUPPORT_BGBG + +#define c1 header->bg_color1 +#define c2 header->bg_color2 + +LRESULT CALLBACK BG_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_WINDOWPOSCHANGING: + { + LPWINDOWPOS wp = (LPWINDOWPOS) lParam; + wp->flags |= SWP_NOACTIVATE; + wp->hwndInsertAfter = g_hwnd; + break; + } + case WM_PAINT: + { + header *header = g_header; + + PAINTSTRUCT ps; + HDC hdc=BeginPaint(hwnd,&ps); + RECT r; + LOGBRUSH lh; + int ry; + + lh.lbStyle = BS_SOLID; + + GetClientRect(hwnd,&r); + // this portion by Drew Davidson, drewdavidson@mindspring.com + ry=r.bottom; + r.bottom=0; + + // JF: made slower, reduced to 4 pixels high, because I like how it looks better/ + while (r.top < ry) + { + int rv,gv,bv; + HBRUSH brush; + rv = (GetRValue(c2) * r.top + GetRValue(c1) * (ry-r.top)) / ry; + gv = (GetGValue(c2) * r.top + GetGValue(c1) * (ry-r.top)) / ry; + bv = (GetBValue(c2) * r.top + GetBValue(c1) * (ry-r.top)) / ry; + lh.lbColor = RGB(rv,gv,bv); + brush = CreateBrushIndirect(&lh); + // note that we don't need to do "SelectObject(hdc, brush)" + // because FillRect lets us specify the brush as a parameter. + r.bottom+=4; + FillRect(hdc, &r, brush); + DeleteObject(brush); + r.top+=4; + } + + if (header->bg_textcolor != -1) + { + HFONT newFont = CreateFontIndirect((LOGFONT *) header->blocks[NB_BGFONT].offset); + if (newFont) + { + HFONT oldFont; + r.left=16; + r.top=8; + SetBkMode(hdc,TRANSPARENT); + SetTextColor(hdc,header->bg_textcolor); + oldFont = SelectObject(hdc,newFont); + DrawText(hdc,g_caption,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOPREFIX); + SelectObject(hdc,oldFont); + DeleteObject(newFont); + } + } + EndPaint(hwnd,&ps); + } + return 0; + } + return DefWindowProc(hwnd,uMsg,wParam,lParam); +} + +#endif //NSIS_SUPPORT_BGBG diff --git a/Source/exehead/components.c b/Source/exehead/components.c index 8b494c4..f7643e4 100755 --- a/Source/exehead/components.c +++ b/Source/exehead/components.c @@ -1,164 +1,164 @@ -/*
- * components.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include "config.h"
-#include "ui.h"
-#include "fileform.h"
-
-void NSISCALL SectionFlagsChanged(unsigned int index) {
- section *sections = g_sections;
-
- int flags = sections[index].flags;
-
- if (flags & SF_SECGRP) {
- unsigned int i = index + 1;
- unsigned int level = 0;
-
- for (; i < (unsigned int) num_sections; i++) {
- if (sections[i].flags & SF_SECGRP) {
- level++;
- continue;
- }
-
- if (sections[i].flags & SF_SECGRPEND) {
- if (level-- == 0) {
- break;
- }
-
- continue;
- }
-
- if ((sections[i].flags & SF_RO) == 0) {
- sections[i].flags &= ~SF_SELECTED;
- sections[i].flags |= (flags & SF_SELECTED);
- }
- }
- }
-}
-
-unsigned int NSISCALL _RefreshSectionGroups(unsigned int i, int not_first_call) {
- unsigned int selected = 0;
- unsigned int not_selected = 0;
-
- section *sections = g_sections;
-
- section *sec = §ions[i];
-
- if (sec->flags & SF_SECGRP) {
- if (not_first_call) {
- sec->flags &= ~(SF_SELECTED | SF_PSELECTED);
- i++;
- }
- }
-
- while (i < (unsigned int) num_sections) {
- int flags = sections[i].flags;
- int ni = i + 1;
-
- if (flags & SF_SECGRP) {
- ni = _RefreshSectionGroups(i, 1);
- flags = sections[i].flags;
- }
-
- if (flags & SF_SECGRPEND) {
- if (selected) {
- if (not_selected) {
- sec->flags |= SF_PSELECTED;
- } else {
- sec->flags |= SF_SELECTED;
- sec->flags &= ~SF_TOGGLED;
- }
- }
-
- return ni;
- }
-
- if (flags & SF_PSELECTED) {
- selected++;
- }
-
- if (flags & SF_SELECTED) {
- selected++;
- } else {
- not_selected++;
- }
-
- i = ni;
- }
-
- return 0;
-}
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
-
-void NSISCALL SetInstType(int inst_type) {
- unsigned int i = 0;
-
- section *sections = g_sections;
-
- if ((unsigned int) inst_type >= NSIS_MAX_INST_TYPES) {
- return;
- }
-
- for (; i < (unsigned int) num_sections; i++) {
- if (sections[i].flags & (SF_SECGRP | SF_SECGRPEND)) {
- continue;
- }
-
- if (sections[i].install_types & (1 << inst_type)) {
- sections[i].flags |= SF_SELECTED;
- } else {
- sections[i].flags &= ~SF_SELECTED;
- }
- }
-}
-
-unsigned int NSISCALL GetInstType(HTREEITEM *items) {
- unsigned int i, j;
-
- section *sections = g_sections;
-
- for (i = 0; i < NSIS_MAX_INST_TYPES; i++) {
- if (!g_header->install_types[i]) {
- continue;
- }
-
- for (j = 0; j < (unsigned int) num_sections; j++) {
- if (sections[j].flags & (SF_SECGRP | SF_SECGRPEND)) {
- continue;
- }
-
- if (items && !items[j]) {
- continue;
- }
-
- if ((sections[j].install_types & (1 << i)) == ((sections[j].flags & SF_SELECTED) << i)) {
- continue;
- } else {
- break;
- }
- }
-
- if (j == (unsigned int) num_sections) {
- break;
- }
- }
-
- return i;
-}
-
-#endif//NSIS_CONFIG_COMPONENTPAGE
+/* + * components.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include "config.h" +#include "ui.h" +#include "fileform.h" + +void NSISCALL SectionFlagsChanged(unsigned int index) { + section *sections = g_sections; + + int flags = sections[index].flags; + + if (flags & SF_SECGRP) { + unsigned int i = index + 1; + unsigned int level = 0; + + for (; i < (unsigned int) num_sections; i++) { + if (sections[i].flags & SF_SECGRP) { + level++; + continue; + } + + if (sections[i].flags & SF_SECGRPEND) { + if (level-- == 0) { + break; + } + + continue; + } + + if ((sections[i].flags & SF_RO) == 0) { + sections[i].flags &= ~SF_SELECTED; + sections[i].flags |= (flags & SF_SELECTED); + } + } + } +} + +unsigned int NSISCALL _RefreshSectionGroups(unsigned int i, int not_first_call) { + unsigned int selected = 0; + unsigned int not_selected = 0; + + section *sections = g_sections; + + section *sec = §ions[i]; + + if (sec->flags & SF_SECGRP) { + if (not_first_call) { + sec->flags &= ~(SF_SELECTED | SF_PSELECTED); + i++; + } + } + + while (i < (unsigned int) num_sections) { + int flags = sections[i].flags; + int ni = i + 1; + + if (flags & SF_SECGRP) { + ni = _RefreshSectionGroups(i, 1); + flags = sections[i].flags; + } + + if (flags & SF_SECGRPEND) { + if (selected) { + if (not_selected) { + sec->flags |= SF_PSELECTED; + } else { + sec->flags |= SF_SELECTED; + sec->flags &= ~SF_TOGGLED; + } + } + + return ni; + } + + if (flags & SF_PSELECTED) { + selected++; + } + + if (flags & SF_SELECTED) { + selected++; + } else { + not_selected++; + } + + i = ni; + } + + return 0; +} + +#ifdef NSIS_CONFIG_COMPONENTPAGE + +void NSISCALL SetInstType(int inst_type) { + unsigned int i = 0; + + section *sections = g_sections; + + if ((unsigned int) inst_type >= NSIS_MAX_INST_TYPES) { + return; + } + + for (; i < (unsigned int) num_sections; i++) { + if (sections[i].flags & (SF_SECGRP | SF_SECGRPEND)) { + continue; + } + + if (sections[i].install_types & (1 << inst_type)) { + sections[i].flags |= SF_SELECTED; + } else { + sections[i].flags &= ~SF_SELECTED; + } + } +} + +unsigned int NSISCALL GetInstType(HTREEITEM *items) { + unsigned int i, j; + + section *sections = g_sections; + + for (i = 0; i < NSIS_MAX_INST_TYPES; i++) { + if (!g_header->install_types[i]) { + continue; + } + + for (j = 0; j < (unsigned int) num_sections; j++) { + if (sections[j].flags & (SF_SECGRP | SF_SECGRPEND)) { + continue; + } + + if (items && !items[j]) { + continue; + } + + if ((sections[j].install_types & (1 << i)) == ((sections[j].flags & SF_SELECTED) << i)) { + continue; + } else { + break; + } + } + + if (j == (unsigned int) num_sections) { + break; + } + } + + return i; +} + +#endif//NSIS_CONFIG_COMPONENTPAGE diff --git a/Source/exehead/components.h b/Source/exehead/components.h index 35b78c6..6d77bea 100755 --- a/Source/exehead/components.h +++ b/Source/exehead/components.h @@ -1,28 +1,28 @@ -/*
- * components.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___COMPONENTS_H___
-#define ___COMPONENTS_H___
-
-void NSISCALL SectionFlagsChanged(unsigned int index);
-#define RefreshSectionGroups() _RefreshSectionGroups(0, 0)
-unsigned int NSISCALL _RefreshSectionGroups(unsigned int i, int not_first_call);
-#ifdef NSIS_CONFIG_COMPONENTPAGE
-void NSISCALL SetInstType(int inst_type);
-unsigned int NSISCALL GetInstType(HTREEITEM *items);
-#endif//NSIS_CONFIG_COMPONENTPAGE
-
-#endif//!___COMPONENTS_H___
+/* + * components.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___COMPONENTS_H___ +#define ___COMPONENTS_H___ + +void NSISCALL SectionFlagsChanged(unsigned int index); +#define RefreshSectionGroups() _RefreshSectionGroups(0, 0) +unsigned int NSISCALL _RefreshSectionGroups(unsigned int i, int not_first_call); +#ifdef NSIS_CONFIG_COMPONENTPAGE +void NSISCALL SetInstType(int inst_type); +unsigned int NSISCALL GetInstType(HTREEITEM *items); +#endif//NSIS_CONFIG_COMPONENTPAGE + +#endif//!___COMPONENTS_H___ diff --git a/Source/exehead/config.h b/Source/exehead/config.h index 03a2afd..4f50e79 100755 --- a/Source/exehead/config.h +++ b/Source/exehead/config.h @@ -1,161 +1,161 @@ -/*
- * config.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef NSIS_CONFIG_H
-#define NSIS_CONFIG_H
-
-#ifndef APSTUDIO_INVOKED // keep msdev's resource editor from mangling the .rc file
-
-#include "sconf.h"
-
-#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
- #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- #undef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- #endif
-#endif
-
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- #ifndef NSIS_SUPPORT_HWNDS
- #define NSIS_SUPPORT_HWNDS
- #endif
-#endif
-
-#ifdef NSIS_CONFIG_LOG_ODS
- #ifndef NSIS_CONFIG_LOG
- #error NSIS_CONFIG_LOG_ODS relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined
- #endif
-#endif
-
-#ifdef NSIS_CONFIG_LOG_STDOUT
- #ifndef NSIS_CONFIG_LOG
- #error NSIS_CONFIG_LOG_STDOUT relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined
- #endif
-#endif
-
-#ifdef NSIS_CONFIG_LOG_TIMESTAMP
- #ifndef NSIS_CONFIG_LOG
- #error NSIS_CONFIG_LOG_TIMESTAMP relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined
- #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
- #ifndef NSIS_COMPRESS_USE_LZMA
- #error compression is enabled but zlib, bzip2 and lzma are disabled.
- #endif
- #endif
- #endif
- #endif
-
- #ifdef NSIS_COMPRESS_USE_ZLIB
- #ifdef NSIS_COMPRESS_USE_BZIP2
- #error both zlib and bzip2 are enabled.
- #endif
- #ifdef NSIS_COMPRESS_USE_LZMA
- #error both zlib and lzma are enabled.
- #endif
- #endif
- #ifdef NSIS_COMPRESS_USE_BZIP2
- #ifdef NSIS_COMPRESS_USE_LZMA
- #error both bzip2 and lzma are enabled.
- #endif
- #endif
-
- #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- #ifdef NSIS_COMPRESS_WHOLE
- #ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- #ifndef _NSIS_CONFIG_VERIFYDIALOG
- #define _NSIS_CONFIG_VERIFYDIALOG
- #endif
- #endif
- #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
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- #ifndef NSIS_SUPPORT_RMDIR
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_RMDIR, but NSIS_SUPPORT_RMDIR is not defined
- #endif
- #ifndef NSIS_SUPPORT_FILE
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_FILE, but NSIS_SUPPORT_FILE is not defined
- #endif
- #ifndef NSIS_SUPPORT_ACTIVEXREG
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_ACTIVEXREG, but NSIS_SUPPORT_ACTIVEXREG is not defined
- #endif
- #ifndef NSIS_SUPPORT_STACK
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_STACK, but NSIS_SUPPORT_STACK is not defined
- #endif
- #ifndef NSIS_SUPPORT_FNUTIL
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_FNUTIL, but NSIS_SUPPORT_FNUTIL is not defined
- #endif
- #ifndef NSIS_SUPPORT_DELETE
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_DELETE, but NSIS_SUPPORT_DELETE is not defined
- #endif
- #ifndef NSIS_SUPPORT_MESSAGEBOX
- #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_MESSAGEBOX, but NSIS_SUPPORT_MESSAGEBOX is not defined
- #endif
-#endif
-
-#if NSIS_MAX_INST_TYPES > 32
- #error NSIS_MAX_INST_TYPES > 32
-#endif
-
-#ifndef NSIS_DEFAULT_LANG
- #define NSIS_DEFAULT_LANG 1033
-#endif
-
-#endif//!APSTUDIO_INVOKED
-
-#endif // NSIS_CONFIG_H
+/* + * config.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef NSIS_CONFIG_H +#define NSIS_CONFIG_H + +#ifndef APSTUDIO_INVOKED // keep msdev's resource editor from mangling the .rc file + +#include "sconf.h" + +#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 + #ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + #undef NSIS_CONFIG_ENHANCEDUI_SUPPORT + #endif +#endif + +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + #ifndef NSIS_SUPPORT_HWNDS + #define NSIS_SUPPORT_HWNDS + #endif +#endif + +#ifdef NSIS_CONFIG_LOG_ODS + #ifndef NSIS_CONFIG_LOG + #error NSIS_CONFIG_LOG_ODS relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined + #endif +#endif + +#ifdef NSIS_CONFIG_LOG_STDOUT + #ifndef NSIS_CONFIG_LOG + #error NSIS_CONFIG_LOG_STDOUT relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined + #endif +#endif + +#ifdef NSIS_CONFIG_LOG_TIMESTAMP + #ifndef NSIS_CONFIG_LOG + #error NSIS_CONFIG_LOG_TIMESTAMP relies on NSIS_CONFIG_LOG, but NSIS_CONFIG_LOG is not defined + #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 + #ifndef NSIS_COMPRESS_USE_LZMA + #error compression is enabled but zlib, bzip2 and lzma are disabled. + #endif + #endif + #endif + #endif + + #ifdef NSIS_COMPRESS_USE_ZLIB + #ifdef NSIS_COMPRESS_USE_BZIP2 + #error both zlib and bzip2 are enabled. + #endif + #ifdef NSIS_COMPRESS_USE_LZMA + #error both zlib and lzma are enabled. + #endif + #endif + #ifdef NSIS_COMPRESS_USE_BZIP2 + #ifdef NSIS_COMPRESS_USE_LZMA + #error both bzip2 and lzma are enabled. + #endif + #endif + + #ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + #ifdef NSIS_COMPRESS_WHOLE + #ifdef NSIS_CONFIG_VISIBLE_SUPPORT + #ifndef _NSIS_CONFIG_VERIFYDIALOG + #define _NSIS_CONFIG_VERIFYDIALOG + #endif + #endif + #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 + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + #ifndef NSIS_SUPPORT_RMDIR + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_RMDIR, but NSIS_SUPPORT_RMDIR is not defined + #endif + #ifndef NSIS_SUPPORT_FILE + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_FILE, but NSIS_SUPPORT_FILE is not defined + #endif + #ifndef NSIS_SUPPORT_ACTIVEXREG + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_ACTIVEXREG, but NSIS_SUPPORT_ACTIVEXREG is not defined + #endif + #ifndef NSIS_SUPPORT_STACK + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_STACK, but NSIS_SUPPORT_STACK is not defined + #endif + #ifndef NSIS_SUPPORT_FNUTIL + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_FNUTIL, but NSIS_SUPPORT_FNUTIL is not defined + #endif + #ifndef NSIS_SUPPORT_DELETE + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_DELETE, but NSIS_SUPPORT_DELETE is not defined + #endif + #ifndef NSIS_SUPPORT_MESSAGEBOX + #error NSIS_CONFIG_PLUGIN_SUPPORT relies on NSIS_SUPPORT_MESSAGEBOX, but NSIS_SUPPORT_MESSAGEBOX is not defined + #endif +#endif + +#if NSIS_MAX_INST_TYPES > 32 + #error NSIS_MAX_INST_TYPES > 32 +#endif + +#ifndef NSIS_DEFAULT_LANG + #define NSIS_DEFAULT_LANG 1033 +#endif + +#endif//!APSTUDIO_INVOKED + +#endif // NSIS_CONFIG_H diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 3b22e29..1566ffc 100755 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -1,1626 +1,1626 @@ -/*
- * exec.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include <shlobj.h>
-#include <shellapi.h>
-#include "fileform.h"
-#include "util.h"
-#include "state.h"
-#include "ui.h"
-#include "components.h"
-#include "exec.h"
-#include "lang.h"
-#include "resource.h"
-
-#define EXEC_ERROR 0x7FFFFFFF
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
-HWND g_SectionHack;
-#endif
-
-#ifdef NSIS_SUPPORT_STACK
-typedef struct _stack_t {
- struct _stack_t *next;
- char text[NSIS_MAX_STRLEN];
-} stack_t;
-
-static stack_t *g_st;
-#endif
-
-exec_flags g_exec_flags;
-exec_flags g_exec_flags_last_used;
-
-struct {
- exec_flags *flags;
- void *ExecuteCodeSegment;
- void *validate_filename;
-} plugin_extra_parameters = {
- &g_exec_flags,
- &ExecuteCodeSegment,
- &validate_filename
-};
-
-#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT)
-HRESULT g_hres;
-#endif
-
-static int NSISCALL ExecuteEntry(entry *entry_);
-
-int NSISCALL resolveaddr(int v)
-{
- if (v < 0)
- {
- return myatoi(g_usrvars[-(v+1)]);
- }
- return v;
-}
-
-int NSISCALL ExecuteCodeSegment(int pos, HWND hwndProgress)
-{
- while (pos >= 0)
- {
- int rv;
- if (g_entries[pos].which == EW_RET) return 0;
- rv=ExecuteEntry(g_entries + pos);
- if (rv == EXEC_ERROR) return EXEC_ERROR;
-
- rv=resolveaddr(rv);
-
- if (!rv) { rv++; pos++; }
- else
- {
- int t=pos;
- rv--; // rv is decremented here by 1, since it was +1 on the other end.
- pos=rv; // set new position
- rv-=t; // set rv to delta for progress adjustment
- }
-
- if (hwndProgress)
- {
- extern int progress_bar_pos, progress_bar_len;
- progress_bar_pos+=rv;
- SendMessage(hwndProgress,PBM_SETPOS,MulDiv(progress_bar_pos,30000,progress_bar_len),0);
- }
- }
- return 0;
-}
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
-
-int NSISCALL ExecuteCallbackFunction(int num)
-{
- return ExecuteCodeSegment(*(&g_header->code_onInit + num), NULL);
-}
-
-#endif
-
-static char bufs[5][NSIS_MAX_STRLEN];
-static int *parms;
-
-void NSISCALL update_status_text_buf1(int strtab)
-{
- update_status_text(strtab, bufs[1]);
-}
-
-static int NSISCALL GetIntFromParm(int id_)
-{
- return myatoi(GetNSISStringTT(parms[id_]));
-}
-
-// NB - USE CAUTION when rearranging code to make use of the new return value of
-// this function - be sure the parm being accessed is not modified before the call.
-// Use a negative number to get the string validated as a file name
-static char * NSISCALL GetStringFromParm(int id_)
-{
- int id = id_ < 0 ? -id_ : id_;
- char *result = GetNSISString(bufs[id >> 4], parms[id & 0xF]);
- if (id_ < 0) validate_filename(result);
- return result;
-}
-
-#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
-
-#define AlterRegistrySAM(sam) (sam | g_exec_flags.alter_reg_view)
-
-// based loosely on code from Tim Kosse
-// in win9x this isn't necessary (RegDeleteKey() can delete a tree of keys),
-// but in win2k you need to do this manually.
-static LONG NSISCALL myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey, int onlyifempty)
-{
- HKEY key;
- int retval=RegOpenKeyEx(thiskey,lpSubKey,0,AlterRegistrySAM(KEY_ENUMERATE_SUB_KEYS),&key);
- if (retval==ERROR_SUCCESS)
- {
- // NB - don't change this to static (recursive function)
- char buffer[MAX_PATH+1];
- while (RegEnumKey(key,0,buffer,MAX_PATH+1)==ERROR_SUCCESS)
- {
- if (onlyifempty)
- {
- RegCloseKey(key);
- return !ERROR_SUCCESS;
- }
- if ((retval=myRegDeleteKeyEx(key,buffer,0)) != ERROR_SUCCESS) break;
- }
- RegCloseKey(key);
- {
- typedef LONG (WINAPI * RegDeleteKeyExAPtr)(HKEY, LPCTSTR, REGSAM, DWORD);
- RegDeleteKeyExAPtr RDKE = (RegDeleteKeyExAPtr)
- myGetProcAddress(MGA_RegDeleteKeyExA);
-
- if (RDKE)
- retval=RDKE(thiskey,lpSubKey,AlterRegistrySAM(0),0);
- else
- retval=g_exec_flags.alter_reg_view||RegDeleteKey(thiskey,lpSubKey);
- }
- }
- return retval;
-}
-
-static HKEY NSISCALL GetRegRootKey(int hRootKey)
-{
- if (hRootKey)
- return (HKEY) hRootKey;
-
- // HKEY_LOCAL_MACHINE - HKEY_CURRENT_USER == 1
- return (HKEY) ((int) HKEY_CURRENT_USER + g_exec_flags.all_user_var);
-}
-
-static HKEY NSISCALL myRegOpenKey(REGSAM samDesired)
-{
- HKEY hKey;
- if (RegOpenKeyEx(GetRegRootKey(parms[1]), GetStringFromParm(0x22), 0, AlterRegistrySAM(samDesired), &hKey) == ERROR_SUCCESS)
- {
- return hKey;
- }
- return NULL;
-}
-#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS
-
-// returns EXEC_ERROR on error
-// returns 0, advance position by 1
-// otherwise, returns new_position+1
-static int NSISCALL ExecuteEntry(entry *entry_)
-{
- char *buf0 = bufs[0];
- char *buf1 = bufs[1];
- char *buf2 = bufs[2];
- char *buf3 = bufs[3];
- //char *buf4 = bufs[4];
-
- char *var0;
- char *var1;
- //char *var2;
- //char *var3;
- //char *var4;
- //char *var5;
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- // Saves 8 bytes
- HWND mainHwnd = g_hwnd;
-#define g_hwnd mainHwnd
-#endif
-
- int exec_error = 0;
-
- entry lent = *entry_;
-
-#define which (lent.which)
-#define parm0 (lent.offsets[0])
-#define parm1 (lent.offsets[1])
-#define parm2 (lent.offsets[2])
-#define parm3 (lent.offsets[3])
-#define parm4 (lent.offsets[4])
-#define parm5 (lent.offsets[5])
-
- var0 = g_usrvars[parm0];
- var1 = g_usrvars[parm1];
- // not used yet
- //var2 = g_usrvars[parm2];
- //var3 = g_usrvars[parm3];
- //var4 = g_usrvars[parm4];
- //var5 = g_usrvars[parm5];
-
- parms = lent.offsets;
-
- switch (which)
- {
- case EW_NOP:
- log_printf2("Jump: %d",parm0);
- return parm0;
- case EW_ABORT:
- {
- log_printf2("Aborting: \"%s\"",GetStringFromParm(0x00));
- update_status_text(parm0,0);
- }
- return EXEC_ERROR;
- case EW_QUIT:
- g_quit_flag++;
- if (g_hwnd) PostQuitMessage(0); // make sure we bail out fast.
- return EXEC_ERROR;
- case EW_CALL:
- {
- int v=resolveaddr(parm0)-1; // address is -1, since we encode it as +1
- log_printf2("Call: %d",v);
- return ExecuteCodeSegment(v,NULL);
- }
- case EW_UPDATETEXT:
- log_printf2("detailprint: %s",GetStringFromParm(0x00));
- update_status_text(parm0,0);
- break;
- case EW_SLEEP:
- {
- int x=GetIntFromParm(0);
- log_printf2("Sleep(%d)",x);
- Sleep(max(x,1));
- }
- break;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- case EW_BRINGTOFRONT:
- log_printf("BringToFront");
- SetForegroundWindow(g_hwnd);
- break;
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- case EW_SETFLAG:
- if (!parm2)
- {
- FIELDN(g_exec_flags_last_used,parm0)=FIELDN(g_exec_flags,parm0);
- FIELDN(g_exec_flags,parm0)=GetIntFromParm(1);
- }
- else
- {
- FIELDN(g_exec_flags,parm0)=FIELDN(g_exec_flags_last_used,parm0);
- }
- break;
- case EW_IFFLAG:
- {
- int f=lent.offsets[!FIELDN(g_exec_flags,parm2)];
- FIELDN(g_exec_flags,parm2)&=parm3;
- return f;
- }
- case EW_GETFLAG:
- myitoa(var0,FIELDN(g_exec_flags,parm1));
- break;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- case EW_CHDETAILSVIEW:
- if (insthwndbutton) ShowWindow(insthwndbutton,parm1);
- if (insthwnd) ShowWindow(insthwnd,parm0);
- break;
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- case EW_SETFILEATTRIBUTES:
- {
- char *buf1=GetStringFromParm(-0x10);
- log_printf3("SetFileAttributes: \"%s\":%08X",buf1,parm1);
- if (!SetFileAttributes(buf1,parm1))
- {
- exec_error++;
- log_printf("SetFileAttributes failed.");
- }
- }
- break;
- case EW_CREATEDIR: {
- char *buf1=GetStringFromParm(-0x10);
- log_printf3("CreateDirectory: \"%s\" (%d)",buf1,parm1);
- {
- char *p = skip_root(buf1);
- char c = 'c';
- if (p)
- {
- while (c)
- {
- p = findchar(p, '\\');
- c = *p;
- *p = 0;
- if (!CreateDirectory(buf1, NULL))
- {
- if (GetLastError() != ERROR_ALREADY_EXISTS)
- {
- log_printf3("CreateDirectory: can't create \"%s\" (err=%d)",buf1,GetLastError());
- exec_error++;
- }
- else if ((GetFileAttributes(buf1) & FILE_ATTRIBUTE_DIRECTORY) == 0)
- {
- log_printf2("CreateDirectory: can't create \"%s\" - a file already exists",buf1);
- exec_error++;
- }
- }
- *p++ = c;
- }
- }
- }
- if (parm1)
- {
- update_status_text_buf1(LANG_OUTPUTDIR);
- mystrcpy(state_output_directory,buf1);
- SetCurrentDirectory(buf1);
- }
- else update_status_text_buf1(LANG_CREATEDIR);
- }
- break;
- case EW_IFFILEEXISTS:
- {
- char *buf0=GetStringFromParm(0x00);
- if (file_exists(buf0))
- {
- log_printf3("IfFileExists: file \"%s\" exists, jumping %d",buf0,parm1);
- return parm1;
- }
- log_printf3("IfFileExists: file \"%s\" does not exist, jumping %d",buf0,parm2);
- }
- return parm2;
-#ifdef NSIS_SUPPORT_RENAME
- case EW_RENAME:
- {
- char *buf3=GetStringFromParm(-0x30);
- char *buf2=GetStringFromParm(-0x21);
- char *buf1=GetStringFromParm(0x13);
- log_printf2("Rename: %s",buf1);
- if (MoveFile(buf3,buf2))
- {
- update_status_text_buf1(LANG_RENAME);
- }
- else
- {
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- if (parm2 && file_exists(buf3))
- {
- MoveFileOnReboot(buf3,buf2);
- update_status_text_buf1(LANG_RENAMEONREBOOT);
- log_printf2("Rename on reboot: %s",buf1);
- }
- else
-#endif
- {
- exec_error++;
- log_printf2("Rename failed: %s",buf1);
- }
- }
- }
- break;
-#endif//NSIS_SUPPORT_RENAME
-#ifdef NSIS_SUPPORT_FNUTIL
- case EW_GETFULLPATHNAME:
- {
- char *fp;
- char *p=var1;
- char *buf0=GetStringFromParm(0x00);
- if (!GetFullPathName(buf0,NSIS_MAX_STRLEN,p,&fp))
- {
- exec_error++;
- *p=0;
- }
- else if (fp>buf0 && *fp)
- {
- WIN32_FIND_DATA *fd=file_exists(buf0);
- if (fd)
- {
- mystrcpy(fp,fd->cFileName);
- }
- else
- {
- exec_error++;
- *p=0;
- }
- }
- if (!parm2) GetShortPathName(p,p,NSIS_MAX_STRLEN);
- }
- break;
- case EW_SEARCHPATH:
- {
- char *fp;
- char *p=var0;
- char *buf0=GetStringFromParm(-0x01);
- if (!SearchPath(NULL,buf0,NULL,NSIS_MAX_STRLEN,p,&fp))
- {
- exec_error++;
- p[0]=0;
- }
- }
- break;
- case EW_GETTEMPFILENAME:
- {
- char *textout=var0;
- if (!my_GetTempFileName(textout, GetStringFromParm(-0x11)))
- exec_error++;
- }
- break;
-#endif
-#ifdef NSIS_SUPPORT_FILE
- case EW_EXTRACTFILE:
- {
- HANDLE hOut;
- int ret;
- char *buf3 = GetStringFromParm(0x31);
- int overwriteflag = parm0 & 7;
-
- log_printf4("File: overwriteflag=%d, allowskipfilesflag=%d, name=\"%s\"",overwriteflag,(parm0>>3)&MB_ABORTRETRYIGNORE,buf3);
- if (validpathspec(buf3))
- {
- mystrcpy(buf0,buf3);
- }
- else mystrcat(addtrailingslash(mystrcpy(buf0,state_output_directory)),buf3);
- validate_filename(buf0);
- _tryagain:
- if (overwriteflag >= 3) // check date and time
- {
- WIN32_FIND_DATA *ffd=file_exists(buf0);
- // if it doesn't exist, overwrite flag will be off (though it doesn't really matter)
- int cmp=0;
- if (ffd)
- {
- cmp=CompareFileTime(&ffd->ftLastWriteTime, (FILETIME*)(lent.offsets + 3));
- }
- overwriteflag=!(cmp & (0x80000000 | (overwriteflag - 3)));
- }
- // remove read only flag if overwrite mode is on
- if (!overwriteflag)
- {
- remove_ro_attr(buf0);
- }
- hOut=myOpenFile(buf0,GENERIC_WRITE,(overwriteflag==1)?CREATE_NEW:CREATE_ALWAYS);
- if (hOut == INVALID_HANDLE_VALUE)
- {
- if (overwriteflag)
- {
- update_status_text(LANG_SKIPPED,buf3);
- if (overwriteflag==2) exec_error++;
- log_printf3("File: skipped: \"%s\" (overwriteflag=%d)",buf0,overwriteflag);
- break;
- }
- log_printf2("File: error creating \"%s\"",buf0);
-
- mystrcpy(buf2,g_usrvars[0]); // save $0
- mystrcpy(g_usrvars[0],buf0); // copy file name to $0
- GetNSISString(buf1,parm5); // use $0
- mystrcpy(g_usrvars[0],buf2); // restore $0
-
- // Modified by ramon 23 May 2003
- switch (my_MessageBox(buf1, parm0>>3))
- {
- case IDRETRY:
- log_printf("File: error, user retry");
- goto _tryagain;
- case IDIGNORE:
- log_printf("File: error, user cancel");
- g_exec_flags.exec_error++;
- return 0;
- default:
- log_printf("File: error, user abort");
- update_status_text(LANG_CANTWRITE,buf0);
- return EXEC_ERROR;
- }
- }
-
- update_status_text(LANG_EXTRACT,buf3);
- {
- g_exec_flags.status_update++;
- ret=GetCompressedDataFromDataBlock(parm2,hOut);
- g_exec_flags.status_update--;
- }
-
- log_printf3("File: wrote %d to \"%s\"",ret,buf0);
-
- if (parm3 != 0xffffffff || parm4 != 0xffffffff)
- SetFileTime(hOut,(FILETIME*)(lent.offsets+3),NULL,(FILETIME*)(lent.offsets+3));
-
- CloseHandle(hOut);
-
- if (ret < 0)
- {
- if (ret == -2)
- {
- GetNSISString(buf0,LANG_ERRORWRITING);
- mystrcat(buf0,buf3);
- }
- else
- {
- GetNSISString(buf0,LANG_ERRORDECOMPRESSING);
- }
- log_printf2("%s",buf0);
- my_MessageBox(buf0,MB_OK|MB_ICONSTOP|(IDOK<<21));
- return EXEC_ERROR;
- }
- }
- break;
-#endif//NSIS_SUPPORT_FILE
-#ifdef NSIS_SUPPORT_DELETE
- case EW_DELETEFILE:
- {
- char *buf0=GetStringFromParm(0x00);
- log_printf2("Delete: \"%s\"",buf0);
- myDelete(buf0,parm1);
- }
- break;
-#endif//NSIS_SUPPORT_DELETE
-#ifdef NSIS_SUPPORT_MESSAGEBOX
- case EW_MESSAGEBOX: // MessageBox
- {
- int v;
- char *buf3=GetStringFromParm(0x31);
- log_printf3("MessageBox: %d,\"%s\"",parm0,buf3);
- v=my_MessageBox(buf3,parm0);
- if (v)
- {
- if (v==parm2)
- {
- return parm3;
- }
- if (v==parm4)
- {
- return parm5;
- }
- }
- else exec_error++;
- }
- break;
-#endif//NSIS_SUPPORT_MESSAGEBOX
-#ifdef NSIS_SUPPORT_RMDIR
- case EW_RMDIR:
- {
- char *buf1=GetStringFromParm(-0x10);
- log_printf2("RMDir: \"%s\"",buf1);
-
- myDelete(buf1,parm1);
- }
- break;
-#endif//NSIS_SUPPORT_RMDIR
-#ifdef NSIS_SUPPORT_STROPTS
- case EW_STRLEN:
- {
- char *buf0=GetStringFromParm(0x01);
- myitoa(var0,mystrlen(buf0));
- }
- break;
- case EW_ASSIGNVAR:
- {
- int newlen=GetIntFromParm(2);
- int start=GetIntFromParm(3);
- int l;
- char *p=var0;
- char *buf0=GetStringFromParm(0x01);
- *p=0;
- if (!parm2 || newlen)
- {
- l=mystrlen(buf0);
-
- if (start<0) start=l+start;
- if (start>=0)
- {
- if (start>l) start=l;
- mystrcpy(p,buf0+start);
- if (newlen)
- {
- if (newlen<0) newlen=mystrlen(p)+newlen;
- if (newlen<0) newlen=0;
- if (newlen < NSIS_MAX_STRLEN) p[newlen]=0;
- }
- }
- }
- }
- break;
- case EW_STRCMP:
- {
- char *buf2=GetStringFromParm(0x20);
- char *buf3=GetStringFromParm(0x31);
- if (!parm4) {
- // case insensitive
- if (!lstrcmpi(buf2,buf3)) return parm2;
- }
- else {
- // case sensitive
- if (!lstrcmp(buf2,buf3)) return parm2;
- }
- }
- return parm3;
-#endif//NSIS_SUPPORT_STROPTS
-#ifdef NSIS_SUPPORT_ENVIRONMENT
- case EW_READENVSTR:
- {
- char *p=var0;
- char *buf0=GetStringFromParm(0x01);
- if (!ExpandEnvironmentStrings(buf0,p,NSIS_MAX_STRLEN)
- || (parm2 && !lstrcmp(buf0, p)))
- {
- exec_error++;
- *p=0;
- }
- p[NSIS_MAX_STRLEN-1]=0;
- }
- break;
-#endif//NSIS_SUPPORT_ENVIRONMENT
-#ifdef NSIS_SUPPORT_INTOPTS
- case EW_INTCMP:
- {
- int v,v2;
- v=GetIntFromParm(0);
- v2=GetIntFromParm(1);
- if (!parm5) {
- // signed
- if (v<v2) return parm3;
- if (v>v2) return parm4;
- }
- else {
- // unsigned
- if ((unsigned int)v<(unsigned int)v2) return parm3;
- if ((unsigned int)v>(unsigned int)v2) return parm4;
- }
- }
- return parm2;
- case EW_INTOP:
- {
- int v,v2;
- char *p=var0;
- v=GetIntFromParm(1);
- v2=GetIntFromParm(2);
- switch (parm3)
- {
- case 0: v+=v2; break;
- case 1: v-=v2; break;
- case 2: v*=v2; break;
- case 3: if (v2) v/=v2; else { v=0; exec_error++; } break;
- case 4: v|=v2; break;
- case 5: v&=v2; break;
- case 6: v^=v2; break;
- case 7: v=!v; break;
- case 8: v=v||v2; break;
- case 9: v=v&&v2; break;
- case 10: if (v2) v%=v2; else { v=0; exec_error++; } break;
- case 11: v=v<<v2; break;
- case 12: v=v>>v2; break;
- }
- myitoa(p,v);
- }
- break;
- case EW_INTFMT: {
- char *buf0=GetStringFromParm(0x01);
- wsprintf(var0,
- buf0,
- GetIntFromParm(2));
- }
- break;
-#endif//NSIS_SUPPORT_INTOPTS
-#ifdef NSIS_SUPPORT_STACK
- case EW_PUSHPOP:
- {
- stack_t *s=g_st;
- int cnt=parm2;
- if (cnt) //Exch contributed by Fritz Elfert
- {
- while (cnt--&&s) s=s->next;
- if (!s)
- {
- log_printf2("Exch: stack < %d elements",parm2);
- my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21));
- return EXEC_ERROR;
- }
- mystrcpy(buf0,s->text);
- mystrcpy(s->text,g_st->text);
- mystrcpy(g_st->text,buf0);
- }
- else if (parm1)
- {
- if (!s)
- {
- log_printf("Pop: stack empty");
- exec_error++;
- break;
- }
- mystrcpy(var0,s->text);
- g_st=s->next;
- GlobalFree((HGLOBAL)s);
- }
- else
- {
- s=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t));
- GetNSISString(s->text,parm0);
- s->next=g_st;
- g_st=s;
- }
- }
- break;
-#endif//NSIS_SUPPORT_STACK
-#ifdef NSIS_SUPPORT_HWNDS
- case EW_FINDWINDOW:
- case EW_SENDMESSAGE:
- {
- int v;
- int b3=GetIntFromParm(3);
- int b4=GetIntFromParm(4);
- if (parm5&1) b3=(int)GetStringFromParm(0x33);
- if (parm5&2) b4=(int)GetStringFromParm(0x44);
-
- if (which == EW_SENDMESSAGE)
- {
- HWND hwnd=(HWND)GetIntFromParm(1);
- int msg=GetIntFromParm(2);
-
- if (parm5>>2) exec_error += !SendMessageTimeout(hwnd,msg,b3,b4,SMTO_NORMAL,parm5>>2,(LPDWORD)&v);
- else v=SendMessage(hwnd,msg,b3,b4);
- }
- else
- {
- char *buf0=GetStringFromParm(0x01);
- char *buf1=GetStringFromParm(0x12);
- v=(int)FindWindowEx((HWND)b3,(HWND)b4,buf0[0]?buf0:NULL,buf1[0]?buf1:NULL);
- }
-
- if (parm0>=0)
- myitoa(var0,v);
- }
- break;
- case EW_ISWINDOW:
- if (IsWindow((HWND)GetIntFromParm(0))) return parm1;
- return parm2;
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- case EW_GETDLGITEM:
- myitoa(
- var0,
- (int)GetDlgItem(
- (HWND)GetIntFromParm(1),
- GetIntFromParm(2)
- )
- );
- break;
- case EW_SETCTLCOLORS:
- {
- ctlcolors *c = (ctlcolors *)(g_blocks[NB_CTLCOLORS].offset + parm1);
- SetWindowLong((HWND) GetIntFromParm(0), GWL_USERDATA, (long) c);
- }
- break;
- case EW_SETBRANDINGIMAGE:
- {
- RECT r;
- HANDLE hImage;
- HWND hwImage=GetDlgItem(g_hwnd, parm1);
- GetClientRect(hwImage, &r);
- hImage=LoadImage(
- 0,
- GetStringFromParm(0x00),
- IMAGE_BITMAP,
- parm2*r.right,
- parm2*r.bottom,
- LR_LOADFROMFILE
- );
- hImage = (HANDLE)SendMessage(
- hwImage,
- STM_SETIMAGE,
- IMAGE_BITMAP,
- (LPARAM)hImage
- );
- // delete old image
- if (hImage) DeleteObject(hImage);
- }
- break;
- case EW_CREATEFONT:
- {
- static LOGFONT f;
- f.lfHeight=-MulDiv(GetIntFromParm(2),GetDeviceCaps(GetDC(g_hwnd),LOGPIXELSY),72);
- f.lfWeight=GetIntFromParm(3);
- f.lfItalic=parm4&1;
- f.lfUnderline=parm4&2;
- f.lfStrikeOut=parm4&4;
- f.lfCharSet=DEFAULT_CHARSET;
- GetNSISString(f.lfFaceName,parm1);
- myitoa(var0,(int)CreateFontIndirect(&f));
- }
- break;
- case EW_SHOWWINDOW:
- {
- HWND hw=(HWND)GetIntFromParm(0);
- int a=GetIntFromParm(1);
- if (parm2) log_printf("HideWindow");
- if (!parm3)
- ShowWindow(hw,a);
- else
- EnableWindow(hw,a);
- }
- break;
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
-#endif//NSIS_SUPPORT_HWNDS
-#ifdef NSIS_SUPPORT_SHELLEXECUTE
- case EW_SHELLEXEC: // this uses improvements of Andras Varga
- {
- int x;
- char *buf0=GetStringFromParm(0x00);
- char *buf3=GetStringFromParm(0x31);
- char *buf2=GetStringFromParm(0x22);
- char *buf1=GetStringFromParm(0x15);
- update_status_text_buf1(LANG_EXECSHELL);
- x=(int)ShellExecute(g_hwnd,buf0[0]?buf0:NULL,buf3,buf2[0]?buf2:NULL,state_output_directory,parm3);
- if (x < 33)
- {
- log_printf5("ExecShell: warning: error (\"%s\": file:\"%s\" params:\"%s\")=%d",buf0,buf3,buf2,x);
- exec_error++;
- }
- else
- {
- log_printf4("ExecShell: success (\"%s\": file:\"%s\" params:\"%s\")",buf0,buf3,buf2);
- }
- }
- break;
-#endif//NSIS_SUPPORT_SHELLEXECUTE
-#ifdef NSIS_SUPPORT_EXECUTE
- case EW_EXECUTE:
- {
- HANDLE hProc;
- char *buf0=GetStringFromParm(0x00);
- log_printf2("Exec: command=\"%s\"",buf0);
- update_status_text(LANG_EXECUTE,buf0);
-
- hProc=myCreateProcess(buf0);
-
- if (hProc)
- {
- log_printf2("Exec: success (\"%s\")",buf0);
- if (parm2)
- {
- DWORD lExitCode;
- while (WaitForSingleObject(hProc,100) == WAIT_TIMEOUT)
- {
- MessageLoop(WM_PAINT);
- }
- GetExitCodeProcess(hProc, &lExitCode);
-
- if (parm1>=0) myitoa(var1,lExitCode);
- else if (lExitCode) exec_error++;
- }
- CloseHandle( hProc );
- }
- else
- {
- exec_error++;
- log_printf2("Exec: failed createprocess (\"%s\")",buf0);
- }
- }
- break;
-#endif//NSIS_SUPPORT_EXECUTE
-#ifdef NSIS_SUPPORT_GETFILETIME
- case EW_GETFILETIME:
- // this new implementation based on one by Dave Bau
- // used FindFirstFile instead of GetFileTime to better handle files that are locked.
- // also allows GetFileTime to be passed a wildcard.
- {
- WIN32_FIND_DATA *ffd;
- char *highout=var0;
- char *lowout=var1;
- char *buf0=GetStringFromParm(0x02);
-
- ffd=file_exists(buf0);
- if (ffd)
- {
- myitoa(lowout,ffd->ftLastWriteTime.dwLowDateTime);
- myitoa(highout,ffd->ftLastWriteTime.dwHighDateTime);
- }
- else
- {
- *lowout=*highout=0;
- exec_error++;
- }
- }
- break;
-#endif//NSIS_SUPPORT_GETFILETIME
-#ifdef NSIS_SUPPORT_GETDLLVERSION
- case EW_GETDLLVERSION:
- {
- char *highout=var0;
- char *lowout=var1;
- DWORD s1;
- VS_FIXEDFILEINFO *pvsf1;
- DWORD d;
- char *buf1=GetStringFromParm(-0x12);
- s1=GetFileVersionInfoSize(buf1,&d);
- *lowout=*highout=0;
- exec_error++;
- if (s1)
- {
- void *b1;
- b1=GlobalAlloc(GPTR,s1);
- if (b1)
- {
- UINT uLen;
- if (GetFileVersionInfo(buf1,0,s1,b1) && VerQueryValue(b1,"\\",(void*)&pvsf1,&uLen))
- {
- myitoa(highout,pvsf1->dwFileVersionMS);
- myitoa(lowout,pvsf1->dwFileVersionLS);
-
- exec_error--;
- }
- GlobalFree(b1);
- }
- }
- }
- break;
-#endif//NSIS_SUPPORT_GETDLLVERSION
-#ifdef NSIS_SUPPORT_ACTIVEXREG
- case EW_REGISTERDLL:
- {
- exec_error++;
- if (SUCCEEDED(g_hres))
- {
- HANDLE h=NULL;
- char *buf1=GetStringFromParm(-0x10);
- char *buf0=GetStringFromParm(0x01);
-
- if (parm4)
- h=GetModuleHandle(buf1);
- if (!h)
- h=LoadLibraryEx(buf1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
- if (h)
- {
- FARPROC funke = GetProcAddress(h,buf0);
- if (funke)
- {
- exec_error--;
- if (parm2)
- {
- update_status_text_buf1(parm2);
- if (funke()) exec_error++;
- }
- else
- {
- void (*func)(HWND,int,char*,void*,void*);
- func=(void*)funke;
- func(
- g_hwnd,
- NSIS_MAX_STRLEN,
- (char*)g_usrvars,
-#ifdef NSIS_SUPPORT_STACK
- (void*)&g_st,
-#else
- NULL,
-#endif//NSIS_SUPPORT_STACK
- &plugin_extra_parameters
- );
- }
- }
- else
- {
- update_status_text(LANG_CANNOTFINDSYMBOL,buf0);
- log_printf3("Error registering DLL: %s not found in %s",buf0,buf1);
- }
- if (!parm3) FreeLibrary(h);
- }
- else
- {
- update_status_text_buf1(LANG_COULDNOTLOAD);
- log_printf2("Error registering DLL: Could not load %s",buf1);
- }
- }
- else
- {
- update_status_text_buf1(LANG_NOOLE);
- log_printf("Error registering DLL: Could not initialize OLE");
- }
- }
- break;
-#endif
-#ifdef NSIS_SUPPORT_CREATESHORTCUT
- case EW_CREATESHORTCUT:
- {
- char *buf1=GetStringFromParm(-0x10);
- char *buf2=GetStringFromParm(-0x21);
- char *buf0=GetStringFromParm(0x02);
- char *buf3=GetStringFromParm(-0x33);
- char *buf4=GetStringFromParm(0x45);
-
- HRESULT hres;
- IShellLink* psl;
-
- if (!validpathspec(buf2))
- GetStringFromParm(0x21);
-
- log_printf8("CreateShortCut: out: \"%s\", in: \"%s %s\", icon: %s,%d, sw=%d, hk=%d",
- buf1,buf2,buf0,buf3,parm4&0xff,(parm4&0xff00)>>8,parm4>>16);
-
- 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,buf2);
- psl->lpVtbl->SetWorkingDirectory(psl,state_output_directory);
- if ((parm4&0xff00)>>8) psl->lpVtbl->SetShowCmd(psl,(parm4&0xff00)>>8);
- psl->lpVtbl->SetHotkey(psl,(unsigned short)(parm4>>16));
- if (buf3[0]) psl->lpVtbl->SetIconLocation(psl,buf3,parm4&0xff);
- psl->lpVtbl->SetArguments(psl,buf0);
- psl->lpVtbl->SetDescription(psl,buf4);
-
- if (SUCCEEDED(hres))
- {
- static WCHAR wsz[1024];
- hres=E_FAIL;
- if (MultiByteToWideChar(CP_ACP, 0, buf1, -1, wsz, 1024))
- hres=ppf->lpVtbl->Save(ppf,(const WCHAR*)wsz,TRUE);
- }
- ppf->lpVtbl->Release(ppf);
- }
- psl->lpVtbl->Release(psl);
- }
-
- if (FAILED(hres))
- {
- exec_error++;
- update_status_text_buf1(LANG_ERRORCREATINGSHORTCUT);
- }
- else
- {
- update_status_text_buf1(LANG_CREATESHORTCUT);
- }
- }
- break;
-#endif//NSIS_SUPPORT_CREATESHORTCUT
-#ifdef NSIS_SUPPORT_COPYFILES
- case EW_COPYFILES: // CopyFile (added by NOP)
- {
- int res;
- SHFILEOPSTRUCT op;
- char *buf0=GetStringFromParm(0x00);
- char *buf1=GetStringFromParm(0x11);
- char *buf2=GetStringFromParm(0x23); // LANG_COPYTO + buf1
- log_printf3("CopyFiles \"%s\"->\"%s\"",buf0,buf1);
-
- if (!file_exists(buf0))
- {
- // workaround for bug #774966
- //
- // on nt4, SHFileOperation silently fails if the source
- // file doesn't exist. do a manual check instead.
-
- update_status_text(LANG_COPYFAILED,0);
- exec_error++;
- break;
- }
-
- op.hwnd=g_hwnd;
- op.wFunc=FO_COPY;
- buf0[mystrlen(buf0)+1]=0;
- buf1[mystrlen(buf1)+1]=0;
-
- op.pFrom=buf0;
- op.pTo=buf1;
- op.lpszProgressTitle=buf2;
- op.fFlags=parm2;
- update_status_text(0,buf2);
- res=SHFileOperation(&op);
- if (res)
- { // some of these changes were from Edgewise (wiked_edge@yahoo.com)
- update_status_text(LANG_COPYFAILED,0);
- exec_error++;
- }
- }
- break;
-#endif//NSIS_SUPPORT_COPYFILES
-#ifdef NSIS_SUPPORT_REBOOT
- case EW_REBOOT:
- if (parm0!=0xbadf00d)
- {
- my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21));
- return EXEC_ERROR;
- }
-
- g_exec_flags.reboot_called++;
- // a following EW_QUIT will make sure the installer quits right away
-
- break;
-#endif//NSIS_SUPPORT_REBOOT
-#ifdef NSIS_SUPPORT_INIFILES
- case EW_WRITEINI:
- {
- char *sec=0, *key=0, *str=0;
-#ifdef NSIS_CONFIG_LOG
- mystrcpy(buf1,"<RM>");
- mystrcpy(buf2,buf1);
-#endif
- if (parm0)
- {
- sec=GetStringFromParm(0x00);
- }
- if (parm1)
- {
- key=GetStringFromParm(0x11);
- }
- if (parm4)
- {
- str=GetStringFromParm(0x22);
- }
- buf3=GetStringFromParm(-0x33);
- log_printf5("WriteINIStr: wrote [%s] %s=%s in %s",buf0,buf1,buf2,buf3);
- if (!WritePrivateProfileString(sec,key,str,buf3)) exec_error++;
- }
- break;
- case EW_READINISTR:
- {
- DWORD errstr = CHAR4_TO_DWORD('!', 'N', '~', 0);
- char *p=var0;
- char *buf0=GetStringFromParm(0x01);
- char *buf1=GetStringFromParm(0x12);
- char *buf2=GetStringFromParm(-0x23);
- GetPrivateProfileString(buf0,buf1,(LPCSTR)&errstr,p,NSIS_MAX_STRLEN-1,buf2);
- if (*(DWORD*)p == errstr)
- {
- exec_error++;
- p[0]=0;
- }
- }
- break;
-#endif//NSIS_SUPPORT_INIFILES
-#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
- case EW_DELREG:
- {
- long res=!ERROR_SUCCESS;
- const char *rkn UNUSED=RegKeyHandleToName((HKEY)parm1);
- if (!parm4)
- {
- HKEY hKey=myRegOpenKey(KEY_SET_VALUE);
- if (hKey)
- {
- char *buf3=GetStringFromParm(0x33);
- res = RegDeleteValue(hKey,buf3);
- log_printf4("DeleteRegValue: \"%s\\%s\" \"%s\"",rkn,buf2,buf3);
- RegCloseKey(hKey);
- }
- }
- else
- {
- char *buf2=GetStringFromParm(0x22);
- log_printf3("DeleteRegKey: \"%s\\%s\"",rkn,buf2);
- res = myRegDeleteKeyEx(GetRegRootKey(parm1),buf2,parm4&2);
- }
- if (res != ERROR_SUCCESS)
- exec_error++;
- }
- break;
- case EW_WRITEREG: // write registry value
- {
- HKEY hKey;
- HKEY rootkey=GetRegRootKey(parm0);
- int type=parm4;
- int rtype=parm5;
- char *buf0=GetStringFromParm(0x02);
- char *buf1=GetStringFromParm(0x11);
- const char *rkn UNUSED=RegKeyHandleToName(rootkey);
-
- exec_error++;
- if (RegCreateKeyEx(rootkey,buf1,0,0,0,AlterRegistrySAM(KEY_SET_VALUE),0,&hKey,0) == ERROR_SUCCESS)
- {
- LPBYTE data = (LPBYTE) buf2;
- DWORD size = 0;
- if (type == REG_SZ)
- {
- GetStringFromParm(0x23);
- size = mystrlen((char *) data) + 1;
- if (rtype == REG_SZ)
- {
- log_printf5("WriteRegStr: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,data);
- }
- else
- {
- log_printf5("WriteRegExpandStr: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,data);
- }
- }
- if (type == REG_DWORD)
- {
- *(LPDWORD) data = GetIntFromParm(3);
- size = sizeof(DWORD);
- log_printf5("WriteRegDWORD: \"%s\\%s\" \"%s\"=\"0x%08x\"",rkn,buf1,buf0,*(LPDWORD) data);
- }
- if (type == REG_BINARY)
- {
-#ifdef NSIS_CONFIG_LOG
- char binbuf[128];
-#endif
- // use buf2, buf3 and buf4
- size = GetCompressedDataFromDataBlockToMemory(parm3, data, 3 * NSIS_MAX_STRLEN);
- LogData2Hex(binbuf, sizeof(binbuf), data, size);
- log_printf5("WriteRegBin: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,binbuf);
- }
-
- if (size >= 0 && RegSetValueEx(hKey,buf0,0,rtype,data,size) == ERROR_SUCCESS)
- {
- exec_error--;
- }
- else
- {
- log_printf4("WriteReg: error writing into \"%s\\%s\" \"%s\"",rkn,buf1,buf0);
- }
-
- RegCloseKey(hKey);
- }
- else { log_printf3("WriteReg: error creating key \"%s\\%s\"",rkn,buf1); }
- }
- break;
- case EW_READREGSTR: // read registry string
- {
- HKEY hKey=myRegOpenKey(KEY_READ);
- char *p=var0;
- char *buf3=GetStringFromParm(0x33); // buf3 == key name
- p[0]=0;
- if (hKey)
- {
- DWORD l = NSIS_MAX_STRLEN - 1;
- DWORD t;
-
- if (RegQueryValueEx(hKey,buf3,NULL,&t,p,&l) != ERROR_SUCCESS ||
- (t != REG_DWORD && t != REG_SZ && t != REG_EXPAND_SZ))
- {
- p[0]=0;
- exec_error++;
- }
- else
- {
- if (t==REG_DWORD)
- {
- exec_error += !parm4;
- myitoa(p,*((DWORD*)p));
- }
- else
- {
- exec_error += parm4;
- p[l]=0;
- }
- }
- RegCloseKey(hKey);
- }
- else exec_error++;
- }
- break;
- case EW_REGENUM:
- {
- HKEY key=myRegOpenKey(KEY_READ);
- char *p=var0;
- int b=GetIntFromParm(3);
- p[0]=0;
- if (key)
- {
- DWORD d=NSIS_MAX_STRLEN-1;
- if (parm4) RegEnumKey(key,b,p,d);
- else if (RegEnumValue(key,b,p,&d,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
- {
- exec_error++;
- break;
- }
- p[NSIS_MAX_STRLEN-1]=0;
- RegCloseKey(key);
- }
- else exec_error++;
- }
-
- break;
-#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS
-#ifdef NSIS_SUPPORT_FILEFUNCTIONS
- case EW_FCLOSE:
- {
- char *t=var0;
- if (*t) CloseHandle((HANDLE)myatoi(t));
- }
- break;
- case EW_FOPEN:
- {
- HANDLE h;
- char *handleout=var0;
- char *buf1=GetStringFromParm(-0x13);
- h=myOpenFile(buf1,parm1,parm2);
- if (h == INVALID_HANDLE_VALUE)
- {
- *handleout=0;
- exec_error++;
- }
- else
- {
- myitoa(handleout,(int)h);
- }
- }
- break;
- case EW_FPUTS:
- {
- DWORD dw;
- int l;
- char *t=var0;
- if (parm2)
- {
- ((unsigned char *)buf1)[0]=GetIntFromParm(1)&0xff;
- l=1;
- }
- else
- {
- l=mystrlen(GetStringFromParm(0x11));
- }
- if (!*t || !WriteFile((HANDLE)myatoi(t),buf1,l,&dw,NULL))
- {
- exec_error++;
- }
- }
- break;
- case EW_FGETS:
- {
- char *textout=var1;
- DWORD dw;
- int rpos=0;
- char *hptr=var0;
- int maxlen=GetIntFromParm(2);
- if (maxlen<1) break;
- if (maxlen > NSIS_MAX_STRLEN-1) maxlen=NSIS_MAX_STRLEN-1;
- if (*hptr)
- {
- char lc=0;
- HANDLE h=(HANDLE)myatoi(hptr);
- while (rpos<maxlen)
- {
- char c;
- if (!ReadFile(h,&c,1,&dw,NULL) || dw != 1) break;
- if (parm3)
- {
- myitoa(textout,(unsigned int)(unsigned char)c);
- return 0;
- }
- if (lc == '\r' || lc == '\n')
- {
- if (lc == c || (c != '\r' && c != '\n')) SetFilePointer(h,-1,NULL,FILE_CURRENT);
- else textout[rpos++]=c;
- break;
- }
- textout[rpos++]=c;
- lc=c;
- if (!c) break;
- }
- }
- textout[rpos]=0;
- if (!rpos) exec_error++;
- }
- break;
- case EW_FSEEK:
- {
- char *t=var0;
- if (*t)
- {
- DWORD v=SetFilePointer((HANDLE)myatoi(t),GetIntFromParm(2),NULL,parm3);
-
- if (parm1>=0)
- {
- myitoa(var1,v);
- }
- }
- }
- break;
-#endif//NSIS_SUPPORT_FILEFUNCTIONS
-#ifdef NSIS_SUPPORT_FINDFIRST
- case EW_FINDCLOSE:
- {
- char *t=var0;
- if (*t) FindClose((HANDLE)myatoi(t));
- }
- break;
- case EW_FINDNEXT:
- {
- char *textout=var0;
- char *t=var1;
- WIN32_FIND_DATA fd;
- if (*t && FindNextFile((HANDLE)myatoi(t),&fd))
- {
- mystrcpy(textout,fd.cFileName);
- }
- else
- {
- exec_error++;
- *textout=0;
- }
-
- }
- break;
- case EW_FINDFIRST:
- {
- char *textout=var0;
- char *handleout=var1;
- HANDLE h;
- WIN32_FIND_DATA fd;
- char *buf0=GetStringFromParm(0x02);
- h=FindFirstFile(buf0,&fd);
- if (h == INVALID_HANDLE_VALUE)
- {
- *handleout=0;
- *textout=0;
- exec_error++;
- }
- else
- {
- myitoa(handleout,(int)h);
- mystrcpy(textout,fd.cFileName);
- }
- }
- break;
-#endif//NSIS_SUPPORT_FINDFIRST
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- case EW_WRITEUNINSTALLER:
- {
- int ret=-666;
- HANDLE hFile;
- char *buf1=GetStringFromParm(-0x10);
-
- if (!validpathspec(buf1))
- GetStringFromParm(-0x13);
-
- remove_ro_attr(buf1);
- hFile=myOpenFile(buf1,GENERIC_WRITE,CREATE_ALWAYS);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- unsigned char *filebuf;
- int filehdrsize = g_filehdrsize;
- filebuf=(unsigned char *)GlobalAlloc(GPTR,filehdrsize);
- if (filebuf)
- {
- DWORD lout;
- SetSelfFilePointer(0);
- ReadSelfFile((char*)filebuf,filehdrsize);
- {
- unsigned char* seeker;
- unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2);
- if (unicon_data) {
- GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2);
- while (*seeker) {
- struct icondata {
- DWORD dwSize;
- DWORD dwOffset;
- } id = *(struct icondata *) seeker;
- seeker += sizeof(struct icondata);
- mini_memcpy(filebuf+id.dwOffset, seeker, id.dwSize);
- seeker += id.dwSize;
- }
- GlobalFree(unicon_data);
- }
- }
- WriteFile(hFile,(char*)filebuf,filehdrsize,&lout,NULL);
- GlobalFree(filebuf);
- ret=GetCompressedDataFromDataBlock(-1,hFile);
- }
- CloseHandle(hFile);
- }
- log_printf3("created uninstaller: %d, \"%s\"",ret,buf1);
- {
- int str = LANG_CREATEDUNINST;
- if (ret < 0)
- {
- str = LANG_ERRORCREATING;
- DeleteFile(buf1);
- exec_error++;
- }
- update_status_text_buf1(str);
- }
- }
- break;
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-#ifdef NSIS_CONFIG_LOG
- case EW_LOG:
- if (parm0)
- {
- log_printf2("settings logging to %d",parm1);
- log_dolog=parm1;
- log_printf2("logging set to %d",parm1);
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
- if (parm1) build_g_logfile();
-#endif
- }
- else
- {
- char *buf0=GetStringFromParm(0x01);
- log_printf2("%s",buf0);
- }
- break;
-#endif//NSIS_CONFIG_LOG
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- case EW_SECTIONSET:
- {
- int x=GetIntFromParm(0);
- if ((unsigned int)x < (unsigned int)num_sections)
- {
- section *sec=g_sections+x;
- if (parm2>=0) // get something
- {
- int res=((int*)sec)[parm2];
- if (!parm2)
- {
- // getting text
- mystrcpy(var1,sec->name);
- }
- else
- {
- // getting number
- myitoa(var1,res);
- }
- }
- else // set something
- {
- parm2=-parm2-1;
- if (parm2)
- {
- // not setting text, get int
- parm1=GetIntFromParm(1);
- }
- else
- {
- // setting text
- GetNSISString(sec->name,parm4);
- sec->flags|=SF_NAMECHG;
- // parm1 is zero so name_ptr will be set to zero
- // if name_ptr is zero, it won't be used after .onInit
- }
-
- ((int*)sec)[parm2]=parm1;
-
- if (parm3) // update flags
- {
- SectionFlagsChanged(x);
- }
- }
- }
- else exec_error++;
- }
- break;
- case EW_INSTTYPESET:
- {
- int x = GetIntFromParm(0);
-
- if ((unsigned int)x < (unsigned int)NSIS_MAX_INST_TYPES)
- {
- if (parm3) // current install type
- {
- if (parm2) // set install type
- {
- SetInstType(x);
- RefreshSectionGroups();
- }
- else // get install type
- {
- myitoa(var1, GetInstType(0));
- }
- }
- else // install type text
- {
- if (parm2) // set text
- {
- g_header->install_types[x] = parm1;
- }
- else // get text
- {
- GetNSISString(var1,g_header->install_types[x]);
- }
- }
- }
- else exec_error++;
- }
- break;
-#endif//NSIS_CONFIG_COMPONENTPAGE
-
-#ifdef NSIS_LOCKWINDOW_SUPPORT
- case EW_LOCKWINDOW:
- {
- // ui_dlg_visible is 1 or 0, so is parm0
- SendMessage(g_hwnd, WM_SETREDRAW, parm0 & ui_dlg_visible, 0);
- if ( parm0 )
- InvalidateRect(g_hwnd, NULL, FALSE);
- break;
- }
-#endif //NSIS_LOCKWINDOW_SUPPORT
- }
-
- g_exec_flags.exec_error += exec_error;
-
- return 0;
-}
+/* + * exec.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include <shlobj.h> +#include <shellapi.h> +#include "fileform.h" +#include "util.h" +#include "state.h" +#include "ui.h" +#include "components.h" +#include "exec.h" +#include "lang.h" +#include "resource.h" + +#define EXEC_ERROR 0x7FFFFFFF + +#ifdef NSIS_CONFIG_COMPONENTPAGE +HWND g_SectionHack; +#endif + +#ifdef NSIS_SUPPORT_STACK +typedef struct _stack_t { + struct _stack_t *next; + char text[NSIS_MAX_STRLEN]; +} stack_t; + +static stack_t *g_st; +#endif + +exec_flags g_exec_flags; +exec_flags g_exec_flags_last_used; + +struct { + exec_flags *flags; + void *ExecuteCodeSegment; + void *validate_filename; +} plugin_extra_parameters = { + &g_exec_flags, + &ExecuteCodeSegment, + &validate_filename +}; + +#if defined(NSIS_SUPPORT_ACTIVEXREG) || defined(NSIS_SUPPORT_CREATESHORTCUT) +HRESULT g_hres; +#endif + +static int NSISCALL ExecuteEntry(entry *entry_); + +int NSISCALL resolveaddr(int v) +{ + if (v < 0) + { + return myatoi(g_usrvars[-(v+1)]); + } + return v; +} + +int NSISCALL ExecuteCodeSegment(int pos, HWND hwndProgress) +{ + while (pos >= 0) + { + int rv; + if (g_entries[pos].which == EW_RET) return 0; + rv=ExecuteEntry(g_entries + pos); + if (rv == EXEC_ERROR) return EXEC_ERROR; + + rv=resolveaddr(rv); + + if (!rv) { rv++; pos++; } + else + { + int t=pos; + rv--; // rv is decremented here by 1, since it was +1 on the other end. + pos=rv; // set new position + rv-=t; // set rv to delta for progress adjustment + } + + if (hwndProgress) + { + extern int progress_bar_pos, progress_bar_len; + progress_bar_pos+=rv; + SendMessage(hwndProgress,PBM_SETPOS,MulDiv(progress_bar_pos,30000,progress_bar_len),0); + } + } + return 0; +} + +#ifdef NSIS_SUPPORT_CODECALLBACKS + +int NSISCALL ExecuteCallbackFunction(int num) +{ + return ExecuteCodeSegment(*(&g_header->code_onInit + num), NULL); +} + +#endif + +static char bufs[5][NSIS_MAX_STRLEN]; +static int *parms; + +void NSISCALL update_status_text_buf1(int strtab) +{ + update_status_text(strtab, bufs[1]); +} + +static int NSISCALL GetIntFromParm(int id_) +{ + return myatoi(GetNSISStringTT(parms[id_])); +} + +// NB - USE CAUTION when rearranging code to make use of the new return value of +// this function - be sure the parm being accessed is not modified before the call. +// Use a negative number to get the string validated as a file name +static char * NSISCALL GetStringFromParm(int id_) +{ + int id = id_ < 0 ? -id_ : id_; + char *result = GetNSISString(bufs[id >> 4], parms[id & 0xF]); + if (id_ < 0) validate_filename(result); + return result; +} + +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + +#define AlterRegistrySAM(sam) (sam | g_exec_flags.alter_reg_view) + +// based loosely on code from Tim Kosse +// in win9x this isn't necessary (RegDeleteKey() can delete a tree of keys), +// but in win2k you need to do this manually. +static LONG NSISCALL myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey, int onlyifempty) +{ + HKEY key; + int retval=RegOpenKeyEx(thiskey,lpSubKey,0,AlterRegistrySAM(KEY_ENUMERATE_SUB_KEYS),&key); + if (retval==ERROR_SUCCESS) + { + // NB - don't change this to static (recursive function) + char buffer[MAX_PATH+1]; + while (RegEnumKey(key,0,buffer,MAX_PATH+1)==ERROR_SUCCESS) + { + if (onlyifempty) + { + RegCloseKey(key); + return !ERROR_SUCCESS; + } + if ((retval=myRegDeleteKeyEx(key,buffer,0)) != ERROR_SUCCESS) break; + } + RegCloseKey(key); + { + typedef LONG (WINAPI * RegDeleteKeyExAPtr)(HKEY, LPCTSTR, REGSAM, DWORD); + RegDeleteKeyExAPtr RDKE = (RegDeleteKeyExAPtr) + myGetProcAddress(MGA_RegDeleteKeyExA); + + if (RDKE) + retval=RDKE(thiskey,lpSubKey,AlterRegistrySAM(0),0); + else + retval=g_exec_flags.alter_reg_view||RegDeleteKey(thiskey,lpSubKey); + } + } + return retval; +} + +static HKEY NSISCALL GetRegRootKey(int hRootKey) +{ + if (hRootKey) + return (HKEY) hRootKey; + + // HKEY_LOCAL_MACHINE - HKEY_CURRENT_USER == 1 + return (HKEY) ((int) HKEY_CURRENT_USER + g_exec_flags.all_user_var); +} + +static HKEY NSISCALL myRegOpenKey(REGSAM samDesired) +{ + HKEY hKey; + if (RegOpenKeyEx(GetRegRootKey(parms[1]), GetStringFromParm(0x22), 0, AlterRegistrySAM(samDesired), &hKey) == ERROR_SUCCESS) + { + return hKey; + } + return NULL; +} +#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS + +// returns EXEC_ERROR on error +// returns 0, advance position by 1 +// otherwise, returns new_position+1 +static int NSISCALL ExecuteEntry(entry *entry_) +{ + char *buf0 = bufs[0]; + char *buf1 = bufs[1]; + char *buf2 = bufs[2]; + char *buf3 = bufs[3]; + //char *buf4 = bufs[4]; + + char *var0; + char *var1; + //char *var2; + //char *var3; + //char *var4; + //char *var5; + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + // Saves 8 bytes + HWND mainHwnd = g_hwnd; +#define g_hwnd mainHwnd +#endif + + int exec_error = 0; + + entry lent = *entry_; + +#define which (lent.which) +#define parm0 (lent.offsets[0]) +#define parm1 (lent.offsets[1]) +#define parm2 (lent.offsets[2]) +#define parm3 (lent.offsets[3]) +#define parm4 (lent.offsets[4]) +#define parm5 (lent.offsets[5]) + + var0 = g_usrvars[parm0]; + var1 = g_usrvars[parm1]; + // not used yet + //var2 = g_usrvars[parm2]; + //var3 = g_usrvars[parm3]; + //var4 = g_usrvars[parm4]; + //var5 = g_usrvars[parm5]; + + parms = lent.offsets; + + switch (which) + { + case EW_NOP: + log_printf2("Jump: %d",parm0); + return parm0; + case EW_ABORT: + { + log_printf2("Aborting: \"%s\"",GetStringFromParm(0x00)); + update_status_text(parm0,0); + } + return EXEC_ERROR; + case EW_QUIT: + g_quit_flag++; + if (g_hwnd) PostQuitMessage(0); // make sure we bail out fast. + return EXEC_ERROR; + case EW_CALL: + { + int v=resolveaddr(parm0)-1; // address is -1, since we encode it as +1 + log_printf2("Call: %d",v); + return ExecuteCodeSegment(v,NULL); + } + case EW_UPDATETEXT: + log_printf2("detailprint: %s",GetStringFromParm(0x00)); + update_status_text(parm0,0); + break; + case EW_SLEEP: + { + int x=GetIntFromParm(0); + log_printf2("Sleep(%d)",x); + Sleep(max(x,1)); + } + break; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case EW_BRINGTOFRONT: + log_printf("BringToFront"); + SetForegroundWindow(g_hwnd); + break; +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + case EW_SETFLAG: + if (!parm2) + { + FIELDN(g_exec_flags_last_used,parm0)=FIELDN(g_exec_flags,parm0); + FIELDN(g_exec_flags,parm0)=GetIntFromParm(1); + } + else + { + FIELDN(g_exec_flags,parm0)=FIELDN(g_exec_flags_last_used,parm0); + } + break; + case EW_IFFLAG: + { + int f=lent.offsets[!FIELDN(g_exec_flags,parm2)]; + FIELDN(g_exec_flags,parm2)&=parm3; + return f; + } + case EW_GETFLAG: + myitoa(var0,FIELDN(g_exec_flags,parm1)); + break; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case EW_CHDETAILSVIEW: + if (insthwndbutton) ShowWindow(insthwndbutton,parm1); + if (insthwnd) ShowWindow(insthwnd,parm0); + break; +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + case EW_SETFILEATTRIBUTES: + { + char *buf1=GetStringFromParm(-0x10); + log_printf3("SetFileAttributes: \"%s\":%08X",buf1,parm1); + if (!SetFileAttributes(buf1,parm1)) + { + exec_error++; + log_printf("SetFileAttributes failed."); + } + } + break; + case EW_CREATEDIR: { + char *buf1=GetStringFromParm(-0x10); + log_printf3("CreateDirectory: \"%s\" (%d)",buf1,parm1); + { + char *p = skip_root(buf1); + char c = 'c'; + if (p) + { + while (c) + { + p = findchar(p, '\\'); + c = *p; + *p = 0; + if (!CreateDirectory(buf1, NULL)) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + log_printf3("CreateDirectory: can't create \"%s\" (err=%d)",buf1,GetLastError()); + exec_error++; + } + else if ((GetFileAttributes(buf1) & FILE_ATTRIBUTE_DIRECTORY) == 0) + { + log_printf2("CreateDirectory: can't create \"%s\" - a file already exists",buf1); + exec_error++; + } + } + *p++ = c; + } + } + } + if (parm1) + { + update_status_text_buf1(LANG_OUTPUTDIR); + mystrcpy(state_output_directory,buf1); + SetCurrentDirectory(buf1); + } + else update_status_text_buf1(LANG_CREATEDIR); + } + break; + case EW_IFFILEEXISTS: + { + char *buf0=GetStringFromParm(0x00); + if (file_exists(buf0)) + { + log_printf3("IfFileExists: file \"%s\" exists, jumping %d",buf0,parm1); + return parm1; + } + log_printf3("IfFileExists: file \"%s\" does not exist, jumping %d",buf0,parm2); + } + return parm2; +#ifdef NSIS_SUPPORT_RENAME + case EW_RENAME: + { + char *buf3=GetStringFromParm(-0x30); + char *buf2=GetStringFromParm(-0x21); + char *buf1=GetStringFromParm(0x13); + log_printf2("Rename: %s",buf1); + if (MoveFile(buf3,buf2)) + { + update_status_text_buf1(LANG_RENAME); + } + else + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (parm2 && file_exists(buf3)) + { + MoveFileOnReboot(buf3,buf2); + update_status_text_buf1(LANG_RENAMEONREBOOT); + log_printf2("Rename on reboot: %s",buf1); + } + else +#endif + { + exec_error++; + log_printf2("Rename failed: %s",buf1); + } + } + } + break; +#endif//NSIS_SUPPORT_RENAME +#ifdef NSIS_SUPPORT_FNUTIL + case EW_GETFULLPATHNAME: + { + char *fp; + char *p=var1; + char *buf0=GetStringFromParm(0x00); + if (!GetFullPathName(buf0,NSIS_MAX_STRLEN,p,&fp)) + { + exec_error++; + *p=0; + } + else if (fp>buf0 && *fp) + { + WIN32_FIND_DATA *fd=file_exists(buf0); + if (fd) + { + mystrcpy(fp,fd->cFileName); + } + else + { + exec_error++; + *p=0; + } + } + if (!parm2) GetShortPathName(p,p,NSIS_MAX_STRLEN); + } + break; + case EW_SEARCHPATH: + { + char *fp; + char *p=var0; + char *buf0=GetStringFromParm(-0x01); + if (!SearchPath(NULL,buf0,NULL,NSIS_MAX_STRLEN,p,&fp)) + { + exec_error++; + p[0]=0; + } + } + break; + case EW_GETTEMPFILENAME: + { + char *textout=var0; + if (!my_GetTempFileName(textout, GetStringFromParm(-0x11))) + exec_error++; + } + break; +#endif +#ifdef NSIS_SUPPORT_FILE + case EW_EXTRACTFILE: + { + HANDLE hOut; + int ret; + char *buf3 = GetStringFromParm(0x31); + int overwriteflag = parm0 & 7; + + log_printf4("File: overwriteflag=%d, allowskipfilesflag=%d, name=\"%s\"",overwriteflag,(parm0>>3)&MB_ABORTRETRYIGNORE,buf3); + if (validpathspec(buf3)) + { + mystrcpy(buf0,buf3); + } + else mystrcat(addtrailingslash(mystrcpy(buf0,state_output_directory)),buf3); + validate_filename(buf0); + _tryagain: + if (overwriteflag >= 3) // check date and time + { + WIN32_FIND_DATA *ffd=file_exists(buf0); + // if it doesn't exist, overwrite flag will be off (though it doesn't really matter) + int cmp=0; + if (ffd) + { + cmp=CompareFileTime(&ffd->ftLastWriteTime, (FILETIME*)(lent.offsets + 3)); + } + overwriteflag=!(cmp & (0x80000000 | (overwriteflag - 3))); + } + // remove read only flag if overwrite mode is on + if (!overwriteflag) + { + remove_ro_attr(buf0); + } + hOut=myOpenFile(buf0,GENERIC_WRITE,(overwriteflag==1)?CREATE_NEW:CREATE_ALWAYS); + if (hOut == INVALID_HANDLE_VALUE) + { + if (overwriteflag) + { + update_status_text(LANG_SKIPPED,buf3); + if (overwriteflag==2) exec_error++; + log_printf3("File: skipped: \"%s\" (overwriteflag=%d)",buf0,overwriteflag); + break; + } + log_printf2("File: error creating \"%s\"",buf0); + + mystrcpy(buf2,g_usrvars[0]); // save $0 + mystrcpy(g_usrvars[0],buf0); // copy file name to $0 + GetNSISString(buf1,parm5); // use $0 + mystrcpy(g_usrvars[0],buf2); // restore $0 + + // Modified by ramon 23 May 2003 + switch (my_MessageBox(buf1, parm0>>3)) + { + case IDRETRY: + log_printf("File: error, user retry"); + goto _tryagain; + case IDIGNORE: + log_printf("File: error, user cancel"); + g_exec_flags.exec_error++; + return 0; + default: + log_printf("File: error, user abort"); + update_status_text(LANG_CANTWRITE,buf0); + return EXEC_ERROR; + } + } + + update_status_text(LANG_EXTRACT,buf3); + { + g_exec_flags.status_update++; + ret=GetCompressedDataFromDataBlock(parm2,hOut); + g_exec_flags.status_update--; + } + + log_printf3("File: wrote %d to \"%s\"",ret,buf0); + + if (parm3 != 0xffffffff || parm4 != 0xffffffff) + SetFileTime(hOut,(FILETIME*)(lent.offsets+3),NULL,(FILETIME*)(lent.offsets+3)); + + CloseHandle(hOut); + + if (ret < 0) + { + if (ret == -2) + { + GetNSISString(buf0,LANG_ERRORWRITING); + mystrcat(buf0,buf3); + } + else + { + GetNSISString(buf0,LANG_ERRORDECOMPRESSING); + } + log_printf2("%s",buf0); + my_MessageBox(buf0,MB_OK|MB_ICONSTOP|(IDOK<<21)); + return EXEC_ERROR; + } + } + break; +#endif//NSIS_SUPPORT_FILE +#ifdef NSIS_SUPPORT_DELETE + case EW_DELETEFILE: + { + char *buf0=GetStringFromParm(0x00); + log_printf2("Delete: \"%s\"",buf0); + myDelete(buf0,parm1); + } + break; +#endif//NSIS_SUPPORT_DELETE +#ifdef NSIS_SUPPORT_MESSAGEBOX + case EW_MESSAGEBOX: // MessageBox + { + int v; + char *buf3=GetStringFromParm(0x31); + log_printf3("MessageBox: %d,\"%s\"",parm0,buf3); + v=my_MessageBox(buf3,parm0); + if (v) + { + if (v==parm2) + { + return parm3; + } + if (v==parm4) + { + return parm5; + } + } + else exec_error++; + } + break; +#endif//NSIS_SUPPORT_MESSAGEBOX +#ifdef NSIS_SUPPORT_RMDIR + case EW_RMDIR: + { + char *buf1=GetStringFromParm(-0x10); + log_printf2("RMDir: \"%s\"",buf1); + + myDelete(buf1,parm1); + } + break; +#endif//NSIS_SUPPORT_RMDIR +#ifdef NSIS_SUPPORT_STROPTS + case EW_STRLEN: + { + char *buf0=GetStringFromParm(0x01); + myitoa(var0,mystrlen(buf0)); + } + break; + case EW_ASSIGNVAR: + { + int newlen=GetIntFromParm(2); + int start=GetIntFromParm(3); + int l; + char *p=var0; + char *buf0=GetStringFromParm(0x01); + *p=0; + if (!parm2 || newlen) + { + l=mystrlen(buf0); + + if (start<0) start=l+start; + if (start>=0) + { + if (start>l) start=l; + mystrcpy(p,buf0+start); + if (newlen) + { + if (newlen<0) newlen=mystrlen(p)+newlen; + if (newlen<0) newlen=0; + if (newlen < NSIS_MAX_STRLEN) p[newlen]=0; + } + } + } + } + break; + case EW_STRCMP: + { + char *buf2=GetStringFromParm(0x20); + char *buf3=GetStringFromParm(0x31); + if (!parm4) { + // case insensitive + if (!lstrcmpi(buf2,buf3)) return parm2; + } + else { + // case sensitive + if (!lstrcmp(buf2,buf3)) return parm2; + } + } + return parm3; +#endif//NSIS_SUPPORT_STROPTS +#ifdef NSIS_SUPPORT_ENVIRONMENT + case EW_READENVSTR: + { + char *p=var0; + char *buf0=GetStringFromParm(0x01); + if (!ExpandEnvironmentStrings(buf0,p,NSIS_MAX_STRLEN) + || (parm2 && !lstrcmp(buf0, p))) + { + exec_error++; + *p=0; + } + p[NSIS_MAX_STRLEN-1]=0; + } + break; +#endif//NSIS_SUPPORT_ENVIRONMENT +#ifdef NSIS_SUPPORT_INTOPTS + case EW_INTCMP: + { + int v,v2; + v=GetIntFromParm(0); + v2=GetIntFromParm(1); + if (!parm5) { + // signed + if (v<v2) return parm3; + if (v>v2) return parm4; + } + else { + // unsigned + if ((unsigned int)v<(unsigned int)v2) return parm3; + if ((unsigned int)v>(unsigned int)v2) return parm4; + } + } + return parm2; + case EW_INTOP: + { + int v,v2; + char *p=var0; + v=GetIntFromParm(1); + v2=GetIntFromParm(2); + switch (parm3) + { + case 0: v+=v2; break; + case 1: v-=v2; break; + case 2: v*=v2; break; + case 3: if (v2) v/=v2; else { v=0; exec_error++; } break; + case 4: v|=v2; break; + case 5: v&=v2; break; + case 6: v^=v2; break; + case 7: v=!v; break; + case 8: v=v||v2; break; + case 9: v=v&&v2; break; + case 10: if (v2) v%=v2; else { v=0; exec_error++; } break; + case 11: v=v<<v2; break; + case 12: v=v>>v2; break; + } + myitoa(p,v); + } + break; + case EW_INTFMT: { + char *buf0=GetStringFromParm(0x01); + wsprintf(var0, + buf0, + GetIntFromParm(2)); + } + break; +#endif//NSIS_SUPPORT_INTOPTS +#ifdef NSIS_SUPPORT_STACK + case EW_PUSHPOP: + { + stack_t *s=g_st; + int cnt=parm2; + if (cnt) //Exch contributed by Fritz Elfert + { + while (cnt--&&s) s=s->next; + if (!s) + { + log_printf2("Exch: stack < %d elements",parm2); + my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21)); + return EXEC_ERROR; + } + mystrcpy(buf0,s->text); + mystrcpy(s->text,g_st->text); + mystrcpy(g_st->text,buf0); + } + else if (parm1) + { + if (!s) + { + log_printf("Pop: stack empty"); + exec_error++; + break; + } + mystrcpy(var0,s->text); + g_st=s->next; + GlobalFree((HGLOBAL)s); + } + else + { + s=(stack_t*)GlobalAlloc(GPTR,sizeof(stack_t)); + GetNSISString(s->text,parm0); + s->next=g_st; + g_st=s; + } + } + break; +#endif//NSIS_SUPPORT_STACK +#ifdef NSIS_SUPPORT_HWNDS + case EW_FINDWINDOW: + case EW_SENDMESSAGE: + { + int v; + int b3=GetIntFromParm(3); + int b4=GetIntFromParm(4); + if (parm5&1) b3=(int)GetStringFromParm(0x33); + if (parm5&2) b4=(int)GetStringFromParm(0x44); + + if (which == EW_SENDMESSAGE) + { + HWND hwnd=(HWND)GetIntFromParm(1); + int msg=GetIntFromParm(2); + + if (parm5>>2) exec_error += !SendMessageTimeout(hwnd,msg,b3,b4,SMTO_NORMAL,parm5>>2,(LPDWORD)&v); + else v=SendMessage(hwnd,msg,b3,b4); + } + else + { + char *buf0=GetStringFromParm(0x01); + char *buf1=GetStringFromParm(0x12); + v=(int)FindWindowEx((HWND)b3,(HWND)b4,buf0[0]?buf0:NULL,buf1[0]?buf1:NULL); + } + + if (parm0>=0) + myitoa(var0,v); + } + break; + case EW_ISWINDOW: + if (IsWindow((HWND)GetIntFromParm(0))) return parm1; + return parm2; +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + case EW_GETDLGITEM: + myitoa( + var0, + (int)GetDlgItem( + (HWND)GetIntFromParm(1), + GetIntFromParm(2) + ) + ); + break; + case EW_SETCTLCOLORS: + { + ctlcolors *c = (ctlcolors *)(g_blocks[NB_CTLCOLORS].offset + parm1); + SetWindowLong((HWND) GetIntFromParm(0), GWL_USERDATA, (long) c); + } + break; + case EW_SETBRANDINGIMAGE: + { + RECT r; + HANDLE hImage; + HWND hwImage=GetDlgItem(g_hwnd, parm1); + GetClientRect(hwImage, &r); + hImage=LoadImage( + 0, + GetStringFromParm(0x00), + IMAGE_BITMAP, + parm2*r.right, + parm2*r.bottom, + LR_LOADFROMFILE + ); + hImage = (HANDLE)SendMessage( + hwImage, + STM_SETIMAGE, + IMAGE_BITMAP, + (LPARAM)hImage + ); + // delete old image + if (hImage) DeleteObject(hImage); + } + break; + case EW_CREATEFONT: + { + static LOGFONT f; + f.lfHeight=-MulDiv(GetIntFromParm(2),GetDeviceCaps(GetDC(g_hwnd),LOGPIXELSY),72); + f.lfWeight=GetIntFromParm(3); + f.lfItalic=parm4&1; + f.lfUnderline=parm4&2; + f.lfStrikeOut=parm4&4; + f.lfCharSet=DEFAULT_CHARSET; + GetNSISString(f.lfFaceName,parm1); + myitoa(var0,(int)CreateFontIndirect(&f)); + } + break; + case EW_SHOWWINDOW: + { + HWND hw=(HWND)GetIntFromParm(0); + int a=GetIntFromParm(1); + if (parm2) log_printf("HideWindow"); + if (!parm3) + ShowWindow(hw,a); + else + EnableWindow(hw,a); + } + break; +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT +#endif//NSIS_SUPPORT_HWNDS +#ifdef NSIS_SUPPORT_SHELLEXECUTE + case EW_SHELLEXEC: // this uses improvements of Andras Varga + { + int x; + char *buf0=GetStringFromParm(0x00); + char *buf3=GetStringFromParm(0x31); + char *buf2=GetStringFromParm(0x22); + char *buf1=GetStringFromParm(0x15); + update_status_text_buf1(LANG_EXECSHELL); + x=(int)ShellExecute(g_hwnd,buf0[0]?buf0:NULL,buf3,buf2[0]?buf2:NULL,state_output_directory,parm3); + if (x < 33) + { + log_printf5("ExecShell: warning: error (\"%s\": file:\"%s\" params:\"%s\")=%d",buf0,buf3,buf2,x); + exec_error++; + } + else + { + log_printf4("ExecShell: success (\"%s\": file:\"%s\" params:\"%s\")",buf0,buf3,buf2); + } + } + break; +#endif//NSIS_SUPPORT_SHELLEXECUTE +#ifdef NSIS_SUPPORT_EXECUTE + case EW_EXECUTE: + { + HANDLE hProc; + char *buf0=GetStringFromParm(0x00); + log_printf2("Exec: command=\"%s\"",buf0); + update_status_text(LANG_EXECUTE,buf0); + + hProc=myCreateProcess(buf0); + + if (hProc) + { + log_printf2("Exec: success (\"%s\")",buf0); + if (parm2) + { + DWORD lExitCode; + while (WaitForSingleObject(hProc,100) == WAIT_TIMEOUT) + { + MessageLoop(WM_PAINT); + } + GetExitCodeProcess(hProc, &lExitCode); + + if (parm1>=0) myitoa(var1,lExitCode); + else if (lExitCode) exec_error++; + } + CloseHandle( hProc ); + } + else + { + exec_error++; + log_printf2("Exec: failed createprocess (\"%s\")",buf0); + } + } + break; +#endif//NSIS_SUPPORT_EXECUTE +#ifdef NSIS_SUPPORT_GETFILETIME + case EW_GETFILETIME: + // this new implementation based on one by Dave Bau + // used FindFirstFile instead of GetFileTime to better handle files that are locked. + // also allows GetFileTime to be passed a wildcard. + { + WIN32_FIND_DATA *ffd; + char *highout=var0; + char *lowout=var1; + char *buf0=GetStringFromParm(0x02); + + ffd=file_exists(buf0); + if (ffd) + { + myitoa(lowout,ffd->ftLastWriteTime.dwLowDateTime); + myitoa(highout,ffd->ftLastWriteTime.dwHighDateTime); + } + else + { + *lowout=*highout=0; + exec_error++; + } + } + break; +#endif//NSIS_SUPPORT_GETFILETIME +#ifdef NSIS_SUPPORT_GETDLLVERSION + case EW_GETDLLVERSION: + { + char *highout=var0; + char *lowout=var1; + DWORD s1; + VS_FIXEDFILEINFO *pvsf1; + DWORD d; + char *buf1=GetStringFromParm(-0x12); + s1=GetFileVersionInfoSize(buf1,&d); + *lowout=*highout=0; + exec_error++; + if (s1) + { + void *b1; + b1=GlobalAlloc(GPTR,s1); + if (b1) + { + UINT uLen; + if (GetFileVersionInfo(buf1,0,s1,b1) && VerQueryValue(b1,"\\",(void*)&pvsf1,&uLen)) + { + myitoa(highout,pvsf1->dwFileVersionMS); + myitoa(lowout,pvsf1->dwFileVersionLS); + + exec_error--; + } + GlobalFree(b1); + } + } + } + break; +#endif//NSIS_SUPPORT_GETDLLVERSION +#ifdef NSIS_SUPPORT_ACTIVEXREG + case EW_REGISTERDLL: + { + exec_error++; + if (SUCCEEDED(g_hres)) + { + HANDLE h=NULL; + char *buf1=GetStringFromParm(-0x10); + char *buf0=GetStringFromParm(0x01); + + if (parm4) + h=GetModuleHandle(buf1); + if (!h) + h=LoadLibraryEx(buf1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (h) + { + FARPROC funke = GetProcAddress(h,buf0); + if (funke) + { + exec_error--; + if (parm2) + { + update_status_text_buf1(parm2); + if (funke()) exec_error++; + } + else + { + void (*func)(HWND,int,char*,void*,void*); + func=(void*)funke; + func( + g_hwnd, + NSIS_MAX_STRLEN, + (char*)g_usrvars, +#ifdef NSIS_SUPPORT_STACK + (void*)&g_st, +#else + NULL, +#endif//NSIS_SUPPORT_STACK + &plugin_extra_parameters + ); + } + } + else + { + update_status_text(LANG_CANNOTFINDSYMBOL,buf0); + log_printf3("Error registering DLL: %s not found in %s",buf0,buf1); + } + if (!parm3) FreeLibrary(h); + } + else + { + update_status_text_buf1(LANG_COULDNOTLOAD); + log_printf2("Error registering DLL: Could not load %s",buf1); + } + } + else + { + update_status_text_buf1(LANG_NOOLE); + log_printf("Error registering DLL: Could not initialize OLE"); + } + } + break; +#endif +#ifdef NSIS_SUPPORT_CREATESHORTCUT + case EW_CREATESHORTCUT: + { + char *buf1=GetStringFromParm(-0x10); + char *buf2=GetStringFromParm(-0x21); + char *buf0=GetStringFromParm(0x02); + char *buf3=GetStringFromParm(-0x33); + char *buf4=GetStringFromParm(0x45); + + HRESULT hres; + IShellLink* psl; + + if (!validpathspec(buf2)) + GetStringFromParm(0x21); + + log_printf8("CreateShortCut: out: \"%s\", in: \"%s %s\", icon: %s,%d, sw=%d, hk=%d", + buf1,buf2,buf0,buf3,parm4&0xff,(parm4&0xff00)>>8,parm4>>16); + + 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,buf2); + psl->lpVtbl->SetWorkingDirectory(psl,state_output_directory); + if ((parm4&0xff00)>>8) psl->lpVtbl->SetShowCmd(psl,(parm4&0xff00)>>8); + psl->lpVtbl->SetHotkey(psl,(unsigned short)(parm4>>16)); + if (buf3[0]) psl->lpVtbl->SetIconLocation(psl,buf3,parm4&0xff); + psl->lpVtbl->SetArguments(psl,buf0); + psl->lpVtbl->SetDescription(psl,buf4); + + if (SUCCEEDED(hres)) + { + static WCHAR wsz[1024]; + hres=E_FAIL; + if (MultiByteToWideChar(CP_ACP, 0, buf1, -1, wsz, 1024)) + hres=ppf->lpVtbl->Save(ppf,(const WCHAR*)wsz,TRUE); + } + ppf->lpVtbl->Release(ppf); + } + psl->lpVtbl->Release(psl); + } + + if (FAILED(hres)) + { + exec_error++; + update_status_text_buf1(LANG_ERRORCREATINGSHORTCUT); + } + else + { + update_status_text_buf1(LANG_CREATESHORTCUT); + } + } + break; +#endif//NSIS_SUPPORT_CREATESHORTCUT +#ifdef NSIS_SUPPORT_COPYFILES + case EW_COPYFILES: // CopyFile (added by NOP) + { + int res; + SHFILEOPSTRUCT op; + char *buf0=GetStringFromParm(0x00); + char *buf1=GetStringFromParm(0x11); + char *buf2=GetStringFromParm(0x23); // LANG_COPYTO + buf1 + log_printf3("CopyFiles \"%s\"->\"%s\"",buf0,buf1); + + if (!file_exists(buf0)) + { + // workaround for bug #774966 + // + // on nt4, SHFileOperation silently fails if the source + // file doesn't exist. do a manual check instead. + + update_status_text(LANG_COPYFAILED,0); + exec_error++; + break; + } + + op.hwnd=g_hwnd; + op.wFunc=FO_COPY; + buf0[mystrlen(buf0)+1]=0; + buf1[mystrlen(buf1)+1]=0; + + op.pFrom=buf0; + op.pTo=buf1; + op.lpszProgressTitle=buf2; + op.fFlags=parm2; + update_status_text(0,buf2); + res=SHFileOperation(&op); + if (res) + { // some of these changes were from Edgewise (wiked_edge@yahoo.com) + update_status_text(LANG_COPYFAILED,0); + exec_error++; + } + } + break; +#endif//NSIS_SUPPORT_COPYFILES +#ifdef NSIS_SUPPORT_REBOOT + case EW_REBOOT: + if (parm0!=0xbadf00d) + { + my_MessageBox(GetNSISStringTT(LANG_INSTCORRUPTED),MB_OK|MB_ICONSTOP|(IDOK<<21)); + return EXEC_ERROR; + } + + g_exec_flags.reboot_called++; + // a following EW_QUIT will make sure the installer quits right away + + break; +#endif//NSIS_SUPPORT_REBOOT +#ifdef NSIS_SUPPORT_INIFILES + case EW_WRITEINI: + { + char *sec=0, *key=0, *str=0; +#ifdef NSIS_CONFIG_LOG + mystrcpy(buf1,"<RM>"); + mystrcpy(buf2,buf1); +#endif + if (parm0) + { + sec=GetStringFromParm(0x00); + } + if (parm1) + { + key=GetStringFromParm(0x11); + } + if (parm4) + { + str=GetStringFromParm(0x22); + } + buf3=GetStringFromParm(-0x33); + log_printf5("WriteINIStr: wrote [%s] %s=%s in %s",buf0,buf1,buf2,buf3); + if (!WritePrivateProfileString(sec,key,str,buf3)) exec_error++; + } + break; + case EW_READINISTR: + { + DWORD errstr = CHAR4_TO_DWORD('!', 'N', '~', 0); + char *p=var0; + char *buf0=GetStringFromParm(0x01); + char *buf1=GetStringFromParm(0x12); + char *buf2=GetStringFromParm(-0x23); + GetPrivateProfileString(buf0,buf1,(LPCSTR)&errstr,p,NSIS_MAX_STRLEN-1,buf2); + if (*(DWORD*)p == errstr) + { + exec_error++; + p[0]=0; + } + } + break; +#endif//NSIS_SUPPORT_INIFILES +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + case EW_DELREG: + { + long res=!ERROR_SUCCESS; + const char *rkn UNUSED=RegKeyHandleToName((HKEY)parm1); + if (!parm4) + { + HKEY hKey=myRegOpenKey(KEY_SET_VALUE); + if (hKey) + { + char *buf3=GetStringFromParm(0x33); + res = RegDeleteValue(hKey,buf3); + log_printf4("DeleteRegValue: \"%s\\%s\" \"%s\"",rkn,buf2,buf3); + RegCloseKey(hKey); + } + } + else + { + char *buf2=GetStringFromParm(0x22); + log_printf3("DeleteRegKey: \"%s\\%s\"",rkn,buf2); + res = myRegDeleteKeyEx(GetRegRootKey(parm1),buf2,parm4&2); + } + if (res != ERROR_SUCCESS) + exec_error++; + } + break; + case EW_WRITEREG: // write registry value + { + HKEY hKey; + HKEY rootkey=GetRegRootKey(parm0); + int type=parm4; + int rtype=parm5; + char *buf0=GetStringFromParm(0x02); + char *buf1=GetStringFromParm(0x11); + const char *rkn UNUSED=RegKeyHandleToName(rootkey); + + exec_error++; + if (RegCreateKeyEx(rootkey,buf1,0,0,0,AlterRegistrySAM(KEY_SET_VALUE),0,&hKey,0) == ERROR_SUCCESS) + { + LPBYTE data = (LPBYTE) buf2; + DWORD size = 0; + if (type == REG_SZ) + { + GetStringFromParm(0x23); + size = mystrlen((char *) data) + 1; + if (rtype == REG_SZ) + { + log_printf5("WriteRegStr: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,data); + } + else + { + log_printf5("WriteRegExpandStr: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,data); + } + } + if (type == REG_DWORD) + { + *(LPDWORD) data = GetIntFromParm(3); + size = sizeof(DWORD); + log_printf5("WriteRegDWORD: \"%s\\%s\" \"%s\"=\"0x%08x\"",rkn,buf1,buf0,*(LPDWORD) data); + } + if (type == REG_BINARY) + { +#ifdef NSIS_CONFIG_LOG + char binbuf[128]; +#endif + // use buf2, buf3 and buf4 + size = GetCompressedDataFromDataBlockToMemory(parm3, data, 3 * NSIS_MAX_STRLEN); + LogData2Hex(binbuf, sizeof(binbuf), data, size); + log_printf5("WriteRegBin: \"%s\\%s\" \"%s\"=\"%s\"",rkn,buf1,buf0,binbuf); + } + + if (size >= 0 && RegSetValueEx(hKey,buf0,0,rtype,data,size) == ERROR_SUCCESS) + { + exec_error--; + } + else + { + log_printf4("WriteReg: error writing into \"%s\\%s\" \"%s\"",rkn,buf1,buf0); + } + + RegCloseKey(hKey); + } + else { log_printf3("WriteReg: error creating key \"%s\\%s\"",rkn,buf1); } + } + break; + case EW_READREGSTR: // read registry string + { + HKEY hKey=myRegOpenKey(KEY_READ); + char *p=var0; + char *buf3=GetStringFromParm(0x33); // buf3 == key name + p[0]=0; + if (hKey) + { + DWORD l = NSIS_MAX_STRLEN - 1; + DWORD t; + + if (RegQueryValueEx(hKey,buf3,NULL,&t,p,&l) != ERROR_SUCCESS || + (t != REG_DWORD && t != REG_SZ && t != REG_EXPAND_SZ)) + { + p[0]=0; + exec_error++; + } + else + { + if (t==REG_DWORD) + { + exec_error += !parm4; + myitoa(p,*((DWORD*)p)); + } + else + { + exec_error += parm4; + p[l]=0; + } + } + RegCloseKey(hKey); + } + else exec_error++; + } + break; + case EW_REGENUM: + { + HKEY key=myRegOpenKey(KEY_READ); + char *p=var0; + int b=GetIntFromParm(3); + p[0]=0; + if (key) + { + DWORD d=NSIS_MAX_STRLEN-1; + if (parm4) RegEnumKey(key,b,p,d); + else if (RegEnumValue(key,b,p,&d,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS) + { + exec_error++; + break; + } + p[NSIS_MAX_STRLEN-1]=0; + RegCloseKey(key); + } + else exec_error++; + } + + break; +#endif//NSIS_SUPPORT_REGISTRYFUNCTIONS +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + case EW_FCLOSE: + { + char *t=var0; + if (*t) CloseHandle((HANDLE)myatoi(t)); + } + break; + case EW_FOPEN: + { + HANDLE h; + char *handleout=var0; + char *buf1=GetStringFromParm(-0x13); + h=myOpenFile(buf1,parm1,parm2); + if (h == INVALID_HANDLE_VALUE) + { + *handleout=0; + exec_error++; + } + else + { + myitoa(handleout,(int)h); + } + } + break; + case EW_FPUTS: + { + DWORD dw; + int l; + char *t=var0; + if (parm2) + { + ((unsigned char *)buf1)[0]=GetIntFromParm(1)&0xff; + l=1; + } + else + { + l=mystrlen(GetStringFromParm(0x11)); + } + if (!*t || !WriteFile((HANDLE)myatoi(t),buf1,l,&dw,NULL)) + { + exec_error++; + } + } + break; + case EW_FGETS: + { + char *textout=var1; + DWORD dw; + int rpos=0; + char *hptr=var0; + int maxlen=GetIntFromParm(2); + if (maxlen<1) break; + if (maxlen > NSIS_MAX_STRLEN-1) maxlen=NSIS_MAX_STRLEN-1; + if (*hptr) + { + char lc=0; + HANDLE h=(HANDLE)myatoi(hptr); + while (rpos<maxlen) + { + char c; + if (!ReadFile(h,&c,1,&dw,NULL) || dw != 1) break; + if (parm3) + { + myitoa(textout,(unsigned int)(unsigned char)c); + return 0; + } + if (lc == '\r' || lc == '\n') + { + if (lc == c || (c != '\r' && c != '\n')) SetFilePointer(h,-1,NULL,FILE_CURRENT); + else textout[rpos++]=c; + break; + } + textout[rpos++]=c; + lc=c; + if (!c) break; + } + } + textout[rpos]=0; + if (!rpos) exec_error++; + } + break; + case EW_FSEEK: + { + char *t=var0; + if (*t) + { + DWORD v=SetFilePointer((HANDLE)myatoi(t),GetIntFromParm(2),NULL,parm3); + + if (parm1>=0) + { + myitoa(var1,v); + } + } + } + break; +#endif//NSIS_SUPPORT_FILEFUNCTIONS +#ifdef NSIS_SUPPORT_FINDFIRST + case EW_FINDCLOSE: + { + char *t=var0; + if (*t) FindClose((HANDLE)myatoi(t)); + } + break; + case EW_FINDNEXT: + { + char *textout=var0; + char *t=var1; + WIN32_FIND_DATA fd; + if (*t && FindNextFile((HANDLE)myatoi(t),&fd)) + { + mystrcpy(textout,fd.cFileName); + } + else + { + exec_error++; + *textout=0; + } + + } + break; + case EW_FINDFIRST: + { + char *textout=var0; + char *handleout=var1; + HANDLE h; + WIN32_FIND_DATA fd; + char *buf0=GetStringFromParm(0x02); + h=FindFirstFile(buf0,&fd); + if (h == INVALID_HANDLE_VALUE) + { + *handleout=0; + *textout=0; + exec_error++; + } + else + { + myitoa(handleout,(int)h); + mystrcpy(textout,fd.cFileName); + } + } + break; +#endif//NSIS_SUPPORT_FINDFIRST +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + case EW_WRITEUNINSTALLER: + { + int ret=-666; + HANDLE hFile; + char *buf1=GetStringFromParm(-0x10); + + if (!validpathspec(buf1)) + GetStringFromParm(-0x13); + + remove_ro_attr(buf1); + hFile=myOpenFile(buf1,GENERIC_WRITE,CREATE_ALWAYS); + if (hFile != INVALID_HANDLE_VALUE) + { + unsigned char *filebuf; + int filehdrsize = g_filehdrsize; + filebuf=(unsigned char *)GlobalAlloc(GPTR,filehdrsize); + if (filebuf) + { + DWORD lout; + SetSelfFilePointer(0); + ReadSelfFile((char*)filebuf,filehdrsize); + { + unsigned char* seeker; + unsigned char* unicon_data = seeker = (unsigned char*)GlobalAlloc(GPTR,parm2); + if (unicon_data) { + GetCompressedDataFromDataBlockToMemory(parm1,unicon_data,parm2); + while (*seeker) { + struct icondata { + DWORD dwSize; + DWORD dwOffset; + } id = *(struct icondata *) seeker; + seeker += sizeof(struct icondata); + mini_memcpy(filebuf+id.dwOffset, seeker, id.dwSize); + seeker += id.dwSize; + } + GlobalFree(unicon_data); + } + } + WriteFile(hFile,(char*)filebuf,filehdrsize,&lout,NULL); + GlobalFree(filebuf); + ret=GetCompressedDataFromDataBlock(-1,hFile); + } + CloseHandle(hFile); + } + log_printf3("created uninstaller: %d, \"%s\"",ret,buf1); + { + int str = LANG_CREATEDUNINST; + if (ret < 0) + { + str = LANG_ERRORCREATING; + DeleteFile(buf1); + exec_error++; + } + update_status_text_buf1(str); + } + } + break; +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_CONFIG_LOG + case EW_LOG: + if (parm0) + { + log_printf2("settings logging to %d",parm1); + log_dolog=parm1; + log_printf2("logging set to %d",parm1); +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) + if (parm1) build_g_logfile(); +#endif + } + else + { + char *buf0=GetStringFromParm(0x01); + log_printf2("%s",buf0); + } + break; +#endif//NSIS_CONFIG_LOG +#ifdef NSIS_CONFIG_COMPONENTPAGE + case EW_SECTIONSET: + { + int x=GetIntFromParm(0); + if ((unsigned int)x < (unsigned int)num_sections) + { + section *sec=g_sections+x; + if (parm2>=0) // get something + { + int res=((int*)sec)[parm2]; + if (!parm2) + { + // getting text + mystrcpy(var1,sec->name); + } + else + { + // getting number + myitoa(var1,res); + } + } + else // set something + { + parm2=-parm2-1; + if (parm2) + { + // not setting text, get int + parm1=GetIntFromParm(1); + } + else + { + // setting text + GetNSISString(sec->name,parm4); + sec->flags|=SF_NAMECHG; + // parm1 is zero so name_ptr will be set to zero + // if name_ptr is zero, it won't be used after .onInit + } + + ((int*)sec)[parm2]=parm1; + + if (parm3) // update flags + { + SectionFlagsChanged(x); + } + } + } + else exec_error++; + } + break; + case EW_INSTTYPESET: + { + int x = GetIntFromParm(0); + + if ((unsigned int)x < (unsigned int)NSIS_MAX_INST_TYPES) + { + if (parm3) // current install type + { + if (parm2) // set install type + { + SetInstType(x); + RefreshSectionGroups(); + } + else // get install type + { + myitoa(var1, GetInstType(0)); + } + } + else // install type text + { + if (parm2) // set text + { + g_header->install_types[x] = parm1; + } + else // get text + { + GetNSISString(var1,g_header->install_types[x]); + } + } + } + else exec_error++; + } + break; +#endif//NSIS_CONFIG_COMPONENTPAGE + +#ifdef NSIS_LOCKWINDOW_SUPPORT + case EW_LOCKWINDOW: + { + // ui_dlg_visible is 1 or 0, so is parm0 + SendMessage(g_hwnd, WM_SETREDRAW, parm0 & ui_dlg_visible, 0); + if ( parm0 ) + InvalidateRect(g_hwnd, NULL, FALSE); + break; + } +#endif //NSIS_LOCKWINDOW_SUPPORT + } + + g_exec_flags.exec_error += exec_error; + + return 0; +} diff --git a/Source/exehead/exec.h b/Source/exehead/exec.h index b49b91d..6af6603 100755 --- a/Source/exehead/exec.h +++ b/Source/exehead/exec.h @@ -1,26 +1,26 @@ -/*
- * exec.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _EXEC_H_
-#define _EXEC_H_
-
-extern exec_flags g_exec_flags;
-extern exec_flags g_exec_flags_last_used;
-
-int NSISCALL ExecuteCodeSegment(int pos, HWND hwndProgress); // returns 0 on success
-int NSISCALL ExecuteCallbackFunction(int num); // returns 0 on success
-
-#endif//_EXEC_H_
+/* + * exec.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _EXEC_H_ +#define _EXEC_H_ + +extern exec_flags g_exec_flags; +extern exec_flags g_exec_flags_last_used; + +int NSISCALL ExecuteCodeSegment(int pos, HWND hwndProgress); // returns 0 on success +int NSISCALL ExecuteCallbackFunction(int num); // returns 0 on success + +#endif//_EXEC_H_ diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index 43f7706..cb2618f 100755 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -1,564 +1,576 @@ -/*
- * fileform.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include "fileform.h"
-#include "util.h"
-#include "state.h"
-#include "resource.h"
-#include "lang.h"
-#include "ui.h"
-#include "exec.h"
-#include "../crc32.h"
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
-#ifdef NSIS_COMPRESS_USE_ZLIB
-#include "../zlib/ZLIB.H"
-#endif
-
-#ifdef NSIS_COMPRESS_USE_LZMA
-#include "../7zip/LZMADecode.h"
-#define z_stream lzma_stream
-#define inflateInit(x) lzmaInit(x)
-#define inflateReset(x) lzmaInit(x)
-#define inflate(x) lzmaDecode(x)
-#define Z_OK LZMA_OK
-#define Z_STREAM_END LZMA_STREAM_END
-#endif
-
-#ifdef NSIS_COMPRESS_USE_BZIP2
-#include "../bzip2/bzlib.h"
-
-#define z_stream DState
-#define inflateInit(x) BZ2_bzDecompressInit(x)
-#define inflateReset(x) BZ2_bzDecompressInit(x)
-
-#define inflate(x) BZ2_bzDecompress(x)
-#define Z_OK BZ_OK
-#define Z_STREAM_END BZ_STREAM_END
-#endif//NSIS_COMPRESS_USE_BZIP2
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
-
-struct block_header g_blocks[BLOCKS_NUM];
-header *g_header;
-int g_flags;
-int g_filehdrsize;
-int g_is_uninstaller;
-
-HANDLE g_db_hFile=INVALID_HANDLE_VALUE;
-
-#if defined(NSIS_CONFIG_COMPRESSION_SUPPORT) && defined(NSIS_COMPRESS_WHOLE)
-HANDLE dbd_hFile=INVALID_HANDLE_VALUE;
-static int dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen;
-#endif//NSIS_COMPRESS_WHOLE
-
-static int m_length;
-static int m_pos;
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-#if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_COMPRESS_WHOLE)
-BOOL CALLBACK verProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- static char *msg;
- if (uMsg == WM_INITDIALOG)
- {
- SetTimer(hwndDlg,1,250,NULL);
- msg = (char *) lParam;
- uMsg = WM_TIMER;
- }
- if (uMsg == WM_TIMER)
- {
- static char bt[64];
- int percent=MulDiv(min(m_pos,m_length),100,m_length);
-#ifdef NSIS_COMPRESS_WHOLE
- if (msg)
-#endif
- {
- wsprintf(bt,msg,percent);
-
- my_SetWindowText(hwndDlg,bt);
- my_SetDialogItemText(hwndDlg,IDC_STR,bt);
-
- ShowWindow(hwndDlg, SW_SHOW);
- }
-
-#ifdef NSIS_COMPRESS_WHOLE
- if (g_exec_flags.status_update & 1)
- {
- wsprintf(bt, "... %d%%", percent);
- update_status_text(0, bt);
- }
-#endif
- }
- return 0;
-}
-#endif//NSIS_CONFIG_CRC_SUPPORT || NSIS_COMPRESS_WHOLE
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
-static z_stream g_inflate_stream;
-#endif
-
-const char * NSISCALL loadHeaders(int cl_flags)
-{
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- HWND hwnd = 0;
- unsigned int verify_time = GetTickCount() + 1000;
-#endif
- crc32_t crc = 0;
- int do_crc = 0;
-#endif//NSIS_CONFIG_CRC_SUPPORT
- int left;
-
- void *data;
- firstheader h;
- header *header;
-
- HANDLE db_hFile;
-
- GetModuleFileName(NULL, state_exe_path, NSIS_MAX_STRLEN);
-
- g_db_hFile = db_hFile = myOpenFile(state_exe_path, GENERIC_READ, OPEN_EXISTING);
- if (db_hFile == INVALID_HANDLE_VALUE)
- {
- return _LANG_CANTOPENSELF;
- }
-
- mystrcpy(state_exe_directory, state_exe_path);
- mystrcpy(state_exe_file, trimslashtoend(state_exe_directory));
-
- left = m_length = GetFileSize(db_hFile,NULL);
- while (left > 0)
- {
- static char temp[32768];
- DWORD l = min(left, (g_filehdrsize ? 32768 : 512));
- if (!ReadSelfFile(temp, l))
- {
-#if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT)
- if (hwnd) DestroyWindow(hwnd);
-#endif//NSIS_CONFIG_CRC_SUPPORT
- return _LANG_INVALIDCRC;
- }
-
- if (!g_filehdrsize)
- {
- mini_memcpy(&h, temp, sizeof(firstheader));
- if (
- (h.flags & (~FH_FLAGS_MASK)) == 0 &&
- h.siginfo == FH_SIG &&
- h.nsinst[2] == FH_INT3 &&
- h.nsinst[1] == FH_INT2 &&
- h.nsinst[0] == FH_INT1
- )
- {
- g_filehdrsize = m_pos;
-
-#if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_CONFIG_SILENT_SUPPORT)
- cl_flags |= h.flags;
-#endif
-
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- g_exec_flags.silent |= cl_flags & FH_FLAGS_SILENT;
-#endif
-
- if (h.length_of_all_following_data > left)
- return _LANG_INVALIDCRC;
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- if ((cl_flags & FH_FLAGS_FORCE_CRC) == 0)
- {
- if (cl_flags & FH_FLAGS_NO_CRC)
- break;
- }
-
- do_crc++;
-
-#ifndef NSIS_CONFIG_CRC_ANAL
- left = h.length_of_all_following_data - 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
- // no crc support, no need to keep on reading
- break;
-#endif//!NSIS_CONFIG_CRC_SUPPORT
- }
- }
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- else if ((cl_flags & FH_FLAGS_SILENT) == 0)
-#endif//NSIS_CONFIG_SILENT_SUPPORT
- {
- if (hwnd)
- {
- MessageLoop(0);
- }
- else if (GetTickCount() > verify_time)
- hwnd = CreateDialogParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_VERIFY),
- 0,
- verProc,
- (LPARAM)_LANG_VERIFYINGINST
- );
- }
-#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)
- return _LANG_INVALIDCRC;
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- if (do_crc)
- {
- crc32_t fcrc;
- SetSelfFilePointer(m_pos);
- if (!ReadSelfFile(&fcrc, sizeof(crc32_t)) || crc != fcrc)
- return _LANG_INVALIDCRC;
- }
-#endif//NSIS_CONFIG_CRC_SUPPORT
-
- data = (void *)GlobalAlloc(GPTR,h.length_of_header);
-
-#ifdef NSIS_COMPRESS_WHOLE
- inflateReset(&g_inflate_stream);
-
- {
- char fno[MAX_PATH];
- my_GetTempFileName(fno, state_temp_dir);
- 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)
- return _LANG_ERRORWRITINGTEMP;
- }
- dbd_srcpos = SetSelfFilePointer(g_filehdrsize + sizeof(firstheader));
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data - ((h.flags & FH_FLAGS_NO_CRC) ? 0 : sizeof(crc32_t));
-#else
- dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data;
-#endif//NSIS_CONFIG_CRC_SUPPORT
-#else
- SetSelfFilePointer(g_filehdrsize + sizeof(firstheader));
-#endif//NSIS_COMPRESS_WHOLE
-
- if (GetCompressedDataFromDataBlockToMemory(-1, data, h.length_of_header) != h.length_of_header)
- {
- return _LANG_INVALIDCRC;
- }
-
- header = g_header = data;
-
- g_flags = header->flags;
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (h.flags & FH_FLAGS_UNINSTALL)
- g_is_uninstaller++;
-#endif
-
- // set offsets to real memory offsets rather than installer's header offset
- left = BLOCKS_NUM;
- while (left--)
- header->blocks[left].offset += (int)data;
-
-#ifdef NSIS_COMPRESS_WHOLE
- header->blocks[NB_DATA].offset = dbd_pos;
-#else
- header->blocks[NB_DATA].offset = SetFilePointer(db_hFile,0,NULL,FILE_CURRENT);
-#endif
-
- mini_memcpy(&g_blocks, &header->blocks, sizeof(g_blocks));
-
- return 0;
-}
-
-#define IBUFSIZE 16384
-#define OBUFSIZE 32768
-
-// returns -3 if compression error/eof/etc
-
-#if !defined(NSIS_COMPRESS_WHOLE) || !defined(NSIS_CONFIG_COMPRESSION_SUPPORT)
-
-int NSISCALL _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;
-
- outbuffer = outbuf?outbuf:(inbuffer+IBUFSIZE);
-
- if (offset>=0)
- {
- SetSelfFilePointer(g_blocks[NB_DATA].offset+offset);
- }
-
- if (!ReadSelfFile((LPVOID)&input_len,sizeof(int))) return -3;
-
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- if (input_len & 0x80000000) // compressed
- {
- char progress[64];
- int input_len_total;
- DWORD ltc = GetTickCount(), tc;
-
- inflateReset(&g_inflate_stream);
- input_len_total = input_len &= 0x7fffffff; // take off top bit.
-
- while (input_len > 0)
- {
- int l=min(input_len,IBUFSIZE);
- int err;
-
- if (!ReadSelfFile((LPVOID)inbuffer,l))
- return -3;
-
- g_inflate_stream.next_in = inbuffer;
- g_inflate_stream.avail_in = l;
- input_len-=l;
-
- 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;
-
- tc = GetTickCount();
- if (g_exec_flags.status_update & 1 && (tc - ltc > 200 || !input_len))
- {
- wsprintf(progress, "... %d%%", MulDiv(input_len_total - input_len, 100, input_len_total));
- update_status_text(0, progress);
- ltc = tc;
- }
-
- // if there's no output, more input is needed
- if (!u)
- break;
-
- if (!outbuf)
- {
- DWORD r;
- 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;
- }
- }
- }
- else
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
- {
- if (!outbuf)
- {
- while (input_len > 0)
- {
- DWORD l=min(input_len,outbuffer_len);
- DWORD t;
- if (!ReadSelfFile((LPVOID)inbuffer,l)) return -3;
- if (!WriteFile(hFileOut,inbuffer,l,&t,NULL) || l!=t) return -2;
- retval+=l;
- input_len-=l;
- }
- }
- else
- {
- int l=min(input_len,outbuflen);
- if (!ReadSelfFile((LPVOID)outbuf,l)) return -3;
- retval=l;
- }
- }
- return retval;
-}
-#else//NSIS_COMPRESS_WHOLE
-
-static char _inbuffer[IBUFSIZE];
-static char _outbuffer[OBUFSIZE];
-extern int m_length;
-extern int m_pos;
-extern BOOL CALLBACK verProc(HWND, UINT, WPARAM, LPARAM);
-extern BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
-static int NSISCALL __ensuredata(int amount)
-{
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- HWND hwnd=NULL;
- unsigned int verify_time=GetTickCount()+500;
-#endif
- int needed=amount-(dbd_size-dbd_pos);
- if (needed>0)
- {
- SetSelfFilePointer(dbd_srcpos);
- SetFilePointer(dbd_hFile,dbd_size,NULL,FILE_BEGIN);
- m_length=needed;
- m_pos=0;
- for (;;)
- {
- int err;
- int l=min(IBUFSIZE,dbd_fulllen-dbd_srcpos);
- if (!ReadSelfFile((LPVOID)_inbuffer,l)) return -1;
- dbd_srcpos+=l;
- g_inflate_stream.next_in=_inbuffer;
- g_inflate_stream.avail_in=l;
- do
- {
- DWORD r,t;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- if (g_header)
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if (!g_exec_flags.silent)
-#endif
- {
- if (hwnd)
- {
- m_pos=m_length-(amount-(dbd_size-dbd_pos));
- MessageLoop(0);
- }
- else if (GetTickCount() > verify_time)
- {
- hwnd = CreateDialogParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_VERIFY),
- 0,
- verProc,
- g_hwnd ? 0 : (LPARAM)_LANG_UNPACKING
- );
- }
- }
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- g_inflate_stream.next_out=_outbuffer;
- g_inflate_stream.avail_out=OBUFSIZE;
- err=inflate(&g_inflate_stream);
- if (err<0)
- {
- return -3;
- }
- r=(DWORD)g_inflate_stream.next_out-(DWORD)_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 || !l) 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);
- }
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- if (hwnd)
- {
- m_pos=m_length;
- SendMessage(hwnd,WM_TIMER,0,0);
- DestroyWindow(hwnd);
- }
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- return 0;
-}
-
-
-int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen)
-{
- DWORD r;
- int input_len;
- int retval;
- if (offset>=0)
- {
- dbd_pos=g_blocks[NB_DATA].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;
- DWORD l=min(input_len,IBUFSIZE);
- if (!ReadFile(dbd_hFile,(LPVOID)_inbuffer,l,&r,NULL) || l != r) return -3;
- if (!WriteFile(hFileOut,_inbuffer,r,&t,NULL) || t != l) 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
-
-BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead)
-{
- DWORD rd;
- return ReadFile(g_db_hFile,lpBuffer,nNumberOfBytesToRead,&rd,NULL) && (rd == nNumberOfBytesToRead);
-}
-
-DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove)
-{
- return SetFilePointer(g_db_hFile,lDistanceToMove,NULL,FILE_BEGIN);
-}
+/* + * fileform.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include "fileform.h" +#include "util.h" +#include "state.h" +#include "resource.h" +#include "lang.h" +#include "ui.h" +#include "exec.h" +#include "../crc32.h" + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +#ifdef NSIS_COMPRESS_USE_ZLIB +#include "../zlib/ZLIB.H" +#endif + +#ifdef NSIS_COMPRESS_USE_LZMA +#include "../7zip/LZMADecode.h" +#define z_stream lzma_stream +#define inflateInit(x) lzmaInit(x) +#define inflateReset(x) lzmaInit(x) +#define inflate(x) lzmaDecode(x) +#define Z_OK LZMA_OK +#define Z_STREAM_END LZMA_STREAM_END +#endif + +#ifdef NSIS_COMPRESS_USE_BZIP2 +#include "../bzip2/bzlib.h" + +#define z_stream DState +#define inflateInit(x) BZ2_bzDecompressInit(x) +#define inflateReset(x) BZ2_bzDecompressInit(x) + +#define inflate(x) BZ2_bzDecompress(x) +#define Z_OK BZ_OK +#define Z_STREAM_END BZ_STREAM_END +#endif//NSIS_COMPRESS_USE_BZIP2 +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + +struct block_header g_blocks[BLOCKS_NUM]; +header *g_header; +int g_flags; +int g_filehdrsize; +int g_is_uninstaller; + +HANDLE g_db_hFile=INVALID_HANDLE_VALUE; + +#if defined(NSIS_CONFIG_COMPRESSION_SUPPORT) && defined(NSIS_COMPRESS_WHOLE) +HANDLE dbd_hFile=INVALID_HANDLE_VALUE; +static int dbd_size, dbd_pos, dbd_srcpos, dbd_fulllen; +#endif//NSIS_COMPRESS_WHOLE + +static int m_length; +static int m_pos; + +#define _calc_percent() (MulDiv(min(m_pos,m_length),100,m_length)) +#ifdef NSIS_COMPRESS_WHOLE +static int NSISCALL calc_percent() +{ + return _calc_percent(); +} +#else +#define calc_percent() _calc_percent() +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +#if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_COMPRESS_WHOLE) +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) + { + char bt[64]; + int percent=calc_percent(); +#ifdef NSIS_COMPRESS_WHOLE + char *msg=g_header?_LANG_UNPACKING:_LANG_VERIFYINGINST; +#else + char *msg=_LANG_VERIFYINGINST; +#endif + + wsprintf(bt,msg,percent); + + my_SetWindowText(hwndDlg,bt); + my_SetDialogItemText(hwndDlg,IDC_STR,bt); + } + return 0; +} + +DWORD verify_time; + +void handle_ver_dlg(BOOL kill) +{ + static HWND hwnd; + + if (kill) + { + if (hwnd) DestroyWindow(hwnd); + hwnd = NULL; + + return; + } + + if (hwnd) + { + MessageLoop(0); + } + else if (GetTickCount() > verify_time) + { +#ifdef NSIS_COMPRESS_WHOLE + if (g_hwnd) + { + if (g_exec_flags.status_update & 1) + { + char bt[64]; + wsprintf(bt, "... %d%%", calc_percent()); + update_status_text(0, bt); + } + } + else +#endif + { + hwnd = CreateDialog( + g_hInstance, + MAKEINTRESOURCE(IDD_VERIFY), + 0, + verProc + ); + } + } +} +#endif//NSIS_CONFIG_CRC_SUPPORT || NSIS_COMPRESS_WHOLE +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT +static z_stream g_inflate_stream; +#endif + +const char * NSISCALL loadHeaders(int cl_flags) +{ + int left; +#ifdef NSIS_CONFIG_CRC_SUPPORT + crc32_t crc = 0; + int do_crc = 0; +#endif//NSIS_CONFIG_CRC_SUPPORT + + void *data; + firstheader h; + header *header; + + HANDLE db_hFile; + +#ifdef NSIS_CONFIG_CRC_SUPPORT +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + verify_time = GetTickCount() + 1000; +#endif +#endif//NSIS_CONFIG_CRC_SUPPORT + + GetModuleFileName(NULL, state_exe_path, NSIS_MAX_STRLEN); + + g_db_hFile = db_hFile = myOpenFile(state_exe_path, GENERIC_READ, OPEN_EXISTING); + if (db_hFile == INVALID_HANDLE_VALUE) + { + return _LANG_CANTOPENSELF; + } + + mystrcpy(state_exe_directory, state_exe_path); + mystrcpy(state_exe_file, trimslashtoend(state_exe_directory)); + + left = m_length = GetFileSize(db_hFile,NULL); + while (left > 0) + { + static char temp[32768]; + DWORD l = min(left, (g_filehdrsize ? 32768 : 512)); + if (!ReadSelfFile(temp, l)) + { +#if defined(NSIS_CONFIG_CRC_SUPPORT) && defined(NSIS_CONFIG_VISIBLE_SUPPORT) + handle_ver_dlg(TRUE); +#endif//NSIS_CONFIG_CRC_SUPPORT + return _LANG_INVALIDCRC; + } + + if (!g_filehdrsize) + { + mini_memcpy(&h, temp, sizeof(firstheader)); + if ( + (h.flags & (~FH_FLAGS_MASK)) == 0 && + h.siginfo == FH_SIG && + h.nsinst[2] == FH_INT3 && + h.nsinst[1] == FH_INT2 && + h.nsinst[0] == FH_INT1 + ) + { + g_filehdrsize = m_pos; + +#if defined(NSIS_CONFIG_CRC_SUPPORT) || defined(NSIS_CONFIG_SILENT_SUPPORT) + cl_flags |= h.flags; +#endif + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + g_exec_flags.silent |= cl_flags & FH_FLAGS_SILENT; +#endif + + if (h.length_of_all_following_data > left) + return _LANG_INVALIDCRC; + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if ((cl_flags & FH_FLAGS_FORCE_CRC) == 0) + { + if (cl_flags & FH_FLAGS_NO_CRC) + break; + } + + do_crc++; + +#ifndef NSIS_CONFIG_CRC_ANAL + left = h.length_of_all_following_data - 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 + // no crc support, no need to keep on reading + break; +#endif//!NSIS_CONFIG_CRC_SUPPORT + } + } +#ifdef NSIS_CONFIG_CRC_SUPPORT + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + else if ((cl_flags & FH_FLAGS_SILENT) == 0) +#endif//NSIS_CONFIG_SILENT_SUPPORT + { + handle_ver_dlg(FALSE); + } +#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 + handle_ver_dlg(TRUE); +#endif//NSIS_CONFIG_CRC_SUPPORT +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + if (!g_filehdrsize) + return _LANG_INVALIDCRC; + +#ifdef NSIS_CONFIG_CRC_SUPPORT + if (do_crc) + { + crc32_t fcrc; + SetSelfFilePointer(m_pos); + if (!ReadSelfFile(&fcrc, sizeof(crc32_t)) || crc != fcrc) + return _LANG_INVALIDCRC; + } +#endif//NSIS_CONFIG_CRC_SUPPORT + + data = (void *)GlobalAlloc(GPTR,h.length_of_header); + +#ifdef NSIS_COMPRESS_WHOLE + inflateReset(&g_inflate_stream); + + { + char fno[MAX_PATH]; + my_GetTempFileName(fno, state_temp_dir); + 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) + return _LANG_ERRORWRITINGTEMP; + } + dbd_srcpos = SetSelfFilePointer(g_filehdrsize + sizeof(firstheader)); +#ifdef NSIS_CONFIG_CRC_SUPPORT + dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data - ((h.flags & FH_FLAGS_NO_CRC) ? 0 : sizeof(crc32_t)); +#else + dbd_fulllen = dbd_srcpos - sizeof(h) + h.length_of_all_following_data; +#endif//NSIS_CONFIG_CRC_SUPPORT +#else + SetSelfFilePointer(g_filehdrsize + sizeof(firstheader)); +#endif//NSIS_COMPRESS_WHOLE + + if (GetCompressedDataFromDataBlockToMemory(-1, data, h.length_of_header) != h.length_of_header) + { + return _LANG_INVALIDCRC; + } + + header = g_header = data; + + g_flags = header->flags; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (h.flags & FH_FLAGS_UNINSTALL) + g_is_uninstaller++; +#endif + + // set offsets to real memory offsets rather than installer's header offset + left = BLOCKS_NUM; + while (left--) + header->blocks[left].offset += (int)data; + +#ifdef NSIS_COMPRESS_WHOLE + header->blocks[NB_DATA].offset = dbd_pos; +#else + header->blocks[NB_DATA].offset = SetFilePointer(db_hFile,0,NULL,FILE_CURRENT); +#endif + + mini_memcpy(&g_blocks, &header->blocks, sizeof(g_blocks)); + + return 0; +} + +#define IBUFSIZE 16384 +#define OBUFSIZE 32768 + +// returns -3 if compression error/eof/etc + +#if !defined(NSIS_COMPRESS_WHOLE) || !defined(NSIS_CONFIG_COMPRESSION_SUPPORT) + +int NSISCALL _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; + + outbuffer = outbuf?outbuf:(inbuffer+IBUFSIZE); + + if (offset>=0) + { + SetSelfFilePointer(g_blocks[NB_DATA].offset+offset); + } + + if (!ReadSelfFile((LPVOID)&input_len,sizeof(int))) return -3; + +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + if (input_len & 0x80000000) // compressed + { + char progress[64]; + int input_len_total; + DWORD ltc = GetTickCount(), tc; + + inflateReset(&g_inflate_stream); + input_len_total = input_len &= 0x7fffffff; // take off top bit. + + while (input_len > 0) + { + int l=min(input_len,IBUFSIZE); + int err; + + if (!ReadSelfFile((LPVOID)inbuffer,l)) + return -3; + + g_inflate_stream.next_in = inbuffer; + g_inflate_stream.avail_in = l; + input_len-=l; + + 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; + + tc = GetTickCount(); + if (g_exec_flags.status_update & 1 && (tc - ltc > 200 || !input_len)) + { + wsprintf(progress, "... %d%%", MulDiv(input_len_total - input_len, 100, input_len_total)); + update_status_text(0, progress); + ltc = tc; + } + + // if there's no output, more input is needed + if (!u) + break; + + if (!outbuf) + { + DWORD r; + 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; + } + } + } + else +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + { + if (!outbuf) + { + while (input_len > 0) + { + DWORD l=min(input_len,outbuffer_len); + DWORD t; + if (!ReadSelfFile((LPVOID)inbuffer,l)) return -3; + if (!WriteFile(hFileOut,inbuffer,l,&t,NULL) || l!=t) return -2; + retval+=l; + input_len-=l; + } + } + else + { + int l=min(input_len,outbuflen); + if (!ReadSelfFile((LPVOID)outbuf,l)) return -3; + retval=l; + } + } + return retval; +} +#else//NSIS_COMPRESS_WHOLE + +static char _inbuffer[IBUFSIZE]; +static char _outbuffer[OBUFSIZE]; +extern int m_length; +extern int m_pos; +extern BOOL CALLBACK verProc(HWND, UINT, WPARAM, LPARAM); +extern BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM); +static int NSISCALL __ensuredata(int amount) +{ + int needed=amount-(dbd_size-dbd_pos); +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + verify_time=GetTickCount()+500; +#endif + if (needed>0) + { + SetSelfFilePointer(dbd_srcpos); + SetFilePointer(dbd_hFile,dbd_size,NULL,FILE_BEGIN); + m_length=needed; + m_pos=0; + for (;;) + { + int err; + int l=min(IBUFSIZE,dbd_fulllen-dbd_srcpos); + if (!ReadSelfFile((LPVOID)_inbuffer,l)) return -1; + dbd_srcpos+=l; + g_inflate_stream.next_in=_inbuffer; + g_inflate_stream.avail_in=l; + do + { + DWORD r,t; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + if (g_header) +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (!g_exec_flags.silent) +#endif + { + m_pos=m_length-(amount-(dbd_size-dbd_pos)); + + handle_ver_dlg(FALSE); + } +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + g_inflate_stream.next_out=_outbuffer; + g_inflate_stream.avail_out=OBUFSIZE; + err=inflate(&g_inflate_stream); + if (err<0) + { + return -3; + } + r=(DWORD)g_inflate_stream.next_out-(DWORD)_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 || !l) 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); + } +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + handle_ver_dlg(TRUE); +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + return 0; +} + + +int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen) +{ + DWORD r; + int input_len; + int retval; + if (offset>=0) + { + dbd_pos=g_blocks[NB_DATA].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; + DWORD l=min(input_len,IBUFSIZE); + if (!ReadFile(dbd_hFile,(LPVOID)_inbuffer,l,&r,NULL) || l != r) return -3; + if (!WriteFile(hFileOut,_inbuffer,r,&t,NULL) || t != l) 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 + +BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) +{ + DWORD rd; + return ReadFile(g_db_hFile,lpBuffer,nNumberOfBytesToRead,&rd,NULL) && (rd == nNumberOfBytesToRead); +} + +DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove) +{ + return SetFilePointer(g_db_hFile,lDistanceToMove,NULL,FILE_BEGIN); +} diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index 982be84..66391f9 100755 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -1,553 +1,553 @@ -/*
- * fileform.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "config.h"
-#include "../Platform.h"
-
-#ifndef _FILEFORM_H_
-#define _FILEFORM_H_
-
-
-// * the installer is compsed of the following parts:
-// exehead (~34kb)
-// firstheader (struct firstheader)
-// * headers (compressed together):
-// header (struct header)
-// * nsis blocks (described in header->blocks)
-// pages (struct page)
-// section headers (struct section)
-// entries/instructions (struct entry)
-// strings (null seperated)
-// language tables (language id, dialog offset, language strings)
-// colors (struct color)
-// data block (files and uninstaller data)
-// * not compressed
-// CRC (optional - 4 bytes)
-//
-// headers + datablock is at least 512 bytes if CRC enabled
-
-
-#define MAX_ENTRY_OFFSETS 6
-
-
-// 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_BRINGTOFRONT, // BringToFront: 0
- 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_SETFLAG, // Sets a flag: 2 [id, data]
- EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask]
- EW_GETFLAG, // Gets a flag: 2 [output, id]
-#ifdef NSIS_SUPPORT_RENAME
- EW_RENAME, // Rename: 3 [old, new, rebootok]
-#endif
-#ifdef NSIS_SUPPORT_FNUTIL
- EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn]
- EW_SEARCHPATH, // SearchPath: 2 [output, filename]
- EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir]
-#endif
-#ifdef NSIS_SUPPORT_FILE
- EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]
- // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
-#endif
-#ifdef NSIS_SUPPORT_DELETE
- EW_DELETEFILE, // Delete File: 2, [filename, rebootok]
-#endif
-#ifdef NSIS_SUPPORT_MESSAGEBOX
- EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2]
-#endif
-#ifdef NSIS_SUPPORT_RMDIR
- EW_RMDIR, // RMDir: 2 [path, recursiveflag]
-#endif
-#ifdef NSIS_SUPPORT_STROPTS
- EW_STRLEN, // StrLen: 2 [output, input]
- EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos]
- EW_STRCMP, // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?]
-#endif
-#ifdef NSIS_SUPPORT_ENVIRONMENT
- EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead]
-#endif
-#ifdef NSIS_SUPPORT_INTOPTS
- EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?]
- 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]
-#endif
-#ifdef NSIS_SUPPORT_STACK
- EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]
-#endif
-#ifdef NSIS_SUPPORT_HWNDS
- EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]
- EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
- EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]
-#endif
-
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id]
- EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors]
- EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file]
- EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags]
- EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state]
-#endif
-
-#ifdef NSIS_SUPPORT_SHELLEXECUTE
- EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
-#endif
-
-#ifdef NSIS_SUPPORT_EXECUTE
- EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]
-#endif
-
-#ifdef NSIS_SUPPORT_GETFILETIME
- EW_GETFILETIME, // GetFileTime; 3 [file highout lowout]
-#endif
-
-#ifdef NSIS_SUPPORT_GETDLLVERSION
- EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout]
-#endif
-
-#ifdef NSIS_SUPPORT_ACTIVEXREG
- EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload]
-#endif
-
-#ifdef NSIS_SUPPORT_CREATESHORTCUT
- EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]
-#endif
-
-#ifdef NSIS_SUPPORT_COPYFILES
- EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags]
-#endif
-
-#ifdef NSIS_SUPPORT_REBOOT
- EW_REBOOT, // Reboot: 0
-#endif
-
-#ifdef NSIS_SUPPORT_INIFILES
- EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File]
- EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file]
-#endif
-
-#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
- 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]
-#endif
-
-#ifdef NSIS_SUPPORT_FILEFUNCTIONS
- 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]
-#endif//NSIS_SUPPORT_FILEFUNCTIONS
-
-#ifdef NSIS_SUPPORT_FINDFIRST
- EW_FINDCLOSE, // FindClose: 1 [handle]
- EW_FINDNEXT, // FindNext: 2 [output, handle]
- EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput]
-#endif
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size]
-#endif
-
-#ifdef NSIS_CONFIG_LOG
- EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate]
-#endif
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text]
- // SectionGetText: 3: [idx, 1, output]
- // SectionSetFlags: 3: [idx, 2, flags]
- // SectionGetFlags: 3: [idx, 3, output]
- EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags]
- // InstTypeGetFlags: 3: [idx, 1, output]
-#endif
-
- // instructions not actually implemented in exehead, but used in compiler.
- EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
- EW_GETFUNCTIONADDR,
-
-#ifdef NSIS_LOCKWINDOW_SUPPORT
- EW_LOCKWINDOW,
-#endif
-};
-
-#define FH_FLAGS_MASK 15
-#define FH_FLAGS_UNINSTALL 1
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
-# define FH_FLAGS_SILENT 2
-#endif
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-# define FH_FLAGS_NO_CRC 4
-# define FH_FLAGS_FORCE_CRC 8
-#endif
-
-#define FH_SIG 0xDEADBEEF
-
-// neato surprise signature that goes in firstheader. :)
-#define FH_INT1 0x6C6C754E
-#define FH_INT2 0x74666F73
-#define FH_INT3 0x74736E49
-
-typedef struct
-{
- int flags; // FH_FLAGS_*
- 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;
-
-// Flags for common_header.flags
-#define CH_FLAGS_DETAILS_SHOWDETAILS 1
-#define CH_FLAGS_DETAILS_NEVERSHOW 2
-#define CH_FLAGS_PROGRESS_COLORED 4
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- #define CH_FLAGS_SILENT 8
- #define CH_FLAGS_SILENT_LOG 16
-#endif
-#define CH_FLAGS_AUTO_CLOSE 32
-#define CH_FLAGS_DIR_NO_SHOW 64
-#define CH_FLAGS_NO_ROOT_DIR 128
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- #define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256
- #define CH_FLAGS_NO_CUSTOM 512
-#endif
-
-// nsis blocks
-struct block_header {
- int offset;
- int num;
-};
-
-enum {
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- NB_PAGES,
-#endif
- NB_SECTIONS,
- NB_ENTRIES,
- NB_STRINGS,
- NB_LANGTABLES,
- NB_CTLCOLORS,
-#ifdef NSIS_SUPPORT_BGBG
- NB_BGFONT,
-#endif
- NB_DATA,
-
- BLOCKS_NUM
-};
-
-// nsis strings
-
-typedef char NSIS_STRING[NSIS_MAX_STRLEN];
-
-// Settings common to both installers and uninstallers
-typedef struct
-{
- int flags; // CH_FLAGS_*
- struct block_header blocks[BLOCKS_NUM];
-
- // InstallDirRegKey stuff
- int install_reg_rootkey;
- // these two are not processed!
- int install_reg_key_ptr, install_reg_value_ptr;
-
-#ifdef NSIS_SUPPORT_BGBG
- int bg_color1, bg_color2, bg_textcolor;
-#endif
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- // installation log window colors
- int lb_bg, lb_fg;
-#endif
-
- // langtable size
- int langtable_size;
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- // license background color
- int license_bg;
-#endif//NSIS_CONFIG_LICENSEPAGE
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // .on* calls
- int code_onInit;
- int code_onInstSuccess;
- int code_onInstFailed;
- int code_onUserAbort;
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- int code_onGUIInit;
- int code_onGUIEnd;
- int code_onMouseOverSection;
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
- int code_onVerifyInstDir;
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- int code_onSelChange;
-#endif//NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_SUPPORT_REBOOT
- int code_onRebootFailed;
-#endif//NSIS_SUPPORT_REBOOT
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- int install_types[NSIS_MAX_INST_TYPES+1];
-#endif
-
- int install_directory_ptr; // default install dir.
- int install_directory_auto_append; // auto append part
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- int str_uninstchild;
- int str_uninstcmd;
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- int str_wininit;
-#endif//NSIS_SUPPORT_MOVEONREBOOT
-} header;
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
-// callback indices
-enum
-{
- CB_ONINIT,
- CB_ONINSTSUCCESS,
- CB_ONINSTFAILED,
- CB_ONUSERABORT,
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- CB_ONGUIINIT,
- CB_ONGUIEND,
- CB_ONMOUSEOVERSECTION,
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
- CB_ONVERIFYINSTDIR,
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- CB_ONSELCHANGE,
-#endif//NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_SUPPORT_REBOOT
- CB_ONREBOOTFAILED
-#endif//NSIS_SUPPORT_REBOOT
-};
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
-// used for section->flags
-#define SF_SELECTED 1
-#define SF_SECGRP 2
-#define SF_SECGRPEND 4
-#define SF_BOLD 8
-#define SF_RO 16
-#define SF_EXPAND 32
-#define SF_PSELECTED 64
-#define SF_TOGGLED 128
-#define SF_NAMECHG 256
-
-typedef struct
-{
- int name_ptr; // initial name pointer
- int install_types; // bits set for each of the different install_types, if any.
- int flags; // SF_* - defined above
- int code;
- int code_size;
- int size_kb;
- char name[NSIS_MAX_STRLEN]; // '' for invisible sections
-} section;
-
-#define SECTION_OFFSET(field) (FIELD_OFFSET(section, field)/sizeof(int))
-
-typedef struct
-{
- int which;
- int offsets[MAX_ENTRY_OFFSETS]; // count and meaning of offsets depend on 'which'
-} entry;
-
-// page window proc
-enum
-{
-#ifdef NSIS_CONFIG_LICENSEPAGE
- PWP_LICENSE,
-#endif
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- PWP_SELCOM,
-#endif
- PWP_DIR,
- PWP_INSTFILES,
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- PWP_UNINST,
-#endif
- PWP_COMPLETED,
- PWP_CUSTOM
-};
-
-// page flags
-#define PF_BACK_ENABLE 256
-#define PF_NEXT_ENABLE 2
-#define PF_CANCEL_ENABLE 4
-#define PF_BACK_SHOW 8 // must be SW_SHOWNA, don't change
-#define PF_LICENSE_STREAM 16
-#define PF_LICENSE_FORCE_SELECTION 32
-#define PF_LICENSE_NO_FORCE_SELECTION 64
-#define PF_LICENSE_SELECTED 1 // must be 1
-#define PF_NO_NEXT_FOCUS 128
-#define PF_PAGE_EX 512
-#define PF_DIR_NO_BTN_DISABLE 1024
-
-typedef struct
-{
- int dlg_id; // dialog resource id
- int wndproc_id;
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- // called before the page is created, or if custom to show the page
- // use Abort to skip the page
- int prefunc;
- // called right before page is shown
- int showfunc;
- // called when the user leaves to the next page
- // use Abort to force the user to stay on this page
- int leavefunc;
-#endif //NSIS_SUPPORT_CODECALLBACKS
-
- int flags;
-
- int caption;
- int back;
- int next;
- int clicknext;
- int cancel;
-
- int parms[5];
-} page;
-
-// text/bg color
-#define CC_TEXT 1
-#define CC_TEXT_SYS 2
-#define CC_BK 4
-#define CC_BK_SYS 8
-#define CC_BKB 16
-
-typedef struct {
- COLORREF text;
- COLORREF bkc;
- UINT lbStyle;
- HBRUSH bkb;
- int bkmode;
- int flags;
-} ctlcolors;
-
-// constants for myDelete (util.c)
-#define DEL_DIR 1
-#define DEL_RECURSE 2
-#define DEL_REBOOT 4
-#define DEL_SIMPLE 8
-
-// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value.
-// Added by ramon 3 jun 2003
-#define NS_SKIP_CODE 252
-#define NS_VAR_CODE 253
-#define NS_SHELL_CODE 254
-#define NS_LANG_CODE 255
-#define NS_CODES_START NS_SKIP_CODE
-
-#define CODE_SHORT(x) (WORD)((((WORD)x & 0x7F) | (((WORD)x & 0x3F80) << 1) | 0x8080))
-#define MAX_CODED 16383
-
-#define NSIS_INSTDIR_INVALID 1
-#define NSIS_INSTDIR_NOT_ENOUGH_SPACE 2
-
-typedef struct
-{
- int autoclose;
- int all_user_var;
- int exec_error;
- int abort;
-#ifdef NSIS_SUPPORT_REBOOT
- int exec_reboot;
- int reboot_called;
-#else
- int _;
- int __;
-#endif
- int XXX_cur_insttype; // depreacted
- int XXX_insttype_changed; // deprecated
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- int silent;
-#else
- int ___;
-#endif
- int instdir_error;
- int rtl;
- int errlvl;
- int alter_reg_view;
- int status_update;
-} exec_flags;
-
-#define FIELDN(x, y) (((int *)&x)[y])
-
-#ifdef EXEHEAD
-
-// the following are only used/implemented in exehead, not makensis.
-
-int NSISCALL 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)
-const char * NSISCALL loadHeaders(int cl_flags);
-
-int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen);
-
-#define GetCompressedDataFromDataBlock(offset, hFileOut) _dodecomp(offset,hFileOut,NULL,0)
-#define GetCompressedDataFromDataBlockToMemory(offset, out, out_len) _dodecomp(offset,NULL,out,out_len)
-
-extern HANDLE g_db_hFile;
-extern int g_quit_flag;
-
-BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead);
-DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove);
-
-extern struct block_header g_blocks[BLOCKS_NUM];
-extern header *g_header;
-extern int g_flags;
-extern int g_filehdrsize;
-extern int g_is_uninstaller;
-
-#define g_pages ((page*)g_blocks[NB_PAGES].offset)
-#define g_sections ((section*)g_blocks[NB_SECTIONS].offset)
-#define num_sections (g_blocks[NB_SECTIONS].num)
-#define g_entries ((entry*)g_blocks[NB_ENTRIES].offset)
-#endif
-
-#endif //_FILEFORM_H_
+/* + * fileform.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "config.h" +#include "../Platform.h" + +#ifndef _FILEFORM_H_ +#define _FILEFORM_H_ + + +// * the installer is compsed of the following parts: +// exehead (~34kb) +// firstheader (struct firstheader) +// * headers (compressed together): +// header (struct header) +// * nsis blocks (described in header->blocks) +// pages (struct page) +// section headers (struct section) +// entries/instructions (struct entry) +// strings (null seperated) +// language tables (language id, dialog offset, language strings) +// colors (struct color) +// data block (files and uninstaller data) +// * not compressed +// CRC (optional - 4 bytes) +// +// headers + datablock is at least 512 bytes if CRC enabled + + +#define MAX_ENTRY_OFFSETS 6 + + +// 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_BRINGTOFRONT, // BringToFront: 0 + 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_SETFLAG, // Sets a flag: 2 [id, data] + EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask] + EW_GETFLAG, // Gets a flag: 2 [output, id] +#ifdef NSIS_SUPPORT_RENAME + EW_RENAME, // Rename: 3 [old, new, rebootok] +#endif +#ifdef NSIS_SUPPORT_FNUTIL + EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn] + EW_SEARCHPATH, // SearchPath: 2 [output, filename] + EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir] +#endif +#ifdef NSIS_SUPPORT_FILE + EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore] + // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer +#endif +#ifdef NSIS_SUPPORT_DELETE + EW_DELETEFILE, // Delete File: 2, [filename, rebootok] +#endif +#ifdef NSIS_SUPPORT_MESSAGEBOX + EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2] +#endif +#ifdef NSIS_SUPPORT_RMDIR + EW_RMDIR, // RMDir: 2 [path, recursiveflag] +#endif +#ifdef NSIS_SUPPORT_STROPTS + EW_STRLEN, // StrLen: 2 [output, input] + EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos] + EW_STRCMP, // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?] +#endif +#ifdef NSIS_SUPPORT_ENVIRONMENT + EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead] +#endif +#ifdef NSIS_SUPPORT_INTOPTS + EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?] + 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] +#endif +#ifdef NSIS_SUPPORT_STACK + EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch] +#endif +#ifdef NSIS_SUPPORT_HWNDS + EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after] + EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2] + EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow] +#endif + +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id] + EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors] + EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file] + EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags] + EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state] +#endif + +#ifdef NSIS_SUPPORT_SHELLEXECUTE + EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow] +#endif + +#ifdef NSIS_SUPPORT_EXECUTE + EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode] +#endif + +#ifdef NSIS_SUPPORT_GETFILETIME + EW_GETFILETIME, // GetFileTime; 3 [file highout lowout] +#endif + +#ifdef NSIS_SUPPORT_GETDLLVERSION + EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout] +#endif + +#ifdef NSIS_SUPPORT_ACTIVEXREG + EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload] +#endif + +#ifdef NSIS_SUPPORT_CREATESHORTCUT + EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16] +#endif + +#ifdef NSIS_SUPPORT_COPYFILES + EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags] +#endif + +#ifdef NSIS_SUPPORT_REBOOT + EW_REBOOT, // Reboot: 0 +#endif + +#ifdef NSIS_SUPPORT_INIFILES + EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File] + EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file] +#endif + +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + 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] +#endif + +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + 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] +#endif//NSIS_SUPPORT_FILEFUNCTIONS + +#ifdef NSIS_SUPPORT_FINDFIRST + EW_FINDCLOSE, // FindClose: 1 [handle] + EW_FINDNEXT, // FindNext: 2 [output, handle] + EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput] +#endif + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size] +#endif + +#ifdef NSIS_CONFIG_LOG + EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate] +#endif + +#ifdef NSIS_CONFIG_COMPONENTPAGE + EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text] + // SectionGetText: 3: [idx, 1, output] + // SectionSetFlags: 3: [idx, 2, flags] + // SectionGetFlags: 3: [idx, 3, output] + EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags] + // InstTypeGetFlags: 3: [idx, 1, output] +#endif + + // instructions not actually implemented in exehead, but used in compiler. + EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR + EW_GETFUNCTIONADDR, + +#ifdef NSIS_LOCKWINDOW_SUPPORT + EW_LOCKWINDOW, +#endif +}; + +#define FH_FLAGS_MASK 15 +#define FH_FLAGS_UNINSTALL 1 +#ifdef NSIS_CONFIG_SILENT_SUPPORT +# define FH_FLAGS_SILENT 2 +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT +# define FH_FLAGS_NO_CRC 4 +# define FH_FLAGS_FORCE_CRC 8 +#endif + +#define FH_SIG 0xDEADBEEF + +// neato surprise signature that goes in firstheader. :) +#define FH_INT1 0x6C6C754E +#define FH_INT2 0x74666F73 +#define FH_INT3 0x74736E49 + +typedef struct +{ + int flags; // FH_FLAGS_* + 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; + +// Flags for common_header.flags +#define CH_FLAGS_DETAILS_SHOWDETAILS 1 +#define CH_FLAGS_DETAILS_NEVERSHOW 2 +#define CH_FLAGS_PROGRESS_COLORED 4 +#ifdef NSIS_CONFIG_SILENT_SUPPORT + #define CH_FLAGS_SILENT 8 + #define CH_FLAGS_SILENT_LOG 16 +#endif +#define CH_FLAGS_AUTO_CLOSE 32 +#define CH_FLAGS_DIR_NO_SHOW 64 +#define CH_FLAGS_NO_ROOT_DIR 128 +#ifdef NSIS_CONFIG_COMPONENTPAGE + #define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256 + #define CH_FLAGS_NO_CUSTOM 512 +#endif + +// nsis blocks +struct block_header { + int offset; + int num; +}; + +enum { +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + NB_PAGES, +#endif + NB_SECTIONS, + NB_ENTRIES, + NB_STRINGS, + NB_LANGTABLES, + NB_CTLCOLORS, +#ifdef NSIS_SUPPORT_BGBG + NB_BGFONT, +#endif + NB_DATA, + + BLOCKS_NUM +}; + +// nsis strings + +typedef char NSIS_STRING[NSIS_MAX_STRLEN]; + +// Settings common to both installers and uninstallers +typedef struct +{ + int flags; // CH_FLAGS_* + struct block_header blocks[BLOCKS_NUM]; + + // InstallDirRegKey stuff + int install_reg_rootkey; + // these two are not processed! + int install_reg_key_ptr, install_reg_value_ptr; + +#ifdef NSIS_SUPPORT_BGBG + int bg_color1, bg_color2, bg_textcolor; +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + // installation log window colors + int lb_bg, lb_fg; +#endif + + // langtable size + int langtable_size; + +#ifdef NSIS_CONFIG_LICENSEPAGE + // license background color + int license_bg; +#endif//NSIS_CONFIG_LICENSEPAGE + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // .on* calls + int code_onInit; + int code_onInstSuccess; + int code_onInstFailed; + int code_onUserAbort; +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + int code_onGUIInit; + int code_onGUIEnd; + int code_onMouseOverSection; +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT + int code_onVerifyInstDir; +#ifdef NSIS_CONFIG_COMPONENTPAGE + int code_onSelChange; +#endif//NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_SUPPORT_REBOOT + int code_onRebootFailed; +#endif//NSIS_SUPPORT_REBOOT +#endif//NSIS_SUPPORT_CODECALLBACKS + +#ifdef NSIS_CONFIG_COMPONENTPAGE + int install_types[NSIS_MAX_INST_TYPES+1]; +#endif + + int install_directory_ptr; // default install dir. + int install_directory_auto_append; // auto append part + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + int str_uninstchild; + int str_uninstcmd; +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_SUPPORT_MOVEONREBOOT + int str_wininit; +#endif//NSIS_SUPPORT_MOVEONREBOOT +} header; + +#ifdef NSIS_SUPPORT_CODECALLBACKS +// callback indices +enum +{ + CB_ONINIT, + CB_ONINSTSUCCESS, + CB_ONINSTFAILED, + CB_ONUSERABORT, +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + CB_ONGUIINIT, + CB_ONGUIEND, + CB_ONMOUSEOVERSECTION, +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT + CB_ONVERIFYINSTDIR, +#ifdef NSIS_CONFIG_COMPONENTPAGE + CB_ONSELCHANGE, +#endif//NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_SUPPORT_REBOOT + CB_ONREBOOTFAILED +#endif//NSIS_SUPPORT_REBOOT +}; +#endif//NSIS_SUPPORT_CODECALLBACKS + +// used for section->flags +#define SF_SELECTED 1 +#define SF_SECGRP 2 +#define SF_SECGRPEND 4 +#define SF_BOLD 8 +#define SF_RO 16 +#define SF_EXPAND 32 +#define SF_PSELECTED 64 +#define SF_TOGGLED 128 +#define SF_NAMECHG 256 + +typedef struct +{ + int name_ptr; // initial name pointer + int install_types; // bits set for each of the different install_types, if any. + int flags; // SF_* - defined above + int code; + int code_size; + int size_kb; + char name[NSIS_MAX_STRLEN]; // '' for invisible sections +} section; + +#define SECTION_OFFSET(field) (FIELD_OFFSET(section, field)/sizeof(int)) + +typedef struct +{ + int which; + int offsets[MAX_ENTRY_OFFSETS]; // count and meaning of offsets depend on 'which' +} entry; + +// page window proc +enum +{ +#ifdef NSIS_CONFIG_LICENSEPAGE + PWP_LICENSE, +#endif +#ifdef NSIS_CONFIG_COMPONENTPAGE + PWP_SELCOM, +#endif + PWP_DIR, + PWP_INSTFILES, +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + PWP_UNINST, +#endif + PWP_COMPLETED, + PWP_CUSTOM +}; + +// page flags +#define PF_BACK_ENABLE 256 +#define PF_NEXT_ENABLE 2 +#define PF_CANCEL_ENABLE 4 +#define PF_BACK_SHOW 8 // must be SW_SHOWNA, don't change +#define PF_LICENSE_STREAM 16 +#define PF_LICENSE_FORCE_SELECTION 32 +#define PF_LICENSE_NO_FORCE_SELECTION 64 +#define PF_LICENSE_SELECTED 1 // must be 1 +#define PF_NO_NEXT_FOCUS 128 +#define PF_PAGE_EX 512 +#define PF_DIR_NO_BTN_DISABLE 1024 + +typedef struct +{ + int dlg_id; // dialog resource id + int wndproc_id; + +#ifdef NSIS_SUPPORT_CODECALLBACKS + // called before the page is created, or if custom to show the page + // use Abort to skip the page + int prefunc; + // called right before page is shown + int showfunc; + // called when the user leaves to the next page + // use Abort to force the user to stay on this page + int leavefunc; +#endif //NSIS_SUPPORT_CODECALLBACKS + + int flags; + + int caption; + int back; + int next; + int clicknext; + int cancel; + + int parms[5]; +} page; + +// text/bg color +#define CC_TEXT 1 +#define CC_TEXT_SYS 2 +#define CC_BK 4 +#define CC_BK_SYS 8 +#define CC_BKB 16 + +typedef struct { + COLORREF text; + COLORREF bkc; + UINT lbStyle; + HBRUSH bkb; + int bkmode; + int flags; +} ctlcolors; + +// constants for myDelete (util.c) +#define DEL_DIR 1 +#define DEL_RECURSE 2 +#define DEL_REBOOT 4 +#define DEL_SIMPLE 8 + +// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value. +// Added by ramon 3 jun 2003 +#define NS_SKIP_CODE 252 +#define NS_VAR_CODE 253 +#define NS_SHELL_CODE 254 +#define NS_LANG_CODE 255 +#define NS_CODES_START NS_SKIP_CODE + +#define CODE_SHORT(x) (WORD)((((WORD)x & 0x7F) | (((WORD)x & 0x3F80) << 1) | 0x8080)) +#define MAX_CODED 16383 + +#define NSIS_INSTDIR_INVALID 1 +#define NSIS_INSTDIR_NOT_ENOUGH_SPACE 2 + +typedef struct +{ + int autoclose; + int all_user_var; + int exec_error; + int abort; +#ifdef NSIS_SUPPORT_REBOOT + int exec_reboot; + int reboot_called; +#else + int _; + int __; +#endif + int XXX_cur_insttype; // depreacted + int XXX_insttype_changed; // deprecated +#ifdef NSIS_CONFIG_SILENT_SUPPORT + int silent; +#else + int ___; +#endif + int instdir_error; + int rtl; + int errlvl; + int alter_reg_view; + int status_update; +} exec_flags; + +#define FIELDN(x, y) (((int *)&x)[y]) + +#ifdef EXEHEAD + +// the following are only used/implemented in exehead, not makensis. + +int NSISCALL 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) +const char * NSISCALL loadHeaders(int cl_flags); + +int NSISCALL _dodecomp(int offset, HANDLE hFileOut, char *outbuf, int outbuflen); + +#define GetCompressedDataFromDataBlock(offset, hFileOut) _dodecomp(offset,hFileOut,NULL,0) +#define GetCompressedDataFromDataBlockToMemory(offset, out, out_len) _dodecomp(offset,NULL,out,out_len) + +extern HANDLE g_db_hFile; +extern int g_quit_flag; + +BOOL NSISCALL ReadSelfFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead); +DWORD NSISCALL SetSelfFilePointer(LONG lDistanceToMove); + +extern struct block_header g_blocks[BLOCKS_NUM]; +extern header *g_header; +extern int g_flags; +extern int g_filehdrsize; +extern int g_is_uninstaller; + +#define g_pages ((page*)g_blocks[NB_PAGES].offset) +#define g_sections ((section*)g_blocks[NB_SECTIONS].offset) +#define num_sections (g_blocks[NB_SECTIONS].num) +#define g_entries ((entry*)g_blocks[NB_ENTRIES].offset) +#endif + +#endif //_FILEFORM_H_ diff --git a/Source/exehead/lang.h b/Source/exehead/lang.h index db5b26b..4c6d425 100755 --- a/Source/exehead/lang.h +++ b/Source/exehead/lang.h @@ -1,85 +1,85 @@ -/*
- * lang.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _NSIS_LANG_H_
-#define _NSIS_LANG_H_
-
-
-// generic startup strings (these will never be overridable)
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-#define _LANG_INVALIDCRC "The installer you are trying to use is corrupted or incomplete.\n" \
- "This could be the result of a damaged disk, a failed download or a virus.\n\n" \
- "You may want to contact the author of this installer to obtain a new copy.\n\n" \
- "It may be possible to skip this check using the /NCRC command line switch\n" \
- "(NOT RECOMMENDED)."
-#else
-#define _LANG_INVALIDCRC "The installer you are trying to use is corrupted or incomplete.\n" \
- "This could be the result of a damaged disk, a failed download or a virus.\n\n" \
- "You may want to contact the author of this installer to obtain a new copy."
-#endif
-
-#define _LANG_ERRORWRITINGTEMP "Error writing temporary file. Make sure your temp folder is valid."
-
-#define _LANG_UNINSTINITERROR "Error launching installer"
-
-#define _LANG_VERIFYINGINST "verifying installer: %d%%"
-
-#define _LANG_UNPACKING "unpacking data: %d%%"
-
-#define _LANG_CANTOPENSELF "Error launching installer" // same as uninstiniterror for size
-
-#define _LANG_GENERIC_ERROR "NSIS Error"
-
-#define LANG_STR_TAB(x) cur_langtable[-((int)x+1)]
-
-#define LANG_BRANDING -1
-#define LANG_CAPTION -2
-#define LANG_NAME -3
-#define LANG_SPACE_AVAIL -4
-#define LANG_SPACE_REQ -5
-#define LANG_CANTWRITE -6
-#define LANG_COPYFAILED -7
-#define LANG_COPYTO -8
-#define LANG_CANNOTFINDSYMBOL -9
-#define LANG_COULDNOTLOAD -10
-#define LANG_CREATEDIR -11
-#define LANG_CREATESHORTCUT -12
-#define LANG_CREATEDUNINST -13
-#define LANG_DELETEFILE -14
-#define LANG_DELETEONREBOOT -15
-#define LANG_ERRORCREATINGSHORTCUT -16
-#define LANG_ERRORCREATING -17
-#define LANG_ERRORDECOMPRESSING -18
-#define LANG_DLLREGERROR -19
-#define LANG_EXECSHELL -20
-#define LANG_EXECUTE -21
-#define LANG_EXTRACT -22
-#define LANG_ERRORWRITING -23
-#define LANG_INSTCORRUPTED -24
-#define LANG_NOOLE -25
-#define LANG_OUTPUTDIR -26
-#define LANG_REMOVEDIR -27
-#define LANG_RENAMEONREBOOT -28
-#define LANG_RENAME -29
-#define LANG_SKIPPED -30
-#define LANG_COPYDETAILS -31
-#define LANG_LOG_INSTALL_PROCESS -32
-#define LANG_BYTE -33
-#define LANG_KILO -34
-#define LANG_MEGA -35
-#define LANG_GIGA -36
-
-#endif//_NSIS_LANG_H_
+/* + * lang.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _NSIS_LANG_H_ +#define _NSIS_LANG_H_ + + +// generic startup strings (these will never be overridable) +#ifdef NSIS_CONFIG_CRC_SUPPORT +#define _LANG_INVALIDCRC "The installer you are trying to use is corrupted or incomplete.\n" \ + "This could be the result of a damaged disk, a failed download or a virus.\n\n" \ + "You may want to contact the author of this installer to obtain a new copy.\n\n" \ + "It may be possible to skip this check using the /NCRC command line switch\n" \ + "(NOT RECOMMENDED)." +#else +#define _LANG_INVALIDCRC "The installer you are trying to use is corrupted or incomplete.\n" \ + "This could be the result of a damaged disk, a failed download or a virus.\n\n" \ + "You may want to contact the author of this installer to obtain a new copy." +#endif + +#define _LANG_ERRORWRITINGTEMP "Error writing temporary file. Make sure your temp folder is valid." + +#define _LANG_UNINSTINITERROR "Error launching installer" + +#define _LANG_VERIFYINGINST "verifying installer: %d%%" + +#define _LANG_UNPACKING "unpacking data: %d%%" + +#define _LANG_CANTOPENSELF "Error launching installer" // same as uninstiniterror for size + +#define _LANG_GENERIC_ERROR "NSIS Error" + +#define LANG_STR_TAB(x) cur_langtable[-((int)x+1)] + +#define LANG_BRANDING -1 +#define LANG_CAPTION -2 +#define LANG_NAME -3 +#define LANG_SPACE_AVAIL -4 +#define LANG_SPACE_REQ -5 +#define LANG_CANTWRITE -6 +#define LANG_COPYFAILED -7 +#define LANG_COPYTO -8 +#define LANG_CANNOTFINDSYMBOL -9 +#define LANG_COULDNOTLOAD -10 +#define LANG_CREATEDIR -11 +#define LANG_CREATESHORTCUT -12 +#define LANG_CREATEDUNINST -13 +#define LANG_DELETEFILE -14 +#define LANG_DELETEONREBOOT -15 +#define LANG_ERRORCREATINGSHORTCUT -16 +#define LANG_ERRORCREATING -17 +#define LANG_ERRORDECOMPRESSING -18 +#define LANG_DLLREGERROR -19 +#define LANG_EXECSHELL -20 +#define LANG_EXECUTE -21 +#define LANG_EXTRACT -22 +#define LANG_ERRORWRITING -23 +#define LANG_INSTCORRUPTED -24 +#define LANG_NOOLE -25 +#define LANG_OUTPUTDIR -26 +#define LANG_REMOVEDIR -27 +#define LANG_RENAMEONREBOOT -28 +#define LANG_RENAME -29 +#define LANG_SKIPPED -30 +#define LANG_COPYDETAILS -31 +#define LANG_LOG_INSTALL_PROCESS -32 +#define LANG_BYTE -33 +#define LANG_KILO -34 +#define LANG_MEGA -35 +#define LANG_GIGA -36 + +#endif//_NSIS_LANG_H_ diff --git a/Source/exehead/resource.h b/Source/exehead/resource.h index 53b2fb5..df080c8 100755 --- a/Source/exehead/resource.h +++ b/Source/exehead/resource.h @@ -1,56 +1,56 @@ -//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by resource.rc
-//
-#ifndef DS_SHELLFONT
-#define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS)
-#endif
-
-#define IDC_BACK 3
-#define IDD_LICENSE 102
-#define IDD_LICENSE_FSRB 108
-#define IDD_LICENSE_FSCB 109
-#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 IDD_VERIFY 111
-#define IDB_BITMAP1 110
-#define IDC_EDIT1 1000
-#define IDC_BROWSE 1001
-#define IDC_PROGRESS 1004
-#define IDC_INTROTEXT 1006
-#define IDC_CHECK1 1008
-#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_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
-#define IDC_LICENSEAGREE 1034
-#define IDC_LICENSEDISAGREE 1035
-
-// 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 1036
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
-
-
+//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#ifndef DS_SHELLFONT +#define DS_SHELLFONT (DS_SETFONT | DS_FIXEDSYS) +#endif + +#define IDC_BACK 3 +#define IDD_LICENSE 102 +#define IDD_LICENSE_FSRB 108 +#define IDD_LICENSE_FSCB 109 +#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 IDD_VERIFY 111 +#define IDB_BITMAP1 110 +#define IDC_EDIT1 1000 +#define IDC_BROWSE 1001 +#define IDC_PROGRESS 1004 +#define IDC_INTROTEXT 1006 +#define IDC_CHECK1 1008 +#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_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 +#define IDC_LICENSEAGREE 1034 +#define IDC_LICENSEDISAGREE 1035 + +// 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 1036 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + + diff --git a/Source/exehead/resource.rc b/Source/exehead/resource.rc index e3b83e1..245927e 100755 --- a/Source/exehead/resource.rc +++ b/Source/exehead/resource.rc @@ -1,282 +1,282 @@ -//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) DIALOGEX 0, 0, 266, 130
-#else
-IDD_LICENSE DIALOGEX 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- ICON IDI_ICON2,IDC_ULICON,0,0,22,20
- LTEXT "",IDC_INTROTEXT,25,0,241,23
- CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL |
- WS_TABSTOP | 0x804,0,24,266,105
-END
-#endif
-
-#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE)
-#if defined(APSTUDIO_INVOKED)
-IDD_LICENSE_FSRB$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130
-#else
-IDD_LICENSE_FSRB DIALOG DISCARDABLE 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg"
-BEGIN
- ICON IDI_ICON2,1031,0,0,22,20
- LTEXT "",IDC_INTROTEXT,25,0,241,23
- CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL |
- WS_TABSTOP | 0x804,0,24,266,85
- CONTROL "",IDC_LICENSEAGREE,"Button",BS_AUTORADIOBUTTON |
- WS_TABSTOP,0,110,266,9
- CONTROL "",IDC_LICENSEDISAGREE,"Button",BS_AUTORADIOBUTTON |
- WS_TABSTOP,0,120,266,9
-END
-#endif
-
-#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE)
-#if defined(APSTUDIO_INVOKED)
-IDD_LICENSE_FSCB$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130
-#else
-IDD_LICENSE_FSCB DIALOG DISCARDABLE 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg"
-BEGIN
- ICON IDI_ICON2,1031,0,0,22,20
- LTEXT "",IDC_INTROTEXT,25,0,241,23
- CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL |
- WS_TABSTOP | 0x804,0,24,266,95
- CONTROL "",IDC_LICENSEAGREE,"Button",BS_AUTOCHECKBOX |
- WS_TABSTOP,0,120,266,9
-END
-#endif
-
-#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT)
-#if defined(APSTUDIO_INVOKED)
-IDD_DIR$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOGEX 0, 0, 266, 130
-#else
-IDD_DIR DIALOGEX 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- EDITTEXT IDC_DIR,8,49,187,12,ES_AUTOHSCROLL
- PUSHBUTTON "",IDC_BROWSE,202,48,55,14
- ICON IDI_ICON2,IDC_ULICON,0,0,22,20
- CONTROL "",IDC_SPACEAVAILABLE,"Static",SS_LEFTNOWORDWRAP,0,122,
- 265,8
- CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE |
- WS_TABSTOP,8,71,118,10
- CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP,0,111,
- 265,8
- LTEXT "",IDC_INTROTEXT,25,0,241,34
- GROUPBOX "",IDC_SELDIRTEXT,1,38,264,30
-END
-#endif
-
-#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE)
-#if defined(APSTUDIO_INVOKED)
-IDD_SELCOM$(NSIS_CONFIG_COMPONENTPAGE) DIALOGEX 0, 0, 266, 130
-#else
-IDD_SELCOM DIALOGEX 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- COMBOBOX IDC_COMBO1,114,25,152,102,CBS_DROPDOWNLIST | NOT
- WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
- ICON IDI_ICON2,IDC_ULICON,0,0,22,20
- LTEXT "",IDC_TEXT2,0,40,108,65
- CONTROL "",IDC_TEXT1,"Static",SS_LEFTNOWORDWRAP,0,27,108,8
- LTEXT "",IDC_SPACEREQUIRED,0,111,111,18,NOT WS_GROUP
- LTEXT "",IDC_INTROTEXT,25,0,241,25
- CONTROL "",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) DIALOGEX 0, 0, 280, 162
-#else
-IDD_INST DIALOGEX 0, 0, 280, 162
-#endif
-STYLE DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION |
- WS_SYSMENU
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- PUSHBUTTON "",IDC_BACK,171,142,50,14,NOT WS_VISIBLE | WS_GROUP
- PUSHBUTTON "",IDOK,223,142,50,14
- PUSHBUTTON "",IDCANCEL,7,142,50,14
- CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ | WS_GROUP,7,138,
- 267,1
- CONTROL "",IDC_CHILDRECT,"Static",SS_BLACKRECT | NOT WS_VISIBLE |
- WS_GROUP,7,6,266,130
- 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) DIALOGEX 0, 0, 266, 130
-#else
-IDD_INSTFILES DIALOGEX 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,24,10,241,
- 11
- CONTROL "",IDC_INTROTEXT,"Static",SS_LEFTNOWORDWRAP |
- SS_NOPREFIX,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,22,20
- PUSHBUTTON "",IDC_SHOWDETAILS,0,28,60,14,NOT WS_TABSTOP
-END
-#endif
-
-#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_UNINSTDLG)
-#if defined(APSTUDIO_INVOKED)
-IDD_UNINST$(_NSIS_CONFIG_UNINSTDLG) DIALOGEX 0, 0, 266, 130
-#else
-IDD_UNINST DIALOGEX 0, 0, 266, 130
-#endif
-STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-BEGIN
- ICON IDI_ICON2,IDC_ULICON,0,1,22,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) DIALOGEX 0, 0, 162, 22
-#else
-IDD_VERIFY DIALOGEX 0, 0, 162, 22
-#endif
-STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP
-FONT 8, "MS Shell Dlg", 0, 0, 0x1
-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
-/////////////////////////////////////////////////////////////////////////////
-
-
+//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) DIALOGEX 0, 0, 266, 130 +#else +IDD_LICENSE DIALOGEX 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDI_ICON2,IDC_ULICON,0,0,22,20 + LTEXT "",IDC_INTROTEXT,25,0,241,23 + CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL | + WS_TABSTOP | 0x804,0,24,266,105 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE) +#if defined(APSTUDIO_INVOKED) +IDD_LICENSE_FSRB$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_LICENSE_FSRB DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_ICON2,1031,0,0,22,20 + LTEXT "",IDC_INTROTEXT,25,0,241,23 + CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL | + WS_TABSTOP | 0x804,0,24,266,85 + CONTROL "",IDC_LICENSEAGREE,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,0,110,266,9 + CONTROL "",IDC_LICENSEDISAGREE,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,0,120,266,9 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_LICENSEPAGE) +#if defined(APSTUDIO_INVOKED) +IDD_LICENSE_FSCB$(NSIS_CONFIG_LICENSEPAGE) DIALOG DISCARDABLE 0, 0, 266, 130 +#else +IDD_LICENSE_FSCB DIALOG DISCARDABLE 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDI_ICON2,1031,0,0,22,20 + LTEXT "",IDC_INTROTEXT,25,0,241,23 + CONTROL "",IDC_EDIT1,"RichEdit20A",WS_BORDER | WS_VSCROLL | + WS_TABSTOP | 0x804,0,24,266,95 + CONTROL "",IDC_LICENSEAGREE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,0,120,266,9 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_VISIBLE_SUPPORT) +#if defined(APSTUDIO_INVOKED) +IDD_DIR$(NSIS_CONFIG_VISIBLE_SUPPORT) DIALOGEX 0, 0, 266, 130 +#else +IDD_DIR DIALOGEX 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_DIR,8,49,187,12,ES_AUTOHSCROLL + PUSHBUTTON "",IDC_BROWSE,202,48,55,14 + ICON IDI_ICON2,IDC_ULICON,0,0,22,20 + CONTROL "",IDC_SPACEAVAILABLE,"Static",SS_LEFTNOWORDWRAP,0,122, + 265,8 + CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | + WS_TABSTOP,8,71,118,10 + CONTROL "",IDC_SPACEREQUIRED,"Static",SS_LEFTNOWORDWRAP,0,111, + 265,8 + LTEXT "",IDC_INTROTEXT,25,0,241,34 + GROUPBOX "",IDC_SELDIRTEXT,1,38,264,30 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE) +#if defined(APSTUDIO_INVOKED) +IDD_SELCOM$(NSIS_CONFIG_COMPONENTPAGE) DIALOGEX 0, 0, 266, 130 +#else +IDD_SELCOM DIALOGEX 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_COMBO1,114,25,152,102,CBS_DROPDOWNLIST | NOT + WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + ICON IDI_ICON2,IDC_ULICON,0,0,22,20 + LTEXT "",IDC_TEXT2,0,40,108,65 + CONTROL "",IDC_TEXT1,"Static",SS_LEFTNOWORDWRAP,0,27,108,8 + LTEXT "",IDC_SPACEREQUIRED,0,111,111,18,NOT WS_GROUP + LTEXT "",IDC_INTROTEXT,25,0,241,25 + CONTROL "",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) DIALOGEX 0, 0, 280, 162 +#else +IDD_INST DIALOGEX 0, 0, 280, 162 +#endif +STYLE DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | + WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + PUSHBUTTON "",IDC_BACK,171,142,50,14,NOT WS_VISIBLE | WS_GROUP + PUSHBUTTON "",IDOK,223,142,50,14 + PUSHBUTTON "",IDCANCEL,7,142,50,14 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ | WS_GROUP,7,138, + 267,1 + CONTROL "",IDC_CHILDRECT,"Static",SS_BLACKRECT | NOT WS_VISIBLE | + WS_GROUP,7,6,266,130 + 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) DIALOGEX 0, 0, 266, 130 +#else +IDD_INSTFILES DIALOGEX 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,24,10,241, + 11 + CONTROL "",IDC_INTROTEXT,"Static",SS_LEFTNOWORDWRAP | + SS_NOPREFIX,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,22,20 + PUSHBUTTON "",IDC_SHOWDETAILS,0,28,60,14,NOT WS_TABSTOP +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(_NSIS_CONFIG_UNINSTDLG) +#if defined(APSTUDIO_INVOKED) +IDD_UNINST$(_NSIS_CONFIG_UNINSTDLG) DIALOGEX 0, 0, 266, 130 +#else +IDD_UNINST DIALOGEX 0, 0, 266, 130 +#endif +STYLE DS_FIXEDSYS | DS_CONTROL | WS_CHILD +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDI_ICON2,IDC_ULICON,0,1,22,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) DIALOGEX 0, 0, 162, 22 +#else +IDD_VERIFY DIALOGEX 0, 0, 162, 22 +#endif +STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CTEXT "",IDC_STR,7,7,148,8 +END +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "IDD_INST$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 273 + TOPMARGIN, 6 + BOTTOMMARGIN, 156 + END + + "IDD_INSTFILES$(NSIS_CONFIG_VISIBLE_SUPPORT)", DIALOG + BEGIN + RIGHTMARGIN, 246 + BOTTOMMARGIN, 125 + END + + "IDD_VERIFY$(_NSIS_CONFIG_VERIFYDIALOG)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 155 + TOPMARGIN, 7 + BOTTOMMARGIN, 15 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""config.h""\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON2 ICON DISCARDABLE "nsis.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +#if defined(APSTUDIO_INVOKED) || defined(NSIS_CONFIG_COMPONENTPAGE) +#if defined(APSTUDIO_INVOKED) +IDB_BITMAP1$(NSIS_CONFIG_COMPONENTPAGE) BITMAP DISCARDABLE "bitmap1.bmp" +#else +IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" +#endif +#endif +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + diff --git a/Source/exehead/state.h b/Source/exehead/state.h index 27730e4..8aa5020 100755 --- a/Source/exehead/state.h +++ b/Source/exehead/state.h @@ -1,42 +1,42 @@ -/*
- * fileform.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "fileform.h"
-
-extern NSIS_STRING g_usrvars[1];
-
-#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]
-#define state_language g_usrvars[24]
-#define state_temp_dir g_usrvars[25]
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
-# define state_plugins_dir g_usrvars[26]
-#endif
-#define state_exe_path g_usrvars[27]
-#define state_exe_file g_usrvars[28]
-#define state_click_next g_usrvars[30]
-
-extern char g_caption[NSIS_MAX_STRLEN*2];
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
-extern HWND g_hwnd;
-extern HANDLE g_hInstance;
-extern HWND insthwnd,insthwndbutton;
-#else
-#define g_hwnd 0
-#define g_hInstance 0
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
+/* + * fileform.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "fileform.h" + +extern NSIS_STRING g_usrvars[1]; + +#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] +#define state_language g_usrvars[24] +#define state_temp_dir g_usrvars[25] +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT +# define state_plugins_dir g_usrvars[26] +#endif +#define state_exe_path g_usrvars[27] +#define state_exe_file g_usrvars[28] +#define state_click_next g_usrvars[30] + +extern char g_caption[NSIS_MAX_STRLEN*2]; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT +extern HWND g_hwnd; +extern HANDLE g_hInstance; +extern HWND insthwnd,insthwndbutton; +#else +#define g_hwnd 0 +#define g_hInstance 0 +#endif//NSIS_CONFIG_VISIBLE_SUPPORT diff --git a/Source/exehead/ui.h b/Source/exehead/ui.h index 9160e3d..ae85609 100755 --- a/Source/exehead/ui.h +++ b/Source/exehead/ui.h @@ -1,60 +1,60 @@ -/*
- * ui.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-
-#ifndef _UI_H_
-#define _UI_H_
-
-extern int *cur_langtable;
-
-extern int NSISCALL ui_doinstall(void);
-void NSISCALL update_status_text(int strtab, const char *text2);
-
-extern int ui_dlg_visible;
-extern HWND m_curwnd;
-
-#ifdef NSIS_CONFIG_LOG
-void NSISCALL build_g_logfile(void);
-#endif
-
-// sent to the last child window to tell it that the install thread is done
-#define WM_NOTIFY_INSTPROC_DONE (WM_USER+0x4)
-
-// sent to every child window to tell it it can start executing NSIS code
-#define WM_NOTIFY_START (WM_USER+0x5)
-
-// sent to the outer window to tell it to go to the next inner window
-#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
-
-// sent to every child window to tell it it is closing soon
-#define WM_NOTIFY_INIGO_MONTOYA (WM_USER+0xb)
-
-// update message used by DirProc and SelProc for space display
-#define WM_IN_UPDATEMSG (WM_USER+0xf)
-
-// custom pages should send this message to let NSIS know they're ready
-#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)
-
-// simulates clicking on the tree
-#define WM_TREEVIEW_KEYHACK (WM_USER+0x13)
-
-// notifies a component selection change (.onMouseOverSection)
-#define WM_NOTIFY_SELCHANGE (WM_USER+0x19)
-
-// Notifies the installation type has changed by the user
-#define WM_NOTIFY_INSTTYPE_CHANGED (WM_USER+0x20)
-
-#endif//_UI_H_
+/* + * ui.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + + +#ifndef _UI_H_ +#define _UI_H_ + +extern int *cur_langtable; + +extern int NSISCALL ui_doinstall(void); +void NSISCALL update_status_text(int strtab, const char *text2); + +extern int ui_dlg_visible; +extern HWND m_curwnd; + +#ifdef NSIS_CONFIG_LOG +void NSISCALL build_g_logfile(void); +#endif + +// sent to the last child window to tell it that the install thread is done +#define WM_NOTIFY_INSTPROC_DONE (WM_USER+0x4) + +// sent to every child window to tell it it can start executing NSIS code +#define WM_NOTIFY_START (WM_USER+0x5) + +// sent to the outer window to tell it to go to the next inner window +#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8) + +// sent to every child window to tell it it is closing soon +#define WM_NOTIFY_INIGO_MONTOYA (WM_USER+0xb) + +// update message used by DirProc and SelProc for space display +#define WM_IN_UPDATEMSG (WM_USER+0xf) + +// custom pages should send this message to let NSIS know they're ready +#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd) + +// simulates clicking on the tree +#define WM_TREEVIEW_KEYHACK (WM_USER+0x13) + +// notifies a component selection change (.onMouseOverSection) +#define WM_NOTIFY_SELCHANGE (WM_USER+0x19) + +// Notifies the installation type has changed by the user +#define WM_NOTIFY_INSTTYPE_CHANGED (WM_USER+0x20) + +#endif//_UI_H_ diff --git a/Source/exehead/util.c b/Source/exehead/util.c index fe1481f..afaacc7 100755 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -1,960 +1,960 @@ -/*
- * util.c
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include <shellapi.h>
-#include "util.h"
-#include "state.h"
-#include "config.h"
-#include "lang.h"
-#include "fileform.h"
-#include "exec.h"
-#include "ui.h"
-#include "resource.h"
-
-#ifdef NSIS_CONFIG_LOG
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
-char g_log_file[1024];
-#endif
-#endif
-
-// *** DO NOT DECLARE MORE VARIABLES INSIDE THIS PRAGMAS ***
-// This will produce a special section called ".ndata" (stands for nsis data)
-// this way makensis during build time, can search for this section by name
-// and change the virtual size of this section
-// which result in extra memory for extra variables without code to do allocation :)
-// nsis then removes the "DISCARDABLE" style from section (for safe)
-#ifdef _MSC_VER
-# pragma bss_seg(NSIS_VARS_SECTION)
-NSIS_STRING g_usrvars[1];
-# pragma bss_seg()
-# pragma comment(linker, "/section:" NSIS_VARS_SECTION ",rwd")
-#else
-# ifdef __GNUC__
-NSIS_STRING g_usrvars[1] __attribute__((section (NSIS_VARS_SECTION)));
-# else
-# error Unknown compiler. You must implement the seperate PE section yourself.
-# endif
-#endif
-
-HANDLE NSISCALL myCreateProcess(char *cmd)
-{
- PROCESS_INFORMATION ProcInfo;
- static STARTUPINFO StartUp;
- StartUp.cb=sizeof(StartUp);
- if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartUp, &ProcInfo))
- return NULL;
- CloseHandle(ProcInfo.hThread);
- return ProcInfo.hProcess;
-}
-
-/*BOOL NSISCALL my_SetWindowText(HWND hWnd, const char *val)
-{
- return SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)val);
-}*/
-
-BOOL NSISCALL my_SetDialogItemText(HWND dlg, UINT idx, const char *val)
-{
- return SetDlgItemText(dlg,idx,val);
-// return my_SetWindowText(GetDlgItem(dlg, idx), val);
-}
-
-int NSISCALL my_GetDialogItemText(UINT idx, char *val)
-{
- extern HWND m_curwnd;
- return GetDlgItemText(m_curwnd, idx, val, NSIS_MAX_STRLEN);
-// return my_GetWindowText(GetDlgItem(m_curwnd, idx), val, NSIS_MAX_STRLEN);
-}
-
-int NSISCALL my_MessageBox(const char *text, UINT type) {
- int _type = type & 0x001FFFFF;
- static MSGBOXPARAMS mbp = {
- sizeof(MSGBOXPARAMS),
- 0,
- 0,
- 0,
- 0,
- 0,
- MAKEINTRESOURCE(IDI_ICON2),
- 0,
- 0,
- 0
- };
-
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- // default for silent installers
- if (g_exec_flags.silent && type >> 21)
- return type >> 21;
-#endif
- // no silent or no default, just show
- if (g_exec_flags.rtl)
- _type ^= MB_RIGHT | MB_RTLREADING;
-
- mbp.hwndOwner = g_hwnd;
- mbp.hInstance = g_hInstance;
- mbp.lpszText = text;
- mbp.lpszCaption = g_caption;
- mbp.dwStyle = _type;
-
- return MessageBoxIndirect(&mbp);
-}
-
-void NSISCALL myDelete(char *buf, int flags)
-{
- static char lbuf[NSIS_MAX_STRLEN];
-
- HANDLE h;
- WIN32_FIND_DATA fd;
- char *fn;
- int valid_dir=is_valid_instpath(buf);
-
- if ((flags & DEL_SIMPLE))
- {
- g_exec_flags.exec_error += !DeleteFile(buf);
- return;
- }
-
-#ifdef NSIS_SUPPORT_RMDIR
- if (!(flags & DEL_DIR) || (valid_dir && (flags & DEL_RECURSE)))
-#endif//NSIS_SUPPORT_RMDIR
- {
- mystrcpy(lbuf,buf);
-#ifdef NSIS_SUPPORT_RMDIR
- if (flags & DEL_DIR)
- mystrcat(lbuf,"\\*.*");
- else
-#endif//NSIS_SUPPORT_RMDIR
- trimslashtoend(buf);
-
- mystrcat(buf,"\\");
-
- fn=buf+mystrlen(buf);
-
- h = FindFirstFile(lbuf,&fd);
- if (h != INVALID_HANDLE_VALUE)
- {
- do
- {
- char *fdfn = fd.cFileName;
- if (*findchar(fdfn, '?') && *fd.cAlternateFileName)
- // name contains unicode, use short name
- fdfn = fd.cAlternateFileName;
-
-#ifdef NSIS_SUPPORT_RMDIR
- if (fdfn[0] == '.' && !fdfn[1]) continue;
- if (fdfn[0] == '.' && fdfn[1] == '.' && !fdfn[2]) continue;
-#endif//NSIS_SUPPORT_RMDIR
- {
- mystrcpy(fn,fdfn);
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
-#ifdef NSIS_SUPPORT_RMDIR
- if ((flags & (DEL_DIR | DEL_RECURSE)) == (DEL_DIR | DEL_RECURSE))
- {
- myDelete(buf,flags);
- }
-#endif//NSIS_SUPPORT_RMDIR
- }
- else
- {
- log_printf2("Delete: DeleteFile(\"%s\")",buf);
- remove_ro_attr(buf);
- if (!DeleteFile(buf))
- {
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- if (flags & DEL_REBOOT)
- {
- log_printf2("Delete: DeleteFile on Reboot(\"%s\")",buf);
- update_status_text(LANG_DELETEONREBOOT,buf);
- MoveFileOnReboot(buf,NULL);
- }
- else
-#endif//NSIS_SUPPORT_MOVEONREBOOT
- {
- log_printf2("Delete: DeleteFile failed(\"%s\")",buf);
- g_exec_flags.exec_error++;
- }
- }
- else
- update_status_text(LANG_DELETEFILE,buf);
- }
- }
- } while (FindNextFile(h,&fd));
- FindClose(h);
- }
-
-#ifdef NSIS_SUPPORT_RMDIR
- if (flags & DEL_DIR)
- fn[-1]=0;
-#endif//NSIS_SUPPORT_RMDIR
- }
-
-#ifdef NSIS_SUPPORT_RMDIR
- if ((flags & DEL_DIR))
- {
- if (!valid_dir)
- {
- log_printf2("RMDir: RemoveDirectory invalid input(\"%s\")",buf);
- g_exec_flags.exec_error++;
- }
- else if (file_exists(buf))
- {
- addtrailingslash(buf);
- log_printf2("RMDir: RemoveDirectory(\"%s\")",buf);
- remove_ro_attr(buf);
- if (!RemoveDirectory(buf))
- {
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- if (flags & DEL_REBOOT)
- {
- log_printf2("RMDir: RemoveDirectory on Reboot(\"%s\")",buf);
- update_status_text(LANG_DELETEONREBOOT,buf);
- MoveFileOnReboot(buf,NULL);
- }
- else
-#endif//NSIS_SUPPORT_MOVEONREBOOT
- {
- log_printf2("RMDir: RemoveDirectory failed(\"%s\")",buf);
- g_exec_flags.exec_error++;
- }
- }
- else
- {
- update_status_text(LANG_REMOVEDIR,buf);
- }
- }
- }
-#endif//NSIS_SUPPORT_RMDIR
-}
-
-char *NSISCALL addtrailingslash(char *str)
-{
- if (lastchar(str)!='\\') mystrcat(str,"\\");
- return str;
-}
-
-/*char NSISCALL lastchar(const char *str)
-{
- return *CharPrev(str,str+mystrlen(str));
-}*/
-
-char * NSISCALL findchar(char *str, char c)
-{
- while (*str && *str != c)
- {
- str = CharNext(str);
- }
- return str;
-}
-
-char * NSISCALL trimslashtoend(char *buf)
-{
- char *p = buf + mystrlen(buf);
- do
- {
- if (*p == '\\')
- break;
- p = CharPrev(buf, p);
- } while (p > buf);
-
- *p = 0;
-
- return p + 1;
-}
-
-int NSISCALL validpathspec(char *ubuf)
-{
- char dl = ubuf[0] | 0x20; // convert alleged drive letter to lower case
- return ((*(WORD*)ubuf==CHAR2_TO_WORD('\\','\\')) || (dl >= 'a' && dl <= 'z' && ubuf[1]==':'));
-}
-
-char * NSISCALL skip_root(char *path)
-{
- char *p = CharNext(path);
- char *p2 = CharNext(p);
-
- if (*path && *(WORD*)p == CHAR2_TO_WORD(':', '\\'))
- {
- return CharNext(p2);
- }
- else if (*(WORD*)path == CHAR2_TO_WORD('\\','\\'))
- {
- // skip host and share name
- int x = 2;
- while (x--)
- {
- p2 = findchar(p2, '\\');
- if (!*p2)
- return NULL;
- p2++; // skip backslash
- }
-
- return p2;
- }
- else
- return NULL;
-}
-
-int NSISCALL is_valid_instpath(char *s)
-{
- static char tmp[NSIS_MAX_STRLEN];
- char *root;
-
- mystrcpy(tmp, s);
-
- root = skip_root(tmp);
-
- if (!root)
- return 0;
-
- // must be called after skip_root or AllowRootDirInstall won't work.
- // validate_filename removes trailing blackslashes and so converts
- // "C:\" to "C:" which is not a valid directory. skip_root returns
- // NULL for "C:" so the above test returns 0.
- // validate_filename is called so directories such as "C:\ " will
- // not pass as a valid non-root directory.
- validate_filename(root);
-
- if ((g_flags & CH_FLAGS_NO_ROOT_DIR) && (!*root || *root == '\\'))
- return 0;
-
- while (mystrlen(tmp) > root - tmp)
- {
- WIN32_FIND_DATA *fd = file_exists(tmp);
- // if the directory bit not set then it's a file, which is not a valid inst dir...
- // GetFileAttributes is not used because it doesn't work with certain files (error 32)
- // as for concerns of the user using * or ?, that's invalid anyway...
- if (fd && !(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- return 0;
- trimslashtoend(tmp);
- }
-
- // if the root drive exists
- addtrailingslash(tmp); // don't check the current directory, check the root directory
- if (GetFileAttributes(tmp) == INVALID_FILE_ATTRIBUTES)
- return 0;
-
- return 1;
-}
-
-char * NSISCALL mystrstri(char *a, const char *b)
-{
- int l = mystrlen(b);
- while (mystrlen(a) >= l)
- {
- char c = a[l];
- a[l] = 0;
- if (!lstrcmpi(a, b))
- {
- a[l] = c;
- return a;
- }
- a[l] = c;
- a = CharNext(a);
- }
- return NULL;
-}
-
-void NSISCALL 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++;
- }
-}
-
-void NSISCALL remove_ro_attr(char *file)
-{
- int attr = GetFileAttributes(file);
- if (attr != INVALID_FILE_ATTRIBUTES)
- SetFileAttributes(file,attr&(~FILE_ATTRIBUTE_READONLY));
-}
-
-HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd)
-{
- int attr = GetFileAttributes(fn);
- return CreateFile(
- fn,
- da,
- FILE_SHARE_READ,
- NULL,
- cd,
- attr == INVALID_FILE_ATTRIBUTES ? 0 : attr,
- NULL
- );
-}
-
-char * NSISCALL my_GetTempFileName(char *buf, const char *dir)
-{
- int n = 100;
- while (n--)
- {
- char prefix[4];
- *(LPDWORD)prefix = CHAR4_TO_DWORD('n', 's', 'a', 0);
- prefix[2] += (char)(GetTickCount() % 26);
- if (GetTempFileName(dir, prefix, 0, buf))
- return buf;
- }
- *buf = 0;
- return 0;
-}
-
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
-void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew)
-{
- BOOL fOk = 0;
- typedef BOOL (WINAPI *mfea_t)(LPCSTR lpExistingFileName,LPCSTR lpNewFileName,DWORD dwFlags);
- mfea_t mfea;
- mfea=(mfea_t) myGetProcAddress(MGA_MoveFileExA);
- if (mfea)
- {
- fOk=mfea(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING);
- }
-
- if (!fOk)
- {
- static char szRenameLine[1024];
- static char wininit[1024];
- static char tmpbuf[1024];
- int cchRenameLine;
- static const char szRenameSec[] = "[Rename]\r\n";
- HANDLE hfile;
- DWORD dwFileSize;
- DWORD dwBytes;
- DWORD dwRenameLinePos;
- char *pszWinInit;
-
- int spn;
-
- *(DWORD*)tmpbuf = CHAR4_TO_DWORD('N', 'U', 'L', 0);
-
- if (pszNew) {
- // create the file if it's not already there to prevent GetShortPathName from failing
- CloseHandle(myOpenFile(pszNew,0,CREATE_NEW));
- spn = GetShortPathName(pszNew,tmpbuf,1024);
- if (!spn || spn > 1024)
- return;
- }
- // wininit is used as a temporary here
- spn = GetShortPathName(pszExisting,wininit,1024);
- if (!spn || spn > 1024)
- return;
- cchRenameLine = wsprintf(szRenameLine,"%s=%s\r\n",tmpbuf,wininit);
-
- GetNSISString(wininit, g_header->str_wininit);
- hfile = myOpenFile(wininit, GENERIC_READ | GENERIC_WRITE, OPEN_ALWAYS);
-
- if (hfile != INVALID_HANDLE_VALUE)
- {
- dwFileSize = GetFileSize(hfile, NULL);
- pszWinInit = GlobalAlloc(GPTR, dwFileSize + cchRenameLine + 10);
-
- if (pszWinInit != NULL)
- {
- if (ReadFile(hfile, pszWinInit, dwFileSize, &dwBytes, NULL) && dwFileSize == dwBytes)
- {
- LPSTR pszRenameSecInFile = mystrstri(pszWinInit, szRenameSec);
- if (pszRenameSecInFile == NULL)
- {
- mystrcpy(pszWinInit+dwFileSize, szRenameSec);
- dwFileSize += 10;
- dwRenameLinePos = dwFileSize;
- }
- else
- {
- char *pszFirstRenameLine = pszRenameSecInFile+10;
- char *pszNextSec = mystrstri(pszFirstRenameLine,"\n[");
- if (pszNextSec)
- {
- char *p = ++pszNextSec;
- while (p < pszWinInit + dwFileSize) {
- p[cchRenameLine] = *p;
- p++;
- }
-
- dwRenameLinePos = pszNextSec - pszWinInit;
- }
- // rename section is last, stick item at end of file
- else dwRenameLinePos = dwFileSize;
- }
-
- mini_memcpy(&pszWinInit[dwRenameLinePos], szRenameLine, cchRenameLine);
- dwFileSize += cchRenameLine;
-
- SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
- WriteFile(hfile, pszWinInit, dwFileSize, &dwBytes, NULL);
-
- GlobalFree(pszWinInit);
- }
- }
-
- CloseHandle(hfile);
- }
- }
-
-#ifdef NSIS_SUPPORT_REBOOT
- g_exec_flags.exec_reboot++;
-#endif
-}
-#endif
-
-void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64)
-{
- HKEY hKey;
- *out=0;
- if (RegOpenKeyEx(root,sub,0,KEY_READ|(x64?KEY_WOW64_64KEY:0),&hKey) == ERROR_SUCCESS)
- {
- DWORD l = NSIS_MAX_STRLEN;
- DWORD t;
- if (RegQueryValueEx(hKey,name,NULL,&t,out,&l ) != ERROR_SUCCESS || (t != REG_SZ && t != REG_EXPAND_SZ)) *out=0;
- out[NSIS_MAX_STRLEN-1]=0;
- RegCloseKey(hKey);
- }
-}
-
-void NSISCALL myitoa(char *s, int d)
-{
- static const char c[] = "%d";
- wsprintf(s,c,d);
-}
-
-int NSISCALL myatoi(char *s)
-{
- unsigned int v=0;
- int sign=1; // sign of positive
- char m=10; // base of 10
- char t='9'; // cap top of numbers at 9
-
- if (*s == '-')
- {
- s++; //skip over -
- sign=-1; // sign flip
- }
-
- if (*s == '0')
- {
- s++; // skip over 0
- if (s[0] >= '0' && s[0] <= '7')
- {
- m=8; // base of 8
- t='7'; // cap top at 7
- }
- if ((s[0] & ~0x20) == 'X')
- {
- m=16; // base of 16
- s++; // advance over 'x'
- }
- }
-
- for (;;)
- {
- int c=*s++;
- if (c >= '0' && c <= t) c-='0';
- else if (m==16 && (c & ~0x20) >= 'A' && (c & ~0x20) <= 'F') c = (c & 7) + 9;
- else break;
- v*=m;
- v+=c;
- }
- return ((int)v)*sign;
-}
-
-// Straight copies of selected shell functions. Calling local functions
-// requires less code than DLL functions. For the savings to outweigh the cost
-// of a new function there should be about a couple of dozen or so calls.
-char * NSISCALL mystrcpy(char *out, const char *in)
-{
- return lstrcpyn(out, in, NSIS_MAX_STRLEN);
-}
-
-int NSISCALL mystrlen(const char *in)
-{
- return lstrlen(in);
-}
-
-char * NSISCALL mystrcat(char *out, const char *concat)
-{
- return lstrcat(out, concat);
-}
-
-char ps_tmpbuf[NSIS_MAX_STRLEN*2];
-
-const char SYSREGKEY[] = "Software\\Microsoft\\Windows\\CurrentVersion";
-const char QUICKLAUNCH[] = "\\Microsoft\\Internet Explorer\\Quick Launch";
-
-typedef HRESULT (__stdcall * PFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR);
-extern void *g_SHGetFolderPath;
-
-// Based on Dave Laundon's simplified process_string
-char * NSISCALL GetNSISString(char *outbuf, int strtab)
-{
- char *in = (char*)GetNSISStringNP(GetNSISTab(strtab));
- char *out = ps_tmpbuf;
- if ((unsigned int) (outbuf - ps_tmpbuf) < sizeof(ps_tmpbuf))
- {
- out = outbuf;
- outbuf = 0;
- }
- while (*in && out - ps_tmpbuf < NSIS_MAX_STRLEN)
- {
- unsigned char nVarIdx = (unsigned char)*in++;
- int nData;
- int fldrs[4];
- if (nVarIdx > NS_CODES_START)
- {
- nData = ((in[1] & 0x7F) << 7) | (in[0] & 0x7F);
- fldrs[0] = in[0]; // current user
- fldrs[1] = in[0] | CSIDL_FLAG_CREATE;
- fldrs[2] = in[1]; // all users
- fldrs[3] = in[1] | CSIDL_FLAG_CREATE;
- in += 2;
-
- if (nVarIdx == NS_SHELL_CODE)
- {
- LPITEMIDLIST idl;
-
- int x = 2;
- DWORD ver = GetVersion();
-
- /*
-
- SHGetFolderPath as provided by shfolder.dll is used to get special folders
- unless the installer is running on Windows 95/98. For 95/98 shfolder.dll is
- only used for the Application Data and Documents folder (if the DLL exists).
- Oherwise, the old SHGetSpecialFolderLocation API is called.
-
- There reason for not using shfolder.dll for all folders on 95/98 is that
- some unsupported folders (such as the Start Menu folder for all users) are
- simulated instead of returning an error so whe can fall back on the folder
- for the current user.
-
- SHGetFolderPath in shell32.dll could be called directly for Windows versions
- later than 95/98 but there is no need to do so, because shfolder.dll is still
- provided and calls shell32.dll.
-
- */
-
- BOOL use_shfolder =
- // Use shfolder if not on 95/98
- !((ver & 0x80000000) && (LOWORD(ver) != 0x5A04)) ||
-
- // Unless the Application Data or Documents folder is requested
- (
- (fldrs[2] == CSIDL_COMMON_APPDATA) ||
- (fldrs[2] == CSIDL_COMMON_DOCUMENTS)
- );
-
- /* Carry on... shfolder stuff is over. */
-
- if (g_exec_flags.all_user_var)
- {
- x = 4;
- }
-
- if (fldrs[0] & 0x80)
- {
- myRegGetStr(HKEY_LOCAL_MACHINE, SYSREGKEY, GetNSISStringNP(fldrs[0] & 0x3F), out, fldrs[0] & 0x40);
- if (!*out)
- GetNSISString(out, fldrs[2]);
- x = 0;
- }
- else if (fldrs[0] == CSIDL_SYSTEM)
- {
- GetSystemDirectory(out, NSIS_MAX_STRLEN);
- x = 0;
- }
- else if (fldrs[0] == CSIDL_WINDOWS)
- {
- GetWindowsDirectory(out, NSIS_MAX_STRLEN);
- x = 0;
- }
-
- while (x--)
- {
- if (g_SHGetFolderPath && use_shfolder)
- {
- PFNSHGETFOLDERPATHA SHGetFolderPathFunc = (PFNSHGETFOLDERPATHA) g_SHGetFolderPath;
- if (!SHGetFolderPathFunc(g_hwnd, fldrs[x], NULL, SHGFP_TYPE_CURRENT, out))
- {
- break;
- }
- }
-
- if (!SHGetSpecialFolderLocation(g_hwnd, fldrs[x], &idl))
- {
- BOOL res = SHGetPathFromIDList(idl, out);
- CoTaskMemFree(idl);
- if (res) break;
- }
-
- *out=0;
- }
-
- if (*out)
- {
- // all users' version is CSIDL_APPDATA only for $QUICKLAUNCH
- // for normal $APPDATA, it'd be CSIDL_APPDATA_COMMON
- if (fldrs[2] == CSIDL_APPDATA)
- {
- mystrcat(out, QUICKLAUNCH);
- }
- }
- validate_filename(out);
- }
- else if (nVarIdx == NS_VAR_CODE)
- {
- if (nData == 29) // $HWNDPARENT
- myitoa(out, (unsigned int) g_hwnd);
- else
- mystrcpy(out, g_usrvars[nData]);
- // validate the directory name
- if ((unsigned int)(nData - 21) < 7) {
- // validate paths for $INSTDIR, $OUTDIR, $EXEDIR, $LANGUAGE, $TEMP, $PLUGINSDIR and $EXEPATH
- // $LANGUAGE is just a number anyway...
- validate_filename(out);
- }
- } // == VAR_CODES_START
- else if (nVarIdx == NS_LANG_CODE)
- {
- GetNSISString(out, -nData-1);
- }
- out += mystrlen(out);
- }
- else if (nVarIdx == NS_SKIP_CODE)
- {
- *out++ = *in++;
- }
- else // Normal char
- {
- *out++ = nVarIdx;
- }
- } // while
- *out = 0;
- if (outbuf)
- return mystrcpy(outbuf, ps_tmpbuf);
- return ps_tmpbuf;
-}
-
-void NSISCALL validate_filename(char *in) {
- char *nono = "*?|<>/\":";
- char *out;
- char *out_save;
-
- // ignoring spaces is wrong, " C:\blah" is invalid
- //while (*in == ' ') in = CharNext(in);
-
- if (in[0] == '\\' && in[1] == '\\' && in[2] == '?' && in[3] == '\\')
- {
- // at least four bytes
- in += 4;
- }
- if (*in)
- {
- // at least two bytes
- if (validpathspec(in)) in += 2;
- }
- out = out_save = in;
- while (*in)
- {
- if ((unsigned char)*in > 31 && !*findchar(nono, *in))
- {
- mini_memcpy(out, in, CharNext(in) - in);
- out = CharNext(out);
- }
- in = CharNext(in);
- }
- *out = 0;
- do
- {
- out = CharPrev(out_save, out);
- if (*out == ' ' || *out == '\\')
- *out = 0;
- else
- break;
- } while (out_save < out);
-}
-
-#ifdef NSIS_CONFIG_LOG
-int log_dolog;
-char log_text[2048]; // 1024 for each wsprintf
-
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
-void NSISCALL log_write(int close)
-{
- 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 = myOpenFile(g_log_file,GENERIC_WRITE,OPEN_ALWAYS);
- if (fp!=INVALID_HANDLE_VALUE)
- SetFilePointer(fp,0,NULL,FILE_END);
- }
- if (fp!=INVALID_HANDLE_VALUE)
- {
- DWORD d;
- mystrcat(log_text,"\r\n");
- WriteFile(fp,log_text,mystrlen(log_text),&d,NULL);
- }
- }
-}
-#endif//!NSIS_CONFIG_LOG_ODS && !NSIS_CONFIG_LOG_STDOUT
-
-const char * _RegKeyHandleToName(HKEY hKey)
-{
- if (hKey == HKEY_CLASSES_ROOT)
- return "HKEY_CLASSES_ROOT";
- else if (hKey == HKEY_CURRENT_USER)
- return "HKEY_CURRENT_USER";
- else if (hKey == HKEY_LOCAL_MACHINE)
- return "HKEY_LOCAL_MACHINE";
- else if (hKey == HKEY_USERS)
- return "HKEY_USERS";
- else if (hKey == HKEY_PERFORMANCE_DATA)
- return "HKEY_PERFORMANCE_DATA";
- else if (hKey == HKEY_CURRENT_CONFIG)
- return "HKEY_CURRENT_CONFIG";
- else if (hKey == HKEY_DYN_DATA)
- return "HKEY_DYN_DATA";
- else
- return "invalid registry key";
-}
-
-void _LogData2Hex(char *buf, size_t buflen, unsigned char *data, size_t datalen)
-{
- char *p = buf;
-
- size_t i;
-
- int dots = 0;
- size_t bufbytes = buflen / 3; // 2 hex digits, one space/null
-
- if (datalen > bufbytes)
- {
- bufbytes--;
- dots = 1;
- }
- else
- bufbytes = datalen;
-
- for (i = 0; i < bufbytes; i++)
- {
- wsprintf(p, "%02x%c", data[i], (i == bufbytes - 1) ? '\0' : ' ');
- p += 3;
- }
-
- if (dots)
- mystrcat(buf, "...");
-}
-
-#ifdef NSIS_CONFIG_LOG_TIMESTAMP
-void log_timestamp(char *buf)
-{
- SYSTEMTIME st;
- GetLocalTime(&st);
- wsprintf(buf,"[%04hu/%02hu/%02hu %02hu:%02hu:%02hu] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
-}
-#else
-# define log_timestamp(x)
-#endif//NSIS_CONFIG_LOG_TIMESTAMP
-
-void log_printf(char *format, ...)
-{
- va_list val;
- va_start(val,format);
-
- log_text[0] = '\0';
- log_timestamp(log_text);
- wvsprintf(log_text+mystrlen(log_text),format,val);
-
- va_end(val);
-#ifdef NSIS_CONFIG_LOG_ODS
- if (log_dolog)
- OutputDebugString(log_text);
-#endif
-#ifdef NSIS_CONFIG_LOG_STDOUT
- if (log_dolog && GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE)
- {
- DWORD dwBytes;
- WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), log_text, lstrlen(log_text), &dwBytes, NULL);
- WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\n", 1, &dwBytes, NULL);
- }
-#endif
-#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT)
- log_write(0);
-#endif
-}
-#endif//NSIS_CONFIG_LOG
-
-WIN32_FIND_DATA * NSISCALL file_exists(char *buf)
-{
- HANDLE h;
- static WIN32_FIND_DATA fd;
- h = FindFirstFile(buf,&fd);
- if (h != INVALID_HANDLE_VALUE)
- {
- FindClose(h);
- return &fd;
- }
- return NULL;
-}
-
-struct MGA_FUNC
-{
- const char *dll;
- const char *func;
-};
-
-struct MGA_FUNC MGA_FUNCS[] = {
- {"KERNEL32", "GetDiskFreeSpaceExA"},
- {"KERNEL32", "MoveFileExA"},
- {"ADVAPI32", "RegDeleteKeyExA"},
- {"ADVAPI32", "OpenProcessToken"},
- {"ADVAPI32", "LookupPrivilegeValueA"},
- {"ADVAPI32", "AdjustTokenPrivileges"},
- {"KERNEL32", "GetUserDefaultUILanguage"},
- {"SHLWAPI", "SHAutoComplete"},
- {"SHFOLDER", "SHGetFolderPathA"}
-};
-
-void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func)
-{
- const char *dll = MGA_FUNCS[func].dll;
- HMODULE hModule = GetModuleHandle(dll);
- if (!hModule)
- hModule = LoadLibrary(dll);
- if (!hModule)
- return NULL;
-
- return GetProcAddress(hModule, MGA_FUNCS[func].func);
-}
-
-void NSISCALL MessageLoop(UINT uCheckedMsg)
-{
- MSG msg;
- while (PeekMessage(&msg, NULL, uCheckedMsg, uCheckedMsg, PM_REMOVE))
- DispatchMessage(&msg);
-}
+/* + * util.c + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include <shellapi.h> +#include "util.h" +#include "state.h" +#include "config.h" +#include "lang.h" +#include "fileform.h" +#include "exec.h" +#include "ui.h" +#include "resource.h" + +#ifdef NSIS_CONFIG_LOG +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) +char g_log_file[1024]; +#endif +#endif + +// *** DO NOT DECLARE MORE VARIABLES INSIDE THIS PRAGMAS *** +// This will produce a special section called ".ndata" (stands for nsis data) +// this way makensis during build time, can search for this section by name +// and change the virtual size of this section +// which result in extra memory for extra variables without code to do allocation :) +// nsis then removes the "DISCARDABLE" style from section (for safe) +#ifdef _MSC_VER +# pragma bss_seg(NSIS_VARS_SECTION) +NSIS_STRING g_usrvars[1]; +# pragma bss_seg() +# pragma comment(linker, "/section:" NSIS_VARS_SECTION ",rwd") +#else +# ifdef __GNUC__ +NSIS_STRING g_usrvars[1] __attribute__((section (NSIS_VARS_SECTION))); +# else +# error Unknown compiler. You must implement the seperate PE section yourself. +# endif +#endif + +HANDLE NSISCALL myCreateProcess(char *cmd) +{ + PROCESS_INFORMATION ProcInfo; + static STARTUPINFO StartUp; + StartUp.cb=sizeof(StartUp); + if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartUp, &ProcInfo)) + return NULL; + CloseHandle(ProcInfo.hThread); + return ProcInfo.hProcess; +} + +/*BOOL NSISCALL my_SetWindowText(HWND hWnd, const char *val) +{ + return SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)val); +}*/ + +BOOL NSISCALL my_SetDialogItemText(HWND dlg, UINT idx, const char *val) +{ + return SetDlgItemText(dlg,idx,val); +// return my_SetWindowText(GetDlgItem(dlg, idx), val); +} + +int NSISCALL my_GetDialogItemText(UINT idx, char *val) +{ + extern HWND m_curwnd; + return GetDlgItemText(m_curwnd, idx, val, NSIS_MAX_STRLEN); +// return my_GetWindowText(GetDlgItem(m_curwnd, idx), val, NSIS_MAX_STRLEN); +} + +int NSISCALL my_MessageBox(const char *text, UINT type) { + int _type = type & 0x001FFFFF; + static MSGBOXPARAMS mbp = { + sizeof(MSGBOXPARAMS), + 0, + 0, + 0, + 0, + 0, + MAKEINTRESOURCE(IDI_ICON2), + 0, + 0, + 0 + }; + +#ifdef NSIS_CONFIG_SILENT_SUPPORT + // default for silent installers + if (g_exec_flags.silent && type >> 21) + return type >> 21; +#endif + // no silent or no default, just show + if (g_exec_flags.rtl) + _type ^= MB_RIGHT | MB_RTLREADING; + + mbp.hwndOwner = g_hwnd; + mbp.hInstance = g_hInstance; + mbp.lpszText = text; + mbp.lpszCaption = g_caption; + mbp.dwStyle = _type; + + return MessageBoxIndirect(&mbp); +} + +void NSISCALL myDelete(char *buf, int flags) +{ + static char lbuf[NSIS_MAX_STRLEN]; + + HANDLE h; + WIN32_FIND_DATA fd; + char *fn; + int valid_dir=is_valid_instpath(buf); + + if ((flags & DEL_SIMPLE)) + { + g_exec_flags.exec_error += !DeleteFile(buf); + return; + } + +#ifdef NSIS_SUPPORT_RMDIR + if (!(flags & DEL_DIR) || (valid_dir && (flags & DEL_RECURSE))) +#endif//NSIS_SUPPORT_RMDIR + { + mystrcpy(lbuf,buf); +#ifdef NSIS_SUPPORT_RMDIR + if (flags & DEL_DIR) + mystrcat(lbuf,"\\*.*"); + else +#endif//NSIS_SUPPORT_RMDIR + trimslashtoend(buf); + + mystrcat(buf,"\\"); + + fn=buf+mystrlen(buf); + + h = FindFirstFile(lbuf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + do + { + char *fdfn = fd.cFileName; + if (*findchar(fdfn, '?') && *fd.cAlternateFileName) + // name contains unicode, use short name + fdfn = fd.cAlternateFileName; + +#ifdef NSIS_SUPPORT_RMDIR + if (fdfn[0] == '.' && !fdfn[1]) continue; + if (fdfn[0] == '.' && fdfn[1] == '.' && !fdfn[2]) continue; +#endif//NSIS_SUPPORT_RMDIR + { + mystrcpy(fn,fdfn); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { +#ifdef NSIS_SUPPORT_RMDIR + if ((flags & (DEL_DIR | DEL_RECURSE)) == (DEL_DIR | DEL_RECURSE)) + { + myDelete(buf,flags); + } +#endif//NSIS_SUPPORT_RMDIR + } + else + { + log_printf2("Delete: DeleteFile(\"%s\")",buf); + remove_ro_attr(buf); + if (!DeleteFile(buf)) + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (flags & DEL_REBOOT) + { + log_printf2("Delete: DeleteFile on Reboot(\"%s\")",buf); + update_status_text(LANG_DELETEONREBOOT,buf); + MoveFileOnReboot(buf,NULL); + } + else +#endif//NSIS_SUPPORT_MOVEONREBOOT + { + log_printf2("Delete: DeleteFile failed(\"%s\")",buf); + g_exec_flags.exec_error++; + } + } + else + update_status_text(LANG_DELETEFILE,buf); + } + } + } while (FindNextFile(h,&fd)); + FindClose(h); + } + +#ifdef NSIS_SUPPORT_RMDIR + if (flags & DEL_DIR) + fn[-1]=0; +#endif//NSIS_SUPPORT_RMDIR + } + +#ifdef NSIS_SUPPORT_RMDIR + if ((flags & DEL_DIR)) + { + if (!valid_dir) + { + log_printf2("RMDir: RemoveDirectory invalid input(\"%s\")",buf); + g_exec_flags.exec_error++; + } + else if (file_exists(buf)) + { + addtrailingslash(buf); + log_printf2("RMDir: RemoveDirectory(\"%s\")",buf); + remove_ro_attr(buf); + if (!RemoveDirectory(buf)) + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (flags & DEL_REBOOT) + { + log_printf2("RMDir: RemoveDirectory on Reboot(\"%s\")",buf); + update_status_text(LANG_DELETEONREBOOT,buf); + MoveFileOnReboot(buf,NULL); + } + else +#endif//NSIS_SUPPORT_MOVEONREBOOT + { + log_printf2("RMDir: RemoveDirectory failed(\"%s\")",buf); + g_exec_flags.exec_error++; + } + } + else + { + update_status_text(LANG_REMOVEDIR,buf); + } + } + } +#endif//NSIS_SUPPORT_RMDIR +} + +char *NSISCALL addtrailingslash(char *str) +{ + if (lastchar(str)!='\\') mystrcat(str,"\\"); + return str; +} + +/*char NSISCALL lastchar(const char *str) +{ + return *CharPrev(str,str+mystrlen(str)); +}*/ + +char * NSISCALL findchar(char *str, char c) +{ + while (*str && *str != c) + { + str = CharNext(str); + } + return str; +} + +char * NSISCALL trimslashtoend(char *buf) +{ + char *p = buf + mystrlen(buf); + do + { + if (*p == '\\') + break; + p = CharPrev(buf, p); + } while (p > buf); + + *p = 0; + + return p + 1; +} + +int NSISCALL validpathspec(char *ubuf) +{ + char dl = ubuf[0] | 0x20; // convert alleged drive letter to lower case + return ((*(WORD*)ubuf==CHAR2_TO_WORD('\\','\\')) || (dl >= 'a' && dl <= 'z' && ubuf[1]==':')); +} + +char * NSISCALL skip_root(char *path) +{ + char *p = CharNext(path); + char *p2 = CharNext(p); + + if (*path && *(WORD*)p == CHAR2_TO_WORD(':', '\\')) + { + return CharNext(p2); + } + else if (*(WORD*)path == CHAR2_TO_WORD('\\','\\')) + { + // skip host and share name + int x = 2; + while (x--) + { + p2 = findchar(p2, '\\'); + if (!*p2) + return NULL; + p2++; // skip backslash + } + + return p2; + } + else + return NULL; +} + +int NSISCALL is_valid_instpath(char *s) +{ + static char tmp[NSIS_MAX_STRLEN]; + char *root; + + mystrcpy(tmp, s); + + root = skip_root(tmp); + + if (!root) + return 0; + + // must be called after skip_root or AllowRootDirInstall won't work. + // validate_filename removes trailing blackslashes and so converts + // "C:\" to "C:" which is not a valid directory. skip_root returns + // NULL for "C:" so the above test returns 0. + // validate_filename is called so directories such as "C:\ " will + // not pass as a valid non-root directory. + validate_filename(root); + + if ((g_flags & CH_FLAGS_NO_ROOT_DIR) && (!*root || *root == '\\')) + return 0; + + while (mystrlen(tmp) > root - tmp) + { + WIN32_FIND_DATA *fd = file_exists(tmp); + // if the directory bit not set then it's a file, which is not a valid inst dir... + // GetFileAttributes is not used because it doesn't work with certain files (error 32) + // as for concerns of the user using * or ?, that's invalid anyway... + if (fd && !(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + return 0; + trimslashtoend(tmp); + } + + // if the root drive exists + addtrailingslash(tmp); // don't check the current directory, check the root directory + if (GetFileAttributes(tmp) == INVALID_FILE_ATTRIBUTES) + return 0; + + return 1; +} + +char * NSISCALL mystrstri(char *a, const char *b) +{ + int l = mystrlen(b); + while (mystrlen(a) >= l) + { + char c = a[l]; + a[l] = 0; + if (!lstrcmpi(a, b)) + { + a[l] = c; + return a; + } + a[l] = c; + a = CharNext(a); + } + return NULL; +} + +void NSISCALL 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++; + } +} + +void NSISCALL remove_ro_attr(char *file) +{ + int attr = GetFileAttributes(file); + if (attr != INVALID_FILE_ATTRIBUTES) + SetFileAttributes(file,attr&(~FILE_ATTRIBUTE_READONLY)); +} + +HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd) +{ + int attr = GetFileAttributes(fn); + return CreateFile( + fn, + da, + FILE_SHARE_READ, + NULL, + cd, + attr == INVALID_FILE_ATTRIBUTES ? 0 : attr, + NULL + ); +} + +char * NSISCALL my_GetTempFileName(char *buf, const char *dir) +{ + int n = 100; + while (n--) + { + char prefix[4]; + *(LPDWORD)prefix = CHAR4_TO_DWORD('n', 's', 'a', 0); + prefix[2] += (char)(GetTickCount() % 26); + if (GetTempFileName(dir, prefix, 0, buf)) + return buf; + } + *buf = 0; + return 0; +} + +#ifdef NSIS_SUPPORT_MOVEONREBOOT +void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew) +{ + BOOL fOk = 0; + typedef BOOL (WINAPI *mfea_t)(LPCSTR lpExistingFileName,LPCSTR lpNewFileName,DWORD dwFlags); + mfea_t mfea; + mfea=(mfea_t) myGetProcAddress(MGA_MoveFileExA); + if (mfea) + { + fOk=mfea(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING); + } + + if (!fOk) + { + static char szRenameLine[1024]; + static char wininit[1024]; + static char tmpbuf[1024]; + int cchRenameLine; + static const char szRenameSec[] = "[Rename]\r\n"; + HANDLE hfile; + DWORD dwFileSize; + DWORD dwBytes; + DWORD dwRenameLinePos; + char *pszWinInit; + + int spn; + + *(DWORD*)tmpbuf = CHAR4_TO_DWORD('N', 'U', 'L', 0); + + if (pszNew) { + // create the file if it's not already there to prevent GetShortPathName from failing + CloseHandle(myOpenFile(pszNew,0,CREATE_NEW)); + spn = GetShortPathName(pszNew,tmpbuf,1024); + if (!spn || spn > 1024) + return; + } + // wininit is used as a temporary here + spn = GetShortPathName(pszExisting,wininit,1024); + if (!spn || spn > 1024) + return; + cchRenameLine = wsprintf(szRenameLine,"%s=%s\r\n",tmpbuf,wininit); + + GetNSISString(wininit, g_header->str_wininit); + hfile = myOpenFile(wininit, GENERIC_READ | GENERIC_WRITE, OPEN_ALWAYS); + + if (hfile != INVALID_HANDLE_VALUE) + { + dwFileSize = GetFileSize(hfile, NULL); + pszWinInit = GlobalAlloc(GPTR, dwFileSize + cchRenameLine + 10); + + if (pszWinInit != NULL) + { + if (ReadFile(hfile, pszWinInit, dwFileSize, &dwBytes, NULL) && dwFileSize == dwBytes) + { + LPSTR pszRenameSecInFile = mystrstri(pszWinInit, szRenameSec); + if (pszRenameSecInFile == NULL) + { + mystrcpy(pszWinInit+dwFileSize, szRenameSec); + dwFileSize += 10; + dwRenameLinePos = dwFileSize; + } + else + { + char *pszFirstRenameLine = pszRenameSecInFile+10; + char *pszNextSec = mystrstri(pszFirstRenameLine,"\n["); + if (pszNextSec) + { + char *p = ++pszNextSec; + while (p < pszWinInit + dwFileSize) { + p[cchRenameLine] = *p; + p++; + } + + dwRenameLinePos = pszNextSec - pszWinInit; + } + // rename section is last, stick item at end of file + else dwRenameLinePos = dwFileSize; + } + + mini_memcpy(&pszWinInit[dwRenameLinePos], szRenameLine, cchRenameLine); + dwFileSize += cchRenameLine; + + SetFilePointer(hfile, 0, NULL, FILE_BEGIN); + WriteFile(hfile, pszWinInit, dwFileSize, &dwBytes, NULL); + + GlobalFree(pszWinInit); + } + } + + CloseHandle(hfile); + } + } + +#ifdef NSIS_SUPPORT_REBOOT + g_exec_flags.exec_reboot++; +#endif +} +#endif + +void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64) +{ + HKEY hKey; + *out=0; + if (RegOpenKeyEx(root,sub,0,KEY_READ|(x64?KEY_WOW64_64KEY:0),&hKey) == ERROR_SUCCESS) + { + DWORD l = NSIS_MAX_STRLEN; + DWORD t; + if (RegQueryValueEx(hKey,name,NULL,&t,out,&l ) != ERROR_SUCCESS || (t != REG_SZ && t != REG_EXPAND_SZ)) *out=0; + out[NSIS_MAX_STRLEN-1]=0; + RegCloseKey(hKey); + } +} + +void NSISCALL myitoa(char *s, int d) +{ + static const char c[] = "%d"; + wsprintf(s,c,d); +} + +int NSISCALL myatoi(char *s) +{ + unsigned int v=0; + int sign=1; // sign of positive + char m=10; // base of 10 + char t='9'; // cap top of numbers at 9 + + if (*s == '-') + { + s++; //skip over - + sign=-1; // sign flip + } + + if (*s == '0') + { + s++; // skip over 0 + if (s[0] >= '0' && s[0] <= '7') + { + m=8; // base of 8 + t='7'; // cap top at 7 + } + if ((s[0] & ~0x20) == 'X') + { + m=16; // base of 16 + s++; // advance over 'x' + } + } + + for (;;) + { + int c=*s++; + if (c >= '0' && c <= t) c-='0'; + else if (m==16 && (c & ~0x20) >= 'A' && (c & ~0x20) <= 'F') c = (c & 7) + 9; + else break; + v*=m; + v+=c; + } + return ((int)v)*sign; +} + +// Straight copies of selected shell functions. Calling local functions +// requires less code than DLL functions. For the savings to outweigh the cost +// of a new function there should be about a couple of dozen or so calls. +char * NSISCALL mystrcpy(char *out, const char *in) +{ + return lstrcpyn(out, in, NSIS_MAX_STRLEN); +} + +int NSISCALL mystrlen(const char *in) +{ + return lstrlen(in); +} + +char * NSISCALL mystrcat(char *out, const char *concat) +{ + return lstrcat(out, concat); +} + +char ps_tmpbuf[NSIS_MAX_STRLEN*2]; + +const char SYSREGKEY[] = "Software\\Microsoft\\Windows\\CurrentVersion"; +const char QUICKLAUNCH[] = "\\Microsoft\\Internet Explorer\\Quick Launch"; + +typedef HRESULT (__stdcall * PFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR); +extern void *g_SHGetFolderPath; + +// Based on Dave Laundon's simplified process_string +char * NSISCALL GetNSISString(char *outbuf, int strtab) +{ + char *in = (char*)GetNSISStringNP(GetNSISTab(strtab)); + char *out = ps_tmpbuf; + if ((unsigned int) (outbuf - ps_tmpbuf) < sizeof(ps_tmpbuf)) + { + out = outbuf; + outbuf = 0; + } + while (*in && out - ps_tmpbuf < NSIS_MAX_STRLEN) + { + unsigned char nVarIdx = (unsigned char)*in++; + int nData; + int fldrs[4]; + if (nVarIdx > NS_CODES_START) + { + nData = ((in[1] & 0x7F) << 7) | (in[0] & 0x7F); + fldrs[0] = in[0]; // current user + fldrs[1] = in[0] | CSIDL_FLAG_CREATE; + fldrs[2] = in[1]; // all users + fldrs[3] = in[1] | CSIDL_FLAG_CREATE; + in += 2; + + if (nVarIdx == NS_SHELL_CODE) + { + LPITEMIDLIST idl; + + int x = 2; + DWORD ver = GetVersion(); + + /* + + SHGetFolderPath as provided by shfolder.dll is used to get special folders + unless the installer is running on Windows 95/98. For 95/98 shfolder.dll is + only used for the Application Data and Documents folder (if the DLL exists). + Oherwise, the old SHGetSpecialFolderLocation API is called. + + There reason for not using shfolder.dll for all folders on 95/98 is that + some unsupported folders (such as the Start Menu folder for all users) are + simulated instead of returning an error so whe can fall back on the folder + for the current user. + + SHGetFolderPath in shell32.dll could be called directly for Windows versions + later than 95/98 but there is no need to do so, because shfolder.dll is still + provided and calls shell32.dll. + + */ + + BOOL use_shfolder = + // Use shfolder if not on 95/98 + !((ver & 0x80000000) && (LOWORD(ver) != 0x5A04)) || + + // Unless the Application Data or Documents folder is requested + ( + (fldrs[2] == CSIDL_COMMON_APPDATA) || + (fldrs[2] == CSIDL_COMMON_DOCUMENTS) + ); + + /* Carry on... shfolder stuff is over. */ + + if (g_exec_flags.all_user_var) + { + x = 4; + } + + if (fldrs[0] & 0x80) + { + myRegGetStr(HKEY_LOCAL_MACHINE, SYSREGKEY, GetNSISStringNP(fldrs[0] & 0x3F), out, fldrs[0] & 0x40); + if (!*out) + GetNSISString(out, fldrs[2]); + x = 0; + } + else if (fldrs[0] == CSIDL_SYSTEM) + { + GetSystemDirectory(out, NSIS_MAX_STRLEN); + x = 0; + } + else if (fldrs[0] == CSIDL_WINDOWS) + { + GetWindowsDirectory(out, NSIS_MAX_STRLEN); + x = 0; + } + + while (x--) + { + if (g_SHGetFolderPath && use_shfolder) + { + PFNSHGETFOLDERPATHA SHGetFolderPathFunc = (PFNSHGETFOLDERPATHA) g_SHGetFolderPath; + if (!SHGetFolderPathFunc(g_hwnd, fldrs[x], NULL, SHGFP_TYPE_CURRENT, out)) + { + break; + } + } + + if (!SHGetSpecialFolderLocation(g_hwnd, fldrs[x], &idl)) + { + BOOL res = SHGetPathFromIDList(idl, out); + CoTaskMemFree(idl); + if (res) break; + } + + *out=0; + } + + if (*out) + { + // all users' version is CSIDL_APPDATA only for $QUICKLAUNCH + // for normal $APPDATA, it'd be CSIDL_APPDATA_COMMON + if (fldrs[2] == CSIDL_APPDATA) + { + mystrcat(out, QUICKLAUNCH); + } + } + validate_filename(out); + } + else if (nVarIdx == NS_VAR_CODE) + { + if (nData == 29) // $HWNDPARENT + myitoa(out, (unsigned int) g_hwnd); + else + mystrcpy(out, g_usrvars[nData]); + // validate the directory name + if ((unsigned int)(nData - 21) < 7) { + // validate paths for $INSTDIR, $OUTDIR, $EXEDIR, $LANGUAGE, $TEMP, $PLUGINSDIR and $EXEPATH + // $LANGUAGE is just a number anyway... + validate_filename(out); + } + } // == VAR_CODES_START + else if (nVarIdx == NS_LANG_CODE) + { + GetNSISString(out, -nData-1); + } + out += mystrlen(out); + } + else if (nVarIdx == NS_SKIP_CODE) + { + *out++ = *in++; + } + else // Normal char + { + *out++ = nVarIdx; + } + } // while + *out = 0; + if (outbuf) + return mystrcpy(outbuf, ps_tmpbuf); + return ps_tmpbuf; +} + +void NSISCALL validate_filename(char *in) { + char *nono = "*?|<>/\":"; + char *out; + char *out_save; + + // ignoring spaces is wrong, " C:\blah" is invalid + //while (*in == ' ') in = CharNext(in); + + if (in[0] == '\\' && in[1] == '\\' && in[2] == '?' && in[3] == '\\') + { + // at least four bytes + in += 4; + } + if (*in) + { + // at least two bytes + if (validpathspec(in)) in += 2; + } + out = out_save = in; + while (*in) + { + if ((unsigned char)*in > 31 && !*findchar(nono, *in)) + { + mini_memcpy(out, in, CharNext(in) - in); + out = CharNext(out); + } + in = CharNext(in); + } + *out = 0; + do + { + out = CharPrev(out_save, out); + if (*out == ' ' || *out == '\\') + *out = 0; + else + break; + } while (out_save < out); +} + +#ifdef NSIS_CONFIG_LOG +int log_dolog; +char log_text[2048]; // 1024 for each wsprintf + +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) +void NSISCALL log_write(int close) +{ + 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 = myOpenFile(g_log_file,GENERIC_WRITE,OPEN_ALWAYS); + if (fp!=INVALID_HANDLE_VALUE) + SetFilePointer(fp,0,NULL,FILE_END); + } + if (fp!=INVALID_HANDLE_VALUE) + { + DWORD d; + mystrcat(log_text,"\r\n"); + WriteFile(fp,log_text,mystrlen(log_text),&d,NULL); + } + } +} +#endif//!NSIS_CONFIG_LOG_ODS && !NSIS_CONFIG_LOG_STDOUT + +const char * _RegKeyHandleToName(HKEY hKey) +{ + if (hKey == HKEY_CLASSES_ROOT) + return "HKEY_CLASSES_ROOT"; + else if (hKey == HKEY_CURRENT_USER) + return "HKEY_CURRENT_USER"; + else if (hKey == HKEY_LOCAL_MACHINE) + return "HKEY_LOCAL_MACHINE"; + else if (hKey == HKEY_USERS) + return "HKEY_USERS"; + else if (hKey == HKEY_PERFORMANCE_DATA) + return "HKEY_PERFORMANCE_DATA"; + else if (hKey == HKEY_CURRENT_CONFIG) + return "HKEY_CURRENT_CONFIG"; + else if (hKey == HKEY_DYN_DATA) + return "HKEY_DYN_DATA"; + else + return "invalid registry key"; +} + +void _LogData2Hex(char *buf, size_t buflen, unsigned char *data, size_t datalen) +{ + char *p = buf; + + size_t i; + + int dots = 0; + size_t bufbytes = buflen / 3; // 2 hex digits, one space/null + + if (datalen > bufbytes) + { + bufbytes--; + dots = 1; + } + else + bufbytes = datalen; + + for (i = 0; i < bufbytes; i++) + { + wsprintf(p, "%02x%c", data[i], (i == bufbytes - 1) ? '\0' : ' '); + p += 3; + } + + if (dots) + mystrcat(buf, "..."); +} + +#ifdef NSIS_CONFIG_LOG_TIMESTAMP +void log_timestamp(char *buf) +{ + SYSTEMTIME st; + GetLocalTime(&st); + wsprintf(buf,"[%04hu/%02hu/%02hu %02hu:%02hu:%02hu] ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); +} +#else +# define log_timestamp(x) +#endif//NSIS_CONFIG_LOG_TIMESTAMP + +void log_printf(char *format, ...) +{ + va_list val; + va_start(val,format); + + log_text[0] = '\0'; + log_timestamp(log_text); + wvsprintf(log_text+mystrlen(log_text),format,val); + + va_end(val); +#ifdef NSIS_CONFIG_LOG_ODS + if (log_dolog) + OutputDebugString(log_text); +#endif +#ifdef NSIS_CONFIG_LOG_STDOUT + if (log_dolog && GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) + { + DWORD dwBytes; + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), log_text, lstrlen(log_text), &dwBytes, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\n", 1, &dwBytes, NULL); + } +#endif +#if !defined(NSIS_CONFIG_LOG_ODS) && !defined(NSIS_CONFIG_LOG_STDOUT) + log_write(0); +#endif +} +#endif//NSIS_CONFIG_LOG + +WIN32_FIND_DATA * NSISCALL file_exists(char *buf) +{ + HANDLE h; + static WIN32_FIND_DATA fd; + h = FindFirstFile(buf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + FindClose(h); + return &fd; + } + return NULL; +} + +struct MGA_FUNC +{ + const char *dll; + const char *func; +}; + +struct MGA_FUNC MGA_FUNCS[] = { + {"KERNEL32", "GetDiskFreeSpaceExA"}, + {"KERNEL32", "MoveFileExA"}, + {"ADVAPI32", "RegDeleteKeyExA"}, + {"ADVAPI32", "OpenProcessToken"}, + {"ADVAPI32", "LookupPrivilegeValueA"}, + {"ADVAPI32", "AdjustTokenPrivileges"}, + {"KERNEL32", "GetUserDefaultUILanguage"}, + {"SHLWAPI", "SHAutoComplete"}, + {"SHFOLDER", "SHGetFolderPathA"} +}; + +void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func) +{ + const char *dll = MGA_FUNCS[func].dll; + HMODULE hModule = GetModuleHandle(dll); + if (!hModule) + hModule = LoadLibrary(dll); + if (!hModule) + return NULL; + + return GetProcAddress(hModule, MGA_FUNCS[func].func); +} + +void NSISCALL MessageLoop(UINT uCheckedMsg) +{ + MSG msg; + while (PeekMessage(&msg, NULL, uCheckedMsg, uCheckedMsg, PM_REMOVE)) + DispatchMessage(&msg); +} diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 2667431..35a1846 100755 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -1,122 +1,122 @@ -/*
- * util.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___NSIS_UTIL_H___
-#define ___NSIS_UTIL_H___
-
-#include "../Platform.h"
-#include "config.h"
-#include <shlobj.h>
-
-extern char ps_tmpbuf[NSIS_MAX_STRLEN*2];
-char * NSISCALL GetNSISString(char *outbuf, int strtab);
-#define GetNSISStringTT(strtab) GetNSISString(0, (strtab))
-#define GetNSISStringNP(strtab) ((const char *)g_blocks[NB_STRINGS].offset+(strtab))
-#define GetNSISTab(strtab) (strtab < 0 ? LANG_STR_TAB(strtab) : strtab)
-void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64);
-int NSISCALL myatoi(char *s);
-void NSISCALL myitoa(char *s, int d);
-char * NSISCALL mystrcpy(char *out, const char *in);
-int NSISCALL mystrlen(const char *in);
-char * NSISCALL mystrcat(char *out, const char *concat);
-char * NSISCALL mystrstr(char *a, char *b);
-WIN32_FIND_DATA * NSISCALL file_exists(char *buf);
-char * NSISCALL my_GetTempFileName(char *buf, const char *dir);
-
-//BOOL NSISCALL my_SetWindowText(HWND hWnd, const char *val);
-#define my_SetWindowText SetWindowText
-BOOL NSISCALL my_SetDialogItemText(HWND dlg, UINT idx, const char *val);
-//#define my_SetDialogItemText SetDlgItemText
-//int NSISCALL my_GetWindowText(HWND hWnd, char *val, int size);
-#define my_GetWindowText GetWindowText
-int NSISCALL my_GetDialogItemText(UINT idx, char *val);
-//#define my_GetDialogItemText GetDlgItemText
-
-#ifdef NSIS_CONFIG_LOG
-extern char log_text[2048];
-void NSISCALL log_write(int close);
-const char * _RegKeyHandleToName(HKEY hKey);
-void _LogData2Hex(char *buf, size_t buflen, unsigned char *data, size_t datalen);
-void log_printf(char *format, ...);
-#define log_printf2(x1,x2) log_printf(x1,x2);
-#define log_printf3(x1,x2,x3) log_printf(x1,x2,x3);
-#define log_printf4(x1,x2,x3,x4) log_printf(x1,x2,x3,x4);
-#define log_printf5(x1,x2,x3,x4,x5) log_printf(x1,x2,x3,x4,x5);
-#define log_printf6(x1,x2,x3,x4,x5,x6) log_printf(x1,x2,x3,x4,x5,x6);
-#define log_printf7(x1,x2,x3,x4,x5,x6,x7) log_printf(x1,x2,x3,x4,x5,x6,x7);
-#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8) log_printf(x1,x2,x3,x4,x5,x6,x7,x8);
-#define RegKeyHandleToName(x1) _RegKeyHandleToName(x1);
-#define LogData2Hex(x1,x2,x3,x4) _LogData2Hex(x1,x2,x3,x4);
-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_printf7(x1,x2,x3,x4,x5,x6,x7)
-#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8)
-#define RegKeyHandleToName(x1) NULL
-#define LogData2Hex(x1,x2,x3,x4)
-#endif
-
-HANDLE NSISCALL myCreateProcess(char *cmd);
-int NSISCALL my_MessageBox(const char *text, UINT type);
-
-void NSISCALL myDelete(char *buf, int flags);
-
-HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd);
-int NSISCALL validpathspec(char *ubuf);
-char * NSISCALL addtrailingslash(char *str);
-//char NSISCALL lastchar(const char *str);
-#define lastchar(str) *CharPrev(str,str+mystrlen(str))
-char * NSISCALL findchar(char *str, char c);
-char * NSISCALL trimslashtoend(char *buf);
-char * NSISCALL skip_root(char *path);
-int NSISCALL is_valid_instpath(char *s);
-void NSISCALL validate_filename(char *fn);
-void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew);
-void NSISCALL mini_memcpy(void *out, const void *in, int len);
-void NSISCALL remove_ro_attr(char *file);
-
-enum myGetProcAddressFunctions {
- MGA_GetDiskFreeSpaceExA,
- MGA_MoveFileExA,
- MGA_RegDeleteKeyExA,
- MGA_OpenProcessToken,
- MGA_LookupPrivilegeValueA,
- MGA_AdjustTokenPrivileges,
- MGA_GetUserDefaultUILanguage,
- MGA_SHAutoComplete,
- MGA_SHGetFolderPathA
-};
-
-void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func);
-void NSISCALL MessageLoop(UINT uCheckedMsg);
-
-// Turn a pair of chars into a word
-// Turn four chars into a dword
-#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
-#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8))
-#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16))
-#else
-#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8))
-#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16))
-#endif
-
-#endif//!___NSIS_UTIL_H___
+/* + * util.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___NSIS_UTIL_H___ +#define ___NSIS_UTIL_H___ + +#include "../Platform.h" +#include "config.h" +#include <shlobj.h> + +extern char ps_tmpbuf[NSIS_MAX_STRLEN*2]; +char * NSISCALL GetNSISString(char *outbuf, int strtab); +#define GetNSISStringTT(strtab) GetNSISString(0, (strtab)) +#define GetNSISStringNP(strtab) ((const char *)g_blocks[NB_STRINGS].offset+(strtab)) +#define GetNSISTab(strtab) (strtab < 0 ? LANG_STR_TAB(strtab) : strtab) +void NSISCALL myRegGetStr(HKEY root, const char *sub, const char *name, char *out, int x64); +int NSISCALL myatoi(char *s); +void NSISCALL myitoa(char *s, int d); +char * NSISCALL mystrcpy(char *out, const char *in); +int NSISCALL mystrlen(const char *in); +char * NSISCALL mystrcat(char *out, const char *concat); +char * NSISCALL mystrstr(char *a, char *b); +WIN32_FIND_DATA * NSISCALL file_exists(char *buf); +char * NSISCALL my_GetTempFileName(char *buf, const char *dir); + +//BOOL NSISCALL my_SetWindowText(HWND hWnd, const char *val); +#define my_SetWindowText SetWindowText +BOOL NSISCALL my_SetDialogItemText(HWND dlg, UINT idx, const char *val); +//#define my_SetDialogItemText SetDlgItemText +//int NSISCALL my_GetWindowText(HWND hWnd, char *val, int size); +#define my_GetWindowText GetWindowText +int NSISCALL my_GetDialogItemText(UINT idx, char *val); +//#define my_GetDialogItemText GetDlgItemText + +#ifdef NSIS_CONFIG_LOG +extern char log_text[2048]; +void NSISCALL log_write(int close); +const char * _RegKeyHandleToName(HKEY hKey); +void _LogData2Hex(char *buf, size_t buflen, unsigned char *data, size_t datalen); +void log_printf(char *format, ...); +#define log_printf2(x1,x2) log_printf(x1,x2); +#define log_printf3(x1,x2,x3) log_printf(x1,x2,x3); +#define log_printf4(x1,x2,x3,x4) log_printf(x1,x2,x3,x4); +#define log_printf5(x1,x2,x3,x4,x5) log_printf(x1,x2,x3,x4,x5); +#define log_printf6(x1,x2,x3,x4,x5,x6) log_printf(x1,x2,x3,x4,x5,x6); +#define log_printf7(x1,x2,x3,x4,x5,x6,x7) log_printf(x1,x2,x3,x4,x5,x6,x7); +#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8) log_printf(x1,x2,x3,x4,x5,x6,x7,x8); +#define RegKeyHandleToName(x1) _RegKeyHandleToName(x1); +#define LogData2Hex(x1,x2,x3,x4) _LogData2Hex(x1,x2,x3,x4); +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_printf7(x1,x2,x3,x4,x5,x6,x7) +#define log_printf8(x1,x2,x3,x4,x5,x6,x7,x8) +#define RegKeyHandleToName(x1) NULL +#define LogData2Hex(x1,x2,x3,x4) +#endif + +HANDLE NSISCALL myCreateProcess(char *cmd); +int NSISCALL my_MessageBox(const char *text, UINT type); + +void NSISCALL myDelete(char *buf, int flags); + +HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd); +int NSISCALL validpathspec(char *ubuf); +char * NSISCALL addtrailingslash(char *str); +//char NSISCALL lastchar(const char *str); +#define lastchar(str) *CharPrev(str,str+mystrlen(str)) +char * NSISCALL findchar(char *str, char c); +char * NSISCALL trimslashtoend(char *buf); +char * NSISCALL skip_root(char *path); +int NSISCALL is_valid_instpath(char *s); +void NSISCALL validate_filename(char *fn); +void NSISCALL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew); +void NSISCALL mini_memcpy(void *out, const void *in, int len); +void NSISCALL remove_ro_attr(char *file); + +enum myGetProcAddressFunctions { + MGA_GetDiskFreeSpaceExA, + MGA_MoveFileExA, + MGA_RegDeleteKeyExA, + MGA_OpenProcessToken, + MGA_LookupPrivilegeValueA, + MGA_AdjustTokenPrivileges, + MGA_GetUserDefaultUILanguage, + MGA_SHAutoComplete, + MGA_SHGetFolderPathA +}; + +void * NSISCALL myGetProcAddress(const enum myGetProcAddressFunctions func); +void NSISCALL MessageLoop(UINT uCheckedMsg); + +// Turn a pair of chars into a word +// Turn four chars into a dword +#ifdef __BIG_ENDIAN__ // Not very likely, but, still... +#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8)) +#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16)) +#else +#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8)) +#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16)) +#endif + +#endif//!___NSIS_UTIL_H___ diff --git a/Source/fileform.cpp b/Source/fileform.cpp index c2bdb67..fddf866 100755 --- a/Source/fileform.cpp +++ b/Source/fileform.cpp @@ -1,194 +1,194 @@ -/*
- * fileform.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "fileform.h"
-#include "exehead/config.h"
-#include "Platform.h"
-
-#include <cassert>
-
-// these functions MUST be synchronized with the structures in Source/exehead/fileform.h !
-// data must be written in the same order it's defined in Source/exehead/fileform.h
-// in the future, i hope to get one of the two automtaically generated from the other
-
-void firstheader_writer::write(const firstheader *data)
-{
- m_sink->write_int(data->flags);
- m_sink->write_int(data->siginfo);
- m_sink->write_int_array(data->nsinst, 3);
- m_sink->write_int(data->length_of_header);
- m_sink->write_int(data->length_of_all_following_data);
-}
-
-void block_header_writer::write(const block_header *data)
-{
- m_sink->write_int(data->offset);
- m_sink->write_int(data->num);
-}
-
-void header_writer::write(const header *data)
-{
- m_sink->write_int(data->flags);
-
- block_header_writer bw(writer::m_sink);
- for (int i = 0; i < BLOCKS_NUM; i++)
- {
- bw.write(&data->blocks[i]);
- }
-
- m_sink->write_int(data->install_reg_rootkey);
- m_sink->write_int(data->install_reg_key_ptr);
- m_sink->write_int(data->install_reg_value_ptr);
-
-#ifdef NSIS_SUPPORT_BGBG
- m_sink->write_int(data->bg_color1);
- m_sink->write_int(data->bg_color2);
- m_sink->write_int(data->bg_textcolor);
-#endif
-
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- m_sink->write_int(data->lb_bg);
- m_sink->write_int(data->lb_fg);
-#endif
-
- m_sink->write_int(data->langtable_size);
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- m_sink->write_int(data->license_bg);
-#endif//NSIS_CONFIG_LICENSEPAGE
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- m_sink->write_int(data->code_onInit);
- m_sink->write_int(data->code_onInstSuccess);
- m_sink->write_int(data->code_onInstFailed);
- m_sink->write_int(data->code_onUserAbort);
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- m_sink->write_int(data->code_onGUIInit);
- m_sink->write_int(data->code_onGUIEnd);
- m_sink->write_int(data->code_onMouseOverSection);
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
- m_sink->write_int(data->code_onVerifyInstDir);
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- m_sink->write_int(data->code_onSelChange);
-#endif//NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_SUPPORT_REBOOT
- m_sink->write_int(data->code_onRebootFailed);
-#endif//NSIS_SUPPORT_REBOOT
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- m_sink->write_int_array(data->install_types, NSIS_MAX_INST_TYPES + 1);
-#endif
-
- m_sink->write_int(data->install_directory_ptr);
- m_sink->write_int(data->install_directory_auto_append);
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- m_sink->write_int(data->str_uninstchild);
- m_sink->write_int(data->str_uninstcmd);
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- m_sink->write_int(data->str_wininit);
-#endif//NSIS_SUPPORT_MOVEONREBOOT
-}
-
-void section_writer::write(const section *data)
-{
- m_sink->write_int(data->name_ptr);
- m_sink->write_int(data->install_types);
- m_sink->write_int(data->flags);
- m_sink->write_int(data->code);
- m_sink->write_int(data->code_size);
- m_sink->write_int(data->size_kb);
- m_sink->write_string(data->name, NSIS_MAX_STRLEN);
-}
-
-void entry_writer::write(const entry *data)
-{
- m_sink->write_int(data->which);
- m_sink->write_int_array(data->offsets, MAX_ENTRY_OFFSETS);
-}
-
-void page_writer::write(const page *data)
-{
- m_sink->write_int(data->dlg_id);
- m_sink->write_int(data->wndproc_id);
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- m_sink->write_int(data->prefunc);
- m_sink->write_int(data->showfunc);
- m_sink->write_int(data->leavefunc);
-#endif //NSIS_SUPPORT_CODECALLBACKS
-
- m_sink->write_int(data->flags);
-
- m_sink->write_int(data->caption);
- m_sink->write_int(data->back);
- m_sink->write_int(data->next);
- m_sink->write_int(data->clicknext);
- m_sink->write_int(data->cancel);
-
- m_sink->write_int_array(data->parms, 5);
-}
-
-void ctlcolors_writer::write(const ctlcolors *data)
-{
- m_sink->write_int(data->text);
- m_sink->write_int(data->bkc);
- m_sink->write_int(data->lbStyle);
- m_sink->write_int((int) data->bkb);
- m_sink->write_int(data->bkmode);
- m_sink->write_int(data->flags);
-}
-
-void LOGFONT_writer::write(const LOGFONT *data)
-{
- m_sink->write_int(data->lfHeight);
- m_sink->write_int(data->lfWidth);
- m_sink->write_int(data->lfEscapement);
- m_sink->write_int(data->lfOrientation);
- m_sink->write_int(data->lfWeight);
- m_sink->write_byte(data->lfItalic);
- m_sink->write_byte(data->lfUnderline);
- m_sink->write_byte(data->lfStrikeOut);
- m_sink->write_byte(data->lfCharSet);
- m_sink->write_byte(data->lfOutPrecision);
- m_sink->write_byte(data->lfClipPrecision);
- m_sink->write_byte(data->lfQuality);
- m_sink->write_byte(data->lfPitchAndFamily);
- m_sink->write_string(data->lfFaceName, LF_FACESIZE);
-}
-
-void lang_table_writer::write(const unsigned char *data)
-{
- assert(sizeof(LANGID) == sizeof(short));
-
- m_sink->write_short(* (short *) data);
- data += sizeof(short);
- m_sink->write_int_array((int *) data, m_lang_strings + 2);
-}
-
-void lang_table_writer::write_block(IGrowBuf *buf, writer_sink *sink, const size_t table_size)
-{
- unsigned char *tables = (unsigned char *) buf->get();
- size_t lang_strings = ( table_size - 2 * sizeof(int) - sizeof(LANGID) ) / sizeof(int);
- size_t l = buf->getlen() / table_size;
- lang_table_writer writer(sink, lang_strings);
- for (size_t i = 0; i < l; i++)
- {
- writer.write(tables + i * table_size);
- }
-}
+/* + * fileform.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "fileform.h" +#include "exehead/config.h" +#include "Platform.h" + +#include <cassert> + +// these functions MUST be synchronized with the structures in Source/exehead/fileform.h ! +// data must be written in the same order it's defined in Source/exehead/fileform.h +// in the future, i hope to get one of the two automtaically generated from the other + +void firstheader_writer::write(const firstheader *data) +{ + m_sink->write_int(data->flags); + m_sink->write_int(data->siginfo); + m_sink->write_int_array(data->nsinst, 3); + m_sink->write_int(data->length_of_header); + m_sink->write_int(data->length_of_all_following_data); +} + +void block_header_writer::write(const block_header *data) +{ + m_sink->write_int(data->offset); + m_sink->write_int(data->num); +} + +void header_writer::write(const header *data) +{ + m_sink->write_int(data->flags); + + block_header_writer bw(writer::m_sink); + for (int i = 0; i < BLOCKS_NUM; i++) + { + bw.write(&data->blocks[i]); + } + + m_sink->write_int(data->install_reg_rootkey); + m_sink->write_int(data->install_reg_key_ptr); + m_sink->write_int(data->install_reg_value_ptr); + +#ifdef NSIS_SUPPORT_BGBG + m_sink->write_int(data->bg_color1); + m_sink->write_int(data->bg_color2); + m_sink->write_int(data->bg_textcolor); +#endif + +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + m_sink->write_int(data->lb_bg); + m_sink->write_int(data->lb_fg); +#endif + + m_sink->write_int(data->langtable_size); + +#ifdef NSIS_CONFIG_LICENSEPAGE + m_sink->write_int(data->license_bg); +#endif//NSIS_CONFIG_LICENSEPAGE + +#ifdef NSIS_SUPPORT_CODECALLBACKS + m_sink->write_int(data->code_onInit); + m_sink->write_int(data->code_onInstSuccess); + m_sink->write_int(data->code_onInstFailed); + m_sink->write_int(data->code_onUserAbort); +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + m_sink->write_int(data->code_onGUIInit); + m_sink->write_int(data->code_onGUIEnd); + m_sink->write_int(data->code_onMouseOverSection); +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT + m_sink->write_int(data->code_onVerifyInstDir); +#ifdef NSIS_CONFIG_COMPONENTPAGE + m_sink->write_int(data->code_onSelChange); +#endif//NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_SUPPORT_REBOOT + m_sink->write_int(data->code_onRebootFailed); +#endif//NSIS_SUPPORT_REBOOT +#endif//NSIS_SUPPORT_CODECALLBACKS + +#ifdef NSIS_CONFIG_COMPONENTPAGE + m_sink->write_int_array(data->install_types, NSIS_MAX_INST_TYPES + 1); +#endif + + m_sink->write_int(data->install_directory_ptr); + m_sink->write_int(data->install_directory_auto_append); + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + m_sink->write_int(data->str_uninstchild); + m_sink->write_int(data->str_uninstcmd); +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#ifdef NSIS_SUPPORT_MOVEONREBOOT + m_sink->write_int(data->str_wininit); +#endif//NSIS_SUPPORT_MOVEONREBOOT +} + +void section_writer::write(const section *data) +{ + m_sink->write_int(data->name_ptr); + m_sink->write_int(data->install_types); + m_sink->write_int(data->flags); + m_sink->write_int(data->code); + m_sink->write_int(data->code_size); + m_sink->write_int(data->size_kb); + m_sink->write_string(data->name, NSIS_MAX_STRLEN); +} + +void entry_writer::write(const entry *data) +{ + m_sink->write_int(data->which); + m_sink->write_int_array(data->offsets, MAX_ENTRY_OFFSETS); +} + +void page_writer::write(const page *data) +{ + m_sink->write_int(data->dlg_id); + m_sink->write_int(data->wndproc_id); + +#ifdef NSIS_SUPPORT_CODECALLBACKS + m_sink->write_int(data->prefunc); + m_sink->write_int(data->showfunc); + m_sink->write_int(data->leavefunc); +#endif //NSIS_SUPPORT_CODECALLBACKS + + m_sink->write_int(data->flags); + + m_sink->write_int(data->caption); + m_sink->write_int(data->back); + m_sink->write_int(data->next); + m_sink->write_int(data->clicknext); + m_sink->write_int(data->cancel); + + m_sink->write_int_array(data->parms, 5); +} + +void ctlcolors_writer::write(const ctlcolors *data) +{ + m_sink->write_int(data->text); + m_sink->write_int(data->bkc); + m_sink->write_int(data->lbStyle); + m_sink->write_int((int) data->bkb); + m_sink->write_int(data->bkmode); + m_sink->write_int(data->flags); +} + +void LOGFONT_writer::write(const LOGFONT *data) +{ + m_sink->write_int(data->lfHeight); + m_sink->write_int(data->lfWidth); + m_sink->write_int(data->lfEscapement); + m_sink->write_int(data->lfOrientation); + m_sink->write_int(data->lfWeight); + m_sink->write_byte(data->lfItalic); + m_sink->write_byte(data->lfUnderline); + m_sink->write_byte(data->lfStrikeOut); + m_sink->write_byte(data->lfCharSet); + m_sink->write_byte(data->lfOutPrecision); + m_sink->write_byte(data->lfClipPrecision); + m_sink->write_byte(data->lfQuality); + m_sink->write_byte(data->lfPitchAndFamily); + m_sink->write_string(data->lfFaceName, LF_FACESIZE); +} + +void lang_table_writer::write(const unsigned char *data) +{ + assert(sizeof(LANGID) == sizeof(short)); + + m_sink->write_short(* (short *) data); + data += sizeof(short); + m_sink->write_int_array((int *) data, m_lang_strings + 2); +} + +void lang_table_writer::write_block(IGrowBuf *buf, writer_sink *sink, const size_t table_size) +{ + unsigned char *tables = (unsigned char *) buf->get(); + size_t lang_strings = ( table_size - 2 * sizeof(int) - sizeof(LANGID) ) / sizeof(int); + size_t l = buf->getlen() / table_size; + lang_table_writer writer(sink, lang_strings); + for (size_t i = 0; i < l; i++) + { + writer.write(tables + i * table_size); + } +} diff --git a/Source/fileform.h b/Source/fileform.h index 1244d18..71afdaf 100755 --- a/Source/fileform.h +++ b/Source/fileform.h @@ -1,63 +1,63 @@ -/*
- * fileform.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___MAKENSIS_FILEFORM_H___
-#define ___MAKENSIS_FILEFORM_H___
-
-#include "exehead/fileform.h"
-#include "writer.h"
-
-#define DECLARE_WRITER(x) \
- class x##_writer : public writer \
- { \
- public: \
- x##_writer(writer_sink *sink) : writer(sink) {} \
- void write(const x *data); \
- static void write_block(IGrowBuf *buf, writer_sink *sink) \
- { \
- x *arr = (x *) buf->get(); \
- size_t l = buf->getlen() / sizeof(x); \
- x##_writer writer(sink); \
- for (size_t i = 0; i < l; i++) \
- { \
- writer.write(&arr[i]); \
- } \
- } \
- }
-
-DECLARE_WRITER(firstheader);
-DECLARE_WRITER(block_header);
-DECLARE_WRITER(header);
-DECLARE_WRITER(section);
-DECLARE_WRITER(entry);
-DECLARE_WRITER(page);
-DECLARE_WRITER(ctlcolors);
-DECLARE_WRITER(LOGFONT);
-
-class lang_table_writer : public writer
-{
-public:
- lang_table_writer(writer_sink *sink, const size_t lang_strings) :
- writer(sink), m_lang_strings(lang_strings) {}
- void write(const unsigned char *data);
- static void write_block(IGrowBuf *buf, writer_sink *sink, const size_t table_size);
-
-private:
- size_t m_lang_strings;
-
-};
-
-#endif//!___MAKENSIS_FILEFORM_H___
+/* + * fileform.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___MAKENSIS_FILEFORM_H___ +#define ___MAKENSIS_FILEFORM_H___ + +#include "exehead/fileform.h" +#include "writer.h" + +#define DECLARE_WRITER(x) \ + class x##_writer : public writer \ + { \ + public: \ + x##_writer(writer_sink *sink) : writer(sink) {} \ + void write(const x *data); \ + static void write_block(IGrowBuf *buf, writer_sink *sink) \ + { \ + x *arr = (x *) buf->get(); \ + size_t l = buf->getlen() / sizeof(x); \ + x##_writer writer(sink); \ + for (size_t i = 0; i < l; i++) \ + { \ + writer.write(&arr[i]); \ + } \ + } \ + } + +DECLARE_WRITER(firstheader); +DECLARE_WRITER(block_header); +DECLARE_WRITER(header); +DECLARE_WRITER(section); +DECLARE_WRITER(entry); +DECLARE_WRITER(page); +DECLARE_WRITER(ctlcolors); +DECLARE_WRITER(LOGFONT); + +class lang_table_writer : public writer +{ +public: + lang_table_writer(writer_sink *sink, const size_t lang_strings) : + writer(sink), m_lang_strings(lang_strings) {} + void write(const unsigned char *data); + static void write_block(IGrowBuf *buf, writer_sink *sink, const size_t table_size); + +private: + size_t m_lang_strings; + +}; + +#endif//!___MAKENSIS_FILEFORM_H___ diff --git a/Source/growbuf.cpp b/Source/growbuf.cpp index 8a13b63..28d8842 100755 --- a/Source/growbuf.cpp +++ b/Source/growbuf.cpp @@ -1,88 +1,88 @@ -/*
- * growbuf.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "growbuf.h"
-
-#include <cstdlib> // for malloc/free
-#include <cstring> // for memcpy
-#include <cstdio> // for f*
-#include <algorithm> // for std::min
-
-#include "Platform.h"
-
-using namespace std;
-
-GrowBuf::GrowBuf() { m_alloc=m_used=m_zero=0; m_s=NULL; m_bs=32768; }
-GrowBuf::~GrowBuf() { free(m_s); }
-
-void GrowBuf::set_zeroing(int zero) { m_zero=zero; }
-
-int GrowBuf::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 GrowBuf::resize(int newlen)
-{
- int os=m_alloc;
- int ou=m_used;
- m_used=newlen;
- if (newlen > m_alloc)
- {
- void *n;
- m_alloc = newlen*2 + m_bs;
- 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_zero && m_used > ou)
- memset((char*)m_s + ou, 0, m_used - ou);
- if (!m_used && m_alloc > 2*m_bs) // only free if you resize to 0 and we're > 64k
- {
- m_alloc=0;
- free(m_s);
- m_s=NULL;
- }
-}
-
-int GrowBuf::getlen() const { return m_used; }
-void *GrowBuf::get() const { return m_s; }
+/* + * growbuf.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "growbuf.h" + +#include <cstdlib> // for malloc/free +#include <cstring> // for memcpy +#include <cstdio> // for f* +#include <algorithm> // for std::min + +#include "Platform.h" + +using namespace std; + +GrowBuf::GrowBuf() { m_alloc=m_used=m_zero=0; m_s=NULL; m_bs=32768; } +GrowBuf::~GrowBuf() { free(m_s); } + +void GrowBuf::set_zeroing(int zero) { m_zero=zero; } + +int GrowBuf::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 GrowBuf::resize(int newlen) +{ + int os=m_alloc; + int ou=m_used; + m_used=newlen; + if (newlen > m_alloc) + { + void *n; + m_alloc = newlen*2 + m_bs; + 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_zero && m_used > ou) + memset((char*)m_s + ou, 0, m_used - ou); + if (!m_used && m_alloc > 2*m_bs) // only free if you resize to 0 and we're > 64k + { + m_alloc=0; + free(m_s); + m_s=NULL; + } +} + +int GrowBuf::getlen() const { return m_used; } +void *GrowBuf::get() const { return m_s; } diff --git a/Source/growbuf.h b/Source/growbuf.h index 42edef1..b3c3fb1 100755 --- a/Source/growbuf.h +++ b/Source/growbuf.h @@ -1,62 +1,62 @@ -/*
- * growbuf.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __GROWBUF_H_
-#define __GROWBUF_H_
-
-class IGrowBuf
-{
- public:
- virtual ~IGrowBuf() {}
- virtual int add(const void *data, int len)=0;
- virtual void resize(int newlen)=0;
- virtual int getlen() const=0;
- virtual void *get() const=0;
-};
-
-class GrowBuf : public IGrowBuf
-{
- private: // don't copy instances
- GrowBuf(const GrowBuf&);
- void operator=(const GrowBuf&);
-
- public:
- GrowBuf();
- virtual ~GrowBuf();
-
- void set_zeroing(int zero);
- int add(const void *data, int len);
- void resize(int newlen);
- int getlen() const;
- void *get() const;
-
- private:
- void *m_s;
- int m_alloc;
- int m_used;
- int m_zero;
-
- protected:
- int m_bs;
-};
-
-class TinyGrowBuf : public GrowBuf {
- public:
- TinyGrowBuf() : GrowBuf() { m_bs=1024; }
-};
-
-#endif
-
+/* + * growbuf.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __GROWBUF_H_ +#define __GROWBUF_H_ + +class IGrowBuf +{ + public: + virtual ~IGrowBuf() {} + virtual int add(const void *data, int len)=0; + virtual void resize(int newlen)=0; + virtual int getlen() const=0; + virtual void *get() const=0; +}; + +class GrowBuf : public IGrowBuf +{ + private: // don't copy instances + GrowBuf(const GrowBuf&); + void operator=(const GrowBuf&); + + public: + GrowBuf(); + virtual ~GrowBuf(); + + void set_zeroing(int zero); + int add(const void *data, int len); + void resize(int newlen); + int getlen() const; + void *get() const; + + private: + void *m_s; + int m_alloc; + int m_used; + int m_zero; + + protected: + int m_bs; +}; + +class TinyGrowBuf : public GrowBuf { + public: + TinyGrowBuf() : GrowBuf() { m_bs=1024; } +}; + +#endif + diff --git a/Source/icon.cpp b/Source/icon.cpp new file mode 100755 index 0000000..e169fcd --- /dev/null +++ b/Source/icon.cpp @@ -0,0 +1,379 @@ +#include "Platform.h" +#include "icon.h" +#include "util.h" +#include "lang.h" + +#include <stdio.h> +#include <stdexcept> +#include <vector> +#include <algorithm> + +using namespace std; + +extern int g_display_errors; +extern FILE *g_output; + +#define SIZEOF_RSRC_ICON_GROUP_ENTRY 14 + +static FILE * open_icon(const char* filename, IconGroupHeader& igh) +{ + FILE* f = FOPEN(filename, "rb"); + if (!f) + throw runtime_error("can't open file"); + + if (!fread(&igh, sizeof(IconGroupHeader), 1, f)) + throw runtime_error("unable to read header from file"); + + FIX_ENDIAN_INT16_INPLACE(igh.wIsIcon); + FIX_ENDIAN_INT16_INPLACE(igh.wReserved); + FIX_ENDIAN_INT16_INPLACE(igh.wCount); + + if (igh.wIsIcon != 1 || igh.wReserved != 0) + throw runtime_error("invalid icon file"); + + return f; +} + +void free_loaded_icon(IconGroup icon) +{ + for (IconGroup::size_type i = 0; i < icon.size(); i++) + { + delete [] icon[i].data; + } +} + +IconGroup load_icon_res(CResourceEditor* re, WORD id) +{ + IconGroupHeader* header; + IconGroup result; + + LPBYTE group = re->GetResourceA( + RT_GROUP_ICON, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); + + if (!group) + throw runtime_error("can't find icon group"); + + header = (IconGroupHeader*) group; + + for (WORD i = 0; i < FIX_ENDIAN_INT16(header->wCount); i++) + { + Icon icon; + icon.index = i; + + RsrcIconGroupEntry* entry = (RsrcIconGroupEntry*) (group + + sizeof(IconGroupHeader) + SIZEOF_RSRC_ICON_GROUP_ENTRY * i); + + memcpy(&icon.meta, &entry->header, sizeof(IconGroupEntry)); + + WORD rsrc_id = FIX_ENDIAN_INT16(entry->wRsrcId); + + icon.data = re->GetResourceA(RT_ICON, MAKEINTRESOURCE(rsrc_id), NSIS_DEFAULT_LANG); + + if (!icon.data) + { + free_loaded_icon(result); + throw runtime_error("can't find icon"); + } + + result.push_back(icon); + } + + return result; +} + +IconGroup load_icon_file(const char* filename) +{ + IconGroupHeader iconHeader; + IconGroup result; + + FILE *file = open_icon(filename, iconHeader); + + for (WORD i = 0; i < iconHeader.wCount; i++) + { + Icon icon; + icon.index = i; + icon.data = NULL; + + if (!fread(&icon.meta, sizeof(IconGroupEntry), 1, file)) + { + free_loaded_icon(result); + throw runtime_error("unable to read entry from file"); + } + + DWORD size = FIX_ENDIAN_INT32(icon.meta.dwRawSize); + if (size > 1048576) // magic numbers are great + { + free_loaded_icon(result); + throw runtime_error("invalid icon file size"); + } + + DWORD iconOffset; + + if (!fread(&iconOffset, sizeof(DWORD), 1, file)) + { + free_loaded_icon(result); + throw runtime_error("unable to read offset from file"); + } + + fpos_t pos; + fgetpos(file, &pos); + + if (fseek(file, iconOffset, SEEK_SET)) + { + free_loaded_icon(result); + throw runtime_error("corrupted icon file, too small"); + } + + icon.data = new BYTE[size]; + + if (!fread(icon.data, size, 1, file)) + { + free_loaded_icon(result); + throw runtime_error("unable to read icon from file"); + } + + fsetpos(file, &pos); + + result.push_back(icon); + } + + return result; +} + +typedef struct +{ + unsigned index1; + unsigned index2; + DWORD size; +} IconPair; + +bool compare_icon(Icon a, Icon b) +{ + return FIX_ENDIAN_INT32(a.meta.dwRawSize) > FIX_ENDIAN_INT32(b.meta.dwRawSize); +} + +static IconGroup sort_icon(IconGroup icon) +{ + IconGroup sorted = icon; + sort(sorted.begin(), sorted.end(), compare_icon); + return sorted; +} + +static vector<IconPair> get_icon_order(IconGroup icon1, IconGroup icon2) +{ + IconGroup sorted_icons1 = sort_icon(icon1); + IconGroup sorted_icons2 = sort_icon(icon2); + + IconGroup::size_type shared_count = min(sorted_icons1.size(), sorted_icons2.size()); + IconGroup::size_type total_count = max(sorted_icons1.size(), sorted_icons2.size()); + + vector<IconPair> result; + IconGroup::size_type i; + + for (i = 0; i < shared_count; i++) + { + IconPair pair; + + pair.index1 = sorted_icons1[i].index; + pair.index2 = sorted_icons2[i].index; + pair.size = max( + FIX_ENDIAN_INT32(sorted_icons1[i].meta.dwRawSize), + FIX_ENDIAN_INT32(sorted_icons2[i].meta.dwRawSize) + ); + + result.push_back(pair); + } + + for (; i < total_count; i++) + { + IconPair pair; + + if (i < sorted_icons1.size()) + { + pair.index1 = sorted_icons1[i].index; + pair.index2 = 0xffff; + pair.size = FIX_ENDIAN_INT32(sorted_icons1[i].meta.dwRawSize); + } + + if (i < sorted_icons2.size()) + { + pair.index2 = sorted_icons2[i].index; + pair.index1 = 0xffff; + pair.size = FIX_ENDIAN_INT32(sorted_icons2[i].meta.dwRawSize); + } + + result.push_back(pair); + } + + return result; +} + +static LPBYTE generate_icon_group(IconGroup icon, vector<IconPair> order, bool first) +{ + LPBYTE group = new BYTE[ + sizeof(IconGroupHeader) // header + + order.size() * SIZEOF_RSRC_ICON_GROUP_ENTRY // entries + ]; + + IconGroupHeader* header = (IconGroupHeader*) group; + + header->wReserved = 0; + header->wIsIcon = FIX_ENDIAN_INT16(1); + header->wCount = FIX_ENDIAN_INT16(icon.size()); + + for (IconGroup::size_type i = 0; i < icon.size(); i++) + { + RsrcIconGroupEntry* entry = (RsrcIconGroupEntry*) + &group[sizeof(IconGroupHeader) + SIZEOF_RSRC_ICON_GROUP_ENTRY * i]; + unsigned index = first ? order[i].index1 : order[i].index2; + + memcpy(&entry->header, &icon[index].meta, sizeof(IconGroupEntry)); + entry->wRsrcId = FIX_ENDIAN_INT16(i + 1); + } + + return group; +} + +// set_icon, must get an initialized resource editor +void set_icon(CResourceEditor* re, WORD wIconId, IconGroup icon1, IconGroup icon2) +{ + vector<IconPair> order = get_icon_order(icon1, icon2); + + // genreate group + LPBYTE group1 = generate_icon_group(icon1, order, true); + + // set group + size_t group_size = sizeof(IconGroupHeader) // header + + order.size() * SIZEOF_RSRC_ICON_GROUP_ENTRY; // entries + + re->UpdateResourceA(RT_GROUP_ICON, MAKEINTRESOURCE(wIconId), NSIS_DEFAULT_LANG, group1, group_size); + + // delete old icons + unsigned i = 1; + while (re->UpdateResourceA(RT_ICON, MAKEINTRESOURCE(i++), NSIS_DEFAULT_LANG, 0, 0)); + + // set new icons + IconGroup::size_type order_index; + for (order_index = 0; order_index < order.size(); order_index++) + { + LPBYTE data = new BYTE[order[order_index].size]; + + if (order_index < icon1.size()) + { + Icon* icon = &icon1[order[order_index].index1]; + memcpy(data, icon->data, FIX_ENDIAN_INT32(icon->meta.dwRawSize)); + } + + re->UpdateResourceA(RT_ICON, MAKEINTRESOURCE(order_index + 1), NSIS_DEFAULT_LANG, data, order[order_index].size); + + delete [] data; + } +} + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +// returns the data of the uninstaller icon that should replace the installer icon data +unsigned char* generate_uninstall_icon_data(IconGroup icon1, IconGroup icon2, size_t &data_size) +{ + IconGroup::size_type i; + vector<IconPair> order = get_icon_order(icon1, icon2); + + // genreate group + LPBYTE group = generate_icon_group(icon2, order, false); + + // calculate size + size_t group_size = sizeof(IconGroupHeader) // header + + order.size() * SIZEOF_RSRC_ICON_GROUP_ENTRY; // entries + + data_size = group_size // group header + + sizeof(DWORD) * 2 // offset and size of group header + + (sizeof(DWORD) * 2) * icon2.size() // offset and size per entry + + sizeof(DWORD); // terminator + + for (i = 0; i < icon2.size(); i++) + { + // add icon sizes + data_size += FIX_ENDIAN_INT32(icon2[i].meta.dwRawSize); + } + + // allocate memory + LPBYTE uninst_data = new BYTE[data_size]; + LPBYTE seeker = uninst_data; + + // fill group header + *(LPDWORD) seeker = FIX_ENDIAN_INT32(group_size); + seeker += sizeof(DWORD); + *(LPDWORD) seeker = 0; + seeker += sizeof(DWORD); + + memcpy(seeker, group, group_size); + seeker += group_size; + + // fill entries + for (i = 0; i < icon2.size(); i++) + { + Icon* icon = &icon2[order[i].index2]; + DWORD size = FIX_ENDIAN_INT32(icon->meta.dwRawSize); + + *(LPDWORD) seeker = FIX_ENDIAN_INT32(size); + seeker += sizeof(DWORD); + *(LPDWORD) seeker = 0; + seeker += sizeof(DWORD); + + memcpy(seeker, icon->data, size); + seeker += size; + } + + // add terminator + *(LPDWORD) seeker = 0; + + // done + return uninst_data; +} + +// Fill the array of icons for uninstall with their offsets +// Returns zero on failure +int generate_unicons_offsets(LPBYTE exeHeader, size_t exeHeaderSize, LPBYTE uninstIconData, WORD wIconId) { + try + { + DWORD offset; + DWORD size; + + CResourceEditor re(exeHeader, exeHeaderSize); + + LPBYTE seeker = uninstIconData; + + offset = re.GetResourceOffsetA(RT_GROUP_ICON, MAKEINTRESOURCE(wIconId), NSIS_DEFAULT_LANG); + + size = *(LPDWORD)seeker; + seeker += sizeof(DWORD); + *(LPDWORD) seeker = FIX_ENDIAN_INT32(offset); + seeker += sizeof(DWORD); + + seeker += FIX_ENDIAN_INT32(size); + + WORD icon_index = 1; + + while (*(LPDWORD)seeker) + { + offset = re.GetResourceOffsetA(RT_ICON, MAKEINTRESOURCE(icon_index), NSIS_DEFAULT_LANG); + + size = *(LPDWORD)seeker; + seeker += sizeof(DWORD); + *(LPDWORD) seeker = FIX_ENDIAN_INT32(offset); + seeker += sizeof(DWORD); + + seeker += FIX_ENDIAN_INT32(size); + + icon_index++; + } + } + catch (const exception& e) + { + if (g_display_errors) + fprintf(g_output, "\nError generating uninstaller icon: %s -- failing!\n", e.what()); + return 0; + } + + return 1; +} +#endif // NSIS_CONFIG_UNINSTALL_SUPPORT diff --git a/Source/icon.h b/Source/icon.h new file mode 100755 index 0000000..e71f28b --- /dev/null +++ b/Source/icon.h @@ -0,0 +1,76 @@ +/* + * icon.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _ICON_H_ +#define _ICON_H_ + +#include "ResourceEditor.h" + +#include <vector> + +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; +} IconGroupEntry; + +typedef struct +{ + IconGroupEntry header; + DWORD dwImageOffset; +} FileIconGroupEntry; + +typedef struct +{ + IconGroupEntry header; + WORD wRsrcId; +} RsrcIconGroupEntry; + +typedef struct +{ + unsigned index; + IconGroupEntry meta; + LPBYTE data; +} Icon; + +typedef std::vector<Icon> IconGroup; + +IconGroup load_icon_file(const char* filename); +IconGroup load_icon_res(CResourceEditor* re, WORD id); +void free_loaded_icon(IconGroup icon); + +void set_icon(CResourceEditor* re, WORD wIconId, IconGroup icon1, IconGroup icon2); + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT +// returns the data of the uninstaller icon (inside filename) that should replace the installer icon data +LPBYTE generate_uninstall_icon_data(IconGroup icon1, IconGroup icon2, size_t &size); +// Fill the array of icons for uninstall with their offsets +int generate_unicons_offsets(LPBYTE exeHeader, size_t exeHeaderSize, LPBYTE uninstIconData, WORD wIconId); +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT + +#endif//_ICON_H_ diff --git a/Source/lang.cpp b/Source/lang.cpp index 586c81a..1bf316f 100755 --- a/Source/lang.cpp +++ b/Source/lang.cpp @@ -1,1108 +1,1108 @@ -/*
- * lang.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include "build.h"
-#include "util.h"
-#include "DialogTemplate.h"
-#include "exehead/resource.h"
-#include "version.h"
-
-using namespace std;
-
-// Default English strings. Should match NSIS_DEFAULT_LANG
-// Do not change the first string in every item, it's the LangString
-// name for usage in scripts.
-
-typedef enum {
- NONE_STATIC = 0,
- INSTALL_STATIC = 1,
- UNINSTALL_STATIC = 2,
- BOTH_STATIC = 3
-} STATICID;
-
-struct NLFString {
- char *szLangStringName;
- char *szDefault;
- STATICID eStaticID;
-};
-
-NLFString NLFStrings[NLF_STRINGS] = {
- {"^Branding", "Nullsoft Install System %s", BOTH_STATIC},
- {"^SetupCaption", "$(^Name) Setup", INSTALL_STATIC},
- {"^UninstallCaption", "$(^Name) Uninstall", UNINSTALL_STATIC},
- {"^LicenseSubCaption", ": License Agreement", NONE_STATIC},
- {"^ComponentsSubCaption", ": Installation Options", NONE_STATIC},
- {"^DirSubCaption", ": Installation Folder", NONE_STATIC},
- {"^InstallingSubCaption", ": Installing", NONE_STATIC},
- {"^CompletedSubCaption", ": Completed", NONE_STATIC},
- {"^UnComponentsSubCaption", ": Uninstallation Options", NONE_STATIC},
- {"^UnDirSubCaption", ": Uninstallation Folder", NONE_STATIC},
- {"^ConfirmSubCaption", ": Confirmation", NONE_STATIC},
- {"^UninstallingSubCaption", ": Uninstalling", NONE_STATIC},
- {"^UnCompletedSubCaption", ": Completed", NONE_STATIC},
- {"^BackBtn", "< &Back", NONE_STATIC},
- {"^NextBtn", "&Next >", NONE_STATIC},
- {"^AgreeBtn", "I &Agree", NONE_STATIC},
- {"^AcceptBtn", "I &accept the terms in the License Agreement", NONE_STATIC},
- {"^DontAcceptBtn", "I &do not accept the terms in the License Agreement", NONE_STATIC},
- {"^InstallBtn", "&Install", NONE_STATIC},
- {"^UninstallBtn", "&Uninstall", NONE_STATIC},
- {"^CancelBtn", "Cancel", NONE_STATIC},
- {"^CloseBtn", "&Close", NONE_STATIC},
- {"^BrowseBtn", "B&rowse...", NONE_STATIC},
- {"^ShowDetailsBtn", "Show &details", NONE_STATIC},
- {"^ClickNext", "Click Next to continue.", NONE_STATIC},
- {"^ClickInstall", "Click Install to start the installation.", NONE_STATIC},
- {"^ClickUninstall", "Click Uninstall to start the uninstallation.", NONE_STATIC},
- {"^Name", "Name", BOTH_STATIC},
- {"^NameDA", 0, NONE_STATIC}, // virtual
- {"^Completed", "Completed", NONE_STATIC},
- {"^LicenseText", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click I Agree.", NONE_STATIC},
- {"^LicenseTextCB", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK", NONE_STATIC},
- {"^LicenseTextRB", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK", NONE_STATIC},
- {"^UnLicenseText", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click I Agree.", NONE_STATIC},
- {"^UnLicenseTextCB", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK", NONE_STATIC},
- {"^UnLicenseTextRB", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK", NONE_STATIC},
- {"^LicenseData", 0, NONE_STATIC}, // virtual - not processed
- {"^Custom", "Custom", NONE_STATIC},
- {"^ComponentsText", "Check the components you want to install and uncheck the components you don't want to install. $_CLICK", NONE_STATIC},
- {"^ComponentsSubText1", "Select the type of install:", NONE_STATIC},
- {"^ComponentsSubText2_NoInstTypes", "Select components to install:", NONE_STATIC},
- {"^ComponentsSubText2", "Or, select the optional components you wish to install:", NONE_STATIC},
- {"^UnComponentsText", "Check the components you want to uninstall and uncheck the components you don't want to uninstall. $_CLICK", NONE_STATIC},
- {"^UnComponentsSubText1", "Select the type of uninstall:", NONE_STATIC},
- {"^UnComponentsSubText2_NoInstTypes", "Select components to uninstall:", NONE_STATIC},
- {"^UnComponentsSubText2", "Or, select the optional components you wish to uninstall:", NONE_STATIC},
- {"^DirText", "Setup will install $(^NameDA) in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK", NONE_STATIC},
- {"^DirSubText", "Destination Folder", NONE_STATIC},
- {"^DirBrowseText", "Select the folder to install $(^NameDA) in:", NONE_STATIC},
- {"^UnDirText", "Setup will uninstall $(^NameDA) from the following folder. To uninstall from a different folder, click Browse and select another folder. $_CLICK", NONE_STATIC},
- {"^UnDirSubText", "", NONE_STATIC},
- {"^UnDirBrowseText", "Select the folder to uninstall $(^NameDA) from:", NONE_STATIC},
- {"^SpaceAvailable", "Space available: ", BOTH_STATIC},
- {"^SpaceRequired", "Space required: ", BOTH_STATIC},
- {"^UninstallingText", "This wizard will uninstall $(^NameDA) from your computer. $_CLICK", NONE_STATIC},
- {"^UninstallingSubText", "Uninstalling from:", NONE_STATIC},
- {"^FileError", "Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Abort to stop the installation,\r\nRetry to try again, or\r\nIgnore to skip this file.", NONE_STATIC},
- {"^FileError_NoIgnore", "Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Retry to try again, or\r\nCancel to stop the installation.", NONE_STATIC},
- {"^CantWrite", "Can't write: ", BOTH_STATIC},
- {"^CopyFailed", "Copy failed", BOTH_STATIC},
- {"^CopyTo", "Copy to ", BOTH_STATIC},
- {"^Registering", "Registering: ", NONE_STATIC},
- {"^Unregistering", "Unregistering: ", NONE_STATIC},
- {"^SymbolNotFound", "Could not find symbol: ", BOTH_STATIC},
- {"^CouldNotLoad", "Could not load: ", BOTH_STATIC},
- {"^CreateFolder", "Create folder: ", BOTH_STATIC},
- {"^CreateShortcut", "Create shortcut: ", BOTH_STATIC},
- {"^CreatedUninstaller", "Created uninstaller: ", BOTH_STATIC},
- {"^Delete", "Delete file: ", BOTH_STATIC},
- {"^DeleteOnReboot", "Delete on reboot: ", BOTH_STATIC},
- {"^ErrorCreatingShortcut", "Error creating shortcut: ", BOTH_STATIC},
- {"^ErrorCreating", "Error creating: ", BOTH_STATIC},
- {"^ErrorDecompressing", "Error decompressing data! Corrupted installer?", BOTH_STATIC},
- {"^ErrorRegistering", "Error registering DLL", BOTH_STATIC},
- {"^ExecShell", "ExecShell: ", BOTH_STATIC},
- {"^Exec", "Execute: ", BOTH_STATIC},
- {"^Extract", "Extract: ", BOTH_STATIC},
- {"^ErrorWriting", "Extract: error writing to file ", BOTH_STATIC},
- {"^InvalidOpcode", "Installer corrupted: invalid opcode", BOTH_STATIC},
- {"^NoOLE", "No OLE for: ", BOTH_STATIC},
- {"^OutputFolder", "Output folder: ", BOTH_STATIC},
- {"^RemoveFolder", "Remove folder: ", BOTH_STATIC},
- {"^RenameOnReboot", "Rename on reboot: ", BOTH_STATIC},
- {"^Rename", "Rename: ", BOTH_STATIC},
- {"^Skipped", "Skipped: ", BOTH_STATIC},
- {"^CopyDetails", "Copy Details To Clipboard", BOTH_STATIC},
- {"^LogInstall", "Log install process", BOTH_STATIC},
- {"^Byte", "B", BOTH_STATIC},
- {"^Kilo", "K", BOTH_STATIC},
- {"^Mega", "M", BOTH_STATIC},
- {"^Giga", "G", BOTH_STATIC},
- {"^Font", "MS Shell Dlg", NONE_STATIC},
- {"^FontSize", "8", NONE_STATIC},
- {"^RTL", "0", NONE_STATIC},
- {"^Language", "English", NONE_STATIC}
-};
-
-// ==============
-// LangStringList
-// ==============
-
-LangStringList::LangStringList() {
- count = 0;
-}
-
-int LangStringList::add(const char *name, int *sn/*=0*/)
-{
- int pos = SortedStringListND<struct langstring>::add(name);
- if (pos == -1) return -1;
-
- ((struct langstring*)gr.get())[pos].sn = count;
- if (sn) *sn = count;
- count++;
- ((struct langstring*)gr.get())[pos].index = -1;
- ((struct langstring*)gr.get())[pos].uindex = -1;
- ((struct langstring*)gr.get())[pos].process = 1;
-
- return pos;
-}
-
-int LangStringList::get(char *name, int *sn/*=0*/, int *index/*=0*/, int *uindex/*=0*/, int *process/*=0*/)
-{
- if (index) *index = -1;
- if (uindex) *uindex = -1;
- if (sn) *sn = -1;
- int v=find(name);
- if (v==-1) return -1;
- if (index) *index = ((struct langstring*)gr.get())[v].index;
- if (uindex) *uindex = ((struct langstring*)gr.get())[v].uindex;
- if (sn) *sn = ((struct langstring*)gr.get())[v].sn;
- if (process) *process = ((struct langstring*)gr.get())[v].process;
- return v;
-}
-
-void LangStringList::set(int pos, int index/*=-1*/, int uindex/*=-1*/, int process/*=-1*/)
-{
- if ((unsigned int)pos > (gr.getlen() / sizeof(struct langstring)))
- return;
-
- struct langstring *data=(struct langstring *)gr.get();
-
- if (index >= 0)
- data[pos].index = index;
- if (uindex >= 0)
- data[pos].uindex = uindex;
- if (process >= 0)
- data[pos].process = process;
-}
-
-void LangStringList::set(char *name, int index, int uindex/*=-1*/, int process/*=-1*/)
-{
- set(get(name), index, uindex, process);
-}
-
-const char* LangStringList::pos2name(int pos)
-{
- struct langstring *data=(struct langstring *)gr.get();
-
- if ((unsigned int)pos > (gr.getlen() / sizeof(struct langstring)))
- return 0;
-
- return ((const char*)strings.get() + data[pos].name);
-}
-
-const char* LangStringList::offset2name(int name)
-{
- if ((unsigned int)name > (unsigned int)strings.getlen())
- return 0;
-
- return (const char*)strings.get() + name;
-}
-
-int LangStringList::getnum()
-{
- return gr.getlen() / sizeof(struct langstring);
-}
-
-int LangStringList::compare_index(const void *item1, const void *item2)
-{
- struct langstring *ls1 = (struct langstring *)item1;
- struct langstring *ls2 = (struct langstring *)item2;
-
- return ls1->index - ls2->index;
-}
-
-langstring* LangStringList::sort_index(int *num)
-{
- if (!num) return 0;
- sortbuf.resize(0);
- sortbuf.add(gr.get(), gr.getlen());
- *num = sortbuf.getlen() / sizeof(struct langstring);
- qsort(sortbuf.get(), *num, sizeof(struct langstring), compare_index);
- return (struct langstring*) sortbuf.get();
-}
-
-int LangStringList::compare_uindex(const void *item1, const void *item2)
-{
- struct langstring *ls1 = (struct langstring *)item1;
- struct langstring *ls2 = (struct langstring *)item2;
-
- return ls1->uindex - ls2->uindex;
-}
-
-langstring* LangStringList::sort_uindex(int *num)
-{
- if (!num) return 0;
- sortbuf.resize(0);
- sortbuf.add(gr.get(), gr.getlen());
- *num = sortbuf.getlen() / sizeof(struct langstring);
- qsort(sortbuf.get(), *num, sizeof(struct langstring), compare_uindex);
- return (struct langstring*) sortbuf.get();
-}
-
-// ============
-// StringsArray
-// ============
-
-StringsArray::StringsArray()
-{
- offsets.set_zeroing(1);
-
- strings.add("", sizeof(""));
-}
-
-void StringsArray::resize(int num)
-{
- offsets.resize(num * sizeof(int));
-}
-
-int StringsArray::set(int idx, char *str)
-{
- if (idx < 0)
- return 0;
-
- if (idx >= (int)(offsets.getlen() / sizeof(int)))
- resize(idx+1);
-
- int old = ((int*)offsets.get())[idx];
-
- ((int*)offsets.get())[idx] = strings.add(str, strlen(str) + 1);
-
- return old;
-}
-
-const char* StringsArray::get(int idx)
-{
- if ((unsigned int)idx >= (offsets.getlen() / sizeof(int)))
- return 0;
-
- return (const char *)strings.get() + ((int*)offsets.get())[idx];
-}
-
-// =========
-// CEXEBuild
-// =========
-
-void CEXEBuild::InitLangTables() {
- keep_ref = false;
-
- for (int i = 0; i < NLF_STRINGS; i++) {
- NLFRefs[i].iRef = 0;
- NLFRefs[i].iUnRef = 0;
-
-#ifdef NSIS_CONFIG_LOG
- if (i == NLF_NAME) {
- NLFRefs[i].iRef++;
- NLFRefs[i].iUnRef++;
- }
-#endif
-
- if (NLFStrings[i].eStaticID & INSTALL_STATIC) {
- set_uninstall_mode(0);
- DefineLangString(NLFStrings[i].szLangStringName);
- }
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (NLFStrings[i].eStaticID & UNINSTALL_STATIC) {
- set_uninstall_mode(1);
- DefineLangString(NLFStrings[i].szLangStringName);
- }
-#endif
- }
-
- set_uninstall_mode(0);
-
- keep_ref = true;
-}
-
-LanguageTable* CEXEBuild::GetLangTable(LANGID &lang, bool create/*=true*/) {
- int nlt = lang_tables.getlen() / sizeof(LanguageTable);
- LanguageTable *nla = (LanguageTable*)lang_tables.get();
-
- lang = lang ? lang : last_used_lang;
- LanguageTable *table = NULL;
-
- for (int i = 0; i < nlt; i++) {
- if (lang == nla[i].lang_id) {
- table = &nla[i];
- break;
- }
- }
- if (!table && create) {
- LanguageTable newtable;
-
- newtable.lang_id = lang;
- newtable.dlg_offset = 0;
- memset(&newtable.nlf, 0, sizeof(NLF));
-
- newtable.lang_strings = new StringsArray;
-
- lang_tables.add(&newtable, sizeof(LanguageTable));
- table = (LanguageTable*)lang_tables.get() + nlt;
- }
-
- if (table) // update last used language if a table was loaded
- last_used_lang = lang;
-
- return table;
-}
-
-char *CEXEBuild::GetLangNameAndCP(LANGID lang, unsigned int *codepage/*=NULL*/) {
- LanguageTable *table = GetLangTable(lang, false);
-
- if (table && table->nlf.m_bLoaded) {
- if (codepage)
- *codepage = table->nlf.m_uCodePage;
-
- return table->nlf.m_szName;
- }
- else {
- if (codepage)
- *codepage = 1252; // English US
-
- if (lang == 1033)
- return "English";
- else
- return "???";
- }
-}
-
-int CEXEBuild::DefineLangString(char *name, int process/*=-1*/) {
- int index, uindex, pos, ret, sn;
- pos = build_langstrings.get(name, &sn, &index, &uindex);
- if (pos < 0) {
- pos = build_langstrings.add(name);
- }
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!uninstall_mode) {
-#endif
- if (index < 0) {
- index = build_langstring_num++;
- }
- ret = -index - 1;
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- }
- else {
- if (uindex < 0) {
- uindex = ubuild_langstring_num++;
- }
- ret = -uindex - 1;
- }
-#endif
-
- build_langstrings.set(pos, index, uindex, process);
-
- // set reference count for NLF strings
- if (keep_ref && name[0] == '^') {
- for (int i = 0; i < NLF_STRINGS; i++) {
- if (!strcmp(name, NLFStrings[i].szLangStringName)) {
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode)
- NLFRefs[i].iUnRef++;
- else
-#endif
- NLFRefs[i].iRef++;
-
- break;
- }
- }
- }
-
- return ret;
-}
-
-int CEXEBuild::DefineInnerLangString(int id, int process/*=-1*/) {
- bool old_keep_ref = keep_ref;
-
- // set reference count for NLF strings
- if (keep_ref) {
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode)
- NLFRefs[id].iUnRef++;
- else
-#endif
- NLFRefs[id].iRef++;
-
- keep_ref = false;
- }
-
- int ret = DefineLangString(NLFStrings[id].szLangStringName, process);
-
- keep_ref = old_keep_ref;
-
- return ret;
-}
-
-int CEXEBuild::SetLangString(char *name, LANGID lang, char *string) {
- if (!string || !name) return PS_ERROR;
-
- LanguageTable *table = GetLangTable(lang);
- if (!table) return PS_ERROR;
-
- int sn;
-
- int pos = build_langstrings.get(name, &sn);
- if (pos < 0)
- pos = build_langstrings.add(name, &sn);
-
- if (table->lang_strings->set(sn, string))
- return PS_WARNING;
-
- return PS_OK;
-}
-
-int CEXEBuild::SetInnerString(int id, char *string) {
- if ((unsigned int)id >= NLF_STRINGS || !string) return PS_ERROR;
-
- int ret = PS_OK;
-
- const char *ps = UserInnerStrings.get(id);
- if (ps && *ps)
- ret = PS_WARNING;
-
- UserInnerStrings.set(id, string);
-
- return ret;
-}
-
-int CEXEBuild::GenerateLangTable(LanguageTable *lt, int num_lang_tables) {
- // Add all installer language strings
- int i, j, l, tabsset;
- struct langstring* lang_strings = NULL;
- TinyGrowBuf *string_ptrs = new TinyGrowBuf[num_lang_tables];
-
- tabsset = 1;
- while (tabsset)
- {
- tabsset = 0;
- for (i = num_lang_tables; i--; )
- {
- // Fill in default values for all used language strings that we can
- FillLanguageTable(<[i]);
- // Make sure the string lists are large enough
- string_ptrs[i].set_zeroing(1);
- if (!uninstall_mode)
- string_ptrs[i].resize(build_langstring_num * sizeof(int));
- else
- string_ptrs[i].resize(ubuild_langstring_num * sizeof(int));
- }
-
- // For all current language strings
- if (!uninstall_mode)
- lang_strings = build_langstrings.sort_index(&l);
- else
- lang_strings = build_langstrings.sort_uindex(&l);
-
- for (j = 0; j < l; j++)
- {
- int lang_string_index;
-
- if (!uninstall_mode)
- lang_string_index = lang_strings[j].index;
- else
- lang_string_index = lang_strings[j].uindex;
-
- // Is this language string used (in the installer)?
- if (lang_string_index >= 0)
- {
- // For each language
- for (i = num_lang_tables; i--; )
- {
- // Get the current string pointer
- int *ptr = (int *)string_ptrs[i].get() + lang_string_index;
- // Not already set?
- if (!*ptr)
- {
- // Get the language string and its name
- const char *str = lt[i].lang_strings->get(lang_strings[j].sn);
- const char *lsn = build_langstrings.offset2name(lang_strings[j].name);
- if (!str || !*str)
- {
- // No string is defined; give a warning (for user strings only)
- if (lsn[0] != '^')
- {
- if (lt[i].nlf.m_bLoaded)
- warning("LangString \"%s\" is not set in language table of language %s", lsn, lt[i].nlf.m_szName);
- else
- warning("LangString \"%s\" is not set in language table of language %d", lsn, lt[i].lang_id);
- }
- }
- else
- {
- // Add the language string to the string data block
- char fn[1024];
- sprintf(fn, "LangString %s", lsn);
- curfilename = fn;
- linecnt = lt[i].lang_id;
- *ptr = add_string(str, lang_strings[j].process, (WORD) lt[i].nlf.m_uCodePage);
- curfilename = 0;
- // Indicate that we should check again for any newly referenced language strings
- tabsset++;
- }
- }
- }
- }
- }
- }
-
- // Optimize langstrings and check for recursion
- for (i = num_lang_tables; i--; )
- {
- TinyGrowBuf rec;
- int *lst = (int *)string_ptrs[i].get();
-
- int langstring_num;
-
- if (!uninstall_mode)
- langstring_num = build_langstring_num;
- else
- langstring_num = ubuild_langstring_num;
-
- for (j = 0; j < langstring_num; j++)
- {
- // Does this string reference another language string directly?
- while (lst[j] < 0)
- {
- // Search through list of language string references
- for (l = 0; (unsigned int)l < rec.getlen() / sizeof(int); l++)
- {
- if (((int*)rec.get())[l] == lst[j])
- {
- // We have the index of a recursive language string; now find the name
- const char *name = "(unnamed)";
- for (l = 0; l < langstring_num; l++)
- {
- int index;
-
- if (!uninstall_mode)
- index = lang_strings[l].index;
- else
- index = lang_strings[l].uindex;
-
- if (lang_strings[l].index == j)
- {
- name = build_langstrings.offset2name(lang_strings[l].name);
- }
- }
- ERROR_MSG("Error: LangString %s is recursive!\n", name);
- delete [] string_ptrs;
- return PS_ERROR;
- }
- }
- // Add this reference to the list
- rec.add(&lst[j], sizeof(int));
- // and dereference it
- lst[j] = lst[-lst[j] - 1];
- }
- rec.resize(0);
- }
- }
-
- // Add language tables into their datablock
- for (i = num_lang_tables; i--; )
- {
- cur_langtables->add(<[i].lang_id, sizeof(LANGID));
- cur_langtables->add(<[i].dlg_offset, sizeof(int));
- int rtl = lt[i].nlf.m_bRTL ? 1 : 0;
- cur_langtables->add(&rtl, sizeof(int));
- cur_langtables->add(string_ptrs[i].get(), string_ptrs[i].getlen());
- string_ptrs[i].resize(0);
- }
-
- cur_header->blocks[NB_LANGTABLES].num = num_lang_tables;
- cur_header->langtable_size = cur_langtables->getlen() / num_lang_tables;
-
- delete [] string_ptrs;
-
- return PS_OK;
-}
-
-int CEXEBuild::GenerateLangTables() {
- int i;
- LanguageTable *lt = (LanguageTable*)lang_tables.get();
-
- SCRIPT_MSG("Generating language tables... ");
-
- if (
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- ubuild_langstring_num > MAX_CODED ||
-#endif
- build_langstring_num > MAX_CODED
- )
- {
- ERROR_MSG("\nError: too many LangStrings. Maximum allowed is %u.\n", MAX_CODED);
- return PS_ERROR;
- }
-
- // If we have no tables (user didn't set any string and didn't load any NLF) create the default one
- if (!lang_tables.getlen()) {
- LANGID lang = NSIS_DEFAULT_LANG;
- LanguageTable *table = GetLangTable(lang);
- if (!table) return PS_ERROR;
-
- lt = (LanguageTable*)lang_tables.get();
- }
-
- // Apply default font
- if (*build_font)
- {
- try {
- init_res_editor();
-
-#define ADD_FONT(id) { \
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \
- if (dlg) { \
- CDialogTemplate td(dlg); \
- res_editor->FreeResource(dlg); \
- td.SetFont(build_font, (WORD) build_font_size); \
- DWORD dwSize; \
- dlg = td.Save(dwSize); \
- res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, dlg, dwSize); \
- delete [] dlg; \
- } \
- }
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- ADD_FONT(IDD_LICENSE);
- ADD_FONT(IDD_LICENSE_FSRB);
- ADD_FONT(IDD_LICENSE_FSCB);
-#endif
- ADD_FONT(IDD_DIR);
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- ADD_FONT(IDD_SELCOM);
-#endif
- ADD_FONT(IDD_INST);
- ADD_FONT(IDD_INSTFILES);
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- ADD_FONT(IDD_UNINST);
-#endif
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- ADD_FONT(IDD_VERIFY);
-#endif
-#undef ADD_FONT
- }
- catch (exception& err) {
- ERROR_MSG("\nError while applying font: %s\n", err.what());
- return PS_ERROR;
- }
- }
-
- // Fill tables with defaults (if needed) and with instruction strings
- // Create language specific resources (currently only dialogs with different fonts)
- int num_lang_tables = lang_tables.getlen() / sizeof(LanguageTable);
- // if there is one string table then there is no need for two sets of dialogs
- int cur_offset = num_lang_tables == 1 ? 0 : 100;
- for (i = 0; i < num_lang_tables; i++)
- {
- if ((lt[i].nlf.m_szFont && !*build_font) || lt[i].nlf.m_bRTL)
- {
- lt[i].dlg_offset = cur_offset;
-
- char *font = lt[i].nlf.m_szFont;
- if (*build_font) font = 0;
-
- try {
- init_res_editor();
-
-#define ADD_FONT(id) { \
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \
- if (dlg) { \
- CDialogTemplate td(dlg,lt[i].nlf.m_uCodePage); \
- res_editor->FreeResource(dlg); \
- if (font) td.SetFont(font, (WORD) lt[i].nlf.m_iFontSize); \
- if (lt[i].nlf.m_bRTL) { \
- td.ConvertToRTL(); \
- DialogItemTemplate* dir = td.GetItem(IDC_DIR); \
- if (id == IDD_DIR && dir) { \
- if ((dir->dwStyle & ES_CENTER) == 0) dir->dwStyle ^= ES_RIGHT; \
- dir->dwExtStyle &= ~(WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR); \
- } \
- } \
- DWORD dwSize; \
- dlg = td.Save(dwSize); \
- res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id+cur_offset), NSIS_DEFAULT_LANG, dlg, dwSize); \
- delete [] dlg; \
- } \
- }
-
-#ifdef NSIS_CONFIG_LICENSEPAGE
- ADD_FONT(IDD_LICENSE);
- ADD_FONT(IDD_LICENSE_FSRB);
- ADD_FONT(IDD_LICENSE_FSCB);
-#endif
- ADD_FONT(IDD_DIR);
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- ADD_FONT(IDD_SELCOM);
-#endif
- ADD_FONT(IDD_INST);
- ADD_FONT(IDD_INSTFILES);
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- ADD_FONT(IDD_UNINST);
-#endif
-#ifdef NSIS_CONFIG_CRC_SUPPORT
- ADD_FONT(IDD_VERIFY);
-#endif
-#undef ADD_FONT
- }
- catch (exception& err) {
- ERROR_MSG("\nError while applying NLF font/RTL: %s\n", err.what());
- return PS_ERROR;
- }
-
- cur_offset += 100;
- }
- }
-
- int orig_uninstall_mode = uninstall_mode;
-
- set_uninstall_mode(0);
- if (GenerateLangTable(lt, num_lang_tables) != PS_OK)
- return PS_ERROR;
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- set_uninstall_mode(1);
- if (GenerateLangTable(lt, num_lang_tables) != PS_OK)
- return PS_ERROR;
-#endif
-
- set_uninstall_mode(orig_uninstall_mode);
-
- SCRIPT_MSG("Done!\n");
-
- return PS_OK;
-}
-
-void CEXEBuild::FillLanguageTable(LanguageTable *table) {
- for (int i = 0; i < NLF_STRINGS; i++) {
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!NLFRefs[i].iUnRef && !NLFRefs[i].iRef)
- continue;
-#else
- if (!NLFRefs[i].iRef)
- continue;
-#endif
-
- else if (i == NLF_SPACE_REQ || i == NLF_SPACE_AVAIL)
- {
- if (no_space_texts)
- {
- continue;
- }
- }
-
- int sn, index;
- int pos = build_langstrings.get(NLFStrings[i].szLangStringName, &sn, &index);
- if (pos >= 0) {
- const char *str = table->lang_strings->get(sn);
- if (!str || !*str) {
- const char *us = UserInnerStrings.get(i);
- if (i == NLF_NAME_DA && (!us || !*us))
- {
- // if the user didn't set NLF_NAME_DA we set it to $(^Name)
- table->lang_strings->set(sn, "$(^Name)");
- }
- if (us && *us) {
- table->lang_strings->set(sn, (char *) us);
- }
- else {
- char *dstr = table->nlf.m_szStrings[i] ? table->nlf.m_szStrings[i] : NLFStrings[i].szDefault;
- if (!dstr)
- continue;
- if (i == NLF_BRANDING) {
- char temp[NSIS_MAX_STRLEN + sizeof(NSIS_VERSION)];
- sprintf(temp, dstr, NSIS_VERSION);
- table->lang_strings->set(sn, temp);
- continue;
- }
- else if (i == NLF_FONT)
- {
- char *font = *build_font ? build_font : table->nlf.m_szFont;
- if (font)
- table->lang_strings->set(sn, font);
- else
- table->lang_strings->set(sn, dstr);
- continue;
- }
- else if (i == NLF_FONTSIZE)
- {
- WORD font_size = *build_font ? (WORD) build_font_size : (WORD) table->nlf.m_iFontSize;
- if (font_size)
- {
- char temp[64];
- sprintf(temp, "%d", font_size);
- table->lang_strings->set(sn, temp);
- }
- else
- table->lang_strings->set(sn, dstr);
- continue;
- }
- table->lang_strings->set(sn, dstr);
- }
- }
- }
- }
-}
-
-char SkipComments(FILE *f) {
- int c;
- while ((c = fgetc(f))) {
- while (c == '\n' || c == '\r') {
- c = fgetc(f); // Skip empty lines
- }
- if (c == '#' || c == ';') {
- while ((c = fgetc(f))) {
- if (c == '\n') break;
- }
- }
- else break;
- }
- return (char) c;
-}
-
-// NSIS Language File parser
-LanguageTable * CEXEBuild::LoadLangFile(char *filename) {
- FILE *f = FOPEN(filename, "r");
- if (!f) {
- ERROR_MSG("Error: Can't open language file - \"%s\"!\n",filename);
- return 0;
- }
-
- // Check header
- char buf[NSIS_MAX_STRLEN];
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
-
- if (strncmp(buf, "NLF v", 5)) {
- ERROR_MSG("Error: Invalid language file.\n");
- return 0;
- }
- int nlf_version = atoi(buf+5);
- if (nlf_version != NLF_VERSION) {
- if (nlf_version != 2 && nlf_version != 3 && nlf_version != 4 && nlf_version != 5) {
- ERROR_MSG("Error: Language file version doesn't match NSIS version.\n");
- return 0;
- }
- }
-
- // Get language ID
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- LANGID lang_id = atoi(buf);
-
- // Get appropriate table
- LanguageTable *table = GetLangTable(lang_id);
- if (!table)
- return 0;
-
- NLF *nlf = &table->nlf;
-
- if (nlf->m_bLoaded) {
- ERROR_MSG("Error: can't load same language file twice.\n");
- return 0;
- }
-
- // Generate language name
- char *p, *p2, t = 0;
-
- p = strrchr(filename, '.');
- if (p) {
- t = *p;
- *p = 0;
- }
- p2 = strrchr(filename, '\\');
- if (p2) {
- p2++;
- nlf->m_szName = (char*)malloc(strlen(p2)+1);
- strcpy(nlf->m_szName, p2);
- }
- else {
- nlf->m_szName = (char*)malloc(strlen(filename)+1);
- strcpy(nlf->m_szName, filename);
- }
- if (p) *p = t;
-
- if (nlf_version != NLF_VERSION) {
- warning_fl("%s language file version doesn't match. Using default English texts for missing strings.", nlf->m_szName);
- }
-
- // set ^Language
- nlf->m_szStrings[NLF_LANGUAGE] = strdup(nlf->m_szName);
-
- int temp;
-
- // Get font
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- if (!nlf->m_szFont) {
- temp=strlen(buf);
- while (buf[temp-1] == '\n' || buf[temp-1] == '\r') {
- buf[temp-1] = 0;
- temp--;
- }
- if (buf[0] != '-' || buf[1] != 0) {
- nlf->m_szFont = (char*)malloc(strlen(buf)+1);
- strcpy(nlf->m_szFont, buf);
- }
- }
-
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- if (!nlf->m_iFontSize) {
- if (buf[0] != '-' || buf[1] != 0) {
- nlf->m_iFontSize = atoi(buf);
- }
- }
-
- // Get code page
- nlf->m_uCodePage = CP_ACP;
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- if (buf[0] != '-' || buf[1] != 0) {
- nlf->m_uCodePage = atoi(buf);
- if (!IsValidCodePage(nlf->m_uCodePage))
- nlf->m_uCodePage = CP_ACP;
- }
-
- // Get RTL setting
- nlf->m_szStrings[NLF_RTL] = (char *)malloc(2);
- nlf->m_bRTL = false;
- buf[0] = SkipComments(f);
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- if (buf[0] == 'R' && buf[1] == 'T' && buf[2] == 'L' && (!buf[3] || buf[3] == '\r' || buf[3] == '\n')) {
- nlf->m_bRTL = true;
- strcpy(nlf->m_szStrings[NLF_RTL], "1");
- }
- else {
- strcpy(nlf->m_szStrings[NLF_RTL], "0");
- }
-
- // Read strings
- for (int i = 0; i < NLF_STRINGS_NO_SPECIAL; i++) {
-
- // skip virtual strings
- if (!NLFStrings[i].szDefault)
- continue;
-
- // Fill in for missing strings
- // 0 will mean default will be used from NLFStrings
- switch (i) {
- case NLF_BTN_LICENSE_AGREE:
- case NLF_BTN_LICENSE_DISAGREE:
- if (nlf_version >= 3) break;
- case NLF_LOG_INSTALL_PROCESS:
- case NLF_BYTE:
- case NLF_KILO:
- case NLF_MEGA:
- case NLF_GIGA:
- case NLF_REGISTERING:
- case NLF_UNREGISTERING:
- if (nlf_version >= 4) break;
- case NLF_FILE_ERROR_NOIGNORE:
- if (nlf_version >= 5) break;
- case NLF_USUBCAPTION_OPTIONS:
- case NLF_USUBCAPTION_DIR:
- case NLF_CLICK_NEXT:
- case NLF_CLICK_INSTALL:
- case NLF_CLICK_UNINSTALL:
- case NLF_LICENSE_TEXT:
- case NLF_LICENSE_TEXT_FSCB:
- case NLF_LICENSE_TEXT_FSRB:
- case NLF_ULICENSE_TEXT:
- case NLF_ULICENSE_TEXT_FSCB:
- case NLF_ULICENSE_TEXT_FSRB:
- case NLF_COMP_TEXT:
- case NLF_UCOMP_TEXT:
- case NLF_UCOMP_SUBTEXT1:
- case NLF_UCOMP_SUBTEXT1_NO_INST_TYPES:
- case NLF_UCOMP_SUBTEXT2:
- case NLF_DIR_TEXT:
- case NLF_DIR_BROWSETEXT:
- case NLF_UDIR_TEXT:
- case NLF_UDIR_SUBTEXT:
- case NLF_UDIR_BROWSETEXT:
- case NLF_UNINST_TEXT:
- if (nlf_version >= 6) break;
- nlf->m_szStrings[i] = 0;
- continue;
- }
-
- buf[0] = SkipComments(f);
-
- fgets(buf+1, NSIS_MAX_STRLEN, f);
- if (strlen(buf) == NSIS_MAX_STRLEN-1) {
- ERROR_MSG("Error: String too long (string #%d - \"%s\")", i, NLFStrings[i].szLangStringName);
- return 0;
- }
- temp=strlen(buf);
-
- while (buf[temp-1] == '\n' || buf[temp-1] == '\r') {
- buf[--temp] = 0;
- }
-
- char *in = buf;
-
- // trim quotes
- if (buf[0] == '"' && buf[temp-1] == '"') {
- in++;
- buf[--temp] = 0;
- }
-
- nlf->m_szStrings[i] = (char*)malloc(temp+1);
- char *out;
- for (out = nlf->m_szStrings[i]; *in; in++, out++) {
- if (*in == '\\') {
- in++;
- switch (*in) {
- case 'n':
- *out = '\n';
- break;
- case 'r':
- *out = '\r';
- break;
- case 't':
- *out = '\t';
- break;
- default:
- *out++ = '\\';
- *out = *in;
- }
- }
- else *out = *in;
- }
- *out = 0;
- }
- fclose(f);
-
- nlf->m_bLoaded = true;
-
- return table;
-}
-
-void CEXEBuild::DeleteLangTable(LanguageTable *table) {
- if (table->nlf.m_szName)
- free(table->nlf.m_szName);
- if (table->nlf.m_szFont)
- free(table->nlf.m_szFont);
- delete table->lang_strings;
- for (int i = 0; i < NLF_STRINGS; i++) {
- if (table->nlf.m_szStrings[i])
- free(table->nlf.m_szStrings[i]);
- }
-}
+/* + * lang.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <stdio.h> +#include <stdlib.h> +#include "build.h" +#include "util.h" +#include "DialogTemplate.h" +#include "exehead/resource.h" +#include "version.h" + +using namespace std; + +// Default English strings. Should match NSIS_DEFAULT_LANG +// Do not change the first string in every item, it's the LangString +// name for usage in scripts. + +typedef enum { + NONE_STATIC = 0, + INSTALL_STATIC = 1, + UNINSTALL_STATIC = 2, + BOTH_STATIC = 3 +} STATICID; + +struct NLFString { + char *szLangStringName; + char *szDefault; + STATICID eStaticID; +}; + +NLFString NLFStrings[NLF_STRINGS] = { + {"^Branding", "Nullsoft Install System %s", BOTH_STATIC}, + {"^SetupCaption", "$(^Name) Setup", INSTALL_STATIC}, + {"^UninstallCaption", "$(^Name) Uninstall", UNINSTALL_STATIC}, + {"^LicenseSubCaption", ": License Agreement", NONE_STATIC}, + {"^ComponentsSubCaption", ": Installation Options", NONE_STATIC}, + {"^DirSubCaption", ": Installation Folder", NONE_STATIC}, + {"^InstallingSubCaption", ": Installing", NONE_STATIC}, + {"^CompletedSubCaption", ": Completed", NONE_STATIC}, + {"^UnComponentsSubCaption", ": Uninstallation Options", NONE_STATIC}, + {"^UnDirSubCaption", ": Uninstallation Folder", NONE_STATIC}, + {"^ConfirmSubCaption", ": Confirmation", NONE_STATIC}, + {"^UninstallingSubCaption", ": Uninstalling", NONE_STATIC}, + {"^UnCompletedSubCaption", ": Completed", NONE_STATIC}, + {"^BackBtn", "< &Back", NONE_STATIC}, + {"^NextBtn", "&Next >", NONE_STATIC}, + {"^AgreeBtn", "I &Agree", NONE_STATIC}, + {"^AcceptBtn", "I &accept the terms in the License Agreement", NONE_STATIC}, + {"^DontAcceptBtn", "I &do not accept the terms in the License Agreement", NONE_STATIC}, + {"^InstallBtn", "&Install", NONE_STATIC}, + {"^UninstallBtn", "&Uninstall", NONE_STATIC}, + {"^CancelBtn", "Cancel", NONE_STATIC}, + {"^CloseBtn", "&Close", NONE_STATIC}, + {"^BrowseBtn", "B&rowse...", NONE_STATIC}, + {"^ShowDetailsBtn", "Show &details", NONE_STATIC}, + {"^ClickNext", "Click Next to continue.", NONE_STATIC}, + {"^ClickInstall", "Click Install to start the installation.", NONE_STATIC}, + {"^ClickUninstall", "Click Uninstall to start the uninstallation.", NONE_STATIC}, + {"^Name", "Name", BOTH_STATIC}, + {"^NameDA", 0, NONE_STATIC}, // virtual + {"^Completed", "Completed", NONE_STATIC}, + {"^LicenseText", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click I Agree.", NONE_STATIC}, + {"^LicenseTextCB", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK", NONE_STATIC}, + {"^LicenseTextRB", "Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK", NONE_STATIC}, + {"^UnLicenseText", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click I Agree.", NONE_STATIC}, + {"^UnLicenseTextCB", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK", NONE_STATIC}, + {"^UnLicenseTextRB", "Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK", NONE_STATIC}, + {"^LicenseData", 0, NONE_STATIC}, // virtual - not processed + {"^Custom", "Custom", NONE_STATIC}, + {"^ComponentsText", "Check the components you want to install and uncheck the components you don't want to install. $_CLICK", NONE_STATIC}, + {"^ComponentsSubText1", "Select the type of install:", NONE_STATIC}, + {"^ComponentsSubText2_NoInstTypes", "Select components to install:", NONE_STATIC}, + {"^ComponentsSubText2", "Or, select the optional components you wish to install:", NONE_STATIC}, + {"^UnComponentsText", "Check the components you want to uninstall and uncheck the components you don't want to uninstall. $_CLICK", NONE_STATIC}, + {"^UnComponentsSubText1", "Select the type of uninstall:", NONE_STATIC}, + {"^UnComponentsSubText2_NoInstTypes", "Select components to uninstall:", NONE_STATIC}, + {"^UnComponentsSubText2", "Or, select the optional components you wish to uninstall:", NONE_STATIC}, + {"^DirText", "Setup will install $(^NameDA) in the following folder. To install in a different folder, click Browse and select another folder. $_CLICK", NONE_STATIC}, + {"^DirSubText", "Destination Folder", NONE_STATIC}, + {"^DirBrowseText", "Select the folder to install $(^NameDA) in:", NONE_STATIC}, + {"^UnDirText", "Setup will uninstall $(^NameDA) from the following folder. To uninstall from a different folder, click Browse and select another folder. $_CLICK", NONE_STATIC}, + {"^UnDirSubText", "", NONE_STATIC}, + {"^UnDirBrowseText", "Select the folder to uninstall $(^NameDA) from:", NONE_STATIC}, + {"^SpaceAvailable", "Space available: ", BOTH_STATIC}, + {"^SpaceRequired", "Space required: ", BOTH_STATIC}, + {"^UninstallingText", "This wizard will uninstall $(^NameDA) from your computer. $_CLICK", NONE_STATIC}, + {"^UninstallingSubText", "Uninstalling from:", NONE_STATIC}, + {"^FileError", "Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Abort to stop the installation,\r\nRetry to try again, or\r\nIgnore to skip this file.", NONE_STATIC}, + {"^FileError_NoIgnore", "Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Retry to try again, or\r\nCancel to stop the installation.", NONE_STATIC}, + {"^CantWrite", "Can't write: ", BOTH_STATIC}, + {"^CopyFailed", "Copy failed", BOTH_STATIC}, + {"^CopyTo", "Copy to ", BOTH_STATIC}, + {"^Registering", "Registering: ", NONE_STATIC}, + {"^Unregistering", "Unregistering: ", NONE_STATIC}, + {"^SymbolNotFound", "Could not find symbol: ", BOTH_STATIC}, + {"^CouldNotLoad", "Could not load: ", BOTH_STATIC}, + {"^CreateFolder", "Create folder: ", BOTH_STATIC}, + {"^CreateShortcut", "Create shortcut: ", BOTH_STATIC}, + {"^CreatedUninstaller", "Created uninstaller: ", BOTH_STATIC}, + {"^Delete", "Delete file: ", BOTH_STATIC}, + {"^DeleteOnReboot", "Delete on reboot: ", BOTH_STATIC}, + {"^ErrorCreatingShortcut", "Error creating shortcut: ", BOTH_STATIC}, + {"^ErrorCreating", "Error creating: ", BOTH_STATIC}, + {"^ErrorDecompressing", "Error decompressing data! Corrupted installer?", BOTH_STATIC}, + {"^ErrorRegistering", "Error registering DLL", BOTH_STATIC}, + {"^ExecShell", "ExecShell: ", BOTH_STATIC}, + {"^Exec", "Execute: ", BOTH_STATIC}, + {"^Extract", "Extract: ", BOTH_STATIC}, + {"^ErrorWriting", "Extract: error writing to file ", BOTH_STATIC}, + {"^InvalidOpcode", "Installer corrupted: invalid opcode", BOTH_STATIC}, + {"^NoOLE", "No OLE for: ", BOTH_STATIC}, + {"^OutputFolder", "Output folder: ", BOTH_STATIC}, + {"^RemoveFolder", "Remove folder: ", BOTH_STATIC}, + {"^RenameOnReboot", "Rename on reboot: ", BOTH_STATIC}, + {"^Rename", "Rename: ", BOTH_STATIC}, + {"^Skipped", "Skipped: ", BOTH_STATIC}, + {"^CopyDetails", "Copy Details To Clipboard", BOTH_STATIC}, + {"^LogInstall", "Log install process", BOTH_STATIC}, + {"^Byte", "B", BOTH_STATIC}, + {"^Kilo", "K", BOTH_STATIC}, + {"^Mega", "M", BOTH_STATIC}, + {"^Giga", "G", BOTH_STATIC}, + {"^Font", "MS Shell Dlg", NONE_STATIC}, + {"^FontSize", "8", NONE_STATIC}, + {"^RTL", "0", NONE_STATIC}, + {"^Language", "English", NONE_STATIC} +}; + +// ============== +// LangStringList +// ============== + +LangStringList::LangStringList() { + count = 0; +} + +int LangStringList::add(const char *name, int *sn/*=0*/) +{ + int pos = SortedStringListND<struct langstring>::add(name); + if (pos == -1) return -1; + + ((struct langstring*)gr.get())[pos].sn = count; + if (sn) *sn = count; + count++; + ((struct langstring*)gr.get())[pos].index = -1; + ((struct langstring*)gr.get())[pos].uindex = -1; + ((struct langstring*)gr.get())[pos].process = 1; + + return pos; +} + +int LangStringList::get(char *name, int *sn/*=0*/, int *index/*=0*/, int *uindex/*=0*/, int *process/*=0*/) +{ + if (index) *index = -1; + if (uindex) *uindex = -1; + if (sn) *sn = -1; + int v=find(name); + if (v==-1) return -1; + if (index) *index = ((struct langstring*)gr.get())[v].index; + if (uindex) *uindex = ((struct langstring*)gr.get())[v].uindex; + if (sn) *sn = ((struct langstring*)gr.get())[v].sn; + if (process) *process = ((struct langstring*)gr.get())[v].process; + return v; +} + +void LangStringList::set(int pos, int index/*=-1*/, int uindex/*=-1*/, int process/*=-1*/) +{ + if ((unsigned int)pos > (gr.getlen() / sizeof(struct langstring))) + return; + + struct langstring *data=(struct langstring *)gr.get(); + + if (index >= 0) + data[pos].index = index; + if (uindex >= 0) + data[pos].uindex = uindex; + if (process >= 0) + data[pos].process = process; +} + +void LangStringList::set(char *name, int index, int uindex/*=-1*/, int process/*=-1*/) +{ + set(get(name), index, uindex, process); +} + +const char* LangStringList::pos2name(int pos) +{ + struct langstring *data=(struct langstring *)gr.get(); + + if ((unsigned int)pos > (gr.getlen() / sizeof(struct langstring))) + return 0; + + return ((const char*)strings.get() + data[pos].name); +} + +const char* LangStringList::offset2name(int name) +{ + if ((unsigned int)name > (unsigned int)strings.getlen()) + return 0; + + return (const char*)strings.get() + name; +} + +int LangStringList::getnum() +{ + return gr.getlen() / sizeof(struct langstring); +} + +int LangStringList::compare_index(const void *item1, const void *item2) +{ + struct langstring *ls1 = (struct langstring *)item1; + struct langstring *ls2 = (struct langstring *)item2; + + return ls1->index - ls2->index; +} + +langstring* LangStringList::sort_index(int *num) +{ + if (!num) return 0; + sortbuf.resize(0); + sortbuf.add(gr.get(), gr.getlen()); + *num = sortbuf.getlen() / sizeof(struct langstring); + qsort(sortbuf.get(), *num, sizeof(struct langstring), compare_index); + return (struct langstring*) sortbuf.get(); +} + +int LangStringList::compare_uindex(const void *item1, const void *item2) +{ + struct langstring *ls1 = (struct langstring *)item1; + struct langstring *ls2 = (struct langstring *)item2; + + return ls1->uindex - ls2->uindex; +} + +langstring* LangStringList::sort_uindex(int *num) +{ + if (!num) return 0; + sortbuf.resize(0); + sortbuf.add(gr.get(), gr.getlen()); + *num = sortbuf.getlen() / sizeof(struct langstring); + qsort(sortbuf.get(), *num, sizeof(struct langstring), compare_uindex); + return (struct langstring*) sortbuf.get(); +} + +// ============ +// StringsArray +// ============ + +StringsArray::StringsArray() +{ + offsets.set_zeroing(1); + + strings.add("", sizeof("")); +} + +void StringsArray::resize(int num) +{ + offsets.resize(num * sizeof(int)); +} + +int StringsArray::set(int idx, char *str) +{ + if (idx < 0) + return 0; + + if (idx >= (int)(offsets.getlen() / sizeof(int))) + resize(idx+1); + + int old = ((int*)offsets.get())[idx]; + + ((int*)offsets.get())[idx] = strings.add(str, strlen(str) + 1); + + return old; +} + +const char* StringsArray::get(int idx) +{ + if ((unsigned int)idx >= (offsets.getlen() / sizeof(int))) + return 0; + + return (const char *)strings.get() + ((int*)offsets.get())[idx]; +} + +// ========= +// CEXEBuild +// ========= + +void CEXEBuild::InitLangTables() { + keep_ref = false; + + for (int i = 0; i < NLF_STRINGS; i++) { + NLFRefs[i].iRef = 0; + NLFRefs[i].iUnRef = 0; + +#ifdef NSIS_CONFIG_LOG + if (i == NLF_NAME) { + NLFRefs[i].iRef++; + NLFRefs[i].iUnRef++; + } +#endif + + if (NLFStrings[i].eStaticID & INSTALL_STATIC) { + set_uninstall_mode(0); + DefineLangString(NLFStrings[i].szLangStringName); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (NLFStrings[i].eStaticID & UNINSTALL_STATIC) { + set_uninstall_mode(1); + DefineLangString(NLFStrings[i].szLangStringName); + } +#endif + } + + set_uninstall_mode(0); + + keep_ref = true; +} + +LanguageTable* CEXEBuild::GetLangTable(LANGID &lang, bool create/*=true*/) { + int nlt = lang_tables.getlen() / sizeof(LanguageTable); + LanguageTable *nla = (LanguageTable*)lang_tables.get(); + + lang = lang ? lang : last_used_lang; + LanguageTable *table = NULL; + + for (int i = 0; i < nlt; i++) { + if (lang == nla[i].lang_id) { + table = &nla[i]; + break; + } + } + if (!table && create) { + LanguageTable newtable; + + newtable.lang_id = lang; + newtable.dlg_offset = 0; + memset(&newtable.nlf, 0, sizeof(NLF)); + + newtable.lang_strings = new StringsArray; + + lang_tables.add(&newtable, sizeof(LanguageTable)); + table = (LanguageTable*)lang_tables.get() + nlt; + } + + if (table) // update last used language if a table was loaded + last_used_lang = lang; + + return table; +} + +char *CEXEBuild::GetLangNameAndCP(LANGID lang, unsigned int *codepage/*=NULL*/) { + LanguageTable *table = GetLangTable(lang, false); + + if (table && table->nlf.m_bLoaded) { + if (codepage) + *codepage = table->nlf.m_uCodePage; + + return table->nlf.m_szName; + } + else { + if (codepage) + *codepage = 1252; // English US + + if (lang == 1033) + return "English"; + else + return "???"; + } +} + +int CEXEBuild::DefineLangString(char *name, int process/*=-1*/) { + int index, uindex, pos, ret, sn; + pos = build_langstrings.get(name, &sn, &index, &uindex); + if (pos < 0) { + pos = build_langstrings.add(name); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!uninstall_mode) { +#endif + if (index < 0) { + index = build_langstring_num++; + } + ret = -index - 1; +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + } + else { + if (uindex < 0) { + uindex = ubuild_langstring_num++; + } + ret = -uindex - 1; + } +#endif + + build_langstrings.set(pos, index, uindex, process); + + // set reference count for NLF strings + if (keep_ref && name[0] == '^') { + for (int i = 0; i < NLF_STRINGS; i++) { + if (!strcmp(name, NLFStrings[i].szLangStringName)) { +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode) + NLFRefs[i].iUnRef++; + else +#endif + NLFRefs[i].iRef++; + + break; + } + } + } + + return ret; +} + +int CEXEBuild::DefineInnerLangString(int id, int process/*=-1*/) { + bool old_keep_ref = keep_ref; + + // set reference count for NLF strings + if (keep_ref) { +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode) + NLFRefs[id].iUnRef++; + else +#endif + NLFRefs[id].iRef++; + + keep_ref = false; + } + + int ret = DefineLangString(NLFStrings[id].szLangStringName, process); + + keep_ref = old_keep_ref; + + return ret; +} + +int CEXEBuild::SetLangString(char *name, LANGID lang, char *string) { + if (!string || !name) return PS_ERROR; + + LanguageTable *table = GetLangTable(lang); + if (!table) return PS_ERROR; + + int sn; + + int pos = build_langstrings.get(name, &sn); + if (pos < 0) + pos = build_langstrings.add(name, &sn); + + if (table->lang_strings->set(sn, string)) + return PS_WARNING; + + return PS_OK; +} + +int CEXEBuild::SetInnerString(int id, char *string) { + if ((unsigned int)id >= NLF_STRINGS || !string) return PS_ERROR; + + int ret = PS_OK; + + const char *ps = UserInnerStrings.get(id); + if (ps && *ps) + ret = PS_WARNING; + + UserInnerStrings.set(id, string); + + return ret; +} + +int CEXEBuild::GenerateLangTable(LanguageTable *lt, int num_lang_tables) { + // Add all installer language strings + int i, j, l, tabsset; + struct langstring* lang_strings = NULL; + TinyGrowBuf *string_ptrs = new TinyGrowBuf[num_lang_tables]; + + tabsset = 1; + while (tabsset) + { + tabsset = 0; + for (i = num_lang_tables; i--; ) + { + // Fill in default values for all used language strings that we can + FillLanguageTable(<[i]); + // Make sure the string lists are large enough + string_ptrs[i].set_zeroing(1); + if (!uninstall_mode) + string_ptrs[i].resize(build_langstring_num * sizeof(int)); + else + string_ptrs[i].resize(ubuild_langstring_num * sizeof(int)); + } + + // For all current language strings + if (!uninstall_mode) + lang_strings = build_langstrings.sort_index(&l); + else + lang_strings = build_langstrings.sort_uindex(&l); + + for (j = 0; j < l; j++) + { + int lang_string_index; + + if (!uninstall_mode) + lang_string_index = lang_strings[j].index; + else + lang_string_index = lang_strings[j].uindex; + + // Is this language string used (in the installer)? + if (lang_string_index >= 0) + { + // For each language + for (i = num_lang_tables; i--; ) + { + // Get the current string pointer + int *ptr = (int *)string_ptrs[i].get() + lang_string_index; + // Not already set? + if (!*ptr) + { + // Get the language string and its name + const char *str = lt[i].lang_strings->get(lang_strings[j].sn); + const char *lsn = build_langstrings.offset2name(lang_strings[j].name); + if (!str || !*str) + { + // No string is defined; give a warning (for user strings only) + if (lsn[0] != '^') + { + if (lt[i].nlf.m_bLoaded) + warning("LangString \"%s\" is not set in language table of language %s", lsn, lt[i].nlf.m_szName); + else + warning("LangString \"%s\" is not set in language table of language %d", lsn, lt[i].lang_id); + } + } + else + { + // Add the language string to the string data block + char fn[1024]; + sprintf(fn, "LangString %s", lsn); + curfilename = fn; + linecnt = lt[i].lang_id; + *ptr = add_string(str, lang_strings[j].process, (WORD) lt[i].nlf.m_uCodePage); + curfilename = 0; + // Indicate that we should check again for any newly referenced language strings + tabsset++; + } + } + } + } + } + } + + // Optimize langstrings and check for recursion + for (i = num_lang_tables; i--; ) + { + TinyGrowBuf rec; + int *lst = (int *)string_ptrs[i].get(); + + int langstring_num; + + if (!uninstall_mode) + langstring_num = build_langstring_num; + else + langstring_num = ubuild_langstring_num; + + for (j = 0; j < langstring_num; j++) + { + // Does this string reference another language string directly? + while (lst[j] < 0) + { + // Search through list of language string references + for (l = 0; (unsigned int)l < rec.getlen() / sizeof(int); l++) + { + if (((int*)rec.get())[l] == lst[j]) + { + // We have the index of a recursive language string; now find the name + const char *name = "(unnamed)"; + for (l = 0; l < langstring_num; l++) + { + int index; + + if (!uninstall_mode) + index = lang_strings[l].index; + else + index = lang_strings[l].uindex; + + if (lang_strings[l].index == j) + { + name = build_langstrings.offset2name(lang_strings[l].name); + } + } + ERROR_MSG("Error: LangString %s is recursive!\n", name); + delete [] string_ptrs; + return PS_ERROR; + } + } + // Add this reference to the list + rec.add(&lst[j], sizeof(int)); + // and dereference it + lst[j] = lst[-lst[j] - 1]; + } + rec.resize(0); + } + } + + // Add language tables into their datablock + for (i = num_lang_tables; i--; ) + { + cur_langtables->add(<[i].lang_id, sizeof(LANGID)); + cur_langtables->add(<[i].dlg_offset, sizeof(int)); + int rtl = lt[i].nlf.m_bRTL ? 1 : 0; + cur_langtables->add(&rtl, sizeof(int)); + cur_langtables->add(string_ptrs[i].get(), string_ptrs[i].getlen()); + string_ptrs[i].resize(0); + } + + cur_header->blocks[NB_LANGTABLES].num = num_lang_tables; + cur_header->langtable_size = cur_langtables->getlen() / num_lang_tables; + + delete [] string_ptrs; + + return PS_OK; +} + +int CEXEBuild::GenerateLangTables() { + int i; + LanguageTable *lt = (LanguageTable*)lang_tables.get(); + + SCRIPT_MSG("Generating language tables... "); + + if ( +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + ubuild_langstring_num > MAX_CODED || +#endif + build_langstring_num > MAX_CODED + ) + { + ERROR_MSG("\nError: too many LangStrings. Maximum allowed is %u.\n", MAX_CODED); + return PS_ERROR; + } + + // If we have no tables (user didn't set any string and didn't load any NLF) create the default one + if (!lang_tables.getlen()) { + LANGID lang = NSIS_DEFAULT_LANG; + LanguageTable *table = GetLangTable(lang); + if (!table) return PS_ERROR; + + lt = (LanguageTable*)lang_tables.get(); + } + + // Apply default font + if (*build_font) + { + try { + init_res_editor(); + +#define ADD_FONT(id) { \ + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \ + if (dlg) { \ + CDialogTemplate td(dlg); \ + res_editor->FreeResource(dlg); \ + td.SetFont(build_font, (WORD) build_font_size); \ + DWORD dwSize; \ + dlg = td.Save(dwSize); \ + res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, dlg, dwSize); \ + delete [] dlg; \ + } \ + } + +#ifdef NSIS_CONFIG_LICENSEPAGE + ADD_FONT(IDD_LICENSE); + ADD_FONT(IDD_LICENSE_FSRB); + ADD_FONT(IDD_LICENSE_FSCB); +#endif + ADD_FONT(IDD_DIR); +#ifdef NSIS_CONFIG_COMPONENTPAGE + ADD_FONT(IDD_SELCOM); +#endif + ADD_FONT(IDD_INST); + ADD_FONT(IDD_INSTFILES); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + ADD_FONT(IDD_UNINST); +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT + ADD_FONT(IDD_VERIFY); +#endif +#undef ADD_FONT + } + catch (exception& err) { + ERROR_MSG("\nError while applying font: %s\n", err.what()); + return PS_ERROR; + } + } + + // Fill tables with defaults (if needed) and with instruction strings + // Create language specific resources (currently only dialogs with different fonts) + int num_lang_tables = lang_tables.getlen() / sizeof(LanguageTable); + // if there is one string table then there is no need for two sets of dialogs + int cur_offset = num_lang_tables == 1 ? 0 : 100; + for (i = 0; i < num_lang_tables; i++) + { + if ((lt[i].nlf.m_szFont && !*build_font) || lt[i].nlf.m_bRTL) + { + lt[i].dlg_offset = cur_offset; + + char *font = lt[i].nlf.m_szFont; + if (*build_font) font = 0; + + try { + init_res_editor(); + +#define ADD_FONT(id) { \ + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG); \ + if (dlg) { \ + CDialogTemplate td(dlg,lt[i].nlf.m_uCodePage); \ + res_editor->FreeResource(dlg); \ + if (font) td.SetFont(font, (WORD) lt[i].nlf.m_iFontSize); \ + if (lt[i].nlf.m_bRTL) { \ + td.ConvertToRTL(); \ + DialogItemTemplate* dir = td.GetItem(IDC_DIR); \ + if (id == IDD_DIR && dir) { \ + if ((dir->dwStyle & ES_CENTER) == 0) dir->dwStyle ^= ES_RIGHT; \ + dir->dwExtStyle &= ~(WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR); \ + } \ + } \ + DWORD dwSize; \ + dlg = td.Save(dwSize); \ + res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(id+cur_offset), NSIS_DEFAULT_LANG, dlg, dwSize); \ + delete [] dlg; \ + } \ + } + +#ifdef NSIS_CONFIG_LICENSEPAGE + ADD_FONT(IDD_LICENSE); + ADD_FONT(IDD_LICENSE_FSRB); + ADD_FONT(IDD_LICENSE_FSCB); +#endif + ADD_FONT(IDD_DIR); +#ifdef NSIS_CONFIG_COMPONENTPAGE + ADD_FONT(IDD_SELCOM); +#endif + ADD_FONT(IDD_INST); + ADD_FONT(IDD_INSTFILES); +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + ADD_FONT(IDD_UNINST); +#endif +#ifdef NSIS_CONFIG_CRC_SUPPORT + ADD_FONT(IDD_VERIFY); +#endif +#undef ADD_FONT + } + catch (exception& err) { + ERROR_MSG("\nError while applying NLF font/RTL: %s\n", err.what()); + return PS_ERROR; + } + + cur_offset += 100; + } + } + + int orig_uninstall_mode = uninstall_mode; + + set_uninstall_mode(0); + if (GenerateLangTable(lt, num_lang_tables) != PS_OK) + return PS_ERROR; + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + set_uninstall_mode(1); + if (GenerateLangTable(lt, num_lang_tables) != PS_OK) + return PS_ERROR; +#endif + + set_uninstall_mode(orig_uninstall_mode); + + SCRIPT_MSG("Done!\n"); + + return PS_OK; +} + +void CEXEBuild::FillLanguageTable(LanguageTable *table) { + for (int i = 0; i < NLF_STRINGS; i++) { +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!NLFRefs[i].iUnRef && !NLFRefs[i].iRef) + continue; +#else + if (!NLFRefs[i].iRef) + continue; +#endif + + else if (i == NLF_SPACE_REQ || i == NLF_SPACE_AVAIL) + { + if (no_space_texts) + { + continue; + } + } + + int sn, index; + int pos = build_langstrings.get(NLFStrings[i].szLangStringName, &sn, &index); + if (pos >= 0) { + const char *str = table->lang_strings->get(sn); + if (!str || !*str) { + const char *us = UserInnerStrings.get(i); + if (i == NLF_NAME_DA && (!us || !*us)) + { + // if the user didn't set NLF_NAME_DA we set it to $(^Name) + table->lang_strings->set(sn, "$(^Name)"); + } + if (us && *us) { + table->lang_strings->set(sn, (char *) us); + } + else { + char *dstr = table->nlf.m_szStrings[i] ? table->nlf.m_szStrings[i] : NLFStrings[i].szDefault; + if (!dstr) + continue; + if (i == NLF_BRANDING) { + char temp[NSIS_MAX_STRLEN + sizeof(NSIS_VERSION)]; + sprintf(temp, dstr, NSIS_VERSION); + table->lang_strings->set(sn, temp); + continue; + } + else if (i == NLF_FONT) + { + char *font = *build_font ? build_font : table->nlf.m_szFont; + if (font) + table->lang_strings->set(sn, font); + else + table->lang_strings->set(sn, dstr); + continue; + } + else if (i == NLF_FONTSIZE) + { + WORD font_size = *build_font ? (WORD) build_font_size : (WORD) table->nlf.m_iFontSize; + if (font_size) + { + char temp[64]; + sprintf(temp, "%d", font_size); + table->lang_strings->set(sn, temp); + } + else + table->lang_strings->set(sn, dstr); + continue; + } + table->lang_strings->set(sn, dstr); + } + } + } + } +} + +char SkipComments(FILE *f) { + int c; + while ((c = fgetc(f))) { + while (c == '\n' || c == '\r') { + c = fgetc(f); // Skip empty lines + } + if (c == '#' || c == ';') { + while ((c = fgetc(f))) { + if (c == '\n') break; + } + } + else break; + } + return (char) c; +} + +// NSIS Language File parser +LanguageTable * CEXEBuild::LoadLangFile(char *filename) { + FILE *f = FOPEN(filename, "r"); + if (!f) { + ERROR_MSG("Error: Can't open language file - \"%s\"!\n",filename); + return 0; + } + + // Check header + char buf[NSIS_MAX_STRLEN]; + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + + if (strncmp(buf, "NLF v", 5)) { + ERROR_MSG("Error: Invalid language file.\n"); + return 0; + } + int nlf_version = atoi(buf+5); + if (nlf_version != NLF_VERSION) { + if (nlf_version != 2 && nlf_version != 3 && nlf_version != 4 && nlf_version != 5) { + ERROR_MSG("Error: Language file version doesn't match NSIS version.\n"); + return 0; + } + } + + // Get language ID + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + LANGID lang_id = atoi(buf); + + // Get appropriate table + LanguageTable *table = GetLangTable(lang_id); + if (!table) + return 0; + + NLF *nlf = &table->nlf; + + if (nlf->m_bLoaded) { + ERROR_MSG("Error: can't load same language file twice.\n"); + return 0; + } + + // Generate language name + char *p, *p2, t = 0; + + p = strrchr(filename, '.'); + if (p) { + t = *p; + *p = 0; + } + p2 = strrchr(filename, '\\'); + if (p2) { + p2++; + nlf->m_szName = (char*)malloc(strlen(p2)+1); + strcpy(nlf->m_szName, p2); + } + else { + nlf->m_szName = (char*)malloc(strlen(filename)+1); + strcpy(nlf->m_szName, filename); + } + if (p) *p = t; + + if (nlf_version != NLF_VERSION) { + warning_fl("%s language file version doesn't match. Using default English texts for missing strings.", nlf->m_szName); + } + + // set ^Language + nlf->m_szStrings[NLF_LANGUAGE] = strdup(nlf->m_szName); + + int temp; + + // Get font + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + if (!nlf->m_szFont) { + temp=strlen(buf); + while (buf[temp-1] == '\n' || buf[temp-1] == '\r') { + buf[temp-1] = 0; + temp--; + } + if (buf[0] != '-' || buf[1] != 0) { + nlf->m_szFont = (char*)malloc(strlen(buf)+1); + strcpy(nlf->m_szFont, buf); + } + } + + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + if (!nlf->m_iFontSize) { + if (buf[0] != '-' || buf[1] != 0) { + nlf->m_iFontSize = atoi(buf); + } + } + + // Get code page + nlf->m_uCodePage = CP_ACP; + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + if (buf[0] != '-' || buf[1] != 0) { + nlf->m_uCodePage = atoi(buf); + if (!IsValidCodePage(nlf->m_uCodePage)) + nlf->m_uCodePage = CP_ACP; + } + + // Get RTL setting + nlf->m_szStrings[NLF_RTL] = (char *)malloc(2); + nlf->m_bRTL = false; + buf[0] = SkipComments(f); + fgets(buf+1, NSIS_MAX_STRLEN, f); + if (buf[0] == 'R' && buf[1] == 'T' && buf[2] == 'L' && (!buf[3] || buf[3] == '\r' || buf[3] == '\n')) { + nlf->m_bRTL = true; + strcpy(nlf->m_szStrings[NLF_RTL], "1"); + } + else { + strcpy(nlf->m_szStrings[NLF_RTL], "0"); + } + + // Read strings + for (int i = 0; i < NLF_STRINGS_NO_SPECIAL; i++) { + + // skip virtual strings + if (!NLFStrings[i].szDefault) + continue; + + // Fill in for missing strings + // 0 will mean default will be used from NLFStrings + switch (i) { + case NLF_BTN_LICENSE_AGREE: + case NLF_BTN_LICENSE_DISAGREE: + if (nlf_version >= 3) break; + case NLF_LOG_INSTALL_PROCESS: + case NLF_BYTE: + case NLF_KILO: + case NLF_MEGA: + case NLF_GIGA: + case NLF_REGISTERING: + case NLF_UNREGISTERING: + if (nlf_version >= 4) break; + case NLF_FILE_ERROR_NOIGNORE: + if (nlf_version >= 5) break; + case NLF_USUBCAPTION_OPTIONS: + case NLF_USUBCAPTION_DIR: + case NLF_CLICK_NEXT: + case NLF_CLICK_INSTALL: + case NLF_CLICK_UNINSTALL: + case NLF_LICENSE_TEXT: + case NLF_LICENSE_TEXT_FSCB: + case NLF_LICENSE_TEXT_FSRB: + case NLF_ULICENSE_TEXT: + case NLF_ULICENSE_TEXT_FSCB: + case NLF_ULICENSE_TEXT_FSRB: + case NLF_COMP_TEXT: + case NLF_UCOMP_TEXT: + case NLF_UCOMP_SUBTEXT1: + case NLF_UCOMP_SUBTEXT1_NO_INST_TYPES: + case NLF_UCOMP_SUBTEXT2: + case NLF_DIR_TEXT: + case NLF_DIR_BROWSETEXT: + case NLF_UDIR_TEXT: + case NLF_UDIR_SUBTEXT: + case NLF_UDIR_BROWSETEXT: + case NLF_UNINST_TEXT: + if (nlf_version >= 6) break; + nlf->m_szStrings[i] = 0; + continue; + } + + buf[0] = SkipComments(f); + + fgets(buf+1, NSIS_MAX_STRLEN, f); + if (strlen(buf) == NSIS_MAX_STRLEN-1) { + ERROR_MSG("Error: String too long (string #%d - \"%s\")", i, NLFStrings[i].szLangStringName); + return 0; + } + temp=strlen(buf); + + while (buf[temp-1] == '\n' || buf[temp-1] == '\r') { + buf[--temp] = 0; + } + + char *in = buf; + + // trim quotes + if (buf[0] == '"' && buf[temp-1] == '"') { + in++; + buf[--temp] = 0; + } + + nlf->m_szStrings[i] = (char*)malloc(temp+1); + char *out; + for (out = nlf->m_szStrings[i]; *in; in++, out++) { + if (*in == '\\') { + in++; + switch (*in) { + case 'n': + *out = '\n'; + break; + case 'r': + *out = '\r'; + break; + case 't': + *out = '\t'; + break; + default: + *out++ = '\\'; + *out = *in; + } + } + else *out = *in; + } + *out = 0; + } + fclose(f); + + nlf->m_bLoaded = true; + + return table; +} + +void CEXEBuild::DeleteLangTable(LanguageTable *table) { + if (table->nlf.m_szName) + free(table->nlf.m_szName); + if (table->nlf.m_szFont) + free(table->nlf.m_szFont); + delete table->lang_strings; + for (int i = 0; i < NLF_STRINGS; i++) { + if (table->nlf.m_szStrings[i]) + free(table->nlf.m_szStrings[i]); + } +} diff --git a/Source/lang.h b/Source/lang.h index 18dc243..6bf2a41 100755 --- a/Source/lang.h +++ b/Source/lang.h @@ -1,199 +1,199 @@ -/*
- * lang.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___NLF___H_____
-#define ___NLF___H_____
-
-#include "strlist.h"
-#include "growbuf.h"
-#include "exehead/fileform.h"
-
-struct NLFRef {
- int iRef;
- int iUnRef;
-};
-
-struct langstring {
- int name;
- int sn;
- int index;
- int uindex;
- int process;
-};
-
-class LangStringList : public SortedStringListND<struct langstring>
-{
- public:
- LangStringList();
-
- int add(const char *name, int *sn=0);
- int get(char *name, int *sn=0, int *index=0, int *uindex=0, int *process=0);
- void set(int pos, int index=-1, int uindex=-1, int process=-1);
- void set(char *name, int index, int uindex=-1, int process=-1);
- const char *pos2name(int pos);
- const char *offset2name(int name);
- int getnum();
- static int compare_index(const void *item1, const void *item2);
- langstring *sort_index(int *num);
- static int compare_uindex(const void *item1, const void *item2);
- langstring *sort_uindex(int *num);
-
- private:
- int count;
- TinyGrowBuf sortbuf;
-};
-
-class StringsArray
-{
- public:
- StringsArray();
-
- void resize(int num);
- int set(int idx, char *str);
- const char *get(int idx);
-
- private:
- TinyGrowBuf offsets;
- GrowBuf strings;
-};
-
-#define NLF_VERSION 6
-
-enum {
- NLF_BRANDING,
- NLF_CAPTION,
- NLF_UCAPTION,
- NLF_SUBCAPTION_LICENSE,
- NLF_SUBCAPTION_OPTIONS,
- NLF_SUBCAPTION_DIR,
- NLF_SUBCAPTION_INSTFILES,
- NLF_SUBCAPTION_COMPLETED,
- NLF_USUBCAPTION_OPTIONS,
- NLF_USUBCAPTION_DIR,
- NLF_USUBCAPTION_CONFIRM,
- NLF_USUBCAPTION_INSTFILES,
- NLF_USUBCAPTION_COMPLETED,
- NLF_BTN_BACK,
- NLF_BTN_NEXT,
- NLF_BTN_LICENSE,
- NLF_BTN_LICENSE_AGREE,
- NLF_BTN_LICENSE_DISAGREE,
- NLF_BTN_INSTALL,
- NLF_BTN_UNINSTALL,
- NLF_BTN_CANCEL,
- NLF_BTN_CLOSE,
- NLF_BTN_BROWSE,
- NLF_BTN_DETAILS,
- NLF_CLICK_NEXT,
- NLF_CLICK_INSTALL,
- NLF_CLICK_UNINSTALL,
- NLF_NAME,
- NLF_NAME_DA, // name with doubled ampersands - virtual
- NLF_COMPLETED,
- NLF_LICENSE_TEXT,
- NLF_LICENSE_TEXT_FSCB,
- NLF_LICENSE_TEXT_FSRB,
- NLF_ULICENSE_TEXT,
- NLF_ULICENSE_TEXT_FSCB,
- NLF_ULICENSE_TEXT_FSRB,
- NLF_LICENSE_DATA, // virtual
- NLF_COMP_CUSTOM,
- NLF_COMP_TEXT,
- NLF_COMP_SUBTEXT1,
- NLF_COMP_SUBTEXT1_NO_INST_TYPES,
- NLF_COMP_SUBTEXT2,
- NLF_UCOMP_TEXT,
- NLF_UCOMP_SUBTEXT1,
- NLF_UCOMP_SUBTEXT1_NO_INST_TYPES,
- NLF_UCOMP_SUBTEXT2,
- NLF_DIR_TEXT,
- NLF_DIR_SUBTEXT,
- NLF_DIR_BROWSETEXT,
- NLF_UDIR_TEXT,
- NLF_UDIR_SUBTEXT,
- NLF_UDIR_BROWSETEXT,
- NLF_SPACE_AVAIL,
- NLF_SPACE_REQ,
- NLF_UNINST_TEXT,
- NLF_UNINST_SUBTEXT,
- NLF_FILE_ERROR,
- NLF_FILE_ERROR_NOIGNORE,
- NLF_CANT_WRITE,
- NLF_COPY_FAILED,
- NLF_COPY_TO,
- NLF_REGISTERING,
- NLF_UNREGISTERING,
- NLF_SYMBOL_NOT_FOUND,
- NLF_COULD_NOT_LOAD,
- NLF_CREATE_DIR,
- NLF_CREATE_SHORTCUT,
- NLF_CREATED_UNINST,
- NLF_DEL_FILE,
- NLF_DEL_ON_REBOOT,
- NLF_ERR_CREATING_SHORTCUT,
- NLF_ERR_CREATING,
- NLF_ERR_DECOMPRESSING,
- NLF_ERR_REG_DLL,
- NLF_EXEC_SHELL,
- NLF_EXEC,
- NLF_EXTRACT,
- NLF_ERR_WRITING,
- NLF_INST_CORRUPTED,
- NLF_NO_OLE,
- NLF_OUTPUT_DIR,
- NLF_REMOVE_DIR,
- NLF_RENAME_ON_REBOOT,
- NLF_RENAME,
- NLF_SKIPPED,
- NLF_COPY_DETAILS,
- NLF_LOG_INSTALL_PROCESS,
- NLF_BYTE,
- NLF_KILO,
- NLF_MEGA,
- NLF_GIGA,
-
- NLF_STRINGS_NO_SPECIAL,
-
- NLF_FONT = NLF_STRINGS_NO_SPECIAL,
- NLF_FONTSIZE,
- NLF_RTL,
- NLF_LANGUAGE,
-
- NLF_STRINGS
-};
-
-struct NLF {
- bool m_bLoaded;
- char *m_szName;
- char *m_szFont;
- int m_iFontSize;
- unsigned int m_uCodePage;
- bool m_bRTL;
-
- char *m_szStrings[NLF_STRINGS];
-};
-
-struct LanguageTable {
- LANGID lang_id;
-
- int dlg_offset;
-
- StringsArray *lang_strings;
-
- NLF nlf;
-};
-
-#endif
+/* + * lang.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___NLF___H_____ +#define ___NLF___H_____ + +#include "strlist.h" +#include "growbuf.h" +#include "exehead/fileform.h" + +struct NLFRef { + int iRef; + int iUnRef; +}; + +struct langstring { + int name; + int sn; + int index; + int uindex; + int process; +}; + +class LangStringList : public SortedStringListND<struct langstring> +{ + public: + LangStringList(); + + int add(const char *name, int *sn=0); + int get(char *name, int *sn=0, int *index=0, int *uindex=0, int *process=0); + void set(int pos, int index=-1, int uindex=-1, int process=-1); + void set(char *name, int index, int uindex=-1, int process=-1); + const char *pos2name(int pos); + const char *offset2name(int name); + int getnum(); + static int compare_index(const void *item1, const void *item2); + langstring *sort_index(int *num); + static int compare_uindex(const void *item1, const void *item2); + langstring *sort_uindex(int *num); + + private: + int count; + TinyGrowBuf sortbuf; +}; + +class StringsArray +{ + public: + StringsArray(); + + void resize(int num); + int set(int idx, char *str); + const char *get(int idx); + + private: + TinyGrowBuf offsets; + GrowBuf strings; +}; + +#define NLF_VERSION 6 + +enum { + NLF_BRANDING, + NLF_CAPTION, + NLF_UCAPTION, + NLF_SUBCAPTION_LICENSE, + NLF_SUBCAPTION_OPTIONS, + NLF_SUBCAPTION_DIR, + NLF_SUBCAPTION_INSTFILES, + NLF_SUBCAPTION_COMPLETED, + NLF_USUBCAPTION_OPTIONS, + NLF_USUBCAPTION_DIR, + NLF_USUBCAPTION_CONFIRM, + NLF_USUBCAPTION_INSTFILES, + NLF_USUBCAPTION_COMPLETED, + NLF_BTN_BACK, + NLF_BTN_NEXT, + NLF_BTN_LICENSE, + NLF_BTN_LICENSE_AGREE, + NLF_BTN_LICENSE_DISAGREE, + NLF_BTN_INSTALL, + NLF_BTN_UNINSTALL, + NLF_BTN_CANCEL, + NLF_BTN_CLOSE, + NLF_BTN_BROWSE, + NLF_BTN_DETAILS, + NLF_CLICK_NEXT, + NLF_CLICK_INSTALL, + NLF_CLICK_UNINSTALL, + NLF_NAME, + NLF_NAME_DA, // name with doubled ampersands - virtual + NLF_COMPLETED, + NLF_LICENSE_TEXT, + NLF_LICENSE_TEXT_FSCB, + NLF_LICENSE_TEXT_FSRB, + NLF_ULICENSE_TEXT, + NLF_ULICENSE_TEXT_FSCB, + NLF_ULICENSE_TEXT_FSRB, + NLF_LICENSE_DATA, // virtual + NLF_COMP_CUSTOM, + NLF_COMP_TEXT, + NLF_COMP_SUBTEXT1, + NLF_COMP_SUBTEXT1_NO_INST_TYPES, + NLF_COMP_SUBTEXT2, + NLF_UCOMP_TEXT, + NLF_UCOMP_SUBTEXT1, + NLF_UCOMP_SUBTEXT1_NO_INST_TYPES, + NLF_UCOMP_SUBTEXT2, + NLF_DIR_TEXT, + NLF_DIR_SUBTEXT, + NLF_DIR_BROWSETEXT, + NLF_UDIR_TEXT, + NLF_UDIR_SUBTEXT, + NLF_UDIR_BROWSETEXT, + NLF_SPACE_AVAIL, + NLF_SPACE_REQ, + NLF_UNINST_TEXT, + NLF_UNINST_SUBTEXT, + NLF_FILE_ERROR, + NLF_FILE_ERROR_NOIGNORE, + NLF_CANT_WRITE, + NLF_COPY_FAILED, + NLF_COPY_TO, + NLF_REGISTERING, + NLF_UNREGISTERING, + NLF_SYMBOL_NOT_FOUND, + NLF_COULD_NOT_LOAD, + NLF_CREATE_DIR, + NLF_CREATE_SHORTCUT, + NLF_CREATED_UNINST, + NLF_DEL_FILE, + NLF_DEL_ON_REBOOT, + NLF_ERR_CREATING_SHORTCUT, + NLF_ERR_CREATING, + NLF_ERR_DECOMPRESSING, + NLF_ERR_REG_DLL, + NLF_EXEC_SHELL, + NLF_EXEC, + NLF_EXTRACT, + NLF_ERR_WRITING, + NLF_INST_CORRUPTED, + NLF_NO_OLE, + NLF_OUTPUT_DIR, + NLF_REMOVE_DIR, + NLF_RENAME_ON_REBOOT, + NLF_RENAME, + NLF_SKIPPED, + NLF_COPY_DETAILS, + NLF_LOG_INSTALL_PROCESS, + NLF_BYTE, + NLF_KILO, + NLF_MEGA, + NLF_GIGA, + + NLF_STRINGS_NO_SPECIAL, + + NLF_FONT = NLF_STRINGS_NO_SPECIAL, + NLF_FONTSIZE, + NLF_RTL, + NLF_LANGUAGE, + + NLF_STRINGS +}; + +struct NLF { + bool m_bLoaded; + char *m_szName; + char *m_szFont; + int m_iFontSize; + unsigned int m_uCodePage; + bool m_bRTL; + + char *m_szStrings[NLF_STRINGS]; +}; + +struct LanguageTable { + LANGID lang_id; + + int dlg_offset; + + StringsArray *lang_strings; + + NLF nlf; +}; + +#endif diff --git a/Source/lineparse.cpp b/Source/lineparse.cpp index 2d42ae6..d933aa1 100755 --- a/Source/lineparse.cpp +++ b/Source/lineparse.cpp @@ -1,236 +1,236 @@ -/*
- * lineparse.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "lineparse.h"
-#include "Platform.h"
-
-#include <cstdlib>
-#include <cstring>
-
-LineParser::LineParser(bool bCommentBlock)
-{
- m_incommentblock=bCommentBlock;
- m_incomment=false;
- m_nt=m_eat=0;
- m_tokens=0;
-}
-
-LineParser::~LineParser()
-{
- freetokens();
-}
-
-bool LineParser::inComment()
-{
- return m_incomment;
-}
-
-bool LineParser::inCommentBlock()
-{
- return m_incommentblock;
-}
-
-int LineParser::parse(char *line, int ignore_escaping/*=0*/) // returns -1 on error
-{
- freetokens();
- bool bPrevCB=m_incommentblock;
- int n=doline(line, ignore_escaping);
- if (n) return n;
- if (m_nt)
- {
- m_incommentblock=bPrevCB;
- m_tokens=(char**)malloc(sizeof(char*)*m_nt);
- n=doline(line, ignore_escaping);
- if (n)
- {
- freetokens();
- return -1;
- }
- }
- return 0;
-}
-
-int LineParser::getnumtokens()
-{
- return m_nt-m_eat;
-}
-
-void LineParser::eattoken()
-{
- m_eat++;
-}
-
-double LineParser::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 LineParser::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* LineParser::gettoken_str(int token)
-{
- token+=m_eat;
- if (token < 0 || token >= m_nt) return "";
- return m_tokens[token];
-}
-
-int LineParser::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;
-}
-
-void LineParser::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 LineParser::doline(char *line, int ignore_escaping/*=0*/)
-{
- m_nt=0;
- m_incomment = false;
- while (*line == ' ' || *line == '\t') line++;
- while (*line)
- {
- if ( m_incommentblock )
- {
- while ( *line )
- {
- if ( *line == '*' && *(line+1) == '/' )
- {
- m_incommentblock=false; // Found end of comment block
- line+=2;
- while (*line == ' ' || *line == '\t') line++;
- break;
- }
- else line++;
- }
- }
- else {
- int lstate=0; // 1=", 2=`, 4='
- if (*line == ';' || *line == '#')
- {
- m_incomment = true;
- break;
- }
- if (*line == '/' && *(line+1) == '*')
- {
- m_incommentblock = true;
- line+=2;
- }
- else {
- if (*line == '\"') lstate=1;
- else if (*line == '\'') lstate=2;
- else if (*line == '`') lstate=4;
- if (lstate) line++;
- int nc=0;
- char *p = line;
- while (*line)
- {
- if (line[0] == '$' && line[1] == '\\') {
- switch (line[2]) {
- case '"':
- case '\'':
- case '`':
- nc += ignore_escaping ? 3 : 1;
- line += 3;
- continue;
- }
- }
- if (lstate==1 && *line =='\"') break;
- if (lstate==2 && *line =='\'') break;
- if (lstate==4 && *line =='`') break;
- if (!lstate && (*line == ' ' || *line == '\t')) break;
-#ifdef NSIS_FIX_COMMENT_HANDLING
- if (!lstate && (*line == ';' || *line == '#' || (*line == '/' && *(line+1) == '*'))) break;
-#endif
- line++;
- nc++;
- }
- if (m_tokens)
- {
- int i;
- m_tokens[m_nt]=(char*)malloc(nc+1);
- for (i = 0; p < line; i++, p++) {
- if (!ignore_escaping && p[0] == '$' && p[1] == '\\') {
- switch (p[2]) {
- case '"':
- case '\'':
- case '`':
- p += 2;
- }
- }
- m_tokens[m_nt][i] = *p;
- }
- m_tokens[m_nt][nc]=0;
- }
- m_nt++;
- if (lstate)
- {
- if (*line) line++;
- else return -2;
- }
- while (*line == ' ' || *line == '\t') line++;
- }
- }
- }
- return 0;
-}
+/* + * lineparse.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "lineparse.h" +#include "Platform.h" + +#include <cstdlib> +#include <cstring> + +LineParser::LineParser(bool bCommentBlock) +{ + m_incommentblock=bCommentBlock; + m_incomment=false; + m_nt=m_eat=0; + m_tokens=0; +} + +LineParser::~LineParser() +{ + freetokens(); +} + +bool LineParser::inComment() +{ + return m_incomment; +} + +bool LineParser::inCommentBlock() +{ + return m_incommentblock; +} + +int LineParser::parse(char *line, int ignore_escaping/*=0*/) // returns -1 on error +{ + freetokens(); + bool bPrevCB=m_incommentblock; + int n=doline(line, ignore_escaping); + if (n) return n; + if (m_nt) + { + m_incommentblock=bPrevCB; + m_tokens=(char**)malloc(sizeof(char*)*m_nt); + n=doline(line, ignore_escaping); + if (n) + { + freetokens(); + return -1; + } + } + return 0; +} + +int LineParser::getnumtokens() +{ + return m_nt-m_eat; +} + +void LineParser::eattoken() +{ + m_eat++; +} + +double LineParser::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 LineParser::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* LineParser::gettoken_str(int token) +{ + token+=m_eat; + if (token < 0 || token >= m_nt) return ""; + return m_tokens[token]; +} + +int LineParser::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; +} + +void LineParser::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 LineParser::doline(char *line, int ignore_escaping/*=0*/) +{ + m_nt=0; + m_incomment = false; + while (*line == ' ' || *line == '\t') line++; + while (*line) + { + if ( m_incommentblock ) + { + while ( *line ) + { + if ( *line == '*' && *(line+1) == '/' ) + { + m_incommentblock=false; // Found end of comment block + line+=2; + while (*line == ' ' || *line == '\t') line++; + break; + } + else line++; + } + } + else { + int lstate=0; // 1=", 2=`, 4=' + if (*line == ';' || *line == '#') + { + m_incomment = true; + break; + } + if (*line == '/' && *(line+1) == '*') + { + m_incommentblock = true; + line+=2; + } + else { + if (*line == '\"') lstate=1; + else if (*line == '\'') lstate=2; + else if (*line == '`') lstate=4; + if (lstate) line++; + int nc=0; + char *p = line; + while (*line) + { + if (line[0] == '$' && line[1] == '\\') { + switch (line[2]) { + case '"': + case '\'': + case '`': + nc += ignore_escaping ? 3 : 1; + line += 3; + continue; + } + } + if (lstate==1 && *line =='\"') break; + if (lstate==2 && *line =='\'') break; + if (lstate==4 && *line =='`') break; + if (!lstate && (*line == ' ' || *line == '\t')) break; +#ifdef NSIS_FIX_COMMENT_HANDLING + if (!lstate && (*line == ';' || *line == '#' || (*line == '/' && *(line+1) == '*'))) break; +#endif + line++; + nc++; + } + if (m_tokens) + { + int i; + m_tokens[m_nt]=(char*)malloc(nc+1); + for (i = 0; p < line; i++, p++) { + if (!ignore_escaping && p[0] == '$' && p[1] == '\\') { + switch (p[2]) { + case '"': + case '\'': + case '`': + p += 2; + } + } + m_tokens[m_nt][i] = *p; + } + m_tokens[m_nt][nc]=0; + } + m_nt++; + if (lstate) + { + if (*line) line++; + else return -2; + } + while (*line == ' ' || *line == '\t') line++; + } + } + } + return 0; +} diff --git a/Source/lineparse.h b/Source/lineparse.h index 2ab67f1..326fbdb 100755 --- a/Source/lineparse.h +++ b/Source/lineparse.h @@ -1,47 +1,47 @@ -/*
- * lineparse.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _LINEPARSE_H_
-#define _LINEPARSE_H_
-
-class LineParser {
- public:
-
- LineParser(bool bCommentBlock);
- virtual ~LineParser();
-
- bool inComment();
- bool inCommentBlock();
- int parse(char *line, int ignore_escaping=0); // returns -1 on error
- int getnumtokens();
- void eattoken();
- double gettoken_float(int token, int *success=0);
- int gettoken_int(int token, int *success=0);
- char *gettoken_str(int token);
- int gettoken_enum(int token, const char *strlist); // null seperated list
-
- private:
-
- void freetokens();
- int doline(char *line, int ignore_escaping=0);
-
- int m_eat;
- int m_nt;
- bool m_incommentblock;
- bool m_incomment;
- char **m_tokens;
-};
-#endif//_LINEPARSE_H_
+/* + * lineparse.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _LINEPARSE_H_ +#define _LINEPARSE_H_ + +class LineParser { + public: + + LineParser(bool bCommentBlock); + virtual ~LineParser(); + + bool inComment(); + bool inCommentBlock(); + int parse(char *line, int ignore_escaping=0); // returns -1 on error + int getnumtokens(); + void eattoken(); + double gettoken_float(int token, int *success=0); + int gettoken_int(int token, int *success=0); + char *gettoken_str(int token); + int gettoken_enum(int token, const char *strlist); // null seperated list + + private: + + void freetokens(); + int doline(char *line, int ignore_escaping=0); + + int m_eat; + int m_nt; + bool m_incommentblock; + bool m_incomment; + char **m_tokens; +}; +#endif//_LINEPARSE_H_ diff --git a/Source/makenssi.cpp b/Source/makenssi.cpp index 46551d5..ef58fba 100755 --- a/Source/makenssi.cpp +++ b/Source/makenssi.cpp @@ -1,554 +1,554 @@ -/*
- * makenssi.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <stdio.h>
-#include <signal.h>
-#ifdef _WIN32
-# include <direct.h>
-#else
-# include <unistd.h>
-#endif
-#include <string>
-
-#include "build.h"
-#include "util.h"
-
-#include "version.h"
-
-using namespace std;
-
-int g_noconfig=0;
-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();
-}
-
-#ifdef _WIN32
-static DWORD WINAPI sigint_event_msg_handler(LPVOID)
-{
- HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "makensis win32 signint event");
-
- if (hEvent)
- {
- if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
- raise(SIGINT);
- CloseHandle(hEvent);
- }
-
- return 0;
-}
-#endif
-
-static void init_signals()
-{
- atexit(myatexit);
- signal(SIGINT,sigint);
-
-#ifdef _WIN32
- DWORD id;
- HANDLE hThread = CreateThread(NULL, 0, sigint_event_msg_handler, NULL, 0, &id);
- if (hThread) CloseHandle(hThread);
-#endif
-}
-
-static void print_logo()
-{
- fprintf(g_output,"MakeNSIS %s - Copyright 1995-2007 Contributors\n"
- "See the file COPYING for license details.\n"
- "Credits can be found in the Users Manual.\n\n", NSIS_VERSION);
- fflush(g_output);
-}
-
-static void print_license()
-{
- fprintf(g_output,"Copyright (C) 1999-2007 Nullsoft and Contributors\n\n"
- "This license applies to everything in the NSIS package, except where otherwise\n"
- "noted.\n\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the\n"
- "use 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"
- "In addition to this license, different licenses apply to the included\n"
- "compression modules. See the file COPYING for details.\n");
- fflush(g_output);
-}
-
-static void print_usage()
-{
- fprintf(g_output,"Usage:\n"
- " makensis [option | script.nsi | - [...]]\n"
- " options are:\n"
- " " OPT_STR "CMDHELP item prints out help for 'item', or lists all commands\n"
- " " OPT_STR "HDRINFO prints information about what options makensis was compiled with\n"
- " " OPT_STR "LICENSE prints the makensis software license\n"
- " " OPT_STR "VERSION prints the makensis version and exits\n"
- " " OPT_STR "Px sets the compiler process priority, where x is 5=realtime,4=high,\n"
- " " " 3=above normal,2=normal,1=below normal,0=idle\n"
- " " OPT_STR "Vx verbosity where x is 4=all,3=no script,2=no info,1=no warnings,0=none\n"
- " " OPT_STR "Ofile specifies a text file to log compiler output (default is stdout)\n"
- " " OPT_STR "PAUSE pauses after execution\n"
- " " OPT_STR "NOCONFIG disables inclusion of <path to makensis.exe>" PLATFORM_PATH_SEPARATOR_STR "nsisconf.nsh\n"
- " " OPT_STR "NOCD disabled the current directory change to that of the .nsi file\n"
- " " OPT_STR "Ddefine[=value] defines the symbol \"define\" for the script [to value]\n"
- " " OPT_STR "Xscriptcmd executes scriptcmd in script (i.e. \"" OPT_STR "XOutFile poop.exe\")\n"
- " parameters are processed by order (" OPT_STR "Ddef ins.nsi != ins.nsi " OPT_STR "Ddef)\n"
- " for script file name, you can use - to read from the standard input\n"
-#ifdef _WIN32
- " you can also use - as an option character: -PAUSE as well as /PAUSE\n"
-#endif
- " you can use a double-dash to end options processing: makensis -- -ins.nsi\n");
- fflush(g_output);
-}
-
-static void print_stub_info(CEXEBuild& build)
-{
- if (build.display_info)
- {
- fprintf(g_output,"Size of first header is %lu bytes.\n",(unsigned long)sizeof(firstheader));
- fprintf(g_output,"Size of main header is %lu bytes.\n",(unsigned long)sizeof(header));
- fprintf(g_output,"Size of each section is %lu bytes.\n",(unsigned long)sizeof(section));
- fprintf(g_output,"Size of each page is %lu bytes.\n",(unsigned long)sizeof(page));
- fprintf(g_output,"Size of each instruction is %lu bytes.\n",(unsigned long)sizeof(entry));
- int x=build.definedlist.getnum();
- fprintf(g_output,"\nDefined symbols: ");
- for (int i=0; i<x; i++)
- {
- fprintf(g_output,"%s",build.definedlist.getname(i));
- char *p=build.definedlist.getvalue(i);
- if (*p) fprintf(g_output,"=%s",p);
- if (i<x-1) fprintf(g_output,",");
- }
- if (!x) fprintf(g_output,"none");
- fprintf(g_output,"\n");
- fflush(g_output);
- }
-}
-
-static string get_home()
-{
- char *home = getenv(
-#ifdef _WIN32
- "APPDATA"
-#else
- "HOME"
-#endif
- );
-
- return home ? home : "";
-}
-
-static int process_config(CEXEBuild& build, string& conf)
-{
- FILE *cfg=fopen(conf.c_str(),"rt");
- if (cfg)
- {
- if (build.display_script)
- {
- fprintf(g_output,"Processing config: \n");
- fflush(g_output);
- }
- int ret=build.process_script(cfg,(char*)conf.c_str());
- 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",build.linecnt);
- fflush(g_output);
- }
- return 1;
- }
- if (build.display_script)
- {
- fprintf(g_output,"\n");
- fflush(g_output);
- }
- }
- return 0;
-}
-
-static int change_to_script_dir(CEXEBuild& build, string& script)
-{
- string dir = get_dir_name(get_full_path(script));
- if (!dir.empty())
- {
- if (build.display_script)
- {
- fprintf(g_output,"Changing directory to: \"%s\"\n",dir.c_str());
- fflush(g_output);
- }
- if (chdir(dir.c_str()))
- {
- if (build.display_errors)
- {
- fprintf(g_output,"Error changing directory to \"%s\"\n",dir.c_str());
- fflush(g_output);
- }
- return 1;
- }
- if (build.display_script)
- {
- fprintf(g_output,"\n");
- fflush(g_output);
- }
- }
- return 0;
-}
-
-#ifdef NSIS_HPUX_ALLOW_UNALIGNED_DATA_ACCESS
-extern "C" void allow_unaligned_data_access();
-#endif
-
-int main(int argc, char **argv)
-{
-#ifdef NSIS_HPUX_ALLOW_UNALIGNED_DATA_ACCESS
- allow_unaligned_data_access();
-#endif
-
- CEXEBuild build;
- int do_cd=1;
- 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;
- int in_files=0;
-
- try
- {
- build.initialize(argv[0]);
- }
- catch (exception& err)
- {
- fprintf(g_output, "Error initalizing CEXEBuild: %s\n", err.what());
- fflush(g_output);
- return 1;
- }
-
- if (argc > 1 && IS_OPT(argv[1]) && !stricmp(&argv[1][1],"VERSION"))
- {
- fprintf(g_output,NSIS_VERSION);
- fflush(g_output);
- return 0;
- }
- if (argc > 1 && IS_OPT(argv[1]) && (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 && IS_OPT(argv[tmpargpos]) && (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;
- }
- print_logo();
- }
-
- init_signals();
-
- if (!g_output) g_output=stdout;
- while (argpos < argc)
- {
- if (!strcmp(argv[argpos], "--"))
- in_files=1;
- else if (IS_OPT(argv[argpos]) && strcmp(argv[argpos], "-") && !in_files)
- {
- if ((argv[argpos][1]=='D' || argv[argpos][1]=='d') && argv[argpos][2])
- {
- char *p=argv[argpos]+2;
- 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 if ((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][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][1],"NOCD")) do_cd=0;
- else if ((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][1],"NOCONFIG")) g_noconfig=1;
- else if (!stricmp(&argv[argpos][1],"PAUSE")) g_dopause=1;
- else if (!stricmp(&argv[argpos][1],"LICENSE"))
- {
- if (build.display_info)
- {
- print_license();
- }
- nousage++;
- }
- else if (!stricmp(&argv[argpos][1],"CMDHELP"))
- {
- if (argpos < argc-1)
- build.print_help(argv[++argpos]);
- else
- build.print_help(NULL);
- nousage++;
- }
- else if (!stricmp(&argv[argpos][1],"NOTIFYHWND"))
- {
-#ifdef _WIN32
- build.notify_hwnd=(HWND)atol(argv[++argpos]);
- if (!IsWindow(build.notify_hwnd))
- build.notify_hwnd=0;
-#else
- argpos++;
- build.warning(OPT_STR "NOTIFYHWND is disabled for non Win32 platforms.");
-#endif
- }
- else if (!stricmp(&argv[argpos][1],"HDRINFO"))
- {
- print_stub_info(build);
- nousage++;
- }
- else if ((argv[argpos][1]=='P' || argv[argpos][1]=='p') &&
- argv[argpos][2] >= '0' && argv[argpos][2] <= '5' && !argv[argpos][3])
- {
-#ifdef _WIN32
- // priority setting added 01-2007 by Comm@nder21
- int p=argv[argpos][2]-'0';
- HANDLE hProc = GetCurrentProcess();
-
- struct
- {
- DWORD priority;
- DWORD fallback;
- } classes[] = {
- {IDLE_PRIORITY_CLASS, IDLE_PRIORITY_CLASS},
- {BELOW_NORMAL_PRIORITY_CLASS, IDLE_PRIORITY_CLASS},
- {NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS},
- {ABOVE_NORMAL_PRIORITY_CLASS, HIGH_PRIORITY_CLASS},
- {HIGH_PRIORITY_CLASS, HIGH_PRIORITY_CLASS},
- {REALTIME_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS}
- };
-
- if (SetPriorityClass(hProc, classes[p].priority) == FALSE)
- {
- SetPriorityClass(hProc, classes[p].fallback);
- }
-
- if (p == 5)
- build.warning("makensis is running in REALTIME priority mode!");
-
-#else
- build.warning(OPT_STR "Px is disabled for non Win32 platforms.");
-#endif
- }
- else break;
- }
- else
- {
- files_processed++;
- if (!strcmp(argv[argpos],"-") && !in_files)
- g_dopause=0;
- if (!g_noconfig)
- {
- g_noconfig=1;
- string main_conf;
- char* env_var = getenv("NSISCONFDIR");
- if(env_var == NULL)
-#ifndef NSIS_CONFIG_CONST_DATA_PATH
- main_conf = get_executable_dir(argv[0]);
-#else
- main_conf = PREFIX_CONF;
-#endif
- else main_conf = env_var;
- main_conf += PLATFORM_PATH_SEPARATOR_STR;
- main_conf += "nsisconf.nsh";
- if (process_config(build, main_conf))
- return 1;
-
- string home_conf = get_home();
- if (home_conf != "")
- {
- home_conf += PLATFORM_PATH_SEPARATOR_STR;
-#ifdef _WIN32
- home_conf += "nsisconf.nsh";
-#else
- home_conf += ".nsisconf.nsh";
-#endif
- if (process_config(build, home_conf))
- return 1;
- }
- }
-
- {
- char sfile[1024];
- if (!strcmp(argv[argpos],"-") && !in_files)
- {
- 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)
- {
- sfile[strlen(sfile)-4]=0;
- fprintf(g_output,"Can't open script \"%s\"\n",sfile);
- fflush(g_output);
- }
- return 1;
- }
- }
- if (do_cd)
- {
- string script_file = string(sfile);
- if (change_to_script_dir(build, script_file))
- return 1;
- }
- }
-
- if (build.display_script)
- {
- build.notify(MAKENSIS_NOTIFY_SCRIPT,sfile);
- fprintf(g_output,"Processing script file: \"%s\"\n",sfile);
- fflush(g_output);
- }
- int ret=build.process_script(fp,sfile);
- 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,build.linecnt);
- fflush(g_output);
- }
- return 1;
- }
- }
- }
- argpos++;
- }
-
- if (argpos<argc || (!files_processed && !cmds_processed))
- {
- if (build.display_errors && !nousage)
- {
- print_usage();
- }
- 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;
-}
+/* + * makenssi.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <stdio.h> +#include <signal.h> +#ifdef _WIN32 +# include <direct.h> +#else +# include <unistd.h> +#endif +#include <string> + +#include "build.h" +#include "util.h" + +#include "version.h" + +using namespace std; + +int g_noconfig=0; +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(); +} + +#ifdef _WIN32 +static DWORD WINAPI sigint_event_msg_handler(LPVOID) +{ + HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, "makensis win32 signint event"); + + if (hEvent) + { + if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) + raise(SIGINT); + CloseHandle(hEvent); + } + + return 0; +} +#endif + +static void init_signals() +{ + atexit(myatexit); + signal(SIGINT,sigint); + +#ifdef _WIN32 + DWORD id; + HANDLE hThread = CreateThread(NULL, 0, sigint_event_msg_handler, NULL, 0, &id); + if (hThread) CloseHandle(hThread); +#endif +} + +static void print_logo() +{ + fprintf(g_output,"MakeNSIS %s - Copyright 1995-2007 Contributors\n" + "See the file COPYING for license details.\n" + "Credits can be found in the Users Manual.\n\n", NSIS_VERSION); + fflush(g_output); +} + +static void print_license() +{ + fprintf(g_output,"Copyright (C) 1999-2007 Nullsoft and Contributors\n\n" + "This license applies to everything in the NSIS package, except where otherwise\n" + "noted.\n\n" + "This software is provided 'as-is', without any express or implied warranty.\n" + "In no event will the authors be held liable for any damages arising from the\n" + "use 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" + "In addition to this license, different licenses apply to the included\n" + "compression modules. See the file COPYING for details.\n"); + fflush(g_output); +} + +static void print_usage() +{ + fprintf(g_output,"Usage:\n" + " makensis [option | script.nsi | - [...]]\n" + " options are:\n" + " " OPT_STR "CMDHELP item prints out help for 'item', or lists all commands\n" + " " OPT_STR "HDRINFO prints information about what options makensis was compiled with\n" + " " OPT_STR "LICENSE prints the makensis software license\n" + " " OPT_STR "VERSION prints the makensis version and exits\n" + " " OPT_STR "Px sets the compiler process priority, where x is 5=realtime,4=high,\n" + " " " 3=above normal,2=normal,1=below normal,0=idle\n" + " " OPT_STR "Vx verbosity where x is 4=all,3=no script,2=no info,1=no warnings,0=none\n" + " " OPT_STR "Ofile specifies a text file to log compiler output (default is stdout)\n" + " " OPT_STR "PAUSE pauses after execution\n" + " " OPT_STR "NOCONFIG disables inclusion of <path to makensis.exe>" PLATFORM_PATH_SEPARATOR_STR "nsisconf.nsh\n" + " " OPT_STR "NOCD disabled the current directory change to that of the .nsi file\n" + " " OPT_STR "Ddefine[=value] defines the symbol \"define\" for the script [to value]\n" + " " OPT_STR "Xscriptcmd executes scriptcmd in script (i.e. \"" OPT_STR "XOutFile poop.exe\")\n" + " parameters are processed by order (" OPT_STR "Ddef ins.nsi != ins.nsi " OPT_STR "Ddef)\n" + " for script file name, you can use - to read from the standard input\n" +#ifdef _WIN32 + " you can also use - as an option character: -PAUSE as well as /PAUSE\n" +#endif + " you can use a double-dash to end options processing: makensis -- -ins.nsi\n"); + fflush(g_output); +} + +static void print_stub_info(CEXEBuild& build) +{ + if (build.display_info) + { + fprintf(g_output,"Size of first header is %lu bytes.\n",(unsigned long)sizeof(firstheader)); + fprintf(g_output,"Size of main header is %lu bytes.\n",(unsigned long)sizeof(header)); + fprintf(g_output,"Size of each section is %lu bytes.\n",(unsigned long)sizeof(section)); + fprintf(g_output,"Size of each page is %lu bytes.\n",(unsigned long)sizeof(page)); + fprintf(g_output,"Size of each instruction is %lu bytes.\n",(unsigned long)sizeof(entry)); + int x=build.definedlist.getnum(); + fprintf(g_output,"\nDefined symbols: "); + for (int i=0; i<x; i++) + { + fprintf(g_output,"%s",build.definedlist.getname(i)); + char *p=build.definedlist.getvalue(i); + if (*p) fprintf(g_output,"=%s",p); + if (i<x-1) fprintf(g_output,","); + } + if (!x) fprintf(g_output,"none"); + fprintf(g_output,"\n"); + fflush(g_output); + } +} + +static string get_home() +{ + char *home = getenv( +#ifdef _WIN32 + "APPDATA" +#else + "HOME" +#endif + ); + + return home ? home : ""; +} + +static int process_config(CEXEBuild& build, string& conf) +{ + FILE *cfg=fopen(conf.c_str(),"rt"); + if (cfg) + { + if (build.display_script) + { + fprintf(g_output,"Processing config: \n"); + fflush(g_output); + } + int ret=build.process_script(cfg,(char*)conf.c_str()); + 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",build.linecnt); + fflush(g_output); + } + return 1; + } + if (build.display_script) + { + fprintf(g_output,"\n"); + fflush(g_output); + } + } + return 0; +} + +static int change_to_script_dir(CEXEBuild& build, string& script) +{ + string dir = get_dir_name(get_full_path(script)); + if (!dir.empty()) + { + if (build.display_script) + { + fprintf(g_output,"Changing directory to: \"%s\"\n",dir.c_str()); + fflush(g_output); + } + if (chdir(dir.c_str())) + { + if (build.display_errors) + { + fprintf(g_output,"Error changing directory to \"%s\"\n",dir.c_str()); + fflush(g_output); + } + return 1; + } + if (build.display_script) + { + fprintf(g_output,"\n"); + fflush(g_output); + } + } + return 0; +} + +#ifdef NSIS_HPUX_ALLOW_UNALIGNED_DATA_ACCESS +extern "C" void allow_unaligned_data_access(); +#endif + +int main(int argc, char **argv) +{ +#ifdef NSIS_HPUX_ALLOW_UNALIGNED_DATA_ACCESS + allow_unaligned_data_access(); +#endif + + CEXEBuild build; + int do_cd=1; + 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; + int in_files=0; + + try + { + build.initialize(argv[0]); + } + catch (exception& err) + { + fprintf(g_output, "Error initalizing CEXEBuild: %s\n", err.what()); + fflush(g_output); + return 1; + } + + if (argc > 1 && IS_OPT(argv[1]) && !stricmp(&argv[1][1],"VERSION")) + { + fprintf(g_output,NSIS_VERSION); + fflush(g_output); + return 0; + } + if (argc > 1 && IS_OPT(argv[1]) && (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 && IS_OPT(argv[tmpargpos]) && (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; + } + print_logo(); + } + + init_signals(); + + if (!g_output) g_output=stdout; + while (argpos < argc) + { + if (!strcmp(argv[argpos], "--")) + in_files=1; + else if (IS_OPT(argv[argpos]) && strcmp(argv[argpos], "-") && !in_files) + { + if ((argv[argpos][1]=='D' || argv[argpos][1]=='d') && argv[argpos][2]) + { + char *p=argv[argpos]+2; + 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 if ((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][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][1],"NOCD")) do_cd=0; + else if ((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][1],"NOCONFIG")) g_noconfig=1; + else if (!stricmp(&argv[argpos][1],"PAUSE")) g_dopause=1; + else if (!stricmp(&argv[argpos][1],"LICENSE")) + { + if (build.display_info) + { + print_license(); + } + nousage++; + } + else if (!stricmp(&argv[argpos][1],"CMDHELP")) + { + if (argpos < argc-1) + build.print_help(argv[++argpos]); + else + build.print_help(NULL); + nousage++; + } + else if (!stricmp(&argv[argpos][1],"NOTIFYHWND")) + { +#ifdef _WIN32 + build.notify_hwnd=(HWND)atol(argv[++argpos]); + if (!IsWindow(build.notify_hwnd)) + build.notify_hwnd=0; +#else + argpos++; + build.warning(OPT_STR "NOTIFYHWND is disabled for non Win32 platforms."); +#endif + } + else if (!stricmp(&argv[argpos][1],"HDRINFO")) + { + print_stub_info(build); + nousage++; + } + else if ((argv[argpos][1]=='P' || argv[argpos][1]=='p') && + argv[argpos][2] >= '0' && argv[argpos][2] <= '5' && !argv[argpos][3]) + { +#ifdef _WIN32 + // priority setting added 01-2007 by Comm@nder21 + int p=argv[argpos][2]-'0'; + HANDLE hProc = GetCurrentProcess(); + + struct + { + DWORD priority; + DWORD fallback; + } classes[] = { + {IDLE_PRIORITY_CLASS, IDLE_PRIORITY_CLASS}, + {BELOW_NORMAL_PRIORITY_CLASS, IDLE_PRIORITY_CLASS}, + {NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS}, + {ABOVE_NORMAL_PRIORITY_CLASS, HIGH_PRIORITY_CLASS}, + {HIGH_PRIORITY_CLASS, HIGH_PRIORITY_CLASS}, + {REALTIME_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS} + }; + + if (SetPriorityClass(hProc, classes[p].priority) == FALSE) + { + SetPriorityClass(hProc, classes[p].fallback); + } + + if (p == 5) + build.warning("makensis is running in REALTIME priority mode!"); + +#else + build.warning(OPT_STR "Px is disabled for non Win32 platforms."); +#endif + } + else break; + } + else + { + files_processed++; + if (!strcmp(argv[argpos],"-") && !in_files) + g_dopause=0; + if (!g_noconfig) + { + g_noconfig=1; + string main_conf; + char* env_var = getenv("NSISCONFDIR"); + if(env_var == NULL) +#ifndef NSIS_CONFIG_CONST_DATA_PATH + main_conf = get_executable_dir(argv[0]); +#else + main_conf = PREFIX_CONF; +#endif + else main_conf = env_var; + main_conf += PLATFORM_PATH_SEPARATOR_STR; + main_conf += "nsisconf.nsh"; + if (process_config(build, main_conf)) + return 1; + + string home_conf = get_home(); + if (home_conf != "") + { + home_conf += PLATFORM_PATH_SEPARATOR_STR; +#ifdef _WIN32 + home_conf += "nsisconf.nsh"; +#else + home_conf += ".nsisconf.nsh"; +#endif + if (process_config(build, home_conf)) + return 1; + } + } + + { + char sfile[1024]; + if (!strcmp(argv[argpos],"-") && !in_files) + { + 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) + { + sfile[strlen(sfile)-4]=0; + fprintf(g_output,"Can't open script \"%s\"\n",sfile); + fflush(g_output); + } + return 1; + } + } + if (do_cd) + { + string script_file = string(sfile); + if (change_to_script_dir(build, script_file)) + return 1; + } + } + + if (build.display_script) + { + build.notify(MAKENSIS_NOTIFY_SCRIPT,sfile); + fprintf(g_output,"Processing script file: \"%s\"\n",sfile); + fflush(g_output); + } + int ret=build.process_script(fp,sfile); + 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,build.linecnt); + fflush(g_output); + } + return 1; + } + } + } + argpos++; + } + + if (argpos<argc || (!files_processed && !cmds_processed)) + { + if (build.display_errors && !nousage) + { + print_usage(); + } + return 1; + } + + if (build.display_info) + { + fprintf(g_output,"\nProcessed "); + if (files_processed) fprintf(g_output,"%d file%s, ",files_processed,files_processed==1?"":"s"); + if (cmds_processed) fprintf(g_output,"%d command line command%s, ",cmds_processed,cmds_processed==1?"":"s"); + fprintf(g_output,"writing output:\n"); + fflush(g_output); + } + + if (build.write_output()) + { + if (build.display_errors) + { + fprintf(g_output,"Error - aborting creation process\n"); + fflush(g_output); + } + return 1; + } + return 0; +} diff --git a/Source/manifest.cpp b/Source/manifest.cpp index 3d6d005..abd55a6 100755 --- a/Source/manifest.cpp +++ b/Source/manifest.cpp @@ -1,67 +1,67 @@ -/*
- * manifest.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include "manifest.h"
-#include "version.h"
-
-namespace manifest
-{
-
-using namespace std;
-
-string generate(comctl comctl_selection, exec_level exec_level_selection)
-{
- if (comctl_selection == comctl_old && exec_level_selection == exec_level_none)
- return "";
-
- string xml = "<?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 " NSIS_VERSION "</description>";
-
- if (comctl_selection == comctl_xp)
- {
- xml += "<dependency><dependentAssembly><assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.Common-Controls\" version=\"6.0.0.0\" processorArchitecture=\"X86\" publicKeyToken=\"6595b64144ccf1df\" language=\"*\" /></dependentAssembly></dependency>";
- }
-
- if (exec_level_selection != exec_level_none)
- {
- string level = "";
-
- switch (exec_level_selection)
- {
- case exec_level_none:
- break;
- case exec_level_user:
- level = "asInvoker";
- break;
- case exec_level_highest:
- level = "highestAvailable";
- break;
- case exec_level_admin:
- level = "requireAdministrator";
- break;
- }
-
- xml += "<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\"><security><requestedPrivileges><requestedExecutionLevel level=\"";
- xml += level;
- xml += "\" uiAccess=\"false\"/></requestedPrivileges></security></trustInfo>";
- }
-
- xml += "</assembly>";
-
- return xml;
-}
-
-};
+/* + * manifest.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include "manifest.h" +#include "version.h" + +namespace manifest +{ + +using namespace std; + +string generate(comctl comctl_selection, exec_level exec_level_selection) +{ + if (comctl_selection == comctl_old && exec_level_selection == exec_level_none) + return ""; + + string xml = "<?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 " NSIS_VERSION "</description>"; + + if (comctl_selection == comctl_xp) + { + xml += "<dependency><dependentAssembly><assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.Common-Controls\" version=\"6.0.0.0\" processorArchitecture=\"X86\" publicKeyToken=\"6595b64144ccf1df\" language=\"*\" /></dependentAssembly></dependency>"; + } + + if (exec_level_selection != exec_level_none) + { + string level = ""; + + switch (exec_level_selection) + { + case exec_level_none: + break; + case exec_level_user: + level = "asInvoker"; + break; + case exec_level_highest: + level = "highestAvailable"; + break; + case exec_level_admin: + level = "requireAdministrator"; + break; + } + + xml += "<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\"><security><requestedPrivileges><requestedExecutionLevel level=\""; + xml += level; + xml += "\" uiAccess=\"false\"/></requestedPrivileges></security></trustInfo>"; + } + + xml += "</assembly>"; + + return xml; +} + +}; diff --git a/Source/manifest.h b/Source/manifest.h index 7533ee8..c336af6 100755 --- a/Source/manifest.h +++ b/Source/manifest.h @@ -1,41 +1,41 @@ -/*
- * manifest.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___MANIFEST_H___
-#define ___MANIFEST_H___
-
-#include <string>
-
-namespace manifest
-{
- enum comctl
- {
- comctl_old,
- comctl_xp
- };
-
- enum exec_level
- {
- exec_level_none,
- exec_level_user,
- exec_level_highest,
- exec_level_admin
- };
-
- std::string generate(comctl, exec_level);
-};
-
-#endif//!___MANIFEST_H___
+/* + * manifest.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___MANIFEST_H___ +#define ___MANIFEST_H___ + +#include <string> + +namespace manifest +{ + enum comctl + { + comctl_old, + comctl_xp + }; + + enum exec_level + { + exec_level_none, + exec_level_user, + exec_level_highest, + exec_level_admin + }; + + std::string generate(comctl, exec_level); +}; + +#endif//!___MANIFEST_H___ diff --git a/Source/mmap.cpp b/Source/mmap.cpp index aecdba2..25668c9 100755 --- a/Source/mmap.cpp +++ b/Source/mmap.cpp @@ -1,512 +1,512 @@ -/*
- * mmap.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "mmap.h"
-
-#include <cstdio> // for f*
-#include <cassert> // for assert
-#ifndef _WIN32
-# include <sys/types.h> // for freebsd
-# include <sys/mman.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <unistd.h>
-#endif
-
-// ========
-// MMapFile
-// ========
-
-int MMapFile::m_iAllocationGranularity = 0;
-
-MMapFile::MMapFile()
-{
-#ifdef _WIN32
- m_hFile = INVALID_HANDLE_VALUE;
- m_hFileMap = NULL;
-#else
- m_hFile = NULL;
- m_hFileDesc = -1;
-#endif
-
- m_pView = NULL;
- m_iSize = 0;
- m_bReadOnly = FALSE;
- m_bTempHandle = FALSE;
-
- if (!m_iAllocationGranularity)
- {
-#ifdef _WIN32
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- m_iAllocationGranularity = (int) si.dwAllocationGranularity;
-#else
- m_iAllocationGranularity = getpagesize();
-#endif
- }
-}
-
-MMapFile::~MMapFile()
-{
- clear();
-}
-
-void MMapFile::clear()
-{
- release();
-
-#ifdef _WIN32
- if (m_hFileMap)
- CloseHandle(m_hFileMap);
- if (m_bTempHandle && m_hFile != INVALID_HANDLE_VALUE)
- CloseHandle(m_hFile);
-
- m_hFile = INVALID_HANDLE_VALUE;
- m_hFileMap = 0;
-#else
- if (m_bTempHandle && m_hFile)
- fclose(m_hFile);
-
- m_hFile = NULL;
-#endif
-}
-
-void MMapFile::setro(BOOL bRO)
-{
- m_bReadOnly = bRO;
-}
-
-#ifdef _WIN32
-int MMapFile::setfile(HANDLE hFile, DWORD dwSize)
-#else
-int MMapFile::setfile(int hFile, DWORD dwSize)
-#endif
-{
- clear();
-
-#ifdef _WIN32
- m_hFile = hFile;
-#else
- m_hFileDesc = hFile;
-#endif
- m_bTempHandle = FALSE;
-
-#ifdef _WIN32
- if (m_hFile == INVALID_HANDLE_VALUE)
-#else
- if (m_hFileDesc == -1)
-#endif
- return 0;
-
- m_iSize = (int) dwSize;
-
- if (m_iSize <= 0)
- return 0;
-
-#ifdef _WIN32
- m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, m_iSize, NULL);
-
- if (!m_hFileMap)
- return 0;
-#endif
-
- m_bReadOnly = TRUE;
-
- return 1;
-}
-
-void MMapFile::resize(int newsize)
-{
- release();
-
- if (newsize > m_iSize)
- {
-#ifdef _WIN32
- if (m_hFileMap)
- CloseHandle(m_hFileMap);
-
- m_hFileMap = 0;
-#endif
-
- m_iSize = newsize;
-
-#ifdef _WIN32
- 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 | FILE_FLAG_SEQUENTIAL_SCAN,
- NULL
- );
-
- m_bTempHandle = TRUE;
- }
-
- if (m_hFile != INVALID_HANDLE_VALUE)
- {
- m_hFileMap = CreateFileMapping(
- m_hFile,
- NULL,
- m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE,
- 0,
- m_iSize,
- NULL
- );
- }
-#else
- if (m_hFile == NULL)
- {
- m_hFile = tmpfile();
- if (m_hFile != NULL)
- {
- m_hFileDesc = fileno(m_hFile);
- m_bTempHandle = TRUE;
- }
- }
-
- // resize
- if (m_hFileDesc != -1)
- {
- unsigned char c = 0;
-
- if (lseek(m_hFileDesc, m_iSize, SEEK_SET) != (off_t)-1)
- {
- if (read(m_hFileDesc, &c, 1) != -1)
- {
- if (lseek(m_hFileDesc, m_iSize, SEEK_SET) != (off_t)-1)
- {
- if (write(m_hFileDesc, &c, 1) != -1)
- {
- return; // no errors
- }
- }
- }
- }
- }
-
- m_hFileDesc = -1; // some error occurred, bail
-#endif
-
-#ifdef _WIN32
- if (!m_hFileMap)
-#else
- if (m_hFileDesc == -1)
-#endif
- {
- extern FILE *g_output;
- extern void quit(); extern int g_display_errors;
- if (g_display_errors)
- {
- fprintf(g_output,"\nInternal compiler error #12345: error creating mmap the size of %d.\n", m_iSize);
- fflush(g_output);
- }
- quit();
- }
- }
-}
-
-int MMapFile::getsize() const
-{
- return m_iSize;
-}
-
-void *MMapFile::get(int offset, int size) const
-{
- return get(offset, &size);
-}
-
-void *MMapFile::get(int offset, int *sizep) const
-{
- if (!sizep)
- return NULL;
-
- assert(!m_pView);
-
- int size = *sizep;
-
- if (!m_iSize || offset + size > m_iSize)
- {
- 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 file (%d, %d) is out of range.\n", offset, size);
- fflush(g_output);
- }
- quit();
- }
-
- // fix offset
- int alignedoffset = offset - (offset % m_iAllocationGranularity);
- size += offset - alignedoffset;
-
-#ifdef _WIN32
- const_cast<MMapFile*>(this)->m_pView =
- MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, alignedoffset, size);
-#else
- const_cast<MMapFile*>(this)->m_pView =
- mmap(0, size, m_bReadOnly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, m_hFileDesc, alignedoffset);
- const_cast<MMapFile*>(this)->m_iMappedSize = *sizep = size;
-#endif
-
-#ifdef _WIN32
- if (!m_pView)
-#else
- if (m_pView == MAP_FAILED)
-#endif
- {
- 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", size);
- fflush(g_output);
- }
- quit();
- }
-
- return (void *)((char *)m_pView + offset - alignedoffset);
-}
-
-void *MMapFile::getmore(int offset, int size) const
-{
- void *pView;
- void *pViewBackup = m_pView;
-#ifndef _WIN32
- int iMappedSizeBackup = m_iMappedSize;
-#endif
- const_cast<MMapFile*>(this)->m_pView = 0;
- pView = get(offset, size);
- const_cast<MMapFile*>(this)->m_pView = pViewBackup;
-#ifndef _WIN32
- const_cast<MMapFile*>(this)->m_iMappedSize = iMappedSizeBackup;
-#endif
- return pView;
-}
-
-void MMapFile::release()
-{
- if (!m_pView)
- return;
-
-#ifdef _WIN32
- UnmapViewOfFile(m_pView);
-#else
- munmap(m_pView, m_iMappedSize);
-#endif
- m_pView = NULL;
-}
-
-void MMapFile::release(void *pView, int size)
-{
- if (!pView)
- return;
-
- unsigned int alignment = ((unsigned int)pView) % m_iAllocationGranularity;
- pView = (char *)pView - alignment;
- size += alignment;
-#ifdef _WIN32
- UnmapViewOfFile(pView);
-#else
- munmap(pView, size);
-#endif
-}
-
-void MMapFile::flush(int num)
-{
- if (m_pView)
-#ifdef _WIN32
- FlushViewOfFile(m_pView, num);
-#else
- msync(m_pView, num, MS_SYNC);
-#endif
-}
-
-// ========
-// MMapFake
-// ========
-
-MMapFake::MMapFake()
-{
- m_pMem = NULL;
- m_iSize = 0;
-}
-
-void MMapFake::set(const char *pMem, int iSize)
-{
- m_pMem = pMem;
- m_iSize = iSize;
-}
-
-int MMapFake::getsize() const
-{
- return m_iSize;
-}
-
-void *MMapFake::get(int offset, int size) const
-{
- return get(offset, &size);
-}
-
-void *MMapFake::get(int offset, int *size) const
-{
- if (!size || (offset + *size > m_iSize))
- return NULL;
- return (void *)(m_pMem + offset);
-}
-
-void *MMapFake::getmore(int offset, int size) const
-{
- return get(offset, size);
-}
-
-void MMapFake::resize(int n) {}
-void MMapFake::release() {}
-void MMapFake::release(void *p, int size) {}
-void MMapFake::clear() {}
-void MMapFake::setro(BOOL b) {}
-void MMapFake::flush(BOOL b) {}
-
-// =======
-// MMapBuf
-// =======
-
-MMapBuf::MMapBuf()
-{
- m_gb_u=0;
- m_alloc=m_used=0;
-}
-
-MMapBuf::~MMapBuf()
-{
- m_fm.release();
-}
-
-int MMapBuf::add(const void *data, int len)
-{
- if (len <= 0) return 0;
- resize(getlen() + len);
- memcpy((char*)get(getlen() - len, len), data, len);
- release();
- return getlen() - len;
-}
-
-void MMapBuf::setro(BOOL bRO)
-{
- m_fm.setro(bRO);
-}
-
-void MMapBuf::resize(int newlen)
-{
- if (!m_gb_u && newlen < (16 << 20)) // still in db mode
- {
- m_gb.resize(newlen);
- return;
- }
-
- // not in db mode
- m_gb_u = 1;
- m_used = newlen;
-
- if (newlen > m_alloc)
- {
- m_alloc = newlen + (16 << 20); // add 16mb to top of mapping
-
- m_fm.resize(m_alloc);
-
- if (m_gb.getlen())
- {
- memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), m_gb.getlen());
- m_fm.flush(m_gb.getlen());
- m_fm.release();
- m_gb.resize(0);
- }
- }
-}
-
-int MMapBuf::getsize() const
-{
- if (m_gb_u)
- return m_fm.getsize();
- return m_gb.getlen();
-}
-
-int MMapBuf::getlen() const
-{
- if (m_gb_u)
- return m_used;
- return m_gb.getlen();
-}
-
-void *MMapBuf::get() const
-{
- return get(0, m_alloc);
-}
-
-void *MMapBuf::get(int offset, int *sizep) const
-{
- if (!sizep)
- return NULL;
- int size = *sizep;
- return get(offset, size);
-}
-
-void *MMapBuf::get(int offset, int size) const
-{
- if (m_gb_u)
- return m_fm.get(offset, size);
- return (void *) ((char *) m_gb.get() + offset);
-}
-
-void *MMapBuf::getmore(int offset, int size) const
-{
- if (m_gb_u)
- return m_fm.getmore(offset, size);
- return (void *) ((char *) m_gb.get() + offset);
-}
-
-void MMapBuf::release()
-{
- if (m_gb_u)
- m_fm.release();
-}
-
-void MMapBuf::release(void *pView, int size)
-{
- if (m_gb_u)
- m_fm.release(pView, size);
-}
-
-void MMapBuf::clear()
-{
- if (m_gb_u)
- m_fm.clear();
-}
-
-void MMapBuf::flush(int num)
-{
- if (m_gb_u)
- m_fm.flush(num);
-}
+/* + * mmap.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "mmap.h" + +#include <cstdio> // for f* +#include <cassert> // for assert +#ifndef _WIN32 +# include <sys/types.h> // for freebsd +# include <sys/mman.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <unistd.h> +#endif + +// ======== +// MMapFile +// ======== + +int MMapFile::m_iAllocationGranularity = 0; + +MMapFile::MMapFile() +{ +#ifdef _WIN32 + m_hFile = INVALID_HANDLE_VALUE; + m_hFileMap = NULL; +#else + m_hFile = NULL; + m_hFileDesc = -1; +#endif + + m_pView = NULL; + m_iSize = 0; + m_bReadOnly = FALSE; + m_bTempHandle = FALSE; + + if (!m_iAllocationGranularity) + { +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + m_iAllocationGranularity = (int) si.dwAllocationGranularity; +#else + m_iAllocationGranularity = getpagesize(); +#endif + } +} + +MMapFile::~MMapFile() +{ + clear(); +} + +void MMapFile::clear() +{ + release(); + +#ifdef _WIN32 + if (m_hFileMap) + CloseHandle(m_hFileMap); + if (m_bTempHandle && m_hFile != INVALID_HANDLE_VALUE) + CloseHandle(m_hFile); + + m_hFile = INVALID_HANDLE_VALUE; + m_hFileMap = 0; +#else + if (m_bTempHandle && m_hFile) + fclose(m_hFile); + + m_hFile = NULL; +#endif +} + +void MMapFile::setro(BOOL bRO) +{ + m_bReadOnly = bRO; +} + +#ifdef _WIN32 +int MMapFile::setfile(HANDLE hFile, DWORD dwSize) +#else +int MMapFile::setfile(int hFile, DWORD dwSize) +#endif +{ + clear(); + +#ifdef _WIN32 + m_hFile = hFile; +#else + m_hFileDesc = hFile; +#endif + m_bTempHandle = FALSE; + +#ifdef _WIN32 + if (m_hFile == INVALID_HANDLE_VALUE) +#else + if (m_hFileDesc == -1) +#endif + return 0; + + m_iSize = (int) dwSize; + + if (m_iSize <= 0) + return 0; + +#ifdef _WIN32 + m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, m_iSize, NULL); + + if (!m_hFileMap) + return 0; +#endif + + m_bReadOnly = TRUE; + + return 1; +} + +void MMapFile::resize(int newsize) +{ + release(); + + if (newsize > m_iSize) + { +#ifdef _WIN32 + if (m_hFileMap) + CloseHandle(m_hFileMap); + + m_hFileMap = 0; +#endif + + m_iSize = newsize; + +#ifdef _WIN32 + 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 | FILE_FLAG_SEQUENTIAL_SCAN, + NULL + ); + + m_bTempHandle = TRUE; + } + + if (m_hFile != INVALID_HANDLE_VALUE) + { + m_hFileMap = CreateFileMapping( + m_hFile, + NULL, + m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, + 0, + m_iSize, + NULL + ); + } +#else + if (m_hFile == NULL) + { + m_hFile = tmpfile(); + if (m_hFile != NULL) + { + m_hFileDesc = fileno(m_hFile); + m_bTempHandle = TRUE; + } + } + + // resize + if (m_hFileDesc != -1) + { + unsigned char c = 0; + + if (lseek(m_hFileDesc, m_iSize, SEEK_SET) != (off_t)-1) + { + if (read(m_hFileDesc, &c, 1) != -1) + { + if (lseek(m_hFileDesc, m_iSize, SEEK_SET) != (off_t)-1) + { + if (write(m_hFileDesc, &c, 1) != -1) + { + return; // no errors + } + } + } + } + } + + m_hFileDesc = -1; // some error occurred, bail +#endif + +#ifdef _WIN32 + if (!m_hFileMap) +#else + if (m_hFileDesc == -1) +#endif + { + extern FILE *g_output; + extern void quit(); extern int g_display_errors; + if (g_display_errors) + { + fprintf(g_output,"\nInternal compiler error #12345: error creating mmap the size of %d.\n", m_iSize); + fflush(g_output); + } + quit(); + } + } +} + +int MMapFile::getsize() const +{ + return m_iSize; +} + +void *MMapFile::get(int offset, int size) const +{ + return get(offset, &size); +} + +void *MMapFile::get(int offset, int *sizep) const +{ + if (!sizep) + return NULL; + + assert(!m_pView); + + int size = *sizep; + + if (!m_iSize || offset + size > m_iSize) + { + 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 file (%d, %d) is out of range.\n", offset, size); + fflush(g_output); + } + quit(); + } + + // fix offset + int alignedoffset = offset - (offset % m_iAllocationGranularity); + size += offset - alignedoffset; + +#ifdef _WIN32 + const_cast<MMapFile*>(this)->m_pView = + MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, alignedoffset, size); +#else + const_cast<MMapFile*>(this)->m_pView = + mmap(0, size, m_bReadOnly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, m_hFileDesc, alignedoffset); + const_cast<MMapFile*>(this)->m_iMappedSize = *sizep = size; +#endif + +#ifdef _WIN32 + if (!m_pView) +#else + if (m_pView == MAP_FAILED) +#endif + { + 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", size); + fflush(g_output); + } + quit(); + } + + return (void *)((char *)m_pView + offset - alignedoffset); +} + +void *MMapFile::getmore(int offset, int size) const +{ + void *pView; + void *pViewBackup = m_pView; +#ifndef _WIN32 + int iMappedSizeBackup = m_iMappedSize; +#endif + const_cast<MMapFile*>(this)->m_pView = 0; + pView = get(offset, size); + const_cast<MMapFile*>(this)->m_pView = pViewBackup; +#ifndef _WIN32 + const_cast<MMapFile*>(this)->m_iMappedSize = iMappedSizeBackup; +#endif + return pView; +} + +void MMapFile::release() +{ + if (!m_pView) + return; + +#ifdef _WIN32 + UnmapViewOfFile(m_pView); +#else + munmap(m_pView, m_iMappedSize); +#endif + m_pView = NULL; +} + +void MMapFile::release(void *pView, int size) +{ + if (!pView) + return; + + unsigned int alignment = ((unsigned int)pView) % m_iAllocationGranularity; + pView = (char *)pView - alignment; + size += alignment; +#ifdef _WIN32 + UnmapViewOfFile(pView); +#else + munmap(pView, size); +#endif +} + +void MMapFile::flush(int num) +{ + if (m_pView) +#ifdef _WIN32 + FlushViewOfFile(m_pView, num); +#else + msync(m_pView, num, MS_SYNC); +#endif +} + +// ======== +// MMapFake +// ======== + +MMapFake::MMapFake() +{ + m_pMem = NULL; + m_iSize = 0; +} + +void MMapFake::set(const char *pMem, int iSize) +{ + m_pMem = pMem; + m_iSize = iSize; +} + +int MMapFake::getsize() const +{ + return m_iSize; +} + +void *MMapFake::get(int offset, int size) const +{ + return get(offset, &size); +} + +void *MMapFake::get(int offset, int *size) const +{ + if (!size || (offset + *size > m_iSize)) + return NULL; + return (void *)(m_pMem + offset); +} + +void *MMapFake::getmore(int offset, int size) const +{ + return get(offset, size); +} + +void MMapFake::resize(int n) {} +void MMapFake::release() {} +void MMapFake::release(void *p, int size) {} +void MMapFake::clear() {} +void MMapFake::setro(BOOL b) {} +void MMapFake::flush(BOOL b) {} + +// ======= +// MMapBuf +// ======= + +MMapBuf::MMapBuf() +{ + m_gb_u=0; + m_alloc=m_used=0; +} + +MMapBuf::~MMapBuf() +{ + m_fm.release(); +} + +int MMapBuf::add(const void *data, int len) +{ + if (len <= 0) return 0; + resize(getlen() + len); + memcpy((char*)get(getlen() - len, len), data, len); + release(); + return getlen() - len; +} + +void MMapBuf::setro(BOOL bRO) +{ + m_fm.setro(bRO); +} + +void MMapBuf::resize(int newlen) +{ + if (!m_gb_u && newlen < (16 << 20)) // still in db mode + { + m_gb.resize(newlen); + return; + } + + // not in db mode + m_gb_u = 1; + m_used = newlen; + + if (newlen > m_alloc) + { + m_alloc = newlen + (16 << 20); // add 16mb to top of mapping + + m_fm.resize(m_alloc); + + if (m_gb.getlen()) + { + memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), m_gb.getlen()); + m_fm.flush(m_gb.getlen()); + m_fm.release(); + m_gb.resize(0); + } + } +} + +int MMapBuf::getsize() const +{ + if (m_gb_u) + return m_fm.getsize(); + return m_gb.getlen(); +} + +int MMapBuf::getlen() const +{ + if (m_gb_u) + return m_used; + return m_gb.getlen(); +} + +void *MMapBuf::get() const +{ + return get(0, m_alloc); +} + +void *MMapBuf::get(int offset, int *sizep) const +{ + if (!sizep) + return NULL; + int size = *sizep; + return get(offset, size); +} + +void *MMapBuf::get(int offset, int size) const +{ + if (m_gb_u) + return m_fm.get(offset, size); + return (void *) ((char *) m_gb.get() + offset); +} + +void *MMapBuf::getmore(int offset, int size) const +{ + if (m_gb_u) + return m_fm.getmore(offset, size); + return (void *) ((char *) m_gb.get() + offset); +} + +void MMapBuf::release() +{ + if (m_gb_u) + m_fm.release(); +} + +void MMapBuf::release(void *pView, int size) +{ + if (m_gb_u) + m_fm.release(pView, size); +} + +void MMapBuf::clear() +{ + if (m_gb_u) + m_fm.clear(); +} + +void MMapBuf::flush(int num) +{ + if (m_gb_u) + m_fm.flush(num); +} diff --git a/Source/mmap.h b/Source/mmap.h index 80e6124..77d810b 100755 --- a/Source/mmap.h +++ b/Source/mmap.h @@ -1,144 +1,144 @@ -/*
- * mmap.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef __MMAP_H_
-#define __MMAP_H_
-
-#include "Platform.h"
-#include "growbuf.h"
-
-#ifndef _WIN32
-#include <cstdio> // for FILE*
-#endif
-
-class IMMap
-{
- public:
- virtual void resize(int newlen)=0;
- virtual int getsize() const=0;
- virtual void *get(int offset, int size) const=0;
- virtual void *get(int offset, int *size) const=0;
- virtual void *getmore(int offset, int size) const=0;
- virtual void release()=0;
- virtual void release(void *view, int size)=0;
- virtual void clear()=0;
- virtual void setro(BOOL bRO)=0;
- virtual void flush(int num)=0;
- virtual ~IMMap() {}
-};
-
-class MMapFile : public IMMap
-{
- private: // don't copy instances
- MMapFile(const MMapFile&);
- void operator=(const MMapFile&);
-
- public:
- MMapFile();
- virtual ~MMapFile();
-
- void clear();
- void setro(BOOL bRO);
-#ifdef _WIN32
- int setfile(HANDLE hFile, DWORD dwSize);
-#else
- int setfile(int hFile, DWORD dwSize);
-#endif
- void resize(int newsize);
- int getsize() const;
- void *get(int offset, int size) const;
- void *get(int offset, int *sizep) const;
- void *getmore(int offset, int size) const;
- void release();
- void release(void *pView, int size);
- void flush(int num);
-
- private:
-#ifdef _WIN32
- HANDLE m_hFile, m_hFileMap;
-#else
- FILE *m_hFile;
- int m_hFileDesc;
- int m_iMappedSize;
-#endif
- void *m_pView;
- int m_iSize;
- BOOL m_bReadOnly;
- BOOL m_bTempHandle;
-
- static int m_iAllocationGranularity;
-};
-
-class MMapFake : public IMMap
-{
- private: // don't copy instances
- MMapFake(const MMapFake&);
- void operator=(const MMapFake&);
- public:
- MMapFake();
-
- void set(const char *pMem, int iSize);
- int getsize() const;
- void *get(int offset, int size) const;
- void *get(int offset, int *size) const;
- void *getmore(int offset, int size) const;
-
- void resize(int n);
- void release();
- void release(void *p, int size);
- void clear();
- void setro(BOOL b);
- void flush(BOOL b);
-
- private:
- const char *m_pMem;
- int m_iSize;
-};
-
-class MMapBuf : public IGrowBuf, public IMMap
-{
- private: // don't copy instances
- MMapBuf(const MMapBuf&);
- void operator=(const MMapBuf&);
-
- public:
- MMapBuf();
- virtual ~MMapBuf();
-
- int add(const void *data, int len);
- void setro(BOOL bRO);
- void resize(int newlen);
- int getsize() const;
- int getlen() const;
- void *get() const;
- void *get(int offset, int *sizep) const;
- void *get(int offset, int size) const;
- void *getmore(int offset, int size) const;
- void release();
- void release(void *pView, int size);
- void clear();
- void flush(int num);
-
- private:
- GrowBuf m_gb;
- MMapFile m_fm;
-
- int m_gb_u;
- int m_alloc, m_used;
-};
-
-#endif//__MMAP_H_
-
+/* + * mmap.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef __MMAP_H_ +#define __MMAP_H_ + +#include "Platform.h" +#include "growbuf.h" + +#ifndef _WIN32 +#include <cstdio> // for FILE* +#endif + +class IMMap +{ + public: + virtual void resize(int newlen)=0; + virtual int getsize() const=0; + virtual void *get(int offset, int size) const=0; + virtual void *get(int offset, int *size) const=0; + virtual void *getmore(int offset, int size) const=0; + virtual void release()=0; + virtual void release(void *view, int size)=0; + virtual void clear()=0; + virtual void setro(BOOL bRO)=0; + virtual void flush(int num)=0; + virtual ~IMMap() {} +}; + +class MMapFile : public IMMap +{ + private: // don't copy instances + MMapFile(const MMapFile&); + void operator=(const MMapFile&); + + public: + MMapFile(); + virtual ~MMapFile(); + + void clear(); + void setro(BOOL bRO); +#ifdef _WIN32 + int setfile(HANDLE hFile, DWORD dwSize); +#else + int setfile(int hFile, DWORD dwSize); +#endif + void resize(int newsize); + int getsize() const; + void *get(int offset, int size) const; + void *get(int offset, int *sizep) const; + void *getmore(int offset, int size) const; + void release(); + void release(void *pView, int size); + void flush(int num); + + private: +#ifdef _WIN32 + HANDLE m_hFile, m_hFileMap; +#else + FILE *m_hFile; + int m_hFileDesc; + int m_iMappedSize; +#endif + void *m_pView; + int m_iSize; + BOOL m_bReadOnly; + BOOL m_bTempHandle; + + static int m_iAllocationGranularity; +}; + +class MMapFake : public IMMap +{ + private: // don't copy instances + MMapFake(const MMapFake&); + void operator=(const MMapFake&); + public: + MMapFake(); + + void set(const char *pMem, int iSize); + int getsize() const; + void *get(int offset, int size) const; + void *get(int offset, int *size) const; + void *getmore(int offset, int size) const; + + void resize(int n); + void release(); + void release(void *p, int size); + void clear(); + void setro(BOOL b); + void flush(BOOL b); + + private: + const char *m_pMem; + int m_iSize; +}; + +class MMapBuf : public IGrowBuf, public IMMap +{ + private: // don't copy instances + MMapBuf(const MMapBuf&); + void operator=(const MMapBuf&); + + public: + MMapBuf(); + virtual ~MMapBuf(); + + int add(const void *data, int len); + void setro(BOOL bRO); + void resize(int newlen); + int getsize() const; + int getlen() const; + void *get() const; + void *get(int offset, int *sizep) const; + void *get(int offset, int size) const; + void *getmore(int offset, int size) const; + void release(); + void release(void *pView, int size); + void clear(); + void flush(int num); + + private: + GrowBuf m_gb; + MMapFile m_fm; + + int m_gb_u; + int m_alloc, m_used; +}; + +#endif//__MMAP_H_ + diff --git a/Source/script.cpp b/Source/script.cpp index 69144c3..e291e1f 100755 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -1,6171 +1,6176 @@ -/*
- * script.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <stdio.h>
-#include <ctype.h>
-#include "tokens.h"
-#include "build.h"
-#include "util.h"
-#include "winchar.h"
-#include "ResourceEditor.h"
-#include "DialogTemplate.h"
-#include "lang.h"
-#include "dirreader.h"
-#include "version.h"
-#include "exehead/resource.h"
-#include <cassert> // for assert(3)
-#include <time.h>
-#include <string>
-#include <algorithm>
-#include "boost/scoped_ptr.hpp"
-
-using namespace std;
-
-#ifdef _WIN32
-# include <direct.h> // for chdir
-#else
-# include <sys/stat.h> // for stat and umask
-# include <sys/types.h> // for mode_t
-# include <fcntl.h> // for O_RDONLY
-# include <unistd.h>
-# include <stdlib.h> // for mkstemp
-#endif
-
-#define MAX_INCLUDEDEPTH 10
-#define MAX_LINELENGTH 16384
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
-// Added by Sunil Kamath 11 June 2003
-char *CEXEBuild::set_file_predefine(char *filename)
-{
- char *oldfilename = definedlist.find("__FILE__");
- if(oldfilename)
- {
- oldfilename = strdup(oldfilename);
- definedlist.del("__FILE__");
- }
- char *p = strrchr(filename,'\\');
- if(p) {
- p++;
- }
- else {
- p = curfilename;
- }
- definedlist.add("__FILE__",p);
-
- return oldfilename;
-}
-
-void CEXEBuild::restore_file_predefine(char *oldfilename)
-{
- definedlist.del("__FILE__");
- if(oldfilename) {
- definedlist.add("__FILE__",oldfilename);
- free(oldfilename);
- }
-}
-
-char *CEXEBuild::set_timestamp_predefine(char *filename)
-{
- char *oldtimestamp = definedlist.find("__TIMESTAMP__");
- if(oldtimestamp) {
- oldtimestamp = strdup(oldtimestamp);
- definedlist.del("__TIMESTAMP__");
- }
-
-#ifdef _WIN32
- char timestampbuf[256] = "";
- char datebuf[128] = "";
- char timebuf[128] = "";
- WIN32_FIND_DATA fd;
- FILETIME floctime;
- SYSTEMTIME stime;
-
- HANDLE hSearch = FindFirstFile(filename, &fd);
- if (hSearch != INVALID_HANDLE_VALUE)
- {
- FindClose(hSearch);
-
- FileTimeToLocalFileTime(&fd.ftLastWriteTime, &floctime);
- FileTimeToSystemTime(&floctime, &stime);
-
- GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &stime, NULL, datebuf, sizeof(datebuf));
- GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, sizeof(timebuf));
- wsprintf(timestampbuf,"%s %s",datebuf,timebuf);
-
- definedlist.add("__TIMESTAMP__",timestampbuf);
- }
-#else
- struct stat st;
- if (!stat(filename, &st))
- definedlist.add("__TIMESTAMP__",ctime(&st.st_mtime));
-#endif
-
- return oldtimestamp;
-}
-
-void CEXEBuild::restore_timestamp_predefine(char *oldtimestamp)
-{
- definedlist.del("__TIMESTAMP__");
- if(oldtimestamp) {
- definedlist.add("__TIMESTAMP__",oldtimestamp);
- free(oldtimestamp);
- }
-}
-
-char *CEXEBuild::set_line_predefine(int linecnt, BOOL is_macro)
-{
- char* linebuf = NULL;
- MANAGE_WITH(linebuf, free);
-
- char temp[128] = "";
- sprintf(temp,"%d",linecnt);
-
- char *oldline = definedlist.find("__LINE__");
- if(oldline) {
- oldline = strdup(oldline);
- definedlist.del("__LINE__");
- }
- if(is_macro && oldline) {
- linebuf = (char *)malloc(strlen(oldline)+strlen(temp)+2);
- sprintf(linebuf,"%s.%s",oldline,temp);
- }
- else {
- linebuf = strdup(temp);
- }
- definedlist.add("__LINE__",linebuf);
-
- return oldline;
-}
-
-void CEXEBuild::restore_line_predefine(char *oldline)
-{
- definedlist.del("__LINE__");
- if(oldline) {
- definedlist.add("__LINE__",oldline);
- free(oldline);
- }
-}
-
-void CEXEBuild::set_date_time_predefines()
-{
- time_t etime;
- struct tm * ltime;
- char datebuf[128];
- char timebuf[128];
-
- time(&etime);
- ltime = localtime(&etime);
-#ifdef _WIN32
- SYSTEMTIME stime;
- stime.wYear = ltime->tm_year+1900;
- stime.wMonth = ltime->tm_mon + 1;
- stime.wDay = ltime->tm_mday;
- stime.wHour= ltime->tm_hour;
- stime.wMinute= ltime->tm_min;
- stime.wSecond= ltime->tm_sec;
- stime.wMilliseconds= 0;
- GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, datebuf, sizeof(datebuf));
- definedlist.add("__DATE__",(char *)datebuf);
- GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, sizeof(timebuf));
- definedlist.add("__TIME__",(char *)timebuf);
-#else
- my_strftime(datebuf, sizeof(datebuf), "%x", ltime);
- definedlist.add("__DATE__",(char *)datebuf);
- my_strftime(timebuf, sizeof(timebuf), "%X", ltime);
- definedlist.add("__TIME__",(char *)timebuf);
-#endif
-}
-
-void CEXEBuild::del_date_time_predefines()
-{
- definedlist.del("__DATE__");
- definedlist.del("__TIME__");
-}
-#endif
-
-int CEXEBuild::process_script(FILE *filepointer, char *filename)
-{
- linecnt = 0;
- fp = filepointer;
- curfilename = filename;
-
- if (has_called_write_output)
- {
- ERROR_MSG("Error (process_script): write_output already called, can't continue\n");
- return PS_ERROR;
- }
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- set_date_time_predefines();
- char *oldfilename = set_file_predefine(curfilename);
- char *oldtimestamp = set_timestamp_predefine(curfilename);
-#endif
-
- int ret=parseScript();
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- restore_file_predefine(oldfilename);
- restore_timestamp_predefine(oldtimestamp);
- del_date_time_predefines();
-#endif
-
- fp = 0;
- curfilename = 0;
-
- if (m_linebuild.getlen())
- {
- ERROR_MSG("Error: invalid script: last line ended with \\\n");
- return PS_ERROR;
- }
-
- if (ret == PS_EOF && num_ifblock())
- {
- ERROR_MSG("!if[macro][n]def: open at EOF - need !endif\n");
- return PS_ERROR;
- }
-
- return ret;
-}
-
-#define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; }
-
-void CEXEBuild::start_ifblock()
-{
- ifblock ib = {0, };
- if (cur_ifblock)
- ib.inherited_ignore = cur_ifblock->ignore || cur_ifblock->inherited_ignore;
- int num = build_preprocessor_data.getlen() / sizeof(ifblock);
- build_preprocessor_data.add(&ib, sizeof(ifblock));
- cur_ifblock = (ifblock *) build_preprocessor_data.get() + num;
-}
-
-void CEXEBuild::end_ifblock()
-{
- if (build_preprocessor_data.getlen())
- {
- cur_ifblock--;
- build_preprocessor_data.resize(build_preprocessor_data.getlen() - sizeof(ifblock));
- if (!build_preprocessor_data.getlen())
- cur_ifblock = 0;
- }
-}
-
-int CEXEBuild::num_ifblock()
-{
- return build_preprocessor_data.getlen() / sizeof(ifblock);
-}
-
-// Func size: just under 200 lines (orip)
-int CEXEBuild::doParse(const char *str)
-{
- LineParser line(inside_comment);
- int res;
-
- while (*str == ' ' || *str == '\t') str++;
-
- // remove trailing slash and null, if there's a previous line
- if (m_linebuild.getlen()>1)
- m_linebuild.resize(m_linebuild.getlen()-2);
-
- m_linebuild.add(str,strlen(str)+1);
-
- // keep waiting for more lines, if this line ends with a backslash
- if (str[0] && CharPrev(str,str+strlen(str))[0] == '\\')
- {
- line.parse((char*)m_linebuild.get());
- if (line.inComment())
- {
- warning_fl("comment contains line-continuation character, following line will be ignored");
- }
- return PS_OK;
- }
-
- // parse before checking if the line should be ignored, so block comments won't be missed
-
- // escaped quotes should be ignored for compile time commands that set defines
- // because defines can be inserted in commands at a later stage
- bool ignore_escaping = (!strnicmp((char*)m_linebuild.get(),"!define",7) || !strnicmp((char*)m_linebuild.get(),"!insertmacro",12));
- res=line.parse((char*)m_linebuild.get(), ignore_escaping);
-
- inside_comment = line.inCommentBlock();
-
- // if ignoring, ignore all lines that don't begin with an exclamation mark
- {
- bool ignore_line = cur_ifblock && (cur_ifblock->ignore || cur_ifblock->inherited_ignore);
- char first_char = *(char *) m_linebuild.get();
- if (ignore_line && (first_char!='!' || !is_valid_token(line.gettoken_str(0))))
- {
- m_linebuild.resize(0);
- return PS_OK;
- }
- }
-
- m_linebuild.resize(0);
-
- if (res)
- {
- if (res==-2) ERROR_MSG("Error: unterminated string parsing line at %s:%d\n",curfilename,linecnt);
- else ERROR_MSG("Error: error parsing line (%s:%d)\n",curfilename,linecnt);
- return PS_ERROR;
- }
-
-parse_again:
- if (line.getnumtokens() < 1) return PS_OK;
-
- int np,op,pos;
- int tkid=get_commandtoken(line.gettoken_str(0),&np,&op,&pos);
- if (tkid == -1)
- {
- char *p=line.gettoken_str(0);
- if (p[0] && p[strlen(p)-1]==':')
- {
- if (p[0] == '!' || (p[0] >= '0' && p[0] <= '9') || p[0] == '$' || p[0] == '-' || p[0] == '+')
- {
- ERROR_MSG("Invalid label: %s (labels cannot begin with !, $, -, +, or 0-9)\n",line.gettoken_str(0));
- return PS_ERROR;
- }
- if (add_label(line.gettoken_str(0))) return PS_ERROR;
- line.eattoken();
- goto parse_again;
- }
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- // Added by Ximon Eighteen 5th August 2002
- // We didn't recognise this command, could it be the name of a
- // function exported from a dll?
- if (m_plugins.IsPluginCommand(line.gettoken_str(0)))
- {
- np = 0; // parameters are optional
- op = -1; // unlimited number of optional parameters
- pos = -1; // placement will tested later
- tkid = TOK__PLUGINCOMMAND;
- }
- else
-#endif
- {
- ERROR_MSG("Invalid command: %s\n",line.gettoken_str(0));
- return PS_ERROR;
- }
- }
-
- if (IsTokenPlacedRight(pos, line.gettoken_str(0)) != PS_OK)
- return PS_ERROR;
-
- int v=line.getnumtokens()-(np+1);
- if (v < 0 || (op >= 0 && v > op)) // opt_parms is -1 for unlimited
- {
- ERROR_MSG("%s expects %d",line.gettoken_str(0),np);
- if (op < 0) ERROR_MSG("+");
- if (op > 0) ERROR_MSG("-%d",op+np);
- ERROR_MSG(" parameters, got %d.\n",line.getnumtokens()-1);
- PRINTHELP()
- }
-
- int if_from_else = 0;
-
- if (tkid == TOK_P_ELSE)
- {
- if (cur_ifblock && cur_ifblock->inherited_ignore)
- return PS_OK;
-
- if (!num_ifblock())
- {
- ERROR_MSG("!else: no if block open (!if[macro][n][def])\n");
- return PS_ERROR;
- }
-
- if (cur_ifblock->elseused)
- {
- ERROR_MSG("!else: else already used in current if block\n");
- return PS_ERROR;
- }
-
- if (cur_ifblock->hasexeced)
- {
- cur_ifblock->ignore++;
- return PS_OK;
- }
-
- if (line.getnumtokens() == 1)
- {
- cur_ifblock->ignore = !cur_ifblock->ignore;
- // if not executed up until now, it will now
- cur_ifblock->hasexeced++;
- cur_ifblock->elseused++;
- return PS_OK;
- }
-
- line.eattoken();
-
- int v=line.gettoken_enum(0,"if\0ifdef\0ifndef\0ifmacrodef\0ifmacrondef\0");
- if (v < 0) PRINTHELP()
- if (line.getnumtokens() == 1) PRINTHELP()
- int cmds[] = {TOK_P_IF, TOK_P_IFDEF, TOK_P_IFNDEF, TOK_P_IFMACRODEF, TOK_P_IFMACRONDEF};
- tkid = cmds[v];
- if_from_else++;
- }
-
- if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF ||
- tkid == TOK_P_IFMACRODEF || tkid == TOK_P_IFMACRONDEF ||
- tkid == TOK_P_IF)
- {
- if (!if_from_else)
- start_ifblock();
-
- if (cur_ifblock && cur_ifblock->inherited_ignore)
- {
- return PS_OK;
- }
-
- int istrue=0;
-
- int mod=0;
-
- int p=0;
-
- if (tkid == TOK_P_IF) {
- if(!strcmp(line.gettoken_str(1),"!")) {
- p = 1;
- line.eattoken();
- }
-
- if(line.getnumtokens() == 2)
- istrue = line.gettoken_int(1);
-
- else if (line.getnumtokens() == 4) {
- mod = line.gettoken_enum(2,"=\0==\0!=\0<=\0<\0>\0>=\0&\0&&\0|\0||\0");
-
- switch(mod) {
- case 0:
- case 1:
- istrue = stricmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break;
- case 2:
- istrue = stricmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break;
- case 3:
- istrue = line.gettoken_float(1) <= line.gettoken_float(3); break;
- case 4:
- istrue = line.gettoken_float(1) < line.gettoken_float(3); break;
- case 5:
- istrue = line.gettoken_float(1) > line.gettoken_float(3); break;
- case 6:
- istrue = line.gettoken_float(1) >= line.gettoken_float(3); break;
- case 7:
- case 8:
- istrue = line.gettoken_int(1) && line.gettoken_int(3); break;
- case 9:
- case 10:
- istrue = line.gettoken_int(1) || line.gettoken_int(3); break;
- default:
- PRINTHELP()
- }
- }
- else PRINTHELP()
-
- if(p) istrue = !istrue;
- }
-
- else {
-
- // pure left to right precedence. Not too powerful, but useful.
- for (p = 1; p < line.getnumtokens(); p ++)
- {
- if (p & 1)
- {
- int new_s;
- if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)
- new_s=!!definedlist.find(line.gettoken_str(p));
- else
- new_s=MacroExists(line.gettoken_str(p));
- if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFMACRONDEF)
- new_s=!new_s;
-
- if (mod == 0) istrue = istrue || new_s;
- else istrue = istrue && new_s;
- }
- else
- {
- mod=line.gettoken_enum(p,"|\0&\0||\0&&\0");
- if (mod == -1) PRINTHELP()
- mod &= 1;
- }
- }
- }
-
- if (istrue)
- {
- cur_ifblock->hasexeced++;
- cur_ifblock->ignore = 0;
- }
- else
- cur_ifblock->ignore++;
-
- return PS_OK;
- }
- if (tkid == TOK_P_ENDIF) {
- if (!num_ifblock())
- {
- ERROR_MSG("!endif: no if block open (!if[macro][n][def])\n");
- return PS_ERROR;
- }
- end_ifblock();
- return PS_OK;
- }
- if (!cur_ifblock || (!cur_ifblock->ignore && !cur_ifblock->inherited_ignore))
- {
- return doCommand(tkid,line);
- }
-
- return PS_OK;
-}
-
-// Func size: about 140 lines (orip)
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
-void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines /*= false*/)
-#else
-void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist)
-#endif
-{
- // convert $\r, $\n to their literals
- // preprocessor replace ${VAR} and $%VAR% with whatever value
- // note that if VAR does not exist, ${VAR} or $%VAR% will go through unmodified
- const char *in=str;
- while (*in)
- {
- int add=1;
- char *t;
- char c=*in;
- t=CharNext(in);
-
- if (t-in > 1) // handle multibyte chars (no escape)
- {
- linedata.add((void*)in,t-in);
- in=t;
- continue;
- }
- in=t;
-
- if (c == '$')
- {
- if (in[0] == '\\')
- {
- if (in[1] == 'r')
- {
- in+=2;
- c='\r';
- }
- else if (in[1] == 'n')
- {
- in+=2;
- c='\n';
- }
- else if (in[1] == 't')
- {
- in+=2;
- c='\t';
- }
- }
- else if (in[0] == '{')
- {
- char *s=strdup(in+1);
- MANAGE_WITH(s, free);
- char *t=s;
- unsigned int bn = 0;
- while (*t)
- {
- if (*t == '{') bn++;
- if (*t == '}' && bn-- == 0) break;
- t=CharNext(t);
- }
- if (*t && t!=s
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
- && !bIgnoreDefines
-#endif
- )
- {
- *t=0;
- // check for defines inside the define name - ${bla${blo}}
- GrowBuf defname;
- ps_addtoline(s,defname,hist);
- defname.add("",1);
- t=definedlist.find((char*)defname.get());
- if (t && hist.find((char*)defname.get(),0)<0)
- {
- in+=strlen(s)+2;
- add=0;
- hist.add((char*)defname.get(),0);
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
- ps_addtoline(t,linedata,hist,true);
-#else
- ps_addtoline(t,linedata,hist);
-#endif
- hist.delbypos(hist.find((char*)defname.get(),0));
- }
- }
- }
- else if (in[0] == '%')
- {
- char *s=strdup(in+1);
- MANAGE_WITH(s, free);
- char *t=s;
- while (*t)
- {
- if (*t == '%') break;
- t=CharNext(t);
- }
- if (*t && t!=s)
- {
- *t=0;
- // check for defines inside the define name - ${bla${blo}}
- GrowBuf defname;
- ps_addtoline(s,defname,hist);
- defname.add("",1);
- t=getenv((char*)defname.get());
- if (t && hist.find((char*)defname.get(),0)<0)
- {
- in+=strlen(s)+2;
- add=0;
- hist.add((char*)defname.get(),0);
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
- ps_addtoline(t,linedata,hist,true);
-#else
- ps_addtoline(t,linedata,hist);
-#endif
- hist.delbypos(hist.find((char*)defname.get(),0));
- }
- }
- }
-#ifdef NSIS_FIX_DEFINES_IN_STRINGS
- else if (in[0] == '$')
- {
- if (in[1] == '{') // Found $$ before - Don't replace this define
- {
- char *s=strdup(in+2);
- MANAGE_WITH(s, free);
- char *t=s;
- unsigned int bn = 0;
- while (*t)
- {
- if (*t == '{') bn++;
- if (*t == '}' && bn-- == 0) break;
- t=CharNext(t);
- }
- if (*t && t!=s)
- {
- *t=0;
- // add text unchanged
- GrowBuf defname;
- ps_addtoline(s,defname,hist);
- in++;
- }
- }
- else
- {
- linedata.add((void*)&c,1);
- in++;
- }
- }
-#endif
- }
- if (add) linedata.add((void*)&c,1);
- }
-}
-
-int CEXEBuild::parseScript()
-{
- char str[MAX_LINELENGTH];
-
- for (;;)
- {
- char *p=str;
- *p=0;
- fgets(str,MAX_LINELENGTH,fp);
- linecnt++;
- if (feof(fp)&&!str[0]) break;
-
- // remove trailing whitespace
- while (*p) p++;
- if (p > str) p--;
- while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--;
- *++p=0;
-
- StringList hist;
- GrowBuf linedata;
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- char *oldline = set_line_predefine(linecnt, FALSE);
-#endif
-
- ps_addtoline(str,linedata,hist);
- linedata.add((void*)"",1);
- int ret=doParse((char*)linedata.get());
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- restore_line_predefine(oldline);
-#endif
-
- if (ret != PS_OK) return ret;
- }
-
- return PS_EOF;
-}
-
-int CEXEBuild::includeScript(char *f)
-{
- SCRIPT_MSG("!include: \"%s\"\n",f);
- FILE *incfp=FOPEN(f,"rt");
- if (!incfp)
- {
- ERROR_MSG("!include: could not open file: \"%s\"\n",f);
- return PS_ERROR;
- }
-
- // auto-fclose(3) incfp
- MANAGE_WITH(incfp, fclose);
-
- if (build_include_depth >= MAX_INCLUDEDEPTH)
- {
- ERROR_MSG("parseScript: too many levels of includes (%d max).\n",MAX_INCLUDEDEPTH);
- return PS_ERROR;
- }
- build_include_depth++;
-
- int last_linecnt=linecnt;
- linecnt=0;
- char *last_filename=curfilename;
- curfilename=f;
- FILE *last_fp=fp;
- fp=incfp;
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- char *oldfilename = set_file_predefine(curfilename);
- char *oldtimestamp = set_timestamp_predefine(curfilename);
-#endif
-
- int r=parseScript();
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- restore_file_predefine(oldfilename);
- restore_timestamp_predefine(oldtimestamp);
-#endif
-
- int errlinecnt=linecnt;
-
- linecnt=last_linecnt;
- curfilename=last_filename;
- fp=last_fp;
-
- build_include_depth--;
- if (r != PS_EOF && r != PS_OK)
- {
- ERROR_MSG("!include: error in script: \"%s\" on line %d\n",f,errlinecnt);
- return PS_ERROR;
- }
- SCRIPT_MSG("!include: closed: \"%s\"\n",f);
- return PS_OK;
-}
-
-// !ifmacro[n]def based on Anders Kjersem's code
-int CEXEBuild::MacroExists(const char *macroname)
-{
- char *m = (char *) m_macros.get();
-
- while (m && *m)
- {
- // check if macroname matches
- if (!stricmp(m, macroname))
- return 1;
-
- // skip macro name
- m += strlen(m) + 1;
-
- // skip params
- while (*m) m += strlen(m) + 1;
- m++;
-
- // skip data
- while (*m) m += strlen(m) + 1;
- if (m - (char *) m_macros.get() >= m_macros.getlen() - 1) break;
- m++;
- }
- return 0;
-}
-
-int CEXEBuild::process_oneline(char *line, char *filename, int linenum)
-{
- char *last_filename=curfilename;
- curfilename=filename;
- int last_linecnt=linecnt;
- linecnt=linenum;
-
- StringList hist;
- GrowBuf linedata;
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- char *oldfilename = NULL;
- char *oldtimestamp = NULL;
- char *oldline = NULL;
- BOOL is_commandline = !strcmp(filename,"command line");
- BOOL is_macro = !strncmp(filename,"macro:",strlen("macro:"));
-
- if(!is_commandline) { // Don't set the predefines for command line /X option
- if(!is_macro) {
- oldfilename = set_file_predefine(curfilename);
- oldtimestamp = set_timestamp_predefine(curfilename);
- }
- oldline = set_line_predefine(linecnt, is_macro);
- }
-#endif
-
- ps_addtoline(line,linedata,hist);
- linedata.add((void*)"",1);
- int ret=doParse((char*)linedata.get());
-
-#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES
- // Added by Sunil Kamath 11 June 2003
- if(!is_commandline) { // Don't set the predefines for command line /X option
- if(!is_macro) {
- restore_file_predefine(oldfilename);
- restore_timestamp_predefine(oldtimestamp);
- }
- restore_line_predefine(oldline);
- }
-#endif
-
- linecnt=last_linecnt;
- curfilename=last_filename;
-
- return ret;
-}
-
-int CEXEBuild::process_jump(LineParser &line, int wt, int *offs)
-{
- const char *s=line.gettoken_str(wt);
- int v;
-
- if (!stricmp(s,"0") || !stricmp(s,"")) *offs=0;
- else if ((v=GetUserVarIndex(line, wt))>=0)
- {
- *offs=-v-1; // to jump to a user variable target, -variable_index-1 is stored.
- }
- else
- {
- if ((s[0] == '-' || s[0] == '+') && !atoi(s+1))
- {
- ERROR_MSG("Error: Goto targets beginning with '+' or '-' must be followed by nonzero integer (relative jump)\n");
- return 1;
- }
- if ((s[0] >= '0' && s[0] <= '9') || s[0] == '$' || s[0] == '!')
- {
- ERROR_MSG("Error: Goto targets cannot begin with 0-9, $, !\n");
- return 1;
- }
- *offs=ns_label.add(s,0);
- }
- return 0;
-}
-
-#define FLAG_OFFSET(flag) (FIELD_OFFSET(exec_flags, flag)/sizeof(int))
-#define SECTION_FIELD_GET(field) (FIELD_OFFSET(section, field)/sizeof(int))
-#define SECTION_FIELD_SET(field) (-1 - (int)(FIELD_OFFSET(section, field)/sizeof(int)))
-
-// Func size: about 5000 lines (orip)
-int CEXEBuild::doCommand(int which_token, LineParser &line)
-{
- static const char *rootkeys[2] = {
- "HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0SHCTX\0",
- "HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0SHELL_CONTEXT\0"
- };
- static HKEY rootkey_tab[] = {
- HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA,0
- };
-
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- build_plugin_table();
-#endif
-
- multiple_entries_instruction=0;
-
- entry ent={0,};
- switch (which_token)
- {
- // macro shit
- ///////////////////////////////////////////////////////////////////////////////
- case TOK_P_MACRO:
- {
- if (!line.gettoken_str(1)[0]) PRINTHELP()
- char *t=(char *)m_macros.get();
- while (t && *t)
- {
- if (!stricmp(t,line.gettoken_str(1))) break;
- t+=strlen(t)+1;
-
- // advance over parameters
- while (*t) t+=strlen(t)+1;
- t++;
-
- // advance over data
- while (*t) t+=strlen(t)+1;
- if (t-(char *)m_macros.get() >= m_macros.getlen()-1)
- break;
- t++;
- }
- if (t && *t)
- {
- ERROR_MSG("!macro: macro named \"%s\" already found!\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- m_macros.add(line.gettoken_str(1),strlen(line.gettoken_str(1))+1);
-
- int pc;
- for (pc=2; pc < line.getnumtokens(); pc ++)
- {
- if (!line.gettoken_str(pc)[0])
- {
- ERROR_MSG("!macro: macro parameter %d is empty, not valid!\n",pc-1);
- return PS_ERROR;
- }
- int a;
- for (a=2; a < pc; a ++)
- {
- if (!stricmp(line.gettoken_str(pc),line.gettoken_str(a)))
- {
- ERROR_MSG("!macro: macro parameter named %s is used multiple times!\n",
- line.gettoken_str(pc));
- return PS_ERROR;
- }
- }
- m_macros.add(line.gettoken_str(pc),strlen(line.gettoken_str(pc))+1);
- }
- m_macros.add("",1);
-
- for (;;)
- {
- char str[MAX_LINELENGTH];
- char *p=str;
- str[0]=0;
- fgets(str,MAX_LINELENGTH,fp);
- //SCRIPT_MSG("%s%s", str, str[strlen(str)-1]=='\n'?"":"\n");
- if (feof(fp) && !str[0])
- {
- ERROR_MSG("!macro \"%s\": unterminated (no !macroend found in file)!\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- // remove trailing whitespace
- while (*p) p++;
- if (p > str) p--;
- while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--;
- *++p=0;
- LineParser l2(false);
- if (!l2.parse(str))
- {
- if (!stricmp(l2.gettoken_str(0),"!macroend"))
- {
- linecnt++;
- break;
- }
- if (!stricmp(l2.gettoken_str(0),"!macro"))
- {
- ERROR_MSG("Error: can't define a macro inside a macro!\n");
- return PS_ERROR;
- }
- }
- if (str[0]) m_macros.add(str,strlen(str)+1);
- else m_macros.add(" ",2);
- linecnt++;
- }
- m_macros.add("",1);
- }
- return PS_OK;
- case TOK_P_MACROEND:
- ERROR_MSG("!macroend: no macro currently open.\n");
- return PS_ERROR;
- case TOK_P_INSERTMACRO:
- {
- if (!line.gettoken_str(1)[0]) PRINTHELP()
- char *t=(char *)m_macros.get();
- char *m=t;
- while (t && *t)
- {
- if (!stricmp(t,line.gettoken_str(1))) break;
- t+=strlen(t)+1;
-
- // advance over parms
- while (*t) t+=strlen(t)+1;
- t++;
-
- // advance over data
- while (*t) t+=strlen(t)+1;
- if (t-(char *)m_macros.get() >= m_macros.getlen()-1)
- break;
- t++;
- }
- SCRIPT_MSG("!insertmacro: %s\n",line.gettoken_str(1));
- if (!t || !*t)
- {
- ERROR_MSG("!insertmacro: macro named \"%s\" not found!\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- t+=strlen(t)+1;
-
-
- GrowBuf l_define_names;
- DefineList l_define_saves;
- int npr=0;
- // advance over parms
- while (*t)
- {
- char *v=definedlist.find(t);
- if (v)
- {
- l_define_saves.add(t,v);
- definedlist.del(t);
- }
- l_define_names.add(t,strlen(t)+1);
- definedlist.add(t,line.gettoken_str(npr+2));
-
- npr++;
- t+=strlen(t)+1;
- }
- l_define_names.add("",1);
- t++;
- if (npr != line.getnumtokens()-2)
- {
- ERROR_MSG("!insertmacro: macro \"%s\" requires %d parameter(s), passed %d!\n",
- line.gettoken_str(1),npr,line.getnumtokens()-2);
- return PS_ERROR;
- }
-
- int lp=0;
- char str[1024];
- if (m_macro_entry.find(line.gettoken_str(1),0)>=0)
- {
- ERROR_MSG("!insertmacro: macro \"%s\" already being inserted!\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- int npos=m_macro_entry.add(line.gettoken_str(1),0);
-
- wsprintf(str,"macro:%s",line.gettoken_str(1));
- while (*t)
- {
- lp++;
- if (strcmp(t," "))
- {
- int ret=process_oneline(t,str,lp);
- if (ret != PS_OK)
- {
- ERROR_MSG("Error in macro %s on macroline %d\n",line.gettoken_str(1),lp);
- return ret;
- }
- }
- {
- // fix t if process_oneline changed m_macros
- char *nm=(char *)m_macros.get();
- if (nm != m)
- {
- t += nm - m;
- m = nm;
- }
- }
- t+=strlen(t)+1;
- }
- m_macro_entry.delbypos(npos);
- {
- char *p=(char*)l_define_names.get();
- while (*p)
- {
- definedlist.del(p);
- char *v;
- if ((v=l_define_saves.find(p))) definedlist.add(p,v);
- p+=strlen(p)+1;
- }
- }
- SCRIPT_MSG("!insertmacro: end of %s\n",line.gettoken_str(1));
- }
- return PS_OK;
-
- // preprocessor files fun
- ///////////////////////////////////////////////////////////////////////////////
-
- case TOK_P_TEMPFILE:
- {
- char *symbol = line.gettoken_str(1);
- char *fpath;
-
-#ifdef _WIN32
- char buf[MAX_PATH], buf2[MAX_PATH];
-
- GetTempPath(MAX_PATH, buf);
- if (!GetTempFileName(buf, "nst", 0, buf2))
- {
- ERROR_MSG("!tempfile: unable to create temporary file.\n");
- return PS_ERROR;
- }
-
- fpath = buf2;
-#else
- char t[] = "/tmp/makensisXXXXXX";
-
- mode_t old_umask = umask(0077);
-
- int fd = mkstemp(t);
- if (fd == -1) {
- ERROR_MSG("!tempfile: unable to create temporary file.\n");
- return PS_ERROR;
- }
- close(fd);
-
- umask(old_umask);
-
- fpath = t;
-#endif
-
- if (definedlist.add(symbol, fpath))
- {
- ERROR_MSG("!tempfile: \"%s\" already defined!\n", symbol);
- return PS_ERROR;
- }
-
- SCRIPT_MSG("!tempfile: \"%s\"=\"%s\"\n", symbol, fpath);
- }
- return PS_OK;
-
- case TOK_P_DELFILE:
- {
- char *file = line.gettoken_str(1);
-#ifndef _WIN32
- file = my_convert(file);
-#endif
- int result = unlink(file);
-#ifndef _WIN32
- my_convert_free(file);
-#endif
- if (result == -1) {
- ERROR_MSG("!delfile: \"%s\" couldn't be deleted.\n", line.gettoken_str(1));
- return PS_ERROR;
- }
-
- SCRIPT_MSG("!delfile: \"%s\"\n", line.gettoken_str(1));
- }
- return PS_OK;
-
- case TOK_P_APPENDFILE:
- {
- char *file = line.gettoken_str(1);
- char *text = line.gettoken_str(2);
-
- FILE *fp = FOPEN(file, "a");
- if (!fp)
- {
- ERROR_MSG("!appendfile: \"%s\" couldn't be opened.\n", file);
- return PS_ERROR;
- }
-
- if (fputs(text, fp) < 0)
- {
- ERROR_MSG("!appendfile: error writing to \"%s\".\n", file);
- return PS_ERROR;
- }
-
- fclose(fp);
-
- SCRIPT_MSG("!appendfile: \"%s\" \"%s\"\n", file, text);
- }
- return PS_OK;
-
- // page ordering shit
- ///////////////////////////////////////////////////////////////////////////////
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- case TOK_UNINSTPAGE:
- set_uninstall_mode(1);
- case TOK_PAGE:
- {
- if (!uninstall_mode) {
- enable_last_page_cancel = 0;
- if (!stricmp(line.gettoken_str(line.getnumtokens()-1),"/ENABLECANCEL"))
- enable_last_page_cancel = 1;
- }
- else {
- uenable_last_page_cancel = 0;
- if (!stricmp(line.gettoken_str(line.getnumtokens()-1),"/ENABLECANCEL"))
- uenable_last_page_cancel = 1;
- }
-
- int k = line.gettoken_enum(1,"custom\0license\0components\0directory\0instfiles\0uninstConfirm\0");
-
- if (k < 0) PRINTHELP();
-
- if (add_page(k) != PS_OK)
- return PS_ERROR;
-
-#ifndef NSIS_SUPPORT_CODECALLBACKS
- if (!k) {
- ERROR_MSG("Error: custom page specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n");
- return PS_ERROR;
- }
-#endif//!NSIS_SUPPORT_CODECALLBACKS
-
- if (k) {
- // not custom
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- switch (line.getnumtokens() - enable_last_page_cancel) {
- case 6:
- PRINTHELP();
- case 5:
- if (*line.gettoken_str(4))
- cur_page->leavefunc = ns_func.add(line.gettoken_str(4),0);
- case 4:
- if (*line.gettoken_str(3))
- cur_page->showfunc = ns_func.add(line.gettoken_str(3),0);
- case 3:
- if (*line.gettoken_str(2))
- cur_page->prefunc = ns_func.add(line.gettoken_str(2),0);
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS
- }
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- else {
- // a custom page
- switch (line.getnumtokens() - enable_last_page_cancel) {
- case 6:
- PRINTHELP();
- case 5:
- cur_page->caption = add_string(line.gettoken_str(4));
- case 4:
- if (*line.gettoken_str(3))
- cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0);
- case 3:
- if (*line.gettoken_str(2))
- cur_page->prefunc = ns_func.add(line.gettoken_str(2),0);
- break;
- case 2:
- ERROR_MSG("Error: custom page must have a creator function!\n");
- PRINTHELP();
- }
- }
-#endif//NSIS_SUPPORT_CODECALLBACKS
-
- SCRIPT_MSG("%sPage: %s", uninstall_mode?"Uninst":"", line.gettoken_str(1));
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (cur_page->prefunc>=0)
- SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2));
- if (cur_page->showfunc>=0 && k)
- SCRIPT_MSG(" (show:%s)", line.gettoken_str(3));
- if (cur_page->leavefunc>=0)
- SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4-!k));
- else if (cur_page->caption && !k)
- SCRIPT_MSG(" (caption:%s)", line.gettoken_str(3));
-#endif
- SCRIPT_MSG("\n");
-
- page_end();
-
- if (k == PAGE_INSTFILES) {
- add_page(PAGE_COMPLETED);
- page_end();
- }
-
- set_uninstall_mode(0);
- }
- return PS_OK;
-
- // extended page setting
- case TOK_PAGEEX:
- {
- int k = line.gettoken_enum(1,"custom\0license\0components\0directory\0instfiles\0uninstConfirm\0");
- if (k < 0) {
- k = line.gettoken_enum(1,"un.custom\0un.license\0un.components\0un.directory\0un.instfiles\0un.uninstConfirm\0");
- if (k < 0) PRINTHELP();
- set_uninstall_mode(1);
- }
-
- SCRIPT_MSG("PageEx: %s\n", line.gettoken_str(1));
-
- if (add_page(k) != PS_OK)
- return PS_ERROR;
-
- cur_page->flags |= PF_PAGE_EX;
- }
- return PS_OK;
-
- case TOK_PAGEEXEND:
- {
- SCRIPT_MSG("PageExEnd\n");
-
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- if (cur_page_type == PAGE_CUSTOM && !cur_page->prefunc) {
- ERROR_MSG("Error: custom pages must have a creator function.\n");
- return PS_ERROR;
- }
-#endif
-
- page_end();
-
- if (cur_page_type == PAGE_INSTFILES) {
- add_page(PAGE_COMPLETED);
- page_end();
- }
-
- set_uninstall_mode(0);
- }
- return PS_OK;
- case TOK_PAGECALLBACKS:
-#ifdef NSIS_SUPPORT_CODECALLBACKS
- {
- SCRIPT_MSG("PageCallbacks:");
-
- if (cur_page_type == PAGE_CUSTOM)
- {
- switch (line.getnumtokens())
- {
- case 4:
- {
- PRINTHELP();
- }
- case 3:
- {
- if (*line.gettoken_str(2))
- {
- if (strnicmp(line.gettoken_str(2), "un.", 3))
- {
- if (uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- else
- {
- if (!uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- cur_page->leavefunc = ns_func.add(line.gettoken_str(2),0);
- }
- }
- case 2:
- {
- if (*line.gettoken_str(1))
- {
- if (strnicmp(line.gettoken_str(1), "un.", 3))
- {
- if (uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- else
- {
- if (!uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- cur_page->prefunc = ns_func.add(line.gettoken_str(1),0);
- }
- }
- }
- }
- else
- {
- switch (line.getnumtokens())
- {
- case 4:
- {
- if (*line.gettoken_str(3))
- {
- if (strnicmp(line.gettoken_str(3), "un.", 3))
- {
- if (uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- else
- {
- if (!uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0);
- }
- }
- case 3:
- {
- if (*line.gettoken_str(2))
- {
- if (strnicmp(line.gettoken_str(2), "un.", 3))
- {
- if (uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- else
- {
- if (!uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- cur_page->showfunc = ns_func.add(line.gettoken_str(2),0);
- }
- }
- case 2:
- {
- if (*line.gettoken_str(1))
- {
- if (strnicmp(line.gettoken_str(1), "un.", 3))
- {
- if (uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- else
- {
- if (!uninstall_mode)
- {
- ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n");
- return PS_ERROR;
- }
- }
- cur_page->prefunc = ns_func.add(line.gettoken_str(1),0);
- }
- }
- }
- }
-
- int custom = cur_page_type == PAGE_CUSTOM ? 1 : 0;
-
- if (cur_page->prefunc>=0)
- SCRIPT_MSG(" %s:%s", !custom?"pre":"creator", line.gettoken_str(1));
- if (cur_page->showfunc>=0 && !custom)
- SCRIPT_MSG(" show:%s", line.gettoken_str(2));
- if (cur_page->leavefunc>=0)
- SCRIPT_MSG(" leave:%s", line.gettoken_str(3-custom));
-
- SCRIPT_MSG("\n");
- }
- return PS_OK;
-#else
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_SUPPORT_CODECALLBACKS
-#else
- case TOK_PAGE:
- case TOK_UNINSTPAGE:
- case TOK_PAGEEX:
- case TOK_PAGEEXEND:
- case TOK_PAGECALLBACKS:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_CONFIG_VISIBLE_SUPPORT
- // header flags
- ///////////////////////////////////////////////////////////////////////////////
- case TOK_LANGSTRING:
- {
- char *name = line.gettoken_str(1);
- LANGID lang = line.gettoken_int(2);
- char *str = line.gettoken_str(3);
- int ret = SetLangString(name, lang, str);
- if (ret == PS_WARNING)
- warning_fl("LangString \"%s\" set multiple times for %d, wasting space", name, lang);
- else if (ret == PS_ERROR) {
- ERROR_MSG("Error: can't set LangString \"%s\"!\n", name);
- return PS_ERROR;
- }
- SCRIPT_MSG("LangString: \"%s\" %d \"%s\"\n", name, lang, str);
- }
- return PS_OK;
- case TOK_LANGSTRINGUP:
- SCRIPT_MSG("Error: LangStringUP is obsolete, there are no more unprocessed strings. Use LangString.\n");
- return PS_ERROR;
- case TOK_LICENSELANGSTRING:
- {
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG))
- {
- warning_fl("LicenseLangString: SilentInstall enabled, wasting space");
- }
-#endif
- char *name = line.gettoken_str(1);
- LANGID lang = line.gettoken_int(2);
- char *file = line.gettoken_str(3);
-
- FILE *fp;
- unsigned int datalen;
- fp=FOPEN(file,"rb");
- if (!fp)
- {
- ERROR_MSG("LicenseLangString: open failed \"%s\"\n",file);
- PRINTHELP()
- }
- MANAGE_WITH(fp, fclose);
- fseek(fp,0,SEEK_END);
- datalen=ftell(fp);
- if (!datalen)
- {
- ERROR_MSG("LicenseLangString: empty license file \"%s\"\n",file);
- return PS_ERROR;
- }
- rewind(fp);
- char *data=(char*)malloc(datalen+2);
- if (!data)
- {
- ERROR_MSG("Internal compiler error #12345: LicenseData malloc(%d) failed.\n", datalen+2);
- return PS_ERROR;
- }
- MANAGE_WITH(data, free);
- char *ldata=data+1;
- if (fread(ldata,1,datalen,fp) != datalen)
- {
- ERROR_MSG("LicenseLangString: can't read file.\n");
- return PS_ERROR;
- }
- ldata[datalen]=0;
- if (!strncmp(ldata,"{\\rtf",sizeof("{\\rtf")-1))
- *data = SF_RTF;
- else
- *data = SF_TEXT;
-
- int ret = SetLangString(name, lang, data);
- if (ret == PS_WARNING)
- warning_fl("LicenseLangString \"%s\" set multiple times for %d, wasting space", name, lang);
- else if (ret == PS_ERROR)
- {
- ERROR_MSG("Error: can't set LicenseLangString \"%s\"!\n", name);
- return PS_ERROR;
- }
-
- SCRIPT_MSG("LicenseLangString: \"%s\" %d \"%s\"\n", name, lang, file);
- }
- return PS_OK;
- case TOK_NAME:
- {
- if (SetInnerString(NLF_NAME,line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- SetInnerString(NLF_NAME_DA,line.gettoken_str(2));
- SCRIPT_MSG("Name: \"%s\"",line.gettoken_str(1));
- if (*line.gettoken_str(2))
- SCRIPT_MSG(" \"%s\"",line.gettoken_str(2));
- SCRIPT_MSG("\n");
- }
- return PS_OK;
- case TOK_CAPTION:
- {
- if (!cur_page)
- {
- if (SetInnerString(NLF_CAPTION,line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- }
- else
- {
- cur_page->caption = add_string(line.gettoken_str(1));
- }
- SCRIPT_MSG("Caption: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_ICON:
- SCRIPT_MSG("Icon: \"%s\"\n",line.gettoken_str(1));
- try {
- init_res_editor();
- replace_icon(res_editor, IDI_ICON2, line.gettoken_str(1));
- }
- catch (exception& err) {
- ERROR_MSG("Error while setting icon to \"%s\": %s\n", line.gettoken_str(1), err.what());
- return PS_ERROR;
- }
- return PS_OK;
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- case TOK_CHECKBITMAP:
- SCRIPT_MSG("CheckBitmap: \"%s\"\n",line.gettoken_str(1));
- try {
- init_res_editor();
- int err = update_bitmap(res_editor, IDB_BITMAP1, line.gettoken_str(1), 96, 16, 8);
- if (err) {
- switch (err) {
- case -1:
- ERROR_MSG("Error: can't find bitmap\n");
- break;
- case -2:
- ERROR_MSG("Error: invalid bitmap file - corrupted or not a bitmap\n");
- break;
- case -3:
- ERROR_MSG("Error: bitmap isn't 96x16 in size\n");
- break;
- case -4:
- ERROR_MSG("Error: bitmap has more than 8bpp\n");
- break;
- }
- return PS_ERROR;
- }
- }
- catch (exception& err) {
- ERROR_MSG("Error while replacing bitmap: %s\n", err.what());
- return PS_ERROR;
- }
- return PS_OK;
-#else//NSIS_CONFIG_COMPONENTPAGE
- case TOK_CHECKBITMAP:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_COMPONENTPAGE
- case TOK_DIRTEXT:
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- {
- if (!cur_page) {
- if (SetInnerString(NLF_DIR_TEXT, line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- if (line.getnumtokens() > 2)
- SetInnerString(NLF_DIR_SUBTEXT, line.gettoken_str(2));
- if (line.getnumtokens() > 3)
- SetInnerString(NLF_BTN_BROWSE, line.gettoken_str(3));
- if (line.getnumtokens() > 4)
- SetInnerString(NLF_DIR_BROWSETEXT, line.gettoken_str(4));
- }
- else {
- if (cur_page_type != PAGE_DIRECTORY) {
- ERROR_MSG("Error: DirText can only be used inside PageEx directory.\n");
- return PS_ERROR;
- }
- cur_page->parms[0] = add_string(line.gettoken_str(1));
- if (line.getnumtokens() > 2)
- cur_page->parms[1] = add_string(line.gettoken_str(2));
- if (line.getnumtokens() > 3)
- cur_page->parms[2] = add_string(line.gettoken_str(3));
- if (line.getnumtokens() > 4)
- cur_page->parms[3] = add_string(line.gettoken_str(4));
- }
- SCRIPT_MSG("DirText: \"%s\" \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- }
- return PS_OK;
-#else//NSIS_CONFIG_VISIBLE_SUPPORT
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_VISIBLE_SUPPORT
- case TOK_DIRVAR:
- {
- if (cur_page_type != PAGE_DIRECTORY && cur_page_type != PAGE_UNINSTCONFIRM) {
- ERROR_MSG("Error: can't use DirVar outside of PageEx directory|uninstConfirm.\n");
- return PS_ERROR;
- }
- cur_page->parms[4] = GetUserVarIndex(line, 1) + 1;
- if (cur_page->parms[4] <= 0) PRINTHELP();
- SCRIPT_MSG("DirVar: %s\n", line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_DIRVERIFY:
- {
- if (cur_page_type != PAGE_DIRECTORY) {
- ERROR_MSG("Error: can't use DirVerify outside of PageEx directory.\n");
- return PS_ERROR;
- }
- cur_page->flags &= ~PF_DIR_NO_BTN_DISABLE;
- int k = line.gettoken_enum(1,"auto\0leave\0");
- if (k == -1)
- PRINTHELP();
- if (k)
- cur_page->flags |= PF_DIR_NO_BTN_DISABLE;
- SCRIPT_MSG("DirVerify: %s\n", line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_GETINSTDIRERROR:
- ent.which = EW_GETFLAG;
- ent.offsets[0] = GetUserVarIndex(line, 1);
- ent.offsets[1] = FLAG_OFFSET(instdir_error);
- return add_entry(&ent);
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- case TOK_COMPTEXT:
- {
- if (!cur_page) {
- if (SetInnerString(NLF_COMP_TEXT, line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- if (line.getnumtokens() > 2)
- SetInnerString(NLF_COMP_SUBTEXT1, line.gettoken_str(2));
- if (line.getnumtokens() > 3)
- SetInnerString(NLF_COMP_SUBTEXT2, line.gettoken_str(3));
- }
- else {
- if (cur_page_type != PAGE_COMPONENTS) {
- ERROR_MSG("Error: ComponentText can only be used inside PageEx components.\n");
- return PS_ERROR;
- }
- cur_page->parms[0] = add_string(line.gettoken_str(1));
- cur_page->parms[1] = add_string(line.gettoken_str(2));
- cur_page->parms[2] = add_string(line.gettoken_str(3));
- cur_page->parms[3] = cur_page->parms[1];
- cur_page->parms[4] = cur_page->parms[2];
- }
- SCRIPT_MSG("ComponentText: \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- }
- return PS_OK;
- case TOK_INSTTYPE:
- {
- int x;
-
- if (!stricmp(line.gettoken_str(1),"/NOCUSTOM"))
- {
- build_header.flags|=CH_FLAGS_NO_CUSTOM;
- SCRIPT_MSG("InstType: disabling custom install type\n");
- }
- else if (!stricmp(line.gettoken_str(1),"/COMPONENTSONLYONCUSTOM"))
- {
- build_header.flags|=CH_FLAGS_COMP_ONLY_ON_CUSTOM;
- SCRIPT_MSG("InstType: making components viewable only on custom install type\n");
- }
- else if (!strnicmp(line.gettoken_str(1),"/CUSTOMSTRING=",14))
- {
- SCRIPT_MSG("InstType: setting custom text to: \"%s\"\n",line.gettoken_str(1)+14);
- if (SetInnerString(NLF_COMP_CUSTOM,line.gettoken_str(1)+14) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space","InstType /CUSTOMSTRING");
- }
- else if (line.gettoken_str(1)[0]=='/')
- {
- PRINTHELP()
- }
- else
- {
- char *itname = line.gettoken_str(1);
-
- if (!strnicmp(itname, "un.", 3)) {
- set_uninstall_mode(1);
- itname += 3;
- }
-
- for (x = 0; x < NSIS_MAX_INST_TYPES && cur_header->install_types[x]; x ++);
- if (x == NSIS_MAX_INST_TYPES)
- {
- ERROR_MSG("InstType: no more than %d install types allowed. %d specified\n", NSIS_MAX_INST_TYPES, NSIS_MAX_INST_TYPES + 1);
- return PS_ERROR;
- }
- else
- {
- cur_header->install_types[x] = add_string(itname);
- SCRIPT_MSG("InstType: %s%d=\"%s\"\n", uninstall_mode ? "(uninstall) " : "", x+1, itname);
- }
-
- set_uninstall_mode(0);
- }
- }
- return PS_OK;
-#else//NSIS_CONFIG_COMPONENTPAGE
- case TOK_COMPTEXT:
- case TOK_INSTTYPE:
- ERROR_MSG("Error: %s specified but NSIS_CONFIG_COMPONENTPAGE not defined\n",line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_CONFIG_LICENSEPAGE
- case TOK_LICENSETEXT:
- {
- if (!cur_page) {
- if (SetInnerString(NLF_LICENSE_TEXT, line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- SetInnerString(NLF_LICENSE_TEXT_FSRB, line.gettoken_str(1));
- SetInnerString(NLF_LICENSE_TEXT_FSCB, line.gettoken_str(1));
- if (line.getnumtokens() > 2)
- SetInnerString(NLF_BTN_LICENSE, line.gettoken_str(2));
- }
- else {
- if (cur_page_type != PAGE_LICENSE) {
- ERROR_MSG("Error: LicenseText can only be used inside PageEx license.\n");
- return PS_ERROR;
- }
- cur_page->parms[0] = add_string(line.gettoken_str(1));
- cur_page->next = add_string(line.gettoken_str(2));
- }
- SCRIPT_MSG("LicenseText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2));
- }
- return PS_OK;
- case TOK_LICENSEDATA:
- {
- int idx = 0;
- char *file = line.gettoken_str(1);
- char *data = NULL;
-
- if (file[0] == '$' && file[1] == '(')
- {
- char *cp = strdup(file+2);
- MANAGE_WITH(cp, free);
- char *p = strchr(cp, ')');
- if (p && p[1] == 0) { // if string is only a language str identifier
- *p = 0;
- idx = DefineLangString(cp, 0);
- }
- data = file;
- }
-
- if (!idx)
- {
- unsigned int datalen;
- FILE *fp=FOPEN(file,"rb");
- if (!fp)
- {
- ERROR_MSG("LicenseData: open failed \"%s\"\n",file);
- PRINTHELP()
- }
- MANAGE_WITH(fp, fclose);
- fseek(fp,0,SEEK_END);
- datalen=ftell(fp);
- if (!datalen)
- {
- ERROR_MSG("LicenseData: empty license file \"%s\"\n",file);
- return PS_ERROR;
- }
- rewind(fp);
- data=(char*)malloc(datalen+2);
- if (!data)
- {
- ERROR_MSG("Internal compiler error #12345: LicenseData malloc(%d) failed.\n", datalen+2);
- return PS_ERROR;
- }
- //MANAGE_WITH(data, free);
- char *ldata=data+1;
- if (fread(ldata,1,datalen,fp) != datalen) {
- ERROR_MSG("LicenseData: can't read file.\n");
- free(data); // TODO: fix later (orip)
- return PS_ERROR;
- }
- ldata[datalen]=0;
- if (!strncmp(ldata,"{\\rtf",sizeof("{\\rtf")-1))
- *data = SF_RTF;
- else
- *data = SF_TEXT;
- }
-
- if (!cur_page) {
- if (SetInnerString(NLF_LICENSE_DATA,data) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- }
- else {
- if (cur_page_type != PAGE_LICENSE) {
- ERROR_MSG("Error: LicenseData can only be used inside PageEx license.\n");
- return PS_ERROR;
- }
-
- cur_page->parms[1] = add_string(data, 0);
- }
-
- if (!idx) free(data); // TODO: fix later (orip)
-
- SCRIPT_MSG("LicenseData: \"%s\"\n",file);
- }
- return PS_OK;
- case TOK_LICENSEFORCESELECTION:
- {
- int k=line.gettoken_enum(1,"off\0checkbox\0radiobuttons\0");
- if (k == -1) PRINTHELP()
- if (k < line.getnumtokens() - 2) PRINTHELP()
-
- if (!cur_page) {
- switch (line.getnumtokens()) {
- case 4:
- SetInnerString(NLF_BTN_LICENSE_DISAGREE, line.gettoken_str(3));
- case 3:
- SetInnerString(NLF_BTN_LICENSE_AGREE, line.gettoken_str(2));
- break;
- }
-
- switch (k) {
- case 0:
- license_res_id = IDD_LICENSE;
- break;
- case 1:
- license_res_id = IDD_LICENSE_FSCB;
- break;
- case 2:
- license_res_id = IDD_LICENSE_FSRB;
- break;
- }
- }
- else {
- if (cur_page_type != PAGE_LICENSE) {
- ERROR_MSG("Error: LicenseForceSelection can only be used inside PageEx license.\n");
- return PS_ERROR;
- }
- switch (line.getnumtokens()) {
- case 4:
- cur_page->parms[3] = add_string(line.gettoken_str(3));
- case 3:
- cur_page->parms[2] = add_string(line.gettoken_str(2));
- break;
- }
-
- cur_page->flags &= ~(PF_LICENSE_FORCE_SELECTION | PF_LICENSE_NO_FORCE_SELECTION);
-
- switch (k) {
- case 0:
- cur_page->dlg_id = IDD_LICENSE;
- cur_page->flags |= PF_LICENSE_NO_FORCE_SELECTION;
- break;
- case 1:
- cur_page->dlg_id = IDD_LICENSE_FSCB;
- cur_page->flags |= PF_LICENSE_FORCE_SELECTION;
- break;
- case 2:
- cur_page->dlg_id = IDD_LICENSE_FSRB;
- cur_page->flags |= PF_LICENSE_FORCE_SELECTION;
- break;
- }
- }
-
- SCRIPT_MSG("LicenseForceSelection: %s \"%s\" \"%s\"\n", line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3));
- }
- return PS_OK;
- case TOK_LICENSEBKCOLOR:
- {
- char *p = line.gettoken_str(1);
- if (!strcmpi(p,"/windows"))
- {
- build_header.license_bg=-COLOR_WINDOW;
- SCRIPT_MSG("LicenseBkColor: /windows\n");
- }
- else if (!strcmpi(p,"/grey") || !strcmpi(p,"/gray"))
- {
- build_header.license_bg=-COLOR_BTNFACE;
- SCRIPT_MSG("LicenseBkColor: /grey\n");
- }
- else
- {
- int v=strtoul(p,&p,16);
- build_header.license_bg=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
- build_uninst.license_bg=build_header.license_bg;
- SCRIPT_MSG("LicenseBkColor: %06X\n",v);
- }
- }
- return PS_OK;
-#else//!NSIS_CONFIG_LICENSEPAGE
- case TOK_LICENSETEXT:
- case TOK_LICENSEDATA:
- case TOK_LICENSEBKCOLOR:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_LICENSEPAGE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_LICENSEPAGE
-#ifdef NSIS_CONFIG_SILENT_SUPPORT
- case TOK_SILENTINST:
- {
- int k=line.gettoken_enum(1,"normal\0silent\0silentlog\0");
- if (k<0) PRINTHELP()
-#ifndef NSIS_CONFIG_LOG
- if (k == 2)
- {
- ERROR_MSG("SilentInstall: silentlog specified, no log support compiled in (use NSIS_CONFIG_LOG)\n");
- return PS_ERROR;
- }
-#endif//NSIS_CONFIG_LOG
- SCRIPT_MSG("SilentInstall: %s\n",line.gettoken_str(1));
-#ifdef NSIS_CONFIG_LICENSEPAGE
- if (k && HasUserDefined(NLF_LICENSE_DATA))
- {
- warning_fl("SilentInstall: LicenseData already specified. wasting space");
- }
- if (k) {
- build_header.flags|=CH_FLAGS_SILENT;
- if (k == 2)
- build_header.flags|=CH_FLAGS_SILENT_LOG;
- }
- else {
- build_header.flags&=~CH_FLAGS_SILENT;
- build_header.flags&=~CH_FLAGS_SILENT_LOG;
- }
-#endif//NSIS_CONFIG_LICENSEPAGE
- }
- return PS_OK;
- case TOK_SILENTUNINST:
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- {
- int k=line.gettoken_enum(1,"normal\0silent\0");
- if (k<0) PRINTHELP()
- if (k)
- build_uninst.flags|=CH_FLAGS_SILENT;
- else
- build_uninst.flags&=~CH_FLAGS_SILENT;
- SCRIPT_MSG("SilentUnInstall: %s\n",line.gettoken_str(1));
- }
- return PS_OK;
-#else
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif
- case TOK_IFSILENT:
- ent.which=EW_IFFLAG;
- if (process_jump(line,1,&ent.offsets[0]) ||
- process_jump(line,2,&ent.offsets[1])) PRINTHELP()
- ent.offsets[2]=FLAG_OFFSET(silent);
- ent.offsets[3]=~0;//new value mask - keep flag
- SCRIPT_MSG("IfSilent ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SETSILENT:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(silent);
- int k=line.gettoken_enum(1,"normal\0silent\0");
- if (k<0) PRINTHELP()
- ent.offsets[1]=add_intstring(k);
- SCRIPT_MSG("SetSilent: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
-#else//!NSIS_CONFIG_SILENT_SUPPORT
- case TOK_SILENTINST:
- case TOK_SILENTUNINST:
- case TOK_IFSILENT:
- case TOK_SETSILENT:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_SILENT_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_CONFIG_SILENT_SUPPORT
- case TOK_OUTFILE:
- strncpy(build_output_filename,line.gettoken_str(1),1024-1);
- SCRIPT_MSG("OutFile: \"%s\"\n",build_output_filename);
- return PS_OK;
- case TOK_INSTDIR:
- {
- char *p = line.gettoken_str(1);
- if (build_header.install_directory_ptr)
- {
- warning_fl("%s: specified multiple times. wasting space",line.gettoken_str(0));
- }
- build_header.install_directory_ptr = add_string(p);
- build_header.install_directory_auto_append = 0;
- char *p2 = p + strlen(p);
- if (*p && *CharPrev(p, p2) != '\\')
- {
- // we risk hitting $\r or something like $(bla\ad) or ${bla\ad} here, but it's better
- // than hitting backslashes in processed strings
- while (p2 > p && *p2 != '\\')
- p2 = CharPrev(p, p2);
- if (*p2 == '\\')
- {
- build_header.install_directory_auto_append = add_string(p2 + 1);
- }
- }
- SCRIPT_MSG("InstallDir: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_INSTALLDIRREGKEY: // InstallDirRegKey
- {
- if (build_header.install_reg_key_ptr)
- {
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- }
- int k=line.gettoken_enum(1,rootkeys[0]);
- if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
- if (k == -1) PRINTHELP()
- build_header.install_reg_rootkey=(int)rootkey_tab[k];
- if (!build_header.install_reg_rootkey) PRINTHELP() // SHCTX is invalid here
- build_header.install_reg_key_ptr = add_string(line.gettoken_str(2),0);
- if (line.gettoken_str(2)[0] == '\\')
- warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0));
- build_header.install_reg_value_ptr = add_string(line.gettoken_str(3),0);
- SCRIPT_MSG("InstallRegKey: \"%s\\%s\\%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- }
- return PS_OK;
- case TOK_CRCCHECK:
- build_crcchk=line.gettoken_enum(1,"off\0on\0force\0");
- if (build_crcchk==-1) PRINTHELP()
- SCRIPT_MSG("CRCCheck: %s\n",line.gettoken_str(1));
- return PS_OK;
- case TOK_INSTPROGRESSFLAGS:
- {
- int x;
- int smooth=0;
- build_header.flags&=~CH_FLAGS_PROGRESS_COLORED;
- for (x = 1; x < line.getnumtokens(); x ++)
- {
- if (!stricmp(line.gettoken_str(x),"smooth")) smooth=1;
- else if (!stricmp(line.gettoken_str(x),"colored")) build_header.flags|=CH_FLAGS_PROGRESS_COLORED;
- else PRINTHELP()
- }
- try {
- init_res_editor();
-
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INSTFILES), NSIS_DEFAULT_LANG);
- if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!");
- CDialogTemplate dt(dlg,uDefCodePage);
- free(dlg);
- DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS);
- if (!progress) {
- throw runtime_error("IDC_PROGRESS doesn't exist!");
- }
-
- if (smooth)
- progress->dwStyle |= PBS_SMOOTH;
- else
- progress->dwStyle &= ~PBS_SMOOTH;
-
- DWORD dwSize;
- dlg = dt.Save(dwSize);
- res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INSTFILES), NSIS_DEFAULT_LANG, dlg, dwSize);
- delete [] dlg;
- }
- catch (exception& err) {
- ERROR_MSG("Error setting smooth progress bar: %s\n", err.what());
- return PS_ERROR;
- }
- SCRIPT_MSG("InstProgressFlags: smooth=%d, colored=%d\n",smooth,
- !!(build_header.flags&CH_FLAGS_PROGRESS_COLORED));
- }
- return PS_OK;
- case TOK_AUTOCLOSE:
- {
- int k=line.gettoken_enum(1,"false\0true\0");
- if (k == -1) PRINTHELP();
- if (k)
- build_header.flags|=CH_FLAGS_AUTO_CLOSE;
- else
- build_header.flags&=~CH_FLAGS_AUTO_CLOSE;
- SCRIPT_MSG("AutoCloseWindow: %s\n",k?"true":"false");
- }
- return PS_OK;
- case TOK_WINDOWICON:
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- disable_window_icon=line.gettoken_enum(1,"on\0off\0");
- if (disable_window_icon == -1) PRINTHELP();
- SCRIPT_MSG("WindowIcon: %s\n",line.gettoken_str(1));
- return PS_OK;
-#else
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0));
- return PS_ERROR;
-#endif // NSIS_CONFIG_VISIBLE_SUPPORT
- case TOK_SHOWDETAILSUNINST:
-#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
- ERROR_MSG("Error: ShowUninstDetails specified but NSIS_CONFIG_UNINSTALL_SUPPORT not defined\n");
- return PS_ERROR;
-#endif
- case TOK_SHOWDETAILS:
- {
- int k=line.gettoken_enum(1,"hide\0show\0nevershow\0");
- if (k == -1) PRINTHELP()
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (which_token == TOK_SHOWDETAILSUNINST)
- {
- build_uninst.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS);
- if (k==1)
- build_uninst.flags|=CH_FLAGS_DETAILS_SHOWDETAILS;
- else if (k==2)
- build_uninst.flags|=CH_FLAGS_DETAILS_NEVERSHOW;
- }
- else
-#endif
- {
- build_header.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS);
- if (k==1)
- build_header.flags|=CH_FLAGS_DETAILS_SHOWDETAILS;
- else if (k==2)
- build_header.flags|=CH_FLAGS_DETAILS_NEVERSHOW;
- }
- SCRIPT_MSG("%s: %s\n",line.gettoken_str(0),line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_DIRSHOW:
- /*{
- int k=line.gettoken_enum(1,"show\0hide\0");
- if (k == -1) PRINTHELP();
- if (k)
- build_header.flags|=CH_FLAGS_DIR_NO_SHOW;
- else
- build_header.flags&=~CH_FLAGS_DIR_NO_SHOW;
- SCRIPT_MSG("DirShow: %s\n",k?"hide":"show");
- }*/
- ERROR_MSG("Error: DirShow doesn't currently work\n");
- return PS_ERROR;
- case TOK_ROOTDIRINST:
- {
- int k=line.gettoken_enum(1,"true\0false\0");
- if (k == -1) PRINTHELP();
- if (k)
- build_header.flags|=CH_FLAGS_NO_ROOT_DIR;
- else
- build_header.flags&=~CH_FLAGS_NO_ROOT_DIR;
- SCRIPT_MSG("AllowRootDirInstall: %s\n",k?"false":"true");
- }
- return PS_OK;
- case TOK_BGFONT:
-#ifndef NSIS_SUPPORT_BGBG
- ERROR_MSG("Error: BGFont specified but NSIS_SUPPORT_BGBG not defined\n");
- return PS_ERROR;
-#else//NSIS_SUPPORT_BGBG
- if (line.getnumtokens()==1)
- {
- memcpy(&bg_font,&bg_default_font,sizeof(LOGFONT));
- SCRIPT_MSG("BGFont: default font\n");
- return PS_OK;
- }
-
- LOGFONT newfont;
- newfont.lfHeight=40;
- newfont.lfWidth=0;
- newfont.lfEscapement=0;
- newfont.lfOrientation=0;
- newfont.lfWeight=FW_NORMAL;
- newfont.lfItalic=FALSE;
- newfont.lfUnderline=FALSE;
- newfont.lfStrikeOut=FALSE;
- newfont.lfCharSet=DEFAULT_CHARSET;
- newfont.lfOutPrecision=OUT_DEFAULT_PRECIS;
- newfont.lfClipPrecision=CLIP_DEFAULT_PRECIS;
- newfont.lfQuality=DEFAULT_QUALITY;
- newfont.lfPitchAndFamily=DEFAULT_PITCH;
-
- strncpy(newfont.lfFaceName,line.gettoken_str(1),LF_FACESIZE);
-
- SCRIPT_MSG("BGFont: \"%s\"",line.gettoken_str(1));
- {
- bool height=false;
- bool weight=false;
- for (int i = 2; i < line.getnumtokens(); i++) {
- char *tok=line.gettoken_str(i);
- if (tok[0]=='/') {
- if (!strcmpi(tok,"/ITALIC")) {
- SCRIPT_MSG(" /ITALIC");
- newfont.lfItalic=TRUE;
- }
- else if (!strcmpi(tok,"/UNDERLINE")) {
- SCRIPT_MSG(" /UNDERLINE");
- newfont.lfUnderline=TRUE;
- }
- else if (!strcmpi(tok,"/STRIKE")) {
- SCRIPT_MSG(" /STRIKE");
- newfont.lfStrikeOut=TRUE;
- }
- else {
- SCRIPT_MSG("\n");
- PRINTHELP();
- }
- }
- else {
- if (!height) {
- SCRIPT_MSG(" height=%s",tok);
- newfont.lfHeight=line.gettoken_int(i);
- height=true;
- }
- else if (!weight) {
- SCRIPT_MSG(" weight=%s",tok);
- newfont.lfWeight=line.gettoken_int(i);
- weight=true;
- }
- else {
- SCRIPT_MSG("\n");
- PRINTHELP();
- }
- }
- }
- }
- SCRIPT_MSG("\n");
- memcpy(&bg_font, &newfont, sizeof(LOGFONT));
- return PS_OK;
-#endif//NSIS_SUPPORT_BGBG
- case TOK_BGGRADIENT:
-#ifndef NSIS_SUPPORT_BGBG
- ERROR_MSG("Error: BGGradient specified but NSIS_SUPPORT_BGBG not defined\n");
- return PS_ERROR;
-#else//NSIS_SUPPORT_BGBG
- if (line.getnumtokens()==1)
- {
- SCRIPT_MSG("BGGradient: default colors\n");
- build_header.bg_color1=0;
- build_header.bg_color2=RGB(0,0,255);
- }
- else if (!stricmp(line.gettoken_str(1),"off"))
- {
- build_header.bg_color1=build_header.bg_color2=build_header.bg_textcolor=-1;
- SCRIPT_MSG("BGGradient: off\n");
- if (line.getnumtokens()>2) PRINTHELP()
- }
- else
- {
- char *p = line.gettoken_str(1);
- int v1,v2,v3=-1;
- v1=strtoul(p,&p,16);
- build_header.bg_color1=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
- p=line.gettoken_str(2);
- v2=strtoul(p,&p,16);
- build_header.bg_color2=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
-
- p=line.gettoken_str(3);
- if (*p)
- {
- if (!stricmp(p,"notext")) build_header.bg_textcolor=-1;
- else
- {
- v3=strtoul(p,&p,16);
- build_header.bg_textcolor=((v3&0xff)<<16)|(v3&0xff00)|((v3&0xff0000)>>16);
- }
- }
-
- SCRIPT_MSG("BGGradient: 0x%06X->0x%06X (text=0x%06X)\n",v1,v2,v3);
- }
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- build_uninst.bg_color1=build_header.bg_color1;
- build_uninst.bg_color2=build_header.bg_color2;
- build_uninst.bg_textcolor=build_header.bg_textcolor;
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-#endif//NSIS_SUPPORT_BGBG
- return PS_OK;
-#ifdef NSIS_CONFIG_VISIBLE_SUPPORT
- case TOK_INSTCOLORS:
- {
- char *p = line.gettoken_str(1);
- if (p[0]=='/')
- {
- if (stricmp(p,"/windows") || line.getnumtokens()!=2) PRINTHELP()
- build_header.lb_fg=build_header.lb_bg=-1;
- SCRIPT_MSG("InstallColors: windows default colors\n");
- }
- else
- {
- int v1,v2;
- if (line.getnumtokens()!=3) PRINTHELP()
- v1=strtoul(p,&p,16);
- build_header.lb_fg=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
- p=line.gettoken_str(2);
- v2=strtoul(p,&p,16);
- build_header.lb_bg=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
- SCRIPT_MSG("InstallColors: fg=%06X bg=%06X\n",v1,v2);
- }
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- build_uninst.lb_fg=build_header.lb_fg;
- build_uninst.lb_bg=build_header.lb_bg;
-#endif
- }
- return PS_OK;
- case TOK_XPSTYLE:
- {
- int k=line.gettoken_enum(1,"on\0off\0");
- if (k == -1) PRINTHELP()
- SCRIPT_MSG("XPStyle: %s\n", line.gettoken_str(1));
- if (!k)
- manifest_comctl = manifest::comctl_xp;
- else
- manifest_comctl = manifest::comctl_old;
- }
- return PS_OK;
- case TOK_CHANGEUI:
- try {
- DWORD dwSize;
- int k=line.gettoken_enum(1, "all\0IDD_LICENSE\0IDD_DIR\0IDD_SELCOM\0IDD_INST\0IDD_INSTFILES\0IDD_UNINST\0IDD_VERIFY\0IDD_LICENSE_FSRB\0IDD_LICENSE_FSCB\0");
- if (k<0) PRINTHELP();
-
- FILE *fui = FOPEN(line.gettoken_str(2), "rb");
- if (!fui) {
- ERROR_MSG("Error: Can't open \"%s\"!\n", line.gettoken_str(2));
- return PS_ERROR;
- }
- MANAGE_WITH(fui, fclose);
-
- fseek(fui, 0, SEEK_END);
- unsigned int len = ftell(fui);
- fseek(fui, 0, SEEK_SET);
- LPBYTE ui = (LPBYTE) malloc(len);
- if (!ui) {
- ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n", len);
- extern void quit(); quit();
- }
- MANAGE_WITH(ui, free);
- if (fread(ui, 1, len, fui) != len) {
- ERROR_MSG("Error: Can't read \"%s\"!\n", line.gettoken_str(2));
- return PS_ERROR;
- }
-
- CResourceEditor *uire = new CResourceEditor(ui, len);
-
- init_res_editor();
-
- // Search for required items
- #define GET(x) dlg = uire->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(x), 0); if (!dlg) return PS_ERROR; CDialogTemplate UIDlg(dlg, uDefCodePage);
- #define SEARCH(x) if (!UIDlg.GetItem(x)) {ERROR_MSG("Error: Can't find %s (%u) in the custom UI!\n", #x, x);delete [] dlg;delete uire;return PS_ERROR;}
- #define SAVE(x) dwSize = UIDlg.GetSize(); res_editor->UpdateResourceA(RT_DIALOG, x, NSIS_DEFAULT_LANG, dlg, dwSize); delete [] dlg;
-
- LPBYTE dlg = NULL;
-
- if (k == 0 || k == 1) {
- GET(IDD_LICENSE);
- SEARCH(IDC_EDIT1);
- SAVE(IDD_LICENSE);
- }
-
- if (k == 0 || k == 2) {
- GET(IDD_DIR);
- SEARCH(IDC_DIR);
- SEARCH(IDC_BROWSE);
-#ifdef NSIS_CONFIG_LOG
- SEARCH(IDC_CHECK1);
-#endif
- SAVE(IDD_DIR);
- }
-
- if (k == 0 || k == 3) {
- GET(IDD_SELCOM);
- SEARCH(IDC_TREE1);
- SEARCH(IDC_COMBO1);
- SAVE(IDD_SELCOM);
- }
-
- if (k == 0 || k == 4) {
- GET(IDD_INST);
- SEARCH(IDC_BACK);
- SEARCH(IDC_CHILDRECT);
- SEARCH(IDC_VERSTR);
- SEARCH(IDOK);
- SEARCH(IDCANCEL);
-
- // Search for bitmap holder (default for SetBrandingImage)
- branding_image_found = false;
- DialogItemTemplate* dlgItem = 0;
- for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) {
- bool check = false;
-
- if (IS_INTRESOURCE(dlgItem->szClass)) {
- if (dlgItem->szClass == MAKEINTRESOURCEW(0x0082)) {
- check = true;
- }
- } else {
- char *szClass = winchar_toansi(dlgItem->szClass);
- check = strcmp(szClass, "Static") == 0;
- delete [] szClass;
- }
-
- if (check) {
- if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) {
- branding_image_found = true;
- branding_image_id = dlgItem->wId;
- break;
- }
- }
- }
-
- SAVE(IDD_INST);
- }
-
- if (k == 0 || k == 5) {
- GET(IDD_INSTFILES);
- SEARCH(IDC_LIST1);
- SEARCH(IDC_PROGRESS);
- SEARCH(IDC_SHOWDETAILS);
- SAVE(IDD_INSTFILES);
- }
-
- if (k == 0 || k == 6) {
- GET(IDD_UNINST);
- SEARCH(IDC_EDIT1);
- SAVE(IDD_UNINST);
- }
-
- if (k == 0 || k == 7) {
- GET(IDD_VERIFY);
- SEARCH(IDC_STR);
- SAVE(IDD_VERIFY);
- }
-
- if (k == 0 || k == 8) {
- GET(IDD_LICENSE_FSRB);
- SEARCH(IDC_EDIT1);
- SEARCH(IDC_LICENSEAGREE);
- SEARCH(IDC_LICENSEDISAGREE);
- SAVE(IDD_LICENSE_FSRB);
- }
-
- if (k == 0 || k == 9) {
- GET(IDD_LICENSE_FSCB);
- SEARCH(IDC_EDIT1);
- SEARCH(IDC_LICENSEAGREE);
- SAVE(IDD_LICENSE_FSCB);
- }
-
- delete uire;
-
- SCRIPT_MSG("ChangeUI: %s %s%s\n", line.gettoken_str(1), line.gettoken_str(2), branding_image_found?" (branding image holder found)":"");
- }
- catch (exception& err) {
- ERROR_MSG("Error while changing UI: %s\n", err.what());
- return PS_ERROR;
- }
- return PS_OK;
- case TOK_ADDBRANDINGIMAGE:
-#ifdef _WIN32
- try {
- int k=line.gettoken_enum(1,"top\0left\0bottom\0right\0");
- int wh=line.gettoken_int(2);
- if (k == -1) PRINTHELP();
- int padding = 2;
- if (line.getnumtokens() == 4)
- padding = line.gettoken_int(3);
-
- init_res_editor();
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG);
-
- CDialogTemplate dt(dlg, uDefCodePage);
-
- res_editor->FreeResource(dlg);
-
- DialogItemTemplate brandingCtl = {0,};
-
- brandingCtl.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE;
- brandingCtl.sX = padding;
- brandingCtl.sY = padding;
- brandingCtl.szClass = MAKEINTRESOURCEW(0x0082);
- brandingCtl.szTitle = NULL;
- brandingCtl.wId = IDC_BRANDIMAGE;
-
- brandingCtl.sHeight = wh;
- brandingCtl.sWidth = wh;
- dt.PixelsToDlgUnits(brandingCtl.sWidth, brandingCtl.sHeight);
- if (k%2) {
- // left (1) / right (3)
-
- if (k & 2) // right
- brandingCtl.sX += dt.GetWidth();
- else // left
- dt.MoveAll(brandingCtl.sWidth + (padding * 2), 0);
-
- dt.Resize(brandingCtl.sWidth + (padding * 2), 0);
-
- brandingCtl.sHeight = dt.GetHeight() - (padding * 2);
- }
- else {
- // top (0) / bottom (2)
-
- if (k & 2) // bottom
- brandingCtl.sY += dt.GetHeight();
- else // top
- dt.MoveAll(0, brandingCtl.sHeight + (padding * 2));
-
- dt.Resize(0, brandingCtl.sHeight + (padding * 2));
-
- brandingCtl.sWidth = dt.GetWidth() - (padding * 2);
- }
-
- dt.AddItem(brandingCtl);
-
- DWORD dwDlgSize;
- dlg = dt.Save(dwDlgSize);
-
- res_editor->UpdateResourceA(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, dlg, dwDlgSize);
-
- delete [] dlg;
-
- dt.DlgUnitsToPixels(brandingCtl.sWidth, brandingCtl.sHeight);
- SCRIPT_MSG("AddBrandingImage: %s %ux%u\n", line.gettoken_str(1), brandingCtl.sWidth, brandingCtl.sHeight);
-
- branding_image_found = true;
- branding_image_id = IDC_BRANDIMAGE;
- }
- catch (exception& err) {
- ERROR_MSG("Error while adding image branding support: %s\n", err.what());
- return PS_ERROR;
- }
- return PS_OK;
-#else
- ERROR_MSG("Error: AddBrandingImage is disabled for non Win32 platforms.\n");
- return PS_ERROR;
-#endif
- case TOK_SETFONT:
- {
- if (!strnicmp(line.gettoken_str(1), "/LANG=", 6))
- {
- LANGID lang_id = atoi(line.gettoken_str(1) + 6);
- LanguageTable *table = GetLangTable(lang_id);
- table->nlf.m_szFont = (char*)malloc(strlen(line.gettoken_str(2))+1);
- strcpy(table->nlf.m_szFont, line.gettoken_str(2));
- table->nlf.m_iFontSize = line.gettoken_int(3);
-
- SCRIPT_MSG("SetFont: lang=%d \"%s\" %s\n", lang_id, line.gettoken_str(2), line.gettoken_str(3));
- }
- else
- {
- strncpy(build_font, line.gettoken_str(1), sizeof(build_font));
- build_font_size = line.gettoken_int(2);
-
- SCRIPT_MSG("SetFont: \"%s\" %s\n", line.gettoken_str(1), line.gettoken_str(2));
- }
- }
- return PS_OK;
-#else
- case TOK_INSTCOLORS:
- case TOK_XPSTYLE:
- case TOK_CHANGEUI:
- case TOK_ADDBRANDINGIMAGE:
- case TOK_SETFONT:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0));
- return PS_ERROR;
-#endif// NSIS_CONFIG_VISIBLE_SUPPORT
-
- case TOK_REQEXECLEVEL:
- {
- int k=line.gettoken_enum(1,"none\0user\0highest\0admin\0");
- switch (k)
- {
- case 0:
- manifest_exec_level = manifest::exec_level_none;
- break;
- case 1:
- manifest_exec_level = manifest::exec_level_user;
- break;
- case 2:
- manifest_exec_level = manifest::exec_level_highest;
- break;
- case 3:
- manifest_exec_level = manifest::exec_level_admin;
- break;
- default:
- PRINTHELP();
- }
- }
- return PS_OK;
-
- // Ability to change compression methods from within the script
- case TOK_SETCOMPRESSOR:
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- {
- if (build_compressor_set) {
- ERROR_MSG("Error: can't change compressor after data already got compressed or header already changed!\n");
- return PS_ERROR;
- }
-
- if (build_compressor_final)
- {
- warning_fl("SetCompressor ignored due to previous call with the /FINAL switch");
- return PS_OK;
- }
-
- int a = 1;
-
- build_compress_whole = false;
-
- while (line.gettoken_str(a)[0] == '/')
- {
- if (!strcmpi(line.gettoken_str(a),"/FINAL"))
- {
- build_compressor_final = true;
- a++;
- }
- else if (!strcmpi(line.gettoken_str(a),"/SOLID"))
- {
- build_compress_whole = true;
- a++;
- }
- else PRINTHELP();
- }
-
- if (a != line.getnumtokens() - 1)
- {
- ERROR_MSG("%s expects %d parameters, got %d.\n", line.gettoken_str(0), a + 1, line.getnumtokens());
- PRINTHELP();
- }
-
- int k=line.gettoken_enum(a, "zlib\0bzip2\0lzma\0");
- switch (k) {
- case 0:
- compressor = &zlib_compressor;
- break;
-
- case 1:
- compressor = &bzip2_compressor;
- break;
-
- case 2:
- compressor = &lzma_compressor;
- break;
-
- default:
- PRINTHELP();
- }
-
- string compressor_name = line.gettoken_str(a);
- compressor_name = lowercase(compressor_name);
-
- if (set_compressor(compressor_name, build_compress_whole) != PS_OK)
- {
- SCRIPT_MSG("SetCompressor: error loading stub for \"%s\" compressor.\n", compressor_name.c_str());
- return PS_ERROR;
- }
-
- SCRIPT_MSG("SetCompressor: %s%s%s\n", build_compressor_final ? "/FINAL " : "", build_compress_whole ? "/SOLID " : "", line.gettoken_str(a));
- }
- return PS_OK;
-#else//NSIS_CONFIG_COMPRESSION_SUPPORT
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
- case TOK_LOADNLF:
- {
- SCRIPT_MSG("LoadLanguageFile: %s\n", line.gettoken_str(1));
-
- LanguageTable *table = LoadLangFile(line.gettoken_str(1));
-
- if (!table)
- return PS_ERROR;
-
- if (!defcodepage_set)
- {
- uDefCodePage = table->nlf.m_uCodePage;
- defcodepage_set = true;
- }
-
- last_used_lang = table->lang_id;
- // define LANG_LangName as "####" (lang id)
- // for example ${LANG_ENGLISH} = 1033
- char lang_id[16];
- char lang_cp[16];
- char lang_name[1024];
- wsprintf(lang_name, "LANG_%s", table->nlf.m_szName);
- wsprintf(lang_id, "%u", table->lang_id);
- wsprintf(lang_cp, "%u", table->nlf.m_uCodePage);
- definedlist.add(lang_name, lang_id);
- wsprintf(lang_name, "LANG_%s_CP", table->nlf.m_szName);
- definedlist.add(lang_name, lang_cp);
- }
- return PS_OK;
-
- // preprocessor-ish (ifdef/ifndef/else/endif are handled one step out from here)
- ///////////////////////////////////////////////////////////////////////////////
- case TOK_P_DEFINE:
- {
- char *define=line.gettoken_str(1);
- char *value;
- char datebuf[256];
- char mathbuf[256];
-
- if (!stricmp(define,"/date") || !stricmp(define,"/utcdate")) {
- if (line.getnumtokens()!=4) PRINTHELP()
-
- char *date_type = define;
-
- define=line.gettoken_str(2);
- value=line.gettoken_str(3);
-
- time_t rawtime;
- time(&rawtime);
-
- if (!stricmp(date_type,"/utcdate"))
- rawtime = mktime(gmtime(&rawtime));
-
- datebuf[0]=0;
- size_t s=strftime(datebuf,sizeof(datebuf),value,localtime(&rawtime));
-
- if (s == 0)
- datebuf[0]=0;
- else
- datebuf[max(s,sizeof(datebuf)-1)]=0;
-
- value=datebuf;
-
- } else if (!stricmp(define,"/math")) {
-
- int value1;
- int value2;
- char *mathop;
-
- if (line.getnumtokens()!=6) PRINTHELP()
-
- define = line.gettoken_str(2);
- value1 = line.gettoken_int(3);
- mathop = line.gettoken_str(4);
- value2 = line.gettoken_int(5);
- value = mathbuf;
-
- if (!strcmp(mathop,"+")) {
- sprintf(value,"%d",value1+value2);
- } else if (!strcmp(mathop,"-")) {
- sprintf(value,"%d",value1-value2);
- } else if (!strcmp(mathop,"*")) {
- sprintf(value,"%d",value1*value2);
- } else if (!strcmp(mathop,"&")) {
- sprintf(value,"%d",value1&value2);
- } else if (!strcmp(mathop,"|")) {
- sprintf(value,"%d",value1|value2);
- } else if (!strcmp(mathop,"^")) {
- sprintf(value,"%d",value1^value2);
- } else if (!strcmp(mathop,"/")) {
- if (value2==0) {
- ERROR_MSG("!define /math: division by zero! (\"%i / %i\")\n",value1,value2);
- return PS_ERROR;
- }
- sprintf(value,"%d",value1/value2);
- } else if (!strcmp(mathop,"%")) {
- if (value2==0) {
- ERROR_MSG("!define /math: division by zero! (\"%i %% %i\")\n",value1,value2);
- return PS_ERROR;
- }
- sprintf(value,"%d",value1%value2);
- } else PRINTHELP()
-
- } else {
- if (line.getnumtokens()==4) PRINTHELP()
-
- value=line.gettoken_str(2);
- }
-
- if (definedlist.add(define,value))
- {
- ERROR_MSG("!define: \"%s\" already defined!\n",define);
- return PS_ERROR;
- }
- SCRIPT_MSG("!define: \"%s\"=\"%s\"\n",define,value);
- }
- return PS_OK;
- case TOK_P_UNDEF:
- if (definedlist.del(line.gettoken_str(1)))
- {
- ERROR_MSG("!undef: \"%s\" not defined!\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- SCRIPT_MSG("!undef: \"%s\"\n",line.gettoken_str(1));
- return PS_OK;
- case TOK_P_PACKEXEHEADER:
- strncpy(build_packname,line.gettoken_str(1),sizeof(build_packname)-1);
- strncpy(build_packcmd,line.gettoken_str(2),sizeof(build_packcmd)-1);
- SCRIPT_MSG("!packhdr: filename=\"%s\", command=\"%s\"\n",
- build_packname, build_packcmd);
- return PS_OK;
- case TOK_P_SYSTEMEXEC:
- {
- char *exec=line.gettoken_str(1);
- int comp=line.gettoken_enum(2,"<\0>\0<>\0=\0ignore\0");
- if (line.getnumtokens() == 2) comp = 4;
- if (comp == -1 && line.getnumtokens() == 3) comp=4;
- if (comp == -1) PRINTHELP()
- int success=0;
- int cmpv=line.gettoken_int(3,&success);
- if (!success && comp != 4) PRINTHELP()
- SCRIPT_MSG("!system: \"%s\"\n",exec);
-#ifdef _WIN32
- int ret=sane_system(exec);
-#else
- char *execfixed = my_convert(exec);
- int ret=system(execfixed);
- my_convert_free(execfixed);
-#endif
- if (comp == 0 && ret < cmpv);
- else if (comp == 1 && ret > cmpv);
- else if (comp == 2 && ret != cmpv);
- else if (comp == 3 && ret == cmpv);
- else if (comp == 4);
- else
- {
- ERROR_MSG("!system: returned %d, aborting\n",ret);
- return PS_ERROR;
- }
- SCRIPT_MSG("!system: returned %d\n",ret);
- }
- return PS_OK;
- case TOK_P_EXECUTE:
- {
- char *exec=line.gettoken_str(1);
-#ifdef _WIN32
- PROCESS_INFORMATION pi;
- STARTUPINFO si={sizeof(STARTUPINFO),};
- if (CreateProcess(NULL,exec,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
- {
- WaitForSingleObject(pi.hProcess,INFINITE);
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
- }
-#else
- char *execfixed = my_convert(exec);
- system(execfixed);
- my_convert_free(execfixed);
-#endif
- SCRIPT_MSG("!execute: \"%s\"\n",exec);
- }
- case TOK_P_ADDINCLUDEDIR:
-#ifdef _WIN32
- include_dirs.add(line.gettoken_str(1),0);
-#else
- {
- char *f = line.gettoken_str(1);
- char *fc = my_convert(f);
- include_dirs.add(fc,0);
- my_convert_free(fc);
- }
-#endif
- return PS_OK;
- case TOK_P_INCLUDE:
- {
- bool required = true;
-
- char *f = line.gettoken_str(1);
-
- if(!stricmp(f,"/nonfatal")) {
- if (line.getnumtokens()!=3)
- PRINTHELP();
-
- f = line.gettoken_str(2);
- required = false;
- } else if (line.getnumtokens()!=2) {
- PRINTHELP();
- }
-
-#ifdef _WIN32
- char *fc = f;
-#else
- char *fc = my_convert(f);
-#endif
- int included = 0;
-
- string dir = get_dir_name(fc);
- string spec = get_file_name(fc);
- string basedir = dir + PLATFORM_PATH_SEPARATOR_STR;
- if (dir == spec) {
- // no path, just file name
- dir = ".";
- basedir = "";
- }
-
-#ifndef _WIN32
- my_convert_free(fc);
-#endif
-
- // search working directory
- boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
- dr->read(dir);
-
- for (dir_reader::iterator files_itr = dr->files().begin();
- files_itr != dr->files().end();
- files_itr++)
- {
- if (!dir_reader::matches(*files_itr, spec))
- continue;
-
- string incfile = basedir + *files_itr;
-
- if (includeScript((char *) incfile.c_str()) != PS_OK) {
- return PS_ERROR;
- }
-
- included++;
- }
-
- if (included)
- return PS_OK;
-
- // search include dirs
- char *incdir = include_dirs.get();
- int incdirs = include_dirs.getnum();
-
- for (int i = 0; i < incdirs; i++, incdir += strlen(incdir) + 1) {
- string curincdir = string(incdir) + PLATFORM_PATH_SEPARATOR_STR + dir;
-
- boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
- dr->read(curincdir);
-
- for (dir_reader::iterator incdir_itr = dr->files().begin();
- incdir_itr != dr->files().end();
- incdir_itr++)
- {
- if (!dir_reader::matches(*incdir_itr, spec))
- continue;
-
- string incfile = string(incdir) + PLATFORM_PATH_SEPARATOR_STR + basedir + *incdir_itr;
-
- if (includeScript((char *) incfile.c_str()) != PS_OK) {
- return PS_ERROR;
- }
-
- included++;
- }
-
- if (included)
- return PS_OK;
-
- }
-
- // nothing found
- if (!included)
- {
- if(required) {
- ERROR_MSG("!include: could not find: \"%s\"\n",f);
- return PS_ERROR;
- } else {
- warning_fl("!include: could not find: \"%s\"",f);
- }
- }
- }
- return PS_OK;
- case TOK_P_CD:
- if (!line.gettoken_str(1)[0] || chdir(line.gettoken_str(1)))
- {
- ERROR_MSG("!cd: error changing to: \"%s\"\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- return PS_OK;
- case TOK_P_ERROR:
- ERROR_MSG("!error: %s\n",line.gettoken_str(1));
- return PS_ERROR;
- case TOK_P_WARNING:
- warning_fl("!warning: %s",line.gettoken_str(1));
- return PS_OK;
- case TOK_P_ECHO:
- SCRIPT_MSG("%s (%s:%d)\n", line.gettoken_str(1),curfilename,linecnt);
- return PS_OK;
-
- case TOK_P_VERBOSE:
- {
- extern int g_display_errors;
- int k=line.gettoken_enum(1,"push\0pop\0");
- int v;
- if (k < 0)
- // just set
- v=line.gettoken_int(1);
- else
- {
- if (k)
- {
- // pop
- int l=verbose_stack.getlen();
- if (l)
- {
- v=((int*)verbose_stack.get())[(l/sizeof(int))-1];
- verbose_stack.resize(l-sizeof(int));
- }
- else
- return PS_OK;
- }
- else
- {
- // push
- v=0;
- if (display_errors)
- {
- v++;
- if (display_warnings)
- {
- v++;
- if (display_info)
- {
- v++;
- if (display_script)
- {
- v++;
- }
- }
- }
- }
- verbose_stack.add(&v,sizeof(int));
- return PS_OK;
- }
- }
- display_script=v>3;
- display_info=v>2;
- display_warnings=v>1;
- display_errors=v>0;
- g_display_errors=display_errors;
- }
- return PS_OK;
-
- case TOK_UNINSTALLEXENAME: PRINTHELP()
-
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- case TOK_UNINSTCAPTION:
- {
- if (SetInnerString(NLF_UCAPTION,line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- SCRIPT_MSG("UninstCaption: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_UNINSTICON:
- SCRIPT_MSG("UninstallIcon: \"%s\"\n",line.gettoken_str(1));
- try {
- free(m_unicon_data);
- m_unicon_data = generate_uninstall_icon_data(line.gettoken_str(1), m_unicon_size);
- }
- catch (exception& err) {
- ERROR_MSG("Error while setting icon to \"%s\": %s\n", line.gettoken_str(1), err.what());
- return PS_ERROR;
- }
- return PS_OK;
- case TOK_UNINSTTEXT:
- {
- if (!cur_page) {
- if (SetInnerString(NLF_UNINST_TEXT, line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- SetInnerString(NLF_UNINST_SUBTEXT, line.gettoken_str(2));
- }
- else {
- if (cur_page_type != PAGE_UNINSTCONFIRM) {
- ERROR_MSG("Error: UninstallText can only be used inside PageEx uninstConfirm.\n");
- return PS_ERROR;
- }
- cur_page->parms[0] = add_string(line.gettoken_str(1));
- cur_page->parms[1] = add_string(line.gettoken_str(2));
- }
- SCRIPT_MSG("UninstallText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2));
- }
- return PS_OK;
- case TOK_UNINSTSUBCAPTION:
- {
- int s;
- int w=line.gettoken_int(1,&s);
- if (!s || w < 0 || w > 2) PRINTHELP()
- SetInnerString(NLF_USUBCAPTION_CONFIRM+w,line.gettoken_str(2));
- SCRIPT_MSG("UninstSubCaption: page:%d, text=%s\n",w,line.gettoken_str(2));
- }
- return PS_OK;
- case TOK_WRITEUNINSTALLER:
- {
- if (uninstall_mode)
- {
- ERROR_MSG("WriteUninstaller only valid from install, not from uninstall.\n");
- PRINTHELP()
- }
- uninstaller_writes_used++;
- ent.which=EW_WRITEUNINSTALLER;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- string full = string("$INSTDIR\\") + string(line.gettoken_str(1));
- ent.offsets[3]=add_string(full.c_str());
- // ent.offsets[1] and ent.offsets[2] are set in CEXEBuild::uninstall_generate()
- if (!ent.offsets[0]) PRINTHELP()
- SCRIPT_MSG("WriteUninstaller: \"%s\"\n",line.gettoken_str(1));
-
- DefineInnerLangString(NLF_ERR_CREATING);
- DefineInnerLangString(NLF_CREATED_UNINST);
- }
- return add_entry(&ent);
-#else//!NSIS_CONFIG_UNINSTALL_SUPPORT
- case TOK_WRITEUNINSTALLER:
- case TOK_UNINSTCAPTION:
- case TOK_UNINSTICON:
- case TOK_UNINSTTEXT:
- case TOK_UNINSTSUBCAPTION:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif
-
-
-
- // section/function shit
- ///////////////////////////////////////////////////////////////////////////////
-
- case TOK_SECTION:
- {
- int a=1,unselected = 0;
- if (!strcmpi(line.gettoken_str(1),"/o"))
- {
- unselected = 1;
- a++;
- }
- else if (line.getnumtokens() > 3)
- PRINTHELP();
- SCRIPT_MSG("Section: \"%s\"",line.gettoken_str(a));
- if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1));
- SCRIPT_MSG("\n");
-#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!stricmp(line.gettoken_str(a),"uninstall"))
- {
- ERROR_MSG("Error: Uninstall section declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n");
- return PS_ERROR;
- }
-#endif
-
- int ret;
-
- if (line.gettoken_str(a)[0]=='-')
- {
- if (!strnicmp(line.gettoken_str(a)+1,"un.",3))
- ret=add_section("un.",line.gettoken_str(a+1));
- else
- ret=add_section("",line.gettoken_str(a+1));
- }
- else ret=add_section(line.gettoken_str(a),line.gettoken_str(a+1));
- if (ret != PS_OK) return ret;
-
- if (unselected)
- build_cursection->flags &= ~SF_SELECTED;
-
- return PS_OK;
- }
- case TOK_SECTIONEND:
- SCRIPT_MSG("SectionEnd\n");
- return section_end();
- case TOK_SECTIONIN:
- {
- SCRIPT_MSG("SectionIn: ");
- int wt;
- for (wt = 1; wt < line.getnumtokens(); wt ++)
- {
- char *p=line.gettoken_str(wt);
- if (!stricmp(p, "RO"))
- {
- if (section_add_flags(SF_RO) != PS_OK) return PS_ERROR;
- SCRIPT_MSG("[RO] ");
- }
- else
- {
- int x=atoi(p)-1;
- if (x >= 0 && x < NSIS_MAX_INST_TYPES)
- {
- if (section_add_install_type(1<<x) != PS_OK) return PS_ERROR;
- SCRIPT_MSG("[%d] ",x);
- }
- else if (x < 0)
- {
- PRINTHELP()
- }
- else
- {
- ERROR_MSG("Error: SectionIn section %d out of range 1-%d\n",x+1,NSIS_MAX_INST_TYPES);
- return PS_ERROR;
- }
- p++;
- }
- }
- SCRIPT_MSG("\n");
- }
- return PS_OK;
- case TOK_SECTIONGROUPEND:
- case TOK_SUBSECTIONEND:
- case TOK_SECTIONGROUP:
- case TOK_SUBSECTION:
- {
- char buf[1024];
- int a=1,ex = 0;
- if (!strcmpi(line.gettoken_str(1),"/e"))
- {
- ex = 1;
- a++;
- }
- wsprintf(buf,"-%s",line.gettoken_str(a));
- if (which_token == TOK_SECTIONGROUP || which_token == TOK_SUBSECTION)
- {
- char *s = line.gettoken_str(a);
- if (!s[0] || (!strcmpi(s, "un.") && !s[3]))
- PRINTHELP();
- }
-
- SCRIPT_MSG("%s %s",line.gettoken_str(0),line.gettoken_str(a));
- if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1));
- SCRIPT_MSG("\n");
- return add_section(buf,line.gettoken_str(a+1),ex);
- }
- case TOK_FUNCTION:
- if (!line.gettoken_str(1)[0]) PRINTHELP()
- if (line.gettoken_str(1)[0]==':' || line.gettoken_str(1)[0]=='/')
- {
- ERROR_MSG("Function: function name cannot begin with : or /.\n");
- PRINTHELP()
- }
- SCRIPT_MSG("Function: \"%s\"\n",line.gettoken_str(1));
-#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (!strnicmp(line.gettoken_str(1),"un.",3))
- {
- ERROR_MSG("Error: Uninstall function declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n");
- return PS_ERROR;
- }
-#endif
- return add_function(line.gettoken_str(1));
- case TOK_FUNCTIONEND:
- SCRIPT_MSG("FunctionEnd\n");
- return function_end();
-
- // flag setters
- ///////////////////////////////////////////////////////////////////////////////
-
- // BEGIN - Added by ramon 23 May 2003
- case TOK_ALLOWSKIPFILES:
- build_allowskipfiles=line.gettoken_enum(1,"off\0on\0");
- if (build_allowskipfiles==-1) PRINTHELP()
- SCRIPT_MSG("AllowSkipFiles: %s\n",line.gettoken_str(1));
- return PS_OK;
- // END - Added by ramon 23 May 2003
- case TOK_SETDATESAVE:
- build_datesave=line.gettoken_enum(1,"off\0on\0");
- if (build_datesave==-1) PRINTHELP()
- SCRIPT_MSG("SetDateSave: %s\n",line.gettoken_str(1));
- return PS_OK;
- case TOK_SETOVERWRITE:
- {
- int k=line.gettoken_enum(1,"on\0off\0try\0ifnewer\0ifdiff\0lastused\0");
- if (k==-1) PRINTHELP()
- if (k==5)
- {
- k=build_overwrite;
- build_overwrite=build_last_overwrite;
- build_last_overwrite=k;
- }
- else
- {
- build_last_overwrite=build_overwrite;
- build_overwrite=k;
- }
- SCRIPT_MSG("SetOverwrite: %s\n",line.gettoken_str(1));
- }
- return PS_OK;
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- case TOK_SETPLUGINUNLOAD:
- build_plugin_unload=line.gettoken_enum(1,"manual\0alwaysoff\0");
- if (build_plugin_unload==-1) PRINTHELP()
- SCRIPT_MSG("SetPluginUnload: %s\n",line.gettoken_str(1));
- return PS_OK;
-#endif //NSIS_CONFIG_PLUGIN_SUPPORT
- case TOK_SETCOMPRESS:
- build_compress=line.gettoken_enum(1,"off\0auto\0force\0");
- if (build_compress==-1) PRINTHELP()
- if (build_compress==0 && build_compress_whole)
- {
- warning_fl("'SetCompress off' encountered, and in whole compression mode. Effectively ignored.");
- }
- SCRIPT_MSG("SetCompress: %s\n",line.gettoken_str(1));
- return PS_OK;
- case TOK_DBOPTIMIZE:
- build_optimize_datablock=line.gettoken_enum(1,"off\0on\0");
- if (build_optimize_datablock==-1) PRINTHELP()
- SCRIPT_MSG("SetDatablockOptimize: %s\n",line.gettoken_str(1));
- return PS_OK;
- case TOK_FILEBUFSIZE:
- build_filebuflen=line.gettoken_int(1);
- build_filebuflen<<=20;
- if (build_filebuflen<=0)
- {
- ERROR_MSG("Error: FileBufSize: invalid buffer size -- %d\n",build_filebuflen);
- return PS_ERROR;
- }
- SCRIPT_MSG("FileBufSize: %smb (%d bytes)\n",line.gettoken_str(1),build_filebuflen);
- return PS_OK;
-#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT
- case TOK_SETCOMPRESSIONLEVEL:
- {
- if (compressor == &lzma_compressor)
- warning_fl("SetCompressionLevel: compressor is set to LZMA. Effectively ignored.");
- if (build_compressor_set && build_compress_whole)
- warning_fl("SetCompressionLevel: data already compressed in compress whole mode. Effectively ignored.");
-
- int s;
- build_compress_level=line.gettoken_int(1,&s);
- if (!s || build_compress_level < 0 || build_compress_level > 9) PRINTHELP();
- SCRIPT_MSG("SetCompressionLevel: %u\n", build_compress_level);
- }
- return PS_OK;
- case TOK_SETCOMPRESSORDICTSIZE:
- {
- if (compressor != &lzma_compressor)
- warning_fl("SetCompressorDictSize: compressor is not set to LZMA. Effectively ignored.");
- if (build_compressor_set && build_compress_whole)
- warning_fl("SetCompressorDictSize: data already compressed in compress whole mode. Effectively ignored.");
-
- int s;
- build_compress_dict_size=line.gettoken_int(1,&s);
- if (!s) PRINTHELP();
- SCRIPT_MSG("SetCompressorDictSize: %u mb\n", build_compress_dict_size);
- build_compress_dict_size <<= 20;
- }
- return PS_OK;
-#else
- case TOK_SETCOMPRESSIONLEVEL:
- case TOK_SETCOMPRESSORDICTSIZE:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_CONFIG_COMPRESSION_SUPPORT
- case TOK_ADDSIZE:
- {
- int s;
- int size_kb=line.gettoken_int(1,&s);
- if (!s) PRINTHELP()
- SCRIPT_MSG("AddSize: %d kb\n",size_kb);
- section_add_size_kb(size_kb);
- }
- return PS_OK;
- case TOK_SUBCAPTION:
- {
- int s;
- int w=line.gettoken_int(1,&s);
- if (!s || w < 0 || w > 4) PRINTHELP()
- SetInnerString(NLF_SUBCAPTION_LICENSE+w,line.gettoken_str(2));
- SCRIPT_MSG("SubCaption: page:%d, text=%s\n",w,line.gettoken_str(2));
- }
- return PS_OK;
- case TOK_FILEERRORTEXT:
-#ifdef NSIS_SUPPORT_FILE
- {
- SetInnerString(NLF_FILE_ERROR,line.gettoken_str(1));
- SetInnerString(NLF_FILE_ERROR_NOIGNORE,line.gettoken_str(2));
- SCRIPT_MSG("FileErrorText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2));
- }
- return PS_OK;
-#else
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif
- case TOK_BRANDINGTEXT:
- {
- int a = 1;
- int trim = 0;
- while (line.gettoken_str(a)[0] == '/') {
- if (!strnicmp(line.gettoken_str(a),"/TRIM",5)) {
- if (!stricmp(line.gettoken_str(a)+5,"LEFT")) trim = 1;
- else if (!stricmp(line.gettoken_str(a)+5,"RIGHT")) trim = 2;
- else if (!stricmp(line.gettoken_str(a)+5,"CENTER")) trim = 3;
- else PRINTHELP();
- a++;
- }
- else break;
- }
- if (line.getnumtokens()!=a+1 && !trim) PRINTHELP();
- if (line.getnumtokens()==a+1)
- SetInnerString(NLF_BRANDING,line.gettoken_str(a));
-#ifdef _WIN32
- if (trim) try {
- init_res_editor();
-
- BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG);
- CDialogTemplate td(dlg,uDefCodePage);
- free(dlg);
-
- if (trim) {
- char str[512];
- if (line.getnumtokens()==a+1 && line.gettoken_str(a)[0])
- strcpy(str, line.gettoken_str(a));
- else
- wsprintf(str, "Nullsoft Install System %s", NSIS_VERSION);
-
- short old_width = td.GetItem(IDC_VERSTR)->sWidth;
-
- switch (trim) {
- case 1: td.LTrimToString(IDC_VERSTR, str, 4); break;
- case 2: td.RTrimToString(IDC_VERSTR, str, 4); break;
- case 3: td.CTrimToString(IDC_VERSTR, str, 4); break;
- }
-
- if (td.GetItem(IDC_VERSTR)->sWidth > old_width)
- {
- warning_fl("BrandingText: \"%s\" is too long, trimming has expanded the label", str);
- }
- }
-
- DWORD dwSize;
- dlg = td.Save(dwSize);
- res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG, dlg, dwSize);
- res_editor->FreeResource(dlg);
- }
- catch (exception& err) {
- ERROR_MSG("Error while triming branding text control: %s\n", err.what());
- return PS_ERROR;
- }
-#else
- if (trim)
- {
- ERROR_MSG("Error: BrandingText /TRIM* is disabled for non Win32 platforms.\n");
- return PS_ERROR;
- }
-#endif
- SCRIPT_MSG("BrandingText: \"%s\"\n",line.gettoken_str(a));
- }
- return PS_OK;
- case TOK_MISCBUTTONTEXT:
- {
- SetInnerString(NLF_BTN_BACK,line.gettoken_str(1));
- SetInnerString(NLF_BTN_NEXT,line.gettoken_str(2));
- SetInnerString(NLF_BTN_CANCEL,line.gettoken_str(3));
- SetInnerString(NLF_BTN_CLOSE,line.gettoken_str(4));
- SCRIPT_MSG("MiscButtonText: back=\"%s\" next=\"%s\" cancel=\"%s\" close=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- }
- return PS_OK;
- case TOK_SPACETEXTS:
- {
- if (!strcmpi(line.gettoken_str(1), "none")) {
- no_space_texts=true;
- SCRIPT_MSG("SpaceTexts: none\n");
- }
- else {
- no_space_texts=false;
- SetInnerString(NLF_SPACE_REQ,line.gettoken_str(1));
- SetInnerString(NLF_SPACE_AVAIL,line.gettoken_str(2));
- SCRIPT_MSG("SpaceTexts: required=\"%s\" available=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2));
- }
- }
- return PS_OK;
- case TOK_INSTBUTTONTEXT:
- {
- SetInnerString(NLF_BTN_INSTALL,line.gettoken_str(1));
- SCRIPT_MSG("InstallButtonText: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_DETAILSBUTTONTEXT:
- {
- if (!cur_page) {
- if (SetInnerString(NLF_BTN_DETAILS,line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- }
- else {
- if (cur_page_type != PAGE_INSTFILES) {
- ERROR_MSG("Error: DetailsButtonText can only be used inside PageEx instfiles.\n");
- return PS_ERROR;
- }
- cur_page->parms[1] = add_string(line.gettoken_str(1));
- }
- SCRIPT_MSG("DetailsButtonText: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_COMPLETEDTEXT:
- {
- if (!cur_page) {
- if (SetInnerString(NLF_COMPLETED,line.gettoken_str(1)) == PS_WARNING)
- warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0));
- }
- else {
- if (cur_page_type != PAGE_INSTFILES) {
- ERROR_MSG("Error: CompletedText can only be used inside PageEx instfiles.\n");
- return PS_ERROR;
- }
- cur_page->parms[2] = add_string(line.gettoken_str(1));
- }
- SCRIPT_MSG("CompletedText: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
- case TOK_UNINSTBUTTONTEXT:
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- {
- SetInnerString(NLF_BTN_UNINSTALL,line.gettoken_str(1));
- SCRIPT_MSG("UninstButtonText: \"%s\"\n",line.gettoken_str(1));
- }
- return PS_OK;
-#else
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif
-
- // instructions
- ///////////////////////////////////////////////////////////////////////////////
- case TOK_NOP:
- SCRIPT_MSG("Nop\n");
- ent.which=EW_NOP;
- return add_entry(&ent);
- case TOK_GOTO:
- ent.which=EW_NOP;
- if (process_jump(line,1,&ent.offsets[0])) PRINTHELP()
- SCRIPT_MSG("Goto: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_SETREGVIEW:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(alter_reg_view);
- // "64" results in setting the flag to 1 which alters the view
- int k=line.gettoken_enum(1,"32\0" "64\0lastused\0");
- if (k<0) PRINTHELP()
- if (k == 0) // 32
- ent.offsets[1]=add_intstring(0);
- else if (k == 1) // 64
- ent.offsets[1]=add_intstring(KEY_WOW64_64KEY);
- else if (k == 2) // last used
- ent.offsets[2]=1;
- SCRIPT_MSG("SetRegView: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_SETSHELLVARCONTEXT:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(all_user_var);
- int k=line.gettoken_enum(1,"current\0all\0");
- if (k<0) PRINTHELP()
- ent.offsets[1]=add_intstring(k);
- SCRIPT_MSG("SetShellVarContext: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_RET:
- SCRIPT_MSG("Return\n");
- ent.which=EW_RET;
- return add_entry(&ent);
- case TOK_CALL:
- if (!line.gettoken_str(1)[0] || (line.gettoken_str(1)[0]==':' && !line.gettoken_str(1)[1] )) PRINTHELP()
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
- if (uninstall_mode && strnicmp(line.gettoken_str(1),"un.",3)
- && (GetUserVarIndex(line,1) < 0) && line.gettoken_str(1)[0]!=':')
- {
- ERROR_MSG("Call must be used with function names starting with \"un.\" in the uninstall section.\n");
- PRINTHELP()
- }
- if (!uninstall_mode && !strnicmp(line.gettoken_str(1),"un.",3))
- {
- ERROR_MSG("Call must not be used with functions starting with \"un.\" in the non-uninstall sections.\n");
- PRINTHELP()
- }
-#endif
- ent.which=EW_CALL;
- ent.offsets[1]=0;
- {
- int v;
- if ((v=GetUserVarIndex(line, 1))>=0)
- {
- ent.offsets[0]=-v-2;
- }
- else
- {
- if (line.gettoken_str(1)[0] == ':')
- {
- ent.offsets[1]=1;
- ent.offsets[0]=ns_label.add(line.gettoken_str(1)+1,0);
- }
- else ent.offsets[0]=ns_func.add(line.gettoken_str(1),0);
- }
- }
- SCRIPT_MSG("Call \"%s\"\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_SETOUTPATH:
- {
- char *op=line.gettoken_str(1);
- if (!strcmp(op,"-"))
- {
- op="$INSTDIR";
- }
- SCRIPT_MSG("SetOutPath: \"%s\"\n",op);
- ent.which=EW_CREATEDIR;
- ent.offsets[0]=add_string(op);
- ent.offsets[1]=1;
-
- DefineInnerLangString(NLF_OUTPUT_DIR);
- }
- return add_entry(&ent);
- case TOK_CREATEDIR:
- {
- char out_path[1024];
- char *p=line.gettoken_str(1);
- if (*p == '-') out_path[0]=0;
- else
- {
- if (p[0] == '\\' && p[1] != '\\') p++;
- strncpy(out_path,p,1024-1);
- if (*CharPrev(out_path,out_path+strlen(out_path))=='\\')
- *CharPrev(out_path,out_path+strlen(out_path))=0; // remove trailing slash
- }
- if (!*out_path) PRINTHELP()
- SCRIPT_MSG("CreateDirectory: \"%s\"\n",out_path);
- ent.which=EW_CREATEDIR;
- ent.offsets[0]=add_string(out_path);
-
- DefineInnerLangString(NLF_CREATE_DIR);
- }
- return add_entry(&ent);
- case TOK_EXEC:
- case TOK_EXECWAIT:
-#ifdef NSIS_SUPPORT_EXECUTE
- ent.which=EW_EXECUTE;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[2]=0;
- if (which_token == TOK_EXECWAIT)
- {
- ent.offsets[2]=1;
- ent.offsets[1]=GetUserVarIndex(line, 2);
- if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
- }
- SCRIPT_MSG("%s: \"%s\" (->%s)\n",ent.offsets[2]?"ExecWait":"Exec",line.gettoken_str(1),line.gettoken_str(2));
-
- DefineInnerLangString(NLF_EXEC);
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_EXECUTE
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_EXECUTE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_EXECUTE
- case TOK_EXECSHELL: // this uses improvements of Andras Varga
-#ifdef NSIS_SUPPORT_SHELLEXECUTE
- {
- ent.which=EW_SHELLEXEC;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=SW_SHOWNORMAL;
- if (line.getnumtokens() > 4)
- {
- int tab[4]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_HIDE};
- int a=line.gettoken_enum(4,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0SW_HIDE\0");
- if (a < 0) PRINTHELP()
- ent.offsets[3]=tab[a];
- }
- string detail=string(line.gettoken_str(1))+" "+string(line.gettoken_str(2));
- ent.offsets[5]=add_string(detail.c_str());
- SCRIPT_MSG("ExecShell: %s: \"%s\" \"%s\" %s\n",line.gettoken_str(1),line.gettoken_str(2),
- line.gettoken_str(3),line.gettoken_str(4));
-
- DefineInnerLangString(NLF_EXEC_SHELL);
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_SHELLEXECUTE
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_SHELLEXECUTE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_SHELLEXECUTE
- case TOK_CALLINSTDLL:
- case TOK_REGDLL:
- case TOK_UNREGDLL:
-#ifndef NSIS_SUPPORT_ACTIVEXREG
- ERROR_MSG("%s: support not compiled in (NSIS_SUPPORT_ACTIVEXREG)\n",line.gettoken_str(0));
- return PS_ERROR;
-#else//NSIS_SUPPORT_ACTIVEXREG
- ent.which=EW_REGISTERDLL;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- if (which_token == TOK_UNREGDLL)
- {
- ent.offsets[1]=add_string("DllUnregisterServer");
- ent.offsets[2]=DefineInnerLangString(NLF_UNREGISTERING);
- }
- else if (which_token == TOK_CALLINSTDLL)
- {
- int a = 2;
- if (!stricmp(line.gettoken_str(a), "/NOUNLOAD")) {
- ent.offsets[3]=1;
- a++;
- }
- if (a+1 != line.getnumtokens()) PRINTHELP();
- ent.offsets[1]=add_string(line.gettoken_str(a));
- if (!ent.offsets[1]) PRINTHELP()
- ent.offsets[2]=0;
- }
- else // register
- {
- ent.offsets[1] = add_string(line.gettoken_str(2));
- if (!ent.offsets[1]) ent.offsets[1]=add_string("DllRegisterServer");
- ent.offsets[2]=DefineInnerLangString(NLF_REGISTERING);
- }
-
- SCRIPT_MSG("%s: \"%s\" %s\n",line.gettoken_str(0),line.gettoken_str(1), line.gettoken_str(ent.offsets[3]?3:2));
-
- DefineInnerLangString(NLF_SYMBOL_NOT_FOUND);
- DefineInnerLangString(NLF_COULD_NOT_LOAD);
- DefineInnerLangString(NLF_NO_OLE);
- // not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL);
- return add_entry(&ent);
-#endif//NSIS_SUPPORT_ACTIVEXREG
- case TOK_RENAME:
-#ifdef NSIS_SUPPORT_RENAME
- {
- int a=1;
- ent.which=EW_RENAME;
- if (!stricmp(line.gettoken_str(1),"/REBOOTOK"))
- {
- ent.offsets[2]=1;
- a++;
-#ifndef NSIS_SUPPORT_MOVEONREBOOT
- ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n");
- PRINTHELP()
-#endif
- }
- else if (line.gettoken_str(1)[0]=='/')
- {
- a=line.getnumtokens(); // cause usage to go here:
- }
- if (line.getnumtokens()!=a+2) PRINTHELP()
- ent.offsets[0]=add_string(line.gettoken_str(a));
- ent.offsets[1]=add_string(line.gettoken_str(a+1));
- string print = string(line.gettoken_str(a)) + "->" + string(line.gettoken_str(a+1));
- ent.offsets[3]=add_string(print.c_str());
- SCRIPT_MSG("Rename: %s%s->%s\n",ent.offsets[2]?"/REBOOTOK ":"",line.gettoken_str(a),line.gettoken_str(a+1));
-
- DefineInnerLangString(NLF_RENAME);
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- DefineInnerLangString(NLF_RENAME_ON_REBOOT);
-#endif
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_RENAME
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RENAME not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_RENAME
- case TOK_MESSAGEBOX:
-#ifdef NSIS_SUPPORT_MESSAGEBOX
- {
- #define MBD(x) {x,#x},
- struct
- {
- int id;
- char *str;
- } list[]=
- {
- MBD(MB_ABORTRETRYIGNORE)
- MBD(MB_OK)
- MBD(MB_OKCANCEL)
- MBD(MB_RETRYCANCEL)
- MBD(MB_YESNO)
- MBD(MB_YESNOCANCEL)
- MBD(MB_ICONEXCLAMATION)
- MBD(MB_ICONINFORMATION)
- MBD(MB_ICONQUESTION)
- MBD(MB_ICONSTOP)
- MBD(MB_USERICON)
- MBD(MB_TOPMOST)
- MBD(MB_SETFOREGROUND)
- MBD(MB_RIGHT)
- MBD(MB_RTLREADING)
- MBD(MB_DEFBUTTON1)
- MBD(MB_DEFBUTTON2)
- MBD(MB_DEFBUTTON3)
- MBD(MB_DEFBUTTON4)
- };
- #undef MBD
- int r=0;
- int x;
- char *p=line.gettoken_str(1);
-
- while (*p)
- {
- char *np=p;
- while (*np && *np != '|') np++;
- if (*np) *np++=0;
- for (x = 0 ; (unsigned) x < sizeof(list) / sizeof(list[0]) && strcmpi(list[x].str, p); x++);
- if ((unsigned) x < sizeof(list) / sizeof(list[0]))
- {
- r|=list[x].id;
- }
- else PRINTHELP()
- p=np;
- }
- ent.which=EW_MESSAGEBOX;
- ent.offsets[0]=r;
- ent.offsets[1]=add_string(line.gettoken_str(2));
- int rettab[] =
- {
- 0,IDABORT,IDCANCEL,IDIGNORE,IDNO,IDOK,IDRETRY,IDYES
- };
- const char *retstr="0\0IDABORT\0IDCANCEL\0IDIGNORE\0IDNO\0IDOK\0IDRETRY\0IDYES\0";
- int a=3;
- if (line.getnumtokens() > 3)
- {
- if (!strcmpi(line.gettoken_str(3),"/SD"))
- {
- int k=line.gettoken_enum(4,retstr);
- if (k <= 0) PRINTHELP();
- ent.offsets[0]|=rettab[k]<<21;
- a=5;
- }
- else if (line.getnumtokens() > 7)
- PRINTHELP();
-
- if (line.getnumtokens() > a)
- {
- ent.offsets[2]=line.gettoken_enum(a,retstr);
- if (ent.offsets[2] < 0)
- PRINTHELP();
- ent.offsets[2] = rettab[ent.offsets[2]];
- if (process_jump(line,a+1,&ent.offsets[3]))
- PRINTHELP();
- if (line.getnumtokens() > a+2)
- {
- int v=line.gettoken_enum(a+2,retstr);
- if (v < 0)
- PRINTHELP();
- ent.offsets[4] = rettab[v];
- if (process_jump(line,a+3,&ent.offsets[5]))
- PRINTHELP();
- }
- }
- }
- SCRIPT_MSG("MessageBox: %d: \"%s\"",r,line.gettoken_str(2));
- if (line.getnumtokens()>a+1) SCRIPT_MSG(" (on %s goto %s)",line.gettoken_str(a),line.gettoken_str(a+1));
- SCRIPT_MSG("\n");
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_MESSAGEBOX
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_MESSAGEBOX not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_MESSAGEBOX
- case TOK_CREATESHORTCUT:
-#ifdef NSIS_SUPPORT_CREATESHORTCUT
- ent.which=EW_CREATESHORTCUT;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=add_string(line.gettoken_str(4));
- ent.offsets[5]=add_string(line.gettoken_str(8));
- int s;
- ent.offsets[4]=line.gettoken_int(5,&s)&0xff;
- if (!s)
- {
- if (line.getnumtokens() > 5 && *line.gettoken_str(5))
- {
- ERROR_MSG("CreateShortCut: cannot interpret icon index\n");
- PRINTHELP()
- }
- ent.offsets[4]=0;
- }
- if (line.getnumtokens() > 6 && *line.gettoken_str(6))
- {
- int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINNOACTIVE/*SW_SHOWMINIMIZED doesn't work*/};
- int a=line.gettoken_enum(6,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0");
- if (a < 0)
- {
- ERROR_MSG("CreateShortCut: unknown show mode \"%s\"\n",line.gettoken_str(6));
- PRINTHELP()
- }
- ent.offsets[4]|=tab[a]<<8;
- }
- if (line.getnumtokens() > 7)
- {
- char *s=(line.gettoken_str(7));
-
- char b[255];
- for (unsigned int spos=0; (spos <= strlen(s)) && (spos <= 255); spos++)
- b[spos]=toupper(*(s+spos));
- strcpy(s,b);
-
- if (*s)
- {
- int c=0;
- if (strstr(s,"ALT|")) ent.offsets[4]|=HOTKEYF_ALT << 24;
- if (strstr(s,"CONTROL|")) ent.offsets[4]|=HOTKEYF_CONTROL << 24;
- if (strstr(s,"EXT|")) ent.offsets[4]|=HOTKEYF_EXT << 24;
- if (strstr(s,"SHIFT|")) ent.offsets[4]|=HOTKEYF_SHIFT << 24;
- while (strstr(s,"|"))
- {
- s=strstr(s,"|")+1;
- }
- if ((s[0] == 'F') && (s[1] >= '1' && s[1] <= '9'))
- {
- c=VK_F1-1+atoi(s+1);
- if (atoi(s+1) < 1 || atoi(s+1) > 24)
- {
- warning_fl("CreateShortCut: F-key \"%s\" out of range",s);
- }
- }
- else if (((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= '0' && s[0] <= '9')) && !s[1])
- c=s[0];
- else
- {
- c=s[0];
- warning_fl("CreateShortCut: unrecognized hotkey \"%s\"",s);
- }
- ent.offsets[4] |= (c) << 16;
- }
- }
- SCRIPT_MSG("CreateShortCut: \"%s\"->\"%s\" %s icon:%s,%d, showmode=0x%X, hotkey=0x%X, comment=%s\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),
- line.gettoken_str(4),ent.offsets[4]&0xff,(ent.offsets[4]>>8)&0xff,ent.offsets[4]>>16,line.gettoken_str(8));
-
- DefineInnerLangString(NLF_CREATE_SHORTCUT);
- DefineInnerLangString(NLF_ERR_CREATING_SHORTCUT);
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_CREATESHORTCUT
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_CREATESHORTCUT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_SUPPORT_CREATESHORTCUT
-#ifdef NSIS_SUPPORT_HWNDS
- case TOK_FINDWINDOW:
- ent.which=EW_FINDWINDOW;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0) PRINTHELP()
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=add_string(line.gettoken_str(4));
- ent.offsets[4]=add_string(line.gettoken_str(5));
- SCRIPT_MSG("FindWindow: output=%s, class=\"%s\", text=\"%s\" hwndparent=\"%s\" hwndafter=\"%s\"\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5));
- return add_entry(&ent);
- case TOK_SENDMESSAGE:
- ent.which=EW_SENDMESSAGE;
-
- if (line.gettoken_str(1)[0] == '/' || line.gettoken_str(2)[0] == '/' ||
- line.gettoken_str(3)[0] == '/' || line.gettoken_str(4)[0] == '/')
- {
- PRINTHELP()
- }
-
- SCRIPT_MSG("SendMessage:");
- {
- int a=5;
- ent.offsets[0]=GetUserVarIndex(line, 5);
- if (ent.offsets[0]>=0)
- {
- SCRIPT_MSG("(->%s)",line.gettoken_str(5));
- a++;
- }
-
- if (!strncmp(line.gettoken_str(a),"/TIMEOUT=",9))
- {
- ent.offsets[5]|=atoi(line.gettoken_str(a)+9)<<2;
- SCRIPT_MSG(" (timeout=%d)",ent.offsets[5]>>2);
- a++;
- }
-
- if (line.getnumtokens()>a)
- {
- PRINTHELP()
- }
- }
-
- if (!strncmp(line.gettoken_str(3),"STR:",4))
- {
- ent.offsets[5]|=1;
- ent.offsets[3]=add_string(line.gettoken_str(3)+4);
- }
- else ent.offsets[3]=add_string(line.gettoken_str(3));
- if (!strncmp(line.gettoken_str(4),"STR:",4))
- {
- ent.offsets[5]|=2;
- ent.offsets[4]=add_string(line.gettoken_str(4)+4);
- }
- else ent.offsets[4]=add_string(line.gettoken_str(4));
-
- ent.offsets[1]=add_string(line.gettoken_str(1));
- ent.offsets[2]=add_string(line.gettoken_str(2));
-
- SCRIPT_MSG("(%s,%s,%s,%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- return add_entry(&ent);
- case TOK_ISWINDOW:
- ent.which=EW_ISWINDOW;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- if (process_jump(line,2,&ent.offsets[1])||
- process_jump(line,3,&ent.offsets[2])) PRINTHELP()
- SCRIPT_MSG("IsWindow(%s): %s:%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- case TOK_GETDLGITEM:
- ent.which=EW_GETDLGITEM;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0]<0) PRINTHELP();
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- SCRIPT_MSG("GetDlgItem: output=%s dialog=%s item=%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
- case TOK_SETCTLCOLORS:
- {
- ctlcolors c={0, };
-
- ent.which=EW_SETCTLCOLORS;
- ent.offsets[0]=add_string(line.gettoken_str(1));
-
- int a = 2;
-
- if (!strcmpi(line.gettoken_str(2),"/BRANDING"))
- a++;
-
- {
- char *p;
-
- if (a == 2 && line.getnumtokens() == 5) {
- ERROR_MSG("Error: SetCtlColors expected 3 parameters, got 4\n");
- return PS_ERROR;
- }
-
- if (!strcmpi(line.gettoken_str(a+1),"transparent")) {
- c.flags|=CC_BKB;
- c.lbStyle=BS_NULL;
- c.bkmode=TRANSPARENT;
- }
- else {
- p=line.gettoken_str(a+1);
- if (*p) {
- int v=strtoul(p,&p,16);
- c.bkc=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
- c.flags|=CC_BK|CC_BKB;
- }
-
- c.lbStyle=BS_SOLID;
- c.bkmode=OPAQUE;
- }
-
- p=line.gettoken_str(a);
- if (*p) {
- int v=strtoul(p,&p,16);
- c.text=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16);
- c.flags|=CC_TEXT;
- }
- }
-
- if (a == 3)
- {
- c.flags|=CC_BK|CC_BKB;
- c.lbStyle=BS_NULL;
- if (!*line.gettoken_str(a+1))
- {
- c.bkc=COLOR_BTNFACE;
- c.flags|=CC_BK_SYS;
- }
- c.flags|=CC_TEXT;
- if (!*line.gettoken_str(a))
- {
- c.text=COLOR_BTNFACE;
- c.flags|=CC_TEXT_SYS;
- }
- c.bkmode=OPAQUE;
- }
-
- int i;
- int l=cur_ctlcolors->getlen()/sizeof(ctlcolors);
- for (i=0; i<l; i++) {
- if (!memcmp((ctlcolors*)cur_ctlcolors->get()+i,&c,sizeof(ctlcolors))) {
- ent.offsets[1]=i*sizeof(ctlcolors);
- break;
- }
- }
- if (i>=l) {
- ent.offsets[1]=cur_ctlcolors->add(&c,sizeof(ctlcolors));
- }
-
- SCRIPT_MSG("SetCtlColors: hwnd=%s %stext=%s background=%s\n",line.gettoken_str(1),a==2?"":"/BRANDING ",line.gettoken_str(a),line.gettoken_str(a+1));
- }
- return add_entry(&ent);
- case TOK_CREATEFONT:
- ent.which=EW_CREATEFONT;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=add_string(line.gettoken_str(2));
- SCRIPT_MSG("CreateFont: output=%s \"%s\"",line.gettoken_str(1),line.gettoken_str(2));
- {
- int height=0;
- int weight=0;
- int flags=0;
- for (int i = 3; i < line.getnumtokens(); i++) {
- char *tok=line.gettoken_str(i);
- if (tok[0]=='/') {
- if (!strcmpi(tok,"/ITALIC")) {
- SCRIPT_MSG(" /ITALIC");
- flags|=1;
- }
- else if (!strcmpi(tok,"/UNDERLINE")) {
- SCRIPT_MSG(" /UNDERLINE");
- flags|=2;
- }
- else if (!strcmpi(tok,"/STRIKE")) {
- SCRIPT_MSG(" /STRIKE");
- flags|=4;
- }
- else {
- SCRIPT_MSG("\n");
- PRINTHELP();
- }
- }
- else {
- if (!height) {
- SCRIPT_MSG(" height=%s",tok);
- height=add_string(tok);
- }
- else if (!weight) {
- SCRIPT_MSG(" weight=%s",tok);
- weight=add_string(tok);
- }
- else {
- SCRIPT_MSG("\n");
- PRINTHELP();
- }
- }
- }
- ent.offsets[2]=height;
- ent.offsets[3]=weight;
- ent.offsets[4]=flags;
- }
- SCRIPT_MSG("\n");
- return add_entry(&ent);
- case TOK_ENABLEWINDOW:
- ent.which=EW_SHOWWINDOW;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[3]=1;
- SCRIPT_MSG("EnableWindow: handle=%s enable=%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SHOWWINDOW:
- ent.which=EW_SHOWWINDOW;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- SCRIPT_MSG("ShowWindow: handle=%s show state=%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_HIDEWINDOW:
- ent.which=EW_SHOWWINDOW;
- ent.offsets[0]=add_string("$HWNDPARENT");
- ent.offsets[1]=add_string("0"/*SW_HIDE*/);
- ent.offsets[2]=1;
- SCRIPT_MSG("HideWindow\n");
- return add_entry(&ent);
- case TOK_BRINGTOFRONT:
- {
- int ret;
- ent.which=EW_SHOWWINDOW;
- ent.offsets[0]=add_string("$HWNDPARENT");
- ent.offsets[1]=add_string("5"/*SW_SHOW*/);
- ret = add_entry(&ent);
- if (ret != PS_OK) return ret;
- ent.which=EW_BRINGTOFRONT;
- ent.offsets[0]=0;
- ent.offsets[1]=0;
- SCRIPT_MSG("BringToFront\n");
- }
- return add_entry(&ent);
-#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT
- case TOK_GETDLGITEM:
- case TOK_SETCTLCOLORS:
- case TOK_SHOWWINDOW:
- case TOK_BRINGTOFRONT:
- case TOK_CREATEFONT:
- case TOK_HIDEWINDOW:
- case TOK_ENABLEWINDOW:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT
-#else//!NSIS_SUPPORT_HWNDS
- case TOK_ISWINDOW:
- case TOK_SENDMESSAGE:
- case TOK_FINDWINDOW:
- case TOK_GETDLGITEM:
- case TOK_SETCTLCOLORS:
- case TOK_SHOWWINDOW:
- case TOK_ENABLEWINDOW:
- case TOK_CREATEFONT:
- case TOK_HIDEWINDOW:
- case TOK_BRINGTOFRONT:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_HWNDS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_HWNDS
- case TOK_DELETE:
-#ifdef NSIS_SUPPORT_DELETE
- {
- int a=1;
- ent.which=EW_DELETEFILE;
- if (!stricmp(line.gettoken_str(a),"/REBOOTOK"))
- {
- a++;
- ent.offsets[1]=DEL_REBOOT;
-#ifndef NSIS_SUPPORT_MOVEONREBOOT
- ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n");
- PRINTHELP()
-#endif
- }
- else if (line.gettoken_str(1)[0]=='/')
- {
- a=line.getnumtokens();
- }
- if (line.getnumtokens() != a+1) PRINTHELP()
- ent.offsets[0]=add_string(line.gettoken_str(a));
- SCRIPT_MSG("Delete: %s\"%s\"\n",ent.offsets[1]?"/REBOOTOK ":"",line.gettoken_str(a));
-
- DefineInnerLangString(NLF_DEL_FILE);
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- DefineInnerLangString(NLF_DEL_ON_REBOOT);
-#endif
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_DELETE
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_DELETE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_DELETE
- case TOK_RMDIR:
-#ifdef NSIS_SUPPORT_RMDIR
- {
- int a=1;
- ent.which=EW_RMDIR;
- ent.offsets[1]=DEL_DIR;
- while (line.gettoken_str(a)[0]=='/')
- {
- if (!stricmp(line.gettoken_str(a),"/r"))
- {
- if (a == 3) PRINTHELP();
- a++;
- ent.offsets[1]|=DEL_RECURSE;
- }
- else if (!stricmp(line.gettoken_str(a),"/REBOOTOK"))
- {
- if (a == 3) PRINTHELP();
- a++;
- ent.offsets[1]|=DEL_REBOOT;
- }
- else PRINTHELP();
- }
- if (a < line.getnumtokens() - 1) PRINTHELP();
- ent.offsets[0]=add_string(line.gettoken_str(a));
- SCRIPT_MSG("RMDir: ");
- if (a>1)
- SCRIPT_MSG("%s ",line.gettoken_str(1));
- if (a>2)
- SCRIPT_MSG("%s ",line.gettoken_str(2));
- SCRIPT_MSG("\"%s\"\n",line.gettoken_str(a));
-
- DefineInnerLangString(NLF_REMOVE_DIR);
- DefineInnerLangString(NLF_DEL_FILE);
-#ifdef NSIS_SUPPORT_MOVEONREBOOT
- DefineInnerLangString(NLF_DEL_ON_REBOOT);
-#endif
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_RMDIR
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RMDIR not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_RMDIR
- case TOK_RESERVEFILE:
- case TOK_FILE:
-#ifdef NSIS_SUPPORT_FILE
- {
- set<string> excluded;
- int a=1,attrib=0,rec=0,fatal=1;
- if (!stricmp(line.gettoken_str(a),"/nonfatal")) {
- fatal=0;
- a++;
- }
- if (which_token == TOK_FILE && !stricmp(line.gettoken_str(a),"/a"))
- {
-#ifdef _WIN32
- attrib=1;
-#else
- warning_fl("%sFile /a is disabled for non Win32 platforms.",(which_token == TOK_FILE)?"":"Reserve");
-#endif
- a++;
- }
- if (!stricmp(line.gettoken_str(a),"/r"))
- {
- rec=1;
- a++;
- }
- else if (which_token == TOK_FILE && !strnicmp(line.gettoken_str(a),"/oname=",7))
- {
- char *on=line.gettoken_str(a)+7;
- a++;
- if (!*on||line.getnumtokens()!=a+1||strstr(on,"*") || strstr(on,"?")) PRINTHELP()
-
- if (on[0]=='"')
- {
- ERROR_MSG("%sFile: output name must not begin with a quote, use \"/oname=name with spaces\".\n",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a));
- PRINTHELP();
- }
-
- int tf=0;
-#ifdef _WIN32
- int v=do_add_file(line.gettoken_str(a), attrib, 0, &tf, on);
-#else
- char *fn = my_convert(line.gettoken_str(a));
- int v=do_add_file(fn, attrib, 0, &tf, on);
- my_convert_free(fn);
-#endif
- if (v != PS_OK) return v;
- if (tf > 1) PRINTHELP()
- if (!tf)
- {
- if (fatal)
- {
- ERROR_MSG("%sFile: \"%s\" -> no files found.\n",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a));
- PRINTHELP()
- }
- else
- {
- warning_fl("%sFile: \"%s\" -> no files found",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a));
-
- // workaround for bug #1299100
- // add a nop opcode so relative jumps will work as expected
- add_entry_direct(EW_NOP);
- }
- }
-
- return PS_OK;
- }
- if (!strnicmp(line.gettoken_str(a),"/x",2))
- {
- while (!strnicmp(line.gettoken_str(a),"/x",2))
- {
- a++;
-
- if (line.getnumtokens() < a+1) PRINTHELP()
-
- excluded.insert(line.gettoken_str(a));
- a++;
- }
- }
-#ifdef _WIN32
- if (line.gettoken_str(a)[0] == '/') PRINTHELP()
-#endif
- if (line.getnumtokens()<a+1) PRINTHELP()
- while (a < line.getnumtokens())
- {
-#ifdef _WIN32
- if (line.gettoken_str(a)[0]=='/') PRINTHELP()
-#endif
- char buf[32];
- char *t=line.gettoken_str(a++);
- if (t[0] && CharNext(t)[0] == ':' && CharNext(t)[1] == '\\' && !CharNext(t)[2])
- {
- strcpy(buf,"X:\\*.*");
- buf[0]=t[0];
- t=buf;
- }
- int tf=0;
-#ifdef _WIN32
- int v=do_add_file(t, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded);
-#else
- char *fn = my_convert(t);
- int v=do_add_file(fn, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded);
- my_convert_free(fn);
-#endif
- if (v != PS_OK) return v;
- if (!tf)
- {
- if (fatal)
- {
- ERROR_MSG("%sFile: \"%s\" -> no files found.\n",(which_token == TOK_FILE)?"":"Reserve",t);
- PRINTHELP();
- }
- else
- {
- warning_fl("%sFile: \"%s\" -> no files found.",(which_token == TOK_FILE)?"":"Reserve",t);
- }
- }
- }
- }
- return PS_OK;
-#else//!NSIS_SUPPORT_FILE
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_FILE
-#ifdef NSIS_SUPPORT_COPYFILES
- case TOK_COPYFILES:
- {
- ent.which=EW_COPYFILES;
- ent.offsets[2]=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_NOERRORUI|FOF_SIMPLEPROGRESS;
-
- int a=1;
- int x;
- for (x = 0; x < 2; x ++)
- {
- if (!stricmp(line.gettoken_str(a),"/SILENT"))
- {
- a++;
- ent.offsets[2]&=~FOF_SIMPLEPROGRESS;
- ent.offsets[2]|=FOF_SILENT;
- }
- else if (!stricmp(line.gettoken_str(a),"/FILESONLY"))
- {
- a++;
- ent.offsets[2]|=FOF_FILESONLY;
- }
- else if (line.gettoken_str(a)[0]=='/') PRINTHELP()
- else break;
- }
- if (line.getnumtokens() < a+2) PRINTHELP()
- ent.offsets[0]=add_string(line.gettoken_str(a));
- ent.offsets[1]=add_string(line.gettoken_str(a+1));
- string copy_to = string("$(^CopyTo)") + line.gettoken_str(a+1);
- ent.offsets[3]=add_string(copy_to.c_str());
- int s;
- int size_kb=line.gettoken_int(a+2,&s);
- if (!s && line.gettoken_str(a+2)[0]) PRINTHELP()
- section_add_size_kb(size_kb);
- SCRIPT_MSG("CopyFiles: %s\"%s\" -> \"%s\", size=%iKB\n",ent.offsets[2]&FOF_SILENT?"(silent) ":"", line.gettoken_str(a),line.gettoken_str(a+1),size_kb);
-
- DefineInnerLangString(NLF_COPY_FAILED);
- DefineInnerLangString(NLF_COPY_TO);
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_COPYFILES
- case TOK_COPYFILES:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_COPYFILES not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_COPYFILES
-
- case TOK_SETFILEATTRIBUTES:
- {
- #define MBD(x) {x,#x},
- struct
- {
- int id;
- char *str;
- } list[]=
- {
- MBD(FILE_ATTRIBUTE_NORMAL)
- MBD(FILE_ATTRIBUTE_ARCHIVE)
- MBD(FILE_ATTRIBUTE_HIDDEN)
- MBD(FILE_ATTRIBUTE_OFFLINE)
- MBD(FILE_ATTRIBUTE_READONLY)
- MBD(FILE_ATTRIBUTE_SYSTEM)
- MBD(FILE_ATTRIBUTE_TEMPORARY)
- {FILE_ATTRIBUTE_NORMAL,"NORMAL"},
- {FILE_ATTRIBUTE_ARCHIVE,"ARCHIVE"},
- {FILE_ATTRIBUTE_HIDDEN,"HIDDEN"},
- {FILE_ATTRIBUTE_OFFLINE,"OFFLINE"},
- {FILE_ATTRIBUTE_READONLY,"READONLY"},
- {FILE_ATTRIBUTE_SYSTEM,"SYSTEM"},
- {FILE_ATTRIBUTE_TEMPORARY,"TEMPORARY"},
- {FILE_ATTRIBUTE_NORMAL,"0"},
- };
- #undef MBD
- int r=0;
- int x;
- char *p=line.gettoken_str(2);
-
- while (*p)
- {
- char *np=p;
- while (*np && *np != '|') np++;
- if (*np) *np++=0;
- for (x = 0 ; (unsigned) x < sizeof(list)/sizeof(list[0]) && stricmp(list[x].str,p); x ++);
-
- if ((unsigned) x < sizeof(list)/sizeof(list[0]))
- {
- r|=list[x].id;
- }
- else PRINTHELP()
- p=np;
- }
- ent.which=EW_SETFILEATTRIBUTES;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=r;
- }
- return add_entry(&ent);
- case TOK_SLEEP:
- {
- ent.which=EW_SLEEP;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- SCRIPT_MSG("Sleep: %s ms\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_IFFILEEXISTS:
- ent.which=EW_IFFILEEXISTS;
- ent.offsets[0] = add_string(line.gettoken_str(1));
- if (process_jump(line,2,&ent.offsets[1]) ||
- process_jump(line,3,&ent.offsets[2])) PRINTHELP()
- SCRIPT_MSG("IfFileExists: \"%s\" ? %s : %s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
- case TOK_QUIT:
- ent.which=EW_QUIT;
- SCRIPT_MSG("Quit\n");
- return add_entry(&ent);
- case TOK_ABORT:
- ent.which=EW_ABORT;
- ent.offsets[0] = add_string(line.gettoken_str(1));
- SCRIPT_MSG("Abort: \"%s\"\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_SETDETAILSVIEW:
- {
- int v=line.gettoken_enum(1,"hide\0show\0");
- ent.which=EW_CHDETAILSVIEW;
- if (v < 0) PRINTHELP()
- ent.offsets[0] = v?SW_SHOWNA:SW_HIDE;
- ent.offsets[1] = v?SW_HIDE:SW_SHOWNA;
- SCRIPT_MSG("SetDetailsView: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_SETDETAILSPRINT:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(status_update);
- int k=line.gettoken_enum(1,"both\0textonly\0listonly\0none\0lastused\0");
- if (k<0) PRINTHELP()
- if (k == 4)
- {
- ent.offsets[2]=1;
- }
- else
- {
- // both 0
- // textonly 2
- // listonly 4
- // none 6
- ent.offsets[1]=add_intstring(k*2);
- }
- SCRIPT_MSG("SetDetailsPrint: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_SETAUTOCLOSE:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(autoclose);
- int k=line.gettoken_enum(1,"false\0true\0");
- if (k < 0) PRINTHELP()
- ent.offsets[1]=add_intstring(k);
- SCRIPT_MSG("SetAutoClose: %s\n",line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_IFERRORS:
- ent.which=EW_IFFLAG;
- if (process_jump(line,1,&ent.offsets[0]) ||
- process_jump(line,2,&ent.offsets[1])) PRINTHELP()
- ent.offsets[2]=FLAG_OFFSET(exec_error);
- ent.offsets[3]=0;//new value mask - clean error
- SCRIPT_MSG("IfErrors ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_IFABORT:
- ent.which=EW_IFFLAG;
- if (process_jump(line,1,&ent.offsets[0]) ||
- process_jump(line,2,&ent.offsets[1])) PRINTHELP()
- ent.offsets[2]=FLAG_OFFSET(abort);
- ent.offsets[3]=~0;//new value mask - keep flag
- SCRIPT_MSG("IfAbort ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_CLEARERRORS:
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(exec_error);
- ent.offsets[1]=add_intstring(0);
- SCRIPT_MSG("ClearErrors\n");
- return add_entry(&ent);
- case TOK_SETERRORS:
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(exec_error);
- ent.offsets[1]=add_intstring(1);
- SCRIPT_MSG("SetErrors\n");
- return add_entry(&ent);
- case TOK_SETERRORLEVEL:
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(errlvl);
- ent.offsets[1]=add_string(line.gettoken_str(1));
- SCRIPT_MSG("SetErrorLevel: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_GETERRORLEVEL:
- ent.which=EW_GETFLAG;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=FLAG_OFFSET(errlvl);
- if (line.gettoken_str(1)[0] && ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetErrorLevel: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
-#ifdef NSIS_SUPPORT_STROPTS
- case TOK_STRLEN:
- ent.which=EW_STRLEN;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=add_string(line.gettoken_str(2));
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("StrLen %s \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_STRCPY:
- ent.which=EW_ASSIGNVAR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=add_string(line.gettoken_str(4));
-
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("StrCpy %s \"%s\" (%s) (%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- return add_entry(&ent);
- case TOK_GETFUNCTIONADDR:
- ent.which=EW_GETFUNCTIONADDR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=ns_func.add(line.gettoken_str(2),0);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("GetFunctionAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_GETLABELADDR:
- ent.which=EW_GETLABELADDR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0 || process_jump(line,2,&ent.offsets[1])) PRINTHELP()
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- SCRIPT_MSG("GetLabelAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_GETCURRENTADDR:
- ent.which=EW_ASSIGNVAR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- {
- char buf[32];
- wsprintf(buf,"%d",1+(cur_header->blocks[NB_ENTRIES].num));
- ent.offsets[1]=add_string(buf);
- }
- if (ent.offsets[0] < 0) PRINTHELP()
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- SCRIPT_MSG("GetCurrentAddress: %s",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_STRCMP:
- case TOK_STRCMPS:
- ent.which=EW_STRCMP;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[4]=which_token == TOK_STRCMPS;
- if (process_jump(line,3,&ent.offsets[2]) ||
- process_jump(line,4,&ent.offsets[3])) PRINTHELP()
- SCRIPT_MSG("%s \"%s\" \"%s\" equal=%s, nonequal=%s\n",line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4));
- return add_entry(&ent);
- case TOK_GETDLLVERSIONLOCAL:
- {
- DWORD low, high;
- if (!GetDLLVersion(line.gettoken_str(1),high,low))
- {
- ERROR_MSG("GetDLLVersionLocal: error reading version info from \"%s\"\n",line.gettoken_str(1));
- return PS_ERROR;
- }
- ent.which=EW_ASSIGNVAR;
- ent.offsets[0]=GetUserVarIndex(line, 2);
- ent.offsets[1]=add_intstring(high);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- if (ent.offsets[0]<0) PRINTHELP()
- add_entry(&ent);
-
- ent.offsets[0]=GetUserVarIndex(line, 3);
- ent.offsets[1]=add_intstring(low);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetDLLVersionLocal: %s (%u,%u)->(%s,%s)\n",
- line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3));
- }
- return add_entry(&ent);
- case TOK_GETFILETIMELOCAL:
- {
- char buf[129];
- DWORD high=0,low=0;
-#ifdef _WIN32
- int flag=0;
- HANDLE hFile=CreateFile(line.gettoken_str(1),0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- FILETIME ft;
- if (GetFileTime(hFile,NULL,NULL,&ft))
- {
- high=ft.dwHighDateTime;
- low=ft.dwLowDateTime;
- flag=1;
- }
- CloseHandle(hFile);
- }
- if (!flag)
- {
- ERROR_MSG("GetFileTimeLocal: error reading date from \"%s\"\n",line.gettoken_str(1));
- return PS_ERROR;
- }
-#else
- struct stat st;
- if (!stat(line.gettoken_str(1), &st))
- {
- unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
- high = (DWORD) (ll >> 32);
- low = (DWORD) ll;
- }
- else
- {
- ERROR_MSG("GetFileTimeLocal: error reading date from \"%s\"\n",line.gettoken_str(1));
- return PS_ERROR;
- }
-#endif
-
- ent.which=EW_ASSIGNVAR;
- ent.offsets[0]=GetUserVarIndex(line, 2);
- wsprintf(buf,"%u",high);
- ent.offsets[1]=add_string(buf);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- if (ent.offsets[0]<0) PRINTHELP()
- add_entry(&ent);
-
- ent.offsets[0]=GetUserVarIndex(line, 3);
- wsprintf(buf,"%u",low);
- ent.offsets[1]=add_string(buf);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetFileTimeLocal: %s (%u,%u)->(%s,%s)\n",
- line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3));
- }
- return add_entry(&ent);
-
-#else//!NSIS_SUPPORT_STROPTS
- case TOK_GETDLLVERSIONLOCAL:
- case TOK_GETFILETIMELOCAL:
- case TOK_GETFUNCTIONADDR:
- case TOK_GETLABELADDR:
- case TOK_GETCURRENTADDR:
- case TOK_STRLEN:
- case TOK_STRCPY:
- case TOK_STRCMP:
- case TOK_STRCMPS:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STROPTS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_STROPTS
-#ifdef NSIS_SUPPORT_INIFILES
- case TOK_DELETEINISEC:
- case TOK_DELETEINISTR:
- {
- char *vname="";
- char *space="";
- ent.which=EW_WRITEINI;
- ent.offsets[0]=add_string(line.gettoken_str(2)); // section name
- if (line.getnumtokens() > 3)
- {
- vname=line.gettoken_str(3);
- ent.offsets[1]=add_string(vname); // value name
- space=" ";
- }
- else ent.offsets[1]=0;
- ent.offsets[2]=0;
- ent.offsets[3]=add_string(line.gettoken_str(1));
- SCRIPT_MSG("DeleteINI%s: [%s] %s%sin %s\n",*vname?"Str":"Sec",
- line.gettoken_str(2),vname,space,line.gettoken_str(1));
- }
- return add_entry(&ent);
- case TOK_FLUSHINI:
- ent.which=EW_WRITEINI;
- ent.offsets[3]=add_string(line.gettoken_str(1));
- SCRIPT_MSG("FlushINI: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_WRITEINISTR:
- ent.which=EW_WRITEINI;
- ent.offsets[0]=add_string(line.gettoken_str(2));
- ent.offsets[1]=add_string(line.gettoken_str(3));
- ent.offsets[2]=add_string(line.gettoken_str(4));
- ent.offsets[3]=add_string(line.gettoken_str(1));
- ent.offsets[4]=1; // write
- SCRIPT_MSG("WriteINIStr: [%s] %s=%s in %s\n",
- line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_READINISTR:
- ent.which=EW_READINISTR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0) PRINTHELP()
- ent.offsets[1]=add_string(line.gettoken_str(3));
- ent.offsets[2]=add_string(line.gettoken_str(4));
- ent.offsets[3]=add_string(line.gettoken_str(2));
- SCRIPT_MSG("ReadINIStr %s [%s]:%s from %s\n",line.gettoken_str(1),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(2));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_INIFILES
- case TOK_DELETEINISEC:
- case TOK_DELETEINISTR:
- case TOK_FLUSHINI:
- case TOK_WRITEINISTR:
- case TOK_READINISTR:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INIFILES not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_INIFILES
- case TOK_DETAILPRINT:
- ent.which=EW_UPDATETEXT;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=0;
- SCRIPT_MSG("DetailPrint: \"%s\"\n",line.gettoken_str(1));
- return add_entry(&ent);
-#ifdef NSIS_SUPPORT_FNUTIL
- case TOK_GETTEMPFILENAME:
- ent.which=EW_GETTEMPFILENAME;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (line.getnumtokens() == 3)
- ent.offsets[1]=add_string(line.gettoken_str(2));
- else
- ent.offsets[1]=add_string("$TEMP");
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetTempFileName -> %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_GETFULLPATHNAME:
- {
- int a=0;
- ent.which=EW_GETFULLPATHNAME;
- if (line.getnumtokens()==4 && !stricmp(line.gettoken_str(1),"/SHORT")) a++;
- else if (line.getnumtokens()==4 || *line.gettoken_str(1)=='/') PRINTHELP()
- ent.offsets[0]=add_string(line.gettoken_str(2+a));
- ent.offsets[1]=GetUserVarIndex(line, 1+a);
- ent.offsets[2]=!a;
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetFullPathName: %s->%s (%d)\n",
- line.gettoken_str(2+a),line.gettoken_str(1+a),a?"sfn":"lfn");
- }
- return add_entry(&ent);
- case TOK_SEARCHPATH:
- ent.which=EW_SEARCHPATH;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0) PRINTHELP()
- ent.offsets[1]=add_string(line.gettoken_str(2));
- SCRIPT_MSG("SearchPath %s %s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
-#else
- case TOK_SEARCHPATH:
- case TOK_GETTEMPFILENAME:
- case TOK_GETFULLPATHNAME:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FNUTIL not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif
- case TOK_GETDLLVERSION:
-#ifdef NSIS_SUPPORT_GETDLLVERSION
- ent.which=EW_GETDLLVERSION;
- ent.offsets[0]=GetUserVarIndex(line, 2);
- ent.offsets[1]=GetUserVarIndex(line, 3);
- ent.offsets[2]=add_string(line.gettoken_str(1));
- if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("GetDLLVersion: %s->%s,%s\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_GETDLLVERSION
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETDLLVERSION not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_GETDLLVERSION
- case TOK_GETFILETIME:
-#ifdef NSIS_SUPPORT_GETFILETIME
- ent.which=EW_GETFILETIME;
- ent.offsets[0]=GetUserVarIndex(line, 2);
- ent.offsets[1]=GetUserVarIndex(line, 3);
- ent.offsets[2]=add_string(line.gettoken_str(1));
- if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("GetFileTime: %s->%s,%s\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_GETFILETIME
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETFILETIME not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_GETFILETIME
-#ifdef NSIS_SUPPORT_INTOPTS
- case TOK_INTOP:
- ent.which=EW_INTOP;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[3]=line.gettoken_enum(3,"+\0-\0*\0/\0|\0&\0^\0!\0||\0&&\0%\0<<\0>>\0~\0");
- if (ent.offsets[0] < 0 || ent.offsets[3] < 0 ||
- ((ent.offsets[3] == 7 || ent.offsets[3] == 13) && line.getnumtokens() > 4))
- PRINTHELP()
- ent.offsets[1]=add_string(line.gettoken_str(2));
- if (ent.offsets[3] != 7 && ent.offsets[3] != 13) ent.offsets[2]=add_string(line.gettoken_str(4));
- if (ent.offsets[3] == 13) {
- ent.offsets[3]=6;
- ent.offsets[2]=add_string("0xFFFFFFFF");
- }
- SCRIPT_MSG("IntOp: %s=%s%s%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- return add_entry(&ent);
- case TOK_INTFMT:
- ent.which=EW_INTFMT;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0]<0) PRINTHELP()
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- SCRIPT_MSG("IntFmt: %s->%s (fmt:%s)\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_INTCMP:
- case TOK_INTCMPU:
- ent.which=EW_INTCMP;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[5]=which_token == TOK_INTCMPU;
- if (process_jump(line,3,&ent.offsets[2]) ||
- process_jump(line,4,&ent.offsets[3]) ||
- process_jump(line,5,&ent.offsets[4])) PRINTHELP()
- SCRIPT_MSG("%s %s:%s equal=%s, < %s, > %s\n",line.gettoken_str(0),
- line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_INTOPTS
- case TOK_INTOP:
- case TOK_INTCMP:
- case TOK_INTFMT:
- case TOK_INTCMPU:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INTOPTS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_INTOPTS
-#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS
- case TOK_READREGSTR:
- case TOK_READREGDWORD:
- {
- ent.which=EW_READREGSTR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- int k=line.gettoken_enum(2,rootkeys[0]);
- if (k == -1) k=line.gettoken_enum(2,rootkeys[1]);
- if (ent.offsets[0] == -1 || k == -1) PRINTHELP()
- ent.offsets[1]=(int)rootkey_tab[k];
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=add_string(line.gettoken_str(4));
- if (which_token == TOK_READREGDWORD) ent.offsets[4]=1;
- else ent.offsets[4]=0;
- if (line.gettoken_str(3)[0] == '\\')
- warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0));
-
- SCRIPT_MSG("%s %s %s\\%s\\%s\n",line.gettoken_str(0),
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- }
- return add_entry(&ent);
- case TOK_DELETEREGVALUE:
- case TOK_DELETEREGKEY:
- {
- int a=1;
- if (which_token==TOK_DELETEREGKEY)
- {
- ent.offsets[4]=1;
- char *s=line.gettoken_str(a);
- if (s[0] == '/')
- {
- if (stricmp(s,"/ifempty")) PRINTHELP()
- a++;
- ent.offsets[4]=3;
- }
- if (line.gettoken_str(a+2)[0]) PRINTHELP()
- }
- int k=line.gettoken_enum(a,rootkeys[0]);
- if (k == -1) k=line.gettoken_enum(a,rootkeys[1]);
- if (k == -1) PRINTHELP()
- ent.which=EW_DELREG;
- ent.offsets[1]=(int)rootkey_tab[k];
- ent.offsets[2]=add_string(line.gettoken_str(a+1));
- ent.offsets[3]=(which_token==TOK_DELETEREGKEY)?0:add_string(line.gettoken_str(a+2));
- if (line.gettoken_str(a+1)[0] == '\\')
- warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0));
- if (which_token==TOK_DELETEREGKEY)
- SCRIPT_MSG("DeleteRegKey: %s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1));
- else
- SCRIPT_MSG("DeleteRegValue: %s\\%s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1),line.gettoken_str(a+2));
- }
- return add_entry(&ent);
- case TOK_WRITEREGSTR:
- case TOK_WRITEREGEXPANDSTR:
- case TOK_WRITEREGBIN:
- case TOK_WRITEREGDWORD:
- {
- int k=line.gettoken_enum(1,rootkeys[0]);
- if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
- if (k == -1) PRINTHELP()
- ent.which=EW_WRITEREG;
- ent.offsets[0]=(int)rootkey_tab[k];
- ent.offsets[1]=add_string(line.gettoken_str(2));
- if (line.gettoken_str(2)[0] == '\\')
- warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0));
- ent.offsets[2]=add_string(line.gettoken_str(3));
- if (which_token == TOK_WRITEREGSTR || which_token == TOK_WRITEREGEXPANDSTR)
- {
- SCRIPT_MSG("%s: %s\\%s\\%s=%s\n",
- line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- ent.offsets[3]=add_string(line.gettoken_str(4));
- ent.offsets[4]=ent.offsets[5]=REG_SZ;
- if (which_token == TOK_WRITEREGEXPANDSTR)
- {
- ent.offsets[5]=REG_EXPAND_SZ;
- }
- }
- if (which_token == TOK_WRITEREGBIN)
- {
- char data[3*NSIS_MAX_STRLEN];
- char *p=line.gettoken_str(4);
- int data_len=0;
- while (*p)
- {
- int c;
- int a,b;
- a=*p;
- if (a >= '0' && a <= '9') a-='0';
- else if (a >= 'a' && a <= 'f') a-='a'-10;
- else if (a >= 'A' && a <= 'F') a-='A'-10;
- else break;
- b=*++p;
- if (b >= '0' && b <= '9') b-='0';
- else if (b >= 'a' && b <= 'f') b-='a'-10;
- else if (b >= 'A' && b <= 'F') b-='A'-10;
- else break;
- p++;
- c=(a<<4)|b;
- if (data_len >= 3*NSIS_MAX_STRLEN)
- {
- ERROR_MSG("WriteRegBin: %d bytes of data exceeded\n",3*NSIS_MAX_STRLEN);
- return PS_ERROR;
- }
- data[data_len++]=c;
- }
- if (*p) PRINTHELP()
- SCRIPT_MSG("WriteRegBin: %s\\%s\\%s=%s\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- ent.offsets[3]=add_db_data(data,data_len);
- if (ent.offsets[3] < 0) return PS_ERROR;
- ent.offsets[4]=ent.offsets[5]=REG_BINARY;
- }
- if (which_token == TOK_WRITEREGDWORD)
- {
- ent.offsets[3]=add_string(line.gettoken_str(4));
- ent.offsets[4]=ent.offsets[5]=REG_DWORD;
-
- SCRIPT_MSG("WriteRegDWORD: %s\\%s\\%s=%s\n",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- }
- }
- return add_entry(&ent);
- case TOK_ENUMREGKEY:
- case TOK_ENUMREGVAL:
- {
- ent.which=EW_REGENUM;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- int k=line.gettoken_enum(2,rootkeys[0]);
- if (k == -1) k=line.gettoken_enum(2,rootkeys[1]);
- if (ent.offsets[0] == -1 || k == -1) PRINTHELP()
- ent.offsets[1]=(int)rootkey_tab[k];
- ent.offsets[2]=add_string(line.gettoken_str(3));
- ent.offsets[3]=add_string(line.gettoken_str(4));
- ent.offsets[4]=which_token == TOK_ENUMREGKEY;
- if (line.gettoken_str(3)[0] == '\\') warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0));
- SCRIPT_MSG("%s %s %s\\%s\\%s\n",which_token == TOK_ENUMREGKEY ? "EnumRegKey" : "EnumRegValue",
- line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_REGISTRYFUNCTIONS
- case TOK_READREGSTR:
- case TOK_READREGDWORD:
- case TOK_DELETEREGVALUE:
- case TOK_DELETEREGKEY:
- case TOK_WRITEREGSTR:
- case TOK_WRITEREGEXPANDSTR:
- case TOK_WRITEREGBIN:
- case TOK_WRITEREGDWORD:
- case TOK_ENUMREGKEY:
- case TOK_ENUMREGVAL:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REGISTRYFUNCTIONS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_REGISTRYFUNCTIONS
-#ifdef NSIS_SUPPORT_STACK
- case TOK_EXCH:
- {
- int swapitem=1;
- int save=GetUserVarIndex(line, 1);
- ent.which=EW_PUSHPOP;
- if (line.gettoken_str(1)[0] && save<0)
- {
- int s=0;
- swapitem=line.gettoken_int(1,&s);
- if (!s || swapitem <= 0) PRINTHELP()
- }
- if (save>=0)
- {
- SCRIPT_MSG("Exch(%s,0)\n",line.gettoken_str(1));
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=0;
- ent.offsets[2]=0;
- add_entry(&ent);
- }
- else SCRIPT_MSG("Exch(st(%d),0)\n",swapitem);
-
- ent.offsets[0]=0;
- ent.offsets[1]=0;
- ent.offsets[2]=swapitem;
-
- if (save>=0)
- {
- add_entry(&ent);
- ent.offsets[0]=save;
- ent.offsets[1]=1;
- ent.offsets[2]=0;
- }
-
- DefineInnerLangString(NLF_INST_CORRUPTED);
- }
- return add_entry(&ent);
- case TOK_PUSH:
- ent.which=EW_PUSHPOP;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=0;
- SCRIPT_MSG("Push: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_POP:
- ent.which=EW_PUSHPOP;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=1;
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("Pop: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_STACK
- case TOK_POP:
- case TOK_PUSH:
- case TOK_EXCH:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STACK not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_STACK
-#ifdef NSIS_SUPPORT_ENVIRONMENT
- case TOK_READENVSTR:
- ent.which=EW_READENVSTR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- {
- char str[NSIS_MAX_STRLEN];
- strcpy(str, "%");
- strcat(str, line.gettoken_str(2));
- strcat(str, "%");
- ent.offsets[1]=add_string(str);
- if (ent.offsets[0] < 0 || strlen(line.gettoken_str(2))<1) PRINTHELP()
- }
- ent.offsets[2]=1;
- SCRIPT_MSG("ReadEnvStr: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_EXPANDENVSTRS:
- ent.which=EW_READENVSTR;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=0;
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("ExpandEnvStrings: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_ENVIRONMENT
- case TOK_EXPANDENVSTRS:
- case TOK_READENVSTR:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_ENVIRONMENT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_ENVIRONMENT
-#ifdef NSIS_SUPPORT_FINDFIRST
- case TOK_FINDFIRST:
- ent.which=EW_FINDFIRST;
- ent.offsets[0]=GetUserVarIndex(line, 2); // out
- ent.offsets[1]=GetUserVarIndex(line, 1); // handleout
- ent.offsets[2]=add_string(line.gettoken_str(3)); // filespec
- if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP()
- SCRIPT_MSG("FindFirst: spec=\"%s\" handle=%s output=%s\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_FINDNEXT:
- ent.which=EW_FINDNEXT;
- ent.offsets[0]=GetUserVarIndex(line, 2);
- ent.offsets[1]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP()
- SCRIPT_MSG("FindNext: handle=%s output=%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_FINDCLOSE:
- ent.which=EW_FINDCLOSE;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("FindClose: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_FINDFIRST
- case TOK_FINDCLOSE:
- case TOK_FINDNEXT:
- case TOK_FINDFIRST:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FINDFIRST not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-
-#endif//!NSIS_SUPPORT_FINDFIRST
-
-
-#ifdef NSIS_SUPPORT_FILEFUNCTIONS
- case TOK_FILEOPEN:
- {
- ent.which=EW_FOPEN;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- ent.offsets[3]=add_string(line.gettoken_str(2));
- ent.offsets[1]=0; //openmode
- if (!stricmp(line.gettoken_str(3),"r"))
- {
- ent.offsets[1]=GENERIC_READ;
- ent.offsets[2]=OPEN_EXISTING;
- }
- else if (!stricmp(line.gettoken_str(3),"w"))
- {
- ent.offsets[1]=GENERIC_WRITE;
- ent.offsets[2]=CREATE_ALWAYS;
- }
- else if (!stricmp(line.gettoken_str(3),"a"))
- {
- ent.offsets[1]=GENERIC_WRITE|GENERIC_READ;
- ent.offsets[2]=OPEN_ALWAYS;
- }
-
- if (ent.offsets[0] < 0 || !ent.offsets[1]) PRINTHELP()
- }
- SCRIPT_MSG("FileOpen: %s as %s -> %s\n",line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_FILECLOSE:
- ent.which=EW_FCLOSE;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- if (ent.offsets[0] < 0) PRINTHELP()
- SCRIPT_MSG("FileClose: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_FILEREAD:
- ent.which=EW_FGETS;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- ent.offsets[1]=GetUserVarIndex(line, 2); // output string
- if (line.gettoken_str(3)[0])
- ent.offsets[2]=add_string(line.gettoken_str(3));
- else
- ent.offsets[2]=add_intstring(NSIS_MAX_STRLEN-1);
- if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("FileRead: %s->%s (max:%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
- return add_entry(&ent);
- case TOK_FILEWRITE:
- ent.which=EW_FPUTS;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- ent.offsets[1]=add_string(line.gettoken_str(2));
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("FileWrite: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_FILEREADBYTE:
- ent.which=EW_FGETS;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- ent.offsets[1]=GetUserVarIndex(line, 2); // output string
- ent.offsets[2]=add_string("1");
- ent.offsets[3]=1;
- if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("FileReadByte: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_FILEWRITEBYTE:
- ent.which=EW_FPUTS;
- ent.offsets[0]=GetUserVarIndex(line, 1); // file handle
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=1;
- if (ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("FileWriteByte: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_FILESEEK:
- {
- char *modestr;
- int tab[3]={FILE_BEGIN,FILE_CURRENT,FILE_END};
- int mode=line.gettoken_enum(3,"SET\0CUR\0END\0");
- ent.which=EW_FSEEK;
- ent.offsets[0]=GetUserVarIndex(line, 1);
- ent.offsets[1]=GetUserVarIndex(line, 4);
- ent.offsets[2]=add_string(line.gettoken_str(2));
-
- if (mode<0 && !line.gettoken_str(3)[0])
- {
- mode=0;
- modestr="SET";
- }
- else modestr=line.gettoken_str(3);
-
- if (mode<0 || ent.offsets[0] < 0 || (ent.offsets[1]<0 && line.gettoken_str(4)[0])) PRINTHELP()
- ent.offsets[3]=tab[mode];
- SCRIPT_MSG("FileSeek: fp=%s, ofs=%s, mode=%s, output=%s\n",
- line.gettoken_str(1),
- line.gettoken_str(2),
- modestr,
- line.gettoken_str(4));
- }
-
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_FILEFUNCTIONS
- case TOK_FILEOPEN:
- case TOK_FILECLOSE:
- case TOK_FILESEEK:
- case TOK_FILEREAD:
- case TOK_FILEWRITE:
- case TOK_FILEREADBYTE:
- case TOK_FILEWRITEBYTE:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILEFUNCTIONS not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-
-#endif//!NSIS_SUPPORT_FILEFUNCTIONS
-#ifdef NSIS_SUPPORT_REBOOT
- case TOK_REBOOT:
- {
- int ret = add_entry_direct(EW_REBOOT, 0xbadf00d);
- if (ret != PS_OK) return ret;
-
- ret = add_entry_direct(EW_QUIT);
- if (ret != PS_OK) return ret;
-
- SCRIPT_MSG("Reboot! (WOW)\n");
-
- DefineInnerLangString(NLF_INST_CORRUPTED);
- }
- return PS_OK;
- case TOK_IFREBOOTFLAG:
- ent.which=EW_IFFLAG;
- if (process_jump(line,1,&ent.offsets[0]) ||
- process_jump(line,2,&ent.offsets[1])) PRINTHELP()
- ent.offsets[2]=FLAG_OFFSET(exec_reboot);
- ent.offsets[3]=~0;//new value mask - keep flag
- SCRIPT_MSG("IfRebootFlag ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SETREBOOTFLAG:
- {
- ent.which=EW_SETFLAG;
- ent.offsets[0]=FLAG_OFFSET(exec_reboot);
- int k=line.gettoken_enum(1,"false\0true\0");
- if (k < 0) PRINTHELP()
- ent.offsets[1]=add_intstring(k);
- }
- return add_entry(&ent);
-#else//!NSIS_SUPPORT_REBOOT
- case TOK_REBOOT:
- case TOK_IFREBOOTFLAG:
- case TOK_SETREBOOTFLAG:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REBOOT not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_REBOOT
-#ifdef NSIS_CONFIG_LOG
- case TOK_LOGSET:
- ent.which=EW_LOG;
- ent.offsets[0]=1;
- ent.offsets[1]=line.gettoken_enum(1,"off\0on\0");
- if (ent.offsets[1]<0) PRINTHELP()
-
- SCRIPT_MSG("LogSet: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_LOGTEXT:
- ent.which=EW_LOG;
- ent.offsets[0]=0;
- ent.offsets[1]=add_string(line.gettoken_str(1));
- SCRIPT_MSG("LogText \"%s\"\n",line.gettoken_str(1));
- return add_entry(&ent);
-#else//!NSIS_CONFIG_LOG
-
- case TOK_LOGSET:
- case TOK_LOGTEXT:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_LOG not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_LOG
-#ifdef NSIS_CONFIG_COMPONENTPAGE
- case TOK_SECTIONSETTEXT:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[2]=SECTION_FIELD_SET(name_ptr);
- ent.offsets[4]=add_string(line.gettoken_str(2));
- SCRIPT_MSG("SectionSetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONGETTEXT:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=GetUserVarIndex(line, 2);
- ent.offsets[2]=SECTION_FIELD_GET(name_ptr);
- if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("SectionGetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONSETFLAGS:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=SECTION_FIELD_SET(flags);
- ent.offsets[3]=1;
- SCRIPT_MSG("SectionSetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONGETFLAGS:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=GetUserVarIndex(line, 2);
- ent.offsets[2]=SECTION_FIELD_GET(flags);
- if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("SectionGetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_INSTTYPESETTEXT:
- ent.which=EW_INSTTYPESET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=1;
- SCRIPT_MSG("InstTypeSetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_INSTTYPEGETTEXT:
- ent.which=EW_INSTTYPESET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=GetUserVarIndex(line, 2);
- ent.offsets[2]=0;
- if (line.gettoken_str(1)[0] && ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("InstTypeGetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONSETINSTTYPES:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=SECTION_FIELD_SET(install_types);
- SCRIPT_MSG("SectionSetInstTypes: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONGETINSTTYPES:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=GetUserVarIndex(line, 2);
- ent.offsets[2]=SECTION_FIELD_GET(install_types);
- if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("SectionGetInstTypes: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONSETSIZE:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=add_string(line.gettoken_str(2));
- ent.offsets[2]=SECTION_FIELD_SET(size_kb);
- SCRIPT_MSG("SectionSetSize: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SECTIONGETSIZE:
- ent.which=EW_SECTIONSET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=GetUserVarIndex(line, 2);
- ent.offsets[2]=SECTION_FIELD_GET(size_kb);
- if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP()
- SCRIPT_MSG("SectionGetSize: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2));
- return add_entry(&ent);
- case TOK_SETCURINSTTYPE:
- ent.which=EW_INSTTYPESET;
- ent.offsets[0]=add_string(line.gettoken_str(1));
- ent.offsets[1]=0;
- ent.offsets[2]=1;
- ent.offsets[3]=1;
- SCRIPT_MSG("SetCurInstType: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
- case TOK_GETCURINSTTYPE:
- ent.which=EW_INSTTYPESET;
- ent.offsets[0]=0;
- ent.offsets[1]=GetUserVarIndex(line,1);
- ent.offsets[2]=0;
- ent.offsets[3]=1;
- if (line.gettoken_str(1)[0] && ent.offsets[0]<0) PRINTHELP()
- SCRIPT_MSG("GetCurInstType: %s\n",line.gettoken_str(1));
- return add_entry(&ent);
-#else//!NSIS_CONFIG_COMPONENTPAGE
- case TOK_SECTIONSETTEXT:
- case TOK_SECTIONGETTEXT:
- case TOK_SECTIONSETFLAGS:
- case TOK_SECTIONGETFLAGS:
- case TOK_SECTIONSETSIZE:
- case TOK_SECTIONGETSIZE:
- case TOK_SECTIONSETINSTTYPES:
- case TOK_SECTIONGETINSTTYPES:
- case TOK_SETCURINSTTYPE:
- case TOK_GETCURINSTTYPE:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_CONFIG_COMPONENTPAGE
-#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT
- case TOK_SETBRANDINGIMAGE:
- {
- SCRIPT_MSG("SetBrandingImage: ");
- if (!branding_image_found) {
- ERROR_MSG("\nError: no branding image found in chosen UI!\n");
- return PS_ERROR;
- }
- ent.which=EW_SETBRANDINGIMAGE;
- for (int i = 1; i < line.getnumtokens(); i++)
- if (!strnicmp(line.gettoken_str(i),"/IMGID=",7)) {
- ent.offsets[1]=atoi(line.gettoken_str(i)+7);
- SCRIPT_MSG("/IMGID=%d ",ent.offsets[1]);
- }
- else if (!stricmp(line.gettoken_str(i),"/RESIZETOFIT")) {
- ent.offsets[2]=1; // must be 1 or 0
- SCRIPT_MSG("/RESIZETOFIT ");
- }
- else if (!ent.offsets[0]) {
- ent.offsets[0]=add_string(line.gettoken_str(i));
- SCRIPT_MSG("\"%s\" ", line.gettoken_str(i));
- }
- else {
- SCRIPT_MSG("\n");
- PRINTHELP();
- }
-
- if (!ent.offsets[1])
- ent.offsets[1]=branding_image_id;
- SCRIPT_MSG("\n");
- }
- return add_entry(&ent);
-#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT
- case TOK_SETBRANDINGIMAGE:
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n",line.gettoken_str(0));
- return PS_ERROR;
-#endif//!NSIS_SUPPORT_CREATEFONT
-
- // Added by ramon 3 jun 2003
- case TOK_DEFVAR:
- {
- int a=1;
-
- if (!strcmpi(line.gettoken_str(1),"/GLOBAL"))
- {
- a++;
- }
-
- if (build_cursection)
- {
- if (a==1)
- {
- ERROR_MSG("Var: currently, only global variables can be defined.\n");
- PRINTHELP();
- }
- }
-
- SCRIPT_MSG("Var: \"%s\"\n",line.gettoken_str(a));
-
- int res = DeclaredUserVar(line.gettoken_str(a));
- if (res != PS_OK)
- return res;
-
- }
- return PS_OK;
-
- // Added by ramon 6 jun 2003
-#ifdef NSIS_SUPPORT_VERSION_INFO
- case TOK_VI_ADDKEY:
- {
- LANGID LangID=0;
- int a = 1;
- if (!strnicmp(line.gettoken_str(a),"/LANG=",6))
- LangID=atoi(line.gettoken_str(a++)+6);
- if (line.getnumtokens()!=a+2) PRINTHELP();
- char *pKey = line.gettoken_str(a);
- char *pValue = line.gettoken_str(a+1);
- if ( !(*pKey) )
- {
- ERROR_MSG("Error: empty name for version info key!\n");
- return PS_ERROR;
- }
- else
- {
- SCRIPT_MSG("%s: \"%s\" \"%s\"\n", line.gettoken_str(0), line.gettoken_str(a), line.gettoken_str(a+1));
- LANGID lReaded = LangID;
- if ( a > 1 && lReaded == 0 )
- warning_fl("%s: %s language not loaded, using default \"1033-English\"", line.gettoken_str(0), line.gettoken_str(1));
-
- unsigned int codepage;
- char *lang_name = GetLangNameAndCP(LangID, &codepage);
-
- if ( rVersionInfo.SetKeyValue(LangID, codepage, pKey, pValue) )
- {
- ERROR_MSG("%s: \"%s\" \"%04d-%s\" already defined!\n",line.gettoken_str(0), line.gettoken_str(2), LangID, lang_name);
- return PS_ERROR;
- }
-
- return PS_OK;
- }
- }
- case TOK_VI_SETPRODUCTVERSION:
- if ( version_product_v[0] )
- {
- ERROR_MSG("Error: %s already defined!\n", line.gettoken_str(0));
- return PS_ERROR;
- }
- strcpy(version_product_v, line.gettoken_str(1));
- return PS_OK;
-
-#else
- case TOK_VI_ADDKEY:
- case TOK_VI_SETPRODUCTVERSION:
- ERROR_MSG("Error: %s specified, NSIS_SUPPORT_VERSION_INFO not defined.\n",line.gettoken_str(0));
- return PS_ERROR;
-#endif
-
- // end of instructions
- ///////////////////////////////////////////////////////////////////////////////
-
- // Added by Ximon Eighteen 5th August 2002
-#ifdef NSIS_CONFIG_PLUGIN_SUPPORT
- case TOK_PLUGINDIR:
- {
- if (line.getnumtokens() == 2)
- {
- SCRIPT_MSG("PluginDir: \"%s\"\n",line.gettoken_str(1));
-#ifdef _WIN32
- m_plugins.FindCommands(line.gettoken_str(1), display_info?true:false);
-#else
- char *converted_path = my_convert(line.gettoken_str(1));
- m_plugins.FindCommands(converted_path, display_info?true:false);
- my_convert_free(converted_path);
-#endif
- return PS_OK;
- }
- }
- return PS_ERROR;
- case TOK__PLUGINCOMMAND:
- {
- int ret;
-
- const string command = m_plugins.NormalizedCommand(line.gettoken_str(0));
- const string dllPath = m_plugins.GetPluginPath(command);
- int data_handle = m_plugins.GetPluginHandle(uninstall_mode?true:false, command);
-
- if (uninstall_mode) uninst_plugin_used = true;
- else plugin_used = true;
-
- // Initialize $PLUGINSDIR
- ent.which=EW_CALL;
- ent.offsets[0]=ns_func.add(uninstall_mode?"un.Initialize_____Plugins":"Initialize_____Plugins",0);
- ret=add_entry(&ent);
- if (ret != PS_OK) {
- return ret;
- }
-
- // DLL name on the user machine
- char tempDLL[NSIS_MAX_STRLEN];
- string dllName = get_file_name(dllPath);
- wsprintf(tempDLL, "$PLUGINSDIR\\%s", dllName.c_str());
-
- // Add the DLL to the installer
- if (data_handle == -1)
- {
- int files_added;
- int old_build_allowskipfiles=build_allowskipfiles;
- build_allowskipfiles=1; // on
- int old_build_overwrite=build_overwrite;
- build_overwrite=1; // off
- int old_build_datesave=build_datesave;
- build_datesave=0; // off
- ret=do_add_file(dllPath.c_str(),0,0,&files_added,tempDLL,2,&data_handle); // 2 means no size add
- if (ret != PS_OK) {
- return ret;
- }
- m_plugins.SetDllDataHandle(uninstall_mode?true:false, line.gettoken_str(0), data_handle);
- build_overwrite=old_build_overwrite;
- build_datesave=old_build_datesave;
- // Added by ramon 23 May 2003
- build_allowskipfiles=old_build_allowskipfiles;
- }
- else
- {
- ent.which=EW_EXTRACTFILE;
-
- DefineInnerLangString(NLF_SKIPPED);
- DefineInnerLangString(NLF_ERR_DECOMPRESSING);
- DefineInnerLangString(NLF_ERR_WRITING);
- DefineInnerLangString(NLF_EXTRACT);
- DefineInnerLangString(NLF_CANT_WRITE);
-
- ent.offsets[0]=1; // overwrite off
- ent.offsets[0]|=(MB_RETRYCANCEL|MB_ICONSTOP|(IDCANCEL<<21))<<3;
- ent.offsets[1]=add_string(tempDLL);
- ent.offsets[2]=data_handle;
- ent.offsets[3]=0xffffffff;
- ent.offsets[4]=0xffffffff;
- ent.offsets[5]=DefineInnerLangString(NLF_FILE_ERROR);
- ret=add_entry(&ent);
- if (ret != PS_OK) {
- return ret;
- }
- }
-
- // SetDetailsPrint lastused
- ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1);
- if (ret != PS_OK) {
- return ret;
- }
-
- // Call the DLL
- string funcname = get_string_suffix(command, "::");
- SCRIPT_MSG("Plugin Command: %s",funcname.c_str());
-
- int i = 1;
- int nounload = 0;
- if (!strcmpi(line.gettoken_str(i), "/NOUNLOAD")) {
- i++;
- nounload++;
- }
-
- // First push dll args
-
- int parmst=i; // we push em in reverse order
- int nounloadmisused=0;
- for (; i < line.getnumtokens(); i++) {
- int w=parmst + (line.getnumtokens()-i - 1);
- ent.which=EW_PUSHPOP;
- ent.offsets[0]=add_string(line.gettoken_str(w));
- if (!strcmpi(line.gettoken_str(w), "/NOUNLOAD")) nounloadmisused=1;
- ent.offsets[1]=0;
- ent.offsets[2]=0;
- ret=add_entry(&ent);
- if (ret != PS_OK) {
- return ret;
- }
- SCRIPT_MSG(" %s",line.gettoken_str(i));
- }
- SCRIPT_MSG("\n");
- if (nounloadmisused)
- warning_fl("/NOUNLOAD must come first before any plugin parameter. Unless the plugin you are trying to use has a parameter /NOUNLOAD, you are doing something wrong");
-
- // next, call it
- ent.which=EW_REGISTERDLL;
- ent.offsets[0]=add_string(tempDLL);;
- ent.offsets[1]=add_string(funcname.c_str());
- ent.offsets[2]=0;
- ent.offsets[3]=nounload|build_plugin_unload;
- ent.offsets[4]=1;
- ret=add_entry(&ent);
- if (ret != PS_OK) {
- return ret;
- }
-
- DefineInnerLangString(NLF_SYMBOL_NOT_FOUND);
- DefineInnerLangString(NLF_COULD_NOT_LOAD);
- DefineInnerLangString(NLF_NO_OLE);
- // not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL);
-
- return PS_OK;
- }
- case TOK_INITPLUGINSDIR:
- {
- int ret;
- SCRIPT_MSG("%s\n",line.gettoken_str(0));
- if (uninstall_mode) uninst_plugin_used = true;
- else plugin_used = true;
- // Call [un.]Initialize_____Plugins
- ent.which=EW_CALL;
- ent.offsets[0]=ns_func.add(uninstall_mode?"un.Initialize_____Plugins":"Initialize_____Plugins",0);
- ret=add_entry(&ent);
- if (ret != PS_OK) return ret;
- // SetDetailsPrint lastused
- ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1);
- if (ret != PS_OK) return ret;
- }
- return PS_OK;
-#else
- case TOK_PLUGINDIR:
- case TOK__PLUGINCOMMAND:
- case TOK_INITPLUGINSDIR:
- {
- ERROR_MSG("Error: %s specified, NSIS_CONFIG_PLUGIN_SUPPORT not defined.\n",line.gettoken_str(0));
- }
- return PS_ERROR;
-#endif// NSIS_CONFIG_PLUGIN_SUPPORT
-
-#ifdef NSIS_LOCKWINDOW_SUPPORT
- case TOK_LOCKWINDOW:
- SCRIPT_MSG("LockWindow: lock state=%d\n",line.gettoken_str(1));
- ent.which=EW_LOCKWINDOW;
- ent.offsets[0]=line.gettoken_enum(1,"on\0off\0");
- if (ent.offsets[0] == -1)
- PRINTHELP();
- return add_entry(&ent);
-#else
- case TOK_LOCKWINDOW:
- {
- ERROR_MSG("Error: %s specified, NSIS_LOCKWINDOW_SUPPORT not defined.\n",line.gettoken_str(0));
- }
- return PS_ERROR;
-#endif // NSIS_LOCKWINDOW_SUPPORT
-
- default: break;
-
- }
- ERROR_MSG("Error: doCommand: Invalid token \"%s\".\n",line.gettoken_str(0));
- return PS_ERROR;
-}
-
-#ifdef NSIS_SUPPORT_FILE
-int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char *name_override, int generatecode, int *data_handle, const set<string>& excluded, const string& basedir, bool dir_created)
-{
- assert(!name_override || !recurse);
-
- string dir = get_dir_name(lgss);
- string spec;
-
- if (dir == lgss) {
- dir = ".";
- spec = lgss;
- } else {
- spec = string(lgss).substr(dir.length() + 1, string::npos);
- }
-
- if (spec == "") {
- spec = "*";
- }
-
- if (basedir == "") {
- dir_created = true;
-
- if (recurse) {
- // save $OUTDIR into $_OUTDIR [StrCpy $_OUTDIR $OUTDIR]
- if (add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("_OUTDIR"), add_string("$OUTDIR")) != PS_OK) {
- return PS_ERROR;
- }
- }
- }
-
- boost::scoped_ptr<dir_reader> dr( new_dir_reader() );
- dr->exclude(excluded);
- dr->read(dir);
-
- // add files in the current directory
- for (dir_reader::iterator files_itr = dr->files().begin();
- files_itr != dr->files().end();
- files_itr++)
- {
- if (!dir_reader::matches(*files_itr, spec))
- continue;
-
- if (!dir_created && generatecode) {
- SCRIPT_MSG("%sFile: Descending to: \"%s\"\n", generatecode ? "" : "Reserve", dir.c_str());
-
- if (do_add_file_create_dir(dir, basedir, attrib) != PS_OK) {
- return PS_ERROR;
- }
-
- dir_created = true;
- }
-
- if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle) != PS_OK) {
- return PS_ERROR;
- }
-
- (*total_files)++;
- }
-
- if (!recurse) {
- return PS_OK;
- }
-
- // recurse into directories
- for (dir_reader::iterator dirs_itr = dr->dirs().begin();
- dirs_itr != dr->dirs().end();
- dirs_itr++)
- {
- string new_dir;
- bool created = false;
-
- if (basedir == "") {
- new_dir = *dirs_itr;
- } else {
- new_dir = basedir + '\\' + *dirs_itr;
- }
-
- string new_spec = dir + PLATFORM_PATH_SEPARATOR_STR + *dirs_itr + PLATFORM_PATH_SEPARATOR_STR;
-
- if (!dir_reader::matches(*dirs_itr, spec)) {
- new_spec += spec;
- } else if (generatecode) {
- // always create directories that match
-
- SCRIPT_MSG("%sFile: Descending to: \"%s\"\n", generatecode ? "" : "Reserve", new_spec.c_str());
-
- if (do_add_file_create_dir(dir + '\\' + *dirs_itr, new_dir, attrib) != PS_OK) {
- return PS_ERROR;
- }
-
- created = true;
- }
-
- const char *new_spec_c = new_spec.c_str();
-
- int res = do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, excluded, new_dir, created);
- if (res != PS_OK) {
- return PS_ERROR;
- }
- }
-
- if (basedir == "") {
- SCRIPT_MSG("%sFile: Returning to: \"%s\"\n", generatecode ? "" : "Reserve", dir.c_str());
-
- // restore $OUTDIR from $_OUTDIR [SetOutPath $_OUTDIR]
- if (add_entry_direct(EW_CREATEDIR, add_string("$_OUTDIR"), 1) != PS_OK) {
- return PS_ERROR;
- }
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::add_file(const string& dir, const string& file, int attrib, const char *name_override, int generatecode, int *data_handle) {
- string newfn_s = dir + PLATFORM_PATH_SEPARATOR_C + file;
- const char *newfn = newfn_s.c_str();
- const char *filename = file.c_str();
-
- MMapFile mmap;
- DWORD len;
-
-#ifdef _WIN32
- HANDLE hFile = CreateFile(
- newfn,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
- NULL
- );
- if (hFile == INVALID_HANDLE_VALUE)
- {
- ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
-
- // Will auto-CloseHandle hFile
- MANAGE_WITH(hFile, CloseHandle);
-
- len = GetFileSize(hFile, NULL);
- if (len && !mmap.setfile(hFile, len))
- {
- ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
-#else
- struct stat s;
- if (stat(newfn, &s)) {
- ERROR_MSG("%sFile: failed stating file \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
-
- len = (DWORD) s.st_size;
-
- int fd = OPEN(newfn, O_RDONLY);
- if (fd == -1)
- {
- ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
-
- // Will auto-close(2) fd
- MANAGE_WITH(fd, close);
-
- if (len && !mmap.setfile(fd, len))
- {
- ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
-#endif
-
- if (generatecode&1)
- section_add_size_kb((len+1023)/1024);
- if (name_override) SCRIPT_MSG("%sFile: \"%s\"->\"%s\"",generatecode?"":"Reserve",filename,name_override);
- else SCRIPT_MSG("%sFile: \"%s\"",generatecode?"":"Reserve",filename);
- if (!build_compress_whole)
- if (build_compress) SCRIPT_MSG(" [compress]");
- fflush(stdout);
- char buf[1024];
- int last_build_datablock_used=getcurdbsize();
- entry ent={0,};
- if (generatecode)
- {
- ent.which=EW_EXTRACTFILE;
-
- DefineInnerLangString(NLF_SKIPPED);
- DefineInnerLangString(NLF_ERR_DECOMPRESSING);
- DefineInnerLangString(NLF_ERR_WRITING);
- DefineInnerLangString(NLF_EXTRACT);
- DefineInnerLangString(NLF_CANT_WRITE);
-
- ent.offsets[0]=build_overwrite;
- if (name_override)
- {
- ent.offsets[1]=add_string(name_override);
- }
- else
- {
- const char *i=filename;
- char *o=buf;
- while (*i)
- {
- const char c=*i++;
- *o++=c;
- if (c == '$') *o++='$';
- }
- *o=0;
- ent.offsets[1]=add_string(buf);
- }
- }
- ent.offsets[2]=add_db_data(&mmap);
-
- mmap.clear();
-
- if (ent.offsets[2] < 0)
- {
- return PS_ERROR;
- }
-
- if (data_handle)
- {
- *data_handle=ent.offsets[2];
- }
-
- {
- DWORD s=getcurdbsize()-last_build_datablock_used;
- if (s) s-=4;
- if (s != len) SCRIPT_MSG(" %d/%d bytes\n",s,len);
- else SCRIPT_MSG(" %d bytes\n",len);
- }
-
- if (generatecode)
- {
- if (build_datesave || build_overwrite>=0x3 /*ifnewer or ifdiff*/)
- {
-#ifdef _WIN32
- FILETIME ft;
- if (GetFileTime(hFile,NULL,NULL,&ft))
- {
- // FAT write time has a resolution of 2 seconds
- PULONGLONG fti = (PULONGLONG) &ft;
- *fti -= *fti % 20000000;
-
- ent.offsets[3]=ft.dwLowDateTime;
- ent.offsets[4]=ft.dwHighDateTime;
- }
-#else
- struct stat st;
- if (!fstat(fd, &st))
- {
- unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL;
-
- // FAT write time has a resolution of 2 seconds
- ll -= ll % 20000000;
-
- ent.offsets[3] = (int) ll;
- ent.offsets[4] = (int) (ll >> 32);
- }
-#endif
- else
- {
- ERROR_MSG("%sFile: failed getting file date from \"%s\"\n",generatecode?"":"Reserve",newfn);
- return PS_ERROR;
- }
- }
- else
- {
- ent.offsets[3]=0xffffffff;
- ent.offsets[4]=0xffffffff;
- }
-
- // overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits
- int mb = 0;
- if (build_allowskipfiles)
- {
- mb = MB_ABORTRETRYIGNORE | MB_ICONSTOP;
- // default for silent installers
- mb |= IDIGNORE << 21;
- }
- else
- {
- mb = MB_RETRYCANCEL | MB_ICONSTOP;
- // default for silent installers
- mb |= IDCANCEL << 21;
- }
- ent.offsets[0] |= mb << 3;
-
- ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE);
- }
-
- if (generatecode)
- {
- int a=add_entry(&ent);
- if (a != PS_OK)
- {
- return a;
- }
- if (attrib)
- {
-#ifdef _WIN32
- ent.which=EW_SETFILEATTRIBUTES;
- // $OUTDIR is the working directory
- ent.offsets[0]=add_string(name_override?name_override:buf);
- ent.offsets[1]=GetFileAttributes(newfn);
- ent.offsets[2]=0;
- ent.offsets[3]=0;
- ent.offsets[4]=0;
- ent.offsets[5]=0;
-
- if (ent.offsets[1] != INVALID_FILE_ATTRIBUTES)
- {
- a=add_entry(&ent);
- if (a != PS_OK)
- {
- return a;
- }
- }
-#endif
- }
- }
-
- return PS_OK;
-}
-
-int CEXEBuild::do_add_file_create_dir(const string& local_dir, const string& dir, int attrib) {
- string outdir_s = "$_OUTDIR\\" + dir;
-
- string::size_type pos = 1;
- pos = outdir_s.find('$', pos);
- while (pos != string::npos) {
- outdir_s = outdir_s.insert(pos, "$");
- pos = outdir_s.find('$', pos + 2);
- }
-
- int outdir = add_string(outdir_s.c_str());
-
- if (add_entry_direct(EW_CREATEDIR, outdir, 1) != PS_OK) {
- return PS_ERROR;
- }
-
-#ifdef _WIN32
- if (attrib) {
- int ndc = add_string(".");
-
- DWORD attr = GetFileAttributes(local_dir.c_str());
-
- if (attr != INVALID_FILE_ATTRIBUTES)
- {
- if (add_entry_direct(EW_SETFILEATTRIBUTES, ndc, attr) != PS_OK)
- {
- return PS_ERROR;
- }
- }
- }
-#endif
-
- return PS_OK;
-}
-#endif
+/* + * script.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <stdio.h> +#include <ctype.h> +#include "tokens.h" +#include "build.h" +#include "util.h" +#include "winchar.h" +#include "ResourceEditor.h" +#include "DialogTemplate.h" +#include "lang.h" +#include "dirreader.h" +#include "version.h" +#include "icon.h" +#include "exehead/resource.h" +#include <cassert> // for assert(3) +#include <time.h> +#include <string> +#include <algorithm> +#include "boost/scoped_ptr.hpp" + +using namespace std; + +#ifdef _WIN32 +# include <direct.h> // for chdir +#else +# include <sys/stat.h> // for stat and umask +# include <sys/types.h> // for mode_t +# include <fcntl.h> // for O_RDONLY +# include <unistd.h> +# include <stdlib.h> // for mkstemp +#endif + +#define MAX_INCLUDEDEPTH 10 +#define MAX_LINELENGTH 16384 + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES +// Added by Sunil Kamath 11 June 2003 +char *CEXEBuild::set_file_predefine(char *filename) +{ + char *oldfilename = definedlist.find("__FILE__"); + if(oldfilename) + { + oldfilename = strdup(oldfilename); + definedlist.del("__FILE__"); + } + char *p = strrchr(filename,'\\'); + if(p) { + p++; + } + else { + p = curfilename; + } + definedlist.add("__FILE__",p); + + return oldfilename; +} + +void CEXEBuild::restore_file_predefine(char *oldfilename) +{ + definedlist.del("__FILE__"); + if(oldfilename) { + definedlist.add("__FILE__",oldfilename); + free(oldfilename); + } +} + +char *CEXEBuild::set_timestamp_predefine(char *filename) +{ + char *oldtimestamp = definedlist.find("__TIMESTAMP__"); + if(oldtimestamp) { + oldtimestamp = strdup(oldtimestamp); + definedlist.del("__TIMESTAMP__"); + } + +#ifdef _WIN32 + char timestampbuf[256] = ""; + char datebuf[128] = ""; + char timebuf[128] = ""; + WIN32_FIND_DATA fd; + FILETIME floctime; + SYSTEMTIME stime; + + HANDLE hSearch = FindFirstFile(filename, &fd); + if (hSearch != INVALID_HANDLE_VALUE) + { + FindClose(hSearch); + + FileTimeToLocalFileTime(&fd.ftLastWriteTime, &floctime); + FileTimeToSystemTime(&floctime, &stime); + + GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &stime, NULL, datebuf, sizeof(datebuf)); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, sizeof(timebuf)); + wsprintf(timestampbuf,"%s %s",datebuf,timebuf); + + definedlist.add("__TIMESTAMP__",timestampbuf); + } +#else + struct stat st; + if (!stat(filename, &st)) + definedlist.add("__TIMESTAMP__",ctime(&st.st_mtime)); +#endif + + return oldtimestamp; +} + +void CEXEBuild::restore_timestamp_predefine(char *oldtimestamp) +{ + definedlist.del("__TIMESTAMP__"); + if(oldtimestamp) { + definedlist.add("__TIMESTAMP__",oldtimestamp); + free(oldtimestamp); + } +} + +char *CEXEBuild::set_line_predefine(int linecnt, BOOL is_macro) +{ + char* linebuf = NULL; + MANAGE_WITH(linebuf, free); + + char temp[128] = ""; + sprintf(temp,"%d",linecnt); + + char *oldline = definedlist.find("__LINE__"); + if(oldline) { + oldline = strdup(oldline); + definedlist.del("__LINE__"); + } + if(is_macro && oldline) { + linebuf = (char *)malloc(strlen(oldline)+strlen(temp)+2); + sprintf(linebuf,"%s.%s",oldline,temp); + } + else { + linebuf = strdup(temp); + } + definedlist.add("__LINE__",linebuf); + + return oldline; +} + +void CEXEBuild::restore_line_predefine(char *oldline) +{ + definedlist.del("__LINE__"); + if(oldline) { + definedlist.add("__LINE__",oldline); + free(oldline); + } +} + +void CEXEBuild::set_date_time_predefines() +{ + time_t etime; + struct tm * ltime; + char datebuf[128]; + char timebuf[128]; + + time(&etime); + ltime = localtime(&etime); +#ifdef _WIN32 + SYSTEMTIME stime; + stime.wYear = ltime->tm_year+1900; + stime.wMonth = ltime->tm_mon + 1; + stime.wDay = ltime->tm_mday; + stime.wHour= ltime->tm_hour; + stime.wMinute= ltime->tm_min; + stime.wSecond= ltime->tm_sec; + stime.wMilliseconds= 0; + GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, datebuf, sizeof(datebuf)); + definedlist.add("__DATE__",(char *)datebuf); + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, timebuf, sizeof(timebuf)); + definedlist.add("__TIME__",(char *)timebuf); +#else + my_strftime(datebuf, sizeof(datebuf), "%x", ltime); + definedlist.add("__DATE__",(char *)datebuf); + my_strftime(timebuf, sizeof(timebuf), "%X", ltime); + definedlist.add("__TIME__",(char *)timebuf); +#endif +} + +void CEXEBuild::del_date_time_predefines() +{ + definedlist.del("__DATE__"); + definedlist.del("__TIME__"); +} +#endif + +int CEXEBuild::process_script(FILE *filepointer, char *filename) +{ + linecnt = 0; + fp = filepointer; + curfilename = filename; + + if (has_called_write_output) + { + ERROR_MSG("Error (process_script): write_output already called, can't continue\n"); + return PS_ERROR; + } + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + set_date_time_predefines(); + char *oldfilename = set_file_predefine(curfilename); + char *oldtimestamp = set_timestamp_predefine(curfilename); +#endif + + int ret=parseScript(); + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + restore_file_predefine(oldfilename); + restore_timestamp_predefine(oldtimestamp); + del_date_time_predefines(); +#endif + + fp = 0; + curfilename = 0; + + if (m_linebuild.getlen()) + { + ERROR_MSG("Error: invalid script: last line ended with \\\n"); + return PS_ERROR; + } + + if (ret == PS_EOF && num_ifblock()) + { + ERROR_MSG("!if[macro][n]def: open at EOF - need !endif\n"); + return PS_ERROR; + } + + return ret; +} + +#define PRINTHELP() { print_help(line.gettoken_str(0)); return PS_ERROR; } + +void CEXEBuild::start_ifblock() +{ + ifblock ib = {0, }; + if (cur_ifblock) + ib.inherited_ignore = cur_ifblock->ignore || cur_ifblock->inherited_ignore; + int num = build_preprocessor_data.getlen() / sizeof(ifblock); + build_preprocessor_data.add(&ib, sizeof(ifblock)); + cur_ifblock = (ifblock *) build_preprocessor_data.get() + num; +} + +void CEXEBuild::end_ifblock() +{ + if (build_preprocessor_data.getlen()) + { + cur_ifblock--; + build_preprocessor_data.resize(build_preprocessor_data.getlen() - sizeof(ifblock)); + if (!build_preprocessor_data.getlen()) + cur_ifblock = 0; + } +} + +int CEXEBuild::num_ifblock() +{ + return build_preprocessor_data.getlen() / sizeof(ifblock); +} + +// Func size: just under 200 lines (orip) +int CEXEBuild::doParse(const char *str) +{ + LineParser line(inside_comment); + int res; + + while (*str == ' ' || *str == '\t') str++; + + // remove trailing slash and null, if there's a previous line + if (m_linebuild.getlen()>1) + m_linebuild.resize(m_linebuild.getlen()-2); + + m_linebuild.add(str,strlen(str)+1); + + // keep waiting for more lines, if this line ends with a backslash + if (str[0] && CharPrev(str,str+strlen(str))[0] == '\\') + { + line.parse((char*)m_linebuild.get()); + if (line.inComment()) + { + warning_fl("comment contains line-continuation character, following line will be ignored"); + } + return PS_OK; + } + + // parse before checking if the line should be ignored, so block comments won't be missed + + // escaped quotes should be ignored for compile time commands that set defines + // because defines can be inserted in commands at a later stage + bool ignore_escaping = (!strnicmp((char*)m_linebuild.get(),"!define",7) || !strnicmp((char*)m_linebuild.get(),"!insertmacro",12)); + res=line.parse((char*)m_linebuild.get(), ignore_escaping); + + inside_comment = line.inCommentBlock(); + + // if ignoring, ignore all lines that don't begin with an exclamation mark + { + bool ignore_line = cur_ifblock && (cur_ifblock->ignore || cur_ifblock->inherited_ignore); + char first_char = *(char *) m_linebuild.get(); + if (ignore_line && (first_char!='!' || !is_valid_token(line.gettoken_str(0)))) + { + m_linebuild.resize(0); + return PS_OK; + } + } + + m_linebuild.resize(0); + + if (res) + { + if (res==-2) ERROR_MSG("Error: unterminated string parsing line at %s:%d\n",curfilename,linecnt); + else ERROR_MSG("Error: error parsing line (%s:%d)\n",curfilename,linecnt); + return PS_ERROR; + } + +parse_again: + if (line.getnumtokens() < 1) return PS_OK; + + int np,op,pos; + int tkid=get_commandtoken(line.gettoken_str(0),&np,&op,&pos); + if (tkid == -1) + { + char *p=line.gettoken_str(0); + if (p[0] && p[strlen(p)-1]==':') + { + if (p[0] == '!' || (p[0] >= '0' && p[0] <= '9') || p[0] == '$' || p[0] == '-' || p[0] == '+') + { + ERROR_MSG("Invalid label: %s (labels cannot begin with !, $, -, +, or 0-9)\n",line.gettoken_str(0)); + return PS_ERROR; + } + if (add_label(line.gettoken_str(0))) return PS_ERROR; + line.eattoken(); + goto parse_again; + } + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + // Added by Ximon Eighteen 5th August 2002 + // We didn't recognise this command, could it be the name of a + // function exported from a dll? + if (m_plugins.IsPluginCommand(line.gettoken_str(0))) + { + np = 0; // parameters are optional + op = -1; // unlimited number of optional parameters + pos = -1; // placement will tested later + tkid = TOK__PLUGINCOMMAND; + } + else +#endif + { + ERROR_MSG("Invalid command: %s\n",line.gettoken_str(0)); + return PS_ERROR; + } + } + + if (IsTokenPlacedRight(pos, line.gettoken_str(0)) != PS_OK) + return PS_ERROR; + + int v=line.getnumtokens()-(np+1); + if (v < 0 || (op >= 0 && v > op)) // opt_parms is -1 for unlimited + { + ERROR_MSG("%s expects %d",line.gettoken_str(0),np); + if (op < 0) ERROR_MSG("+"); + if (op > 0) ERROR_MSG("-%d",op+np); + ERROR_MSG(" parameters, got %d.\n",line.getnumtokens()-1); + PRINTHELP() + } + + int if_from_else = 0; + + if (tkid == TOK_P_ELSE) + { + if (cur_ifblock && cur_ifblock->inherited_ignore) + return PS_OK; + + if (!num_ifblock()) + { + ERROR_MSG("!else: no if block open (!if[macro][n][def])\n"); + return PS_ERROR; + } + + if (cur_ifblock->elseused) + { + ERROR_MSG("!else: else already used in current if block\n"); + return PS_ERROR; + } + + if (cur_ifblock->hasexeced) + { + cur_ifblock->ignore++; + return PS_OK; + } + + if (line.getnumtokens() == 1) + { + cur_ifblock->ignore = !cur_ifblock->ignore; + // if not executed up until now, it will now + cur_ifblock->hasexeced++; + cur_ifblock->elseused++; + return PS_OK; + } + + line.eattoken(); + + int v=line.gettoken_enum(0,"if\0ifdef\0ifndef\0ifmacrodef\0ifmacrondef\0"); + if (v < 0) PRINTHELP() + if (line.getnumtokens() == 1) PRINTHELP() + int cmds[] = {TOK_P_IF, TOK_P_IFDEF, TOK_P_IFNDEF, TOK_P_IFMACRODEF, TOK_P_IFMACRONDEF}; + tkid = cmds[v]; + if_from_else++; + } + + if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF || + tkid == TOK_P_IFMACRODEF || tkid == TOK_P_IFMACRONDEF || + tkid == TOK_P_IF) + { + if (!if_from_else) + start_ifblock(); + + if (cur_ifblock && cur_ifblock->inherited_ignore) + { + return PS_OK; + } + + int istrue=0; + + int mod=0; + + int p=0; + + if (tkid == TOK_P_IF) { + if(!strcmp(line.gettoken_str(1),"!")) { + p = 1; + line.eattoken(); + } + + if(line.getnumtokens() == 2) + istrue = line.gettoken_int(1); + + else if (line.getnumtokens() == 4) { + mod = line.gettoken_enum(2,"=\0==\0!=\0<=\0<\0>\0>=\0&\0&&\0|\0||\0"); + + switch(mod) { + case 0: + case 1: + istrue = stricmp(line.gettoken_str(1),line.gettoken_str(3)) == 0; break; + case 2: + istrue = stricmp(line.gettoken_str(1),line.gettoken_str(3)) != 0; break; + case 3: + istrue = line.gettoken_float(1) <= line.gettoken_float(3); break; + case 4: + istrue = line.gettoken_float(1) < line.gettoken_float(3); break; + case 5: + istrue = line.gettoken_float(1) > line.gettoken_float(3); break; + case 6: + istrue = line.gettoken_float(1) >= line.gettoken_float(3); break; + case 7: + case 8: + istrue = line.gettoken_int(1) && line.gettoken_int(3); break; + case 9: + case 10: + istrue = line.gettoken_int(1) || line.gettoken_int(3); break; + default: + PRINTHELP() + } + } + else PRINTHELP() + + if(p) istrue = !istrue; + } + + else { + + // pure left to right precedence. Not too powerful, but useful. + for (p = 1; p < line.getnumtokens(); p ++) + { + if (p & 1) + { + int new_s; + if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF) + new_s=!!definedlist.find(line.gettoken_str(p)); + else + new_s=MacroExists(line.gettoken_str(p)); + if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFMACRONDEF) + new_s=!new_s; + + if (mod == 0) istrue = istrue || new_s; + else istrue = istrue && new_s; + } + else + { + mod=line.gettoken_enum(p,"|\0&\0||\0&&\0"); + if (mod == -1) PRINTHELP() + mod &= 1; + } + } + } + + if (istrue) + { + cur_ifblock->hasexeced++; + cur_ifblock->ignore = 0; + } + else + cur_ifblock->ignore++; + + return PS_OK; + } + if (tkid == TOK_P_ENDIF) { + if (!num_ifblock()) + { + ERROR_MSG("!endif: no if block open (!if[macro][n][def])\n"); + return PS_ERROR; + } + end_ifblock(); + return PS_OK; + } + if (!cur_ifblock || (!cur_ifblock->ignore && !cur_ifblock->inherited_ignore)) + { + return doCommand(tkid,line); + } + + return PS_OK; +} + +// Func size: about 140 lines (orip) +#ifdef NSIS_FIX_DEFINES_IN_STRINGS +void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist, bool bIgnoreDefines /*= false*/) +#else +void CEXEBuild::ps_addtoline(const char *str, GrowBuf &linedata, StringList &hist) +#endif +{ + // convert $\r, $\n to their literals + // preprocessor replace ${VAR} and $%VAR% with whatever value + // note that if VAR does not exist, ${VAR} or $%VAR% will go through unmodified + const char *in=str; + while (*in) + { + int add=1; + char *t; + char c=*in; + t=CharNext(in); + + if (t-in > 1) // handle multibyte chars (no escape) + { + linedata.add((void*)in,t-in); + in=t; + continue; + } + in=t; + + if (c == '$') + { + if (in[0] == '\\') + { + if (in[1] == 'r') + { + in+=2; + c='\r'; + } + else if (in[1] == 'n') + { + in+=2; + c='\n'; + } + else if (in[1] == 't') + { + in+=2; + c='\t'; + } + } + else if (in[0] == '{') + { + char *s=strdup(in+1); + MANAGE_WITH(s, free); + char *t=s; + unsigned int bn = 0; + while (*t) + { + if (*t == '{') bn++; + if (*t == '}' && bn-- == 0) break; + t=CharNext(t); + } + if (*t && t!=s +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + && !bIgnoreDefines +#endif + ) + { + *t=0; + // check for defines inside the define name - ${bla${blo}} + GrowBuf defname; + ps_addtoline(s,defname,hist); + defname.add("",1); + t=definedlist.find((char*)defname.get()); + if (t && hist.find((char*)defname.get(),0)<0) + { + in+=strlen(s)+2; + add=0; + hist.add((char*)defname.get(),0); +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + ps_addtoline(t,linedata,hist,true); +#else + ps_addtoline(t,linedata,hist); +#endif + hist.delbypos(hist.find((char*)defname.get(),0)); + } + } + } + else if (in[0] == '%') + { + char *s=strdup(in+1); + MANAGE_WITH(s, free); + char *t=s; + while (*t) + { + if (*t == '%') break; + t=CharNext(t); + } + if (*t && t!=s) + { + *t=0; + // check for defines inside the define name - ${bla${blo}} + GrowBuf defname; + ps_addtoline(s,defname,hist); + defname.add("",1); + t=getenv((char*)defname.get()); + if (t && hist.find((char*)defname.get(),0)<0) + { + in+=strlen(s)+2; + add=0; + hist.add((char*)defname.get(),0); +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + ps_addtoline(t,linedata,hist,true); +#else + ps_addtoline(t,linedata,hist); +#endif + hist.delbypos(hist.find((char*)defname.get(),0)); + } + } + } +#ifdef NSIS_FIX_DEFINES_IN_STRINGS + else if (in[0] == '$') + { + if (in[1] == '{') // Found $$ before - Don't replace this define + { + char *s=strdup(in+2); + MANAGE_WITH(s, free); + char *t=s; + unsigned int bn = 0; + while (*t) + { + if (*t == '{') bn++; + if (*t == '}' && bn-- == 0) break; + t=CharNext(t); + } + if (*t && t!=s) + { + *t=0; + // add text unchanged + GrowBuf defname; + ps_addtoline(s,defname,hist); + in++; + } + } + else + { + linedata.add((void*)&c,1); + in++; + } + } +#endif + } + if (add) linedata.add((void*)&c,1); + } +} + +int CEXEBuild::parseScript() +{ + char str[MAX_LINELENGTH]; + + for (;;) + { + char *p=str; + *p=0; + fgets(str,MAX_LINELENGTH,fp); + linecnt++; + if (feof(fp)&&!str[0]) break; + + // remove trailing whitespace + while (*p) p++; + if (p > str) p--; + while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--; + *++p=0; + + StringList hist; + GrowBuf linedata; + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + char *oldline = set_line_predefine(linecnt, FALSE); +#endif + + ps_addtoline(str,linedata,hist); + linedata.add((void*)"",1); + int ret=doParse((char*)linedata.get()); + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + restore_line_predefine(oldline); +#endif + + if (ret != PS_OK) return ret; + } + + return PS_EOF; +} + +int CEXEBuild::includeScript(char *f) +{ + SCRIPT_MSG("!include: \"%s\"\n",f); + FILE *incfp=FOPEN(f,"rt"); + if (!incfp) + { + ERROR_MSG("!include: could not open file: \"%s\"\n",f); + return PS_ERROR; + } + + // auto-fclose(3) incfp + MANAGE_WITH(incfp, fclose); + + if (build_include_depth >= MAX_INCLUDEDEPTH) + { + ERROR_MSG("parseScript: too many levels of includes (%d max).\n",MAX_INCLUDEDEPTH); + return PS_ERROR; + } + build_include_depth++; + + int last_linecnt=linecnt; + linecnt=0; + char *last_filename=curfilename; + curfilename=f; + FILE *last_fp=fp; + fp=incfp; + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + char *oldfilename = set_file_predefine(curfilename); + char *oldtimestamp = set_timestamp_predefine(curfilename); +#endif + + int r=parseScript(); + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + restore_file_predefine(oldfilename); + restore_timestamp_predefine(oldtimestamp); +#endif + + int errlinecnt=linecnt; + + linecnt=last_linecnt; + curfilename=last_filename; + fp=last_fp; + + build_include_depth--; + if (r != PS_EOF && r != PS_OK) + { + ERROR_MSG("!include: error in script: \"%s\" on line %d\n",f,errlinecnt); + return PS_ERROR; + } + SCRIPT_MSG("!include: closed: \"%s\"\n",f); + return PS_OK; +} + +// !ifmacro[n]def based on Anders Kjersem's code +int CEXEBuild::MacroExists(const char *macroname) +{ + char *m = (char *) m_macros.get(); + + while (m && *m) + { + // check if macroname matches + if (!stricmp(m, macroname)) + return 1; + + // skip macro name + m += strlen(m) + 1; + + // skip params + while (*m) m += strlen(m) + 1; + m++; + + // skip data + while (*m) m += strlen(m) + 1; + if (m - (char *) m_macros.get() >= m_macros.getlen() - 1) break; + m++; + } + return 0; +} + +int CEXEBuild::process_oneline(char *line, char *filename, int linenum) +{ + char *last_filename=curfilename; + curfilename=filename; + int last_linecnt=linecnt; + linecnt=linenum; + + StringList hist; + GrowBuf linedata; + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + char *oldfilename = NULL; + char *oldtimestamp = NULL; + char *oldline = NULL; + BOOL is_commandline = !strcmp(filename,"command line"); + BOOL is_macro = !strncmp(filename,"macro:",strlen("macro:")); + + if(!is_commandline) { // Don't set the predefines for command line /X option + if(!is_macro) { + oldfilename = set_file_predefine(curfilename); + oldtimestamp = set_timestamp_predefine(curfilename); + } + oldline = set_line_predefine(linecnt, is_macro); + } +#endif + + ps_addtoline(line,linedata,hist); + linedata.add((void*)"",1); + int ret=doParse((char*)linedata.get()); + +#ifdef NSIS_SUPPORT_STANDARD_PREDEFINES + // Added by Sunil Kamath 11 June 2003 + if(!is_commandline) { // Don't set the predefines for command line /X option + if(!is_macro) { + restore_file_predefine(oldfilename); + restore_timestamp_predefine(oldtimestamp); + } + restore_line_predefine(oldline); + } +#endif + + linecnt=last_linecnt; + curfilename=last_filename; + + return ret; +} + +int CEXEBuild::process_jump(LineParser &line, int wt, int *offs) +{ + const char *s=line.gettoken_str(wt); + int v; + + if (!stricmp(s,"0") || !stricmp(s,"")) *offs=0; + else if ((v=GetUserVarIndex(line, wt))>=0) + { + *offs=-v-1; // to jump to a user variable target, -variable_index-1 is stored. + } + else + { + if ((s[0] == '-' || s[0] == '+') && !atoi(s+1)) + { + ERROR_MSG("Error: Goto targets beginning with '+' or '-' must be followed by nonzero integer (relative jump)\n"); + return 1; + } + if ((s[0] >= '0' && s[0] <= '9') || s[0] == '$' || s[0] == '!') + { + ERROR_MSG("Error: Goto targets cannot begin with 0-9, $, !\n"); + return 1; + } + *offs=ns_label.add(s,0); + } + return 0; +} + +#define FLAG_OFFSET(flag) (FIELD_OFFSET(exec_flags, flag)/sizeof(int)) +#define SECTION_FIELD_GET(field) (FIELD_OFFSET(section, field)/sizeof(int)) +#define SECTION_FIELD_SET(field) (-1 - (int)(FIELD_OFFSET(section, field)/sizeof(int))) + +// Func size: about 5000 lines (orip) +int CEXEBuild::doCommand(int which_token, LineParser &line) +{ + static const char *rootkeys[2] = { + "HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0SHCTX\0", + "HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0SHELL_CONTEXT\0" + }; + static HKEY rootkey_tab[] = { + HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA,0 + }; + +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + build_plugin_table(); +#endif + + multiple_entries_instruction=0; + + entry ent={0,}; + switch (which_token) + { + // macro shit + /////////////////////////////////////////////////////////////////////////////// + case TOK_P_MACRO: + { + if (!line.gettoken_str(1)[0]) PRINTHELP() + char *t=(char *)m_macros.get(); + while (t && *t) + { + if (!stricmp(t,line.gettoken_str(1))) break; + t+=strlen(t)+1; + + // advance over parameters + while (*t) t+=strlen(t)+1; + t++; + + // advance over data + while (*t) t+=strlen(t)+1; + if (t-(char *)m_macros.get() >= m_macros.getlen()-1) + break; + t++; + } + if (t && *t) + { + ERROR_MSG("!macro: macro named \"%s\" already found!\n",line.gettoken_str(1)); + return PS_ERROR; + } + m_macros.add(line.gettoken_str(1),strlen(line.gettoken_str(1))+1); + + int pc; + for (pc=2; pc < line.getnumtokens(); pc ++) + { + if (!line.gettoken_str(pc)[0]) + { + ERROR_MSG("!macro: macro parameter %d is empty, not valid!\n",pc-1); + return PS_ERROR; + } + int a; + for (a=2; a < pc; a ++) + { + if (!stricmp(line.gettoken_str(pc),line.gettoken_str(a))) + { + ERROR_MSG("!macro: macro parameter named %s is used multiple times!\n", + line.gettoken_str(pc)); + return PS_ERROR; + } + } + m_macros.add(line.gettoken_str(pc),strlen(line.gettoken_str(pc))+1); + } + m_macros.add("",1); + + for (;;) + { + char str[MAX_LINELENGTH]; + char *p=str; + str[0]=0; + fgets(str,MAX_LINELENGTH,fp); + //SCRIPT_MSG("%s%s", str, str[strlen(str)-1]=='\n'?"":"\n"); + if (feof(fp) && !str[0]) + { + ERROR_MSG("!macro \"%s\": unterminated (no !macroend found in file)!\n",line.gettoken_str(1)); + return PS_ERROR; + } + // remove trailing whitespace + while (*p) p++; + if (p > str) p--; + while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--; + *++p=0; + LineParser l2(false); + if (!l2.parse(str)) + { + if (!stricmp(l2.gettoken_str(0),"!macroend")) + { + linecnt++; + break; + } + if (!stricmp(l2.gettoken_str(0),"!macro")) + { + ERROR_MSG("Error: can't define a macro inside a macro!\n"); + return PS_ERROR; + } + } + if (str[0]) m_macros.add(str,strlen(str)+1); + else m_macros.add(" ",2); + linecnt++; + } + m_macros.add("",1); + } + return PS_OK; + case TOK_P_MACROEND: + ERROR_MSG("!macroend: no macro currently open.\n"); + return PS_ERROR; + case TOK_P_INSERTMACRO: + { + if (!line.gettoken_str(1)[0]) PRINTHELP() + char *t=(char *)m_macros.get(); + char *m=t; + while (t && *t) + { + if (!stricmp(t,line.gettoken_str(1))) break; + t+=strlen(t)+1; + + // advance over parms + while (*t) t+=strlen(t)+1; + t++; + + // advance over data + while (*t) t+=strlen(t)+1; + if (t-(char *)m_macros.get() >= m_macros.getlen()-1) + break; + t++; + } + SCRIPT_MSG("!insertmacro: %s\n",line.gettoken_str(1)); + if (!t || !*t) + { + ERROR_MSG("!insertmacro: macro named \"%s\" not found!\n",line.gettoken_str(1)); + return PS_ERROR; + } + t+=strlen(t)+1; + + + GrowBuf l_define_names; + DefineList l_define_saves; + int npr=0; + // advance over parms + while (*t) + { + char *v=definedlist.find(t); + if (v) + { + l_define_saves.add(t,v); + definedlist.del(t); + } + l_define_names.add(t,strlen(t)+1); + definedlist.add(t,line.gettoken_str(npr+2)); + + npr++; + t+=strlen(t)+1; + } + l_define_names.add("",1); + t++; + if (npr != line.getnumtokens()-2) + { + ERROR_MSG("!insertmacro: macro \"%s\" requires %d parameter(s), passed %d!\n", + line.gettoken_str(1),npr,line.getnumtokens()-2); + return PS_ERROR; + } + + int lp=0; + char str[1024]; + if (m_macro_entry.find(line.gettoken_str(1),0)>=0) + { + ERROR_MSG("!insertmacro: macro \"%s\" already being inserted!\n",line.gettoken_str(1)); + return PS_ERROR; + } + int npos=m_macro_entry.add(line.gettoken_str(1),0); + + wsprintf(str,"macro:%s",line.gettoken_str(1)); + while (*t) + { + lp++; + if (strcmp(t," ")) + { + int ret=process_oneline(t,str,lp); + if (ret != PS_OK) + { + ERROR_MSG("Error in macro %s on macroline %d\n",line.gettoken_str(1),lp); + return ret; + } + } + { + // fix t if process_oneline changed m_macros + char *nm=(char *)m_macros.get(); + if (nm != m) + { + t += nm - m; + m = nm; + } + } + t+=strlen(t)+1; + } + m_macro_entry.delbypos(npos); + { + char *p=(char*)l_define_names.get(); + while (*p) + { + definedlist.del(p); + char *v; + if ((v=l_define_saves.find(p))) definedlist.add(p,v); + p+=strlen(p)+1; + } + } + SCRIPT_MSG("!insertmacro: end of %s\n",line.gettoken_str(1)); + } + return PS_OK; + + // preprocessor files fun + /////////////////////////////////////////////////////////////////////////////// + + case TOK_P_TEMPFILE: + { + char *symbol = line.gettoken_str(1); + char *fpath; + +#ifdef _WIN32 + char buf[MAX_PATH], buf2[MAX_PATH]; + + GetTempPath(MAX_PATH, buf); + if (!GetTempFileName(buf, "nst", 0, buf2)) + { + ERROR_MSG("!tempfile: unable to create temporary file.\n"); + return PS_ERROR; + } + + fpath = buf2; +#else + char t[] = "/tmp/makensisXXXXXX"; + + mode_t old_umask = umask(0077); + + int fd = mkstemp(t); + if (fd == -1) { + ERROR_MSG("!tempfile: unable to create temporary file.\n"); + return PS_ERROR; + } + close(fd); + + umask(old_umask); + + fpath = t; +#endif + + if (definedlist.add(symbol, fpath)) + { + ERROR_MSG("!tempfile: \"%s\" already defined!\n", symbol); + return PS_ERROR; + } + + SCRIPT_MSG("!tempfile: \"%s\"=\"%s\"\n", symbol, fpath); + } + return PS_OK; + + case TOK_P_DELFILE: + { + char *file = line.gettoken_str(1); +#ifndef _WIN32 + file = my_convert(file); +#endif + int result = unlink(file); +#ifndef _WIN32 + my_convert_free(file); +#endif + if (result == -1) { + ERROR_MSG("!delfile: \"%s\" couldn't be deleted.\n", line.gettoken_str(1)); + return PS_ERROR; + } + + SCRIPT_MSG("!delfile: \"%s\"\n", line.gettoken_str(1)); + } + return PS_OK; + + case TOK_P_APPENDFILE: + { + char *file = line.gettoken_str(1); + char *text = line.gettoken_str(2); + + FILE *fp = FOPEN(file, "a"); + if (!fp) + { + ERROR_MSG("!appendfile: \"%s\" couldn't be opened.\n", file); + return PS_ERROR; + } + + if (fputs(text, fp) < 0) + { + ERROR_MSG("!appendfile: error writing to \"%s\".\n", file); + return PS_ERROR; + } + + fclose(fp); + + SCRIPT_MSG("!appendfile: \"%s\" \"%s\"\n", file, text); + } + return PS_OK; + + // page ordering shit + /////////////////////////////////////////////////////////////////////////////// +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_UNINSTPAGE: + set_uninstall_mode(1); + case TOK_PAGE: + { + if (!uninstall_mode) { + enable_last_page_cancel = 0; + if (!stricmp(line.gettoken_str(line.getnumtokens()-1),"/ENABLECANCEL")) + enable_last_page_cancel = 1; + } + else { + uenable_last_page_cancel = 0; + if (!stricmp(line.gettoken_str(line.getnumtokens()-1),"/ENABLECANCEL")) + uenable_last_page_cancel = 1; + } + + int k = line.gettoken_enum(1,"custom\0license\0components\0directory\0instfiles\0uninstConfirm\0"); + + if (k < 0) PRINTHELP(); + + if (add_page(k) != PS_OK) + return PS_ERROR; + +#ifndef NSIS_SUPPORT_CODECALLBACKS + if (!k) { + ERROR_MSG("Error: custom page specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n"); + return PS_ERROR; + } +#endif//!NSIS_SUPPORT_CODECALLBACKS + + if (k) { + // not custom +#ifdef NSIS_SUPPORT_CODECALLBACKS + switch (line.getnumtokens() - enable_last_page_cancel) { + case 6: + PRINTHELP(); + case 5: + if (*line.gettoken_str(4)) + cur_page->leavefunc = ns_func.add(line.gettoken_str(4),0); + case 4: + if (*line.gettoken_str(3)) + cur_page->showfunc = ns_func.add(line.gettoken_str(3),0); + case 3: + if (*line.gettoken_str(2)) + cur_page->prefunc = ns_func.add(line.gettoken_str(2),0); + } +#endif//NSIS_SUPPORT_CODECALLBACKS + } +#ifdef NSIS_SUPPORT_CODECALLBACKS + else { + // a custom page + switch (line.getnumtokens() - enable_last_page_cancel) { + case 6: + PRINTHELP(); + case 5: + cur_page->caption = add_string(line.gettoken_str(4)); + case 4: + if (*line.gettoken_str(3)) + cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0); + case 3: + if (*line.gettoken_str(2)) + cur_page->prefunc = ns_func.add(line.gettoken_str(2),0); + break; + case 2: + ERROR_MSG("Error: custom page must have a creator function!\n"); + PRINTHELP(); + } + } +#endif//NSIS_SUPPORT_CODECALLBACKS + + SCRIPT_MSG("%sPage: %s", uninstall_mode?"Uninst":"", line.gettoken_str(1)); + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (cur_page->prefunc>=0) + SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2)); + if (cur_page->showfunc>=0 && k) + SCRIPT_MSG(" (show:%s)", line.gettoken_str(3)); + if (cur_page->leavefunc>=0) + SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4-!k)); + else if (cur_page->caption && !k) + SCRIPT_MSG(" (caption:%s)", line.gettoken_str(3)); +#endif + SCRIPT_MSG("\n"); + + page_end(); + + if (k == PAGE_INSTFILES) { + add_page(PAGE_COMPLETED); + page_end(); + } + + set_uninstall_mode(0); + } + return PS_OK; + + // extended page setting + case TOK_PAGEEX: + { + int k = line.gettoken_enum(1,"custom\0license\0components\0directory\0instfiles\0uninstConfirm\0"); + if (k < 0) { + k = line.gettoken_enum(1,"un.custom\0un.license\0un.components\0un.directory\0un.instfiles\0un.uninstConfirm\0"); + if (k < 0) PRINTHELP(); + set_uninstall_mode(1); + } + + SCRIPT_MSG("PageEx: %s\n", line.gettoken_str(1)); + + if (add_page(k) != PS_OK) + return PS_ERROR; + + cur_page->flags |= PF_PAGE_EX; + } + return PS_OK; + + case TOK_PAGEEXEND: + { + SCRIPT_MSG("PageExEnd\n"); + +#ifdef NSIS_SUPPORT_CODECALLBACKS + if (cur_page_type == PAGE_CUSTOM && !cur_page->prefunc) { + ERROR_MSG("Error: custom pages must have a creator function.\n"); + return PS_ERROR; + } +#endif + + page_end(); + + if (cur_page_type == PAGE_INSTFILES) { + add_page(PAGE_COMPLETED); + page_end(); + } + + set_uninstall_mode(0); + } + return PS_OK; + case TOK_PAGECALLBACKS: +#ifdef NSIS_SUPPORT_CODECALLBACKS + { + SCRIPT_MSG("PageCallbacks:"); + + if (cur_page_type == PAGE_CUSTOM) + { + switch (line.getnumtokens()) + { + case 4: + { + PRINTHELP(); + } + case 3: + { + if (*line.gettoken_str(2)) + { + if (strnicmp(line.gettoken_str(2), "un.", 3)) + { + if (uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + else + { + if (!uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + cur_page->leavefunc = ns_func.add(line.gettoken_str(2),0); + } + } + case 2: + { + if (*line.gettoken_str(1)) + { + if (strnicmp(line.gettoken_str(1), "un.", 3)) + { + if (uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + else + { + if (!uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + cur_page->prefunc = ns_func.add(line.gettoken_str(1),0); + } + } + } + } + else + { + switch (line.getnumtokens()) + { + case 4: + { + if (*line.gettoken_str(3)) + { + if (strnicmp(line.gettoken_str(3), "un.", 3)) + { + if (uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + else + { + if (!uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + cur_page->leavefunc = ns_func.add(line.gettoken_str(3),0); + } + } + case 3: + { + if (*line.gettoken_str(2)) + { + if (strnicmp(line.gettoken_str(2), "un.", 3)) + { + if (uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + else + { + if (!uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + cur_page->showfunc = ns_func.add(line.gettoken_str(2),0); + } + } + case 2: + { + if (*line.gettoken_str(1)) + { + if (strnicmp(line.gettoken_str(1), "un.", 3)) + { + if (uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + else + { + if (!uninstall_mode) + { + ERROR_MSG("\nError: function names must start with \"un.\" in an uninstall page.\n"); + return PS_ERROR; + } + } + cur_page->prefunc = ns_func.add(line.gettoken_str(1),0); + } + } + } + } + + int custom = cur_page_type == PAGE_CUSTOM ? 1 : 0; + + if (cur_page->prefunc>=0) + SCRIPT_MSG(" %s:%s", !custom?"pre":"creator", line.gettoken_str(1)); + if (cur_page->showfunc>=0 && !custom) + SCRIPT_MSG(" show:%s", line.gettoken_str(2)); + if (cur_page->leavefunc>=0) + SCRIPT_MSG(" leave:%s", line.gettoken_str(3-custom)); + + SCRIPT_MSG("\n"); + } + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_CODECALLBACKS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_SUPPORT_CODECALLBACKS +#else + case TOK_PAGE: + case TOK_UNINSTPAGE: + case TOK_PAGEEX: + case TOK_PAGEEXEND: + case TOK_PAGECALLBACKS: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_VISIBLE_SUPPORT + // header flags + /////////////////////////////////////////////////////////////////////////////// + case TOK_LANGSTRING: + { + char *name = line.gettoken_str(1); + LANGID lang = line.gettoken_int(2); + char *str = line.gettoken_str(3); + int ret = SetLangString(name, lang, str); + if (ret == PS_WARNING) + warning_fl("LangString \"%s\" set multiple times for %d, wasting space", name, lang); + else if (ret == PS_ERROR) { + ERROR_MSG("Error: can't set LangString \"%s\"!\n", name); + return PS_ERROR; + } + SCRIPT_MSG("LangString: \"%s\" %d \"%s\"\n", name, lang, str); + } + return PS_OK; + case TOK_LANGSTRINGUP: + SCRIPT_MSG("Error: LangStringUP is obsolete, there are no more unprocessed strings. Use LangString.\n"); + return PS_ERROR; + case TOK_LICENSELANGSTRING: + { +#ifdef NSIS_CONFIG_SILENT_SUPPORT + if (build_header.flags&(CH_FLAGS_SILENT|CH_FLAGS_SILENT_LOG)) + { + warning_fl("LicenseLangString: SilentInstall enabled, wasting space"); + } +#endif + char *name = line.gettoken_str(1); + LANGID lang = line.gettoken_int(2); + char *file = line.gettoken_str(3); + + FILE *fp; + unsigned int datalen; + fp=FOPEN(file,"rb"); + if (!fp) + { + ERROR_MSG("LicenseLangString: open failed \"%s\"\n",file); + PRINTHELP() + } + MANAGE_WITH(fp, fclose); + fseek(fp,0,SEEK_END); + datalen=ftell(fp); + if (!datalen) + { + ERROR_MSG("LicenseLangString: empty license file \"%s\"\n",file); + return PS_ERROR; + } + rewind(fp); + char *data=(char*)malloc(datalen+2); + if (!data) + { + ERROR_MSG("Internal compiler error #12345: LicenseData malloc(%d) failed.\n", datalen+2); + return PS_ERROR; + } + MANAGE_WITH(data, free); + char *ldata=data+1; + if (fread(ldata,1,datalen,fp) != datalen) + { + ERROR_MSG("LicenseLangString: can't read file.\n"); + return PS_ERROR; + } + ldata[datalen]=0; + if (!strncmp(ldata,"{\\rtf",sizeof("{\\rtf")-1)) + *data = SF_RTF; + else + *data = SF_TEXT; + + int ret = SetLangString(name, lang, data); + if (ret == PS_WARNING) + warning_fl("LicenseLangString \"%s\" set multiple times for %d, wasting space", name, lang); + else if (ret == PS_ERROR) + { + ERROR_MSG("Error: can't set LicenseLangString \"%s\"!\n", name); + return PS_ERROR; + } + + SCRIPT_MSG("LicenseLangString: \"%s\" %d \"%s\"\n", name, lang, file); + } + return PS_OK; + case TOK_NAME: + { + if (SetInnerString(NLF_NAME,line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + SetInnerString(NLF_NAME_DA,line.gettoken_str(2)); + SCRIPT_MSG("Name: \"%s\"",line.gettoken_str(1)); + if (*line.gettoken_str(2)) + SCRIPT_MSG(" \"%s\"",line.gettoken_str(2)); + SCRIPT_MSG("\n"); + } + return PS_OK; + case TOK_CAPTION: + { + if (!cur_page) + { + if (SetInnerString(NLF_CAPTION,line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + } + else + { + cur_page->caption = add_string(line.gettoken_str(1)); + } + SCRIPT_MSG("Caption: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_ICON: + SCRIPT_MSG("Icon: \"%s\"\n",line.gettoken_str(1)); + try { + free_loaded_icon(installer_icon); + installer_icon = load_icon_file(line.gettoken_str(1)); + } + catch (exception& err) { + ERROR_MSG("Error while loading icon from \"%s\": %s\n", line.gettoken_str(1), err.what()); + return PS_ERROR; + } + return PS_OK; +#ifdef NSIS_CONFIG_COMPONENTPAGE + case TOK_CHECKBITMAP: + SCRIPT_MSG("CheckBitmap: \"%s\"\n",line.gettoken_str(1)); + try { + init_res_editor(); + int err = update_bitmap(res_editor, IDB_BITMAP1, line.gettoken_str(1), 96, 16, 8); + if (err) { + switch (err) { + case -1: + ERROR_MSG("Error: can't find bitmap\n"); + break; + case -2: + ERROR_MSG("Error: invalid bitmap file - corrupted or not a bitmap\n"); + break; + case -3: + ERROR_MSG("Error: bitmap isn't 96x16 in size\n"); + break; + case -4: + ERROR_MSG("Error: bitmap has more than 8bpp\n"); + break; + } + return PS_ERROR; + } + } + catch (exception& err) { + ERROR_MSG("Error while replacing bitmap: %s\n", err.what()); + return PS_ERROR; + } + return PS_OK; +#else//NSIS_CONFIG_COMPONENTPAGE + case TOK_CHECKBITMAP: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE + case TOK_DIRTEXT: +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + { + if (!cur_page) { + if (SetInnerString(NLF_DIR_TEXT, line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + if (line.getnumtokens() > 2) + SetInnerString(NLF_DIR_SUBTEXT, line.gettoken_str(2)); + if (line.getnumtokens() > 3) + SetInnerString(NLF_BTN_BROWSE, line.gettoken_str(3)); + if (line.getnumtokens() > 4) + SetInnerString(NLF_DIR_BROWSETEXT, line.gettoken_str(4)); + } + else { + if (cur_page_type != PAGE_DIRECTORY) { + ERROR_MSG("Error: DirText can only be used inside PageEx directory.\n"); + return PS_ERROR; + } + cur_page->parms[0] = add_string(line.gettoken_str(1)); + if (line.getnumtokens() > 2) + cur_page->parms[1] = add_string(line.gettoken_str(2)); + if (line.getnumtokens() > 3) + cur_page->parms[2] = add_string(line.gettoken_str(3)); + if (line.getnumtokens() > 4) + cur_page->parms[3] = add_string(line.gettoken_str(4)); + } + SCRIPT_MSG("DirText: \"%s\" \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return PS_OK; +#else//NSIS_CONFIG_VISIBLE_SUPPORT + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_DIRVAR: + { + if (cur_page_type != PAGE_DIRECTORY && cur_page_type != PAGE_UNINSTCONFIRM) { + ERROR_MSG("Error: can't use DirVar outside of PageEx directory|uninstConfirm.\n"); + return PS_ERROR; + } + cur_page->parms[4] = GetUserVarIndex(line, 1) + 1; + if (cur_page->parms[4] <= 0) PRINTHELP(); + SCRIPT_MSG("DirVar: %s\n", line.gettoken_str(1)); + } + return PS_OK; + case TOK_DIRVERIFY: + { + if (cur_page_type != PAGE_DIRECTORY) { + ERROR_MSG("Error: can't use DirVerify outside of PageEx directory.\n"); + return PS_ERROR; + } + cur_page->flags &= ~PF_DIR_NO_BTN_DISABLE; + int k = line.gettoken_enum(1,"auto\0leave\0"); + if (k == -1) + PRINTHELP(); + if (k) + cur_page->flags |= PF_DIR_NO_BTN_DISABLE; + SCRIPT_MSG("DirVerify: %s\n", line.gettoken_str(1)); + } + return PS_OK; + case TOK_GETINSTDIRERROR: + ent.which = EW_GETFLAG; + ent.offsets[0] = GetUserVarIndex(line, 1); + ent.offsets[1] = FLAG_OFFSET(instdir_error); + return add_entry(&ent); +#ifdef NSIS_CONFIG_COMPONENTPAGE + case TOK_COMPTEXT: + { + if (!cur_page) { + if (SetInnerString(NLF_COMP_TEXT, line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + if (line.getnumtokens() > 2) + SetInnerString(NLF_COMP_SUBTEXT1, line.gettoken_str(2)); + if (line.getnumtokens() > 3) + SetInnerString(NLF_COMP_SUBTEXT2, line.gettoken_str(3)); + } + else { + if (cur_page_type != PAGE_COMPONENTS) { + ERROR_MSG("Error: ComponentText can only be used inside PageEx components.\n"); + return PS_ERROR; + } + cur_page->parms[0] = add_string(line.gettoken_str(1)); + cur_page->parms[1] = add_string(line.gettoken_str(2)); + cur_page->parms[2] = add_string(line.gettoken_str(3)); + cur_page->parms[3] = cur_page->parms[1]; + cur_page->parms[4] = cur_page->parms[2]; + } + SCRIPT_MSG("ComponentText: \"%s\" \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + } + return PS_OK; + case TOK_INSTTYPE: + { + int x; + + if (!stricmp(line.gettoken_str(1),"/NOCUSTOM")) + { + build_header.flags|=CH_FLAGS_NO_CUSTOM; + SCRIPT_MSG("InstType: disabling custom install type\n"); + } + else if (!stricmp(line.gettoken_str(1),"/COMPONENTSONLYONCUSTOM")) + { + build_header.flags|=CH_FLAGS_COMP_ONLY_ON_CUSTOM; + SCRIPT_MSG("InstType: making components viewable only on custom install type\n"); + } + else if (!strnicmp(line.gettoken_str(1),"/CUSTOMSTRING=",14)) + { + SCRIPT_MSG("InstType: setting custom text to: \"%s\"\n",line.gettoken_str(1)+14); + if (SetInnerString(NLF_COMP_CUSTOM,line.gettoken_str(1)+14) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space","InstType /CUSTOMSTRING"); + } + else if (line.gettoken_str(1)[0]=='/') + { + PRINTHELP() + } + else + { + char *itname = line.gettoken_str(1); + + if (!strnicmp(itname, "un.", 3)) { + set_uninstall_mode(1); + itname += 3; + } + + for (x = 0; x < NSIS_MAX_INST_TYPES && cur_header->install_types[x]; x ++); + if (x == NSIS_MAX_INST_TYPES) + { + ERROR_MSG("InstType: no more than %d install types allowed. %d specified\n", NSIS_MAX_INST_TYPES, NSIS_MAX_INST_TYPES + 1); + return PS_ERROR; + } + else + { + cur_header->install_types[x] = add_string(itname); + SCRIPT_MSG("InstType: %s%d=\"%s\"\n", uninstall_mode ? "(uninstall) " : "", x+1, itname); + } + + set_uninstall_mode(0); + } + } + return PS_OK; +#else//NSIS_CONFIG_COMPONENTPAGE + case TOK_COMPTEXT: + case TOK_INSTTYPE: + ERROR_MSG("Error: %s specified but NSIS_CONFIG_COMPONENTPAGE not defined\n",line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_CONFIG_LICENSEPAGE + case TOK_LICENSETEXT: + { + if (!cur_page) { + if (SetInnerString(NLF_LICENSE_TEXT, line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + SetInnerString(NLF_LICENSE_TEXT_FSRB, line.gettoken_str(1)); + SetInnerString(NLF_LICENSE_TEXT_FSCB, line.gettoken_str(1)); + if (line.getnumtokens() > 2) + SetInnerString(NLF_BTN_LICENSE, line.gettoken_str(2)); + } + else { + if (cur_page_type != PAGE_LICENSE) { + ERROR_MSG("Error: LicenseText can only be used inside PageEx license.\n"); + return PS_ERROR; + } + cur_page->parms[0] = add_string(line.gettoken_str(1)); + cur_page->next = add_string(line.gettoken_str(2)); + } + SCRIPT_MSG("LicenseText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + } + return PS_OK; + case TOK_LICENSEDATA: + { + int idx = 0; + char *file = line.gettoken_str(1); + char *data = NULL; + + if (file[0] == '$' && file[1] == '(') + { + char *cp = strdup(file+2); + MANAGE_WITH(cp, free); + char *p = strchr(cp, ')'); + if (p && p[1] == 0) { // if string is only a language str identifier + *p = 0; + idx = DefineLangString(cp, 0); + } + data = file; + } + + if (!idx) + { + unsigned int datalen; + FILE *fp=FOPEN(file,"rb"); + if (!fp) + { + ERROR_MSG("LicenseData: open failed \"%s\"\n",file); + PRINTHELP() + } + MANAGE_WITH(fp, fclose); + fseek(fp,0,SEEK_END); + datalen=ftell(fp); + if (!datalen) + { + ERROR_MSG("LicenseData: empty license file \"%s\"\n",file); + return PS_ERROR; + } + rewind(fp); + data=(char*)malloc(datalen+2); + if (!data) + { + ERROR_MSG("Internal compiler error #12345: LicenseData malloc(%d) failed.\n", datalen+2); + return PS_ERROR; + } + //MANAGE_WITH(data, free); + char *ldata=data+1; + if (fread(ldata,1,datalen,fp) != datalen) { + ERROR_MSG("LicenseData: can't read file.\n"); + free(data); // TODO: fix later (orip) + return PS_ERROR; + } + ldata[datalen]=0; + if (!strncmp(ldata,"{\\rtf",sizeof("{\\rtf")-1)) + *data = SF_RTF; + else + *data = SF_TEXT; + } + + if (!cur_page) { + if (SetInnerString(NLF_LICENSE_DATA,data) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + } + else { + if (cur_page_type != PAGE_LICENSE) { + ERROR_MSG("Error: LicenseData can only be used inside PageEx license.\n"); + return PS_ERROR; + } + + cur_page->parms[1] = add_string(data, 0); + } + + if (!idx) free(data); // TODO: fix later (orip) + + SCRIPT_MSG("LicenseData: \"%s\"\n",file); + } + return PS_OK; + case TOK_LICENSEFORCESELECTION: + { + int k=line.gettoken_enum(1,"off\0checkbox\0radiobuttons\0"); + if (k == -1) PRINTHELP() + if (k < line.getnumtokens() - 2) PRINTHELP() + + if (!cur_page) { + switch (line.getnumtokens()) { + case 4: + SetInnerString(NLF_BTN_LICENSE_DISAGREE, line.gettoken_str(3)); + case 3: + SetInnerString(NLF_BTN_LICENSE_AGREE, line.gettoken_str(2)); + break; + } + + switch (k) { + case 0: + license_res_id = IDD_LICENSE; + break; + case 1: + license_res_id = IDD_LICENSE_FSCB; + break; + case 2: + license_res_id = IDD_LICENSE_FSRB; + break; + } + } + else { + if (cur_page_type != PAGE_LICENSE) { + ERROR_MSG("Error: LicenseForceSelection can only be used inside PageEx license.\n"); + return PS_ERROR; + } + switch (line.getnumtokens()) { + case 4: + cur_page->parms[3] = add_string(line.gettoken_str(3)); + case 3: + cur_page->parms[2] = add_string(line.gettoken_str(2)); + break; + } + + cur_page->flags &= ~(PF_LICENSE_FORCE_SELECTION | PF_LICENSE_NO_FORCE_SELECTION); + + switch (k) { + case 0: + cur_page->dlg_id = IDD_LICENSE; + cur_page->flags |= PF_LICENSE_NO_FORCE_SELECTION; + break; + case 1: + cur_page->dlg_id = IDD_LICENSE_FSCB; + cur_page->flags |= PF_LICENSE_FORCE_SELECTION; + break; + case 2: + cur_page->dlg_id = IDD_LICENSE_FSRB; + cur_page->flags |= PF_LICENSE_FORCE_SELECTION; + break; + } + } + + SCRIPT_MSG("LicenseForceSelection: %s \"%s\" \"%s\"\n", line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3)); + } + return PS_OK; + case TOK_LICENSEBKCOLOR: + { + char *p = line.gettoken_str(1); + if (!strcmpi(p,"/windows")) + { + build_header.license_bg=-COLOR_WINDOW; + SCRIPT_MSG("LicenseBkColor: /windows\n"); + } + else if (!strcmpi(p,"/grey") || !strcmpi(p,"/gray")) + { + build_header.license_bg=-COLOR_BTNFACE; + SCRIPT_MSG("LicenseBkColor: /grey\n"); + } + else + { + int v=strtoul(p,&p,16); + build_header.license_bg=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16); + build_uninst.license_bg=build_header.license_bg; + SCRIPT_MSG("LicenseBkColor: %06X\n",v); + } + } + return PS_OK; +#else//!NSIS_CONFIG_LICENSEPAGE + case TOK_LICENSETEXT: + case TOK_LICENSEDATA: + case TOK_LICENSEBKCOLOR: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_LICENSEPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_LICENSEPAGE +#ifdef NSIS_CONFIG_SILENT_SUPPORT + case TOK_SILENTINST: + { + int k=line.gettoken_enum(1,"normal\0silent\0silentlog\0"); + if (k<0) PRINTHELP() +#ifndef NSIS_CONFIG_LOG + if (k == 2) + { + ERROR_MSG("SilentInstall: silentlog specified, no log support compiled in (use NSIS_CONFIG_LOG)\n"); + return PS_ERROR; + } +#endif//NSIS_CONFIG_LOG + SCRIPT_MSG("SilentInstall: %s\n",line.gettoken_str(1)); +#ifdef NSIS_CONFIG_LICENSEPAGE + if (k && HasUserDefined(NLF_LICENSE_DATA)) + { + warning_fl("SilentInstall: LicenseData already specified. wasting space"); + } + if (k) { + build_header.flags|=CH_FLAGS_SILENT; + if (k == 2) + build_header.flags|=CH_FLAGS_SILENT_LOG; + } + else { + build_header.flags&=~CH_FLAGS_SILENT; + build_header.flags&=~CH_FLAGS_SILENT_LOG; + } +#endif//NSIS_CONFIG_LICENSEPAGE + } + return PS_OK; + case TOK_SILENTUNINST: +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + { + int k=line.gettoken_enum(1,"normal\0silent\0"); + if (k<0) PRINTHELP() + if (k) + build_uninst.flags|=CH_FLAGS_SILENT; + else + build_uninst.flags&=~CH_FLAGS_SILENT; + SCRIPT_MSG("SilentUnInstall: %s\n",line.gettoken_str(1)); + } + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + case TOK_IFSILENT: + ent.which=EW_IFFLAG; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=FLAG_OFFSET(silent); + ent.offsets[3]=~0;//new value mask - keep flag + SCRIPT_MSG("IfSilent ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SETSILENT: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(silent); + int k=line.gettoken_enum(1,"normal\0silent\0"); + if (k<0) PRINTHELP() + ent.offsets[1]=add_intstring(k); + SCRIPT_MSG("SetSilent: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); +#else//!NSIS_CONFIG_SILENT_SUPPORT + case TOK_SILENTINST: + case TOK_SILENTUNINST: + case TOK_IFSILENT: + case TOK_SETSILENT: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_SILENT_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_SILENT_SUPPORT + case TOK_OUTFILE: + strncpy(build_output_filename,line.gettoken_str(1),1024-1); + SCRIPT_MSG("OutFile: \"%s\"\n",build_output_filename); + return PS_OK; + case TOK_INSTDIR: + { + char *p = line.gettoken_str(1); + if (build_header.install_directory_ptr) + { + warning_fl("%s: specified multiple times. wasting space",line.gettoken_str(0)); + } + build_header.install_directory_ptr = add_string(p); + build_header.install_directory_auto_append = 0; + char *p2 = p + strlen(p); + if (*p && *CharPrev(p, p2) != '\\') + { + // we risk hitting $\r or something like $(bla\ad) or ${bla\ad} here, but it's better + // than hitting backslashes in processed strings + while (p2 > p && *p2 != '\\') + p2 = CharPrev(p, p2); + if (*p2 == '\\') + { + build_header.install_directory_auto_append = add_string(p2 + 1); + } + } + SCRIPT_MSG("InstallDir: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_INSTALLDIRREGKEY: // InstallDirRegKey + { + if (build_header.install_reg_key_ptr) + { + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + } + int k=line.gettoken_enum(1,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(1,rootkeys[1]); + if (k == -1) PRINTHELP() + build_header.install_reg_rootkey=(int)rootkey_tab[k]; + if (!build_header.install_reg_rootkey) PRINTHELP() // SHCTX is invalid here + build_header.install_reg_key_ptr = add_string(line.gettoken_str(2),0); + if (line.gettoken_str(2)[0] == '\\') + warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0)); + build_header.install_reg_value_ptr = add_string(line.gettoken_str(3),0); + SCRIPT_MSG("InstallRegKey: \"%s\\%s\\%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + } + return PS_OK; + case TOK_CRCCHECK: + build_crcchk=line.gettoken_enum(1,"off\0on\0force\0"); + if (build_crcchk==-1) PRINTHELP() + SCRIPT_MSG("CRCCheck: %s\n",line.gettoken_str(1)); + return PS_OK; + case TOK_INSTPROGRESSFLAGS: + { + int x; + int smooth=0; + build_header.flags&=~CH_FLAGS_PROGRESS_COLORED; + for (x = 1; x < line.getnumtokens(); x ++) + { + if (!stricmp(line.gettoken_str(x),"smooth")) smooth=1; + else if (!stricmp(line.gettoken_str(x),"colored")) build_header.flags|=CH_FLAGS_PROGRESS_COLORED; + else PRINTHELP() + } + try { + init_res_editor(); + + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INSTFILES), NSIS_DEFAULT_LANG); + if (!dlg) throw runtime_error("IDD_INSTFILES doesn't exist!"); + CDialogTemplate dt(dlg,uDefCodePage); + free(dlg); + DialogItemTemplate* progress = dt.GetItem(IDC_PROGRESS); + if (!progress) { + throw runtime_error("IDC_PROGRESS doesn't exist!"); + } + + if (smooth) + progress->dwStyle |= PBS_SMOOTH; + else + progress->dwStyle &= ~PBS_SMOOTH; + + DWORD dwSize; + dlg = dt.Save(dwSize); + res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INSTFILES), NSIS_DEFAULT_LANG, dlg, dwSize); + delete [] dlg; + } + catch (exception& err) { + ERROR_MSG("Error setting smooth progress bar: %s\n", err.what()); + return PS_ERROR; + } + SCRIPT_MSG("InstProgressFlags: smooth=%d, colored=%d\n",smooth, + !!(build_header.flags&CH_FLAGS_PROGRESS_COLORED)); + } + return PS_OK; + case TOK_AUTOCLOSE: + { + int k=line.gettoken_enum(1,"false\0true\0"); + if (k == -1) PRINTHELP(); + if (k) + build_header.flags|=CH_FLAGS_AUTO_CLOSE; + else + build_header.flags&=~CH_FLAGS_AUTO_CLOSE; + SCRIPT_MSG("AutoCloseWindow: %s\n",k?"true":"false"); + } + return PS_OK; + case TOK_WINDOWICON: +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + disable_window_icon=line.gettoken_enum(1,"on\0off\0"); + if (disable_window_icon == -1) PRINTHELP(); + SCRIPT_MSG("WindowIcon: %s\n",line.gettoken_str(1)); + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif // NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_SHOWDETAILSUNINST: +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + ERROR_MSG("Error: ShowUninstDetails specified but NSIS_CONFIG_UNINSTALL_SUPPORT not defined\n"); + return PS_ERROR; +#endif + case TOK_SHOWDETAILS: + { + int k=line.gettoken_enum(1,"hide\0show\0nevershow\0"); + if (k == -1) PRINTHELP() +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (which_token == TOK_SHOWDETAILSUNINST) + { + build_uninst.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS); + if (k==1) + build_uninst.flags|=CH_FLAGS_DETAILS_SHOWDETAILS; + else if (k==2) + build_uninst.flags|=CH_FLAGS_DETAILS_NEVERSHOW; + } + else +#endif + { + build_header.flags&=~(CH_FLAGS_DETAILS_NEVERSHOW|CH_FLAGS_DETAILS_SHOWDETAILS); + if (k==1) + build_header.flags|=CH_FLAGS_DETAILS_SHOWDETAILS; + else if (k==2) + build_header.flags|=CH_FLAGS_DETAILS_NEVERSHOW; + } + SCRIPT_MSG("%s: %s\n",line.gettoken_str(0),line.gettoken_str(1)); + } + return PS_OK; + case TOK_DIRSHOW: + /*{ + int k=line.gettoken_enum(1,"show\0hide\0"); + if (k == -1) PRINTHELP(); + if (k) + build_header.flags|=CH_FLAGS_DIR_NO_SHOW; + else + build_header.flags&=~CH_FLAGS_DIR_NO_SHOW; + SCRIPT_MSG("DirShow: %s\n",k?"hide":"show"); + }*/ + ERROR_MSG("Error: DirShow doesn't currently work\n"); + return PS_ERROR; + case TOK_ROOTDIRINST: + { + int k=line.gettoken_enum(1,"true\0false\0"); + if (k == -1) PRINTHELP(); + if (k) + build_header.flags|=CH_FLAGS_NO_ROOT_DIR; + else + build_header.flags&=~CH_FLAGS_NO_ROOT_DIR; + SCRIPT_MSG("AllowRootDirInstall: %s\n",k?"false":"true"); + } + return PS_OK; + case TOK_BGFONT: +#ifndef NSIS_SUPPORT_BGBG + ERROR_MSG("Error: BGFont specified but NSIS_SUPPORT_BGBG not defined\n"); + return PS_ERROR; +#else//NSIS_SUPPORT_BGBG + if (line.getnumtokens()==1) + { + memcpy(&bg_font,&bg_default_font,sizeof(LOGFONT)); + SCRIPT_MSG("BGFont: default font\n"); + return PS_OK; + } + + LOGFONT newfont; + newfont.lfHeight=40; + newfont.lfWidth=0; + newfont.lfEscapement=0; + newfont.lfOrientation=0; + newfont.lfWeight=FW_NORMAL; + newfont.lfItalic=FALSE; + newfont.lfUnderline=FALSE; + newfont.lfStrikeOut=FALSE; + newfont.lfCharSet=DEFAULT_CHARSET; + newfont.lfOutPrecision=OUT_DEFAULT_PRECIS; + newfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; + newfont.lfQuality=DEFAULT_QUALITY; + newfont.lfPitchAndFamily=DEFAULT_PITCH; + + strncpy(newfont.lfFaceName,line.gettoken_str(1),LF_FACESIZE); + + SCRIPT_MSG("BGFont: \"%s\"",line.gettoken_str(1)); + { + bool height=false; + bool weight=false; + for (int i = 2; i < line.getnumtokens(); i++) { + char *tok=line.gettoken_str(i); + if (tok[0]=='/') { + if (!strcmpi(tok,"/ITALIC")) { + SCRIPT_MSG(" /ITALIC"); + newfont.lfItalic=TRUE; + } + else if (!strcmpi(tok,"/UNDERLINE")) { + SCRIPT_MSG(" /UNDERLINE"); + newfont.lfUnderline=TRUE; + } + else if (!strcmpi(tok,"/STRIKE")) { + SCRIPT_MSG(" /STRIKE"); + newfont.lfStrikeOut=TRUE; + } + else { + SCRIPT_MSG("\n"); + PRINTHELP(); + } + } + else { + if (!height) { + SCRIPT_MSG(" height=%s",tok); + newfont.lfHeight=line.gettoken_int(i); + height=true; + } + else if (!weight) { + SCRIPT_MSG(" weight=%s",tok); + newfont.lfWeight=line.gettoken_int(i); + weight=true; + } + else { + SCRIPT_MSG("\n"); + PRINTHELP(); + } + } + } + } + SCRIPT_MSG("\n"); + memcpy(&bg_font, &newfont, sizeof(LOGFONT)); + return PS_OK; +#endif//NSIS_SUPPORT_BGBG + case TOK_BGGRADIENT: +#ifndef NSIS_SUPPORT_BGBG + ERROR_MSG("Error: BGGradient specified but NSIS_SUPPORT_BGBG not defined\n"); + return PS_ERROR; +#else//NSIS_SUPPORT_BGBG + if (line.getnumtokens()==1) + { + SCRIPT_MSG("BGGradient: default colors\n"); + build_header.bg_color1=0; + build_header.bg_color2=RGB(0,0,255); + } + else if (!stricmp(line.gettoken_str(1),"off")) + { + build_header.bg_color1=build_header.bg_color2=build_header.bg_textcolor=-1; + SCRIPT_MSG("BGGradient: off\n"); + if (line.getnumtokens()>2) PRINTHELP() + } + else + { + char *p = line.gettoken_str(1); + int v1,v2,v3=-1; + v1=strtoul(p,&p,16); + build_header.bg_color1=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16); + p=line.gettoken_str(2); + v2=strtoul(p,&p,16); + build_header.bg_color2=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16); + + p=line.gettoken_str(3); + if (*p) + { + if (!stricmp(p,"notext")) build_header.bg_textcolor=-1; + else + { + v3=strtoul(p,&p,16); + build_header.bg_textcolor=((v3&0xff)<<16)|(v3&0xff00)|((v3&0xff0000)>>16); + } + } + + SCRIPT_MSG("BGGradient: 0x%06X->0x%06X (text=0x%06X)\n",v1,v2,v3); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.bg_color1=build_header.bg_color1; + build_uninst.bg_color2=build_header.bg_color2; + build_uninst.bg_textcolor=build_header.bg_textcolor; +#endif//NSIS_CONFIG_UNINSTALL_SUPPORT +#endif//NSIS_SUPPORT_BGBG + return PS_OK; +#ifdef NSIS_CONFIG_VISIBLE_SUPPORT + case TOK_INSTCOLORS: + { + char *p = line.gettoken_str(1); + if (p[0]=='/') + { + if (stricmp(p,"/windows") || line.getnumtokens()!=2) PRINTHELP() + build_header.lb_fg=build_header.lb_bg=-1; + SCRIPT_MSG("InstallColors: windows default colors\n"); + } + else + { + int v1,v2; + if (line.getnumtokens()!=3) PRINTHELP() + v1=strtoul(p,&p,16); + build_header.lb_fg=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16); + p=line.gettoken_str(2); + v2=strtoul(p,&p,16); + build_header.lb_bg=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16); + SCRIPT_MSG("InstallColors: fg=%06X bg=%06X\n",v1,v2); + } + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + build_uninst.lb_fg=build_header.lb_fg; + build_uninst.lb_bg=build_header.lb_bg; +#endif + } + return PS_OK; + case TOK_XPSTYLE: + { + int k=line.gettoken_enum(1,"on\0off\0"); + if (k == -1) PRINTHELP() + SCRIPT_MSG("XPStyle: %s\n", line.gettoken_str(1)); + if (!k) + manifest_comctl = manifest::comctl_xp; + else + manifest_comctl = manifest::comctl_old; + } + return PS_OK; + case TOK_CHANGEUI: + try { + DWORD dwSize; + int k=line.gettoken_enum(1, "all\0IDD_LICENSE\0IDD_DIR\0IDD_SELCOM\0IDD_INST\0IDD_INSTFILES\0IDD_UNINST\0IDD_VERIFY\0IDD_LICENSE_FSRB\0IDD_LICENSE_FSCB\0"); + if (k<0) PRINTHELP(); + + FILE *fui = FOPEN(line.gettoken_str(2), "rb"); + if (!fui) { + ERROR_MSG("Error: Can't open \"%s\"!\n", line.gettoken_str(2)); + return PS_ERROR; + } + MANAGE_WITH(fui, fclose); + + fseek(fui, 0, SEEK_END); + unsigned int len = ftell(fui); + fseek(fui, 0, SEEK_SET); + LPBYTE ui = (LPBYTE) malloc(len); + if (!ui) { + ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n", len); + extern void quit(); quit(); + } + MANAGE_WITH(ui, free); + if (fread(ui, 1, len, fui) != len) { + ERROR_MSG("Error: Can't read \"%s\"!\n", line.gettoken_str(2)); + return PS_ERROR; + } + + CResourceEditor *uire = new CResourceEditor(ui, len); + + init_res_editor(); + + // Search for required items + #define GET(x) dlg = uire->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(x), 0); if (!dlg) return PS_ERROR; CDialogTemplate UIDlg(dlg, uDefCodePage); + #define SEARCH(x) if (!UIDlg.GetItem(x)) {ERROR_MSG("Error: Can't find %s (%u) in the custom UI!\n", #x, x);delete [] dlg;delete uire;return PS_ERROR;} + #define SAVE(x) dwSize = UIDlg.GetSize(); res_editor->UpdateResourceA(RT_DIALOG, x, NSIS_DEFAULT_LANG, dlg, dwSize); delete [] dlg; + + LPBYTE dlg = NULL; + + if (k == 0 || k == 1) { + GET(IDD_LICENSE); + SEARCH(IDC_EDIT1); + SAVE(IDD_LICENSE); + } + + if (k == 0 || k == 2) { + GET(IDD_DIR); + SEARCH(IDC_DIR); + SEARCH(IDC_BROWSE); +#ifdef NSIS_CONFIG_LOG + SEARCH(IDC_CHECK1); +#endif + SAVE(IDD_DIR); + } + + if (k == 0 || k == 3) { + GET(IDD_SELCOM); + SEARCH(IDC_TREE1); + SEARCH(IDC_COMBO1); + SAVE(IDD_SELCOM); + } + + if (k == 0 || k == 4) { + GET(IDD_INST); + SEARCH(IDC_BACK); + SEARCH(IDC_CHILDRECT); + SEARCH(IDC_VERSTR); + SEARCH(IDOK); + SEARCH(IDCANCEL); + + // Search for bitmap holder (default for SetBrandingImage) + branding_image_found = false; + DialogItemTemplate* dlgItem = 0; + for (int i = 0; (dlgItem = UIDlg.GetItemByIdx(i)); i++) { + bool check = false; + + if (IS_INTRESOURCE(dlgItem->szClass)) { + if (dlgItem->szClass == MAKEINTRESOURCEW(0x0082)) { + check = true; + } + } else { + char *szClass = winchar_toansi(dlgItem->szClass); + check = strcmp(szClass, "Static") == 0; + delete [] szClass; + } + + if (check) { + if ((dlgItem->dwStyle & SS_BITMAP) == SS_BITMAP) { + branding_image_found = true; + branding_image_id = dlgItem->wId; + break; + } + } + } + + SAVE(IDD_INST); + } + + if (k == 0 || k == 5) { + GET(IDD_INSTFILES); + SEARCH(IDC_LIST1); + SEARCH(IDC_PROGRESS); + SEARCH(IDC_SHOWDETAILS); + SAVE(IDD_INSTFILES); + } + + if (k == 0 || k == 6) { + GET(IDD_UNINST); + SEARCH(IDC_EDIT1); + SAVE(IDD_UNINST); + } + + if (k == 0 || k == 7) { + GET(IDD_VERIFY); + SEARCH(IDC_STR); + SAVE(IDD_VERIFY); + } + + if (k == 0 || k == 8) { + GET(IDD_LICENSE_FSRB); + SEARCH(IDC_EDIT1); + SEARCH(IDC_LICENSEAGREE); + SEARCH(IDC_LICENSEDISAGREE); + SAVE(IDD_LICENSE_FSRB); + } + + if (k == 0 || k == 9) { + GET(IDD_LICENSE_FSCB); + SEARCH(IDC_EDIT1); + SEARCH(IDC_LICENSEAGREE); + SAVE(IDD_LICENSE_FSCB); + } + + delete uire; + + SCRIPT_MSG("ChangeUI: %s %s%s\n", line.gettoken_str(1), line.gettoken_str(2), branding_image_found?" (branding image holder found)":""); + } + catch (exception& err) { + ERROR_MSG("Error while changing UI: %s\n", err.what()); + return PS_ERROR; + } + return PS_OK; + case TOK_ADDBRANDINGIMAGE: +#ifdef _WIN32 + try { + int k=line.gettoken_enum(1,"top\0left\0bottom\0right\0"); + int wh=line.gettoken_int(2); + if (k == -1) PRINTHELP(); + int padding = 2; + if (line.getnumtokens() == 4) + padding = line.gettoken_int(3); + + init_res_editor(); + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG); + + CDialogTemplate dt(dlg, uDefCodePage); + + res_editor->FreeResource(dlg); + + DialogItemTemplate brandingCtl = {0,}; + + brandingCtl.dwStyle = SS_BITMAP | WS_CHILD | WS_VISIBLE; + brandingCtl.sX = padding; + brandingCtl.sY = padding; + brandingCtl.szClass = MAKEINTRESOURCEW(0x0082); + brandingCtl.szTitle = NULL; + brandingCtl.wId = IDC_BRANDIMAGE; + + brandingCtl.sHeight = wh; + brandingCtl.sWidth = wh; + dt.PixelsToDlgUnits(brandingCtl.sWidth, brandingCtl.sHeight); + if (k%2) { + // left (1) / right (3) + + if (k & 2) // right + brandingCtl.sX += dt.GetWidth(); + else // left + dt.MoveAll(brandingCtl.sWidth + (padding * 2), 0); + + dt.Resize(brandingCtl.sWidth + (padding * 2), 0); + + brandingCtl.sHeight = dt.GetHeight() - (padding * 2); + } + else { + // top (0) / bottom (2) + + if (k & 2) // bottom + brandingCtl.sY += dt.GetHeight(); + else // top + dt.MoveAll(0, brandingCtl.sHeight + (padding * 2)); + + dt.Resize(0, brandingCtl.sHeight + (padding * 2)); + + brandingCtl.sWidth = dt.GetWidth() - (padding * 2); + } + + dt.AddItem(brandingCtl); + + DWORD dwDlgSize; + dlg = dt.Save(dwDlgSize); + + res_editor->UpdateResourceA(RT_DIALOG, IDD_INST, NSIS_DEFAULT_LANG, dlg, dwDlgSize); + + delete [] dlg; + + dt.DlgUnitsToPixels(brandingCtl.sWidth, brandingCtl.sHeight); + SCRIPT_MSG("AddBrandingImage: %s %ux%u\n", line.gettoken_str(1), brandingCtl.sWidth, brandingCtl.sHeight); + + branding_image_found = true; + branding_image_id = IDC_BRANDIMAGE; + } + catch (exception& err) { + ERROR_MSG("Error while adding image branding support: %s\n", err.what()); + return PS_ERROR; + } + return PS_OK; +#else + ERROR_MSG("Error: AddBrandingImage is disabled for non Win32 platforms.\n"); + return PS_ERROR; +#endif + case TOK_SETFONT: + { + if (!strnicmp(line.gettoken_str(1), "/LANG=", 6)) + { + LANGID lang_id = atoi(line.gettoken_str(1) + 6); + LanguageTable *table = GetLangTable(lang_id); + table->nlf.m_szFont = (char*)malloc(strlen(line.gettoken_str(2))+1); + strcpy(table->nlf.m_szFont, line.gettoken_str(2)); + table->nlf.m_iFontSize = line.gettoken_int(3); + + SCRIPT_MSG("SetFont: lang=%d \"%s\" %s\n", lang_id, line.gettoken_str(2), line.gettoken_str(3)); + } + else + { + strncpy(build_font, line.gettoken_str(1), sizeof(build_font)); + build_font_size = line.gettoken_int(2); + + SCRIPT_MSG("SetFont: \"%s\" %s\n", line.gettoken_str(1), line.gettoken_str(2)); + } + } + return PS_OK; +#else + case TOK_INSTCOLORS: + case TOK_XPSTYLE: + case TOK_CHANGEUI: + case TOK_ADDBRANDINGIMAGE: + case TOK_SETFONT: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_VISIBLE_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif// NSIS_CONFIG_VISIBLE_SUPPORT + + case TOK_REQEXECLEVEL: + { + int k=line.gettoken_enum(1,"none\0user\0highest\0admin\0"); + switch (k) + { + case 0: + manifest_exec_level = manifest::exec_level_none; + break; + case 1: + manifest_exec_level = manifest::exec_level_user; + break; + case 2: + manifest_exec_level = manifest::exec_level_highest; + break; + case 3: + manifest_exec_level = manifest::exec_level_admin; + break; + default: + PRINTHELP(); + } + } + return PS_OK; + + // Ability to change compression methods from within the script + case TOK_SETCOMPRESSOR: +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + { + if (build_compressor_set) { + ERROR_MSG("Error: can't change compressor after data already got compressed or header already changed!\n"); + return PS_ERROR; + } + + if (build_compressor_final) + { + warning_fl("SetCompressor ignored due to previous call with the /FINAL switch"); + return PS_OK; + } + + int a = 1; + + build_compress_whole = false; + + while (line.gettoken_str(a)[0] == '/') + { + if (!strcmpi(line.gettoken_str(a),"/FINAL")) + { + build_compressor_final = true; + a++; + } + else if (!strcmpi(line.gettoken_str(a),"/SOLID")) + { + build_compress_whole = true; + a++; + } + else PRINTHELP(); + } + + if (a != line.getnumtokens() - 1) + { + ERROR_MSG("%s expects %d parameters, got %d.\n", line.gettoken_str(0), a + 1, line.getnumtokens()); + PRINTHELP(); + } + + int k=line.gettoken_enum(a, "zlib\0bzip2\0lzma\0"); + switch (k) { + case 0: + compressor = &zlib_compressor; + break; + + case 1: + compressor = &bzip2_compressor; + break; + + case 2: + compressor = &lzma_compressor; + break; + + default: + PRINTHELP(); + } + + string compressor_name = line.gettoken_str(a); + compressor_name = lowercase(compressor_name); + + if (set_compressor(compressor_name, build_compress_whole) != PS_OK) + { + SCRIPT_MSG("SetCompressor: error loading stub for \"%s\" compressor.\n", compressor_name.c_str()); + return PS_ERROR; + } + + SCRIPT_MSG("SetCompressor: %s%s%s\n", build_compressor_final ? "/FINAL " : "", build_compress_whole ? "/SOLID " : "", line.gettoken_str(a)); + } + return PS_OK; +#else//NSIS_CONFIG_COMPRESSION_SUPPORT + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + case TOK_LOADNLF: + { + SCRIPT_MSG("LoadLanguageFile: %s\n", line.gettoken_str(1)); + + LanguageTable *table = LoadLangFile(line.gettoken_str(1)); + + if (!table) + return PS_ERROR; + + if (!defcodepage_set) + { + uDefCodePage = table->nlf.m_uCodePage; + defcodepage_set = true; + } + + last_used_lang = table->lang_id; + // define LANG_LangName as "####" (lang id) + // for example ${LANG_ENGLISH} = 1033 + char lang_id[16]; + char lang_cp[16]; + char lang_name[1024]; + wsprintf(lang_name, "LANG_%s", table->nlf.m_szName); + wsprintf(lang_id, "%u", table->lang_id); + wsprintf(lang_cp, "%u", table->nlf.m_uCodePage); + definedlist.add(lang_name, lang_id); + wsprintf(lang_name, "LANG_%s_CP", table->nlf.m_szName); + definedlist.add(lang_name, lang_cp); + } + return PS_OK; + + // preprocessor-ish (ifdef/ifndef/else/endif are handled one step out from here) + /////////////////////////////////////////////////////////////////////////////// + case TOK_P_DEFINE: + { + char *define=line.gettoken_str(1); + char *value; + char datebuf[256]; + char mathbuf[256]; + + if (!stricmp(define,"/date") || !stricmp(define,"/utcdate")) { + if (line.getnumtokens()!=4) PRINTHELP() + + char *date_type = define; + + define=line.gettoken_str(2); + value=line.gettoken_str(3); + + time_t rawtime; + time(&rawtime); + + if (!stricmp(date_type,"/utcdate")) + rawtime = mktime(gmtime(&rawtime)); + + datebuf[0]=0; + size_t s=strftime(datebuf,sizeof(datebuf),value,localtime(&rawtime)); + + if (s == 0) + datebuf[0]=0; + else + datebuf[max(s,sizeof(datebuf)-1)]=0; + + value=datebuf; + + } else if (!stricmp(define,"/math")) { + + int value1; + int value2; + char *mathop; + + if (line.getnumtokens()!=6) PRINTHELP() + + define = line.gettoken_str(2); + value1 = line.gettoken_int(3); + mathop = line.gettoken_str(4); + value2 = line.gettoken_int(5); + value = mathbuf; + + if (!strcmp(mathop,"+")) { + sprintf(value,"%d",value1+value2); + } else if (!strcmp(mathop,"-")) { + sprintf(value,"%d",value1-value2); + } else if (!strcmp(mathop,"*")) { + sprintf(value,"%d",value1*value2); + } else if (!strcmp(mathop,"&")) { + sprintf(value,"%d",value1&value2); + } else if (!strcmp(mathop,"|")) { + sprintf(value,"%d",value1|value2); + } else if (!strcmp(mathop,"^")) { + sprintf(value,"%d",value1^value2); + } else if (!strcmp(mathop,"/")) { + if (value2==0) { + ERROR_MSG("!define /math: division by zero! (\"%i / %i\")\n",value1,value2); + return PS_ERROR; + } + sprintf(value,"%d",value1/value2); + } else if (!strcmp(mathop,"%")) { + if (value2==0) { + ERROR_MSG("!define /math: division by zero! (\"%i %% %i\")\n",value1,value2); + return PS_ERROR; + } + sprintf(value,"%d",value1%value2); + } else PRINTHELP() + + } else { + if (line.getnumtokens()==4) PRINTHELP() + + value=line.gettoken_str(2); + } + + if (definedlist.add(define,value)) + { + ERROR_MSG("!define: \"%s\" already defined!\n",define); + return PS_ERROR; + } + SCRIPT_MSG("!define: \"%s\"=\"%s\"\n",define,value); + } + return PS_OK; + case TOK_P_UNDEF: + if (definedlist.del(line.gettoken_str(1))) + { + ERROR_MSG("!undef: \"%s\" not defined!\n",line.gettoken_str(1)); + return PS_ERROR; + } + SCRIPT_MSG("!undef: \"%s\"\n",line.gettoken_str(1)); + return PS_OK; + case TOK_P_PACKEXEHEADER: + strncpy(build_packname,line.gettoken_str(1),sizeof(build_packname)-1); + strncpy(build_packcmd,line.gettoken_str(2),sizeof(build_packcmd)-1); + SCRIPT_MSG("!packhdr: filename=\"%s\", command=\"%s\"\n", + build_packname, build_packcmd); + return PS_OK; + case TOK_P_SYSTEMEXEC: + { + char *exec=line.gettoken_str(1); + int comp=line.gettoken_enum(2,"<\0>\0<>\0=\0ignore\0"); + if (line.getnumtokens() == 2) comp = 4; + if (comp == -1 && line.getnumtokens() == 3) comp=4; + if (comp == -1) PRINTHELP() + int success=0; + int cmpv=line.gettoken_int(3,&success); + if (!success && comp != 4) PRINTHELP() + SCRIPT_MSG("!system: \"%s\"\n",exec); +#ifdef _WIN32 + int ret=sane_system(exec); +#else + char *execfixed = my_convert(exec); + int ret=system(execfixed); + my_convert_free(execfixed); +#endif + if (comp == 0 && ret < cmpv); + else if (comp == 1 && ret > cmpv); + else if (comp == 2 && ret != cmpv); + else if (comp == 3 && ret == cmpv); + else if (comp == 4); + else + { + ERROR_MSG("!system: returned %d, aborting\n",ret); + return PS_ERROR; + } + SCRIPT_MSG("!system: returned %d\n",ret); + } + return PS_OK; + case TOK_P_EXECUTE: + { + char *exec=line.gettoken_str(1); +#ifdef _WIN32 + PROCESS_INFORMATION pi; + STARTUPINFO si={sizeof(STARTUPINFO),}; + if (CreateProcess(NULL,exec,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) + { + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } +#else + char *execfixed = my_convert(exec); + system(execfixed); + my_convert_free(execfixed); +#endif + SCRIPT_MSG("!execute: \"%s\"\n",exec); + } + case TOK_P_ADDINCLUDEDIR: +#ifdef _WIN32 + include_dirs.add(line.gettoken_str(1),0); +#else + { + char *f = line.gettoken_str(1); + char *fc = my_convert(f); + include_dirs.add(fc,0); + my_convert_free(fc); + } +#endif + return PS_OK; + case TOK_P_INCLUDE: + { + bool required = true; + + char *f = line.gettoken_str(1); + + if(!stricmp(f,"/nonfatal")) { + if (line.getnumtokens()!=3) + PRINTHELP(); + + f = line.gettoken_str(2); + required = false; + } else if (line.getnumtokens()!=2) { + PRINTHELP(); + } + +#ifdef _WIN32 + char *fc = f; +#else + char *fc = my_convert(f); +#endif + int included = 0; + + string dir = get_dir_name(fc); + string spec = get_file_name(fc); + string basedir = dir + PLATFORM_PATH_SEPARATOR_STR; + if (dir == spec) { + // no path, just file name + dir = "."; + basedir = ""; + } + +#ifndef _WIN32 + my_convert_free(fc); +#endif + + // search working directory + boost::scoped_ptr<dir_reader> dr( new_dir_reader() ); + dr->read(dir); + + for (dir_reader::iterator files_itr = dr->files().begin(); + files_itr != dr->files().end(); + files_itr++) + { + if (!dir_reader::matches(*files_itr, spec)) + continue; + + string incfile = basedir + *files_itr; + + if (includeScript((char *) incfile.c_str()) != PS_OK) { + return PS_ERROR; + } + + included++; + } + + if (included) + return PS_OK; + + // search include dirs + char *incdir = include_dirs.get(); + int incdirs = include_dirs.getnum(); + + for (int i = 0; i < incdirs; i++, incdir += strlen(incdir) + 1) { + string curincdir = string(incdir) + PLATFORM_PATH_SEPARATOR_STR + dir; + + boost::scoped_ptr<dir_reader> dr( new_dir_reader() ); + dr->read(curincdir); + + for (dir_reader::iterator incdir_itr = dr->files().begin(); + incdir_itr != dr->files().end(); + incdir_itr++) + { + if (!dir_reader::matches(*incdir_itr, spec)) + continue; + + string incfile = string(incdir) + PLATFORM_PATH_SEPARATOR_STR + basedir + *incdir_itr; + + if (includeScript((char *) incfile.c_str()) != PS_OK) { + return PS_ERROR; + } + + included++; + } + + if (included) + return PS_OK; + + } + + // nothing found + if (!included) + { + if(required) { + ERROR_MSG("!include: could not find: \"%s\"\n",f); + return PS_ERROR; + } else { + warning_fl("!include: could not find: \"%s\"",f); + } + } + } + return PS_OK; + case TOK_P_CD: + if (!line.gettoken_str(1)[0] || chdir(line.gettoken_str(1))) + { + ERROR_MSG("!cd: error changing to: \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } + return PS_OK; + case TOK_P_ERROR: + ERROR_MSG("!error: %s\n",line.gettoken_str(1)); + return PS_ERROR; + case TOK_P_WARNING: + warning_fl("!warning: %s",line.gettoken_str(1)); + return PS_OK; + case TOK_P_ECHO: + SCRIPT_MSG("%s (%s:%d)\n", line.gettoken_str(1),curfilename,linecnt); + return PS_OK; + + case TOK_P_VERBOSE: + { + extern int g_display_errors; + int k=line.gettoken_enum(1,"push\0pop\0"); + int v; + if (k < 0) + // just set + v=line.gettoken_int(1); + else + { + if (k) + { + // pop + int l=verbose_stack.getlen(); + if (l) + { + v=((int*)verbose_stack.get())[(l/sizeof(int))-1]; + verbose_stack.resize(l-sizeof(int)); + } + else + return PS_OK; + } + else + { + // push + v=0; + if (display_errors) + { + v++; + if (display_warnings) + { + v++; + if (display_info) + { + v++; + if (display_script) + { + v++; + } + } + } + } + verbose_stack.add(&v,sizeof(int)); + return PS_OK; + } + } + display_script=v>3; + display_info=v>2; + display_warnings=v>1; + display_errors=v>0; + g_display_errors=display_errors; + } + return PS_OK; + + case TOK_UNINSTALLEXENAME: PRINTHELP() + + +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + case TOK_UNINSTCAPTION: + { + if (SetInnerString(NLF_UCAPTION,line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + SCRIPT_MSG("UninstCaption: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_UNINSTICON: + SCRIPT_MSG("UninstallIcon: \"%s\"\n",line.gettoken_str(1)); + try { + free_loaded_icon(uninstaller_icon); + uninstaller_icon = load_icon_file(line.gettoken_str(1)); + } + catch (exception& err) { + ERROR_MSG("Error while loading icon from \"%s\": %s\n", line.gettoken_str(1), err.what()); + return PS_ERROR; + } + return PS_OK; + case TOK_UNINSTTEXT: + { + if (!cur_page) { + if (SetInnerString(NLF_UNINST_TEXT, line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + SetInnerString(NLF_UNINST_SUBTEXT, line.gettoken_str(2)); + } + else { + if (cur_page_type != PAGE_UNINSTCONFIRM) { + ERROR_MSG("Error: UninstallText can only be used inside PageEx uninstConfirm.\n"); + return PS_ERROR; + } + cur_page->parms[0] = add_string(line.gettoken_str(1)); + cur_page->parms[1] = add_string(line.gettoken_str(2)); + } + SCRIPT_MSG("UninstallText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + } + return PS_OK; + case TOK_UNINSTSUBCAPTION: + { + int s; + int w=line.gettoken_int(1,&s); + if (!s || w < 0 || w > 2) PRINTHELP() + SetInnerString(NLF_USUBCAPTION_CONFIRM+w,line.gettoken_str(2)); + SCRIPT_MSG("UninstSubCaption: page:%d, text=%s\n",w,line.gettoken_str(2)); + } + return PS_OK; + case TOK_WRITEUNINSTALLER: + { + if (uninstall_mode) + { + ERROR_MSG("WriteUninstaller only valid from install, not from uninstall.\n"); + PRINTHELP() + } + uninstaller_writes_used++; + ent.which=EW_WRITEUNINSTALLER; + ent.offsets[0]=add_string(line.gettoken_str(1)); + string full = string("$INSTDIR\\") + string(line.gettoken_str(1)); + ent.offsets[3]=add_string(full.c_str()); + // ent.offsets[1] and ent.offsets[2] are set in CEXEBuild::uninstall_generate() + if (!ent.offsets[0]) PRINTHELP() + SCRIPT_MSG("WriteUninstaller: \"%s\"\n",line.gettoken_str(1)); + + DefineInnerLangString(NLF_ERR_CREATING); + DefineInnerLangString(NLF_CREATED_UNINST); + } + return add_entry(&ent); +#else//!NSIS_CONFIG_UNINSTALL_SUPPORT + case TOK_WRITEUNINSTALLER: + case TOK_UNINSTCAPTION: + case TOK_UNINSTICON: + case TOK_UNINSTTEXT: + case TOK_UNINSTSUBCAPTION: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + + + + // section/function shit + /////////////////////////////////////////////////////////////////////////////// + + case TOK_SECTION: + { + int a=1,unselected = 0; + if (!strcmpi(line.gettoken_str(1),"/o")) + { + unselected = 1; + a++; + } + else if (line.getnumtokens() > 3) + PRINTHELP(); + SCRIPT_MSG("Section: \"%s\"",line.gettoken_str(a)); + if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1)); + SCRIPT_MSG("\n"); +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!stricmp(line.gettoken_str(a),"uninstall")) + { + ERROR_MSG("Error: Uninstall section declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n"); + return PS_ERROR; + } +#endif + + int ret; + + if (line.gettoken_str(a)[0]=='-') + { + if (!strnicmp(line.gettoken_str(a)+1,"un.",3)) + ret=add_section("un.",line.gettoken_str(a+1)); + else + ret=add_section("",line.gettoken_str(a+1)); + } + else ret=add_section(line.gettoken_str(a),line.gettoken_str(a+1)); + if (ret != PS_OK) return ret; + + if (unselected) + build_cursection->flags &= ~SF_SELECTED; + + return PS_OK; + } + case TOK_SECTIONEND: + SCRIPT_MSG("SectionEnd\n"); + return section_end(); + case TOK_SECTIONIN: + { + SCRIPT_MSG("SectionIn: "); + int wt; + for (wt = 1; wt < line.getnumtokens(); wt ++) + { + char *p=line.gettoken_str(wt); + if (!stricmp(p, "RO")) + { + if (section_add_flags(SF_RO) != PS_OK) return PS_ERROR; + SCRIPT_MSG("[RO] "); + } + else + { + int x=atoi(p)-1; + if (x >= 0 && x < NSIS_MAX_INST_TYPES) + { + if (section_add_install_type(1<<x) != PS_OK) return PS_ERROR; + SCRIPT_MSG("[%d] ",x); + } + else if (x < 0) + { + PRINTHELP() + } + else + { + ERROR_MSG("Error: SectionIn section %d out of range 1-%d\n",x+1,NSIS_MAX_INST_TYPES); + return PS_ERROR; + } + p++; + } + } + SCRIPT_MSG("\n"); + } + return PS_OK; + case TOK_SECTIONGROUPEND: + case TOK_SUBSECTIONEND: + case TOK_SECTIONGROUP: + case TOK_SUBSECTION: + { + char buf[1024]; + int a=1,ex = 0; + if (!strcmpi(line.gettoken_str(1),"/e")) + { + ex = 1; + a++; + } + wsprintf(buf,"-%s",line.gettoken_str(a)); + if (which_token == TOK_SECTIONGROUP || which_token == TOK_SUBSECTION) + { + char *s = line.gettoken_str(a); + if (!s[0] || (!strcmpi(s, "un.") && !s[3])) + PRINTHELP(); + } + + SCRIPT_MSG("%s %s",line.gettoken_str(0),line.gettoken_str(a)); + if (line.gettoken_str(a+1)[0]) SCRIPT_MSG(" ->(%s)",line.gettoken_str(a+1)); + SCRIPT_MSG("\n"); + return add_section(buf,line.gettoken_str(a+1),ex); + } + case TOK_FUNCTION: + if (!line.gettoken_str(1)[0]) PRINTHELP() + if (line.gettoken_str(1)[0]==':' || line.gettoken_str(1)[0]=='/') + { + ERROR_MSG("Function: function name cannot begin with : or /.\n"); + PRINTHELP() + } + SCRIPT_MSG("Function: \"%s\"\n",line.gettoken_str(1)); +#ifndef NSIS_CONFIG_UNINSTALL_SUPPORT + if (!strnicmp(line.gettoken_str(1),"un.",3)) + { + ERROR_MSG("Error: Uninstall function declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n"); + return PS_ERROR; + } +#endif + return add_function(line.gettoken_str(1)); + case TOK_FUNCTIONEND: + SCRIPT_MSG("FunctionEnd\n"); + return function_end(); + + // flag setters + /////////////////////////////////////////////////////////////////////////////// + + // BEGIN - Added by ramon 23 May 2003 + case TOK_ALLOWSKIPFILES: + build_allowskipfiles=line.gettoken_enum(1,"off\0on\0"); + if (build_allowskipfiles==-1) PRINTHELP() + SCRIPT_MSG("AllowSkipFiles: %s\n",line.gettoken_str(1)); + return PS_OK; + // END - Added by ramon 23 May 2003 + case TOK_SETDATESAVE: + build_datesave=line.gettoken_enum(1,"off\0on\0"); + if (build_datesave==-1) PRINTHELP() + SCRIPT_MSG("SetDateSave: %s\n",line.gettoken_str(1)); + return PS_OK; + case TOK_SETOVERWRITE: + { + int k=line.gettoken_enum(1,"on\0off\0try\0ifnewer\0ifdiff\0lastused\0"); + if (k==-1) PRINTHELP() + if (k==5) + { + k=build_overwrite; + build_overwrite=build_last_overwrite; + build_last_overwrite=k; + } + else + { + build_last_overwrite=build_overwrite; + build_overwrite=k; + } + SCRIPT_MSG("SetOverwrite: %s\n",line.gettoken_str(1)); + } + return PS_OK; +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + case TOK_SETPLUGINUNLOAD: + build_plugin_unload=line.gettoken_enum(1,"manual\0alwaysoff\0"); + if (build_plugin_unload==-1) PRINTHELP() + SCRIPT_MSG("SetPluginUnload: %s\n",line.gettoken_str(1)); + return PS_OK; +#endif //NSIS_CONFIG_PLUGIN_SUPPORT + case TOK_SETCOMPRESS: + build_compress=line.gettoken_enum(1,"off\0auto\0force\0"); + if (build_compress==-1) PRINTHELP() + if (build_compress==0 && build_compress_whole) + { + warning_fl("'SetCompress off' encountered, and in whole compression mode. Effectively ignored."); + } + SCRIPT_MSG("SetCompress: %s\n",line.gettoken_str(1)); + return PS_OK; + case TOK_DBOPTIMIZE: + build_optimize_datablock=line.gettoken_enum(1,"off\0on\0"); + if (build_optimize_datablock==-1) PRINTHELP() + SCRIPT_MSG("SetDatablockOptimize: %s\n",line.gettoken_str(1)); + return PS_OK; + case TOK_FILEBUFSIZE: + build_filebuflen=line.gettoken_int(1); + build_filebuflen<<=20; + if (build_filebuflen<=0) + { + ERROR_MSG("Error: FileBufSize: invalid buffer size -- %d\n",build_filebuflen); + return PS_ERROR; + } + SCRIPT_MSG("FileBufSize: %smb (%d bytes)\n",line.gettoken_str(1),build_filebuflen); + return PS_OK; +#ifdef NSIS_CONFIG_COMPRESSION_SUPPORT + case TOK_SETCOMPRESSIONLEVEL: + { + if (compressor == &lzma_compressor) + warning_fl("SetCompressionLevel: compressor is set to LZMA. Effectively ignored."); + if (build_compressor_set && build_compress_whole) + warning_fl("SetCompressionLevel: data already compressed in compress whole mode. Effectively ignored."); + + int s; + build_compress_level=line.gettoken_int(1,&s); + if (!s || build_compress_level < 0 || build_compress_level > 9) PRINTHELP(); + SCRIPT_MSG("SetCompressionLevel: %u\n", build_compress_level); + } + return PS_OK; + case TOK_SETCOMPRESSORDICTSIZE: + { + if (compressor != &lzma_compressor) + warning_fl("SetCompressorDictSize: compressor is not set to LZMA. Effectively ignored."); + if (build_compressor_set && build_compress_whole) + warning_fl("SetCompressorDictSize: data already compressed in compress whole mode. Effectively ignored."); + + int s; + build_compress_dict_size=line.gettoken_int(1,&s); + if (!s) PRINTHELP(); + SCRIPT_MSG("SetCompressorDictSize: %u mb\n", build_compress_dict_size); + build_compress_dict_size <<= 20; + } + return PS_OK; +#else + case TOK_SETCOMPRESSIONLEVEL: + case TOK_SETCOMPRESSORDICTSIZE: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPRESSION_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_COMPRESSION_SUPPORT + case TOK_ADDSIZE: + { + int s; + int size_kb=line.gettoken_int(1,&s); + if (!s) PRINTHELP() + SCRIPT_MSG("AddSize: %d kb\n",size_kb); + section_add_size_kb(size_kb); + } + return PS_OK; + case TOK_SUBCAPTION: + { + int s; + int w=line.gettoken_int(1,&s); + if (!s || w < 0 || w > 4) PRINTHELP() + SetInnerString(NLF_SUBCAPTION_LICENSE+w,line.gettoken_str(2)); + SCRIPT_MSG("SubCaption: page:%d, text=%s\n",w,line.gettoken_str(2)); + } + return PS_OK; + case TOK_FILEERRORTEXT: +#ifdef NSIS_SUPPORT_FILE + { + SetInnerString(NLF_FILE_ERROR,line.gettoken_str(1)); + SetInnerString(NLF_FILE_ERROR_NOIGNORE,line.gettoken_str(2)); + SCRIPT_MSG("FileErrorText: \"%s\" \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + } + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + case TOK_BRANDINGTEXT: + { + int a = 1; + int trim = 0; + while (line.gettoken_str(a)[0] == '/') { + if (!strnicmp(line.gettoken_str(a),"/TRIM",5)) { + if (!stricmp(line.gettoken_str(a)+5,"LEFT")) trim = 1; + else if (!stricmp(line.gettoken_str(a)+5,"RIGHT")) trim = 2; + else if (!stricmp(line.gettoken_str(a)+5,"CENTER")) trim = 3; + else PRINTHELP(); + a++; + } + else break; + } + if (line.getnumtokens()!=a+1 && !trim) PRINTHELP(); + if (line.getnumtokens()==a+1) + SetInnerString(NLF_BRANDING,line.gettoken_str(a)); +#ifdef _WIN32 + if (trim) try { + init_res_editor(); + + BYTE* dlg = res_editor->GetResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG); + CDialogTemplate td(dlg,uDefCodePage); + free(dlg); + + if (trim) { + char str[512]; + if (line.getnumtokens()==a+1 && line.gettoken_str(a)[0]) + strcpy(str, line.gettoken_str(a)); + else + wsprintf(str, "Nullsoft Install System %s", NSIS_VERSION); + + short old_width = td.GetItem(IDC_VERSTR)->sWidth; + + switch (trim) { + case 1: td.LTrimToString(IDC_VERSTR, str, 4); break; + case 2: td.RTrimToString(IDC_VERSTR, str, 4); break; + case 3: td.CTrimToString(IDC_VERSTR, str, 4); break; + } + + if (td.GetItem(IDC_VERSTR)->sWidth > old_width) + { + warning_fl("BrandingText: \"%s\" is too long, trimming has expanded the label", str); + } + } + + DWORD dwSize; + dlg = td.Save(dwSize); + res_editor->UpdateResourceA(RT_DIALOG, MAKEINTRESOURCE(IDD_INST), NSIS_DEFAULT_LANG, dlg, dwSize); + res_editor->FreeResource(dlg); + } + catch (exception& err) { + ERROR_MSG("Error while triming branding text control: %s\n", err.what()); + return PS_ERROR; + } +#else + if (trim) + { + ERROR_MSG("Error: BrandingText /TRIM* is disabled for non Win32 platforms.\n"); + return PS_ERROR; + } +#endif + SCRIPT_MSG("BrandingText: \"%s\"\n",line.gettoken_str(a)); + } + return PS_OK; + case TOK_MISCBUTTONTEXT: + { + SetInnerString(NLF_BTN_BACK,line.gettoken_str(1)); + SetInnerString(NLF_BTN_NEXT,line.gettoken_str(2)); + SetInnerString(NLF_BTN_CANCEL,line.gettoken_str(3)); + SetInnerString(NLF_BTN_CLOSE,line.gettoken_str(4)); + SCRIPT_MSG("MiscButtonText: back=\"%s\" next=\"%s\" cancel=\"%s\" close=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return PS_OK; + case TOK_SPACETEXTS: + { + if (!strcmpi(line.gettoken_str(1), "none")) { + no_space_texts=true; + SCRIPT_MSG("SpaceTexts: none\n"); + } + else { + no_space_texts=false; + SetInnerString(NLF_SPACE_REQ,line.gettoken_str(1)); + SetInnerString(NLF_SPACE_AVAIL,line.gettoken_str(2)); + SCRIPT_MSG("SpaceTexts: required=\"%s\" available=\"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + } + } + return PS_OK; + case TOK_INSTBUTTONTEXT: + { + SetInnerString(NLF_BTN_INSTALL,line.gettoken_str(1)); + SCRIPT_MSG("InstallButtonText: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_DETAILSBUTTONTEXT: + { + if (!cur_page) { + if (SetInnerString(NLF_BTN_DETAILS,line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + } + else { + if (cur_page_type != PAGE_INSTFILES) { + ERROR_MSG("Error: DetailsButtonText can only be used inside PageEx instfiles.\n"); + return PS_ERROR; + } + cur_page->parms[1] = add_string(line.gettoken_str(1)); + } + SCRIPT_MSG("DetailsButtonText: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_COMPLETEDTEXT: + { + if (!cur_page) { + if (SetInnerString(NLF_COMPLETED,line.gettoken_str(1)) == PS_WARNING) + warning_fl("%s: specified multiple times, wasting space",line.gettoken_str(0)); + } + else { + if (cur_page_type != PAGE_INSTFILES) { + ERROR_MSG("Error: CompletedText can only be used inside PageEx instfiles.\n"); + return PS_ERROR; + } + cur_page->parms[2] = add_string(line.gettoken_str(1)); + } + SCRIPT_MSG("CompletedText: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; + case TOK_UNINSTBUTTONTEXT: +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + { + SetInnerString(NLF_BTN_UNINSTALL,line.gettoken_str(1)); + SCRIPT_MSG("UninstButtonText: \"%s\"\n",line.gettoken_str(1)); + } + return PS_OK; +#else + ERROR_MSG("Error: %s specified, NSIS_CONFIG_UNINSTALL_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + + // instructions + /////////////////////////////////////////////////////////////////////////////// + case TOK_NOP: + SCRIPT_MSG("Nop\n"); + ent.which=EW_NOP; + return add_entry(&ent); + case TOK_GOTO: + ent.which=EW_NOP; + if (process_jump(line,1,&ent.offsets[0])) PRINTHELP() + SCRIPT_MSG("Goto: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETREGVIEW: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(alter_reg_view); + // "64" results in setting the flag to 1 which alters the view + int k=line.gettoken_enum(1,"32\0" "64\0lastused\0"); + if (k<0) PRINTHELP() + if (k == 0) // 32 + ent.offsets[1]=add_intstring(0); + else if (k == 1) // 64 + ent.offsets[1]=add_intstring(KEY_WOW64_64KEY); + else if (k == 2) // last used + ent.offsets[2]=1; + SCRIPT_MSG("SetRegView: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_SETSHELLVARCONTEXT: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(all_user_var); + int k=line.gettoken_enum(1,"current\0all\0"); + if (k<0) PRINTHELP() + ent.offsets[1]=add_intstring(k); + SCRIPT_MSG("SetShellVarContext: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_RET: + SCRIPT_MSG("Return\n"); + ent.which=EW_RET; + return add_entry(&ent); + case TOK_CALL: + if (!line.gettoken_str(1)[0] || (line.gettoken_str(1)[0]==':' && !line.gettoken_str(1)[1] )) PRINTHELP() +#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT + if (uninstall_mode && strnicmp(line.gettoken_str(1),"un.",3) + && (GetUserVarIndex(line,1) < 0) && line.gettoken_str(1)[0]!=':') + { + ERROR_MSG("Call must be used with function names starting with \"un.\" in the uninstall section.\n"); + PRINTHELP() + } + if (!uninstall_mode && !strnicmp(line.gettoken_str(1),"un.",3)) + { + ERROR_MSG("Call must not be used with functions starting with \"un.\" in the non-uninstall sections.\n"); + PRINTHELP() + } +#endif + ent.which=EW_CALL; + ent.offsets[1]=0; + { + int v; + if ((v=GetUserVarIndex(line, 1))>=0) + { + ent.offsets[0]=-v-2; + } + else + { + if (line.gettoken_str(1)[0] == ':') + { + ent.offsets[1]=1; + ent.offsets[0]=ns_label.add(line.gettoken_str(1)+1,0); + } + else ent.offsets[0]=ns_func.add(line.gettoken_str(1),0); + } + } + SCRIPT_MSG("Call \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETOUTPATH: + { + char *op=line.gettoken_str(1); + if (!strcmp(op,"-")) + { + op="$INSTDIR"; + } + SCRIPT_MSG("SetOutPath: \"%s\"\n",op); + ent.which=EW_CREATEDIR; + ent.offsets[0]=add_string(op); + ent.offsets[1]=1; + + DefineInnerLangString(NLF_OUTPUT_DIR); + } + return add_entry(&ent); + case TOK_CREATEDIR: + { + char out_path[1024]; + char *p=line.gettoken_str(1); + if (*p == '-') out_path[0]=0; + else + { + if (p[0] == '\\' && p[1] != '\\') p++; + strncpy(out_path,p,1024-1); + if (*CharPrev(out_path,out_path+strlen(out_path))=='\\') + *CharPrev(out_path,out_path+strlen(out_path))=0; // remove trailing slash + } + if (!*out_path) PRINTHELP() + SCRIPT_MSG("CreateDirectory: \"%s\"\n",out_path); + ent.which=EW_CREATEDIR; + ent.offsets[0]=add_string(out_path); + + DefineInnerLangString(NLF_CREATE_DIR); + } + return add_entry(&ent); + case TOK_EXEC: + case TOK_EXECWAIT: +#ifdef NSIS_SUPPORT_EXECUTE + ent.which=EW_EXECUTE; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[2]=0; + if (which_token == TOK_EXECWAIT) + { + ent.offsets[2]=1; + ent.offsets[1]=GetUserVarIndex(line, 2); + if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP() + } + SCRIPT_MSG("%s: \"%s\" (->%s)\n",ent.offsets[2]?"ExecWait":"Exec",line.gettoken_str(1),line.gettoken_str(2)); + + DefineInnerLangString(NLF_EXEC); + return add_entry(&ent); +#else//!NSIS_SUPPORT_EXECUTE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_EXECUTE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_EXECUTE + case TOK_EXECSHELL: // this uses improvements of Andras Varga +#ifdef NSIS_SUPPORT_SHELLEXECUTE + { + ent.which=EW_SHELLEXEC; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=SW_SHOWNORMAL; + if (line.getnumtokens() > 4) + { + int tab[4]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_HIDE}; + int a=line.gettoken_enum(4,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0SW_HIDE\0"); + if (a < 0) PRINTHELP() + ent.offsets[3]=tab[a]; + } + string detail=string(line.gettoken_str(1))+" "+string(line.gettoken_str(2)); + ent.offsets[5]=add_string(detail.c_str()); + SCRIPT_MSG("ExecShell: %s: \"%s\" \"%s\" %s\n",line.gettoken_str(1),line.gettoken_str(2), + line.gettoken_str(3),line.gettoken_str(4)); + + DefineInnerLangString(NLF_EXEC_SHELL); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_SHELLEXECUTE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_SHELLEXECUTE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_SHELLEXECUTE + case TOK_CALLINSTDLL: + case TOK_REGDLL: + case TOK_UNREGDLL: +#ifndef NSIS_SUPPORT_ACTIVEXREG + ERROR_MSG("%s: support not compiled in (NSIS_SUPPORT_ACTIVEXREG)\n",line.gettoken_str(0)); + return PS_ERROR; +#else//NSIS_SUPPORT_ACTIVEXREG + ent.which=EW_REGISTERDLL; + ent.offsets[0]=add_string(line.gettoken_str(1)); + if (which_token == TOK_UNREGDLL) + { + ent.offsets[1]=add_string("DllUnregisterServer"); + ent.offsets[2]=DefineInnerLangString(NLF_UNREGISTERING); + } + else if (which_token == TOK_CALLINSTDLL) + { + int a = 2; + if (!stricmp(line.gettoken_str(a), "/NOUNLOAD")) { + ent.offsets[3]=1; + a++; + } + if (a+1 != line.getnumtokens()) PRINTHELP(); + ent.offsets[1]=add_string(line.gettoken_str(a)); + if (!ent.offsets[1]) PRINTHELP() + ent.offsets[2]=0; + } + else // register + { + ent.offsets[1] = add_string(line.gettoken_str(2)); + if (!ent.offsets[1]) ent.offsets[1]=add_string("DllRegisterServer"); + ent.offsets[2]=DefineInnerLangString(NLF_REGISTERING); + } + + SCRIPT_MSG("%s: \"%s\" %s\n",line.gettoken_str(0),line.gettoken_str(1), line.gettoken_str(ent.offsets[3]?3:2)); + + DefineInnerLangString(NLF_SYMBOL_NOT_FOUND); + DefineInnerLangString(NLF_COULD_NOT_LOAD); + DefineInnerLangString(NLF_NO_OLE); + // not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL); + return add_entry(&ent); +#endif//NSIS_SUPPORT_ACTIVEXREG + case TOK_RENAME: +#ifdef NSIS_SUPPORT_RENAME + { + int a=1; + ent.which=EW_RENAME; + if (!stricmp(line.gettoken_str(1),"/REBOOTOK")) + { + ent.offsets[2]=1; + a++; +#ifndef NSIS_SUPPORT_MOVEONREBOOT + ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"); + PRINTHELP() +#endif + } + else if (line.gettoken_str(1)[0]=='/') + { + a=line.getnumtokens(); // cause usage to go here: + } + if (line.getnumtokens()!=a+2) PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + ent.offsets[1]=add_string(line.gettoken_str(a+1)); + string print = string(line.gettoken_str(a)) + "->" + string(line.gettoken_str(a+1)); + ent.offsets[3]=add_string(print.c_str()); + SCRIPT_MSG("Rename: %s%s->%s\n",ent.offsets[2]?"/REBOOTOK ":"",line.gettoken_str(a),line.gettoken_str(a+1)); + + DefineInnerLangString(NLF_RENAME); +#ifdef NSIS_SUPPORT_MOVEONREBOOT + DefineInnerLangString(NLF_RENAME_ON_REBOOT); +#endif + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_RENAME + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RENAME not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_RENAME + case TOK_MESSAGEBOX: +#ifdef NSIS_SUPPORT_MESSAGEBOX + { + #define MBD(x) {x,#x}, + struct + { + int id; + char *str; + } list[]= + { + MBD(MB_ABORTRETRYIGNORE) + MBD(MB_OK) + MBD(MB_OKCANCEL) + MBD(MB_RETRYCANCEL) + MBD(MB_YESNO) + MBD(MB_YESNOCANCEL) + MBD(MB_ICONEXCLAMATION) + MBD(MB_ICONINFORMATION) + MBD(MB_ICONQUESTION) + MBD(MB_ICONSTOP) + MBD(MB_USERICON) + MBD(MB_TOPMOST) + MBD(MB_SETFOREGROUND) + MBD(MB_RIGHT) + MBD(MB_RTLREADING) + MBD(MB_DEFBUTTON1) + MBD(MB_DEFBUTTON2) + MBD(MB_DEFBUTTON3) + MBD(MB_DEFBUTTON4) + }; + #undef MBD + int r=0; + int x; + char *p=line.gettoken_str(1); + + while (*p) + { + char *np=p; + while (*np && *np != '|') np++; + if (*np) *np++=0; + for (x = 0 ; (unsigned) x < sizeof(list) / sizeof(list[0]) && strcmpi(list[x].str, p); x++); + if ((unsigned) x < sizeof(list) / sizeof(list[0])) + { + r|=list[x].id; + } + else PRINTHELP() + p=np; + } + ent.which=EW_MESSAGEBOX; + ent.offsets[0]=r; + ent.offsets[1]=add_string(line.gettoken_str(2)); + int rettab[] = + { + 0,IDABORT,IDCANCEL,IDIGNORE,IDNO,IDOK,IDRETRY,IDYES + }; + const char *retstr="0\0IDABORT\0IDCANCEL\0IDIGNORE\0IDNO\0IDOK\0IDRETRY\0IDYES\0"; + int a=3; + if (line.getnumtokens() > 3) + { + if (!strcmpi(line.gettoken_str(3),"/SD")) + { + int k=line.gettoken_enum(4,retstr); + if (k <= 0) PRINTHELP(); + ent.offsets[0]|=rettab[k]<<21; + a=5; + } + else if (line.getnumtokens() > 7) + PRINTHELP(); + + if (line.getnumtokens() > a) + { + ent.offsets[2]=line.gettoken_enum(a,retstr); + if (ent.offsets[2] < 0) + PRINTHELP(); + ent.offsets[2] = rettab[ent.offsets[2]]; + if (process_jump(line,a+1,&ent.offsets[3])) + PRINTHELP(); + if (line.getnumtokens() > a+2) + { + int v=line.gettoken_enum(a+2,retstr); + if (v < 0) + PRINTHELP(); + ent.offsets[4] = rettab[v]; + if (process_jump(line,a+3,&ent.offsets[5])) + PRINTHELP(); + } + } + } + SCRIPT_MSG("MessageBox: %d: \"%s\"",r,line.gettoken_str(2)); + if (line.getnumtokens()>a+1) SCRIPT_MSG(" (on %s goto %s)",line.gettoken_str(a),line.gettoken_str(a+1)); + SCRIPT_MSG("\n"); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_MESSAGEBOX + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_MESSAGEBOX not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_MESSAGEBOX + case TOK_CREATESHORTCUT: +#ifdef NSIS_SUPPORT_CREATESHORTCUT + ent.which=EW_CREATESHORTCUT; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[5]=add_string(line.gettoken_str(8)); + int s; + ent.offsets[4]=line.gettoken_int(5,&s)&0xff; + if (!s) + { + if (line.getnumtokens() > 5 && *line.gettoken_str(5)) + { + ERROR_MSG("CreateShortCut: cannot interpret icon index\n"); + PRINTHELP() + } + ent.offsets[4]=0; + } + if (line.getnumtokens() > 6 && *line.gettoken_str(6)) + { + int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINNOACTIVE/*SW_SHOWMINIMIZED doesn't work*/}; + int a=line.gettoken_enum(6,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0"); + if (a < 0) + { + ERROR_MSG("CreateShortCut: unknown show mode \"%s\"\n",line.gettoken_str(6)); + PRINTHELP() + } + ent.offsets[4]|=tab[a]<<8; + } + if (line.getnumtokens() > 7) + { + char *s=(line.gettoken_str(7)); + + char b[255]; + for (unsigned int spos=0; (spos <= strlen(s)) && (spos <= 255); spos++) + b[spos]=toupper(*(s+spos)); + strcpy(s,b); + + if (*s) + { + int c=0; + if (strstr(s,"ALT|")) ent.offsets[4]|=HOTKEYF_ALT << 24; + if (strstr(s,"CONTROL|")) ent.offsets[4]|=HOTKEYF_CONTROL << 24; + if (strstr(s,"EXT|")) ent.offsets[4]|=HOTKEYF_EXT << 24; + if (strstr(s,"SHIFT|")) ent.offsets[4]|=HOTKEYF_SHIFT << 24; + while (strstr(s,"|")) + { + s=strstr(s,"|")+1; + } + if ((s[0] == 'F') && (s[1] >= '1' && s[1] <= '9')) + { + c=VK_F1-1+atoi(s+1); + if (atoi(s+1) < 1 || atoi(s+1) > 24) + { + warning_fl("CreateShortCut: F-key \"%s\" out of range",s); + } + } + else if (((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= '0' && s[0] <= '9')) && !s[1]) + c=s[0]; + else + { + c=s[0]; + warning_fl("CreateShortCut: unrecognized hotkey \"%s\"",s); + } + ent.offsets[4] |= (c) << 16; + } + } + SCRIPT_MSG("CreateShortCut: \"%s\"->\"%s\" %s icon:%s,%d, showmode=0x%X, hotkey=0x%X, comment=%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3), + line.gettoken_str(4),ent.offsets[4]&0xff,(ent.offsets[4]>>8)&0xff,ent.offsets[4]>>16,line.gettoken_str(8)); + + DefineInnerLangString(NLF_CREATE_SHORTCUT); + DefineInnerLangString(NLF_ERR_CREATING_SHORTCUT); + return add_entry(&ent); +#else//!NSIS_SUPPORT_CREATESHORTCUT + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_CREATESHORTCUT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_SUPPORT_CREATESHORTCUT +#ifdef NSIS_SUPPORT_HWNDS + case TOK_FINDWINDOW: + ent.which=EW_FINDWINDOW; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=add_string(line.gettoken_str(5)); + SCRIPT_MSG("FindWindow: output=%s, class=\"%s\", text=\"%s\" hwndparent=\"%s\" hwndafter=\"%s\"\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); + return add_entry(&ent); + case TOK_SENDMESSAGE: + ent.which=EW_SENDMESSAGE; + + if (line.gettoken_str(1)[0] == '/' || line.gettoken_str(2)[0] == '/' || + line.gettoken_str(3)[0] == '/' || line.gettoken_str(4)[0] == '/') + { + PRINTHELP() + } + + SCRIPT_MSG("SendMessage:"); + { + int a=5; + ent.offsets[0]=GetUserVarIndex(line, 5); + if (ent.offsets[0]>=0) + { + SCRIPT_MSG("(->%s)",line.gettoken_str(5)); + a++; + } + + if (!strncmp(line.gettoken_str(a),"/TIMEOUT=",9)) + { + ent.offsets[5]|=atoi(line.gettoken_str(a)+9)<<2; + SCRIPT_MSG(" (timeout=%d)",ent.offsets[5]>>2); + a++; + } + + if (line.getnumtokens()>a) + { + PRINTHELP() + } + } + + if (!strncmp(line.gettoken_str(3),"STR:",4)) + { + ent.offsets[5]|=1; + ent.offsets[3]=add_string(line.gettoken_str(3)+4); + } + else ent.offsets[3]=add_string(line.gettoken_str(3)); + if (!strncmp(line.gettoken_str(4),"STR:",4)) + { + ent.offsets[5]|=2; + ent.offsets[4]=add_string(line.gettoken_str(4)+4); + } + else ent.offsets[4]=add_string(line.gettoken_str(4)); + + ent.offsets[1]=add_string(line.gettoken_str(1)); + ent.offsets[2]=add_string(line.gettoken_str(2)); + + SCRIPT_MSG("(%s,%s,%s,%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_ISWINDOW: + ent.which=EW_ISWINDOW; + ent.offsets[0]=add_string(line.gettoken_str(1)); + if (process_jump(line,2,&ent.offsets[1])|| + process_jump(line,3,&ent.offsets[2])) PRINTHELP() + SCRIPT_MSG("IsWindow(%s): %s:%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + case TOK_GETDLGITEM: + ent.which=EW_GETDLGITEM; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0]<0) PRINTHELP(); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + SCRIPT_MSG("GetDlgItem: output=%s dialog=%s item=%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_SETCTLCOLORS: + { + ctlcolors c={0, }; + + ent.which=EW_SETCTLCOLORS; + ent.offsets[0]=add_string(line.gettoken_str(1)); + + int a = 2; + + if (!strcmpi(line.gettoken_str(2),"/BRANDING")) + a++; + + { + char *p; + + if (a == 2 && line.getnumtokens() == 5) { + ERROR_MSG("Error: SetCtlColors expected 3 parameters, got 4\n"); + return PS_ERROR; + } + + if (!strcmpi(line.gettoken_str(a+1),"transparent")) { + c.flags|=CC_BKB; + c.lbStyle=BS_NULL; + c.bkmode=TRANSPARENT; + } + else { + p=line.gettoken_str(a+1); + if (*p) { + int v=strtoul(p,&p,16); + c.bkc=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16); + c.flags|=CC_BK|CC_BKB; + } + + c.lbStyle=BS_SOLID; + c.bkmode=OPAQUE; + } + + p=line.gettoken_str(a); + if (*p) { + int v=strtoul(p,&p,16); + c.text=((v&0xff)<<16)|(v&0xff00)|((v&0xff0000)>>16); + c.flags|=CC_TEXT; + } + } + + if (a == 3) + { + c.flags|=CC_BK|CC_BKB; + c.lbStyle=BS_NULL; + if (!*line.gettoken_str(a+1)) + { + c.bkc=COLOR_BTNFACE; + c.flags|=CC_BK_SYS; + } + c.flags|=CC_TEXT; + if (!*line.gettoken_str(a)) + { + c.text=COLOR_BTNFACE; + c.flags|=CC_TEXT_SYS; + } + c.bkmode=OPAQUE; + } + + int i; + int l=cur_ctlcolors->getlen()/sizeof(ctlcolors); + for (i=0; i<l; i++) { + if (!memcmp((ctlcolors*)cur_ctlcolors->get()+i,&c,sizeof(ctlcolors))) { + ent.offsets[1]=i*sizeof(ctlcolors); + break; + } + } + if (i>=l) { + ent.offsets[1]=cur_ctlcolors->add(&c,sizeof(ctlcolors)); + } + + SCRIPT_MSG("SetCtlColors: hwnd=%s %stext=%s background=%s\n",line.gettoken_str(1),a==2?"":"/BRANDING ",line.gettoken_str(a),line.gettoken_str(a+1)); + } + return add_entry(&ent); + case TOK_CREATEFONT: + ent.which=EW_CREATEFONT; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("CreateFont: output=%s \"%s\"",line.gettoken_str(1),line.gettoken_str(2)); + { + int height=0; + int weight=0; + int flags=0; + for (int i = 3; i < line.getnumtokens(); i++) { + char *tok=line.gettoken_str(i); + if (tok[0]=='/') { + if (!strcmpi(tok,"/ITALIC")) { + SCRIPT_MSG(" /ITALIC"); + flags|=1; + } + else if (!strcmpi(tok,"/UNDERLINE")) { + SCRIPT_MSG(" /UNDERLINE"); + flags|=2; + } + else if (!strcmpi(tok,"/STRIKE")) { + SCRIPT_MSG(" /STRIKE"); + flags|=4; + } + else { + SCRIPT_MSG("\n"); + PRINTHELP(); + } + } + else { + if (!height) { + SCRIPT_MSG(" height=%s",tok); + height=add_string(tok); + } + else if (!weight) { + SCRIPT_MSG(" weight=%s",tok); + weight=add_string(tok); + } + else { + SCRIPT_MSG("\n"); + PRINTHELP(); + } + } + } + ent.offsets[2]=height; + ent.offsets[3]=weight; + ent.offsets[4]=flags; + } + SCRIPT_MSG("\n"); + return add_entry(&ent); + case TOK_ENABLEWINDOW: + ent.which=EW_SHOWWINDOW; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[3]=1; + SCRIPT_MSG("EnableWindow: handle=%s enable=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SHOWWINDOW: + ent.which=EW_SHOWWINDOW; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("ShowWindow: handle=%s show state=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_HIDEWINDOW: + ent.which=EW_SHOWWINDOW; + ent.offsets[0]=add_string("$HWNDPARENT"); + ent.offsets[1]=add_string("0"/*SW_HIDE*/); + ent.offsets[2]=1; + SCRIPT_MSG("HideWindow\n"); + return add_entry(&ent); + case TOK_BRINGTOFRONT: + { + int ret; + ent.which=EW_SHOWWINDOW; + ent.offsets[0]=add_string("$HWNDPARENT"); + ent.offsets[1]=add_string("5"/*SW_SHOW*/); + ret = add_entry(&ent); + if (ret != PS_OK) return ret; + ent.which=EW_BRINGTOFRONT; + ent.offsets[0]=0; + ent.offsets[1]=0; + SCRIPT_MSG("BringToFront\n"); + } + return add_entry(&ent); +#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT + case TOK_GETDLGITEM: + case TOK_SETCTLCOLORS: + case TOK_SHOWWINDOW: + case TOK_BRINGTOFRONT: + case TOK_CREATEFONT: + case TOK_HIDEWINDOW: + case TOK_ENABLEWINDOW: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//NSIS_CONFIG_ENHANCEDUI_SUPPORT +#else//!NSIS_SUPPORT_HWNDS + case TOK_ISWINDOW: + case TOK_SENDMESSAGE: + case TOK_FINDWINDOW: + case TOK_GETDLGITEM: + case TOK_SETCTLCOLORS: + case TOK_SHOWWINDOW: + case TOK_ENABLEWINDOW: + case TOK_CREATEFONT: + case TOK_HIDEWINDOW: + case TOK_BRINGTOFRONT: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_HWNDS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_HWNDS + case TOK_DELETE: +#ifdef NSIS_SUPPORT_DELETE + { + int a=1; + ent.which=EW_DELETEFILE; + if (!stricmp(line.gettoken_str(a),"/REBOOTOK")) + { + a++; + ent.offsets[1]=DEL_REBOOT; +#ifndef NSIS_SUPPORT_MOVEONREBOOT + ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"); + PRINTHELP() +#endif + } + else if (line.gettoken_str(1)[0]=='/') + { + a=line.getnumtokens(); + } + if (line.getnumtokens() != a+1) PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + SCRIPT_MSG("Delete: %s\"%s\"\n",ent.offsets[1]?"/REBOOTOK ":"",line.gettoken_str(a)); + + DefineInnerLangString(NLF_DEL_FILE); +#ifdef NSIS_SUPPORT_MOVEONREBOOT + DefineInnerLangString(NLF_DEL_ON_REBOOT); +#endif + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_DELETE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_DELETE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_DELETE + case TOK_RMDIR: +#ifdef NSIS_SUPPORT_RMDIR + { + int a=1; + ent.which=EW_RMDIR; + ent.offsets[1]=DEL_DIR; + while (line.gettoken_str(a)[0]=='/') + { + if (!stricmp(line.gettoken_str(a),"/r")) + { + if (a == 3) PRINTHELP(); + a++; + ent.offsets[1]|=DEL_RECURSE; + } + else if (!stricmp(line.gettoken_str(a),"/REBOOTOK")) + { + if (a == 3) PRINTHELP(); + a++; + ent.offsets[1]|=DEL_REBOOT; + } + else PRINTHELP(); + } + if (a < line.getnumtokens() - 1) PRINTHELP(); + ent.offsets[0]=add_string(line.gettoken_str(a)); + SCRIPT_MSG("RMDir: "); + if (a>1) + SCRIPT_MSG("%s ",line.gettoken_str(1)); + if (a>2) + SCRIPT_MSG("%s ",line.gettoken_str(2)); + SCRIPT_MSG("\"%s\"\n",line.gettoken_str(a)); + + DefineInnerLangString(NLF_REMOVE_DIR); + DefineInnerLangString(NLF_DEL_FILE); +#ifdef NSIS_SUPPORT_MOVEONREBOOT + DefineInnerLangString(NLF_DEL_ON_REBOOT); +#endif + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_RMDIR + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_RMDIR not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_RMDIR + case TOK_RESERVEFILE: + case TOK_FILE: +#ifdef NSIS_SUPPORT_FILE + { + set<string> excluded; + int a=1,attrib=0,rec=0,fatal=1; + if (!stricmp(line.gettoken_str(a),"/nonfatal")) { + fatal=0; + a++; + } + if (which_token == TOK_FILE && !stricmp(line.gettoken_str(a),"/a")) + { +#ifdef _WIN32 + attrib=1; +#else + warning_fl("%sFile /a is disabled for non Win32 platforms.",(which_token == TOK_FILE)?"":"Reserve"); +#endif + a++; + } + if (!stricmp(line.gettoken_str(a),"/r")) + { + rec=1; + a++; + } + else if (which_token == TOK_FILE && !strnicmp(line.gettoken_str(a),"/oname=",7)) + { + char *on=line.gettoken_str(a)+7; + a++; + if (!*on||line.getnumtokens()!=a+1||strstr(on,"*") || strstr(on,"?")) PRINTHELP() + + if (on[0]=='"') + { + ERROR_MSG("%sFile: output name must not begin with a quote, use \"/oname=name with spaces\".\n",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a)); + PRINTHELP(); + } + + int tf=0; +#ifdef _WIN32 + int v=do_add_file(line.gettoken_str(a), attrib, 0, &tf, on); +#else + char *fn = my_convert(line.gettoken_str(a)); + int v=do_add_file(fn, attrib, 0, &tf, on); + my_convert_free(fn); +#endif + if (v != PS_OK) return v; + if (tf > 1) PRINTHELP() + if (!tf) + { + if (fatal) + { + ERROR_MSG("%sFile: \"%s\" -> no files found.\n",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a)); + PRINTHELP() + } + else + { + warning_fl("%sFile: \"%s\" -> no files found",(which_token == TOK_FILE)?"":"Reserve",line.gettoken_str(a)); + + // workaround for bug #1299100 + // add a nop opcode so relative jumps will work as expected + add_entry_direct(EW_NOP); + } + } + + return PS_OK; + } + if (!strnicmp(line.gettoken_str(a),"/x",2)) + { + while (!strnicmp(line.gettoken_str(a),"/x",2)) + { + a++; + + if (line.getnumtokens() < a+1) PRINTHELP() + + excluded.insert(line.gettoken_str(a)); + a++; + } + } +#ifdef _WIN32 + if (line.gettoken_str(a)[0] == '/') PRINTHELP() +#endif + if (line.getnumtokens()<a+1) PRINTHELP() + while (a < line.getnumtokens()) + { +#ifdef _WIN32 + if (line.gettoken_str(a)[0]=='/') PRINTHELP() +#endif + char buf[32]; + char *t=line.gettoken_str(a++); + if (t[0] && CharNext(t)[0] == ':' && CharNext(t)[1] == '\\' && !CharNext(t)[2]) + { + strcpy(buf,"X:\\*.*"); + buf[0]=t[0]; + t=buf; + } + int tf=0; +#ifdef _WIN32 + int v=do_add_file(t, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded); +#else + char *fn = my_convert(t); + int v=do_add_file(fn, attrib, rec, &tf, NULL, which_token == TOK_FILE, NULL, excluded); + my_convert_free(fn); +#endif + if (v != PS_OK) return v; + if (!tf) + { + if (fatal) + { + ERROR_MSG("%sFile: \"%s\" -> no files found.\n",(which_token == TOK_FILE)?"":"Reserve",t); + PRINTHELP(); + } + else + { + warning_fl("%sFile: \"%s\" -> no files found.",(which_token == TOK_FILE)?"":"Reserve",t); + } + } + } + } + return PS_OK; +#else//!NSIS_SUPPORT_FILE + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_FILE +#ifdef NSIS_SUPPORT_COPYFILES + case TOK_COPYFILES: + { + ent.which=EW_COPYFILES; + ent.offsets[2]=FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_NOERRORUI|FOF_SIMPLEPROGRESS; + + int a=1; + int x; + for (x = 0; x < 2; x ++) + { + if (!stricmp(line.gettoken_str(a),"/SILENT")) + { + a++; + ent.offsets[2]&=~FOF_SIMPLEPROGRESS; + ent.offsets[2]|=FOF_SILENT; + } + else if (!stricmp(line.gettoken_str(a),"/FILESONLY")) + { + a++; + ent.offsets[2]|=FOF_FILESONLY; + } + else if (line.gettoken_str(a)[0]=='/') PRINTHELP() + else break; + } + if (line.getnumtokens() < a+2) PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(a)); + ent.offsets[1]=add_string(line.gettoken_str(a+1)); + string copy_to = string("$(^CopyTo)") + line.gettoken_str(a+1); + ent.offsets[3]=add_string(copy_to.c_str()); + int s; + int size_kb=line.gettoken_int(a+2,&s); + if (!s && line.gettoken_str(a+2)[0]) PRINTHELP() + section_add_size_kb(size_kb); + SCRIPT_MSG("CopyFiles: %s\"%s\" -> \"%s\", size=%iKB\n",ent.offsets[2]&FOF_SILENT?"(silent) ":"", line.gettoken_str(a),line.gettoken_str(a+1),size_kb); + + DefineInnerLangString(NLF_COPY_FAILED); + DefineInnerLangString(NLF_COPY_TO); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_COPYFILES + case TOK_COPYFILES: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_COPYFILES not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_COPYFILES + + case TOK_SETFILEATTRIBUTES: + { + #define MBD(x) {x,#x}, + struct + { + int id; + char *str; + } list[]= + { + MBD(FILE_ATTRIBUTE_NORMAL) + MBD(FILE_ATTRIBUTE_ARCHIVE) + MBD(FILE_ATTRIBUTE_HIDDEN) + MBD(FILE_ATTRIBUTE_OFFLINE) + MBD(FILE_ATTRIBUTE_READONLY) + MBD(FILE_ATTRIBUTE_SYSTEM) + MBD(FILE_ATTRIBUTE_TEMPORARY) + {FILE_ATTRIBUTE_NORMAL,"NORMAL"}, + {FILE_ATTRIBUTE_ARCHIVE,"ARCHIVE"}, + {FILE_ATTRIBUTE_HIDDEN,"HIDDEN"}, + {FILE_ATTRIBUTE_OFFLINE,"OFFLINE"}, + {FILE_ATTRIBUTE_READONLY,"READONLY"}, + {FILE_ATTRIBUTE_SYSTEM,"SYSTEM"}, + {FILE_ATTRIBUTE_TEMPORARY,"TEMPORARY"}, + {FILE_ATTRIBUTE_NORMAL,"0"}, + }; + #undef MBD + int r=0; + int x; + char *p=line.gettoken_str(2); + + while (*p) + { + char *np=p; + while (*np && *np != '|') np++; + if (*np) *np++=0; + for (x = 0 ; (unsigned) x < sizeof(list)/sizeof(list[0]) && stricmp(list[x].str,p); x ++); + + if ((unsigned) x < sizeof(list)/sizeof(list[0])) + { + r|=list[x].id; + } + else PRINTHELP() + p=np; + } + ent.which=EW_SETFILEATTRIBUTES; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=r; + } + return add_entry(&ent); + case TOK_SLEEP: + { + ent.which=EW_SLEEP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("Sleep: %s ms\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_IFFILEEXISTS: + ent.which=EW_IFFILEEXISTS; + ent.offsets[0] = add_string(line.gettoken_str(1)); + if (process_jump(line,2,&ent.offsets[1]) || + process_jump(line,3,&ent.offsets[2])) PRINTHELP() + SCRIPT_MSG("IfFileExists: \"%s\" ? %s : %s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_QUIT: + ent.which=EW_QUIT; + SCRIPT_MSG("Quit\n"); + return add_entry(&ent); + case TOK_ABORT: + ent.which=EW_ABORT; + ent.offsets[0] = add_string(line.gettoken_str(1)); + SCRIPT_MSG("Abort: \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_SETDETAILSVIEW: + { + int v=line.gettoken_enum(1,"hide\0show\0"); + ent.which=EW_CHDETAILSVIEW; + if (v < 0) PRINTHELP() + ent.offsets[0] = v?SW_SHOWNA:SW_HIDE; + ent.offsets[1] = v?SW_HIDE:SW_SHOWNA; + SCRIPT_MSG("SetDetailsView: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_SETDETAILSPRINT: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(status_update); + int k=line.gettoken_enum(1,"both\0textonly\0listonly\0none\0lastused\0"); + if (k<0) PRINTHELP() + if (k == 4) + { + ent.offsets[2]=1; + } + else + { + // both 0 + // textonly 2 + // listonly 4 + // none 6 + ent.offsets[1]=add_intstring(k*2); + } + SCRIPT_MSG("SetDetailsPrint: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_SETAUTOCLOSE: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(autoclose); + int k=line.gettoken_enum(1,"false\0true\0"); + if (k < 0) PRINTHELP() + ent.offsets[1]=add_intstring(k); + SCRIPT_MSG("SetAutoClose: %s\n",line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_IFERRORS: + ent.which=EW_IFFLAG; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=FLAG_OFFSET(exec_error); + ent.offsets[3]=0;//new value mask - clean error + SCRIPT_MSG("IfErrors ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_IFABORT: + ent.which=EW_IFFLAG; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=FLAG_OFFSET(abort); + ent.offsets[3]=~0;//new value mask - keep flag + SCRIPT_MSG("IfAbort ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_CLEARERRORS: + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(exec_error); + ent.offsets[1]=add_intstring(0); + SCRIPT_MSG("ClearErrors\n"); + return add_entry(&ent); + case TOK_SETERRORS: + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(exec_error); + ent.offsets[1]=add_intstring(1); + SCRIPT_MSG("SetErrors\n"); + return add_entry(&ent); + case TOK_SETERRORLEVEL: + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(errlvl); + ent.offsets[1]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("SetErrorLevel: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_GETERRORLEVEL: + ent.which=EW_GETFLAG; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=FLAG_OFFSET(errlvl); + if (line.gettoken_str(1)[0] && ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetErrorLevel: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#ifdef NSIS_SUPPORT_STROPTS + case TOK_STRLEN: + ent.which=EW_STRLEN; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("StrLen %s \"%s\"\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_STRCPY: + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("StrCpy %s \"%s\" (%s) (%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_GETFUNCTIONADDR: + ent.which=EW_GETFUNCTIONADDR; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=ns_func.add(line.gettoken_str(2),0); + ent.offsets[2]=0; + ent.offsets[3]=0; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("GetFunctionAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_GETLABELADDR: + ent.which=EW_GETLABELADDR; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0 || process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=0; + ent.offsets[3]=0; + SCRIPT_MSG("GetLabelAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_GETCURRENTADDR: + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=GetUserVarIndex(line, 1); + { + char buf[32]; + wsprintf(buf,"%d",1+(cur_header->blocks[NB_ENTRIES].num)); + ent.offsets[1]=add_string(buf); + } + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[2]=0; + ent.offsets[3]=0; + SCRIPT_MSG("GetCurrentAddress: %s",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_STRCMP: + case TOK_STRCMPS: + ent.which=EW_STRCMP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[4]=which_token == TOK_STRCMPS; + if (process_jump(line,3,&ent.offsets[2]) || + process_jump(line,4,&ent.offsets[3])) PRINTHELP() + SCRIPT_MSG("%s \"%s\" \"%s\" equal=%s, nonequal=%s\n",line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_GETDLLVERSIONLOCAL: + { + DWORD low, high; + if (!GetDLLVersion(line.gettoken_str(1),high,low)) + { + ERROR_MSG("GetDLLVersionLocal: error reading version info from \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=GetUserVarIndex(line, 2); + ent.offsets[1]=add_intstring(high); + ent.offsets[2]=0; + ent.offsets[3]=0; + if (ent.offsets[0]<0) PRINTHELP() + add_entry(&ent); + + ent.offsets[0]=GetUserVarIndex(line, 3); + ent.offsets[1]=add_intstring(low); + ent.offsets[2]=0; + ent.offsets[3]=0; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetDLLVersionLocal: %s (%u,%u)->(%s,%s)\n", + line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); + } + return add_entry(&ent); + case TOK_GETFILETIMELOCAL: + { + char buf[129]; + DWORD high=0,low=0; +#ifdef _WIN32 + int flag=0; + HANDLE hFile=CreateFile(line.gettoken_str(1),0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + FILETIME ft; + if (GetFileTime(hFile,NULL,NULL,&ft)) + { + high=ft.dwHighDateTime; + low=ft.dwLowDateTime; + flag=1; + } + CloseHandle(hFile); + } + if (!flag) + { + ERROR_MSG("GetFileTimeLocal: error reading date from \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } +#else + struct stat st; + if (!stat(line.gettoken_str(1), &st)) + { + unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL; + high = (DWORD) (ll >> 32); + low = (DWORD) ll; + } + else + { + ERROR_MSG("GetFileTimeLocal: error reading date from \"%s\"\n",line.gettoken_str(1)); + return PS_ERROR; + } +#endif + + ent.which=EW_ASSIGNVAR; + ent.offsets[0]=GetUserVarIndex(line, 2); + wsprintf(buf,"%u",high); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=0; + ent.offsets[3]=0; + if (ent.offsets[0]<0) PRINTHELP() + add_entry(&ent); + + ent.offsets[0]=GetUserVarIndex(line, 3); + wsprintf(buf,"%u",low); + ent.offsets[1]=add_string(buf); + ent.offsets[2]=0; + ent.offsets[3]=0; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetFileTimeLocal: %s (%u,%u)->(%s,%s)\n", + line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); + } + return add_entry(&ent); + +#else//!NSIS_SUPPORT_STROPTS + case TOK_GETDLLVERSIONLOCAL: + case TOK_GETFILETIMELOCAL: + case TOK_GETFUNCTIONADDR: + case TOK_GETLABELADDR: + case TOK_GETCURRENTADDR: + case TOK_STRLEN: + case TOK_STRCPY: + case TOK_STRCMP: + case TOK_STRCMPS: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STROPTS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_STROPTS +#ifdef NSIS_SUPPORT_INIFILES + case TOK_DELETEINISEC: + case TOK_DELETEINISTR: + { + char *vname=""; + char *space=""; + ent.which=EW_WRITEINI; + ent.offsets[0]=add_string(line.gettoken_str(2)); // section name + if (line.getnumtokens() > 3) + { + vname=line.gettoken_str(3); + ent.offsets[1]=add_string(vname); // value name + space=" "; + } + else ent.offsets[1]=0; + ent.offsets[2]=0; + ent.offsets[3]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("DeleteINI%s: [%s] %s%sin %s\n",*vname?"Str":"Sec", + line.gettoken_str(2),vname,space,line.gettoken_str(1)); + } + return add_entry(&ent); + case TOK_FLUSHINI: + ent.which=EW_WRITEINI; + ent.offsets[3]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("FlushINI: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_WRITEINISTR: + ent.which=EW_WRITEINI; + ent.offsets[0]=add_string(line.gettoken_str(2)); + ent.offsets[1]=add_string(line.gettoken_str(3)); + ent.offsets[2]=add_string(line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(1)); + ent.offsets[4]=1; // write + SCRIPT_MSG("WriteINIStr: [%s] %s=%s in %s\n", + line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_READINISTR: + ent.which=EW_READINISTR; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(3)); + ent.offsets[2]=add_string(line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("ReadINIStr %s [%s]:%s from %s\n",line.gettoken_str(1),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(2)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_INIFILES + case TOK_DELETEINISEC: + case TOK_DELETEINISTR: + case TOK_FLUSHINI: + case TOK_WRITEINISTR: + case TOK_READINISTR: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INIFILES not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_INIFILES + case TOK_DETAILPRINT: + ent.which=EW_UPDATETEXT; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + SCRIPT_MSG("DetailPrint: \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); +#ifdef NSIS_SUPPORT_FNUTIL + case TOK_GETTEMPFILENAME: + ent.which=EW_GETTEMPFILENAME; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (line.getnumtokens() == 3) + ent.offsets[1]=add_string(line.gettoken_str(2)); + else + ent.offsets[1]=add_string("$TEMP"); + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetTempFileName -> %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_GETFULLPATHNAME: + { + int a=0; + ent.which=EW_GETFULLPATHNAME; + if (line.getnumtokens()==4 && !stricmp(line.gettoken_str(1),"/SHORT")) a++; + else if (line.getnumtokens()==4 || *line.gettoken_str(1)=='/') PRINTHELP() + ent.offsets[0]=add_string(line.gettoken_str(2+a)); + ent.offsets[1]=GetUserVarIndex(line, 1+a); + ent.offsets[2]=!a; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetFullPathName: %s->%s (%d)\n", + line.gettoken_str(2+a),line.gettoken_str(1+a),a?"sfn":"lfn"); + } + return add_entry(&ent); + case TOK_SEARCHPATH: + ent.which=EW_SEARCHPATH; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SearchPath %s %s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); +#else + case TOK_SEARCHPATH: + case TOK_GETTEMPFILENAME: + case TOK_GETFULLPATHNAME: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FNUTIL not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif + case TOK_GETDLLVERSION: +#ifdef NSIS_SUPPORT_GETDLLVERSION + ent.which=EW_GETDLLVERSION; + ent.offsets[0]=GetUserVarIndex(line, 2); + ent.offsets[1]=GetUserVarIndex(line, 3); + ent.offsets[2]=add_string(line.gettoken_str(1)); + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("GetDLLVersion: %s->%s,%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_GETDLLVERSION + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETDLLVERSION not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_GETDLLVERSION + case TOK_GETFILETIME: +#ifdef NSIS_SUPPORT_GETFILETIME + ent.which=EW_GETFILETIME; + ent.offsets[0]=GetUserVarIndex(line, 2); + ent.offsets[1]=GetUserVarIndex(line, 3); + ent.offsets[2]=add_string(line.gettoken_str(1)); + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("GetFileTime: %s->%s,%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_GETFILETIME + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_GETFILETIME not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_GETFILETIME +#ifdef NSIS_SUPPORT_INTOPTS + case TOK_INTOP: + ent.which=EW_INTOP; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[3]=line.gettoken_enum(3,"+\0-\0*\0/\0|\0&\0^\0!\0||\0&&\0%\0<<\0>>\0~\0"); + if (ent.offsets[0] < 0 || ent.offsets[3] < 0 || + ((ent.offsets[3] == 7 || ent.offsets[3] == 13) && line.getnumtokens() > 4)) + PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[3] != 7 && ent.offsets[3] != 13) ent.offsets[2]=add_string(line.gettoken_str(4)); + if (ent.offsets[3] == 13) { + ent.offsets[3]=6; + ent.offsets[2]=add_string("0xFFFFFFFF"); + } + SCRIPT_MSG("IntOp: %s=%s%s%s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + return add_entry(&ent); + case TOK_INTFMT: + ent.which=EW_INTFMT; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0]<0) PRINTHELP() + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + SCRIPT_MSG("IntFmt: %s->%s (fmt:%s)\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_INTCMP: + case TOK_INTCMPU: + ent.which=EW_INTCMP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[5]=which_token == TOK_INTCMPU; + if (process_jump(line,3,&ent.offsets[2]) || + process_jump(line,4,&ent.offsets[3]) || + process_jump(line,5,&ent.offsets[4])) PRINTHELP() + SCRIPT_MSG("%s %s:%s equal=%s, < %s, > %s\n",line.gettoken_str(0), + line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(5)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_INTOPTS + case TOK_INTOP: + case TOK_INTCMP: + case TOK_INTFMT: + case TOK_INTCMPU: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_INTOPTS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_INTOPTS +#ifdef NSIS_SUPPORT_REGISTRYFUNCTIONS + case TOK_READREGSTR: + case TOK_READREGDWORD: + { + ent.which=EW_READREGSTR; + ent.offsets[0]=GetUserVarIndex(line, 1); + int k=line.gettoken_enum(2,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); + if (ent.offsets[0] == -1 || k == -1) PRINTHELP() + ent.offsets[1]=(int)rootkey_tab[k]; + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + if (which_token == TOK_READREGDWORD) ent.offsets[4]=1; + else ent.offsets[4]=0; + if (line.gettoken_str(3)[0] == '\\') + warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0)); + + SCRIPT_MSG("%s %s %s\\%s\\%s\n",line.gettoken_str(0), + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return add_entry(&ent); + case TOK_DELETEREGVALUE: + case TOK_DELETEREGKEY: + { + int a=1; + if (which_token==TOK_DELETEREGKEY) + { + ent.offsets[4]=1; + char *s=line.gettoken_str(a); + if (s[0] == '/') + { + if (stricmp(s,"/ifempty")) PRINTHELP() + a++; + ent.offsets[4]=3; + } + if (line.gettoken_str(a+2)[0]) PRINTHELP() + } + int k=line.gettoken_enum(a,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(a,rootkeys[1]); + if (k == -1) PRINTHELP() + ent.which=EW_DELREG; + ent.offsets[1]=(int)rootkey_tab[k]; + ent.offsets[2]=add_string(line.gettoken_str(a+1)); + ent.offsets[3]=(which_token==TOK_DELETEREGKEY)?0:add_string(line.gettoken_str(a+2)); + if (line.gettoken_str(a+1)[0] == '\\') + warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0)); + if (which_token==TOK_DELETEREGKEY) + SCRIPT_MSG("DeleteRegKey: %s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1)); + else + SCRIPT_MSG("DeleteRegValue: %s\\%s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1),line.gettoken_str(a+2)); + } + return add_entry(&ent); + case TOK_WRITEREGSTR: + case TOK_WRITEREGEXPANDSTR: + case TOK_WRITEREGBIN: + case TOK_WRITEREGDWORD: + { + int k=line.gettoken_enum(1,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(1,rootkeys[1]); + if (k == -1) PRINTHELP() + ent.which=EW_WRITEREG; + ent.offsets[0]=(int)rootkey_tab[k]; + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (line.gettoken_str(2)[0] == '\\') + warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0)); + ent.offsets[2]=add_string(line.gettoken_str(3)); + if (which_token == TOK_WRITEREGSTR || which_token == TOK_WRITEREGEXPANDSTR) + { + SCRIPT_MSG("%s: %s\\%s\\%s=%s\n", + line.gettoken_str(0),line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=ent.offsets[5]=REG_SZ; + if (which_token == TOK_WRITEREGEXPANDSTR) + { + ent.offsets[5]=REG_EXPAND_SZ; + } + } + if (which_token == TOK_WRITEREGBIN) + { + char data[3*NSIS_MAX_STRLEN]; + char *p=line.gettoken_str(4); + int data_len=0; + while (*p) + { + int c; + int a,b; + a=*p; + if (a >= '0' && a <= '9') a-='0'; + else if (a >= 'a' && a <= 'f') a-='a'-10; + else if (a >= 'A' && a <= 'F') a-='A'-10; + else break; + b=*++p; + if (b >= '0' && b <= '9') b-='0'; + else if (b >= 'a' && b <= 'f') b-='a'-10; + else if (b >= 'A' && b <= 'F') b-='A'-10; + else break; + p++; + c=(a<<4)|b; + if (data_len >= 3*NSIS_MAX_STRLEN) + { + ERROR_MSG("WriteRegBin: %d bytes of data exceeded\n",3*NSIS_MAX_STRLEN); + return PS_ERROR; + } + data[data_len++]=c; + } + if (*p) PRINTHELP() + SCRIPT_MSG("WriteRegBin: %s\\%s\\%s=%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + ent.offsets[3]=add_db_data(data,data_len); + if (ent.offsets[3] < 0) return PS_ERROR; + ent.offsets[4]=ent.offsets[5]=REG_BINARY; + } + if (which_token == TOK_WRITEREGDWORD) + { + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=ent.offsets[5]=REG_DWORD; + + SCRIPT_MSG("WriteRegDWORD: %s\\%s\\%s=%s\n", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + } + return add_entry(&ent); + case TOK_ENUMREGKEY: + case TOK_ENUMREGVAL: + { + ent.which=EW_REGENUM; + ent.offsets[0]=GetUserVarIndex(line, 1); + int k=line.gettoken_enum(2,rootkeys[0]); + if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); + if (ent.offsets[0] == -1 || k == -1) PRINTHELP() + ent.offsets[1]=(int)rootkey_tab[k]; + ent.offsets[2]=add_string(line.gettoken_str(3)); + ent.offsets[3]=add_string(line.gettoken_str(4)); + ent.offsets[4]=which_token == TOK_ENUMREGKEY; + if (line.gettoken_str(3)[0] == '\\') warning_fl("%s: registry path name begins with \'\\\', may cause problems",line.gettoken_str(0)); + SCRIPT_MSG("%s %s %s\\%s\\%s\n",which_token == TOK_ENUMREGKEY ? "EnumRegKey" : "EnumRegValue", + line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4)); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_REGISTRYFUNCTIONS + case TOK_READREGSTR: + case TOK_READREGDWORD: + case TOK_DELETEREGVALUE: + case TOK_DELETEREGKEY: + case TOK_WRITEREGSTR: + case TOK_WRITEREGEXPANDSTR: + case TOK_WRITEREGBIN: + case TOK_WRITEREGDWORD: + case TOK_ENUMREGKEY: + case TOK_ENUMREGVAL: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REGISTRYFUNCTIONS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_REGISTRYFUNCTIONS +#ifdef NSIS_SUPPORT_STACK + case TOK_EXCH: + { + int swapitem=1; + int save=GetUserVarIndex(line, 1); + ent.which=EW_PUSHPOP; + if (line.gettoken_str(1)[0] && save<0) + { + int s=0; + swapitem=line.gettoken_int(1,&s); + if (!s || swapitem <= 0) PRINTHELP() + } + if (save>=0) + { + SCRIPT_MSG("Exch(%s,0)\n",line.gettoken_str(1)); + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + ent.offsets[2]=0; + add_entry(&ent); + } + else SCRIPT_MSG("Exch(st(%d),0)\n",swapitem); + + ent.offsets[0]=0; + ent.offsets[1]=0; + ent.offsets[2]=swapitem; + + if (save>=0) + { + add_entry(&ent); + ent.offsets[0]=save; + ent.offsets[1]=1; + ent.offsets[2]=0; + } + + DefineInnerLangString(NLF_INST_CORRUPTED); + } + return add_entry(&ent); + case TOK_PUSH: + ent.which=EW_PUSHPOP; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + SCRIPT_MSG("Push: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_POP: + ent.which=EW_PUSHPOP; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=1; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("Pop: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_STACK + case TOK_POP: + case TOK_PUSH: + case TOK_EXCH: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_STACK not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_STACK +#ifdef NSIS_SUPPORT_ENVIRONMENT + case TOK_READENVSTR: + ent.which=EW_READENVSTR; + ent.offsets[0]=GetUserVarIndex(line, 1); + { + char str[NSIS_MAX_STRLEN]; + strcpy(str, "%"); + strcat(str, line.gettoken_str(2)); + strcat(str, "%"); + ent.offsets[1]=add_string(str); + if (ent.offsets[0] < 0 || strlen(line.gettoken_str(2))<1) PRINTHELP() + } + ent.offsets[2]=1; + SCRIPT_MSG("ReadEnvStr: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_EXPANDENVSTRS: + ent.which=EW_READENVSTR; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=0; + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("ExpandEnvStrings: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_ENVIRONMENT + case TOK_EXPANDENVSTRS: + case TOK_READENVSTR: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_ENVIRONMENT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_ENVIRONMENT +#ifdef NSIS_SUPPORT_FINDFIRST + case TOK_FINDFIRST: + ent.which=EW_FINDFIRST; + ent.offsets[0]=GetUserVarIndex(line, 2); // out + ent.offsets[1]=GetUserVarIndex(line, 1); // handleout + ent.offsets[2]=add_string(line.gettoken_str(3)); // filespec + if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP() + SCRIPT_MSG("FindFirst: spec=\"%s\" handle=%s output=%s\n",line.gettoken_str(3),line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FINDNEXT: + ent.which=EW_FINDNEXT; + ent.offsets[0]=GetUserVarIndex(line, 2); + ent.offsets[1]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0 || ent.offsets[1] < 0) PRINTHELP() + SCRIPT_MSG("FindNext: handle=%s output=%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FINDCLOSE: + ent.which=EW_FINDCLOSE; + ent.offsets[0]=GetUserVarIndex(line, 1); + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("FindClose: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_SUPPORT_FINDFIRST + case TOK_FINDCLOSE: + case TOK_FINDNEXT: + case TOK_FINDFIRST: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FINDFIRST not defined.\n", line.gettoken_str(0)); + return PS_ERROR; + +#endif//!NSIS_SUPPORT_FINDFIRST + + +#ifdef NSIS_SUPPORT_FILEFUNCTIONS + case TOK_FILEOPEN: + { + ent.which=EW_FOPEN; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + ent.offsets[3]=add_string(line.gettoken_str(2)); + ent.offsets[1]=0; //openmode + if (!stricmp(line.gettoken_str(3),"r")) + { + ent.offsets[1]=GENERIC_READ; + ent.offsets[2]=OPEN_EXISTING; + } + else if (!stricmp(line.gettoken_str(3),"w")) + { + ent.offsets[1]=GENERIC_WRITE; + ent.offsets[2]=CREATE_ALWAYS; + } + else if (!stricmp(line.gettoken_str(3),"a")) + { + ent.offsets[1]=GENERIC_WRITE|GENERIC_READ; + ent.offsets[2]=OPEN_ALWAYS; + } + + if (ent.offsets[0] < 0 || !ent.offsets[1]) PRINTHELP() + } + SCRIPT_MSG("FileOpen: %s as %s -> %s\n",line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILECLOSE: + ent.which=EW_FCLOSE; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + if (ent.offsets[0] < 0) PRINTHELP() + SCRIPT_MSG("FileClose: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILEREAD: + ent.which=EW_FGETS; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + ent.offsets[1]=GetUserVarIndex(line, 2); // output string + if (line.gettoken_str(3)[0]) + ent.offsets[2]=add_string(line.gettoken_str(3)); + else + ent.offsets[2]=add_intstring(NSIS_MAX_STRLEN-1); + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("FileRead: %s->%s (max:%s)\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3)); + return add_entry(&ent); + case TOK_FILEWRITE: + ent.which=EW_FPUTS; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + ent.offsets[1]=add_string(line.gettoken_str(2)); + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("FileWrite: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILEREADBYTE: + ent.which=EW_FGETS; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + ent.offsets[1]=GetUserVarIndex(line, 2); // output string + ent.offsets[2]=add_string("1"); + ent.offsets[3]=1; + if (ent.offsets[0]<0 || ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("FileReadByte: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_FILEWRITEBYTE: + ent.which=EW_FPUTS; + ent.offsets[0]=GetUserVarIndex(line, 1); // file handle + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=1; + if (ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("FileWriteByte: %s->%s\n",line.gettoken_str(2),line.gettoken_str(1)); + return add_entry(&ent); + case TOK_FILESEEK: + { + char *modestr; + int tab[3]={FILE_BEGIN,FILE_CURRENT,FILE_END}; + int mode=line.gettoken_enum(3,"SET\0CUR\0END\0"); + ent.which=EW_FSEEK; + ent.offsets[0]=GetUserVarIndex(line, 1); + ent.offsets[1]=GetUserVarIndex(line, 4); + ent.offsets[2]=add_string(line.gettoken_str(2)); + + if (mode<0 && !line.gettoken_str(3)[0]) + { + mode=0; + modestr="SET"; + } + else modestr=line.gettoken_str(3); + + if (mode<0 || ent.offsets[0] < 0 || (ent.offsets[1]<0 && line.gettoken_str(4)[0])) PRINTHELP() + ent.offsets[3]=tab[mode]; + SCRIPT_MSG("FileSeek: fp=%s, ofs=%s, mode=%s, output=%s\n", + line.gettoken_str(1), + line.gettoken_str(2), + modestr, + line.gettoken_str(4)); + } + + return add_entry(&ent); +#else//!NSIS_SUPPORT_FILEFUNCTIONS + case TOK_FILEOPEN: + case TOK_FILECLOSE: + case TOK_FILESEEK: + case TOK_FILEREAD: + case TOK_FILEWRITE: + case TOK_FILEREADBYTE: + case TOK_FILEWRITEBYTE: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_FILEFUNCTIONS not defined.\n", line.gettoken_str(0)); + return PS_ERROR; + +#endif//!NSIS_SUPPORT_FILEFUNCTIONS +#ifdef NSIS_SUPPORT_REBOOT + case TOK_REBOOT: + { + int ret = add_entry_direct(EW_REBOOT, 0xbadf00d); + if (ret != PS_OK) return ret; + + ret = add_entry_direct(EW_QUIT); + if (ret != PS_OK) return ret; + + SCRIPT_MSG("Reboot! (WOW)\n"); + + DefineInnerLangString(NLF_INST_CORRUPTED); + } + return PS_OK; + case TOK_IFREBOOTFLAG: + ent.which=EW_IFFLAG; + if (process_jump(line,1,&ent.offsets[0]) || + process_jump(line,2,&ent.offsets[1])) PRINTHELP() + ent.offsets[2]=FLAG_OFFSET(exec_reboot); + ent.offsets[3]=~0;//new value mask - keep flag + SCRIPT_MSG("IfRebootFlag ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SETREBOOTFLAG: + { + ent.which=EW_SETFLAG; + ent.offsets[0]=FLAG_OFFSET(exec_reboot); + int k=line.gettoken_enum(1,"false\0true\0"); + if (k < 0) PRINTHELP() + ent.offsets[1]=add_intstring(k); + } + return add_entry(&ent); +#else//!NSIS_SUPPORT_REBOOT + case TOK_REBOOT: + case TOK_IFREBOOTFLAG: + case TOK_SETREBOOTFLAG: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_REBOOT not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_REBOOT +#ifdef NSIS_CONFIG_LOG + case TOK_LOGSET: + ent.which=EW_LOG; + ent.offsets[0]=1; + ent.offsets[1]=line.gettoken_enum(1,"off\0on\0"); + if (ent.offsets[1]<0) PRINTHELP() + + SCRIPT_MSG("LogSet: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_LOGTEXT: + ent.which=EW_LOG; + ent.offsets[0]=0; + ent.offsets[1]=add_string(line.gettoken_str(1)); + SCRIPT_MSG("LogText \"%s\"\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_CONFIG_LOG + + case TOK_LOGSET: + case TOK_LOGTEXT: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_LOG not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_LOG +#ifdef NSIS_CONFIG_COMPONENTPAGE + case TOK_SECTIONSETTEXT: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[2]=SECTION_FIELD_SET(name_ptr); + ent.offsets[4]=add_string(line.gettoken_str(2)); + SCRIPT_MSG("SectionSetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETTEXT: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=GetUserVarIndex(line, 2); + ent.offsets[2]=SECTION_FIELD_GET(name_ptr); + if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("SectionGetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONSETFLAGS: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=SECTION_FIELD_SET(flags); + ent.offsets[3]=1; + SCRIPT_MSG("SectionSetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETFLAGS: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=GetUserVarIndex(line, 2); + ent.offsets[2]=SECTION_FIELD_GET(flags); + if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("SectionGetFlags: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_INSTTYPESETTEXT: + ent.which=EW_INSTTYPESET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=1; + SCRIPT_MSG("InstTypeSetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_INSTTYPEGETTEXT: + ent.which=EW_INSTTYPESET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=GetUserVarIndex(line, 2); + ent.offsets[2]=0; + if (line.gettoken_str(1)[0] && ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("InstTypeGetText: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONSETINSTTYPES: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=SECTION_FIELD_SET(install_types); + SCRIPT_MSG("SectionSetInstTypes: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETINSTTYPES: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=GetUserVarIndex(line, 2); + ent.offsets[2]=SECTION_FIELD_GET(install_types); + if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("SectionGetInstTypes: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONSETSIZE: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=add_string(line.gettoken_str(2)); + ent.offsets[2]=SECTION_FIELD_SET(size_kb); + SCRIPT_MSG("SectionSetSize: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SECTIONGETSIZE: + ent.which=EW_SECTIONSET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=GetUserVarIndex(line, 2); + ent.offsets[2]=SECTION_FIELD_GET(size_kb); + if (line.gettoken_str(2)[0] && ent.offsets[1]<0) PRINTHELP() + SCRIPT_MSG("SectionGetSize: %s->%s\n",line.gettoken_str(1),line.gettoken_str(2)); + return add_entry(&ent); + case TOK_SETCURINSTTYPE: + ent.which=EW_INSTTYPESET; + ent.offsets[0]=add_string(line.gettoken_str(1)); + ent.offsets[1]=0; + ent.offsets[2]=1; + ent.offsets[3]=1; + SCRIPT_MSG("SetCurInstType: %s\n",line.gettoken_str(1)); + return add_entry(&ent); + case TOK_GETCURINSTTYPE: + ent.which=EW_INSTTYPESET; + ent.offsets[0]=0; + ent.offsets[1]=GetUserVarIndex(line,1); + ent.offsets[2]=0; + ent.offsets[3]=1; + if (line.gettoken_str(1)[0] && ent.offsets[0]<0) PRINTHELP() + SCRIPT_MSG("GetCurInstType: %s\n",line.gettoken_str(1)); + return add_entry(&ent); +#else//!NSIS_CONFIG_COMPONENTPAGE + case TOK_SECTIONSETTEXT: + case TOK_SECTIONGETTEXT: + case TOK_SECTIONSETFLAGS: + case TOK_SECTIONGETFLAGS: + case TOK_SECTIONSETSIZE: + case TOK_SECTIONGETSIZE: + case TOK_SECTIONSETINSTTYPES: + case TOK_SECTIONGETINSTTYPES: + case TOK_SETCURINSTTYPE: + case TOK_GETCURINSTTYPE: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_COMPONENTPAGE not defined.\n", line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_CONFIG_COMPONENTPAGE +#ifdef NSIS_CONFIG_ENHANCEDUI_SUPPORT + case TOK_SETBRANDINGIMAGE: + { + SCRIPT_MSG("SetBrandingImage: "); + if (!branding_image_found) { + ERROR_MSG("\nError: no branding image found in chosen UI!\n"); + return PS_ERROR; + } + ent.which=EW_SETBRANDINGIMAGE; + for (int i = 1; i < line.getnumtokens(); i++) + if (!strnicmp(line.gettoken_str(i),"/IMGID=",7)) { + ent.offsets[1]=atoi(line.gettoken_str(i)+7); + SCRIPT_MSG("/IMGID=%d ",ent.offsets[1]); + } + else if (!stricmp(line.gettoken_str(i),"/RESIZETOFIT")) { + ent.offsets[2]=1; // must be 1 or 0 + SCRIPT_MSG("/RESIZETOFIT "); + } + else if (!ent.offsets[0]) { + ent.offsets[0]=add_string(line.gettoken_str(i)); + SCRIPT_MSG("\"%s\" ", line.gettoken_str(i)); + } + else { + SCRIPT_MSG("\n"); + PRINTHELP(); + } + + if (!ent.offsets[1]) + ent.offsets[1]=branding_image_id; + SCRIPT_MSG("\n"); + } + return add_entry(&ent); +#else//NSIS_CONFIG_ENHANCEDUI_SUPPORT + case TOK_SETBRANDINGIMAGE: + ERROR_MSG("Error: %s specified, NSIS_CONFIG_ENHANCEDUI_SUPPORT not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif//!NSIS_SUPPORT_CREATEFONT + + // Added by ramon 3 jun 2003 + case TOK_DEFVAR: + { + int a=1; + + if (!strcmpi(line.gettoken_str(1),"/GLOBAL")) + { + a++; + } + else if (line.getnumtokens() == 3) + { + PRINTHELP(); + } + + if (build_cursection) + { + if (a==1) + { + ERROR_MSG("Var: currently, only global variables can be defined.\n"); + PRINTHELP(); + } + } + + SCRIPT_MSG("Var: \"%s\"\n",line.gettoken_str(a)); + + int res = DeclaredUserVar(line.gettoken_str(a)); + if (res != PS_OK) + return res; + + } + return PS_OK; + + // Added by ramon 6 jun 2003 +#ifdef NSIS_SUPPORT_VERSION_INFO + case TOK_VI_ADDKEY: + { + LANGID LangID=0; + int a = 1; + if (!strnicmp(line.gettoken_str(a),"/LANG=",6)) + LangID=atoi(line.gettoken_str(a++)+6); + if (line.getnumtokens()!=a+2) PRINTHELP(); + char *pKey = line.gettoken_str(a); + char *pValue = line.gettoken_str(a+1); + if ( !(*pKey) ) + { + ERROR_MSG("Error: empty name for version info key!\n"); + return PS_ERROR; + } + else + { + SCRIPT_MSG("%s: \"%s\" \"%s\"\n", line.gettoken_str(0), line.gettoken_str(a), line.gettoken_str(a+1)); + LANGID lReaded = LangID; + if ( a > 1 && lReaded == 0 ) + warning_fl("%s: %s language not loaded, using default \"1033-English\"", line.gettoken_str(0), line.gettoken_str(1)); + + unsigned int codepage; + char *lang_name = GetLangNameAndCP(LangID, &codepage); + + if ( rVersionInfo.SetKeyValue(LangID, codepage, pKey, pValue) ) + { + ERROR_MSG("%s: \"%s\" \"%04d-%s\" already defined!\n",line.gettoken_str(0), line.gettoken_str(2), LangID, lang_name); + return PS_ERROR; + } + + return PS_OK; + } + } + case TOK_VI_SETPRODUCTVERSION: + if ( version_product_v[0] ) + { + ERROR_MSG("Error: %s already defined!\n", line.gettoken_str(0)); + return PS_ERROR; + } + strcpy(version_product_v, line.gettoken_str(1)); + return PS_OK; + +#else + case TOK_VI_ADDKEY: + case TOK_VI_SETPRODUCTVERSION: + ERROR_MSG("Error: %s specified, NSIS_SUPPORT_VERSION_INFO not defined.\n",line.gettoken_str(0)); + return PS_ERROR; +#endif + + // end of instructions + /////////////////////////////////////////////////////////////////////////////// + + // Added by Ximon Eighteen 5th August 2002 +#ifdef NSIS_CONFIG_PLUGIN_SUPPORT + case TOK_PLUGINDIR: + { + if (line.getnumtokens() == 2) + { + SCRIPT_MSG("PluginDir: \"%s\"\n",line.gettoken_str(1)); +#ifdef _WIN32 + m_plugins.FindCommands(line.gettoken_str(1), display_info?true:false); +#else + char *converted_path = my_convert(line.gettoken_str(1)); + m_plugins.FindCommands(converted_path, display_info?true:false); + my_convert_free(converted_path); +#endif + return PS_OK; + } + } + return PS_ERROR; + case TOK__PLUGINCOMMAND: + { + int ret; + + const string command = m_plugins.NormalizedCommand(line.gettoken_str(0)); + const string dllPath = m_plugins.GetPluginPath(command); + int data_handle = m_plugins.GetPluginHandle(uninstall_mode?true:false, command); + + if (uninstall_mode) uninst_plugin_used = true; + else plugin_used = true; + + // Initialize $PLUGINSDIR + ent.which=EW_CALL; + ent.offsets[0]=ns_func.add(uninstall_mode?"un.Initialize_____Plugins":"Initialize_____Plugins",0); + ret=add_entry(&ent); + if (ret != PS_OK) { + return ret; + } + + // DLL name on the user machine + char tempDLL[NSIS_MAX_STRLEN]; + string dllName = get_file_name(dllPath); + wsprintf(tempDLL, "$PLUGINSDIR\\%s", dllName.c_str()); + + // Add the DLL to the installer + if (data_handle == -1) + { + int files_added; + int old_build_allowskipfiles=build_allowskipfiles; + build_allowskipfiles=1; // on + int old_build_overwrite=build_overwrite; + build_overwrite=1; // off + int old_build_datesave=build_datesave; + build_datesave=0; // off + ret=do_add_file(dllPath.c_str(),0,0,&files_added,tempDLL,2,&data_handle); // 2 means no size add + if (ret != PS_OK) { + return ret; + } + m_plugins.SetDllDataHandle(uninstall_mode?true:false, line.gettoken_str(0), data_handle); + build_overwrite=old_build_overwrite; + build_datesave=old_build_datesave; + // Added by ramon 23 May 2003 + build_allowskipfiles=old_build_allowskipfiles; + } + else + { + ent.which=EW_EXTRACTFILE; + + DefineInnerLangString(NLF_SKIPPED); + DefineInnerLangString(NLF_ERR_DECOMPRESSING); + DefineInnerLangString(NLF_ERR_WRITING); + DefineInnerLangString(NLF_EXTRACT); + DefineInnerLangString(NLF_CANT_WRITE); + + ent.offsets[0]=1; // overwrite off + ent.offsets[0]|=(MB_RETRYCANCEL|MB_ICONSTOP|(IDCANCEL<<21))<<3; + ent.offsets[1]=add_string(tempDLL); + ent.offsets[2]=data_handle; + ent.offsets[3]=0xffffffff; + ent.offsets[4]=0xffffffff; + ent.offsets[5]=DefineInnerLangString(NLF_FILE_ERROR); + ret=add_entry(&ent); + if (ret != PS_OK) { + return ret; + } + } + + // SetDetailsPrint lastused + ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1); + if (ret != PS_OK) { + return ret; + } + + // Call the DLL + string funcname = get_string_suffix(command, "::"); + SCRIPT_MSG("Plugin Command: %s",funcname.c_str()); + + int i = 1; + int nounload = 0; + if (!strcmpi(line.gettoken_str(i), "/NOUNLOAD")) { + i++; + nounload++; + } + + // First push dll args + + int parmst=i; // we push em in reverse order + int nounloadmisused=0; + for (; i < line.getnumtokens(); i++) { + int w=parmst + (line.getnumtokens()-i - 1); + ent.which=EW_PUSHPOP; + ent.offsets[0]=add_string(line.gettoken_str(w)); + if (!strcmpi(line.gettoken_str(w), "/NOUNLOAD")) nounloadmisused=1; + ent.offsets[1]=0; + ent.offsets[2]=0; + ret=add_entry(&ent); + if (ret != PS_OK) { + return ret; + } + SCRIPT_MSG(" %s",line.gettoken_str(i)); + } + SCRIPT_MSG("\n"); + if (nounloadmisused) + warning_fl("/NOUNLOAD must come first before any plugin parameter. Unless the plugin you are trying to use has a parameter /NOUNLOAD, you are doing something wrong"); + + // next, call it + ent.which=EW_REGISTERDLL; + ent.offsets[0]=add_string(tempDLL);; + ent.offsets[1]=add_string(funcname.c_str()); + ent.offsets[2]=0; + ent.offsets[3]=nounload|build_plugin_unload; + ent.offsets[4]=1; + ret=add_entry(&ent); + if (ret != PS_OK) { + return ret; + } + + DefineInnerLangString(NLF_SYMBOL_NOT_FOUND); + DefineInnerLangString(NLF_COULD_NOT_LOAD); + DefineInnerLangString(NLF_NO_OLE); + // not used anywhere - DefineInnerLangString(NLF_ERR_REG_DLL); + + return PS_OK; + } + case TOK_INITPLUGINSDIR: + { + int ret; + SCRIPT_MSG("%s\n",line.gettoken_str(0)); + if (uninstall_mode) uninst_plugin_used = true; + else plugin_used = true; + // Call [un.]Initialize_____Plugins + ent.which=EW_CALL; + ent.offsets[0]=ns_func.add(uninstall_mode?"un.Initialize_____Plugins":"Initialize_____Plugins",0); + ret=add_entry(&ent); + if (ret != PS_OK) return ret; + // SetDetailsPrint lastused + ret=add_entry_direct(EW_SETFLAG, FLAG_OFFSET(status_update), 0, 1); + if (ret != PS_OK) return ret; + } + return PS_OK; +#else + case TOK_PLUGINDIR: + case TOK__PLUGINCOMMAND: + case TOK_INITPLUGINSDIR: + { + ERROR_MSG("Error: %s specified, NSIS_CONFIG_PLUGIN_SUPPORT not defined.\n",line.gettoken_str(0)); + } + return PS_ERROR; +#endif// NSIS_CONFIG_PLUGIN_SUPPORT + +#ifdef NSIS_LOCKWINDOW_SUPPORT + case TOK_LOCKWINDOW: + SCRIPT_MSG("LockWindow: lock state=%d\n",line.gettoken_str(1)); + ent.which=EW_LOCKWINDOW; + ent.offsets[0]=line.gettoken_enum(1,"on\0off\0"); + if (ent.offsets[0] == -1) + PRINTHELP(); + return add_entry(&ent); +#else + case TOK_LOCKWINDOW: + { + ERROR_MSG("Error: %s specified, NSIS_LOCKWINDOW_SUPPORT not defined.\n",line.gettoken_str(0)); + } + return PS_ERROR; +#endif // NSIS_LOCKWINDOW_SUPPORT + + default: break; + + } + ERROR_MSG("Error: doCommand: Invalid token \"%s\".\n",line.gettoken_str(0)); + return PS_ERROR; +} + +#ifdef NSIS_SUPPORT_FILE +int CEXEBuild::do_add_file(const char *lgss, int attrib, int recurse, int *total_files, const char *name_override, int generatecode, int *data_handle, const set<string>& excluded, const string& basedir, bool dir_created) +{ + assert(!name_override || !recurse); + + string dir = get_dir_name(lgss); + string spec; + + if (dir == lgss) { + dir = "."; + spec = lgss; + } else { + spec = string(lgss).substr(dir.length() + 1, string::npos); + } + + if (spec == "") { + spec = "*"; + } + + if (basedir == "") { + dir_created = true; + + if (recurse) { + // save $OUTDIR into $_OUTDIR [StrCpy $_OUTDIR $OUTDIR] + if (add_entry_direct(EW_ASSIGNVAR, m_UserVarNames.get("_OUTDIR"), add_string("$OUTDIR")) != PS_OK) { + return PS_ERROR; + } + } + } + + boost::scoped_ptr<dir_reader> dr( new_dir_reader() ); + dr->exclude(excluded); + dr->read(dir); + + // add files in the current directory + for (dir_reader::iterator files_itr = dr->files().begin(); + files_itr != dr->files().end(); + files_itr++) + { + if (!dir_reader::matches(*files_itr, spec)) + continue; + + if (!dir_created && generatecode) { + SCRIPT_MSG("%sFile: Descending to: \"%s\"\n", generatecode ? "" : "Reserve", dir.c_str()); + + if (do_add_file_create_dir(dir, basedir, attrib) != PS_OK) { + return PS_ERROR; + } + + dir_created = true; + } + + if (add_file(dir, *files_itr, attrib, name_override, generatecode, data_handle) != PS_OK) { + return PS_ERROR; + } + + (*total_files)++; + } + + if (!recurse) { + return PS_OK; + } + + // recurse into directories + for (dir_reader::iterator dirs_itr = dr->dirs().begin(); + dirs_itr != dr->dirs().end(); + dirs_itr++) + { + string new_dir; + bool created = false; + + if (basedir == "") { + new_dir = *dirs_itr; + } else { + new_dir = basedir + '\\' + *dirs_itr; + } + + string new_spec = dir + PLATFORM_PATH_SEPARATOR_STR + *dirs_itr + PLATFORM_PATH_SEPARATOR_STR; + + if (!dir_reader::matches(*dirs_itr, spec)) { + new_spec += spec; + } else if (generatecode) { + // always create directories that match + + SCRIPT_MSG("%sFile: Descending to: \"%s\"\n", generatecode ? "" : "Reserve", new_spec.c_str()); + + if (do_add_file_create_dir(dir + '\\' + *dirs_itr, new_dir, attrib) != PS_OK) { + return PS_ERROR; + } + + created = true; + } + + const char *new_spec_c = new_spec.c_str(); + + int res = do_add_file(new_spec_c, attrib, 1, total_files, NULL, generatecode, NULL, excluded, new_dir, created); + if (res != PS_OK) { + return PS_ERROR; + } + } + + if (basedir == "") { + SCRIPT_MSG("%sFile: Returning to: \"%s\"\n", generatecode ? "" : "Reserve", dir.c_str()); + + // restore $OUTDIR from $_OUTDIR [SetOutPath $_OUTDIR] + if (add_entry_direct(EW_CREATEDIR, add_string("$_OUTDIR"), 1) != PS_OK) { + return PS_ERROR; + } + } + + return PS_OK; +} + +int CEXEBuild::add_file(const string& dir, const string& file, int attrib, const char *name_override, int generatecode, int *data_handle) { + string newfn_s = dir + PLATFORM_PATH_SEPARATOR_C + file; + const char *newfn = newfn_s.c_str(); + const char *filename = file.c_str(); + + MMapFile mmap; + DWORD len; + +#ifdef _WIN32 + HANDLE hFile = CreateFile( + newfn, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + NULL + ); + if (hFile == INVALID_HANDLE_VALUE) + { + ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } + + // Will auto-CloseHandle hFile + MANAGE_WITH(hFile, CloseHandle); + + len = GetFileSize(hFile, NULL); + if (len && !mmap.setfile(hFile, len)) + { + ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } +#else + struct stat s; + if (stat(newfn, &s)) { + ERROR_MSG("%sFile: failed stating file \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } + + len = (DWORD) s.st_size; + + int fd = OPEN(newfn, O_RDONLY); + if (fd == -1) + { + ERROR_MSG("%sFile: failed opening file \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } + + // Will auto-close(2) fd + MANAGE_WITH(fd, close); + + if (len && !mmap.setfile(fd, len)) + { + ERROR_MSG("%sFile: failed creating mmap of \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } +#endif + + if (generatecode&1) + section_add_size_kb((len+1023)/1024); + if (name_override) SCRIPT_MSG("%sFile: \"%s\"->\"%s\"",generatecode?"":"Reserve",filename,name_override); + else SCRIPT_MSG("%sFile: \"%s\"",generatecode?"":"Reserve",filename); + if (!build_compress_whole) + if (build_compress) SCRIPT_MSG(" [compress]"); + fflush(stdout); + char buf[1024]; + int last_build_datablock_used=getcurdbsize(); + entry ent={0,}; + if (generatecode) + { + ent.which=EW_EXTRACTFILE; + + DefineInnerLangString(NLF_SKIPPED); + DefineInnerLangString(NLF_ERR_DECOMPRESSING); + DefineInnerLangString(NLF_ERR_WRITING); + DefineInnerLangString(NLF_EXTRACT); + DefineInnerLangString(NLF_CANT_WRITE); + + ent.offsets[0]=build_overwrite; + if (name_override) + { + ent.offsets[1]=add_string(name_override); + } + else + { + const char *i=filename; + char *o=buf; + while (*i) + { + const char c=*i++; + *o++=c; + if (c == '$') *o++='$'; + } + *o=0; + ent.offsets[1]=add_string(buf); + } + } + ent.offsets[2]=add_db_data(&mmap); + + mmap.clear(); + + if (ent.offsets[2] < 0) + { + return PS_ERROR; + } + + if (data_handle) + { + *data_handle=ent.offsets[2]; + } + + { + DWORD s=getcurdbsize()-last_build_datablock_used; + if (s) s-=4; + if (s != len) SCRIPT_MSG(" %d/%d bytes\n",s,len); + else SCRIPT_MSG(" %d bytes\n",len); + } + + if (generatecode) + { + if (build_datesave || build_overwrite>=0x3 /*ifnewer or ifdiff*/) + { +#ifdef _WIN32 + FILETIME ft; + if (GetFileTime(hFile,NULL,NULL,&ft)) + { + // FAT write time has a resolution of 2 seconds + PULONGLONG fti = (PULONGLONG) &ft; + *fti -= *fti % 20000000; + + ent.offsets[3]=ft.dwLowDateTime; + ent.offsets[4]=ft.dwHighDateTime; + } +#else + struct stat st; + if (!fstat(fd, &st)) + { + unsigned long long ll = (st.st_mtime * 10000000LL) + 116444736000000000LL; + + // FAT write time has a resolution of 2 seconds + ll -= ll % 20000000; + + ent.offsets[3] = (int) ll; + ent.offsets[4] = (int) (ll >> 32); + } +#endif + else + { + ERROR_MSG("%sFile: failed getting file date from \"%s\"\n",generatecode?"":"Reserve",newfn); + return PS_ERROR; + } + } + else + { + ent.offsets[3]=0xffffffff; + ent.offsets[4]=0xffffffff; + } + + // overwrite flag can be 0, 1, 2 or 3. in all cases, 2 bits + int mb = 0; + if (build_allowskipfiles) + { + mb = MB_ABORTRETRYIGNORE | MB_ICONSTOP; + // default for silent installers + mb |= IDIGNORE << 21; + } + else + { + mb = MB_RETRYCANCEL | MB_ICONSTOP; + // default for silent installers + mb |= IDCANCEL << 21; + } + ent.offsets[0] |= mb << 3; + + ent.offsets[5] = DefineInnerLangString(build_allowskipfiles ? NLF_FILE_ERROR : NLF_FILE_ERROR_NOIGNORE); + } + + if (generatecode) + { + int a=add_entry(&ent); + if (a != PS_OK) + { + return a; + } + if (attrib) + { +#ifdef _WIN32 + ent.which=EW_SETFILEATTRIBUTES; + // $OUTDIR is the working directory + ent.offsets[0]=add_string(name_override?name_override:buf); + ent.offsets[1]=GetFileAttributes(newfn); + ent.offsets[2]=0; + ent.offsets[3]=0; + ent.offsets[4]=0; + ent.offsets[5]=0; + + if (ent.offsets[1] != INVALID_FILE_ATTRIBUTES) + { + a=add_entry(&ent); + if (a != PS_OK) + { + return a; + } + } +#endif + } + } + + return PS_OK; +} + +int CEXEBuild::do_add_file_create_dir(const string& local_dir, const string& dir, int attrib) { + string outdir_s = "$_OUTDIR\\" + dir; + + string::size_type pos = 1; + pos = outdir_s.find('$', pos); + while (pos != string::npos) { + outdir_s = outdir_s.insert(pos, "$"); + pos = outdir_s.find('$', pos + 2); + } + + int outdir = add_string(outdir_s.c_str()); + + if (add_entry_direct(EW_CREATEDIR, outdir, 1) != PS_OK) { + return PS_ERROR; + } + +#ifdef _WIN32 + if (attrib) { + int ndc = add_string("."); + + DWORD attr = GetFileAttributes(local_dir.c_str()); + + if (attr != INVALID_FILE_ATTRIBUTES) + { + if (add_entry_direct(EW_SETFILEATTRIBUTES, ndc, attr) != PS_OK) + { + return PS_ERROR; + } + } + } +#endif + + return PS_OK; +} +#endif diff --git a/Source/strlist.cpp b/Source/strlist.cpp index f61fa0b..4af6959 100755 --- a/Source/strlist.cpp +++ b/Source/strlist.cpp @@ -1,204 +1,204 @@ -/*
- * strlist.cpp: Implementation of the StringList class.
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "strlist.h"
-
-int StringList::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 StringList::find(const char *str, int case_sensitive, int *idx/*=NULL*/) const // returns -1 if not found
-{
- const char *s=get();
- int ml=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 StringList::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 StringList::idx2pos(int idx) const
-{
- 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;
-}
-
-int StringList::getnum() const
-{
- char *s=(char*)gr.get();
- int ml=gr.getlen();
- int offs=0;
- int idx=0;
- while (offs < ml)
- {
- offs+=strlen(s+offs)+1;
- idx++;
- }
- return idx;
-}
-
-const char *StringList::get() const
-{
- return (const char*)gr.get();
-}
-
-int StringList::getlen() const
-{
- return gr.getlen();
-}
-
-// ==========
-// DefineList
-// ==========
-
-DefineList::~DefineList()
-{
- struct define *s=(struct define*)gr.get();
- int num=gr.getlen()/sizeof(struct define);
-
- for (int i=0; i<num; i++) {
- free(s[i].value);
- }
-}
-
-int DefineList::add(const char *name, const char *value/*=""*/)
-{
- int pos=SortedStringList<struct define>::add(name);
- if (pos == -1)
- {
- return 1;
- }
-
- char **newvalue=&(((struct define*)gr.get())[pos].value);
- *newvalue=(char*)malloc(strlen(value)+1);
- if (!(*newvalue))
- {
- extern FILE *g_output;
- extern int g_display_errors;
- extern void quit();
- if (g_display_errors)
- {
- fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%lu) failed.\n",(unsigned long)strlen(value)+1);
- fflush(g_output);
- }
- quit();
- }
- strcpy(*newvalue,value);
- return 0;
-}
-
-char *DefineList::find(const char *name)
-{
- int v=SortedStringList<struct define>::find(name);
- if (v==-1)
- {
- return NULL;
- }
- return ((struct define*)gr.get())[v].value;
-}
-
-// returns 0 on success, 1 otherwise
-int DefineList::del(const char *str)
-{
- int pos=SortedStringList<struct define>::find(str);
- if (pos==-1) return 1;
-
- struct define *db=(struct define *)gr.get();
- free(db[pos].value);
- delbypos(pos);
-
- return 0;
-}
-
-int DefineList::getnum()
-{
- return gr.getlen()/sizeof(define);
-}
-
-char *DefineList::getname(int num)
-{
- if ((unsigned int)getnum() <= (unsigned int)num)
- return 0;
- return ((struct define*)gr.get())[num].name;
-}
-
-char *DefineList::getvalue(int num)
-{
- if ((unsigned int)getnum() <= (unsigned int)num)
- return 0;
- return ((struct define*)gr.get())[num].value;
-}
-
-// ==============
-// FastStringList
-// ==============
-
-int FastStringList::add(const char *name, int case_sensitive/*=0*/)
-{
- int pos = SortedStringListND<struct string_t>::add(name, case_sensitive);
- if (pos == -1) return -1;
- return ((struct string_t*)gr.get())[pos].name;
-}
-
-char *FastStringList::get() const
-{
- return (char*)strings.get();
-}
-
-int FastStringList::getlen() const
-{
- return strings.getlen();
-}
-
-int FastStringList::getnum() const
-{
- return gr.getlen()/sizeof(struct string_t);
-}
-
+/* + * strlist.cpp: Implementation of the StringList class. + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "strlist.h" + +int StringList::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 StringList::find(const char *str, int case_sensitive, int *idx/*=NULL*/) const // returns -1 if not found +{ + const char *s=get(); + int ml=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 StringList::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 StringList::idx2pos(int idx) const +{ + 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; +} + +int StringList::getnum() const +{ + char *s=(char*)gr.get(); + int ml=gr.getlen(); + int offs=0; + int idx=0; + while (offs < ml) + { + offs+=strlen(s+offs)+1; + idx++; + } + return idx; +} + +const char *StringList::get() const +{ + return (const char*)gr.get(); +} + +int StringList::getlen() const +{ + return gr.getlen(); +} + +// ========== +// DefineList +// ========== + +DefineList::~DefineList() +{ + struct define *s=(struct define*)gr.get(); + int num=gr.getlen()/sizeof(struct define); + + for (int i=0; i<num; i++) { + free(s[i].value); + } +} + +int DefineList::add(const char *name, const char *value/*=""*/) +{ + int pos=SortedStringList<struct define>::add(name); + if (pos == -1) + { + return 1; + } + + char **newvalue=&(((struct define*)gr.get())[pos].value); + *newvalue=(char*)malloc(strlen(value)+1); + if (!(*newvalue)) + { + extern FILE *g_output; + extern int g_display_errors; + extern void quit(); + if (g_display_errors) + { + fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%lu) failed.\n",(unsigned long)strlen(value)+1); + fflush(g_output); + } + quit(); + } + strcpy(*newvalue,value); + return 0; +} + +char *DefineList::find(const char *name) +{ + int v=SortedStringList<struct define>::find(name); + if (v==-1) + { + return NULL; + } + return ((struct define*)gr.get())[v].value; +} + +// returns 0 on success, 1 otherwise +int DefineList::del(const char *str) +{ + int pos=SortedStringList<struct define>::find(str); + if (pos==-1) return 1; + + struct define *db=(struct define *)gr.get(); + free(db[pos].value); + delbypos(pos); + + return 0; +} + +int DefineList::getnum() +{ + return gr.getlen()/sizeof(define); +} + +char *DefineList::getname(int num) +{ + if ((unsigned int)getnum() <= (unsigned int)num) + return 0; + return ((struct define*)gr.get())[num].name; +} + +char *DefineList::getvalue(int num) +{ + if ((unsigned int)getnum() <= (unsigned int)num) + return 0; + return ((struct define*)gr.get())[num].value; +} + +// ============== +// FastStringList +// ============== + +int FastStringList::add(const char *name, int case_sensitive/*=0*/) +{ + int pos = SortedStringListND<struct string_t>::add(name, case_sensitive); + if (pos == -1) return -1; + return ((struct string_t*)gr.get())[pos].name; +} + +char *FastStringList::get() const +{ + return (char*)strings.get(); +} + +int FastStringList::getlen() const +{ + return strings.getlen(); +} + +int FastStringList::getnum() const +{ + return gr.getlen()/sizeof(struct string_t); +} + diff --git a/Source/strlist.h b/Source/strlist.h index 0c2a633..dd08855 100755 --- a/Source/strlist.h +++ b/Source/strlist.h @@ -1,258 +1,258 @@ -/*
- * strlist.h: Implementation of the StringList class.
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _STRLIST_H_
-#define _STRLIST_H_
-
-#include "Platform.h"
-#include <cstdio>
-#include "growbuf.h"
-
-class StringList
-{
-private: // don't copy instances
- StringList(const StringList&);
- void operator=(const StringList&);
-
-public:
- StringList() {}
- ~StringList() {}
-
- int add(const char *str, int case_sensitive);
- // use 2 for case sensitive end-of-string matches too
- int find(const char *str, int case_sensitive, int *idx=NULL) const; // returns -1 if not found
- void delbypos(int pos);
- int idx2pos(int idx) const;
- int getnum() const;
- const char *get() const;
- int getlen() const;
-
-private:
- GrowBuf gr;
-};
-
-template <class T>
-class SortedStringList
-{
- public:
- virtual ~SortedStringList()
- {
- T *s=(T*)gr.get();
- size_t num=gr.getlen()/sizeof(T);
-
- for (size_t i=0; i<num; i++) {
- free(s[i].name);
- }
- }
-
- // returns -1 when name already exists and pos if added
- int add(const char *name, int case_sensitive=0)
- {
- T newstruct={0,};
- int pos=find(name,case_sensitive,1);
- if (pos==-1) return -1;
- newstruct.name=(char*)malloc(strlen(name)+1);
- if (!newstruct.name)
- {
- extern FILE *g_output;
- extern int g_display_errors;
- extern void quit();
- if (g_display_errors)
- {
- fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%lu) failed.\n",(unsigned long)strlen(name)+1);
- fflush(g_output);
- }
- quit();
- }
- strcpy(newstruct.name,name);
- gr.add(&newstruct,sizeof(T));
-
- T *s=(T*)gr.get();
- memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T)));
- memcpy(s+pos,&newstruct,sizeof(T));
-
- return pos;
- }
-
- // returns -1 if not found, position if found
- // if returnbestpos=1 returns -1 if found, best pos to insert if not found
- int find(const char *str, int case_sensitive=0, int returnbestpos=0)
- {
- T *data=(T *)gr.get();
- int ul=gr.getlen()/sizeof(T);
- int ll=0;
- int nextpos=(ul+ll)/2;
-
- while (ul > ll)
- {
- int res;
- if (case_sensitive)
- res=strcmp(str, data[nextpos].name);
- else
- res=stricmp(str, data[nextpos].name);
- if (res==0) return returnbestpos ? -1 : nextpos;
- if (res<0) ul=nextpos;
- else ll=nextpos+1;
- nextpos=(ul+ll)/2;
- }
-
- return returnbestpos ? nextpos : -1;
- }
-
- // returns 0 on success, 1 otherwise
- int del(const char *str, int case_sensitive=0)
- {
- int pos=find(str, case_sensitive);
- if (pos==-1) return 1;
-
- delbypos(pos);
-
- return 0;
- }
-
- void delbypos(int pos)
- {
- T *db=(T *)gr.get();
- free(db[pos].name);
- memmove(db+pos,db+pos+1,gr.getlen()-(pos*sizeof(T))-sizeof(T));
- gr.resize(gr.getlen()-sizeof(T));
- }
-
- protected:
- TinyGrowBuf gr;
-};
-
-#define mymin(x, y) ((x < y) ? x : y)
-
-template <class T>
-class SortedStringListND // no delete - can be placed in GrowBuf
-{
- public:
- SortedStringListND() { }
- virtual ~SortedStringListND() { }
-
- // returns -1 when name already exists and pos if added
- int add(const char *name, int case_sensitive=0, int alwaysreturnpos=0)
- {
- int where=0;
- T newstruct={0,};
- int pos=find(name,-1,case_sensitive,1,&where);
- if (pos==-1) return alwaysreturnpos ? where : -1;
- newstruct.name=strings.add(name,strlen(name)+1);
-
- gr.add(&newstruct,sizeof(T));
- T *s=(T*)gr.get();
- memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T)));
- memcpy(s+pos,&newstruct,sizeof(T));
-
- return pos;
- }
-
- // returns -1 if not found, position if found
- // if returnbestpos=1 returns -1 if found, best pos to insert if not found
- // if n_chars equal to -1 all string is tested
- int find(const char *str, int n_chars=-1, int case_sensitive=0, int returnbestpos=0, int *where=0)
- {
- T *data=(T *)gr.get();
- int ul=gr.getlen()/sizeof(T);
- int ll=0;
- int nextpos=(ul+ll)/2;
-
- while (ul > ll)
- {
- int res;
- const char *pCurr = (char*)strings.get() + data[nextpos].name;
- if (n_chars < 0)
- {
- if (case_sensitive)
- res = strcmp(str, pCurr);
- else
- res = stricmp(str, pCurr);
- }
- else
- {
- if (case_sensitive)
- res=strncmp(str, pCurr, mymin((unsigned int) n_chars, strlen(pCurr)));
- else
- res=strnicmp(str, pCurr, mymin((unsigned int) n_chars, strlen(pCurr)));
- if (res == 0 && n_chars != -1 && (unsigned int) n_chars != strlen(pCurr))
- res = n_chars - strlen(pCurr);
- }
-
- if (res==0)
- {
- if (where) *where = nextpos;
- return returnbestpos ? (case_sensitive!=-1 ? -1 : nextpos) : nextpos;
- }
- if (res<0) ul=nextpos;
- else ll=nextpos+1;
- nextpos=(ul+ll)/2;
- }
-
- return returnbestpos ? nextpos : -1;
- }
-
- protected:
- TinyGrowBuf gr;
- GrowBuf strings;
-};
-
-struct define {
- char *name;
- char *value;
-};
-
-class DefineList : public SortedStringList<struct define>
-{
- private: // don't copy instances
- DefineList(const DefineList&);
- void operator=(const DefineList&);
-
- public:
- DefineList() {} // VC6 complains otherwise
- virtual ~DefineList();
-
- int add(const char *name, const char *value="");
- char *find(const char *name);
-
- // returns 0 on success, 1 otherwise
- int del(const char *str);
- int getnum();
- char *getname(int num);
- char *getvalue(int num);
-};
-
-struct string_t {
- int name;
-};
-
-class FastStringList : public SortedStringListND<struct string_t>
-{
- private: // don't copy instances
- FastStringList(const FastStringList&);
- void operator=(const FastStringList&);
-
- public:
- FastStringList() {} // VC6 complains otherwise
- virtual ~FastStringList() {}
-
- int add(const char *name, int case_sensitive=0);
- char *get() const;
- int getlen() const;
- int getnum() const;
-};
-
-#endif//_STRLIST_H_
+/* + * strlist.h: Implementation of the StringList class. + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _STRLIST_H_ +#define _STRLIST_H_ + +#include "Platform.h" +#include <cstdio> +#include "growbuf.h" + +class StringList +{ +private: // don't copy instances + StringList(const StringList&); + void operator=(const StringList&); + +public: + StringList() {} + ~StringList() {} + + int add(const char *str, int case_sensitive); + // use 2 for case sensitive end-of-string matches too + int find(const char *str, int case_sensitive, int *idx=NULL) const; // returns -1 if not found + void delbypos(int pos); + int idx2pos(int idx) const; + int getnum() const; + const char *get() const; + int getlen() const; + +private: + GrowBuf gr; +}; + +template <class T> +class SortedStringList +{ + public: + virtual ~SortedStringList() + { + T *s=(T*)gr.get(); + size_t num=gr.getlen()/sizeof(T); + + for (size_t i=0; i<num; i++) { + free(s[i].name); + } + } + + // returns -1 when name already exists and pos if added + int add(const char *name, int case_sensitive=0) + { + T newstruct={0,}; + int pos=find(name,case_sensitive,1); + if (pos==-1) return -1; + newstruct.name=(char*)malloc(strlen(name)+1); + if (!newstruct.name) + { + extern FILE *g_output; + extern int g_display_errors; + extern void quit(); + if (g_display_errors) + { + fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%lu) failed.\n",(unsigned long)strlen(name)+1); + fflush(g_output); + } + quit(); + } + strcpy(newstruct.name,name); + gr.add(&newstruct,sizeof(T)); + + T *s=(T*)gr.get(); + memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T))); + memcpy(s+pos,&newstruct,sizeof(T)); + + return pos; + } + + // returns -1 if not found, position if found + // if returnbestpos=1 returns -1 if found, best pos to insert if not found + int find(const char *str, int case_sensitive=0, int returnbestpos=0) + { + T *data=(T *)gr.get(); + int ul=gr.getlen()/sizeof(T); + int ll=0; + int nextpos=(ul+ll)/2; + + while (ul > ll) + { + int res; + if (case_sensitive) + res=strcmp(str, data[nextpos].name); + else + res=stricmp(str, data[nextpos].name); + if (res==0) return returnbestpos ? -1 : nextpos; + if (res<0) ul=nextpos; + else ll=nextpos+1; + nextpos=(ul+ll)/2; + } + + return returnbestpos ? nextpos : -1; + } + + // returns 0 on success, 1 otherwise + int del(const char *str, int case_sensitive=0) + { + int pos=find(str, case_sensitive); + if (pos==-1) return 1; + + delbypos(pos); + + return 0; + } + + void delbypos(int pos) + { + T *db=(T *)gr.get(); + free(db[pos].name); + memmove(db+pos,db+pos+1,gr.getlen()-(pos*sizeof(T))-sizeof(T)); + gr.resize(gr.getlen()-sizeof(T)); + } + + protected: + TinyGrowBuf gr; +}; + +#define mymin(x, y) ((x < y) ? x : y) + +template <class T> +class SortedStringListND // no delete - can be placed in GrowBuf +{ + public: + SortedStringListND() { } + virtual ~SortedStringListND() { } + + // returns -1 when name already exists and pos if added + int add(const char *name, int case_sensitive=0, int alwaysreturnpos=0) + { + int where=0; + T newstruct={0,}; + int pos=find(name,-1,case_sensitive,1,&where); + if (pos==-1) return alwaysreturnpos ? where : -1; + newstruct.name=strings.add(name,strlen(name)+1); + + gr.add(&newstruct,sizeof(T)); + T *s=(T*)gr.get(); + memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T))); + memcpy(s+pos,&newstruct,sizeof(T)); + + return pos; + } + + // returns -1 if not found, position if found + // if returnbestpos=1 returns -1 if found, best pos to insert if not found + // if n_chars equal to -1 all string is tested + int find(const char *str, int n_chars=-1, int case_sensitive=0, int returnbestpos=0, int *where=0) + { + T *data=(T *)gr.get(); + int ul=gr.getlen()/sizeof(T); + int ll=0; + int nextpos=(ul+ll)/2; + + while (ul > ll) + { + int res; + const char *pCurr = (char*)strings.get() + data[nextpos].name; + if (n_chars < 0) + { + if (case_sensitive) + res = strcmp(str, pCurr); + else + res = stricmp(str, pCurr); + } + else + { + if (case_sensitive) + res=strncmp(str, pCurr, mymin((unsigned int) n_chars, strlen(pCurr))); + else + res=strnicmp(str, pCurr, mymin((unsigned int) n_chars, strlen(pCurr))); + if (res == 0 && n_chars != -1 && (unsigned int) n_chars != strlen(pCurr)) + res = n_chars - strlen(pCurr); + } + + if (res==0) + { + if (where) *where = nextpos; + return returnbestpos ? (case_sensitive!=-1 ? -1 : nextpos) : nextpos; + } + if (res<0) ul=nextpos; + else ll=nextpos+1; + nextpos=(ul+ll)/2; + } + + return returnbestpos ? nextpos : -1; + } + + protected: + TinyGrowBuf gr; + GrowBuf strings; +}; + +struct define { + char *name; + char *value; +}; + +class DefineList : public SortedStringList<struct define> +{ + private: // don't copy instances + DefineList(const DefineList&); + void operator=(const DefineList&); + + public: + DefineList() {} // VC6 complains otherwise + virtual ~DefineList(); + + int add(const char *name, const char *value=""); + char *find(const char *name); + + // returns 0 on success, 1 otherwise + int del(const char *str); + int getnum(); + char *getname(int num); + char *getvalue(int num); +}; + +struct string_t { + int name; +}; + +class FastStringList : public SortedStringListND<struct string_t> +{ + private: // don't copy instances + FastStringList(const FastStringList&); + void operator=(const FastStringList&); + + public: + FastStringList() {} // VC6 complains otherwise + virtual ~FastStringList() {} + + int add(const char *name, int case_sensitive=0); + char *get() const; + int getlen() const; + int getnum() const; +}; + +#endif//_STRLIST_H_ diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 2f38aa7..7d9ee4b 100755 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -1,397 +1,397 @@ -/*
- * tokens.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.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;
- int placement; // where the token can be placed
-} tokenType;
-
-
-static tokenType tokenlist[TOK__LAST] =
-{
-{TOK_ABORT,"Abort",0,1,"[message]",TP_CODE},
-{TOK_ADDBRANDINGIMAGE,"AddBrandingImage",2,1,"(top|left|bottom|right) (height|width) [padding]",TP_GLOBAL},
-{TOK_ADDSIZE,"AddSize",1,0,"size_to_add_to_section_in_kb",TP_SEC},
-{TOK_AUTOCLOSE,"AutoCloseWindow",1,0,"(false|true)",TP_GLOBAL},
-{TOK_BGFONT,"BGFont",0,6,"[font_face [height [wieght] [/ITALIC] [/UNDERLINE] [/STRIKE]]]",TP_GLOBAL},
-{TOK_BGGRADIENT,"BGGradient",0,3,"(off | [top_color [bottom_color [text_color]]])",TP_GLOBAL},
-{TOK_BRANDINGTEXT,"BrandingText",1,1,"[/TRIM(LEFT|RIGHT|CENTER)] installer_text",TP_GLOBAL},
-{TOK_BRINGTOFRONT,"BringToFront",0,0,"",TP_CODE},
-{TOK_CALL,"Call",1,0,"function_name | [:label_name]",TP_CODE},
-{TOK_CALLINSTDLL,"CallInstDLL",2,1,"dll_path_on_target.dll [/NOUNLOAD] function",TP_CODE},
-{TOK_CAPTION,"Caption",1,0,"installer_caption",TP_GLOBAL|TP_PAGEEX},
-{TOK_CHANGEUI,"ChangeUI",2,0,"(all|dlg_id) ui_file.exe",TP_GLOBAL},
-{TOK_CLEARERRORS,"ClearErrors",0,0,"",TP_CODE},
-{TOK_COMPTEXT,"ComponentText",0,3,"[component_page_description] [component_subtext1] [component_subtext2]",TP_PG},
-{TOK_GETDLLVERSION,"GetDLLVersion",3,0,"filename $(user_var: high output) $(user_var: low output)",TP_CODE},
-{TOK_GETDLLVERSIONLOCAL,"GetDLLVersionLocal",3,0,"localfilename $(user_var: high output) $(user_var: low output)",TP_CODE},
-{TOK_GETFILETIME,"GetFileTime",3,0,"file $(user_var: high output) $(user_var: low output)",TP_CODE},
-{TOK_GETFILETIMELOCAL,"GetFileTimeLocal",3,0,"localfile $(user_var: high output) $(user_var: low output)",TP_CODE},
-{TOK_COPYFILES,"CopyFiles",2,3,"[/SILENT] [/FILESONLY] source_path destination_path [total_size_in_kb]",TP_CODE},
-{TOK_CRCCHECK,"CRCCheck",1,0,"(on|force|off)",TP_GLOBAL},
-{TOK_CREATEDIR,"CreateDirectory",1,0,"directory_name",TP_CODE},
-{TOK_CREATEFONT,"CreateFont",2,5,"$(user_var: handle output) face_name [height wieght /ITALIC /UNDERLINE /STRIKE]",TP_CODE},
-{TOK_CREATESHORTCUT,"CreateShortCut",2,6,"shortcut_name.lnk shortcut_target [parameters [icon_file [icon index [showmode [hotkey [comment]]]]]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED)\n hotkey=(ALT|CONTROL|EXT|SHIFT)|(F1-F24|A-Z)",TP_CODE},
-{TOK_DBOPTIMIZE,"SetDatablockOptimize",1,0,"(off|on)",TP_ALL},
-{TOK_DELETEINISEC,"DeleteINISec",2,0,"ini_file section_name",TP_CODE},
-{TOK_DELETEINISTR,"DeleteINIStr",3,0,"ini_file section_name entry_name",TP_CODE},
-{TOK_DELETEREGKEY,"DeleteRegKey",2,1,"[/ifempty] root_key subkey\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_DELETEREGVALUE,"DeleteRegValue",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_DELETE,"Delete",1,1,"[/REBOOTOK] filespec",TP_CODE},
-{TOK_DETAILPRINT,"DetailPrint",1,0,"message",TP_CODE},
-{TOK_DIRTEXT,"DirText",0,4,"[directory_page_description] [directory_page_subtext] [browse_button_text] [browse_dlg_text]",TP_PG},
-//{TOK_DIRSHOW,"DirShow",1,0,"(show|hide)",TP_PG},
-{TOK_DIRSHOW,"DirShow",0,0,"doesn't currently work",TP_ALL},
-{TOK_DIRVAR,"DirVar",1,0,"$(user_var: dir in/out))",TP_PAGEEX},
-{TOK_DIRVERIFY,"DirVerify",1,0,"auto|leave",TP_PAGEEX},
-{TOK_GETINSTDIRERROR,"GetInstDirError",1,0,"$(user_var: error output)",TP_CODE},
-{TOK_ROOTDIRINST,"AllowRootDirInstall",1,0,"(true|false)",TP_GLOBAL},
-{TOK_CHECKBITMAP,"CheckBitmap",1,0,"local_bitmap.bmp",TP_GLOBAL},
-{TOK_ENABLEWINDOW,"EnableWindow",2,0,"hwnd (1|0)",TP_CODE},
-{TOK_ENUMREGKEY,"EnumRegKey",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_ENUMREGVAL,"EnumRegValue",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_EXCH,"Exch",0,1,"[$(user_var)] | [stack_item_index]",TP_CODE},
-{TOK_EXEC,"Exec",1,0,"command_line",TP_CODE},
-{TOK_EXECWAIT,"ExecWait",1,1,"command_line [$(user_var: return value)]",TP_CODE},
-{TOK_EXECSHELL,"ExecShell",2,2,"(open|print|etc) command_line [parameters [showmode]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_HIDE)",TP_CODE},
-{TOK_EXPANDENVSTRS,"ExpandEnvStrings",2,0,"$(user_var: output) string",TP_CODE},
-{TOK_FINDWINDOW,"FindWindow",2,3,"$(user_var: handle output) WindowClass [WindowTitle] [Window_Parent] [Child_After]",TP_CODE},
-{TOK_FINDCLOSE,"FindClose",1,0,"$(user_var: handle input)",TP_CODE},
-{TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec",TP_CODE},
-{TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)",TP_CODE},
-{TOK_FILE,"File",1,-1,"[/nonfatal] [/a] ([/r] [/x filespec [...]] filespec [...] |\n /oname=outfile one_file_only)",TP_CODE},
-{TOK_FILEBUFSIZE,"FileBufSize",1,0,"buf_size_mb",TP_ALL},
-{TOK_FLUSHINI,"FlushINI",1,0,"ini_file",TP_CODE},
-{TOK_RESERVEFILE,"ReserveFile",1,-1,"[/nonfatal] [/r] [/x filespec [...]] file [file...]",TP_ALL},
-{TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)",TP_CODE},
-{TOK_FILEERRORTEXT,"FileErrorText",0,2,"[text (can contain $0)] [text without ignore (can contain $0)]",TP_GLOBAL},
-{TOK_FILEOPEN,"FileOpen",3,0,"$(user_var: handle output) filename openmode\n openmode=r|w|a",TP_CODE},
-{TOK_FILEREAD,"FileRead",2,1,"$(user_var: handle input) $(user_var: text output) [maxlen]",TP_CODE},
-{TOK_FILEWRITE,"FileWrite",2,0,"$(user_var: handle input) text",TP_CODE},
-{TOK_FILEREADBYTE,"FileReadByte",2,0,"$(user_var: handle input) $(user_var: bytevalue output)",TP_CODE},
-{TOK_FILEWRITEBYTE,"FileWriteByte",2,0,"$(user_var: handle input) bytevalue",TP_CODE},
-{TOK_FILESEEK,"FileSeek",2,2,"$(user_var: handle input) offset [mode] [$(user_var: new position output)]\n mode=SET|CUR|END",TP_CODE},
-{TOK_FUNCTION,"Function",1,0,"function_name",TP_GLOBAL},
-{TOK_FUNCTIONEND,"FunctionEnd",0,0,"",TP_FUNC},
-{TOK_GETDLGITEM,"GetDlgItem",3,0,"$(user_var: handle output) dialog item_id",TP_CODE},
-{TOK_GETFULLPATHNAME,"GetFullPathName",2,1,"[/SHORT] $(user_var: result) path_or_file",TP_CODE},
-{TOK_GETTEMPFILENAME,"GetTempFileName",1,1,"$(user_var: name output) [base_dir]",TP_CODE},
-{TOK_HIDEWINDOW,"HideWindow",0,0,"",TP_CODE},
-{TOK_ICON,"Icon",1,0,"local_icon.ico",TP_GLOBAL},
-{TOK_IFABORT,"IfAbort",1,1,"label_to_goto_if_abort [label_to_goto_if_no_abort]",TP_CODE},
-{TOK_IFERRORS,"IfErrors",1,1,"label_to_goto_if_errors [label_to_goto_if_no_errors]",TP_CODE},
-{TOK_IFFILEEXISTS,"IfFileExists",2,1,"filename label_to_goto_if_file_exists [label_to_goto_otherwise]",TP_CODE},
-{TOK_IFREBOOTFLAG,"IfRebootFlag",1,1,"jump_if_set [jump_if_not_set]",TP_CODE},
-{TOK_IFSILENT,"IfSilent",1,1,"jump_if_silent [jump_if_not_silent]",TP_CODE},
-{TOK_INSTALLDIRREGKEY,"InstallDirRegKey",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)",TP_GLOBAL},
-{TOK_INSTCOLORS,"InstallColors",1,1,"(/windows | (foreground_color background_color))",TP_GLOBAL},
-{TOK_INSTDIR,"InstallDir",1,0,"default_install_directory",TP_GLOBAL},
-{TOK_INSTPROGRESSFLAGS,"InstProgressFlags",0,-1,"[flag [...]]\n flag={smooth|colored}",TP_GLOBAL},
-{TOK_INSTTYPE,"InstType",1,0,"[un.]install_type_name | /NOCUSTOM | /CUSTOMSTRING=str | /COMPONENTSONLYONCUSTOM",TP_GLOBAL},
-{TOK_INTOP,"IntOp",3,1,"$(user_var: result) val1 OP [val2]\n OP=(+ - * / % | & ^ ~ ! || && << >>)",TP_CODE},
-{TOK_INTCMP,"IntCmp",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]",TP_CODE},
-{TOK_INTCMPU,"IntCmpU",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]",TP_CODE},
-{TOK_INTFMT,"IntFmt",3,0,"$(user_var: output) format_string input",TP_CODE},
-{TOK_ISWINDOW,"IsWindow",2,1,"hwnd jump_if_window [jump_if_not_window]",TP_CODE},
-{TOK_GOTO,"Goto",1,0,"label",TP_CODE},
-{TOK_LANGSTRING,"LangString",3,0,"[un.]name lang_id string",TP_GLOBAL},
-{TOK_LANGSTRINGUP,"LangStringUP",0,0,"obsolete, use LangString.",TP_ALL},
-{TOK_LICENSEDATA,"LicenseData",1,0,"local_file_that_has_license_text | license_lang_string",TP_PG},
-{TOK_LICENSEFORCESELECTION,"LicenseForceSelection",1,2,"(checkbox [accept_text] | radiobuttons [accept_text] [decline_text] | off)",TP_PG},
-{TOK_LICENSELANGSTRING,"LicenseLangString",3,0,"name lang_id license_path",TP_GLOBAL},
-{TOK_LICENSETEXT,"LicenseText",1,1,"license_page_description [license_button_text]",TP_PG},
-{TOK_LICENSEBKCOLOR,"LicenseBkColor",1,0,"background_color",TP_GLOBAL},
-{TOK_LOADNLF,"LoadLanguageFile",1,0,"language.nlf",TP_GLOBAL},
-{TOK_LOGSET,"LogSet",1,0,"on|off",TP_CODE},
-{TOK_LOGTEXT,"LogText",1,0,"text",TP_CODE},
-{TOK_MESSAGEBOX,"MessageBox",2,6,"mode messagebox_text [/SD return] [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_USERICON|MB_TOPMOST|MB_SETFOREGROUND|MB_RIGHT",TP_CODE},
-{TOK_NOP,"Nop",0,0,"",TP_CODE},
-{TOK_NAME,"Name",1,1,"installer_name installer_name_doubled_ampersands",TP_GLOBAL},
-{TOK_OUTFILE,"OutFile",1,0,"install_output.exe",TP_GLOBAL},
-#ifdef NSIS_SUPPORT_CODECALLBACKS
-{TOK_PAGE,"Page",1,4,"((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles|uninstConfirm) [pre_function] [show_function] [leave_function])) [/ENABLECANCEL]",TP_GLOBAL},
-#else
-{TOK_PAGE,"Page",1,1,"license|components|directory|instfiles|uninstConfirm [/ENABLECANCEL]",TP_GLOBAL},
-#endif
-{TOK_PAGECALLBACKS,"PageCallbacks",0,3,"([creator_function] [leave_function]) | ([pre_function] [show_function] [leave_function])",TP_PAGEEX},
-{TOK_PAGEEX,"PageEx",1,0,"[un.](custom|uninstConfirm|license|components|directory|instfiles)",TP_GLOBAL},
-{TOK_PAGEEXEND,"PageExEnd",0,0,"",TP_PAGEEX},
-{TOK_POP,"Pop",1,0,"$(user_var: output)",TP_CODE},
-{TOK_PUSH,"Push",1,0,"string",TP_CODE},
-{TOK_QUIT,"Quit",0,0,"",TP_CODE},
-{TOK_READINISTR,"ReadINIStr",4,0,"$(user_var: output) ini_file section entry_name",TP_CODE},
-{TOK_READREGDWORD,"ReadRegDWORD",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_READREGSTR,"ReadRegStr",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_READENVSTR,"ReadEnvStr",2,0,"$(user_var: output) name",TP_CODE},
-{TOK_REBOOT,"Reboot",0,0,"",TP_CODE},
-{TOK_REGDLL,"RegDLL",1,1,"dll_path_on_target.dll [entrypoint_symbol]",TP_CODE},
-{TOK_RENAME,"Rename",2,1,"[/REBOOTOK] source_file destination_file",TP_CODE},
-{TOK_RET,"Return",0,0,"",TP_CODE},
-{TOK_RMDIR,"RMDir",1,2,"[/r] [/REBOOTOK] directory_name",TP_CODE},
-{TOK_SECTION,"Section",0,3,"[/o] [-][un.][section_name] [section index output]",TP_GLOBAL},
-{TOK_SECTIONEND,"SectionEnd",0,0,"",TP_SEC},
-{TOK_SECTIONIN,"SectionIn",1,-1,"InstTypeIdx [InstTypeIdx [...]]",TP_SEC},
-{TOK_SUBSECTION,"SubSection",1,2,"deprecated - use SectionGroup",TP_GLOBAL},
-{TOK_SECTIONGROUP,"SectionGroup",1,2,"[/e] [un.]section_group_name [section index output]",TP_GLOBAL},
-{TOK_SUBSECTIONEND,"SubSectionEnd",0,0,"deprecated - use SectionGroupEnd",TP_GLOBAL},
-{TOK_SECTIONGROUPEND,"SectionGroupEnd",0,0,"",TP_GLOBAL},
-{TOK_SEARCHPATH,"SearchPath",2,0,"$(user_var: result) filename",TP_CODE},
-{TOK_SECTIONSETFLAGS,"SectionSetFlags",2,0,"section_index flags",TP_CODE},
-{TOK_SECTIONGETFLAGS,"SectionGetFlags",2,0,"section_index $(user_var: output flags)",TP_CODE},
-{TOK_SECTIONSETINSTTYPES,"SectionSetInstTypes",2,0,"section_index inst_types",TP_CODE},
-{TOK_SECTIONGETINSTTYPES,"SectionGetInstTypes",2,0,"section_index $(user_var: output inst_types)",TP_CODE},
-{TOK_SECTIONGETTEXT,"SectionGetText",2,0,"section_index $(user_var: output text)",TP_CODE},
-{TOK_SECTIONSETTEXT,"SectionSetText",2,0,"section_index text_string",TP_CODE},
-{TOK_SECTIONGETSIZE,"SectionGetSize",2,0,"section_index $(user_var: output size)",TP_CODE},
-{TOK_SECTIONSETSIZE,"SectionSetSize",2,0,"section_index new_size",TP_CODE},
-{TOK_GETCURINSTTYPE,"GetCurInstType",1,0,"$(user_var: output inst_type_idx)",TP_CODE},
-{TOK_SETCURINSTTYPE,"SetCurInstType",1,0,"inst_type_idx",TP_CODE},
-{TOK_INSTTYPESETTEXT,"InstTypeSetText",2,0,"insttype_index flags",TP_CODE},
-{TOK_INSTTYPEGETTEXT,"InstTypeGetText",2,0,"insttype_index $(user_var: output flags)",TP_CODE},
-{TOK_SENDMESSAGE,"SendMessage",4,2,"hwnd message [wparam|STR:wParam] [lparam|STR:lParam] [$(user_var: return value)] [/TIMEOUT=X]",TP_CODE},
-{TOK_SETAUTOCLOSE,"SetAutoClose",1,0,"(false|true)",TP_CODE},
-{TOK_SETCTLCOLORS,"SetCtlColors",2,2,"hwnd [/BRANDING] [text_color] [transparent|bg_color]",TP_CODE},
-{TOK_SETBRANDINGIMAGE,"SetBrandingImage",1,2,"[/IMGID=image_item_id_in_dialog] [/RESIZETOFIT] bitmap.bmp",TP_CODE},
-{TOK_SETCOMPRESS,"SetCompress",1,0,"(off|auto|force)",TP_ALL},
-{TOK_SETCOMPRESSOR,"SetCompressor",1,2,"[/FINAL] [/SOLID] (zlib|bzip2|lzma)",TP_GLOBAL},
-{TOK_SETCOMPRESSORDICTSIZE,"SetCompressorDictSize",1,0,"dict_size_mb",TP_ALL},
-{TOK_SETCOMPRESSIONLEVEL,"SetCompressionLevel",1,0,"level_0-9",TP_ALL},
-{TOK_SETDATESAVE,"SetDateSave",1,0,"(off|on)",TP_ALL},
-{TOK_SETDETAILSVIEW,"SetDetailsView",1,0,"(hide|show)",TP_CODE},
-{TOK_SETDETAILSPRINT,"SetDetailsPrint",1,0,"(none|listonly|textonly|both)",TP_CODE},
-{TOK_SETERRORS,"SetErrors",0,0,"",TP_CODE},
-{TOK_SETERRORLEVEL,"SetErrorLevel",1,0,"error_level",TP_CODE},
-{TOK_GETERRORLEVEL,"GetErrorLevel",1,0,"$(user_var: output)",TP_CODE},
-{TOK_SETFILEATTRIBUTES,"SetFileAttributes",2,0,"file attribute[|attribute[...]]\n attribute=(NORMAL|ARCHIVE|HIDDEN|OFFLINE|READONLY|SYSTEM|TEMPORARY|0)",TP_CODE},
-{TOK_SETFONT,"SetFont",2,1,"[/LANG=lang_id] font_face_name font_size",TP_GLOBAL},
-{TOK_SETOUTPATH,"SetOutPath",1,0,"output_path",TP_CODE},
-{TOK_SETOVERWRITE,"SetOverwrite",1,0,"on|off|try|ifnewer|ifdiff",TP_ALL},
-{TOK_SETPLUGINUNLOAD,"SetPluginUnload",1,0,"(manual|alwaysoff)",TP_ALL},
-{TOK_SETREBOOTFLAG,"SetRebootFlag",1,0,"true|false",TP_CODE},
-{TOK_SETREGVIEW,"SetRegView",1,0,"32|64|lastused",TP_CODE},
-{TOK_SETSHELLVARCONTEXT,"SetShellVarContext",1,0,"all|current",TP_CODE},
-{TOK_SETSILENT,"SetSilent",1,0,"silent|normal",TP_CODE},
-{TOK_SHOWDETAILS,"ShowInstDetails",1,0,"(hide|show|nevershow)",TP_GLOBAL},
-{TOK_SHOWDETAILSUNINST,"ShowUninstDetails",1,0,"(hide|show|nevershow)",TP_GLOBAL},
-{TOK_SHOWWINDOW,"ShowWindow",2,0,"hwnd show_state",TP_CODE},
-{TOK_SILENTINST,"SilentInstall",1,0,"(normal|silent|silentlog)",TP_GLOBAL},
-{TOK_SILENTUNINST,"SilentUnInstall",1,0,"(normal|silent)",TP_GLOBAL},
-{TOK_SLEEP,"Sleep",1,0,"sleep_time_in_ms",TP_CODE},
-{TOK_STRCMP,"StrCmp",3,1,"str1 str2 label_to_goto_if_equal [label_to_goto_if_not]",TP_CODE},
-{TOK_STRCMPS,"StrCmpS",3,1,"str1 str2 label_to_goto_if_equal [label_to_goto_if_not]",TP_CODE},
-{TOK_STRCPY,"StrCpy",2,2,"$(user_var: output) str [maxlen] [startoffset]",TP_CODE},
-{TOK_STRLEN,"StrLen",2,0,"$(user_var: length output) str",TP_CODE},
-{TOK_SUBCAPTION,"SubCaption",2,0,"page_number(0-4) new_subcaption",TP_GLOBAL},
-{TOK_UNINSTALLEXENAME,"UninstallExeName",0,0,"no longer supported, use WriteUninstaller from section.",TP_ALL},
-{TOK_UNINSTCAPTION,"UninstallCaption",1,0,"uninstaller_caption",TP_GLOBAL},
-{TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico",TP_GLOBAL},
-#ifdef NSIS_SUPPORT_CODECALLBACKS
-{TOK_UNINSTPAGE,"UninstPage",1,4,"((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles|uninstConfirm) [pre_function] [show_function] [leave_function])) [/ENABLECANCEL]",TP_GLOBAL},
-#else
-{TOK_UNINSTPAGE,"UninstPage",1,1,"license|components|directory|instfiles|uninstConfirm [/ENABLECANCEL]",TP_GLOBAL},
-#endif
-{TOK_UNINSTTEXT,"UninstallText",1,1,"Text_to_go_on_uninstall_page [subtext]",TP_PG},
-{TOK_UNINSTSUBCAPTION,"UninstallSubCaption",2,0,"page_number(0-2) new_subcaption",TP_GLOBAL},
-{TOK_UNREGDLL,"UnRegDLL",1,0,"dll_path_on_target.dll",TP_CODE},
-{TOK_WINDOWICON,"WindowIcon",1,0,"on|off",TP_GLOBAL},
-{TOK_WRITEINISTR,"WriteINIStr",4,0,"ini_file section_name entry_name new_value",TP_CODE},
-{TOK_WRITEREGBIN,"WriteRegBin",4,0,"rootkey subkey entry_name hex_string_like_12848412AB\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_WRITEREGDWORD,"WriteRegDWORD",4,0,"rootkey subkey entry_name new_value_dword\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_WRITEREGSTR,"WriteRegStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_WRITEREGEXPANDSTR,"WriteRegExpandStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE},
-{TOK_WRITEUNINSTALLER,"WriteUninstaller",1,0,"uninstall_exe_name",TP_CODE},
-{TOK_XPSTYLE, "XPStyle",1,0,"(on|off)",TP_GLOBAL},
-{TOK_REQEXECLEVEL, "RequestExecutionLevel",1,0,"none|user|highest|admin",TP_GLOBAL},
-{TOK_P_PACKEXEHEADER,"!packhdr",2,0,"temp_file_name command_line_to_compress_that_temp_file",TP_ALL},
-{TOK_P_SYSTEMEXEC,"!system",1,2,"command [<|>|<>|=) retval]",TP_ALL},
-{TOK_P_EXECUTE,"!execute",1,0,"command",TP_ALL},
-{TOK_P_ADDINCLUDEDIR,"!AddIncludeDir",1,0,"dir",TP_ALL},
-{TOK_P_INCLUDE,"!include",1,1,"[/NONFATAL] filename.nsh",TP_ALL},
-{TOK_P_CD,"!cd",1,0,"absolute_or_relative_new_directory",TP_ALL},
-{TOK_P_IF,"!if",1,3,"[!] value [(==,!=,<=,<,>,>=,&&,||) value2] [...]",TP_ALL},
-{TOK_P_IFDEF,"!ifdef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL},
-{TOK_P_IFNDEF,"!ifndef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL},
-{TOK_P_ENDIF,"!endif",0,0,"",TP_ALL},
-{TOK_P_DEFINE,"!define",1,4,"([/date|/utcdate] symbol [value]) | (/math symbol val1 OP val2)\n OP=(+ - * / % & | ^)",TP_ALL},
-{TOK_P_UNDEF,"!undef",1,1,"symbol [value]",TP_ALL},
-{TOK_P_ELSE,"!else",0,-1,"[if[macro][n][def] ...]",TP_ALL},
-{TOK_P_ECHO,"!echo",1,0,"message",TP_ALL},
-{TOK_P_WARNING,"!warning",0,1,"[warning_message]",TP_ALL},
-{TOK_P_ERROR,"!error",0,1,"[error_message]",TP_ALL},
-
-{TOK_P_VERBOSE,"!verbose",1,0,"verbose_level | push | pop",TP_ALL},
-
-{TOK_P_MACRO,"!macro",1,-1,"macroname [parms ...]",TP_ALL},
-{TOK_P_MACROEND,"!macroend",0,0,"",TP_ALL},
-{TOK_P_INSERTMACRO,"!insertmacro",1,-1,"macroname [parms ...]",TP_ALL},
-{TOK_P_IFMACRODEF,"!ifmacrodef",1,-1,"macro [| macro2 [& macro3 [...]]]",TP_ALL},
-{TOK_P_IFMACRONDEF,"!ifmacrondef",1,-1,"macro [| macro2 [& macro3 [...]]]",TP_ALL},
-
-{TOK_P_TEMPFILE,"!tempfile",1,0,"symbol",TP_ALL},
-{TOK_P_DELFILE,"!delfile",1,0,"file",TP_ALL},
-{TOK_P_APPENDFILE,"!appendfile",2,0,"file appended_line",TP_ALL},
-
-{TOK_MISCBUTTONTEXT,"MiscButtonText",0,4,"[back button text] [next button text] [cancel button text] [close button text]",TP_GLOBAL},
-{TOK_DETAILSBUTTONTEXT,"DetailsButtonText",0,1,"[details button text]",TP_PG},
-{TOK_UNINSTBUTTONTEXT,"UninstallButtonText",0,1,"[uninstall button text]",TP_GLOBAL},
-{TOK_INSTBUTTONTEXT,"InstallButtonText",0,1,"[install button text]",TP_GLOBAL},
-{TOK_SPACETEXTS,"SpaceTexts",0,2,"none | ([space required text] [space available text])",TP_GLOBAL},
-{TOK_COMPLETEDTEXT,"CompletedText",0,1,"[completed text]",TP_PG},
-
-{TOK_GETFUNCTIONADDR,"GetFunctionAddress",2,0,"output function",TP_CODE},
-{TOK_GETLABELADDR,"GetLabelAddress",2,0,"output label",TP_CODE},
-{TOK_GETCURRENTADDR,"GetCurrentAddress",1,0,"output",TP_CODE},
-
-{TOK_PLUGINDIR,"!AddPluginDir",1,0,"new_plugin_directory",TP_ALL},
-{TOK_INITPLUGINSDIR,"InitPluginsDir",0,0,"",TP_CODE},
-// Added by ramon 23 May 2003
-{TOK_ALLOWSKIPFILES,"AllowSkipFiles",1,0,"(off|on)",TP_ALL},
-// Added by ramon 3 jun 2003
-{TOK_DEFVAR,"Var",1,1,"[/GLOBAL] var_name",TP_ALL},
-// Added by ramon 6 jun 2003
-{TOK_VI_ADDKEY,"VIAddVersionKey",2,1,"/LANG=lang_id keyname value",TP_GLOBAL},
-{TOK_VI_SETPRODUCTVERSION,"VIProductVersion",1,0,"[version_string_X.X.X.X]",TP_GLOBAL},
-{TOK_LOCKWINDOW,"LockWindow",1,0,"(on|off)",TP_CODE},
-};
-
-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);
- }
-
-}
-
-bool CEXEBuild::is_valid_token(char *s)
-{
- for (int x = 0; x < TOK__LAST; x ++)
- if (!stricmp(tokenlist[x].name,s))
- return true;
- return false;
-}
-
-int CEXEBuild::get_commandtoken(char *s, int *np, int *op, int *pos)
-{
- 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;
- *pos=x;
- return tokenlist[x].id;
- }
- return -1;
-}
-
-int CEXEBuild::GetCurrentTokenPlace()
-{
- if (build_cursection)
- {
- if (build_cursection_isfunc)
- {
- return TP_FUNC;
- }
- else
- {
- return TP_SEC;
- }
- }
-
- if (cur_page)
- return TP_PAGEEX;
-
- return TP_GLOBAL;
-}
-
-int CEXEBuild::IsTokenPlacedRight(int pos, char *tok)
-{
- if ((unsigned int) pos > (sizeof(tokenlist) / sizeof(tokenType)))
- return PS_OK;
-
- int tp = tokenlist[pos].placement;
- int cp = GetCurrentTokenPlace();
- if (tp & cp) {
- return PS_OK;
- }
- else {
- char err[1024];
- if (cp == TP_SEC) {
- strcpy(err, "Error: command %s not valid in Section\n");
- }
- else if (cp == TP_FUNC) {
- strcpy(err, "Error: command %s not valid in Function\n");
- }
- else if (cp == TP_PAGEEX) {
- strcpy(err, "Error: command %s not valid in PageEx\n");
- }
- else
- {
- strcpy(err, "Error: command %s not valid outside ");
- if (tp & TP_SEC)
- strcat(err, "Section");
- if (tp & TP_FUNC)
- {
- if (tp & TP_SEC)
- {
- if (tp & TP_PAGEEX)
- {
- strcat(err, ", ");
- }
- else
- {
- strcat(err, " or ");
- }
- }
- strcat(err, "Function");
- }
- if (tp & TP_PAGEEX)
- {
- if (tp & TP_CODE)
- {
- strcat(err, " or ");
- }
- strcat(err, "PageEx");
- }
- strcat(err, "\n");
- }
- ERROR_MSG(err, tok);
- return PS_ERROR;
- }
-}
+/* + * tokens.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.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; + int placement; // where the token can be placed +} tokenType; + + +static tokenType tokenlist[TOK__LAST] = +{ +{TOK_ABORT,"Abort",0,1,"[message]",TP_CODE}, +{TOK_ADDBRANDINGIMAGE,"AddBrandingImage",2,1,"(top|left|bottom|right) (height|width) [padding]",TP_GLOBAL}, +{TOK_ADDSIZE,"AddSize",1,0,"size_to_add_to_section_in_kb",TP_SEC}, +{TOK_AUTOCLOSE,"AutoCloseWindow",1,0,"(false|true)",TP_GLOBAL}, +{TOK_BGFONT,"BGFont",0,6,"[font_face [height [wieght] [/ITALIC] [/UNDERLINE] [/STRIKE]]]",TP_GLOBAL}, +{TOK_BGGRADIENT,"BGGradient",0,3,"(off | [top_color [bottom_color [text_color]]])",TP_GLOBAL}, +{TOK_BRANDINGTEXT,"BrandingText",1,1,"[/TRIM(LEFT|RIGHT|CENTER)] installer_text",TP_GLOBAL}, +{TOK_BRINGTOFRONT,"BringToFront",0,0,"",TP_CODE}, +{TOK_CALL,"Call",1,0,"function_name | [:label_name]",TP_CODE}, +{TOK_CALLINSTDLL,"CallInstDLL",2,1,"dll_path_on_target.dll [/NOUNLOAD] function",TP_CODE}, +{TOK_CAPTION,"Caption",1,0,"installer_caption",TP_GLOBAL|TP_PAGEEX}, +{TOK_CHANGEUI,"ChangeUI",2,0,"(all|dlg_id) ui_file.exe",TP_GLOBAL}, +{TOK_CLEARERRORS,"ClearErrors",0,0,"",TP_CODE}, +{TOK_COMPTEXT,"ComponentText",0,3,"[component_page_description] [component_subtext1] [component_subtext2]",TP_PG}, +{TOK_GETDLLVERSION,"GetDLLVersion",3,0,"filename $(user_var: high output) $(user_var: low output)",TP_CODE}, +{TOK_GETDLLVERSIONLOCAL,"GetDLLVersionLocal",3,0,"localfilename $(user_var: high output) $(user_var: low output)",TP_CODE}, +{TOK_GETFILETIME,"GetFileTime",3,0,"file $(user_var: high output) $(user_var: low output)",TP_CODE}, +{TOK_GETFILETIMELOCAL,"GetFileTimeLocal",3,0,"localfile $(user_var: high output) $(user_var: low output)",TP_CODE}, +{TOK_COPYFILES,"CopyFiles",2,3,"[/SILENT] [/FILESONLY] source_path destination_path [total_size_in_kb]",TP_CODE}, +{TOK_CRCCHECK,"CRCCheck",1,0,"(on|force|off)",TP_GLOBAL}, +{TOK_CREATEDIR,"CreateDirectory",1,0,"directory_name",TP_CODE}, +{TOK_CREATEFONT,"CreateFont",2,5,"$(user_var: handle output) face_name [height wieght /ITALIC /UNDERLINE /STRIKE]",TP_CODE}, +{TOK_CREATESHORTCUT,"CreateShortCut",2,6,"shortcut_name.lnk shortcut_target [parameters [icon_file [icon index [showmode [hotkey [comment]]]]]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED)\n hotkey=(ALT|CONTROL|EXT|SHIFT)|(F1-F24|A-Z)",TP_CODE}, +{TOK_DBOPTIMIZE,"SetDatablockOptimize",1,0,"(off|on)",TP_ALL}, +{TOK_DELETEINISEC,"DeleteINISec",2,0,"ini_file section_name",TP_CODE}, +{TOK_DELETEINISTR,"DeleteINIStr",3,0,"ini_file section_name entry_name",TP_CODE}, +{TOK_DELETEREGKEY,"DeleteRegKey",2,1,"[/ifempty] root_key subkey\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_DELETEREGVALUE,"DeleteRegValue",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_DELETE,"Delete",1,1,"[/REBOOTOK] filespec",TP_CODE}, +{TOK_DETAILPRINT,"DetailPrint",1,0,"message",TP_CODE}, +{TOK_DIRTEXT,"DirText",0,4,"[directory_page_description] [directory_page_subtext] [browse_button_text] [browse_dlg_text]",TP_PG}, +//{TOK_DIRSHOW,"DirShow",1,0,"(show|hide)",TP_PG}, +{TOK_DIRSHOW,"DirShow",0,0,"doesn't currently work",TP_ALL}, +{TOK_DIRVAR,"DirVar",1,0,"$(user_var: dir in/out))",TP_PAGEEX}, +{TOK_DIRVERIFY,"DirVerify",1,0,"auto|leave",TP_PAGEEX}, +{TOK_GETINSTDIRERROR,"GetInstDirError",1,0,"$(user_var: error output)",TP_CODE}, +{TOK_ROOTDIRINST,"AllowRootDirInstall",1,0,"(true|false)",TP_GLOBAL}, +{TOK_CHECKBITMAP,"CheckBitmap",1,0,"local_bitmap.bmp",TP_GLOBAL}, +{TOK_ENABLEWINDOW,"EnableWindow",2,0,"hwnd (1|0)",TP_CODE}, +{TOK_ENUMREGKEY,"EnumRegKey",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_ENUMREGVAL,"EnumRegValue",4,0,"$(user_var: output) rootkey subkey index\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_EXCH,"Exch",0,1,"[$(user_var)] | [stack_item_index]",TP_CODE}, +{TOK_EXEC,"Exec",1,0,"command_line",TP_CODE}, +{TOK_EXECWAIT,"ExecWait",1,1,"command_line [$(user_var: return value)]",TP_CODE}, +{TOK_EXECSHELL,"ExecShell",2,2,"(open|print|etc) command_line [parameters [showmode]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_HIDE)",TP_CODE}, +{TOK_EXPANDENVSTRS,"ExpandEnvStrings",2,0,"$(user_var: output) string",TP_CODE}, +{TOK_FINDWINDOW,"FindWindow",2,3,"$(user_var: handle output) WindowClass [WindowTitle] [Window_Parent] [Child_After]",TP_CODE}, +{TOK_FINDCLOSE,"FindClose",1,0,"$(user_var: handle input)",TP_CODE}, +{TOK_FINDFIRST,"FindFirst",3,0,"$(user_var: handle output) $(user_var: filename output) filespec",TP_CODE}, +{TOK_FINDNEXT,"FindNext",2,0,"$(user_var: handle input) $(user_var: filename output)",TP_CODE}, +{TOK_FILE,"File",1,-1,"[/nonfatal] [/a] ([/r] [/x filespec [...]] filespec [...] |\n /oname=outfile one_file_only)",TP_CODE}, +{TOK_FILEBUFSIZE,"FileBufSize",1,0,"buf_size_mb",TP_ALL}, +{TOK_FLUSHINI,"FlushINI",1,0,"ini_file",TP_CODE}, +{TOK_RESERVEFILE,"ReserveFile",1,-1,"[/nonfatal] [/r] [/x filespec [...]] file [file...]",TP_ALL}, +{TOK_FILECLOSE,"FileClose",1,0,"$(user_var: handle input)",TP_CODE}, +{TOK_FILEERRORTEXT,"FileErrorText",0,2,"[text (can contain $0)] [text without ignore (can contain $0)]",TP_GLOBAL}, +{TOK_FILEOPEN,"FileOpen",3,0,"$(user_var: handle output) filename openmode\n openmode=r|w|a",TP_CODE}, +{TOK_FILEREAD,"FileRead",2,1,"$(user_var: handle input) $(user_var: text output) [maxlen]",TP_CODE}, +{TOK_FILEWRITE,"FileWrite",2,0,"$(user_var: handle input) text",TP_CODE}, +{TOK_FILEREADBYTE,"FileReadByte",2,0,"$(user_var: handle input) $(user_var: bytevalue output)",TP_CODE}, +{TOK_FILEWRITEBYTE,"FileWriteByte",2,0,"$(user_var: handle input) bytevalue",TP_CODE}, +{TOK_FILESEEK,"FileSeek",2,2,"$(user_var: handle input) offset [mode] [$(user_var: new position output)]\n mode=SET|CUR|END",TP_CODE}, +{TOK_FUNCTION,"Function",1,0,"function_name",TP_GLOBAL}, +{TOK_FUNCTIONEND,"FunctionEnd",0,0,"",TP_FUNC}, +{TOK_GETDLGITEM,"GetDlgItem",3,0,"$(user_var: handle output) dialog item_id",TP_CODE}, +{TOK_GETFULLPATHNAME,"GetFullPathName",2,1,"[/SHORT] $(user_var: result) path_or_file",TP_CODE}, +{TOK_GETTEMPFILENAME,"GetTempFileName",1,1,"$(user_var: name output) [base_dir]",TP_CODE}, +{TOK_HIDEWINDOW,"HideWindow",0,0,"",TP_CODE}, +{TOK_ICON,"Icon",1,0,"local_icon.ico",TP_GLOBAL}, +{TOK_IFABORT,"IfAbort",1,1,"label_to_goto_if_abort [label_to_goto_if_no_abort]",TP_CODE}, +{TOK_IFERRORS,"IfErrors",1,1,"label_to_goto_if_errors [label_to_goto_if_no_errors]",TP_CODE}, +{TOK_IFFILEEXISTS,"IfFileExists",2,1,"filename label_to_goto_if_file_exists [label_to_goto_otherwise]",TP_CODE}, +{TOK_IFREBOOTFLAG,"IfRebootFlag",1,1,"jump_if_set [jump_if_not_set]",TP_CODE}, +{TOK_IFSILENT,"IfSilent",1,1,"jump_if_silent [jump_if_not_silent]",TP_CODE}, +{TOK_INSTALLDIRREGKEY,"InstallDirRegKey",3,0,"root_key subkey entry_name\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD)",TP_GLOBAL}, +{TOK_INSTCOLORS,"InstallColors",1,1,"(/windows | (foreground_color background_color))",TP_GLOBAL}, +{TOK_INSTDIR,"InstallDir",1,0,"default_install_directory",TP_GLOBAL}, +{TOK_INSTPROGRESSFLAGS,"InstProgressFlags",0,-1,"[flag [...]]\n flag={smooth|colored}",TP_GLOBAL}, +{TOK_INSTTYPE,"InstType",1,0,"[un.]install_type_name | /NOCUSTOM | /CUSTOMSTRING=str | /COMPONENTSONLYONCUSTOM",TP_GLOBAL}, +{TOK_INTOP,"IntOp",3,1,"$(user_var: result) val1 OP [val2]\n OP=(+ - * / % | & ^ ~ ! || && << >>)",TP_CODE}, +{TOK_INTCMP,"IntCmp",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]",TP_CODE}, +{TOK_INTCMPU,"IntCmpU",3,2,"val1 val2 jump_if_equal [jump_if_val1_less] [jump_if_val1_more]",TP_CODE}, +{TOK_INTFMT,"IntFmt",3,0,"$(user_var: output) format_string input",TP_CODE}, +{TOK_ISWINDOW,"IsWindow",2,1,"hwnd jump_if_window [jump_if_not_window]",TP_CODE}, +{TOK_GOTO,"Goto",1,0,"label",TP_CODE}, +{TOK_LANGSTRING,"LangString",3,0,"[un.]name lang_id string",TP_GLOBAL}, +{TOK_LANGSTRINGUP,"LangStringUP",0,0,"obsolete, use LangString.",TP_ALL}, +{TOK_LICENSEDATA,"LicenseData",1,0,"local_file_that_has_license_text | license_lang_string",TP_PG}, +{TOK_LICENSEFORCESELECTION,"LicenseForceSelection",1,2,"(checkbox [accept_text] | radiobuttons [accept_text] [decline_text] | off)",TP_PG}, +{TOK_LICENSELANGSTRING,"LicenseLangString",3,0,"name lang_id license_path",TP_GLOBAL}, +{TOK_LICENSETEXT,"LicenseText",1,1,"license_page_description [license_button_text]",TP_PG}, +{TOK_LICENSEBKCOLOR,"LicenseBkColor",1,0,"background_color",TP_GLOBAL}, +{TOK_LOADNLF,"LoadLanguageFile",1,0,"language.nlf",TP_GLOBAL}, +{TOK_LOGSET,"LogSet",1,0,"on|off",TP_CODE}, +{TOK_LOGTEXT,"LogText",1,0,"text",TP_CODE}, +{TOK_MESSAGEBOX,"MessageBox",2,6,"mode messagebox_text [/SD return] [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_USERICON|MB_TOPMOST|MB_SETFOREGROUND|MB_RIGHT",TP_CODE}, +{TOK_NOP,"Nop",0,0,"",TP_CODE}, +{TOK_NAME,"Name",1,1,"installer_name installer_name_doubled_ampersands",TP_GLOBAL}, +{TOK_OUTFILE,"OutFile",1,0,"install_output.exe",TP_GLOBAL}, +#ifdef NSIS_SUPPORT_CODECALLBACKS +{TOK_PAGE,"Page",1,4,"((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles|uninstConfirm) [pre_function] [show_function] [leave_function])) [/ENABLECANCEL]",TP_GLOBAL}, +#else +{TOK_PAGE,"Page",1,1,"license|components|directory|instfiles|uninstConfirm [/ENABLECANCEL]",TP_GLOBAL}, +#endif +{TOK_PAGECALLBACKS,"PageCallbacks",0,3,"([creator_function] [leave_function]) | ([pre_function] [show_function] [leave_function])",TP_PAGEEX}, +{TOK_PAGEEX,"PageEx",1,0,"[un.](custom|uninstConfirm|license|components|directory|instfiles)",TP_GLOBAL}, +{TOK_PAGEEXEND,"PageExEnd",0,0,"",TP_PAGEEX}, +{TOK_POP,"Pop",1,0,"$(user_var: output)",TP_CODE}, +{TOK_PUSH,"Push",1,0,"string",TP_CODE}, +{TOK_QUIT,"Quit",0,0,"",TP_CODE}, +{TOK_READINISTR,"ReadINIStr",4,0,"$(user_var: output) ini_file section entry_name",TP_CODE}, +{TOK_READREGDWORD,"ReadRegDWORD",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_READREGSTR,"ReadRegStr",4,0,"$(user_var: output) rootkey subkey entry\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_READENVSTR,"ReadEnvStr",2,0,"$(user_var: output) name",TP_CODE}, +{TOK_REBOOT,"Reboot",0,0,"",TP_CODE}, +{TOK_REGDLL,"RegDLL",1,1,"dll_path_on_target.dll [entrypoint_symbol]",TP_CODE}, +{TOK_RENAME,"Rename",2,1,"[/REBOOTOK] source_file destination_file",TP_CODE}, +{TOK_RET,"Return",0,0,"",TP_CODE}, +{TOK_RMDIR,"RMDir",1,2,"[/r] [/REBOOTOK] directory_name",TP_CODE}, +{TOK_SECTION,"Section",0,3,"[/o] [-][un.][section_name] [section index output]",TP_GLOBAL}, +{TOK_SECTIONEND,"SectionEnd",0,0,"",TP_SEC}, +{TOK_SECTIONIN,"SectionIn",1,-1,"InstTypeIdx [InstTypeIdx [...]]",TP_SEC}, +{TOK_SUBSECTION,"SubSection",1,2,"deprecated - use SectionGroup",TP_GLOBAL}, +{TOK_SECTIONGROUP,"SectionGroup",1,2,"[/e] [un.]section_group_name [section index output]",TP_GLOBAL}, +{TOK_SUBSECTIONEND,"SubSectionEnd",0,0,"deprecated - use SectionGroupEnd",TP_GLOBAL}, +{TOK_SECTIONGROUPEND,"SectionGroupEnd",0,0,"",TP_GLOBAL}, +{TOK_SEARCHPATH,"SearchPath",2,0,"$(user_var: result) filename",TP_CODE}, +{TOK_SECTIONSETFLAGS,"SectionSetFlags",2,0,"section_index flags",TP_CODE}, +{TOK_SECTIONGETFLAGS,"SectionGetFlags",2,0,"section_index $(user_var: output flags)",TP_CODE}, +{TOK_SECTIONSETINSTTYPES,"SectionSetInstTypes",2,0,"section_index inst_types",TP_CODE}, +{TOK_SECTIONGETINSTTYPES,"SectionGetInstTypes",2,0,"section_index $(user_var: output inst_types)",TP_CODE}, +{TOK_SECTIONGETTEXT,"SectionGetText",2,0,"section_index $(user_var: output text)",TP_CODE}, +{TOK_SECTIONSETTEXT,"SectionSetText",2,0,"section_index text_string",TP_CODE}, +{TOK_SECTIONGETSIZE,"SectionGetSize",2,0,"section_index $(user_var: output size)",TP_CODE}, +{TOK_SECTIONSETSIZE,"SectionSetSize",2,0,"section_index new_size",TP_CODE}, +{TOK_GETCURINSTTYPE,"GetCurInstType",1,0,"$(user_var: output inst_type_idx)",TP_CODE}, +{TOK_SETCURINSTTYPE,"SetCurInstType",1,0,"inst_type_idx",TP_CODE}, +{TOK_INSTTYPESETTEXT,"InstTypeSetText",2,0,"insttype_index flags",TP_CODE}, +{TOK_INSTTYPEGETTEXT,"InstTypeGetText",2,0,"insttype_index $(user_var: output flags)",TP_CODE}, +{TOK_SENDMESSAGE,"SendMessage",4,2,"hwnd message [wparam|STR:wParam] [lparam|STR:lParam] [$(user_var: return value)] [/TIMEOUT=X]",TP_CODE}, +{TOK_SETAUTOCLOSE,"SetAutoClose",1,0,"(false|true)",TP_CODE}, +{TOK_SETCTLCOLORS,"SetCtlColors",2,2,"hwnd [/BRANDING] [text_color] [transparent|bg_color]",TP_CODE}, +{TOK_SETBRANDINGIMAGE,"SetBrandingImage",1,2,"[/IMGID=image_item_id_in_dialog] [/RESIZETOFIT] bitmap.bmp",TP_CODE}, +{TOK_SETCOMPRESS,"SetCompress",1,0,"(off|auto|force)",TP_ALL}, +{TOK_SETCOMPRESSOR,"SetCompressor",1,2,"[/FINAL] [/SOLID] (zlib|bzip2|lzma)",TP_GLOBAL}, +{TOK_SETCOMPRESSORDICTSIZE,"SetCompressorDictSize",1,0,"dict_size_mb",TP_ALL}, +{TOK_SETCOMPRESSIONLEVEL,"SetCompressionLevel",1,0,"level_0-9",TP_ALL}, +{TOK_SETDATESAVE,"SetDateSave",1,0,"(off|on)",TP_ALL}, +{TOK_SETDETAILSVIEW,"SetDetailsView",1,0,"(hide|show)",TP_CODE}, +{TOK_SETDETAILSPRINT,"SetDetailsPrint",1,0,"(none|listonly|textonly|both)",TP_CODE}, +{TOK_SETERRORS,"SetErrors",0,0,"",TP_CODE}, +{TOK_SETERRORLEVEL,"SetErrorLevel",1,0,"error_level",TP_CODE}, +{TOK_GETERRORLEVEL,"GetErrorLevel",1,0,"$(user_var: output)",TP_CODE}, +{TOK_SETFILEATTRIBUTES,"SetFileAttributes",2,0,"file attribute[|attribute[...]]\n attribute=(NORMAL|ARCHIVE|HIDDEN|OFFLINE|READONLY|SYSTEM|TEMPORARY|0)",TP_CODE}, +{TOK_SETFONT,"SetFont",2,1,"[/LANG=lang_id] font_face_name font_size",TP_GLOBAL}, +{TOK_SETOUTPATH,"SetOutPath",1,0,"output_path",TP_CODE}, +{TOK_SETOVERWRITE,"SetOverwrite",1,0,"on|off|try|ifnewer|ifdiff",TP_ALL}, +{TOK_SETPLUGINUNLOAD,"SetPluginUnload",1,0,"(manual|alwaysoff)",TP_ALL}, +{TOK_SETREBOOTFLAG,"SetRebootFlag",1,0,"true|false",TP_CODE}, +{TOK_SETREGVIEW,"SetRegView",1,0,"32|64|lastused",TP_CODE}, +{TOK_SETSHELLVARCONTEXT,"SetShellVarContext",1,0,"all|current",TP_CODE}, +{TOK_SETSILENT,"SetSilent",1,0,"silent|normal",TP_CODE}, +{TOK_SHOWDETAILS,"ShowInstDetails",1,0,"(hide|show|nevershow)",TP_GLOBAL}, +{TOK_SHOWDETAILSUNINST,"ShowUninstDetails",1,0,"(hide|show|nevershow)",TP_GLOBAL}, +{TOK_SHOWWINDOW,"ShowWindow",2,0,"hwnd show_state",TP_CODE}, +{TOK_SILENTINST,"SilentInstall",1,0,"(normal|silent|silentlog)",TP_GLOBAL}, +{TOK_SILENTUNINST,"SilentUnInstall",1,0,"(normal|silent)",TP_GLOBAL}, +{TOK_SLEEP,"Sleep",1,0,"sleep_time_in_ms",TP_CODE}, +{TOK_STRCMP,"StrCmp",3,1,"str1 str2 label_to_goto_if_equal [label_to_goto_if_not]",TP_CODE}, +{TOK_STRCMPS,"StrCmpS",3,1,"str1 str2 label_to_goto_if_equal [label_to_goto_if_not]",TP_CODE}, +{TOK_STRCPY,"StrCpy",2,2,"$(user_var: output) str [maxlen] [startoffset]",TP_CODE}, +{TOK_STRLEN,"StrLen",2,0,"$(user_var: length output) str",TP_CODE}, +{TOK_SUBCAPTION,"SubCaption",2,0,"page_number(0-4) new_subcaption",TP_GLOBAL}, +{TOK_UNINSTALLEXENAME,"UninstallExeName",0,0,"no longer supported, use WriteUninstaller from section.",TP_ALL}, +{TOK_UNINSTCAPTION,"UninstallCaption",1,0,"uninstaller_caption",TP_GLOBAL}, +{TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico",TP_GLOBAL}, +#ifdef NSIS_SUPPORT_CODECALLBACKS +{TOK_UNINSTPAGE,"UninstPage",1,4,"((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles|uninstConfirm) [pre_function] [show_function] [leave_function])) [/ENABLECANCEL]",TP_GLOBAL}, +#else +{TOK_UNINSTPAGE,"UninstPage",1,1,"license|components|directory|instfiles|uninstConfirm [/ENABLECANCEL]",TP_GLOBAL}, +#endif +{TOK_UNINSTTEXT,"UninstallText",1,1,"Text_to_go_on_uninstall_page [subtext]",TP_PG}, +{TOK_UNINSTSUBCAPTION,"UninstallSubCaption",2,0,"page_number(0-2) new_subcaption",TP_GLOBAL}, +{TOK_UNREGDLL,"UnRegDLL",1,0,"dll_path_on_target.dll",TP_CODE}, +{TOK_WINDOWICON,"WindowIcon",1,0,"on|off",TP_GLOBAL}, +{TOK_WRITEINISTR,"WriteINIStr",4,0,"ini_file section_name entry_name new_value",TP_CODE}, +{TOK_WRITEREGBIN,"WriteRegBin",4,0,"rootkey subkey entry_name hex_string_like_12848412AB\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_WRITEREGDWORD,"WriteRegDWORD",4,0,"rootkey subkey entry_name new_value_dword\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_WRITEREGSTR,"WriteRegStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_WRITEREGEXPANDSTR,"WriteRegExpandStr",4,0,"rootkey subkey entry_name new_value_string\n root_key=(HKCR|HKLM|HKCU|HKU|HKCC|HKDD|HKPD|SHCTX)",TP_CODE}, +{TOK_WRITEUNINSTALLER,"WriteUninstaller",1,0,"uninstall_exe_name",TP_CODE}, +{TOK_XPSTYLE, "XPStyle",1,0,"(on|off)",TP_GLOBAL}, +{TOK_REQEXECLEVEL, "RequestExecutionLevel",1,0,"none|user|highest|admin",TP_GLOBAL}, +{TOK_P_PACKEXEHEADER,"!packhdr",2,0,"temp_file_name command_line_to_compress_that_temp_file",TP_ALL}, +{TOK_P_SYSTEMEXEC,"!system",1,2,"command [<|>|<>|=) retval]",TP_ALL}, +{TOK_P_EXECUTE,"!execute",1,0,"command",TP_ALL}, +{TOK_P_ADDINCLUDEDIR,"!AddIncludeDir",1,0,"dir",TP_ALL}, +{TOK_P_INCLUDE,"!include",1,1,"[/NONFATAL] filename.nsh",TP_ALL}, +{TOK_P_CD,"!cd",1,0,"absolute_or_relative_new_directory",TP_ALL}, +{TOK_P_IF,"!if",1,3,"[!] value [(==,!=,<=,<,>,>=,&&,||) value2] [...]",TP_ALL}, +{TOK_P_IFDEF,"!ifdef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL}, +{TOK_P_IFNDEF,"!ifndef",1,-1,"symbol [| symbol2 [& symbol3 [...]]]",TP_ALL}, +{TOK_P_ENDIF,"!endif",0,0,"",TP_ALL}, +{TOK_P_DEFINE,"!define",1,4,"([/date|/utcdate] symbol [value]) | (/math symbol val1 OP val2)\n OP=(+ - * / % & | ^)",TP_ALL}, +{TOK_P_UNDEF,"!undef",1,1,"symbol [value]",TP_ALL}, +{TOK_P_ELSE,"!else",0,-1,"[if[macro][n][def] ...]",TP_ALL}, +{TOK_P_ECHO,"!echo",1,0,"message",TP_ALL}, +{TOK_P_WARNING,"!warning",0,1,"[warning_message]",TP_ALL}, +{TOK_P_ERROR,"!error",0,1,"[error_message]",TP_ALL}, + +{TOK_P_VERBOSE,"!verbose",1,0,"verbose_level | push | pop",TP_ALL}, + +{TOK_P_MACRO,"!macro",1,-1,"macroname [parms ...]",TP_ALL}, +{TOK_P_MACROEND,"!macroend",0,0,"",TP_ALL}, +{TOK_P_INSERTMACRO,"!insertmacro",1,-1,"macroname [parms ...]",TP_ALL}, +{TOK_P_IFMACRODEF,"!ifmacrodef",1,-1,"macro [| macro2 [& macro3 [...]]]",TP_ALL}, +{TOK_P_IFMACRONDEF,"!ifmacrondef",1,-1,"macro [| macro2 [& macro3 [...]]]",TP_ALL}, + +{TOK_P_TEMPFILE,"!tempfile",1,0,"symbol",TP_ALL}, +{TOK_P_DELFILE,"!delfile",1,0,"file",TP_ALL}, +{TOK_P_APPENDFILE,"!appendfile",2,0,"file appended_line",TP_ALL}, + +{TOK_MISCBUTTONTEXT,"MiscButtonText",0,4,"[back button text] [next button text] [cancel button text] [close button text]",TP_GLOBAL}, +{TOK_DETAILSBUTTONTEXT,"DetailsButtonText",0,1,"[details button text]",TP_PG}, +{TOK_UNINSTBUTTONTEXT,"UninstallButtonText",0,1,"[uninstall button text]",TP_GLOBAL}, +{TOK_INSTBUTTONTEXT,"InstallButtonText",0,1,"[install button text]",TP_GLOBAL}, +{TOK_SPACETEXTS,"SpaceTexts",0,2,"none | ([space required text] [space available text])",TP_GLOBAL}, +{TOK_COMPLETEDTEXT,"CompletedText",0,1,"[completed text]",TP_PG}, + +{TOK_GETFUNCTIONADDR,"GetFunctionAddress",2,0,"output function",TP_CODE}, +{TOK_GETLABELADDR,"GetLabelAddress",2,0,"output label",TP_CODE}, +{TOK_GETCURRENTADDR,"GetCurrentAddress",1,0,"output",TP_CODE}, + +{TOK_PLUGINDIR,"!AddPluginDir",1,0,"new_plugin_directory",TP_ALL}, +{TOK_INITPLUGINSDIR,"InitPluginsDir",0,0,"",TP_CODE}, +// Added by ramon 23 May 2003 +{TOK_ALLOWSKIPFILES,"AllowSkipFiles",1,0,"(off|on)",TP_ALL}, +// Added by ramon 3 jun 2003 +{TOK_DEFVAR,"Var",1,1,"[/GLOBAL] var_name",TP_ALL}, +// Added by ramon 6 jun 2003 +{TOK_VI_ADDKEY,"VIAddVersionKey",2,1,"/LANG=lang_id keyname value",TP_GLOBAL}, +{TOK_VI_SETPRODUCTVERSION,"VIProductVersion",1,0,"[version_string_X.X.X.X]",TP_GLOBAL}, +{TOK_LOCKWINDOW,"LockWindow",1,0,"(on|off)",TP_CODE}, +}; + +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); + } + +} + +bool CEXEBuild::is_valid_token(char *s) +{ + for (int x = 0; x < TOK__LAST; x ++) + if (!stricmp(tokenlist[x].name,s)) + return true; + return false; +} + +int CEXEBuild::get_commandtoken(char *s, int *np, int *op, int *pos) +{ + 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; + *pos=x; + return tokenlist[x].id; + } + return -1; +} + +int CEXEBuild::GetCurrentTokenPlace() +{ + if (build_cursection) + { + if (build_cursection_isfunc) + { + return TP_FUNC; + } + else + { + return TP_SEC; + } + } + + if (cur_page) + return TP_PAGEEX; + + return TP_GLOBAL; +} + +int CEXEBuild::IsTokenPlacedRight(int pos, char *tok) +{ + if ((unsigned int) pos > (sizeof(tokenlist) / sizeof(tokenType))) + return PS_OK; + + int tp = tokenlist[pos].placement; + int cp = GetCurrentTokenPlace(); + if (tp & cp) { + return PS_OK; + } + else { + char err[1024]; + if (cp == TP_SEC) { + strcpy(err, "Error: command %s not valid in Section\n"); + } + else if (cp == TP_FUNC) { + strcpy(err, "Error: command %s not valid in Function\n"); + } + else if (cp == TP_PAGEEX) { + strcpy(err, "Error: command %s not valid in PageEx\n"); + } + else + { + strcpy(err, "Error: command %s not valid outside "); + if (tp & TP_SEC) + strcat(err, "Section"); + if (tp & TP_FUNC) + { + if (tp & TP_SEC) + { + if (tp & TP_PAGEEX) + { + strcat(err, ", "); + } + else + { + strcat(err, " or "); + } + } + strcat(err, "Function"); + } + if (tp & TP_PAGEEX) + { + if (tp & TP_CODE) + { + strcat(err, " or "); + } + strcat(err, "PageEx"); + } + strcat(err, "\n"); + } + ERROR_MSG(err, tok); + return PS_ERROR; + } +} diff --git a/Source/tokens.h b/Source/tokens.h index 0f78add..65c415a 100755 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -1,274 +1,274 @@ -/*
- * tokens.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#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_LICENSEBKCOLOR,
- TOK_LICENSEDATA,
- TOK_LICENSEFORCESELECTION,
- TOK_LICENSELANGSTRING,
- TOK_LICENSETEXT,
- 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_BGFONT,
- TOK_BGGRADIENT,
- TOK_INSTCOLORS,
- TOK_SUBCAPTION,
- TOK_UNINSTSUBCAPTION,
- TOK_BRANDINGTEXT,
- TOK_FILEERRORTEXT,
- TOK_INSTPROGRESSFLAGS,
- TOK_XPSTYLE,
- TOK_REQEXECLEVEL,
- TOK_CHANGEUI,
- TOK_ADDBRANDINGIMAGE,
- TOK_SETFONT,
- TOK_LOADNLF,
- TOK_RESERVEFILE,
- TOK_ALLOWSKIPFILES,
- TOK_DEFVAR,
- TOK_VI_ADDKEY,
- TOK_VI_SETPRODUCTVERSION,
-
- TOK_MISCBUTTONTEXT,
- TOK_DETAILSBUTTONTEXT,
- TOK_UNINSTBUTTONTEXT,
- TOK_INSTBUTTONTEXT,
- TOK_SPACETEXTS,
- TOK_COMPLETEDTEXT,
-
- TOK_LANGSTRING,
- TOK_LANGSTRINGUP,
-
- // comrpession stuff
- TOK_SETCOMPRESS,
- TOK_DBOPTIMIZE,
- TOK_SETCOMPRESSOR,
- TOK_SETCOMPRESSORDICTSIZE,
- TOK_SETCOMPRESSIONLEVEL,
- TOK_FILEBUFSIZE,
-
- // system "preprocessor"ish tokens
- TOK_P_IF,
- 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_EXECUTE,
- TOK_P_ADDINCLUDEDIR,
- 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,
- TOK_P_IFMACRODEF,
- TOK_P_IFMACRONDEF,
-
- TOK_P_TEMPFILE,
- TOK_P_DELFILE,
- TOK_P_APPENDFILE,
-
- // section/function shit
- TOK_SECTION,
- TOK_SECTIONEND,
- TOK_SECTIONIN,
- TOK_SECTIONGROUP,
- TOK_SECTIONGROUPEND,
- TOK_SUBSECTION,
- TOK_SUBSECTIONEND,
- TOK_FUNCTION,
- TOK_FUNCTIONEND,
- TOK_ADDSIZE,
-
- // page oredering shit
- TOK_PAGE,
- TOK_UNINSTPAGE,
-
- // PageEx stuff
- TOK_PAGEEX,
- TOK_PAGEEXEND,
- TOK_DIRVAR,
- TOK_DIRVERIFY,
- TOK_PAGECALLBACKS,
-
- TOK_GETINSTDIRERROR,
-
- // flag setters
- TOK_SETDATESAVE,
- TOK_SETOVERWRITE,
- TOK_SETPLUGINUNLOAD,
-
- // 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_FLUSHINI,
- 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_IFABORT,
- TOK_STRCPY,
- TOK_STRCMP,
- TOK_STRCMPS,
- 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_GETDLGITEM,
- TOK_SETCTLCOLORS,
- 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_SECTIONSETINSTTYPES,
- TOK_SECTIONGETINSTTYPES,
- TOK_SECTIONSETSIZE,
- TOK_SECTIONGETSIZE,
- TOK_INSTTYPESETTEXT,
- TOK_INSTTYPEGETTEXT,
- TOK_GETCURINSTTYPE,
- TOK_SETCURINSTTYPE,
- TOK_SETREGVIEW,
- TOK_SETSHELLVARCONTEXT,
- TOK_PLUGINDIR,
- TOK_INITPLUGINSDIR,
- TOK_CREATEFONT,
- TOK_SHOWWINDOW,
- TOK_ENABLEWINDOW,
- TOK_SETSILENT,
- TOK_IFSILENT,
- TOK_SETERRORLEVEL,
- TOK_GETERRORLEVEL,
- TOK_LOCKWINDOW,
-
- TOK__LAST,
- TOK__PLUGINCOMMAND
-};
-
-#endif//_TOKENS_H_
+/* + * tokens.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#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_LICENSEBKCOLOR, + TOK_LICENSEDATA, + TOK_LICENSEFORCESELECTION, + TOK_LICENSELANGSTRING, + TOK_LICENSETEXT, + 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_BGFONT, + TOK_BGGRADIENT, + TOK_INSTCOLORS, + TOK_SUBCAPTION, + TOK_UNINSTSUBCAPTION, + TOK_BRANDINGTEXT, + TOK_FILEERRORTEXT, + TOK_INSTPROGRESSFLAGS, + TOK_XPSTYLE, + TOK_REQEXECLEVEL, + TOK_CHANGEUI, + TOK_ADDBRANDINGIMAGE, + TOK_SETFONT, + TOK_LOADNLF, + TOK_RESERVEFILE, + TOK_ALLOWSKIPFILES, + TOK_DEFVAR, + TOK_VI_ADDKEY, + TOK_VI_SETPRODUCTVERSION, + + TOK_MISCBUTTONTEXT, + TOK_DETAILSBUTTONTEXT, + TOK_UNINSTBUTTONTEXT, + TOK_INSTBUTTONTEXT, + TOK_SPACETEXTS, + TOK_COMPLETEDTEXT, + + TOK_LANGSTRING, + TOK_LANGSTRINGUP, + + // comrpession stuff + TOK_SETCOMPRESS, + TOK_DBOPTIMIZE, + TOK_SETCOMPRESSOR, + TOK_SETCOMPRESSORDICTSIZE, + TOK_SETCOMPRESSIONLEVEL, + TOK_FILEBUFSIZE, + + // system "preprocessor"ish tokens + TOK_P_IF, + 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_EXECUTE, + TOK_P_ADDINCLUDEDIR, + 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, + TOK_P_IFMACRODEF, + TOK_P_IFMACRONDEF, + + TOK_P_TEMPFILE, + TOK_P_DELFILE, + TOK_P_APPENDFILE, + + // section/function shit + TOK_SECTION, + TOK_SECTIONEND, + TOK_SECTIONIN, + TOK_SECTIONGROUP, + TOK_SECTIONGROUPEND, + TOK_SUBSECTION, + TOK_SUBSECTIONEND, + TOK_FUNCTION, + TOK_FUNCTIONEND, + TOK_ADDSIZE, + + // page oredering shit + TOK_PAGE, + TOK_UNINSTPAGE, + + // PageEx stuff + TOK_PAGEEX, + TOK_PAGEEXEND, + TOK_DIRVAR, + TOK_DIRVERIFY, + TOK_PAGECALLBACKS, + + TOK_GETINSTDIRERROR, + + // flag setters + TOK_SETDATESAVE, + TOK_SETOVERWRITE, + TOK_SETPLUGINUNLOAD, + + // 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_FLUSHINI, + 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_IFABORT, + TOK_STRCPY, + TOK_STRCMP, + TOK_STRCMPS, + 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_GETDLGITEM, + TOK_SETCTLCOLORS, + 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_SECTIONSETINSTTYPES, + TOK_SECTIONGETINSTTYPES, + TOK_SECTIONSETSIZE, + TOK_SECTIONGETSIZE, + TOK_INSTTYPESETTEXT, + TOK_INSTTYPEGETTEXT, + TOK_GETCURINSTTYPE, + TOK_SETCURINSTTYPE, + TOK_SETREGVIEW, + TOK_SETSHELLVARCONTEXT, + TOK_PLUGINDIR, + TOK_INITPLUGINSDIR, + TOK_CREATEFONT, + TOK_SHOWWINDOW, + TOK_ENABLEWINDOW, + TOK_SETSILENT, + TOK_IFSILENT, + TOK_SETERRORLEVEL, + TOK_GETERRORLEVEL, + TOK_LOCKWINDOW, + + TOK__LAST, + TOK__PLUGINCOMMAND +}; + +#endif//_TOKENS_H_ diff --git a/Source/uservars.h b/Source/uservars.h index d559a4c..2a5c21e 100755 --- a/Source/uservars.h +++ b/Source/uservars.h @@ -1,103 +1,103 @@ -/*
- * uservars.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 2003 Ramon
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___USERVARS___H_____
-#define ___USERVARS___H_____
-
-#include "lang.h"
-
-struct uservarstring {
- int name;
- int index;
- int pos;
- int reference;
-};
-
-class UserVarsStringList : public SortedStringListND<struct uservarstring>
-{
- public:
- UserVarsStringList()
- {
- index = 0;
- }
- ~UserVarsStringList() { }
-
- int add(const char *name, int ref_count = 0 )
- {
- int pos=SortedStringListND<struct uservarstring>::add(name);
- if (pos == -1) return -1;
-
- ((struct uservarstring*)gr.get())[pos].index = index;
- ((struct uservarstring*)gr.get())[pos].pos = pos;
- ((struct uservarstring*)gr.get())[pos].reference = ref_count;
-
- int temp = index;
- index++;
-
- return temp;
- }
-
- int get(char *name, int n_chars = -1)
- {
- int v=SortedStringListND<struct uservarstring>::find(name, n_chars);
- if (v==-1) return -1;
- return (((struct uservarstring*)gr.get())[v].index);
- }
-
- int getnum()
- {
- return index;
- }
-
- int get_reference(int idx)
- {
- int pos=get_internal_idx(idx);
- if (pos==-1) return -1;
- return (((struct uservarstring*)gr.get())[pos].reference);
- }
-
- int inc_reference(int idx)
- {
- int pos=get_internal_idx(idx);
- ((struct uservarstring*)gr.get())[pos].reference++;
- return (((struct uservarstring*)gr.get())[pos].reference)-1;
- }
-
- char *idx2name(int idx)
- {
- int pos=get_internal_idx(idx);
- if (pos==-1) return NULL;
- struct uservarstring *data=(struct uservarstring *)gr.get();
- return ((char*)strings.get() + data[pos].name);
- }
-
- private:
- int index;
- int get_internal_idx(int idx)
- {
- struct uservarstring *data=(struct uservarstring *)gr.get();
- for (int i = 0; i < index; i++)
- {
- if (data[i].index == idx)
- {
- return i;
- }
- }
- return -1;
- }
-};
-
-#endif
+/* + * uservars.h + * + * This file is a part of NSIS. + * + * Copyright (C) 2003 Ramon + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___USERVARS___H_____ +#define ___USERVARS___H_____ + +#include "lang.h" + +struct uservarstring { + int name; + int index; + int pos; + int reference; +}; + +class UserVarsStringList : public SortedStringListND<struct uservarstring> +{ + public: + UserVarsStringList() + { + index = 0; + } + ~UserVarsStringList() { } + + int add(const char *name, int ref_count = 0 ) + { + int pos=SortedStringListND<struct uservarstring>::add(name); + if (pos == -1) return -1; + + ((struct uservarstring*)gr.get())[pos].index = index; + ((struct uservarstring*)gr.get())[pos].pos = pos; + ((struct uservarstring*)gr.get())[pos].reference = ref_count; + + int temp = index; + index++; + + return temp; + } + + int get(char *name, int n_chars = -1) + { + int v=SortedStringListND<struct uservarstring>::find(name, n_chars); + if (v==-1) return -1; + return (((struct uservarstring*)gr.get())[v].index); + } + + int getnum() + { + return index; + } + + int get_reference(int idx) + { + int pos=get_internal_idx(idx); + if (pos==-1) return -1; + return (((struct uservarstring*)gr.get())[pos].reference); + } + + int inc_reference(int idx) + { + int pos=get_internal_idx(idx); + ((struct uservarstring*)gr.get())[pos].reference++; + return (((struct uservarstring*)gr.get())[pos].reference)-1; + } + + char *idx2name(int idx) + { + int pos=get_internal_idx(idx); + if (pos==-1) return NULL; + struct uservarstring *data=(struct uservarstring *)gr.get(); + return ((char*)strings.get() + data[pos].name); + } + + private: + int index; + int get_internal_idx(int idx) + { + struct uservarstring *data=(struct uservarstring *)gr.get(); + for (int i = 0; i < index; i++) + { + if (data[i].index == idx) + { + return i; + } + } + return -1; + } +}; + +#endif diff --git a/Source/util.cpp b/Source/util.cpp index cd0b757..25e515e 100755 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -1,1095 +1,832 @@ -/*
- * util.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#include <string.h>
-#include "exehead/fileform.h"
-#include "util.h"
-#include "strlist.h"
-#include "winchar.h"
-
-#ifndef _WIN32
-# include <ctype.h>
-# include <unistd.h> // for close(2)
-# include <fcntl.h> // for open(2)
-# include <iconv.h>
-#endif
-
-#ifdef __APPLE__
-namespace Apple { // defines struct section
-# include <mach-o/dyld.h> // for _NSGetExecutablePath
-};
-# include <sys/param.h> // for MAXPATHLEN
-#endif
-
-#include <cassert> // for assert
-#include <algorithm>
-#include <stdexcept>
-
-using namespace std;
-
-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=getchar()) != '\r' && a != '\n' && a != 27/*esc*/);
- }
-}
-
-// Returns 0 if everything is OK
-// Returns -1 if can't find the file
-// Returns -2 if the file is an invalid bitmap
-// Returns -3 if the size doesn't match
-// Returns -4 if the bpp doesn't match
-int update_bitmap(CResourceEditor* re, WORD id, const char* filename, int width/*=0*/, int height/*=0*/, int maxbpp/*=0*/) {
- FILE *f = FOPEN(filename, "rb");
- if (!f) return -1;
-
- if (fgetc(f) != 'B' || fgetc(f) != 'M') {
- fclose(f);
- return -2;
- }
-
- if (width != 0) {
- LONG biWidth;
- fseek(f, 18, SEEK_SET); // Seek to the width member of the header
- fread(&biWidth, sizeof(LONG), 1, f);
- FIX_ENDIAN_INT32_INPLACE(biWidth);
- if (width != biWidth) {
- fclose(f);
- return -3;
- }
- }
-
- if (height != 0) {
- LONG biHeight;
- fseek(f, 22, SEEK_SET); // Seek to the height member of the header
- fread(&biHeight, sizeof(LONG), 1, f);
- FIX_ENDIAN_INT32_INPLACE(biHeight);
- // Bitmap height can be negative too...
- if (height != abs(biHeight)) {
- fclose(f);
- return -3;
- }
- }
-
- if (maxbpp != 0) {
- WORD biBitCount;
- fseek(f, 28, SEEK_SET); // Seek to the height member of the header
- fread(&biBitCount, sizeof(WORD), 1, f);
- FIX_ENDIAN_INT16_INPLACE(biBitCount);
- if (biBitCount > maxbpp) {
- fclose(f);
- return -4;
- }
- }
-
- DWORD dwSize;
- fseek(f, 2, SEEK_SET);
- fread(&dwSize, sizeof(DWORD), 1, f);
- FIX_ENDIAN_INT32_INPLACE(dwSize);
- 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 -2;
- }
- fclose(f);
-
- re->UpdateResourceA(RT_BITMAP, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, bitmap, dwSize);
-
- free(bitmap);
-
- 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
-
-static FILE * open_icon(const char* filename, IconGroupHeader *igh)
-{
- FILE* f = FOPEN(filename, "rb");
- if (!f)
- throw runtime_error("can't open file");
-
- if (!fread(igh, sizeof(IconGroupHeader), 1, f))
- throw runtime_error("unable to read file");
-
- FIX_ENDIAN_INT16_INPLACE(igh->wIsIcon);
- FIX_ENDIAN_INT16_INPLACE(igh->wReserved);
- FIX_ENDIAN_INT16_INPLACE(igh->wCount);
-
- if (igh->wIsIcon != 1 || igh->wReserved != 0)
- throw runtime_error("invalid icon file");
-
- return f;
-}
-
-// replace_icon, must get an initialized resource editor
-void replace_icon(CResourceEditor* re, WORD wIconId, const char* filename)
-{
- IconGroupHeader igh, *new_igh;
- FILE *f = open_icon(filename, &igh);
-
- BYTE* rsrcIconGroup = (BYTE*)malloc(sizeof(IconGroupHeader) + igh.wCount*SIZEOF_RSRC_ICON_GROUP_ENTRY);
- if (!rsrcIconGroup) throw bad_alloc();
-
- CopyMemory(rsrcIconGroup, &igh, sizeof(IconGroupHeader));
-
- new_igh = (IconGroupHeader *) rsrcIconGroup;
- FIX_ENDIAN_INT16_INPLACE(new_igh->wIsIcon);
- FIX_ENDIAN_INT16_INPLACE(new_igh->wReserved);
- FIX_ENDIAN_INT16_INPLACE(new_igh->wCount);
-
- RsrcIconGroupEntry* ige = (RsrcIconGroupEntry*)(rsrcIconGroup + sizeof(IconGroupHeader));
-
- int i = 1;
-
- // Delete old icons
- while (re->UpdateResourceA(RT_ICON, MAKEINTRESOURCE(i++), NSIS_DEFAULT_LANG, 0, 0));
-
- for (i = 0; i < igh.wCount; i++) {
- fread(ige, sizeof(FileIconGroupEntry)-sizeof(DWORD), 1, f);
-
- DWORD dwRawSize = FIX_ENDIAN_INT32(ige->dwRawSize);
-
- ige->wRsrcId = FIX_ENDIAN_INT16(i + 1);
-
- DWORD dwOffset;
- fread(&dwOffset, sizeof(DWORD), 1, f);
-
- FIX_ENDIAN_INT32_INPLACE(dwOffset);
-
- fpos_t pos;
- fgetpos(f, &pos);
-
- if (fseek(f, dwOffset, SEEK_SET)) {
- free(rsrcIconGroup);
- throw runtime_error("corrupted icon file, too small");
- }
- BYTE* iconData = (BYTE*)malloc(dwRawSize);
- if (!iconData) {
- free(rsrcIconGroup);
- throw bad_alloc();
- }
- fread(iconData, sizeof(BYTE), dwRawSize, f);
- re->UpdateResourceA(RT_ICON, MAKEINTRESOURCE(i+1), NSIS_DEFAULT_LANG, iconData, dwRawSize);
- free(iconData);
-
- fsetpos(f, &pos);
-
- // 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->UpdateResourceA(RT_GROUP_ICON, MAKEINTRESOURCE(wIconId), NSIS_DEFAULT_LANG, rsrcIconGroup, sizeof(IconGroupHeader) + igh.wCount*SIZEOF_RSRC_ICON_GROUP_ENTRY);
-
- free(rsrcIconGroup);
-}
-
-#ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
-// returns the data of the uninstaller icon that should replace the installer icon data
-unsigned char* generate_uninstall_icon_data(const char* filename, size_t &size)
-{
- int i;
-
- IconGroupHeader igh;
- FILE *f = open_icon(filename, &igh);
-
- 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)) throw runtime_error("unable to read file");
- offsets[i] = ige.dwImageOffset;
- rawSizes[i] = ige.dwRawSize;
- iNewIconSize += FIX_ENDIAN_INT32(ige.dwRawSize);
- }
-
- // Before each icon come two DWORDs, one for size and the other for offset (set later)
- // The last size is 0, no offset
- iNewIconSize += sizeof(DWORD)*(1 + igh.wCount*2);
-
- BYTE* pbUninstIcon = (BYTE*)malloc(iNewIconSize);
- if (!pbUninstIcon) throw bad_alloc();
-
- BYTE* seeker = pbUninstIcon;
-
- for (i = 0; i < igh.wCount; i++) {
- *(DWORD*)seeker = rawSizes[i];
- seeker += sizeof(DWORD);
- *(DWORD*)seeker = 0;
- seeker += sizeof(DWORD);
- fseek(f, FIX_ENDIAN_INT32(offsets[i]), SEEK_SET);
- fread(seeker, 1, FIX_ENDIAN_INT32(rawSizes[i]), f);
- seeker += FIX_ENDIAN_INT32(rawSizes[i]);
- }
-
- // This is how we know there are no more icons (size = 0)
- *(DWORD*)seeker = 0;
-
- free(offsets);
- free(rawSizes);
-
- 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,"\nError finding icon resources: %s -- failing!\n", y);return 0;}
-
-int find_in_dir(PRESOURCE_DIRECTORY rd, WORD id) {
- WORD i = FIX_ENDIAN_INT16(rd->Header.NumberOfNamedEntries);
- WORD l = i + FIX_ENDIAN_INT16(rd->Header.NumberOfIdEntries);
-
- for (; i < l; i++) {
- if (FIX_ENDIAN_INT16(rd->Entries[i].UName.Id) == id) {
- return i;
- }
- }
-
- return -1;
-}
-
-// Fill the array of icons for uninstall with their offsets
-// Returns zero on failure
-int generate_unicons_offsets(unsigned char* exeHeader, size_t exeHeaderSize, unsigned char* uninstIconData) {
- DWORD dwResourceSectionVA;
-
- PIMAGE_NT_HEADERS ntHeaders = CResourceEditor::GetNTHeaders(exeHeader);
- PRESOURCE_DIRECTORY rdRoot = CResourceEditor::GetResourceDirectory(exeHeader, exeHeaderSize, ntHeaders, &dwResourceSectionVA);
-
- int idx = find_in_dir(rdRoot, (WORD) (long) RT_ICON);
- MY_ASSERT(idx < 0, "no icons found");
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY rdEntry = rdRoot->Entries[idx];
- FIX_ENDIAN_INT32_INPLACE(rdEntry.UOffset.OffsetToData);
- MY_ASSERT(!rdEntry.UOffset.DirectoryOffset.DataIsDirectory, "bad resource directory");
-
- PRESOURCE_DIRECTORY rdIcons = PRESOURCE_DIRECTORY(rdEntry.UOffset.DirectoryOffset.OffsetToDirectory + DWORD(rdRoot));
-
- MY_ASSERT((size_t)rdIcons - (size_t)exeHeader > exeHeaderSize, "corrupted EXE - invalid pointer");
-
- WORD wNumberOfEntries = FIX_ENDIAN_INT16(rdIcons->Header.NumberOfIdEntries);
-
- MY_ASSERT(wNumberOfEntries == 0, "no icons found");
-
- for (WORD i = 0; i < wNumberOfEntries; i++) { // Icons dir can't have named entries
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY icoEntry = rdIcons->Entries[i];
- FIX_ENDIAN_INT32_INPLACE(icoEntry.UOffset.OffsetToData);
-
- MY_ASSERT(!icoEntry.UOffset.DirectoryOffset.DataIsDirectory, "bad resource directory");
- PRESOURCE_DIRECTORY rd = PRESOURCE_DIRECTORY(icoEntry.UOffset.DirectoryOffset.OffsetToDirectory + DWORD(rdRoot));
-
- MY_ASSERT((size_t)rd - (size_t)exeHeader > exeHeaderSize, "corrupted EXE - invalid pointer");
-
- MY_IMAGE_RESOURCE_DIRECTORY_ENTRY datEntry = rd->Entries[0];
- FIX_ENDIAN_INT32_INPLACE(datEntry.UOffset.OffsetToData);
-
- MY_ASSERT(datEntry.UOffset.DirectoryOffset.DataIsDirectory, "bad resource directory");
-
- PIMAGE_RESOURCE_DATA_ENTRY rde = PIMAGE_RESOURCE_DATA_ENTRY(datEntry.UOffset.OffsetToData + DWORD(rdRoot));
-
- MY_ASSERT((size_t)rde - (size_t)exeHeader > exeHeaderSize, "corrupted EXE - invalid pointer");
-
- // find icon to replace
- LPBYTE seeker = uninstIconData;
- while (*seeker) {
- DWORD dwSize = *(DWORD*)seeker;
- seeker += sizeof(DWORD);
- DWORD dwOffset = *(DWORD*)seeker;
- // if we haven't set the offset yet and the size is the same, it's a match
- if (!dwOffset && dwSize == rde->Size)
- break;
-
- seeker += FIX_ENDIAN_INT32(dwSize) + sizeof(DWORD);
-
- // reached the end of the list and no match
- MY_ASSERT(!*seeker, "installer, uninstaller icon size mismatch - see the Icon instruction's documentation for more information");
- }
-
- // Set offset
- DWORD dwOffset = FIX_ENDIAN_INT32(rde->OffsetToData) + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader);
- *(LPDWORD) seeker = FIX_ENDIAN_INT32(dwOffset);
-
- MY_ASSERT(dwOffset > exeHeaderSize || dwOffset < (DWORD)rdRoot - (DWORD)exeHeader, "invalid data offset - icon resource probably compressed");
- }
-
- LPBYTE seeker = uninstIconData;
- while (*seeker) {
- DWORD dwSize = *(DWORD*)seeker;
- seeker += sizeof(DWORD);
- DWORD dwOffset = *(DWORD*)seeker;
- seeker += sizeof(DWORD);
- // offset isn't set which means we found no match for this one
- MY_ASSERT(!dwOffset, "installer, uninstaller number of icons doesn't match - see the Icon instruction's documentation for more information");
- seeker += FIX_ENDIAN_INT32(dwSize);
- }
-
- return 1;
-}
-#endif // NSIS_CONFIG_UNINSTALL_SUPPORT
-
-#ifndef _WIN32
-char *CharPrev(const char *s, const char *p) {
- if (!s || !p || p < s)
- return NULL;
- while (*s) {
- char *n = CharNext(s);
- if (n >= p)
- break;
- s = n;
- }
- return (char *) s;
-}
-
-char *CharNext(const char *s) {
- int l = 0;
- if (s && *s)
- l = max(1, mblen(s, MB_CUR_MAX));
- return (char *) s + l;
-}
-
-char *CharNextExA(WORD codepage, const char *s, int flags) {
- char buf[1024];
- snprintf(buf, 1024, "CP%d", codepage);
- setlocale(LC_CTYPE, buf);
-
- const char* np;
- int len = mblen(s, strlen(s));
- if (len > 0)
- np = s + len;
- else
- np = s + 1;
-
- setlocale(LC_CTYPE, "");
-
- return (char *) np;
-}
-
-int wsprintf(char *s, const char *format, ...) {
- va_list val;
- va_start(val, format);
- int res = vsnprintf(s, 1024, format, val);
- va_end(val);
- return res;
-}
-
-// iconv const inconsistency workaround by Alexandre Oliva
-template <typename T>
-inline size_t __iconv_adaptor
- (size_t (*iconv_func)(iconv_t, T, size_t *, char**,size_t*),
- iconv_t cd, char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
-{
- return iconv_func (cd, (T)inbuf, inbytesleft, outbuf, outbytesleft);
-}
-
-void static create_code_page_string(char *buf, size_t len, UINT code_page) {
- if (code_page == CP_ACP)
- code_page = 1252;
-
- snprintf(buf, len, "CP%d", code_page);
-}
-
-int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
- int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
- LPBOOL lpUsedDefaultChar) {
- static char buffer[4096];
-
- char cp[128];
- create_code_page_string(cp, sizeof(cp), CodePage);
-
- iconv_t cd = iconv_open(cp, "UCS-2LE");
- if (cd == (iconv_t) -1) {
- return 0;
- }
-
- if (cchWideChar < 0) {
- cchWideChar = (int) winchar_strlen(lpWideCharStr) + 1;
- }
-
- if (cbMultiByte == 0) {
- cbMultiByte = sizeof(buffer);
- lpMultiByteStr = buffer;
- }
-
- char *in = (char *) lpWideCharStr;
- char *out = lpMultiByteStr;
- size_t inbytes = cchWideChar * sizeof(WCHAR);
- size_t outbytes = cbMultiByte;
-
- if (__iconv_adaptor(iconv, cd, &in, &inbytes, &out, &outbytes) == (size_t) -1) {
- iconv_close(cd);
- return 0;
- }
-
- iconv_close(cd);
-
- return cbMultiByte - outbytes;
-}
-
-int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
- int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) {
- static WCHAR buffer[4096];
-
- char cp[128];
- create_code_page_string(cp, sizeof(cp), CodePage);
-
- iconv_t cd = iconv_open("UCS-2LE", cp);
- if (cd == (iconv_t) -1) {
- return 0;
- }
-
- if (cbMultiByte < 0) {
- cbMultiByte = strlen(lpMultiByteStr) + 1;
- }
-
- if (cchWideChar == 0) {
- cchWideChar = sizeof(buffer);
- lpWideCharStr = buffer;
- }
-
- char *in = (char *) lpMultiByteStr;
- char *out = (char *) lpWideCharStr;
- size_t inbytes = cbMultiByte;
- size_t outbytes = cchWideChar * sizeof(WCHAR);
-
- if (__iconv_adaptor(iconv, cd, &in, &inbytes, &out, &outbytes) == (size_t) -1) {
- iconv_close(cd);
- return 0;
- }
-
- iconv_close(cd);
-
- return cchWideChar - (outbytes / sizeof (WCHAR));
-}
-
-BOOL IsValidCodePage(UINT CodePage)
-{
- char cp[128];
- create_code_page_string(cp, sizeof(cp), CodePage);
-
- iconv_t cd = iconv_open("UCS-2LE", cp);
- if (cd == (iconv_t) -1)
- return FALSE;
-
- iconv_close(cd);
-
- return TRUE;
-}
-
-#define MY_ERROR_MSG(x) {if (g_display_errors) {fprintf(g_output,"%s", x);}}
-
-char *my_convert(const char *path)
-{
- // TODO: (orip) ref. this func. to use std::string?
- char *converted_path = strdup(path);
- size_t len = strlen(path);
-
- if(!converted_path)
- {
- MY_ERROR_MSG("Error: could not allocate memory in my_convert()\n");
- return (char*) path; /* dirty */
- }
-
- /* Replace drive letter X: by /X */
- if(len >= 2)
- {
- if (path[1] == ':')
- {
- converted_path[0] = '/';
- converted_path[1] = (char) tolower((int) path[0]);
- }
- }
-
- char *p = converted_path;
-
- do
- {
- if (*p == '\\')
- {
- *p = '/';
- }
- p = CharNext(p);
- }
- while (*p);
-
- return converted_path;
-}
-
-void my_convert_free(char *converted_path)
-{
- free(converted_path);
-}
-
-int my_open(const char *pathname, int flags)
-{
- char *converted_pathname = my_convert(pathname);
-
- int result = open(converted_pathname, flags);
- my_convert_free(converted_pathname);
- return result;
-}
-
-FILE *my_fopen(const char *path, const char *mode)
-{
- char *converted_path = my_convert(path);
-
- FILE *result = fopen(converted_path, mode);
- my_convert_free(converted_path);
- return result;
-}
-#endif//!_WIN32
-
-void *operator new(size_t size) throw(bad_alloc) {
- void *p = malloc(size);
- if (!p)
- throw bad_alloc();
- return p;
-}
-
-void operator delete(void *p) throw() {
- if (p) free(p);
-}
-
-void operator delete [](void *p) throw() {
- if (p) free(p);
-}
-
-size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
- return strftime(s, max, fmt, tm);
-}
-
-string get_full_path(const string &path) {
-#ifdef _WIN32
- char *throwaway;
- char real_path[1024];
- int rc = GetFullPathName(path.c_str(),1024,real_path,&throwaway);
- assert(rc <= 1024); // path size is limited by MAX_PATH (260)
- assert(rc != 0); // rc==0 in case of error
- return string(real_path);
-#else//_WIN32
-#ifdef PATH_MAX
- static char buffer[PATH_MAX];
-#else//PATH_MAX
- int path_max = pathconf(path, _PC_PATH_MAX);
- if (path_max <= 0)
- path_max = 4096;
- char *buffer = (char *) malloc(path_max);
- if (!buffer)
- return string(path);
-#endif//PATH_MAX
- if (!realpath(path.c_str(), buffer))
- strcpy(buffer, path.c_str());
- string result(buffer);
-#ifndef PATH_MAX
- free(buffer);
-#endif//!PATH_MAX
- return result;
-#endif//_WIN32
-}
-
-string get_string_prefix(const string& str, const string& separator) {
- const string::size_type last_separator_pos = str.rfind(separator);
- if (last_separator_pos == string::npos)
- return str;
- return str.substr(0, last_separator_pos);
-}
-
-string get_string_suffix(const string& str, const string& separator) {
- const string::size_type last_separator_pos = str.rfind(separator);
- if (last_separator_pos == string::npos)
- return str;
- return str.substr(last_separator_pos + separator.size(), string::npos);
-}
-
-string get_dir_name(const string& path) {
- return get_string_prefix(path, PLATFORM_PATH_SEPARATOR_STR);
-}
-
-string get_file_name(const string& path) {
- return get_string_suffix(path, PLATFORM_PATH_SEPARATOR_STR);
-}
-
-string get_executable_path(const char* argv0) {
-#ifdef _WIN32
- char temp_buf[MAX_PATH+1];
- temp_buf[0] = '\0';
- int rc = GetModuleFileName(NULL,temp_buf,MAX_PATH);
- assert(rc != 0);
- return string(temp_buf);
-#elif __APPLE__
- char temp_buf[MAXPATHLEN+1];
- unsigned int buf_len = MAXPATHLEN;
- int rc = Apple::_NSGetExecutablePath(temp_buf, &buf_len);
- assert(rc == 0);
- return string(temp_buf);
-#else /* Linux/BSD/POSIX/etc */
- const char *envpath = getenv("_");
- if( envpath != NULL ) return get_full_path( envpath );
- else {
- char* pathtmp;
- char* path = NULL;
- size_t len = 100;
- int nchars;
- while(1){
- pathtmp = (char*)realloc(path,len+1);
- if( pathtmp == NULL ){
- free(path);
- return get_full_path(argv0);
- }
- path = pathtmp;
- nchars = readlink("/proc/self/exe", path, len);
- if( nchars == -1 ){
- free(path);
- return get_full_path(argv0);
- }
- if( nchars < (int) len ){
- path[nchars] = '\0';
- string result(path);
- free(path);
- return result;
- }
- len *= 2;
- }
- }
-#endif
-}
-
-string get_executable_dir(const char *argv0) {
- return get_dir_name(get_executable_path(argv0));
-}
-
-string remove_file_extension(const string& path) {
- return get_string_prefix(path, ".");
-}
-
-string lowercase(const string &str) {
- string result = str;
- transform(str.begin(), str.end(), result.begin(), tolower);
- return result;
-}
-
-int sane_system(const char *command) {
-#ifdef _WIN32
-
- // workaround for bug #1509909
- // http://sf.net/tracker/?func=detail&atid=373085&aid=1509909&group_id=22049
- //
- // cmd.exe /C has some weird handling for quotes. it strips
- // the surrounding quotes, if they exist. if there are quotes
- // around the program path and its arguments, it will strip
- // the outer quotes. this may result in something like:
- // `program files\nsis\makensis.exe" "args`
- // which obviously fails...
- //
- // to avoid the stripping, a harmless string is prefixed
- // to the command line.
-
- string command_s = "IF 1==1 ";
- command_s += command;
- return system(command_s.c_str());
-
-#else
-
- return system(command);
-
-#endif
-}
-
-static bool GetDLLVersionUsingRE(const string& filepath, DWORD& high, DWORD & low)
-{
- bool found = false;
-
- FILE *fdll = FOPEN(filepath.c_str(), "rb");
- if (!fdll)
- return 0;
-
- fseek(fdll, 0, SEEK_END);
- unsigned int len = ftell(fdll);
- fseek(fdll, 0, SEEK_SET);
-
- LPBYTE dll = (LPBYTE) malloc(len);
-
- if (!dll)
- {
- fclose(fdll);
- return 0;
- }
-
- if (fread(dll, 1, len, fdll) != len)
- {
- fclose(fdll);
- free(dll);
- return 0;
- }
-
- try
- {
- CResourceEditor *dllre = new CResourceEditor(dll, len);
- LPBYTE ver = dllre->GetResourceA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0);
- int versize = dllre->GetResourceSizeA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0);
-
- if (ver)
- {
- if ((size_t) versize > sizeof(WORD) * 3)
- {
- // get VS_FIXEDFILEINFO from VS_VERSIONINFO
- WCHAR *szKey = (WCHAR *)(ver + sizeof(WORD) * 3);
- int len = (winchar_strlen(szKey) + 1) * sizeof(WCHAR) + sizeof(WORD) * 3;
- len = (len + 3) & ~3; // align on DWORD boundry
- VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO *)(ver + len);
- if (versize > len && verinfo->dwSignature == VS_FFI_SIGNATURE)
- {
- low = verinfo->dwFileVersionLS;
- high = verinfo->dwFileVersionMS;
- found = true;
- }
- }
- dllre->FreeResource(ver);
- }
-
- delete dllre;
- }
- catch (exception&)
- {
- }
-
- return found;
-}
-
-static bool GetDLLVersionUsingAPI(const string& filepath, DWORD& high, DWORD& low)
-{
- bool found = false;
-
-#ifdef _WIN32
- char path[1024];
- char *name;
- path[0] = 0;
-
- GetFullPathName(filepath.c_str(), 1024, path, &name);
-
- DWORD d;
- DWORD verSize = GetFileVersionInfoSize(path, &d);
- if (verSize)
- {
- void *buf = (void *) GlobalAlloc(GPTR, verSize);
- if (buf)
- {
- UINT uLen;
- VS_FIXEDFILEINFO *pvsf;
- if (GetFileVersionInfo(path, 0, verSize, buf) && VerQueryValue(buf, "\\", (void**) &pvsf, &uLen))
- {
- low = pvsf->dwFileVersionLS;
- high = pvsf->dwFileVersionMS;
- found = true;
- }
- GlobalFree(buf);
- }
- }
-#endif
-
- return found;
-}
-
-#ifdef _WIN32
-
-// the following structure must be byte-aligned.
-#pragma pack( push, pre_vxd_ver, 1 )
-typedef struct _VXD_VERSION_RESOURCE {
- char cType;
- WORD wID;
- char cName;
- WORD wOrdinal;
- WORD wFlags;
- DWORD dwResSize;
- BYTE bVerData;
-} VXD_VERSION_RESOURCE, *PVXD_VERSION_RESOURCE;
-#pragma pack( pop, pre_vxd_ver )
-
-static BOOL GetVxdVersion( LPCSTR szFile, LPDWORD lpdwLen, LPVOID lpData )
-{
-
- HANDLE hFile = NULL;
- HANDLE hFileMapping = NULL;
- void * pView = NULL;
- DWORD dwSize = 0;
- DWORD dwError = 0;
-
- PIMAGE_DOS_HEADER pDosExeHdr = NULL;
- PIMAGE_NT_HEADERS pNtExeHdr = NULL;
- PIMAGE_VXD_HEADER pLEHdr = NULL;
- PVXD_VERSION_RESOURCE pVerRes = NULL;
- LPVOID pRawRes = NULL;
-
- // Open the file for shared read access.
- hFile = CreateFile( szFile, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, 0, NULL );
- if ( hFile == INVALID_HANDLE_VALUE )
- {
- return FALSE;
- }
-
- // Create a read-only file mapping object for the file.
- hFileMapping = CreateFileMapping( hFile, NULL,
- PAGE_READONLY, 0, 0, NULL);
- if ( !hFileMapping )
- {
- dwError = GetLastError();
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( dwError );
- return FALSE;
- }
-
- // Map a view of the the file.
- pView = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 );
- if ( !pView )
- {
- dwError = GetLastError();
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( dwError );
- return FALSE;
- }
-
- // The DOS header begins at byte 0.
- pDosExeHdr = (PIMAGE_DOS_HEADER) pView;
-
- // Check to make sure the file has a DOS EXE header.
- if ( pDosExeHdr->e_magic != IMAGE_DOS_SIGNATURE )
- {
- if ( pView )
- UnmapViewOfFile( pView );
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( ERROR_BAD_FORMAT );
- return FALSE;
- }
-
- // Find the beginning of the NT header at offset e_lfanew.
- pNtExeHdr = (PIMAGE_NT_HEADERS) ( (DWORD) pView
- + (DWORD) pDosExeHdr->e_lfanew );
-
- // Check to make sure the file is a VxD.
- if ( (DWORD) pNtExeHdr->Signature != IMAGE_VXD_SIGNATURE )
- {
- if ( pView )
- UnmapViewOfFile( pView );
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( ERROR_BAD_FORMAT );
- return FALSE;
- }
-
- // The LE header begins at the same place as the NT header.
- pLEHdr = (PIMAGE_VXD_HEADER) pNtExeHdr;
-
- // e32_winreslen contains the size of the VxD's version resource.
- if ( pLEHdr->e32_winreslen == 0 ) {
- *lpdwLen = 0;
- if ( pView )
- UnmapViewOfFile( pView );
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND );
- return FALSE;
- }
-
- // e32_winresoff contains the offset of the resource in the VxD.
- pVerRes = (VXD_VERSION_RESOURCE *) ( (DWORD) pView
- + (DWORD) pLEHdr->e32_winresoff );
- dwSize = pVerRes->dwResSize;
- pRawRes = &(pVerRes->bVerData);
-
- // Make sure the supplied buffer is large enough for the resource.
- if ( ( lpData == NULL ) || ( *lpdwLen < dwSize ) ) {
- *lpdwLen = dwSize;
-
- if ( pView )
- UnmapViewOfFile( pView );
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError( ERROR_INSUFFICIENT_BUFFER );
- return FALSE;
- }
-
- // Zero the passed buffer and copy the resource into it.
- ZeroMemory( lpData, *lpdwLen );
- CopyMemory( lpData, pRawRes, dwSize );
- *lpdwLen = dwSize;
-
- // Clean up resources.
- if ( pView )
- UnmapViewOfFile( pView );
-
- if ( hFileMapping )
- CloseHandle( hFileMapping );
-
- if ( hFile != INVALID_HANDLE_VALUE )
- CloseHandle( hFile );
-
- SetLastError(0);
- return TRUE;
-}
-
-static DWORD GetVxdVersionInfoSize( LPCSTR szFile )
-{
- DWORD dwResult = 0;
-
- // Call GetVxdVersion() with NULL for the pointer to the buffer.
- if ( !GetVxdVersion( szFile, &dwResult, NULL ) )
- {
- DWORD dwError = GetLastError();
-
- // GetVxdVersion() will fail with ERROR_INSUFFICIENT_BUFFER and
- // the required buffer size will be returned in dwResult.
- if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
- {
- SetLastError( 0 );
- return dwResult;
- }
- }
-
- // The following line is never executed.
- return 0;
-}
-
-static BOOL GetVxdVersionInfo( LPCSTR szFile, DWORD dwLen, LPVOID lpData )
-{
- return GetVxdVersion( szFile, &dwLen, lpData );
-}
-
-#endif //_WIN32
-
-static bool GetDLLVersionFromVXD(const string& filepath, DWORD& high, DWORD& low)
-{
- bool found = false;
-
-#ifdef _WIN32
- DWORD verSize = GetVxdVersionInfoSize(filepath.c_str());
- if (verSize)
- {
- void *buf = (void *) GlobalAlloc(GPTR, verSize);
- if (buf)
- {
- UINT uLen;
- VS_FIXEDFILEINFO *pvsf;
- if (GetVxdVersionInfo(filepath.c_str(), verSize, buf) && VerQueryValue(buf, "\\", (void**) &pvsf, &uLen))
- {
- low = pvsf->dwFileVersionLS;
- high = pvsf->dwFileVersionMS;
- found = true;
- }
- GlobalFree(buf);
- }
- }
-#endif
-
- return found;
-}
-
-bool GetDLLVersion(const string& filepath, DWORD& high, DWORD& low)
-{
- if (GetDLLVersionUsingAPI(filepath, high, low))
- return true;
-
- if (GetDLLVersionUsingRE(filepath, high, low))
- return true;
-
- if (GetDLLVersionFromVXD(filepath, high, low))
- return true;
-
- return false;
-}
+/* + * util.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include <stdio.h> +#include <stdarg.h> +#include <time.h> +#include <string.h> +#include "exehead/fileform.h" +#include "util.h" +#include "strlist.h" +#include "winchar.h" + +#ifndef _WIN32 +# include <ctype.h> +# include <unistd.h> // for close(2) +# include <fcntl.h> // for open(2) +# include <iconv.h> +#endif + +#ifdef __APPLE__ +namespace Apple { // defines struct section +# include <mach-o/dyld.h> // for _NSGetExecutablePath +}; +# include <sys/param.h> // for MAXPATHLEN +#endif + +#include <cassert> // for assert +#include <algorithm> +#include <stdexcept> + +using namespace std; + +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=getchar()) != '\r' && a != '\n' && a != 27/*esc*/); + } +} + +// Returns 0 if everything is OK +// Returns -1 if can't find the file +// Returns -2 if the file is an invalid bitmap +// Returns -3 if the size doesn't match +// Returns -4 if the bpp doesn't match +int update_bitmap(CResourceEditor* re, WORD id, const char* filename, int width/*=0*/, int height/*=0*/, int maxbpp/*=0*/) { + FILE *f = FOPEN(filename, "rb"); + if (!f) return -1; + + if (fgetc(f) != 'B' || fgetc(f) != 'M') { + fclose(f); + return -2; + } + + if (width != 0) { + LONG biWidth; + fseek(f, 18, SEEK_SET); // Seek to the width member of the header + fread(&biWidth, sizeof(LONG), 1, f); + FIX_ENDIAN_INT32_INPLACE(biWidth); + if (width != biWidth) { + fclose(f); + return -3; + } + } + + if (height != 0) { + LONG biHeight; + fseek(f, 22, SEEK_SET); // Seek to the height member of the header + fread(&biHeight, sizeof(LONG), 1, f); + FIX_ENDIAN_INT32_INPLACE(biHeight); + // Bitmap height can be negative too... + if (height != abs(biHeight)) { + fclose(f); + return -3; + } + } + + if (maxbpp != 0) { + WORD biBitCount; + fseek(f, 28, SEEK_SET); // Seek to the height member of the header + fread(&biBitCount, sizeof(WORD), 1, f); + FIX_ENDIAN_INT16_INPLACE(biBitCount); + if (biBitCount > maxbpp) { + fclose(f); + return -4; + } + } + + DWORD dwSize; + fseek(f, 2, SEEK_SET); + fread(&dwSize, sizeof(DWORD), 1, f); + FIX_ENDIAN_INT32_INPLACE(dwSize); + 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 -2; + } + fclose(f); + + re->UpdateResourceA(RT_BITMAP, MAKEINTRESOURCE(id), NSIS_DEFAULT_LANG, bitmap, dwSize); + + free(bitmap); + + return 0; +} + +#ifndef _WIN32 +char *CharPrev(const char *s, const char *p) { + if (!s || !p || p < s) + return NULL; + while (*s) { + char *n = CharNext(s); + if (n >= p) + break; + s = n; + } + return (char *) s; +} + +char *CharNext(const char *s) { + int l = 0; + if (s && *s) + l = max(1, mblen(s, MB_CUR_MAX)); + return (char *) s + l; +} + +char *CharNextExA(WORD codepage, const char *s, int flags) { + char buf[1024]; + snprintf(buf, 1024, "CP%d", codepage); + setlocale(LC_CTYPE, buf); + + const char* np; + int len = mblen(s, strlen(s)); + if (len > 0) + np = s + len; + else + np = s + 1; + + setlocale(LC_CTYPE, ""); + + return (char *) np; +} + +int wsprintf(char *s, const char *format, ...) { + va_list val; + va_start(val, format); + int res = vsnprintf(s, 1024, format, val); + va_end(val); + return res; +} + +// iconv const inconsistency workaround by Alexandre Oliva +template <typename T> +inline size_t __iconv_adaptor + (size_t (*iconv_func)(iconv_t, T, size_t *, char**,size_t*), + iconv_t cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + return iconv_func (cd, (T)inbuf, inbytesleft, outbuf, outbytesleft); +} + +void static create_code_page_string(char *buf, size_t len, UINT code_page) { + if (code_page == CP_ACP) + code_page = 1252; + + snprintf(buf, len, "CP%d", code_page); +} + +int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, + int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar) { + static char buffer[4096]; + + char cp[128]; + create_code_page_string(cp, sizeof(cp), CodePage); + + iconv_t cd = iconv_open(cp, "UCS-2LE"); + if (cd == (iconv_t) -1) { + return 0; + } + + if (cchWideChar < 0) { + cchWideChar = (int) winchar_strlen(lpWideCharStr) + 1; + } + + if (cbMultiByte == 0) { + cbMultiByte = sizeof(buffer); + lpMultiByteStr = buffer; + } + + char *in = (char *) lpWideCharStr; + char *out = lpMultiByteStr; + size_t inbytes = cchWideChar * sizeof(WCHAR); + size_t outbytes = cbMultiByte; + + if (__iconv_adaptor(iconv, cd, &in, &inbytes, &out, &outbytes) == (size_t) -1) { + iconv_close(cd); + return 0; + } + + iconv_close(cd); + + return cbMultiByte - outbytes; +} + +int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, + int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) { + static WCHAR buffer[4096]; + + char cp[128]; + create_code_page_string(cp, sizeof(cp), CodePage); + + iconv_t cd = iconv_open("UCS-2LE", cp); + if (cd == (iconv_t) -1) { + return 0; + } + + if (cbMultiByte < 0) { + cbMultiByte = strlen(lpMultiByteStr) + 1; + } + + if (cchWideChar == 0) { + cchWideChar = sizeof(buffer); + lpWideCharStr = buffer; + } + + char *in = (char *) lpMultiByteStr; + char *out = (char *) lpWideCharStr; + size_t inbytes = cbMultiByte; + size_t outbytes = cchWideChar * sizeof(WCHAR); + + if (__iconv_adaptor(iconv, cd, &in, &inbytes, &out, &outbytes) == (size_t) -1) { + iconv_close(cd); + return 0; + } + + iconv_close(cd); + + return cchWideChar - (outbytes / sizeof (WCHAR)); +} + +BOOL IsValidCodePage(UINT CodePage) +{ + char cp[128]; + create_code_page_string(cp, sizeof(cp), CodePage); + + iconv_t cd = iconv_open("UCS-2LE", cp); + if (cd == (iconv_t) -1) + return FALSE; + + iconv_close(cd); + + return TRUE; +} + +#define MY_ERROR_MSG(x) {if (g_display_errors) {fprintf(g_output,"%s", x);}} + +char *my_convert(const char *path) +{ + // TODO: (orip) ref. this func. to use std::string? + char *converted_path = strdup(path); + size_t len = strlen(path); + + if(!converted_path) + { + MY_ERROR_MSG("Error: could not allocate memory in my_convert()\n"); + return (char*) path; /* dirty */ + } + + /* Replace drive letter X: by /X */ + if(len >= 2) + { + if (path[1] == ':') + { + converted_path[0] = '/'; + converted_path[1] = (char) tolower((int) path[0]); + } + } + + char *p = converted_path; + + do + { + if (*p == '\\') + { + *p = '/'; + } + p = CharNext(p); + } + while (*p); + + return converted_path; +} + +void my_convert_free(char *converted_path) +{ + free(converted_path); +} + +int my_open(const char *pathname, int flags) +{ + char *converted_pathname = my_convert(pathname); + + int result = open(converted_pathname, flags); + my_convert_free(converted_pathname); + return result; +} + +FILE *my_fopen(const char *path, const char *mode) +{ + char *converted_path = my_convert(path); + + FILE *result = fopen(converted_path, mode); + my_convert_free(converted_path); + return result; +} +#endif//!_WIN32 + +void *operator new(size_t size) throw(bad_alloc) { + void *p = malloc(size); + if (!p) + throw bad_alloc(); + return p; +} + +void operator delete(void *p) throw() { + if (p) free(p); +} + +void operator delete [](void *p) throw() { + if (p) free(p); +} + +size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) { + return strftime(s, max, fmt, tm); +} + +string get_full_path(const string &path) { +#ifdef _WIN32 + char *throwaway; + char real_path[1024]; + int rc = GetFullPathName(path.c_str(),1024,real_path,&throwaway); + assert(rc <= 1024); // path size is limited by MAX_PATH (260) + assert(rc != 0); // rc==0 in case of error + return string(real_path); +#else//_WIN32 +#ifdef PATH_MAX + static char buffer[PATH_MAX]; +#else//PATH_MAX + int path_max = pathconf(path, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 4096; + char *buffer = (char *) malloc(path_max); + if (!buffer) + return string(path); +#endif//PATH_MAX + if (!realpath(path.c_str(), buffer)) + strcpy(buffer, path.c_str()); + string result(buffer); +#ifndef PATH_MAX + free(buffer); +#endif//!PATH_MAX + return result; +#endif//_WIN32 +} + +string get_string_prefix(const string& str, const string& separator) { + const string::size_type last_separator_pos = str.rfind(separator); + if (last_separator_pos == string::npos) + return str; + return str.substr(0, last_separator_pos); +} + +string get_string_suffix(const string& str, const string& separator) { + const string::size_type last_separator_pos = str.rfind(separator); + if (last_separator_pos == string::npos) + return str; + return str.substr(last_separator_pos + separator.size(), string::npos); +} + +string get_dir_name(const string& path) { + return get_string_prefix(path, PLATFORM_PATH_SEPARATOR_STR); +} + +string get_file_name(const string& path) { + return get_string_suffix(path, PLATFORM_PATH_SEPARATOR_STR); +} + +string get_executable_path(const char* argv0) { +#ifdef _WIN32 + char temp_buf[MAX_PATH+1]; + temp_buf[0] = '\0'; + int rc = GetModuleFileName(NULL,temp_buf,MAX_PATH); + assert(rc != 0); + return string(temp_buf); +#elif __APPLE__ + char temp_buf[MAXPATHLEN+1]; + unsigned int buf_len = MAXPATHLEN; + int rc = Apple::_NSGetExecutablePath(temp_buf, &buf_len); + assert(rc == 0); + return string(temp_buf); +#else /* Linux/BSD/POSIX/etc */ + const char *envpath = getenv("_"); + if( envpath != NULL ) return get_full_path( envpath ); + else { + char* pathtmp; + char* path = NULL; + size_t len = 100; + int nchars; + while(1){ + pathtmp = (char*)realloc(path,len+1); + if( pathtmp == NULL ){ + free(path); + return get_full_path(argv0); + } + path = pathtmp; + nchars = readlink("/proc/self/exe", path, len); + if( nchars == -1 ){ + free(path); + return get_full_path(argv0); + } + if( nchars < (int) len ){ + path[nchars] = '\0'; + string result(path); + free(path); + return result; + } + len *= 2; + } + } +#endif +} + +string get_executable_dir(const char *argv0) { + return get_dir_name(get_executable_path(argv0)); +} + +string remove_file_extension(const string& path) { + return get_string_prefix(path, "."); +} + +string lowercase(const string &str) { + string result = str; + transform(str.begin(), str.end(), result.begin(), tolower); + return result; +} + +int sane_system(const char *command) { +#ifdef _WIN32 + + // workaround for bug #1509909 + // http://sf.net/tracker/?func=detail&atid=373085&aid=1509909&group_id=22049 + // + // cmd.exe /C has some weird handling for quotes. it strips + // the surrounding quotes, if they exist. if there are quotes + // around the program path and its arguments, it will strip + // the outer quotes. this may result in something like: + // `program files\nsis\makensis.exe" "args` + // which obviously fails... + // + // to avoid the stripping, a harmless string is prefixed + // to the command line. + + string command_s = "IF 1==1 "; + command_s += command; + return system(command_s.c_str()); + +#else + + return system(command); + +#endif +} + +static bool GetDLLVersionUsingRE(const string& filepath, DWORD& high, DWORD & low) +{ + bool found = false; + + FILE *fdll = FOPEN(filepath.c_str(), "rb"); + if (!fdll) + return 0; + + fseek(fdll, 0, SEEK_END); + unsigned int len = ftell(fdll); + fseek(fdll, 0, SEEK_SET); + + LPBYTE dll = (LPBYTE) malloc(len); + + if (!dll) + { + fclose(fdll); + return 0; + } + + if (fread(dll, 1, len, fdll) != len) + { + fclose(fdll); + free(dll); + return 0; + } + + try + { + CResourceEditor *dllre = new CResourceEditor(dll, len); + LPBYTE ver = dllre->GetResourceA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0); + int versize = dllre->GetResourceSizeA(VS_FILE_INFO, MAKEINTRESOURCE(VS_VERSION_INFO), 0); + + if (ver) + { + if ((size_t) versize > sizeof(WORD) * 3) + { + // get VS_FIXEDFILEINFO from VS_VERSIONINFO + WCHAR *szKey = (WCHAR *)(ver + sizeof(WORD) * 3); + int len = (winchar_strlen(szKey) + 1) * sizeof(WCHAR) + sizeof(WORD) * 3; + len = (len + 3) & ~3; // align on DWORD boundry + VS_FIXEDFILEINFO *verinfo = (VS_FIXEDFILEINFO *)(ver + len); + if (versize > len && verinfo->dwSignature == VS_FFI_SIGNATURE) + { + low = verinfo->dwFileVersionLS; + high = verinfo->dwFileVersionMS; + found = true; + } + } + dllre->FreeResource(ver); + } + + delete dllre; + } + catch (exception&) + { + } + + return found; +} + +static bool GetDLLVersionUsingAPI(const string& filepath, DWORD& high, DWORD& low) +{ + bool found = false; + +#ifdef _WIN32 + char path[1024]; + char *name; + path[0] = 0; + + GetFullPathName(filepath.c_str(), 1024, path, &name); + + DWORD d; + DWORD verSize = GetFileVersionInfoSize(path, &d); + if (verSize) + { + void *buf = (void *) GlobalAlloc(GPTR, verSize); + if (buf) + { + UINT uLen; + VS_FIXEDFILEINFO *pvsf; + if (GetFileVersionInfo(path, 0, verSize, buf) && VerQueryValue(buf, "\\", (void**) &pvsf, &uLen)) + { + low = pvsf->dwFileVersionLS; + high = pvsf->dwFileVersionMS; + found = true; + } + GlobalFree(buf); + } + } +#endif + + return found; +} + +#ifdef _WIN32 + +// the following structure must be byte-aligned. +#pragma pack( push, pre_vxd_ver, 1 ) +typedef struct _VXD_VERSION_RESOURCE { + char cType; + WORD wID; + char cName; + WORD wOrdinal; + WORD wFlags; + DWORD dwResSize; + BYTE bVerData; +} VXD_VERSION_RESOURCE, *PVXD_VERSION_RESOURCE; +#pragma pack( pop, pre_vxd_ver ) + +static BOOL GetVxdVersion( LPCSTR szFile, LPDWORD lpdwLen, LPVOID lpData ) +{ + + HANDLE hFile = NULL; + HANDLE hFileMapping = NULL; + void * pView = NULL; + DWORD dwSize = 0; + DWORD dwError = 0; + + PIMAGE_DOS_HEADER pDosExeHdr = NULL; + PIMAGE_NT_HEADERS pNtExeHdr = NULL; + PIMAGE_VXD_HEADER pLEHdr = NULL; + PVXD_VERSION_RESOURCE pVerRes = NULL; + LPVOID pRawRes = NULL; + + // Open the file for shared read access. + hFile = CreateFile( szFile, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) + { + return FALSE; + } + + // Create a read-only file mapping object for the file. + hFileMapping = CreateFileMapping( hFile, NULL, + PAGE_READONLY, 0, 0, NULL); + if ( !hFileMapping ) + { + dwError = GetLastError(); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( dwError ); + return FALSE; + } + + // Map a view of the the file. + pView = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 ); + if ( !pView ) + { + dwError = GetLastError(); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( dwError ); + return FALSE; + } + + // The DOS header begins at byte 0. + pDosExeHdr = (PIMAGE_DOS_HEADER) pView; + + // Check to make sure the file has a DOS EXE header. + if ( pDosExeHdr->e_magic != IMAGE_DOS_SIGNATURE ) + { + if ( pView ) + UnmapViewOfFile( pView ); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( ERROR_BAD_FORMAT ); + return FALSE; + } + + // Find the beginning of the NT header at offset e_lfanew. + pNtExeHdr = (PIMAGE_NT_HEADERS) ( (DWORD) pView + + (DWORD) pDosExeHdr->e_lfanew ); + + // Check to make sure the file is a VxD. + if ( (DWORD) pNtExeHdr->Signature != IMAGE_VXD_SIGNATURE ) + { + if ( pView ) + UnmapViewOfFile( pView ); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( ERROR_BAD_FORMAT ); + return FALSE; + } + + // The LE header begins at the same place as the NT header. + pLEHdr = (PIMAGE_VXD_HEADER) pNtExeHdr; + + // e32_winreslen contains the size of the VxD's version resource. + if ( pLEHdr->e32_winreslen == 0 ) { + *lpdwLen = 0; + if ( pView ) + UnmapViewOfFile( pView ); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( ERROR_RESOURCE_DATA_NOT_FOUND ); + return FALSE; + } + + // e32_winresoff contains the offset of the resource in the VxD. + pVerRes = (VXD_VERSION_RESOURCE *) ( (DWORD) pView + + (DWORD) pLEHdr->e32_winresoff ); + dwSize = pVerRes->dwResSize; + pRawRes = &(pVerRes->bVerData); + + // Make sure the supplied buffer is large enough for the resource. + if ( ( lpData == NULL ) || ( *lpdwLen < dwSize ) ) { + *lpdwLen = dwSize; + + if ( pView ) + UnmapViewOfFile( pView ); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + // Zero the passed buffer and copy the resource into it. + ZeroMemory( lpData, *lpdwLen ); + CopyMemory( lpData, pRawRes, dwSize ); + *lpdwLen = dwSize; + + // Clean up resources. + if ( pView ) + UnmapViewOfFile( pView ); + + if ( hFileMapping ) + CloseHandle( hFileMapping ); + + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle( hFile ); + + SetLastError(0); + return TRUE; +} + +static DWORD GetVxdVersionInfoSize( LPCSTR szFile ) +{ + DWORD dwResult = 0; + + // Call GetVxdVersion() with NULL for the pointer to the buffer. + if ( !GetVxdVersion( szFile, &dwResult, NULL ) ) + { + DWORD dwError = GetLastError(); + + // GetVxdVersion() will fail with ERROR_INSUFFICIENT_BUFFER and + // the required buffer size will be returned in dwResult. + if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) + { + SetLastError( 0 ); + return dwResult; + } + } + + // The following line is never executed. + return 0; +} + +static BOOL GetVxdVersionInfo( LPCSTR szFile, DWORD dwLen, LPVOID lpData ) +{ + return GetVxdVersion( szFile, &dwLen, lpData ); +} + +#endif //_WIN32 + +static bool GetDLLVersionFromVXD(const string& filepath, DWORD& high, DWORD& low) +{ + bool found = false; + +#ifdef _WIN32 + DWORD verSize = GetVxdVersionInfoSize(filepath.c_str()); + if (verSize) + { + void *buf = (void *) GlobalAlloc(GPTR, verSize); + if (buf) + { + UINT uLen; + VS_FIXEDFILEINFO *pvsf; + if (GetVxdVersionInfo(filepath.c_str(), verSize, buf) && VerQueryValue(buf, "\\", (void**) &pvsf, &uLen)) + { + low = pvsf->dwFileVersionLS; + high = pvsf->dwFileVersionMS; + found = true; + } + GlobalFree(buf); + } + } +#endif + + return found; +} + +bool GetDLLVersion(const string& filepath, DWORD& high, DWORD& low) +{ + if (GetDLLVersionUsingAPI(filepath, high, low)) + return true; + + if (GetDLLVersionUsingRE(filepath, high, low)) + return true; + + if (GetDLLVersionFromVXD(filepath, high, low)) + return true; + + return false; +} diff --git a/Source/util.h b/Source/util.h index b29c4a8..9f1a480 100755 --- a/Source/util.h +++ b/Source/util.h @@ -1,156 +1,146 @@ -/*
- * util.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef _UTIL_H_
-#define _UTIL_H_
-
-#include <string> // for std::string
-
-#include "boost/scoped_ptr.hpp" // for boost::scoped_ptr
-#include "ResourceEditor.h"
-
-#ifndef _WIN32
-# include <iconv.h>
-# include <stdio.h>
-#endif
-
-
-// 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, const char* filename, int width=0, int height=0, int maxbpp=0);
-
-// reads icon file filename and places its icons in the resource wIconId using resource editor re
-void replace_icon(CResourceEditor* re, WORD wIconId, const 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(const char* filename, size_t &size);
-// Fill the array of icons for uninstall with their offsets
-int generate_unicons_offsets(unsigned char* exeHeader, size_t exeHeaderSize, unsigned char* uninstIconData);
-#endif//NSIS_CONFIG_UNINSTALL_SUPPORT
-
-size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm);
-
-bool GetDLLVersion(const std::string& filepath, DWORD& high, DWORD& low);
-
-std::string get_full_path(const std::string& path);
-std::string get_dir_name(const std::string& path);
-std::string get_file_name(const std::string& path);
-std::string get_executable_dir(const char *argv0);
-std::string remove_file_extension(const std::string& path);
-std::string lowercase(const std::string&);
-
-std::string get_string_prefix(const std::string& str, const std::string& separator);
-std::string get_string_suffix(const std::string& str, const std::string& separator);
-
-int sane_system(const char *command);
-
-#ifndef _WIN32
-char *CharPrev(const char *s, const char *p);
-char *CharNext(const char *s);
-char *CharNextExA(WORD codepage, const char *s, int flags);
-int wsprintf(char *s, const char *format, ...);
-int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
- int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
- LPBOOL lpUsedDefaultChar);
-int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
- int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
-BOOL IsValidCodePage(UINT CodePage);
-
-char *my_convert(const char *path);
-void my_convert_free(char *converted_path);
-int my_open(const char *pathname, int flags);
-FILE *my_fopen(const char *path, const char *mode);
-
-#define FOPEN(a, b) my_fopen(a, b)
-#define OPEN(a, b) my_open(a, b)
-
-#else
-
-#define FOPEN(a, b) fopen(a, b)
-#define OPEN(a, b) open(a, b)
-#endif
-
-// round a value up to be a multiple of 512
-// assumption: T is an int type
-template <class T>
-inline T align_to_512(const T x) {
- return (x+511) & ~511;
-}
-
-// ================
-// ResourceManagers
-// ================
-
-// When a ResourceManager instance goes out of scope, it will run
-// _FREE_RESOURCE on the resource.
-// Example use:
-// int fd = open(..);
-// assert(fd != -1);
-// MANAGE_WITH(fd, close);
-
-class BaseResourceManager {
-protected:
- BaseResourceManager() {}
-public:
- virtual ~BaseResourceManager() {}
-};
-
-template <typename _RESOURCE, typename _FREE_RESOURCE>
-class ResourceManager : public BaseResourceManager {
-public:
- ResourceManager(_RESOURCE& resource) : m_resource(resource) {}
- virtual ~ResourceManager() { m_free_resource(m_resource); };
-private: // members
- _RESOURCE& m_resource;
- _FREE_RESOURCE m_free_resource;
-private: // don't copy instances
- ResourceManager(const ResourceManager&);
- void operator=(const ResourceManager&);
-};
-
-#define RM_MANGLE_FREEFUNC(freefunc) \
- __free_with_##freefunc
-
-#define RM_DEFINE_FREEFUNC(freefunc) \
-struct RM_MANGLE_FREEFUNC(freefunc) { \
- template <typename T> void operator()(T& x) { freefunc(x); } \
-}
-
-typedef boost::scoped_ptr<BaseResourceManager> ResourceManagerPtr;
-
-template<typename _FREE_RESOURCE, typename _RESOURCE>
-void createResourceManager(_RESOURCE& resource, ResourceManagerPtr& ptr) {
- ptr.reset(new ResourceManager<_RESOURCE, _FREE_RESOURCE>(resource));
-}
-
-#define RM_MANGLE_RESOURCE(resource) resource##_autoManager
-#define MANAGE_WITH(resource, freefunc) \
- ResourceManagerPtr RM_MANGLE_RESOURCE(resource); \
- createResourceManager<RM_MANGLE_FREEFUNC(freefunc)>( \
- resource, RM_MANGLE_RESOURCE(resource))
-
-// Add more resource-freeing functions here when you need them
-RM_DEFINE_FREEFUNC(close);
-RM_DEFINE_FREEFUNC(CloseHandle);
-RM_DEFINE_FREEFUNC(fclose);
-RM_DEFINE_FREEFUNC(free);
-
-#endif //_UTIL_H_
+/* + * util.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#include <string> // for std::string + +#include "boost/scoped_ptr.hpp" // for boost::scoped_ptr +#include "ResourceEditor.h" + +#ifndef _WIN32 +# include <iconv.h> +# include <stdio.h> +#endif + + +// 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, const char* filename, int width=0, int height=0, int maxbpp=0); + +size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm); + +bool GetDLLVersion(const std::string& filepath, DWORD& high, DWORD& low); + +std::string get_full_path(const std::string& path); +std::string get_dir_name(const std::string& path); +std::string get_file_name(const std::string& path); +std::string get_executable_dir(const char *argv0); +std::string remove_file_extension(const std::string& path); +std::string lowercase(const std::string&); + +std::string get_string_prefix(const std::string& str, const std::string& separator); +std::string get_string_suffix(const std::string& str, const std::string& separator); + +int sane_system(const char *command); + +#ifndef _WIN32 +char *CharPrev(const char *s, const char *p); +char *CharNext(const char *s); +char *CharNextExA(WORD codepage, const char *s, int flags); +int wsprintf(char *s, const char *format, ...); +int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, + int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar); +int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, + int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar); +BOOL IsValidCodePage(UINT CodePage); + +char *my_convert(const char *path); +void my_convert_free(char *converted_path); +int my_open(const char *pathname, int flags); +FILE *my_fopen(const char *path, const char *mode); + +#define FOPEN(a, b) my_fopen(a, b) +#define OPEN(a, b) my_open(a, b) + +#else + +#define FOPEN(a, b) fopen(a, b) +#define OPEN(a, b) open(a, b) +#endif + +// round a value up to be a multiple of 512 +// assumption: T is an int type +template <class T> +inline T align_to_512(const T x) { + return (x+511) & ~511; +} + +// ================ +// ResourceManagers +// ================ + +// When a ResourceManager instance goes out of scope, it will run +// _FREE_RESOURCE on the resource. +// Example use: +// int fd = open(..); +// assert(fd != -1); +// MANAGE_WITH(fd, close); + +class BaseResourceManager { +protected: + BaseResourceManager() {} +public: + virtual ~BaseResourceManager() {} +}; + +template <typename _RESOURCE, typename _FREE_RESOURCE> +class ResourceManager : public BaseResourceManager { +public: + ResourceManager(_RESOURCE& resource) : m_resource(resource) {} + virtual ~ResourceManager() { m_free_resource(m_resource); }; +private: // members + _RESOURCE& m_resource; + _FREE_RESOURCE m_free_resource; +private: // don't copy instances + ResourceManager(const ResourceManager&); + void operator=(const ResourceManager&); +}; + +#define RM_MANGLE_FREEFUNC(freefunc) \ + __free_with_##freefunc + +#define RM_DEFINE_FREEFUNC(freefunc) \ +struct RM_MANGLE_FREEFUNC(freefunc) { \ + template <typename T> void operator()(T& x) { freefunc(x); } \ +} + +typedef boost::scoped_ptr<BaseResourceManager> ResourceManagerPtr; + +template<typename _FREE_RESOURCE, typename _RESOURCE> +void createResourceManager(_RESOURCE& resource, ResourceManagerPtr& ptr) { + ptr.reset(new ResourceManager<_RESOURCE, _FREE_RESOURCE>(resource)); +} + +#define RM_MANGLE_RESOURCE(resource) resource##_autoManager +#define MANAGE_WITH(resource, freefunc) \ + ResourceManagerPtr RM_MANGLE_RESOURCE(resource); \ + createResourceManager<RM_MANGLE_FREEFUNC(freefunc)>( \ + resource, RM_MANGLE_RESOURCE(resource)) + +// Add more resource-freeing functions here when you need them +RM_DEFINE_FREEFUNC(close); +RM_DEFINE_FREEFUNC(CloseHandle); +RM_DEFINE_FREEFUNC(fclose); +RM_DEFINE_FREEFUNC(free); + +#endif //_UTIL_H_ diff --git a/Source/winchar.cpp b/Source/winchar.cpp index 8657867..87d446b 100755 --- a/Source/winchar.cpp +++ b/Source/winchar.cpp @@ -1,126 +1,126 @@ -/*
- * winchar.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-#include "winchar.h"
-#include "util.h"
-
-#include <stdexcept>
-
-using std::runtime_error;
-
-WCHAR *winchar_fromansi(const char* s, unsigned int codepage/*=CP_ACP*/)
-{
- int l = MultiByteToWideChar(codepage, 0, s, -1, 0, 0);
- if (l == 0)
- throw runtime_error("Unicode conversion failed");
-
- WCHAR *ws = new WCHAR[l + 1];
-
- if (MultiByteToWideChar(codepage, 0, s, -1, ws, l + 1) == 0)
- throw runtime_error("Unicode conversion failed");
-
- return ws;
-}
-
-char *winchar_toansi(const WCHAR* ws, unsigned int codepage/*=CP_ACP*/)
-{
- int l = WideCharToMultiByte(codepage, 0, ws, -1, 0, 0, 0, 0);
- if (l == 0)
- throw runtime_error("Unicode conversion failed");
-
- char *s = new char[l + 1];
-
- if (WideCharToMultiByte(codepage, 0, ws, -1, s, l + 1, 0, 0) == 0)
- throw runtime_error("Unicode conversion failed");
-
- return s;
-}
-
-WCHAR *winchar_strcpy(WCHAR *ws1, const WCHAR *ws2)
-{
- WCHAR *ret = ws1;
-
- while (*ws2)
- {
- *ws1++ = *ws2++;
- }
-
- *ws1 = 0;
-
- return ret;
-}
-
-WCHAR *winchar_strncpy(WCHAR *ws1, const WCHAR *ws2, size_t n)
-{
- WCHAR *ret = ws1;
-
- while (n && *ws2)
- {
- *ws1++ = *ws2++;
- n--;
- }
-
- while (n--)
- {
- *ws1++ = 0;
- }
-
- return ret;
-}
-
-size_t winchar_strlen(const WCHAR *ws)
-{
- size_t len = 0;
-
- while (*ws++)
- {
- len++;
- }
-
- return len;
-}
-
-WCHAR *winchar_strdup(const WCHAR *ws)
-{
- WCHAR *dup = new WCHAR[winchar_strlen(ws) + 1];
- winchar_strcpy(dup, ws);
- return dup;
-}
-
-int winchar_strcmp(const WCHAR *ws1, const WCHAR *ws2)
-{
- int diff = 0;
-
- do
- {
- diff = static_cast<int>(*ws1) - static_cast<int>(*ws2);
- }
- while (*ws1++ && *ws2++ && !diff);
-
- return diff;
-}
-
-int winchar_stoi(const WCHAR *ws)
-{
- char *s = winchar_toansi(ws);
-
- int ret = atoi(s);
-
- delete [] s;
-
- return ret;
-}
+/* + * winchar.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" +#include "winchar.h" +#include "util.h" + +#include <stdexcept> + +using std::runtime_error; + +WCHAR *winchar_fromansi(const char* s, unsigned int codepage/*=CP_ACP*/) +{ + int l = MultiByteToWideChar(codepage, 0, s, -1, 0, 0); + if (l == 0) + throw runtime_error("Unicode conversion failed"); + + WCHAR *ws = new WCHAR[l + 1]; + + if (MultiByteToWideChar(codepage, 0, s, -1, ws, l + 1) == 0) + throw runtime_error("Unicode conversion failed"); + + return ws; +} + +char *winchar_toansi(const WCHAR* ws, unsigned int codepage/*=CP_ACP*/) +{ + int l = WideCharToMultiByte(codepage, 0, ws, -1, 0, 0, 0, 0); + if (l == 0) + throw runtime_error("Unicode conversion failed"); + + char *s = new char[l + 1]; + + if (WideCharToMultiByte(codepage, 0, ws, -1, s, l + 1, 0, 0) == 0) + throw runtime_error("Unicode conversion failed"); + + return s; +} + +WCHAR *winchar_strcpy(WCHAR *ws1, const WCHAR *ws2) +{ + WCHAR *ret = ws1; + + while (*ws2) + { + *ws1++ = *ws2++; + } + + *ws1 = 0; + + return ret; +} + +WCHAR *winchar_strncpy(WCHAR *ws1, const WCHAR *ws2, size_t n) +{ + WCHAR *ret = ws1; + + while (n && *ws2) + { + *ws1++ = *ws2++; + n--; + } + + while (n--) + { + *ws1++ = 0; + } + + return ret; +} + +size_t winchar_strlen(const WCHAR *ws) +{ + size_t len = 0; + + while (*ws++) + { + len++; + } + + return len; +} + +WCHAR *winchar_strdup(const WCHAR *ws) +{ + WCHAR *dup = new WCHAR[winchar_strlen(ws) + 1]; + winchar_strcpy(dup, ws); + return dup; +} + +int winchar_strcmp(const WCHAR *ws1, const WCHAR *ws2) +{ + int diff = 0; + + do + { + diff = static_cast<int>(*ws1) - static_cast<int>(*ws2); + } + while (*ws1++ && *ws2++ && !diff); + + return diff; +} + +int winchar_stoi(const WCHAR *ws) +{ + char *s = winchar_toansi(ws); + + int ret = atoi(s); + + delete [] s; + + return ret; +} diff --git a/Source/winchar.h b/Source/winchar.h index b0be250..07ac7e7 100755 --- a/Source/winchar.h +++ b/Source/winchar.h @@ -1,26 +1,26 @@ -/*
- * winchar.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "Platform.h"
-
-WCHAR *winchar_fromansi(const char* s, unsigned int codepage = CP_ACP);
-char *winchar_toansi(const WCHAR* ws, unsigned int codepage = CP_ACP);
-WCHAR *winchar_strcpy(WCHAR *ws1, const WCHAR *ws2);
-WCHAR *winchar_strncpy(WCHAR *ws1, const WCHAR *ws2, size_t n);
-size_t winchar_strlen(const WCHAR *ws);
-WCHAR *winchar_strdup(const WCHAR *ws);
-int winchar_strcmp(const WCHAR *ws1, const WCHAR *ws2);
-int winchar_stoi(const WCHAR *ws);
+/* + * winchar.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "Platform.h" + +WCHAR *winchar_fromansi(const char* s, unsigned int codepage = CP_ACP); +char *winchar_toansi(const WCHAR* ws, unsigned int codepage = CP_ACP); +WCHAR *winchar_strcpy(WCHAR *ws1, const WCHAR *ws2); +WCHAR *winchar_strncpy(WCHAR *ws1, const WCHAR *ws2, size_t n); +size_t winchar_strlen(const WCHAR *ws); +WCHAR *winchar_strdup(const WCHAR *ws); +int winchar_strcmp(const WCHAR *ws1, const WCHAR *ws2); +int winchar_stoi(const WCHAR *ws); diff --git a/Source/writer.cpp b/Source/writer.cpp index 20207fd..f41975f 100755 --- a/Source/writer.cpp +++ b/Source/writer.cpp @@ -1,89 +1,89 @@ -/*
- * writer.cpp
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "exehead/config.h"
-#include "writer.h"
-#include "growbuf.h"
-#include "util.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdexcept>
-
-void writer_sink::write_byte(const unsigned char b)
-{
- write_data(&b, 1);
-}
-
-void writer_sink::write_short(const short s)
-{
- short fs = FIX_ENDIAN_INT16(s);
- write_data(&fs, sizeof(short));
-}
-
-void writer_sink::write_int(const int i)
-{
- int fi = FIX_ENDIAN_INT32(i);
- write_data(&fi, sizeof(int));
-}
-
-void writer_sink::write_int_array(const int i[], const size_t len)
-{
- for (size_t l = 0; l < len; l++)
- {
- write_int(i[l]);
- }
-}
-
-void writer_sink::write_string(const char *s)
-{
- write_data(s, strlen(s) + 1);
-}
-
-void writer_sink::write_string(const char *s, const size_t size)
-{
- char *wb = new char[size];
- memset(wb, 0, size);
- strncpy(wb, s, size);
- write_data(wb, size);
- delete [] wb;
-}
-
-void writer_sink::write_growbuf(const IGrowBuf *b)
-{
- write_data(b->get(), b->getlen());
-}
-
-void growbuf_writer_sink::write_data(const void *data, const size_t size)
-{
- m_buf->add(data, size);
-}
-
-void file_writer_sink::write_data(const void *data, const size_t size)
-{
- if (fwrite(data, 1, size, m_fp) != size)
- {
- throw std::runtime_error("error writing");
- }
-}
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-#include "crc32.h"
-
-void crc_writer_sink::write_data(const void *data, const size_t size)
-{
- *m_crc = CRC32(*m_crc, (const unsigned char *) data, size);
-}
-#endif
+/* + * writer.cpp + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "exehead/config.h" +#include "writer.h" +#include "growbuf.h" +#include "util.h" +#include <string.h> +#include <stdlib.h> +#include <stdexcept> + +void writer_sink::write_byte(const unsigned char b) +{ + write_data(&b, 1); +} + +void writer_sink::write_short(const short s) +{ + short fs = FIX_ENDIAN_INT16(s); + write_data(&fs, sizeof(short)); +} + +void writer_sink::write_int(const int i) +{ + int fi = FIX_ENDIAN_INT32(i); + write_data(&fi, sizeof(int)); +} + +void writer_sink::write_int_array(const int i[], const size_t len) +{ + for (size_t l = 0; l < len; l++) + { + write_int(i[l]); + } +} + +void writer_sink::write_string(const char *s) +{ + write_data(s, strlen(s) + 1); +} + +void writer_sink::write_string(const char *s, const size_t size) +{ + char *wb = new char[size]; + memset(wb, 0, size); + strncpy(wb, s, size); + write_data(wb, size); + delete [] wb; +} + +void writer_sink::write_growbuf(const IGrowBuf *b) +{ + write_data(b->get(), b->getlen()); +} + +void growbuf_writer_sink::write_data(const void *data, const size_t size) +{ + m_buf->add(data, size); +} + +void file_writer_sink::write_data(const void *data, const size_t size) +{ + if (fwrite(data, 1, size, m_fp) != size) + { + throw std::runtime_error("error writing"); + } +} + +#ifdef NSIS_CONFIG_CRC_SUPPORT +#include "crc32.h" + +void crc_writer_sink::write_data(const void *data, const size_t size) +{ + *m_crc = CRC32(*m_crc, (const unsigned char *) data, size); +} +#endif diff --git a/Source/writer.h b/Source/writer.h index 7f672bb..1a26581 100755 --- a/Source/writer.h +++ b/Source/writer.h @@ -1,87 +1,87 @@ -/*
- * writer.h
- *
- * This file is a part of NSIS.
- *
- * Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * Licensed under the zlib/libpng license (the "License");
- * you may not use this file except in compliance with the License.
- *
- * Licence details can be found in the file COPYING.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#ifndef ___WRITER__H___
-#define ___WRITER__H___
-
-#include "exehead/config.h"
-#include "growbuf.h"
-#include "crc32.h"
-#include <stdio.h>
-
-class writer_sink {
-public:
- writer_sink() {}
- virtual ~writer_sink() {}
-
- virtual void write_byte(const unsigned char b);
- virtual void write_short(const short s);
- virtual void write_int(const int i);
- virtual void write_int_array(const int i[], const size_t len);
- virtual void write_string(const char *s);
- virtual void write_string(const char *s, const size_t size);
- virtual void write_growbuf(const IGrowBuf *b);
-
- virtual void write_data(const void *data, const size_t size) = 0;
-
-};
-
-class writer {
-public:
- writer(writer_sink *sink) : m_sink(sink) {}
- virtual ~writer() {}
-
-protected:
- writer_sink *m_sink;
-
-};
-
-class growbuf_writer_sink : public writer_sink {
-public:
- growbuf_writer_sink(IGrowBuf *buf) : m_buf(buf) {}
-
- virtual void write_data(const void *data, const size_t size);
-
-private:
- IGrowBuf *m_buf;
-
-};
-
-class file_writer_sink : public writer_sink {
-public:
- file_writer_sink(FILE *fp) : m_fp(fp) {}
-
- virtual void write_data(const void *data, const size_t size);
-
-private:
- FILE *m_fp;
-
-};
-
-#ifdef NSIS_CONFIG_CRC_SUPPORT
-class crc_writer_sink : public writer_sink {
-public:
- crc_writer_sink(crc32_t *crc) : m_crc(crc) {}
-
- virtual void write_data(const void *data, const size_t size);
-
-private:
- crc32_t *m_crc;
-
-};
-#endif
-
-#endif//!___WRITER__H___
+/* + * writer.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2007 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef ___WRITER__H___ +#define ___WRITER__H___ + +#include "exehead/config.h" +#include "growbuf.h" +#include "crc32.h" +#include <stdio.h> + +class writer_sink { +public: + writer_sink() {} + virtual ~writer_sink() {} + + virtual void write_byte(const unsigned char b); + virtual void write_short(const short s); + virtual void write_int(const int i); + virtual void write_int_array(const int i[], const size_t len); + virtual void write_string(const char *s); + virtual void write_string(const char *s, const size_t size); + virtual void write_growbuf(const IGrowBuf *b); + + virtual void write_data(const void *data, const size_t size) = 0; + +}; + +class writer { +public: + writer(writer_sink *sink) : m_sink(sink) {} + virtual ~writer() {} + +protected: + writer_sink *m_sink; + +}; + +class growbuf_writer_sink : public writer_sink { +public: + growbuf_writer_sink(IGrowBuf *buf) : m_buf(buf) {} + + virtual void write_data(const void *data, const size_t size); + +private: + IGrowBuf *m_buf; + +}; + +class file_writer_sink : public writer_sink { +public: + file_writer_sink(FILE *fp) : m_fp(fp) {} + + virtual void write_data(const void *data, const size_t size); + +private: + FILE *m_fp; + +}; + +#ifdef NSIS_CONFIG_CRC_SUPPORT +class crc_writer_sink : public writer_sink { +public: + crc_writer_sink(crc32_t *crc) : m_crc(crc) {} + + virtual void write_data(const void *data, const size_t size); + +private: + crc32_t *m_crc; + +}; +#endif + +#endif//!___WRITER__H___ diff --git a/Source/zlib/DEFLATE.H b/Source/zlib/DEFLATE.H index 0af4034..7dc521b 100755 --- a/Source/zlib/DEFLATE.H +++ b/Source/zlib/DEFLATE.H @@ -1,251 +1,251 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* deflate.h -- internal compression state + * Copyright (C) 1995-1998 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "ZUTIL.H" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + + ulg window_size; + + Posf *prev; + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + long block_start; + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + + uInt max_chain_length; + + uInt max_lazy_match; +# define max_insert_length max_lazy_match + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + + int nice_match; /* Stop searching when current match exceeds this */ + + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + int bi_valid; + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/Source/zlib/INFBLOCK.C b/Source/zlib/INFBLOCK.C index 8e937fb..73aef2d 100755 --- a/Source/zlib/INFBLOCK.C +++ b/Source/zlib/INFBLOCK.C @@ -1,710 +1,710 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-#include "../Platform.h"
-#include "../exehead/config.h"
-
-#include "ZUTIL.H"
-
-#ifndef min
-# define min(x,y) ((x<y)?x:y)
-#endif
-
-/* defines for inflate input/output */
-/* update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE(r) {UPDATE inflate_flush(z); return r;}
-
-/* get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-
-
-#define NEEDBYTE {if(!n)LEAVE(Z_OK)}
-#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 inflate_flush(z); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE(Z_OK)}}}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/* load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-#define LAST (s->last == DRY)
-
-#define FIXEDH 544 /* number of hufts used by fixed tables */
-
-
-
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* And'ing with mask[n] masks the lower n bits */
-local unsigned short inflate_mask[17] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-}; // use to reduce .data #define INFLATE_MASK(x, n) (x & (~((unsigned short) 0xFFFF << n)))
-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};
-
-/* 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};
-
-/* build fixed tables only once--keep them here */
-local char fixed_built = 0;
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl=9;
-local uInt fixed_bd=5;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-/* copy as much as possible from the sliding window to the output area */
-local void ZEXPORT inflate_flush(z)
-z_streamp z;
-{
- inflate_blocks_statef *s = &z->blocks;
- uInt n;
- Bytef *q;
-
- /* local copies of source and destination pointers */
- q = s->read;
-
-again:
- /* compute number of bytes to copy as far as end of window */
- n = (uInt)((q <= s->write ? s->write : s->end) - q);
- n = min(n, z->avail_out);
-
- /* update counters */
- z->avail_out -= n;
- //z->total_out += n;
-
- /* copy as far as end of window */
- zmemcpy(z->next_out, q, n);
- z->next_out += 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;
-
- /* do the same for the beginning of the window */
- goto again;
- }
-
- /* update pointers */
- s->read = q;
-}
-
-#define BMAX 15 /* maximum bit length of any code */
-
-local int ZEXPORT 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--)
- {
- int nextw=w;
- /* here i is the Huffman code of length k bits for value *p */
- /* make tables up to required level */
- while (k > (nextw=w + l))
- {
- h++;
-
- /* compute minimum size table less than or equal to l bits */
- z = g - nextw;
- z = z > (uInt)l ? l : z; /* table size upper limit */
- if ((f = 1 << (j = k - nextw)) > 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 && (f <<= 1) > *++xp) /* try smaller tables up to z 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;
- 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 */
- w=nextw; /* previous table always l bits */
- }
-
- /* 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 ZEXPORT inflate(z_streamp z)
-{
- inflate_blocks_statef *s = &z->blocks;
- inflate_codes_statef *c = &s->sub.decode.t_codes; /* codes state */
-
- // lousy two bytes saved by doing this
- struct
- {
- 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 */
-
- /* CODES variables */
-
- inflate_huft *j; /* temporary pointer */
- uInt e; /* extra bits or operation */
- Bytef *f; /* pointer to copy strings from */
- } _state;
-
-#define t _state.t
-#define b _state.b
-#define k _state.k
-#define p _state.p
-#define n _state.n
-#define q _state.q
-#define m _state.m
-
- /* 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;
- DUMPBITS(3)
- s->last = (t & 1) ? DRY : TYPE;
- switch (t >> 1)
- {
- case 0: /* stored */
- Tracev((stderr, "inflate: stored block%s\n",
- LAST ? " (last)" : ""));
- DUMPBITS(k&7)
- s->mode = LENS; /* get length of stored block */
- break;
- case 1: /* fixed */
- Tracev((stderr, "inflate: fixed codes block%s\n",
- LAST ? " (last)" : ""));
- {
- 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 < 288; _k++)
- {
- char v=8;
- if (_k > 143)
- {
- if (_k < 256) v++;
- else if (_k < 280) v--;
- }
- c[_k] = v;
- }
-
- 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;
-
- huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, fixed_mem, &f);
-
- /* done */
- fixed_built++;
- }
-
- //s->sub.decode.t_codes.mode = CODES_START;
- s->sub.decode.t_codes.lbits = (Byte)fixed_bl;
- s->sub.decode.t_codes.dbits = (Byte)fixed_bd;
- s->sub.decode.t_codes.ltree = fixed_tl;
- s->sub.decode.t_codes.dtree = fixed_td;
- }
- s->mode = CODES_START;
- break;
- case 2: /* dynamic */
- Tracev((stderr, "inflate: dynamic codes block%s\n",
- LAST ? " (last)" : ""));
- s->mode = TABLE;
- break;
- case 3: /* illegal */
- /* the only illegal value possible is 3 because we check only 2 bits */
- goto bad;
- }
- break;
- case LENS:
- NEEDBITS(16)
- 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;
- break;
- case STORED:
- {
- uInt mn;
-
- if (n == 0)
- LEAVE(Z_OK)
- NEEDOUT
- mn = min(m, n);
- t = min(s->sub.left, mn);
- zmemcpy(q, p, t);
- p += t; n -= t;
- q += t; m -= t;
- if (!(s->sub.left -= t))
- s->mode = s->last;
- break;
- }
- case TABLE:
- NEEDBITS(14)
- s->sub.trees.table = t = (uInt)b & 0x3fff;
- if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
- {
- s->mode = BAD;
- LEAVE(Z_DATA_ERROR);
- }
- //t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
- 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.t_blens[(int)border[s->sub.trees.index++]] = (uInt)b & 7;
- DUMPBITS(3)
- }
- while (s->sub.trees.index < 19)
- s->sub.trees.t_blens[(int)border[s->sub.trees.index++]] = 0;
- s->sub.trees.bb = 7;
-
- {
- uInt hn = 0; /* hufts used in space */
-
- t = huft_build(s->sub.trees.t_blens, 19, 19, (short *)Z_NULL, (short*)Z_NULL,
- &s->sub.trees.tb, &s->sub.trees.bb, s->hufts, &hn);
- if (t != Z_OK || !s->sub.trees.bb)
- {
- s->mode = BAD;
- break;
- }
- }
-
- 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.t_blens[s->sub.trees.index++] = c;
- }
- else /* c == 16..18 */
- {
- if (c == 18)
- {
- i=7;
- j=11;
- }
- else
- {
- i=c-14;
- j=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))
- {
- s->mode = BAD;
- LEAVE(Z_DATA_ERROR);
- }
- c = c == 16 ? s->sub.trees.t_blens[i - 1] : 0;
- do {
- s->sub.trees.t_blens[i++] = c;
- } while (--j);
- s->sub.trees.index = i;
- }
- }
- s->sub.trees.tb = Z_NULL;
- {
- uInt hn = 0; /* hufts used in space */
- uInt bl, bd;
- inflate_huft *tl, *td;
- int nl,nd;
- t = s->sub.trees.table;
-
- nl = 257 + (t & 0x1f);
- nd = 1 + ((t >> 5) & 0x1f);
- bl = 9; /* must be <= 9 for lookahead assumptions */
- bd = 6; /* must be <= 9 for lookahead assumptions */
-
- t = huft_build(s->sub.trees.t_blens, nl, 257, cplens, cplext, &tl, &bl, s->hufts, &hn);
- if (bl == 0) t = Z_DATA_ERROR;
- if (t == Z_OK)
- {
- /* build distance tree */
- t = huft_build(s->sub.trees.t_blens + nl, nd, 0, cpdist, cpdext, &td, &bd, s->hufts, &hn);
- }
- if (t != Z_OK || (bd == 0 && nl > 257))
- {
- s->mode = BAD;
- LEAVE(Z_DATA_ERROR);
- }
- Tracev((stderr, "inflate: trees ok\n"));
-
- //s->sub.decode.t_codes.mode = CODES_START;
- s->sub.decode.t_codes.lbits = (Byte)bl;
- s->sub.decode.t_codes.dbits = (Byte)bd;
- s->sub.decode.t_codes.ltree = tl;
- s->sub.decode.t_codes.dtree = td;
- }
- s->mode = CODES_START;
-
-#define j (_state.j)
-#define e (_state.e)
-#define f (_state.f)
-
- /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-
- case CODES_START: /* x: set up for LEN */
- c->sub.code.need = c->lbits;
- c->sub.code.tree = c->ltree;
- s->mode = CODES_LEN;
- case CODES_LEN: /* i: get length/literal/eob next */
- t = c->sub.code.need;
- NEEDBITS(t)
- j = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[t]);
- DUMPBITS(j->bits)
- e = (uInt)(j->exop);
- if (e == 0) /* literal */
- {
- c->sub.lit = j->base;
- s->mode = CODES_LIT;
- break;
- }
- if (e & 16) /* length */
- {
- c->sub.copy.get = e & 15;
- c->len = j->base;
- s->mode = CODES_LENEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = j + j->base;
- break;
- }
- if (e & 32) /* end of block */
- {
- s->mode = CODES_WASH;
- break;
- }
- goto bad;
- case CODES_LENEXT: /* i: getting length extra (have base) */
- t = c->sub.copy.get;
- NEEDBITS(t)
- c->len += (uInt)b & (uInt)inflate_mask[t];
- DUMPBITS(t)
- c->sub.code.need = c->dbits;
- c->sub.code.tree = c->dtree;
- s->mode = CODES_DIST;
- case CODES_DIST: /* i: get distance next */
- t = c->sub.code.need;
- NEEDBITS(t)
- j = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[t]);
- DUMPBITS(j->bits)
- e = (uInt)(j->exop);
- if (e & 16) /* distance */
- {
- c->sub.copy.get = e & 15;
- c->sub.copy.dist = j->base;
- s->mode = CODES_DISTEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = j + j->base;
- break;
- }
- goto bad; /* invalid code */
- case CODES_DISTEXT: /* i: getting distance extra */
- t = c->sub.copy.get;
- NEEDBITS(t)
- c->sub.copy.dist += (uInt)b & (uInt)inflate_mask[t];
- DUMPBITS(t)
- s->mode = CODES_COPY;
- case CODES_COPY: /* o: copying bytes in window, waiting for space */
- f = (uInt)(q - s->window) < c->sub.copy.dist ?
- s->end - (c->sub.copy.dist - (q - s->window)) :
- q - c->sub.copy.dist;
-
- while (c->len)
- {
- NEEDOUT
- OUTBYTE(*f++)
- if (f == s->end)
- f = s->window;
- c->len--;
- }
- s->mode = CODES_START;
- break;
- case CODES_LIT: /* o: got literal, waiting for output space */
- NEEDOUT
- OUTBYTE(c->sub.lit)
- s->mode = CODES_START;
- break;
- case CODES_WASH: /* o: got eob, possibly more output */
- if (k > 7) /* return unused byte, if any */
- {
- k -= 8;
- n++;
- p--; /* can always return one */
- }
- /* flushing will be done in DRY */
-
-#undef j
-#undef e
-#undef f
-
- case DRY:
- FLUSH
- if (s->write != s->read)
- LEAVE(Z_OK)
- if (s->mode == CODES_WASH)
- {
- 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))));
- }
- /* DRY if last, TYPE if not */
- s->mode = s->last;
- if (s->mode == TYPE)
- break;
- LEAVE(Z_STREAM_END)
- //case BAD:
- //r = Z_DATA_ERROR;
- //LEAVE
- default: // we'll call Z_STREAM_ERROR if BAD anyway
- bad:
- s->mode = BAD;
- LEAVE(Z_STREAM_ERROR)
- }
-}
-
-#undef t
-#undef b
-#undef k
-#undef p
-#undef n
-#undef q
-#undef m
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#include "../Platform.h" +#include "../exehead/config.h" + +#include "ZUTIL.H" + +#ifndef min +# define min(x,y) ((x<y)?x:y) +#endif + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE(r) {UPDATE inflate_flush(z); return r;} + +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} + + +#define NEEDBYTE {if(!n)LEAVE(Z_OK)} +#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 inflate_flush(z); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE(Z_OK)}}} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +#define LAST (s->last == DRY) + +#define FIXEDH 544 /* number of hufts used by fixed tables */ + + + +typedef struct inflate_blocks_state FAR inflate_blocks_statef; +#define exop word.what.Exop +#define bits word.what.Bits + +/* And'ing with mask[n] masks the lower n bits */ +local unsigned short inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; // use to reduce .data #define INFLATE_MASK(x, n) (x & (~((unsigned short) 0xFFFF << n))) +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}; + +/* 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}; + +/* build fixed tables only once--keep them here */ +local char fixed_built = 0; +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl=9; +local uInt fixed_bd=5; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; + +/* copy as much as possible from the sliding window to the output area */ +local void ZEXPORT inflate_flush(z) +z_streamp z; +{ + inflate_blocks_statef *s = &z->blocks; + uInt n; + Bytef *q; + + /* local copies of source and destination pointers */ + q = s->read; + +again: + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + n = min(n, z->avail_out); + + /* update counters */ + z->avail_out -= n; + //z->total_out += n; + + /* copy as far as end of window */ + zmemcpy(z->next_out, q, n); + z->next_out += 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; + + /* do the same for the beginning of the window */ + goto again; + } + + /* update pointers */ + s->read = q; +} + +#define BMAX 15 /* maximum bit length of any code */ + +local int ZEXPORT 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--) + { + int nextw=w; + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > (nextw=w + l)) + { + h++; + + /* compute minimum size table less than or equal to l bits */ + z = g - nextw; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - nextw)) > 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 && (f <<= 1) > *++xp) /* try smaller tables up to z 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; + 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 */ + w=nextw; /* previous table always l bits */ + } + + /* 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 ZEXPORT inflate(z_streamp z) +{ + inflate_blocks_statef *s = &z->blocks; + inflate_codes_statef *c = &s->sub.decode.t_codes; /* codes state */ + + // lousy two bytes saved by doing this + struct + { + 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 */ + + /* CODES variables */ + + inflate_huft *j; /* temporary pointer */ + uInt e; /* extra bits or operation */ + Bytef *f; /* pointer to copy strings from */ + } _state; + +#define t _state.t +#define b _state.b +#define k _state.k +#define p _state.p +#define n _state.n +#define q _state.q +#define m _state.m + + /* 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; + DUMPBITS(3) + s->last = (t & 1) ? DRY : TYPE; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + LAST ? " (last)" : "")); + DUMPBITS(k&7) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + LAST ? " (last)" : "")); + { + 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 < 288; _k++) + { + char v=8; + if (_k > 143) + { + if (_k < 256) v++; + else if (_k < 280) v--; + } + c[_k] = v; + } + + 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; + + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, fixed_mem, &f); + + /* done */ + fixed_built++; + } + + //s->sub.decode.t_codes.mode = CODES_START; + s->sub.decode.t_codes.lbits = (Byte)fixed_bl; + s->sub.decode.t_codes.dbits = (Byte)fixed_bd; + s->sub.decode.t_codes.ltree = fixed_tl; + s->sub.decode.t_codes.dtree = fixed_td; + } + s->mode = CODES_START; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + LAST ? " (last)" : "")); + s->mode = TABLE; + break; + case 3: /* illegal */ + /* the only illegal value possible is 3 because we check only 2 bits */ + goto bad; + } + break; + case LENS: + NEEDBITS(16) + 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; + break; + case STORED: + { + uInt mn; + + if (n == 0) + LEAVE(Z_OK) + NEEDOUT + mn = min(m, n); + t = min(s->sub.left, mn); + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if (!(s->sub.left -= t)) + s->mode = s->last; + break; + } + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + LEAVE(Z_DATA_ERROR); + } + //t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + 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.t_blens[(int)border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.t_blens[(int)border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + + { + uInt hn = 0; /* hufts used in space */ + + t = huft_build(s->sub.trees.t_blens, 19, 19, (short *)Z_NULL, (short*)Z_NULL, + &s->sub.trees.tb, &s->sub.trees.bb, s->hufts, &hn); + if (t != Z_OK || !s->sub.trees.bb) + { + s->mode = BAD; + break; + } + } + + 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.t_blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + if (c == 18) + { + i=7; + j=11; + } + else + { + i=c-14; + j=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)) + { + s->mode = BAD; + LEAVE(Z_DATA_ERROR); + } + c = c == 16 ? s->sub.trees.t_blens[i - 1] : 0; + do { + s->sub.trees.t_blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt hn = 0; /* hufts used in space */ + uInt bl, bd; + inflate_huft *tl, *td; + int nl,nd; + t = s->sub.trees.table; + + nl = 257 + (t & 0x1f); + nd = 1 + ((t >> 5) & 0x1f); + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + + t = huft_build(s->sub.trees.t_blens, nl, 257, cplens, cplext, &tl, &bl, s->hufts, &hn); + if (bl == 0) t = Z_DATA_ERROR; + if (t == Z_OK) + { + /* build distance tree */ + t = huft_build(s->sub.trees.t_blens + nl, nd, 0, cpdist, cpdext, &td, &bd, s->hufts, &hn); + } + if (t != Z_OK || (bd == 0 && nl > 257)) + { + s->mode = BAD; + LEAVE(Z_DATA_ERROR); + } + Tracev((stderr, "inflate: trees ok\n")); + + //s->sub.decode.t_codes.mode = CODES_START; + s->sub.decode.t_codes.lbits = (Byte)bl; + s->sub.decode.t_codes.dbits = (Byte)bd; + s->sub.decode.t_codes.ltree = tl; + s->sub.decode.t_codes.dtree = td; + } + s->mode = CODES_START; + +#define j (_state.j) +#define e (_state.e) +#define f (_state.f) + + /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + + case CODES_START: /* x: set up for LEN */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + s->mode = CODES_LEN; + case CODES_LEN: /* i: get length/literal/eob next */ + t = c->sub.code.need; + NEEDBITS(t) + j = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[t]); + DUMPBITS(j->bits) + e = (uInt)(j->exop); + if (e == 0) /* literal */ + { + c->sub.lit = j->base; + s->mode = CODES_LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = j->base; + s->mode = CODES_LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = j + j->base; + break; + } + if (e & 32) /* end of block */ + { + s->mode = CODES_WASH; + break; + } + goto bad; + case CODES_LENEXT: /* i: getting length extra (have base) */ + t = c->sub.copy.get; + NEEDBITS(t) + c->len += (uInt)b & (uInt)inflate_mask[t]; + DUMPBITS(t) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + s->mode = CODES_DIST; + case CODES_DIST: /* i: get distance next */ + t = c->sub.code.need; + NEEDBITS(t) + j = c->sub.code.tree + ((uInt)b & (uInt)inflate_mask[t]); + DUMPBITS(j->bits) + e = (uInt)(j->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = j->base; + s->mode = CODES_DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = j + j->base; + break; + } + goto bad; /* invalid code */ + case CODES_DISTEXT: /* i: getting distance extra */ + t = c->sub.copy.get; + NEEDBITS(t) + c->sub.copy.dist += (uInt)b & (uInt)inflate_mask[t]; + DUMPBITS(t) + s->mode = CODES_COPY; + case CODES_COPY: /* o: copying bytes in window, waiting for space */ + f = (uInt)(q - s->window) < c->sub.copy.dist ? + s->end - (c->sub.copy.dist - (q - s->window)) : + q - c->sub.copy.dist; + + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + s->mode = CODES_START; + break; + case CODES_LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + s->mode = CODES_START; + break; + case CODES_WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + k -= 8; + n++; + p--; /* can always return one */ + } + /* flushing will be done in DRY */ + +#undef j +#undef e +#undef f + + case DRY: + FLUSH + if (s->write != s->read) + LEAVE(Z_OK) + if (s->mode == CODES_WASH) + { + 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)))); + } + /* DRY if last, TYPE if not */ + s->mode = s->last; + if (s->mode == TYPE) + break; + LEAVE(Z_STREAM_END) + //case BAD: + //r = Z_DATA_ERROR; + //LEAVE + default: // we'll call Z_STREAM_ERROR if BAD anyway + bad: + s->mode = BAD; + LEAVE(Z_STREAM_ERROR) + } +} + +#undef t +#undef b +#undef k +#undef p +#undef n +#undef q +#undef m diff --git a/Source/zlib/ZCONF.H b/Source/zlib/ZCONF.H index 6ca8fb5..d465607 100755 --- a/Source/zlib/ZCONF.H +++ b/Source/zlib/ZCONF.H @@ -1,71 +1,71 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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: ZCONF.H,v 1.3 2007/01/13 17:28:23 kichik Exp $ */
-
-#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 */
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* 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: ZCONF.H,v 1.2 2006/10/28 19:45:02 joostverburg Exp $ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + + +#define MAX_MEM_LEVEL 9 + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +#define OF(args) args + + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +typedef Byte FAR Bytef; +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +typedef void FAR *voidpf; +typedef void *voidp; + +#ifndef z_off_t +# define z_off_t long +#endif + + +#endif /* _ZCONF_H */ diff --git a/Source/zlib/ZLIB.H b/Source/zlib/ZLIB.H index e1ee3a4..1c983d8 100755 --- a/Source/zlib/ZLIB.H +++ b/Source/zlib/ZLIB.H @@ -1,297 +1,297 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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"
-#include "ZUTIL.H"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifdef EXEHEAD
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-
-
-typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- CODES_START, /* x: set up for LEN */
- CODES_LEN, /* i: get length/literal/eob next */
- CODES_LENEXT, /* i: getting length extra (have base) */
- CODES_DIST, /* i: get distance next */
- CODES_DISTEXT, /* i: getting distance extra */
- CODES_COPY, /* o: copying bytes in window, waiting for space */
- CODES_LIT, /* o: got literal, waiting for output space */
- CODES_WASH, /* o: got eob, possibly still output waiting */
- //CODES_END, /* x: got eob and all data flushed */
- //CODES_BADCODE, /* x: got error */
-
- 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_mode;
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
- /* mode */
- //inflate_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 */
-
-};
-
-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
-
-typedef struct inflate_codes_state inflate_codes_statef;
-
-struct inflate_blocks_state {
-
- /* mode */
- inflate_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 t_blens[258+31+31]; /* 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 t_codes;
- } decode; /* if CODES, current state */
- } sub; /* submode */
-
- uInt last; /* DRY if this block is the last block, TYPE otherwise */
-
- /* 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 << MAX_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 */
-
-};
-
-
-
-#else
-struct internal_state;
-#endif
-
-typedef struct z_stream_s {
- Bytef *next_in; /* next input byte */
- uInt avail_in; /* number of bytes available at next_in */
-#ifndef EXEHEAD
- uLong total_in; /* total nb of input bytes read so far */
-#endif
-
- Bytef *next_out; /* next output byte should be put there */
- uInt avail_out; /* remaining free space at next_out */
-#ifndef EXEHEAD
- uLong total_out; /* total nb of bytes output so far */
-#endif
-
-// char *msg; /* last error message, NULL if no error */
- //struct internal_state FAR *state; /* not visible by applications */
-#ifdef EXEHEAD
- struct inflate_blocks_state blocks; /* current inflate_blocks state */
-#else
- struct internal_state *state;
-#endif
-
-} 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)
-
-#ifndef EXEHEAD
-
-#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)
-
-#else
-// EXEHEAD doesn't need a specific return code, just < 0
-
-#define Z_STREAM_ERROR Z_ERRNO
-#define Z_DATA_ERROR Z_ERRNO
-#define Z_MEM_ERROR Z_ERRNO
-#define Z_BUF_ERROR Z_ERRNO
-#define Z_VERSION_ERROR Z_ERRNO
-
-#endif
-/* 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));
-
-
-#define inflateInit(x) inflateReset(x)
-int ZEXPORT 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));
-
-//void ZEXPORT inflateReset OF((
- // z_streamp));
-#define inflateReset(z) \
-{ \
- (z)->blocks.mode = TYPE; \
- (z)->blocks.bitk = (z)->blocks.bitb = 0; \
- (z)->blocks.read = (z)->blocks.write = (z)->blocks.window; \
- (z)->blocks.end = (z)->blocks.window + (1 << DEF_WBITS); \
-}
-
- /* 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));
-
-#define deflateInit(strm, level) \
- deflateInit_((strm), (level), "", sizeof(z_stream))
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZLIB_H */
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* 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" +#include "ZUTIL.H" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef EXEHEAD + +typedef struct inflate_huft_s FAR inflate_huft; + + + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + CODES_START, /* x: set up for LEN */ + CODES_LEN, /* i: get length/literal/eob next */ + CODES_LENEXT, /* i: getting length extra (have base) */ + CODES_DIST, /* i: get distance next */ + CODES_DISTEXT, /* i: getting distance extra */ + CODES_COPY, /* o: copying bytes in window, waiting for space */ + CODES_LIT, /* o: got literal, waiting for output space */ + CODES_WASH, /* o: got eob, possibly still output waiting */ + //CODES_END, /* x: got eob and all data flushed */ + //CODES_BADCODE, /* x: got error */ + + 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_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + //inflate_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 */ + +}; + +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 + +typedef struct inflate_codes_state inflate_codes_statef; + +struct inflate_blocks_state { + + /* mode */ + inflate_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 t_blens[258+31+31]; /* 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 t_codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + + uInt last; /* DRY if this block is the last block, TYPE otherwise */ + + /* 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 << MAX_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 */ + +}; + + + +#else +struct internal_state; +#endif + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ +#ifndef EXEHEAD + uLong total_in; /* total nb of input bytes read so far */ +#endif + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ +#ifndef EXEHEAD + uLong total_out; /* total nb of bytes output so far */ +#endif + +// char *msg; /* last error message, NULL if no error */ + //struct internal_state FAR *state; /* not visible by applications */ +#ifdef EXEHEAD + struct inflate_blocks_state blocks; /* current inflate_blocks state */ +#else + struct internal_state *state; +#endif + +} 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) + +#ifndef EXEHEAD + +#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) + +#else +// EXEHEAD doesn't need a specific return code, just < 0 + +#define Z_STREAM_ERROR Z_ERRNO +#define Z_DATA_ERROR Z_ERRNO +#define Z_MEM_ERROR Z_ERRNO +#define Z_BUF_ERROR Z_ERRNO +#define Z_VERSION_ERROR Z_ERRNO + +#endif +/* 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)); + + +#define inflateInit(x) inflateReset(x) +int ZEXPORT 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)); + +//void ZEXPORT inflateReset OF(( + // z_streamp)); +#define inflateReset(z) \ +{ \ + (z)->blocks.mode = TYPE; \ + (z)->blocks.bitk = (z)->blocks.bitb = 0; \ + (z)->blocks.read = (z)->blocks.write = (z)->blocks.window; \ + (z)->blocks.end = (z)->blocks.window + (1 << DEF_WBITS); \ +} + + /* 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)); + +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), "", sizeof(z_stream)) + + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/Source/zlib/ZUTIL.H b/Source/zlib/ZUTIL.H index 67defc5..cf27a2c 100755 --- a/Source/zlib/ZUTIL.H +++ b/Source/zlib/ZUTIL.H @@ -1,85 +1,85 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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: ZUTIL.H,v 1.6 2007/01/25 18:07:40 kichik Exp $ */
-
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
-
-#include "../Platform.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
-# ifdef _WIN32
-# include "../exehead/util.h"
-# define zmemcpy mini_memcpy
-# else
-# define zmemcpy memcpy
-# endif
-#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) malloc((items)*(size))
-#define ZFREE(strm, addr) { if (addr) free(addr); }
-#define TRY_FREE(s, p) { ZFREE(s, p); }
-#define ERR_RETURN(strm,err) return (err)
-
-#endif /* _Z_UTIL_H */
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* 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: ZUTIL.H,v 1.5 2007/01/13 17:28:23 kichik Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "../Platform.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 +# ifdef _WIN32 +# include "../exehead/util.h" +# define zmemcpy mini_memcpy +# else +# define zmemcpy memcpy +# endif +#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) malloc((items)*(size)) +#define ZFREE(strm, addr) { if (addr) free(addr); } +#define TRY_FREE(s, p) { ZFREE(s, p); } +#define ERR_RETURN(strm,err) return (err) + +#endif /* _Z_UTIL_H */ diff --git a/Source/zlib/deflate.c b/Source/zlib/deflate.c index 1b74143..6cd5bc2 100755 --- a/Source/zlib/deflate.c +++ b/Source/zlib/deflate.c @@ -1,857 +1,857 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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_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 32767 //stock is 4096, but 32767 enables slightly better compression
-#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 =
-/* 9 */ {32, 258, 258, 16384, 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;
-
-
- 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 > MAX_WBITS || 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.func;
-
- s->level = level;
- s->max_lazy_match = configuration_table.max_lazy;
- s->good_match = configuration_table.good_length;
- s->nice_match = configuration_table.nice_length;
- s->max_chain_length = configuration_table.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.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.max_lazy;
- s->good_match = configuration_table.good_length;
- s->nice_match = configuration_table.nice_length;
- s->max_chain_length = configuration_table.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
-# error 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_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;
-}
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* 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_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 32767 //stock is 4096, but 32767 enables slightly better compression +#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 = +/* 9 */ {32, 258, 258, 16384, 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; + + + 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 > MAX_WBITS || 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.func; + + s->level = level; + s->max_lazy_match = configuration_table.max_lazy; + s->good_match = configuration_table.good_length; + s->nice_match = configuration_table.nice_length; + s->max_chain_length = configuration_table.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.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.max_lazy; + s->good_match = configuration_table.good_length; + s->nice_match = configuration_table.nice_length; + s->max_chain_length = configuration_table.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 +# error 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_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + s->match_length = MIN_MATCH-1; + } + } + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/Source/zlib/trees.c b/Source/zlib/trees.c index eb1a5af..43377e5 100755 --- a/Source/zlib/trees.c +++ b/Source/zlib/trees.c @@ -1,894 +1,894 @@ -/*
- * This file is a part of the zlib compression module for NSIS.
- *
- * Copyright and license information can be found below.
- * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors
- *
- * The original zlib source code is available at
- * http://www.zlib.net/
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.
- */
-
-/* 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);
-#ifdef DEBUG
- s->bits_sent += 2*16;
-#endif
- }
-#ifdef DEBUG
- s->bits_sent += (ulg)len<<3;
-#endif
- while (len--) {
- put_byte(s, *buf++);
- }
-}
+/* + * This file is a part of the zlib compression module for NSIS. + * + * Copyright and license information can be found below. + * Modifications Copyright (C) 1999-2007 Nullsoft and Contributors + * + * The original zlib source code is available at + * http://www.zlib.net/ + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +/* 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); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} |