1 #include "affconfig.h"
2 #include "afflib.h"
3 #include "afflib_i.h"
4
5 /*
6 * Distributed under the Berkeley 4-part license
7 * Simson L. Garfinkel, March 12, 2012
8 */
9
10
11 #include "../../../Common/MyWindows.h"
12 #include "../../../Common/MyInitGuid.h"
13 #include "../../Common/FileStreams.h"
14 #include "../../Common/StreamUtils.h"
15 #include "../LZMA/LZMADecoder.h"
16 #include "../LZMA/LZMAEncoder.h"
17 #include "LzmaBench.h"
18
19 #include "LzmaRam.h"
20 extern "C" {
21 #include "LzmaRamDecode.h"
22 }
23
24 class CInMemoryStream: public ISequentialInStream, public CMyUnknownImp {
25 public:
26 const unsigned char *buf;
27 size_t buflen;
28 size_t ptr;
~CInMemoryStream()29 virtual ~CInMemoryStream(){}
CInMemoryStream(const unsigned char * buf_,size_t len)30 CInMemoryStream(const unsigned char *buf_,size_t len){
31 buf = buf_;
32 buflen = len;
33 ptr = 0;
34 }
35
36 MY_UNKNOWN_IMP1(IInStream)
STDMETHOD(Read)37 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize){
38 if(ptr+size > buflen) size = buflen - ptr; // max that can be read
39 memcpy(data,buf+ptr,size);
40 ptr += size;
41 if(processedSize) *processedSize = size;
42 return S_OK;
43 }
44 };
45
46
47 class COutMemoryStream: public ISequentialOutStream, public CMyUnknownImp {
48 public:
49 unsigned char *buf;
50 size_t buflen;
51 size_t ptr;
52 size_t *notify;
~COutMemoryStream()53 virtual ~COutMemoryStream(){}
COutMemoryStream(unsigned char * buf_,size_t len,size_t * notify_)54 COutMemoryStream(unsigned char *buf_,size_t len,size_t *notify_){
55 buf = buf_;
56 buflen = len;
57 ptr = 0;
58 notify = notify_;
59 }
60
STDMETHOD(Write)61 MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size,
62 UInt32 *processedSize){
63 if(ptr+size > buflen) return E_FAIL;
64 memcpy(buf+ptr,data,size);
65 ptr += size;
66 if(processedSize) *processedSize = size;
67 if(notify) *notify = ptr;
68 return S_OK;
69 }
70 };
71
72 /*
73 * Attempt to compress. Return -1 if fail.
74 * (Fails if compression results in expansion.
75 */
76
lzma_compress(unsigned char * dest,size_t * destLen,const unsigned char * data,size_t datalen,int level)77 int lzma_compress(unsigned char *dest,size_t *destLen,const unsigned char *data,size_t datalen,int level)
78 {
79 PROPID propIDs[] = {
80 NCoderPropID::kDictionarySize,
81 NCoderPropID::kPosStateBits,
82 NCoderPropID::kLitContextBits,
83 NCoderPropID::kLitPosBits,
84 NCoderPropID::kAlgorithm,
85 NCoderPropID::kNumFastBytes,
86 NCoderPropID::kMatchFinder,
87 NCoderPropID::kEndMarker
88 };
89 const int nprops = sizeof(propIDs) / sizeof(propIDs[0]);
90 PROPVARIANT p[nprops];
91
92 p[0].vt = VT_UI4; p[0].ulVal = UInt32(1 << 24);
93 p[1].vt = VT_UI4; p[1].ulVal = UInt32(2); // posBits
94 p[2].vt = VT_UI4; p[2].ulVal = UInt32(3); // literal context bits
95 p[3].vt = VT_UI4; p[3].ulVal = UInt32(0); // literal pos bits
96 p[4].vt = VT_UI4; p[4].ulVal = UInt32(2); // compression mode
97 p[5].vt = VT_UI4; p[5].ulVal = UInt32(128); // fast_bytes
98
99 // old code generates warnings now
100 //p[6].vt = VT_BSTR; p[6].bstrVal = L"bt4"; // it's okay; we won't change it
101
102 // new code
103 const void *temp = L"bt4";
104 p[6].vt = VT_BSTR; p[6].bstrVal = (OLECHAR *)temp; // it's okay; we won't change it
105
106 p[7].vt = VT_BOOL; p[7].boolVal = VARIANT_FALSE;
107
108 NCompress::NLZMA::CEncoder *encoder = new NCompress::NLZMA::CEncoder;
109
110 if (encoder->SetCoderProperties(propIDs, p, nprops) != S_OK){
111 return -1; /* Couldn't set encoder properties */
112 }
113
114 /* Open and configure the output stream */
115 UInt64 fileSize = datalen;
116 COutMemoryStream *outStream = new COutMemoryStream(dest,*destLen,destLen);
117 outStream->AddRef();
118
119 encoder->WriteCoderProperties(outStream);
120
121 for (int i = 0; i < 8; i++) {
122 Byte b = Byte(fileSize >> (8 * i));
123 if (outStream->Write(&b, sizeof(b), 0) != S_OK){
124 outStream->Release();
125 return -1; /* Write error while encoding */
126 }
127 }
128
129 CInMemoryStream *inStream = new CInMemoryStream(data,datalen);
130 inStream->AddRef();
131 HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0);
132 inStream->Release();
133 outStream->Release();
134 delete(encoder);
135
136 return result;
137 }
138
139
lzma_uncompress(unsigned char * buf,size_t * buflen,const unsigned char * cbuf,size_t cbuf_size)140 int lzma_uncompress(unsigned char *buf,size_t *buflen, const unsigned char *cbuf,size_t cbuf_size)
141 {
142 CInMemoryStream *inStream = new CInMemoryStream(cbuf,cbuf_size);
143 inStream->AddRef();
144
145 const UInt32 kPropertiesSize = 5;
146 Byte properties[kPropertiesSize];
147 UInt32 processedSize;
148 UInt64 fileSize = 0;
149 NCompress::NLZMA::CDecoder decoderSpec;
150
151 if (inStream->Read(properties, kPropertiesSize, &processedSize) != S_OK){
152 inStream->Release();
153 return -1;
154 }
155 if (processedSize != kPropertiesSize) return -1;
156 if (decoderSpec.SetDecoderProperties2(properties, kPropertiesSize) != S_OK){
157 inStream->Release();
158 return -1;
159 }
160
161 for (int i = 0; i < 8; i++) {
162 Byte b;
163 if (inStream->Read(&b, sizeof(b), &processedSize) != S_OK) return -1;
164 if (processedSize != 1){
165 inStream->Release();
166 return -1;
167 }
168 fileSize |= ((UInt64)b) << (8 * i);
169 }
170
171 COutMemoryStream *outStream = new COutMemoryStream(buf,*buflen,buflen);
172 outStream->AddRef();
173 int r = decoderSpec.Code(inStream, outStream, 0, &fileSize, 0);
174 inStream->Release();
175 outStream->Release();
176 return r;
177 }
178
179