1 #include "rar.hpp"
2
ComprDataIO()3 ComprDataIO::ComprDataIO()
4 {
5 Init();
6 }
7
8
Init()9 void ComprDataIO::Init()
10 {
11 UnpackFromMemory=false;
12 UnpackToMemory=false;
13 UnpPackedSize=0;
14 ShowProgress=true;
15 TestMode=false;
16 SkipUnpCRC=false;
17 PackVolume=false;
18 UnpVolume=false;
19 NextVolumeMissing=false;
20 SrcFile=NULL;
21 DestFile=NULL;
22 UnpWrSize=0;
23 Command=NULL;
24 Encryption=0;
25 Decryption=0;
26 TotalPackRead=0;
27 CurPackRead=CurPackWrite=CurUnpRead=CurUnpWrite=0;
28 PackFileCRC=UnpFileCRC=PackedCRC=0xffffffff;
29 LastPercent=-1;
30 SubHead=NULL;
31 SubHeadPos=NULL;
32 CurrentCommand=0;
33 ProcessedArcSize=TotalArcSize=0;
34 }
35
36
37
38
UnpRead(byte * Addr,size_t Count)39 int ComprDataIO::UnpRead(byte *Addr,size_t Count)
40 {
41 int RetCode=0,TotalRead=0;
42 byte *ReadAddr;
43 ReadAddr=Addr;
44 while (Count > 0)
45 {
46 Archive *SrcArc=(Archive *)SrcFile;
47
48 size_t ReadSize=((int64)Count>UnpPackedSize) ? (size_t)UnpPackedSize:Count;
49 if (UnpackFromMemory)
50 {
51 memcpy(Addr,UnpackFromMemoryAddr,UnpackFromMemorySize);
52 RetCode=(int)UnpackFromMemorySize;
53 UnpackFromMemorySize=0;
54 }
55 else
56 {
57 if (!SrcFile->IsOpened())
58 return(-1);
59 RetCode=SrcFile->Read(ReadAddr,ReadSize);
60 FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->NewLhd;
61 if (hd->Flags & LHD_SPLIT_AFTER)
62 PackedCRC=CRC(PackedCRC,ReadAddr,RetCode);
63 }
64 CurUnpRead+=RetCode;
65 TotalRead+=RetCode;
66 #ifndef NOVOLUME
67 // These variable are not used in NOVOLUME mode, so it is better
68 // to exclude commands below to avoid compiler warnings.
69 ReadAddr+=RetCode;
70 Count-=RetCode;
71 #endif
72 UnpPackedSize-=RetCode;
73 if (UnpPackedSize == 0 && UnpVolume)
74 {
75 #ifndef NOVOLUME
76 if (!MergeArchive(*SrcArc,this,true,CurrentCommand))
77 #endif
78 {
79 NextVolumeMissing=true;
80 return(-1);
81 }
82 }
83 else
84 break;
85 }
86 Archive *SrcArc=(Archive *)SrcFile;
87 if (SrcArc!=NULL)
88 ShowUnpRead(SrcArc->CurBlockPos+CurUnpRead,UnpArcSize);
89 if (RetCode!=-1)
90 {
91 RetCode=TotalRead;
92 #ifndef RAR_NOCRYPT
93 if (Decryption)
94 #ifndef SFX_MODULE
95 if (Decryption<20)
96 Decrypt.Crypt(Addr,RetCode,(Decryption==15) ? NEW_CRYPT : OLD_DECODE);
97 else
98 if (Decryption==20)
99 for (int I=0;I<RetCode;I+=16)
100 Decrypt.DecryptBlock20(&Addr[I]);
101 else
102 #endif
103 {
104 int CryptSize=(RetCode & 0xf)==0 ? RetCode:((RetCode & ~0xf)+16);
105 Decrypt.DecryptBlock(Addr,CryptSize);
106 }
107 #endif
108 }
109 Wait();
110 return(RetCode);
111 }
112
113
114 #if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
115 // Disable the run time stack check for unrar.dll, so we can manipulate
116 // with ProcessDataProc call type below. Run time check would intercept
117 // a wrong ESP before we restore it.
118 #pragma runtime_checks( "s", off )
119 #endif
120
UnpWrite(byte * Addr,size_t Count)121 void ComprDataIO::UnpWrite(byte *Addr,size_t Count)
122 {
123
124 #ifdef RARDLL
125 RAROptions *Cmd=((Archive *)SrcFile)->GetRAROptions();
126 if (Cmd->DllOpMode!=RAR_SKIP)
127 {
128 if (Cmd->Callback!=NULL &&
129 Cmd->Callback(UCM_PROCESSDATA,Cmd->UserData,(LPARAM)Addr,Count)==-1)
130 ErrHandler.Exit(USER_BREAK);
131 if (Cmd->ProcessDataProc!=NULL)
132 {
133 // Here we preserve ESP value. It is necessary for those developers,
134 // who still define ProcessDataProc callback as "C" type function,
135 // even though in year 2001 we announced in unrar.dll whatsnew.txt
136 // that it will be PASCAL type (for compatibility with Visual Basic).
137 #if defined(_MSC_VER)
138 #ifndef _WIN_64
139 __asm mov ebx,esp
140 #endif
141 #elif defined(_WIN_ALL) && defined(__BORLANDC__)
142 _EBX=_ESP;
143 #endif
144 int RetCode=Cmd->ProcessDataProc(Addr,(int)Count);
145
146 // Restore ESP after ProcessDataProc with wrongly defined calling
147 // convention broken it.
148 #if defined(_MSC_VER)
149 #ifndef _WIN_64
150 __asm mov esp,ebx
151 #endif
152 #elif defined(_WIN_ALL) && defined(__BORLANDC__)
153 _ESP=_EBX;
154 #endif
155 if (RetCode==0)
156 ErrHandler.Exit(USER_BREAK);
157 }
158 }
159 #endif // RARDLL
160
161 UnpWrAddr=Addr;
162 UnpWrSize=Count;
163 if (UnpackToMemory)
164 {
165 if (Count <= UnpackToMemorySize)
166 {
167 memcpy(UnpackToMemoryAddr,Addr,Count);
168 UnpackToMemoryAddr+=Count;
169 UnpackToMemorySize-=Count;
170 }
171 }
172 else
173 if (!TestMode)
174 DestFile->Write(Addr,Count);
175 CurUnpWrite+=Count;
176 if (!SkipUnpCRC)
177 #ifndef SFX_MODULE
178 if (((Archive *)SrcFile)->OldFormat)
179 UnpFileCRC=OldCRC((ushort)UnpFileCRC,Addr,Count);
180 else
181 #endif
182 UnpFileCRC=CRC(UnpFileCRC,Addr,Count);
183 ShowUnpWrite();
184 Wait();
185 }
186
187 #if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
188 // Restore the run time stack check for unrar.dll.
189 #pragma runtime_checks( "s", restore )
190 #endif
191
192
193
194
195
196
ShowUnpRead(int64 ArcPos,int64 ArcSize)197 void ComprDataIO::ShowUnpRead(int64 ArcPos,int64 ArcSize)
198 {
199 if (ShowProgress && SrcFile!=NULL)
200 {
201 if (TotalArcSize!=0)
202 {
203 // important when processing several archives or multivolume archive
204 ArcSize=TotalArcSize;
205 ArcPos+=ProcessedArcSize;
206 }
207
208 Archive *SrcArc=(Archive *)SrcFile;
209 RAROptions *Cmd=SrcArc->GetRAROptions();
210
211 int CurPercent=ToPercent(ArcPos,ArcSize);
212 if (!Cmd->DisablePercentage && CurPercent!=LastPercent)
213 {
214 mprintf("\b\b\b\b%3d%%",CurPercent);
215 LastPercent=CurPercent;
216 }
217 }
218 }
219
220
ShowUnpWrite()221 void ComprDataIO::ShowUnpWrite()
222 {
223 }
224
225
226
227
228
229
230
231
SetFiles(File * SrcFile,File * DestFile)232 void ComprDataIO::SetFiles(File *SrcFile,File *DestFile)
233 {
234 if (SrcFile!=NULL)
235 ComprDataIO::SrcFile=SrcFile;
236 if (DestFile!=NULL)
237 ComprDataIO::DestFile=DestFile;
238 LastPercent=-1;
239 }
240
241
GetUnpackedData(byte ** Data,size_t * Size)242 void ComprDataIO::GetUnpackedData(byte **Data,size_t *Size)
243 {
244 *Data=UnpWrAddr;
245 *Size=UnpWrSize;
246 }
247
248
SetEncryption(int Method,const wchar * Password,const byte * Salt,bool Encrypt,bool HandsOffHash)249 void ComprDataIO::SetEncryption(int Method,const wchar *Password,const byte *Salt,bool Encrypt,bool HandsOffHash)
250 {
251 if (Encrypt)
252 {
253 Encryption=*Password ? Method:0;
254 #ifndef RAR_NOCRYPT
255 Crypt.SetCryptKeys(Password,Salt,Encrypt,false,HandsOffHash);
256 #endif
257 }
258 else
259 {
260 Decryption=*Password ? Method:0;
261 #ifndef RAR_NOCRYPT
262 Decrypt.SetCryptKeys(Password,Salt,Encrypt,Method<29,HandsOffHash);
263 #endif
264 }
265 }
266
267
268 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
SetAV15Encryption()269 void ComprDataIO::SetAV15Encryption()
270 {
271 Decryption=15;
272 Decrypt.SetAV15Encryption();
273 }
274 #endif
275
276
277 #if !defined(SFX_MODULE) && !defined(RAR_NOCRYPT)
SetCmt13Encryption()278 void ComprDataIO::SetCmt13Encryption()
279 {
280 Decryption=13;
281 Decrypt.SetCmt13Encryption();
282 }
283 #endif
284
285
286
287
SetUnpackToMemory(byte * Addr,uint Size)288 void ComprDataIO::SetUnpackToMemory(byte *Addr,uint Size)
289 {
290 UnpackToMemory=true;
291 UnpackToMemoryAddr=Addr;
292 UnpackToMemorySize=Size;
293 }
294
295
296