"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/dll.cpp" (4 May 2022, 13506 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "dll.cpp" see the
Fossies "Dox" file reference documentation.
1 #include "rar.hpp"
2
3 static int RarErrorToDll(RAR_EXIT ErrCode);
4
5 struct DataSet
6 {
7 CommandData Cmd;
8 Archive Arc;
9 CmdExtract Extract;
10 int OpenMode;
11 int HeaderSize;
12
13 DataSet():Arc(&Cmd),Extract(&Cmd) {};
14 };
15
16
17 HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
18 {
19 RAROpenArchiveDataEx rx;
20 memset(&rx,0,sizeof(rx));
21 rx.ArcName=r->ArcName;
22 rx.OpenMode=r->OpenMode;
23 rx.CmtBuf=r->CmtBuf;
24 rx.CmtBufSize=r->CmtBufSize;
25 HANDLE hArc=RAROpenArchiveEx(&rx);
26 r->OpenResult=rx.OpenResult;
27 r->CmtSize=rx.CmtSize;
28 r->CmtState=rx.CmtState;
29 return hArc;
30 }
31
32
33 HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
34 {
35 DataSet *Data=NULL;
36 try
37 {
38 ErrHandler.Clean();
39
40 r->OpenResult=0;
41 Data=new DataSet;
42 Data->Cmd.DllError=0;
43 Data->OpenMode=r->OpenMode;
44 Data->Cmd.FileArgs.AddString(L"*");
45 Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
46
47 char AnsiArcName[NM];
48 *AnsiArcName=0;
49 if (r->ArcName!=NULL)
50 {
51 strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
52 #ifdef _WIN_ALL
53 if (!AreFileApisANSI())
54 {
55 OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
56 AnsiArcName[ASIZE(AnsiArcName)-1]=0;
57 }
58 #endif
59 }
60
61 wchar ArcName[NM];
62 GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
63
64 Data->Cmd.AddArcName(ArcName);
65 Data->Cmd.Overwrite=OVERWRITE_ALL;
66 Data->Cmd.VersionControl=1;
67
68 Data->Cmd.Callback=r->Callback;
69 Data->Cmd.UserData=r->UserData;
70
71 // Open shared mode is added by request of dll users, who need to
72 // browse and unpack archives while downloading.
73 Data->Cmd.OpenShared = true;
74 if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
75 {
76 r->OpenResult=ERAR_EOPEN;
77 delete Data;
78 return NULL;
79 }
80 if (!Data->Arc.IsArchive(true))
81 {
82 if (Data->Cmd.DllError!=0)
83 r->OpenResult=Data->Cmd.DllError;
84 else
85 {
86 RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
87 if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
88 r->OpenResult=RarErrorToDll(ErrCode);
89 else
90 r->OpenResult=ERAR_BAD_ARCHIVE;
91 }
92 delete Data;
93 return NULL;
94 }
95 r->Flags=0;
96
97 if (Data->Arc.Volume)
98 r->Flags|=ROADF_VOLUME;
99 if (Data->Arc.MainComment)
100 r->Flags|=ROADF_COMMENT;
101 if (Data->Arc.Locked)
102 r->Flags|=ROADF_LOCK;
103 if (Data->Arc.Solid)
104 r->Flags|=ROADF_SOLID;
105 if (Data->Arc.NewNumbering)
106 r->Flags|=ROADF_NEWNUMBERING;
107 if (Data->Arc.Signed)
108 r->Flags|=ROADF_SIGNED;
109 if (Data->Arc.Protected)
110 r->Flags|=ROADF_RECOVERY;
111 if (Data->Arc.Encrypted)
112 r->Flags|=ROADF_ENCHEADERS;
113 if (Data->Arc.FirstVolume)
114 r->Flags|=ROADF_FIRSTVOLUME;
115
116 Array<wchar> CmtDataW;
117 if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
118 {
119 if (r->CmtBufW!=NULL)
120 {
121 CmtDataW.Push(0);
122 size_t Size=wcslen(&CmtDataW[0])+1;
123
124 r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
125 r->CmtSize=(uint)Min(Size,r->CmtBufSize);
126 memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
127 r->CmtBufW[r->CmtSize-1]=0;
128 }
129 else
130 if (r->CmtBuf!=NULL)
131 {
132 Array<char> CmtData(CmtDataW.Size()*4+1);
133 memset(&CmtData[0],0,CmtData.Size());
134 WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
135 size_t Size=strlen(&CmtData[0])+1;
136
137 r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
138 r->CmtSize=(uint)Min(Size,r->CmtBufSize);
139 memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
140 r->CmtBuf[r->CmtSize-1]=0;
141 }
142 }
143 else
144 r->CmtState=r->CmtSize=0;
145 Data->Extract.ExtractArchiveInit(Data->Arc);
146 return (HANDLE)Data;
147 }
148 catch (RAR_EXIT ErrCode)
149 {
150 if (Data!=NULL && Data->Cmd.DllError!=0)
151 r->OpenResult=Data->Cmd.DllError;
152 else
153 r->OpenResult=RarErrorToDll(ErrCode);
154 if (Data != NULL)
155 delete Data;
156 return NULL;
157 }
158 catch (std::bad_alloc&) // Catch 'new' exception.
159 {
160 r->OpenResult=ERAR_NO_MEMORY;
161 if (Data != NULL)
162 delete Data;
163 }
164 return NULL; // To make compilers happy.
165 }
166
167
168 int PASCAL RARCloseArchive(HANDLE hArcData)
169 {
170 DataSet *Data=(DataSet *)hArcData;
171 try
172 {
173 bool Success=Data==NULL ? false:Data->Arc.Close();
174 delete Data;
175 return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
176 }
177 catch (RAR_EXIT ErrCode)
178 {
179 return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
180 }
181 }
182
183
184 int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
185 {
186 struct RARHeaderDataEx X;
187 memset(&X,0,sizeof(X));
188
189 int Code=RARReadHeaderEx(hArcData,&X);
190
191 strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
192 strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
193 D->Flags=X.Flags;
194 D->PackSize=X.PackSize;
195 D->UnpSize=X.UnpSize;
196 D->HostOS=X.HostOS;
197 D->FileCRC=X.FileCRC;
198 D->FileTime=X.FileTime;
199 D->UnpVer=X.UnpVer;
200 D->Method=X.Method;
201 D->FileAttr=X.FileAttr;
202 D->CmtSize=0;
203 D->CmtState=0;
204
205 return Code;
206 }
207
208
209 int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
210 {
211 DataSet *Data=(DataSet *)hArcData;
212 try
213 {
214 if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
215 {
216 if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
217 Data->Arc.EndArcHead.NextVolume)
218 if (MergeArchive(Data->Arc,NULL,false,'L'))
219 {
220 Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
221 return RARReadHeaderEx(hArcData,D);
222 }
223 else
224 return ERAR_EOPEN;
225
226 if (Data->Arc.BrokenHeader)
227 return ERAR_BAD_DATA;
228
229 // Might be necessary if RARSetPassword is still called instead of
230 // open callback for RAR5 archives and if password is invalid.
231 if (Data->Arc.FailedHeaderDecryption)
232 return ERAR_BAD_PASSWORD;
233
234 return ERAR_END_ARCHIVE;
235 }
236 FileHeader *hd=&Data->Arc.FileHead;
237 if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
238 {
239 int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
240 if (Code==0)
241 return RARReadHeaderEx(hArcData,D);
242 else
243 return Code;
244 }
245 wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
246 WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
247
248 wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
249 WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
250 #ifdef _WIN_ALL
251 CharToOemA(D->FileName,D->FileName);
252 #endif
253
254 D->Flags=0;
255 if (hd->SplitBefore)
256 D->Flags|=RHDF_SPLITBEFORE;
257 if (hd->SplitAfter)
258 D->Flags|=RHDF_SPLITAFTER;
259 if (hd->Encrypted)
260 D->Flags|=RHDF_ENCRYPTED;
261 if (hd->Solid)
262 D->Flags|=RHDF_SOLID;
263 if (hd->Dir)
264 D->Flags|=RHDF_DIRECTORY;
265
266 D->PackSize=uint(hd->PackSize & 0xffffffff);
267 D->PackSizeHigh=uint(hd->PackSize>>32);
268 D->UnpSize=uint(hd->UnpSize & 0xffffffff);
269 D->UnpSizeHigh=uint(hd->UnpSize>>32);
270 D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
271 D->UnpVer=Data->Arc.FileHead.UnpVer;
272 D->FileCRC=hd->FileHash.CRC32;
273 D->FileTime=hd->mtime.GetDos();
274
275 uint64 MRaw=hd->mtime.GetWin();
276 D->MtimeLow=(uint)MRaw;
277 D->MtimeHigh=(uint)(MRaw>>32);
278 uint64 CRaw=hd->ctime.GetWin();
279 D->CtimeLow=(uint)CRaw;
280 D->CtimeHigh=(uint)(CRaw>>32);
281 uint64 ARaw=hd->atime.GetWin();
282 D->AtimeLow=(uint)ARaw;
283 D->AtimeHigh=(uint)(ARaw>>32);
284
285 D->Method=hd->Method+0x30;
286 D->FileAttr=hd->FileAttr;
287 D->CmtSize=0;
288 D->CmtState=0;
289
290 D->DictSize=uint(hd->WinSize/1024);
291
292 switch (hd->FileHash.Type)
293 {
294 case HASH_RAR14:
295 case HASH_CRC32:
296 D->HashType=RAR_HASH_CRC32;
297 break;
298 case HASH_BLAKE2:
299 D->HashType=RAR_HASH_BLAKE2;
300 memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
301 break;
302 default:
303 D->HashType=RAR_HASH_NONE;
304 break;
305 }
306
307 D->RedirType=hd->RedirType;
308 // RedirNameSize sanity check is useful in case some developer
309 // did not initialize Reserved area with 0 as required in docs.
310 // We have taken 'Redir*' fields from Reserved area. We may remove
311 // this RedirNameSize check sometimes later.
312 if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
313 D->RedirNameSize>0 && D->RedirNameSize<100000)
314 wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
315 D->DirTarget=hd->DirTarget;
316 }
317 catch (RAR_EXIT ErrCode)
318 {
319 return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
320 }
321 return ERAR_SUCCESS;
322 }
323
324
325 int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
326 {
327 DataSet *Data=(DataSet *)hArcData;
328 try
329 {
330 Data->Cmd.DllError=0;
331 if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
332 Operation==RAR_SKIP && !Data->Arc.Solid)
333 {
334 if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
335 Data->Arc.FileHead.SplitAfter)
336 if (MergeArchive(Data->Arc,NULL,false,'L'))
337 {
338 Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
339 return ERAR_SUCCESS;
340 }
341 else
342 return ERAR_EOPEN;
343 Data->Arc.SeekToNext();
344 }
345 else
346 {
347 Data->Cmd.DllOpMode=Operation;
348
349 *Data->Cmd.ExtrPath=0;
350 *Data->Cmd.DllDestName=0;
351
352 if (DestPath!=NULL)
353 {
354 char ExtrPathA[NM];
355 strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
356 #ifdef _WIN_ALL
357 // We must not apply OemToCharBuffA directly to DestPath,
358 // because we do not know DestPath length and OemToCharBuffA
359 // does not stop at 0.
360 OemToCharA(ExtrPathA,ExtrPathA);
361 #endif
362 CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
363 AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
364 }
365 if (DestName!=NULL)
366 {
367 char DestNameA[NM];
368 strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
369 #ifdef _WIN_ALL
370 // We must not apply OemToCharBuffA directly to DestName,
371 // because we do not know DestName length and OemToCharBuffA
372 // does not stop at 0.
373 OemToCharA(DestNameA,DestNameA);
374 #endif
375 CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
376 }
377
378 if (DestPathW!=NULL)
379 {
380 wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
381 AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
382 }
383
384 if (DestNameW!=NULL)
385 wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
386
387 wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command));
388 Data->Cmd.Test=Operation!=RAR_EXTRACT;
389 bool Repeat=false;
390 Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
391
392 // Now we process extra file information if any.
393 //
394 // Archive can be closed if we process volumes, next volume is missing
395 // and current one is already removed or deleted. So we need to check
396 // if archive is still open to avoid calling file operations on
397 // the invalid file handle. Some of our file operations like Seek()
398 // process such invalid handle correctly, some not.
399 while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 &&
400 Data->Arc.GetHeaderType()==HEAD_SERVICE)
401 {
402 Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
403 Data->Arc.SeekToNext();
404 }
405 Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
406 }
407 }
408 catch (std::bad_alloc&)
409 {
410 return ERAR_NO_MEMORY;
411 }
412 catch (RAR_EXIT ErrCode)
413 {
414 return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
415 }
416 return Data->Cmd.DllError;
417 }
418
419
420 int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
421 {
422 return ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL);
423 }
424
425
426 int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
427 {
428 return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName);
429 }
430
431
432 void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
433 {
434 DataSet *Data=(DataSet *)hArcData;
435 Data->Cmd.ChangeVolProc=ChangeVolProc;
436 }
437
438
439 void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
440 {
441 DataSet *Data=(DataSet *)hArcData;
442 Data->Cmd.Callback=Callback;
443 Data->Cmd.UserData=UserData;
444 }
445
446
447 void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
448 {
449 DataSet *Data=(DataSet *)hArcData;
450 Data->Cmd.ProcessDataProc=ProcessDataProc;
451 }
452
453
454 void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
455 {
456 #ifndef RAR_NOCRYPT
457 DataSet *Data=(DataSet *)hArcData;
458 wchar PasswordW[MAXPASSWORD];
459 GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
460 Data->Cmd.Password.Set(PasswordW);
461 cleandata(PasswordW,sizeof(PasswordW));
462 #endif
463 }
464
465
466 int PASCAL RARGetDllVersion()
467 {
468 return RAR_DLL_VERSION;
469 }
470
471
472 static int RarErrorToDll(RAR_EXIT ErrCode)
473 {
474 switch(ErrCode)
475 {
476 case RARX_FATAL:
477 case RARX_READ:
478 return ERAR_EREAD;
479 case RARX_CRC:
480 return ERAR_BAD_DATA;
481 case RARX_WRITE:
482 return ERAR_EWRITE;
483 case RARX_OPEN:
484 return ERAR_EOPEN;
485 case RARX_CREATE:
486 return ERAR_ECREATE;
487 case RARX_MEMORY:
488 return ERAR_NO_MEMORY;
489 case RARX_BADPWD:
490 return ERAR_BAD_PASSWORD;
491 case RARX_SUCCESS:
492 return ERAR_SUCCESS; // 0.
493 default:
494 return ERAR_UNKNOWN;
495 }
496 }