1 #include "rar.hpp"
2
3
4
5
6 #if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
7 // Disable the run time stack check for unrar.dll, so we can manipulate
8 // with ChangeVolProc call type below. Run time check would intercept
9 // a wrong ESP before we restore it.
10 #pragma runtime_checks( "s", off )
11 #endif
12
MergeArchive(Archive & Arc,ComprDataIO * DataIO,bool ShowFileName,char Command)13 bool MergeArchive(Archive &Arc,ComprDataIO *DataIO,bool ShowFileName,char Command)
14 {
15 RAROptions *Cmd=Arc.GetRAROptions();
16
17 int HeaderType=Arc.GetHeaderType();
18 FileHeader *hd=HeaderType==NEWSUB_HEAD ? &Arc.SubHead:&Arc.NewLhd;
19 bool SplitHeader=(HeaderType==FILE_HEAD || HeaderType==NEWSUB_HEAD) &&
20 (hd->Flags & LHD_SPLIT_AFTER)!=0;
21
22 if (DataIO!=NULL && SplitHeader && hd->UnpVer>=20 &&
23 hd->FileCRC!=0xffffffff && DataIO->PackedCRC!=~hd->FileCRC)
24 {
25 Log(Arc.FileName,St(MDataBadCRC),hd->FileName,Arc.FileName);
26 }
27
28 int64 PosBeforeClose=Arc.Tell();
29
30 if (DataIO!=NULL)
31 DataIO->ProcessedArcSize+=Arc.FileLength();
32
33 Arc.Close();
34
35 char NextName[NM];
36 wchar NextNameW[NM];
37 strcpy(NextName,Arc.FileName);
38 wcscpy(NextNameW,Arc.FileNameW);
39 NextVolumeName(NextName,NextNameW,ASIZE(NextName),(Arc.NewMhd.Flags & MHD_NEWNUMBERING)==0 || Arc.OldFormat);
40
41 #if !defined(SFX_MODULE) && !defined(RARDLL)
42 bool RecoveryDone=false;
43 #endif
44 bool FailedOpen=false,OldSchemeTested=false;
45
46 #if !defined(GUI) && !defined(SILENT)
47 // In -vp mode we force the pause before next volume even if it is present
48 // and even if we are on the hard disk. It is important when user does not
49 // want to process partially downloaded volumes preliminary.
50 if (Cmd->VolumePause && !AskNextVol(NextName,NextNameW))
51 FailedOpen=true;
52 #endif
53
54 if (!FailedOpen)
55 while (!Arc.Open(NextName,NextNameW))
56 {
57 // We need to open a new volume which size was not calculated
58 // in total size before, so we cannot calculate the total progress
59 // anymore. Let's reset the total size to zero and stop
60 // the total progress.
61 if (DataIO!=NULL)
62 DataIO->TotalArcSize=0;
63
64 if (!OldSchemeTested)
65 {
66 // Checking for new style volumes renamed by user to old style
67 // name format. Some users did it for unknown reason.
68 char AltNextName[NM];
69 wchar AltNextNameW[NM];
70 strcpy(AltNextName,Arc.FileName);
71 wcscpy(AltNextNameW,Arc.FileNameW);
72 NextVolumeName(AltNextName,AltNextNameW,ASIZE(AltNextName),true);
73 OldSchemeTested=true;
74 if (Arc.Open(AltNextName,AltNextNameW))
75 {
76 strcpy(NextName,AltNextName);
77 wcscpy(NextNameW,AltNextNameW);
78 break;
79 }
80 }
81 #ifdef RARDLL
82 if (Cmd->Callback==NULL && Cmd->ChangeVolProc==NULL ||
83 Cmd->Callback!=NULL && Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_ASK)==-1)
84 {
85 Cmd->DllError=ERAR_EOPEN;
86 FailedOpen=true;
87 break;
88 }
89 if (Cmd->ChangeVolProc!=NULL)
90 {
91 // Here we preserve ESP value. It is necessary for those developers,
92 // who still define ChangeVolProc callback as "C" type function,
93 // even though in year 2001 we announced in unrar.dll whatsnew.txt
94 // that it will be PASCAL type (for compatibility with Visual Basic).
95 #if defined(_MSC_VER)
96 #ifndef _WIN_64
97 __asm mov ebx,esp
98 #endif
99 #elif defined(_WIN_ALL) && defined(__BORLANDC__)
100 _EBX=_ESP;
101 #endif
102 int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_ASK);
103
104 // Restore ESP after ChangeVolProc with wrongly defined calling
105 // convention broken it.
106 #if defined(_MSC_VER)
107 #ifndef _WIN_64
108 __asm mov esp,ebx
109 #endif
110 #elif defined(_WIN_ALL) && defined(__BORLANDC__)
111 _ESP=_EBX;
112 #endif
113 if (RetCode==0)
114 {
115 Cmd->DllError=ERAR_EOPEN;
116 FailedOpen=true;
117 break;
118 }
119 }
120 #else // RARDLL
121
122 #if !defined(SFX_MODULE) && !defined(_WIN_CE)
123 if (!RecoveryDone)
124 {
125 RecVolumes RecVol;
126 RecVol.Restore(Cmd,Arc.FileName,Arc.FileNameW,true);
127 RecoveryDone=true;
128 continue;
129 }
130 #endif
131
132 #ifndef GUI
133 if (!Cmd->VolumePause && !IsRemovable(NextName))
134 {
135 FailedOpen=true;
136 break;
137 }
138 #endif
139 #ifndef SILENT
140 if (Cmd->AllYes || !AskNextVol(NextName,NextNameW))
141 #endif
142 {
143 FailedOpen=true;
144 break;
145 }
146
147 #endif // RARDLL
148 }
149
150 if (FailedOpen)
151 {
152 #if !defined(SILENT) && !defined(_WIN_CE)
153 Log(Arc.FileName,St(MAbsNextVol),NextName);
154 #endif
155 Arc.Open(Arc.FileName,Arc.FileNameW);
156 Arc.Seek(PosBeforeClose,SEEK_SET);
157 return(false);
158 }
159 Arc.CheckArc(true);
160 #ifdef RARDLL
161 if (Cmd->Callback!=NULL &&
162 Cmd->Callback(UCM_CHANGEVOLUME,Cmd->UserData,(LPARAM)NextName,RAR_VOL_NOTIFY)==-1)
163 return(false);
164 if (Cmd->ChangeVolProc!=NULL)
165 {
166 #if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
167 _EBX=_ESP;
168 #endif
169 int RetCode=Cmd->ChangeVolProc(NextName,RAR_VOL_NOTIFY);
170 #if defined(_WIN_ALL) && !defined(_MSC_VER) && !defined(__MINGW32__)
171 _ESP=_EBX;
172 #endif
173 if (RetCode==0)
174 return(false);
175 }
176 #endif
177
178 if (Command=='T' || Command=='X' || Command=='E')
179 mprintf(St(Command=='T' ? MTestVol:MExtrVol),Arc.FileName);
180
181
182 if (SplitHeader)
183 Arc.SearchBlock(HeaderType);
184 else
185 Arc.ReadHeader();
186 if (Arc.GetHeaderType()==FILE_HEAD)
187 {
188 Arc.ConvertAttributes();
189 Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET);
190 }
191 #ifndef GUI
192 if (ShowFileName)
193 {
194 char OutName[NM];
195 IntToExt(Arc.NewLhd.FileName,OutName);
196 #ifdef UNICODE_SUPPORTED
197 bool WideName=(Arc.NewLhd.Flags & LHD_UNICODE) && UnicodeEnabled();
198 if (WideName)
199 {
200 wchar NameW[NM];
201 ConvertPath(Arc.NewLhd.FileNameW,NameW);
202 char Name[NM];
203 if (WideToChar(NameW,Name) && IsNameUsable(Name))
204 strcpy(OutName,Name);
205 }
206 #endif
207 mprintf(St(MExtrPoints),OutName);
208 if (!Cmd->DisablePercentage)
209 mprintf(" ");
210 }
211 #endif
212 if (DataIO!=NULL)
213 {
214 if (HeaderType==ENDARC_HEAD)
215 DataIO->UnpVolume=false;
216 else
217 {
218 DataIO->UnpVolume=(hd->Flags & LHD_SPLIT_AFTER)!=0;
219 DataIO->SetPackedSizeToRead(hd->FullPackSize);
220 }
221 #ifdef SFX_MODULE
222 DataIO->UnpArcSize=Arc.FileLength();
223 #endif
224
225 // Reset the size of packed data read from current volume. It is used
226 // to display the total progress and preceding volumes are already
227 // compensated with ProcessedArcSize, so we need to reset this variable.
228 DataIO->CurUnpRead=0;
229
230 DataIO->PackedCRC=0xffffffff;
231 // DataIO->SetFiles(&Arc,NULL);
232 }
233 return(true);
234 }
235
236 #if defined(RARDLL) && defined(_MSC_VER) && !defined(_WIN_64)
237 // Restore the run time stack check for unrar.dll.
238 #pragma runtime_checks( "s", restore )
239 #endif
240
241
242
243
244
245
246 #ifndef SILENT
AskNextVol(char * ArcName,wchar * ArcNameW)247 bool AskNextVol(char *ArcName,wchar *ArcNameW)
248 {
249 eprintf(St(MAskNextVol),ArcName);
250 if (Ask(St(MContinueQuit))==2)
251 return(false);
252 return(true);
253 }
254 #endif
255