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