1 // UpdateCallback.cpp
2
3 #include "StdAfx.h"
4
5 #ifndef _7ZIP_ST
6 #include "../../../Windows/Synchronization.h"
7 #endif
8
9 #include "../../../Common/ComTry.h"
10 #include "../../../Common/IntToString.h"
11 #include "../../../Common/StringConvert.h"
12 #include "../../../Common/Wildcard.h"
13
14 #include "../../../Windows/FileDir.h"
15 #include "../../../Windows/FileName.h"
16 #include "../../../Windows/PropVariant.h"
17
18 #include "../../Common/StreamObjects.h"
19
20 #include "UpdateCallback.h"
21
22 #if defined(_WIN32) && !defined(UNDER_CE)
23 #define _USE_SECURITY_CODE
24 #include "../../../Windows/SecurityUtils.h"
25 #endif
26
27 using namespace NWindows;
28 using namespace NFile;
29
30 #ifndef _7ZIP_ST
31 static NSynchronization::CCriticalSection g_CriticalSection;
32 #define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
33 #else
34 #define MT_LOCK
35 #endif
36
37
38 #ifdef _USE_SECURITY_CODE
39 bool InitLocalPrivileges();
40 #endif
41
CArchiveUpdateCallback()42 CArchiveUpdateCallback::CArchiveUpdateCallback():
43 _hardIndex_From((UInt32)(Int32)-1),
44
45 Callback(NULL),
46
47 DirItems(NULL),
48 ParentDirItem(NULL),
49
50 Arc(NULL),
51 ArcItems(NULL),
52 UpdatePairs(NULL),
53 NewNames(NULL),
54
55 ShareForWrite(false),
56 StdInMode(false),
57
58 KeepOriginalItemNames(false),
59 StoreNtSecurity(false),
60 StoreHardLinks(false),
61 StoreSymLinks(false),
62
63 ProcessedItemsStatuses(NULL)
64 {
65 #ifdef _USE_SECURITY_CODE
66 _saclEnabled = InitLocalPrivileges();
67 #endif
68 }
69
70
SetTotal(UInt64 size)71 STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
72 {
73 COM_TRY_BEGIN
74 return Callback->SetTotal(size);
75 COM_TRY_END
76 }
77
SetCompleted(const UInt64 * completeValue)78 STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
79 {
80 COM_TRY_BEGIN
81 return Callback->SetCompleted(completeValue);
82 COM_TRY_END
83 }
84
SetRatioInfo(const UInt64 * inSize,const UInt64 * outSize)85 STDMETHODIMP CArchiveUpdateCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
86 {
87 COM_TRY_BEGIN
88 return Callback->SetRatioInfo(inSize, outSize);
89 COM_TRY_END
90 }
91
92
93 /*
94 static const CStatProp kProps[] =
95 {
96 { NULL, kpidPath, VT_BSTR},
97 { NULL, kpidIsDir, VT_BOOL},
98 { NULL, kpidSize, VT_UI8},
99 { NULL, kpidCTime, VT_FILETIME},
100 { NULL, kpidATime, VT_FILETIME},
101 { NULL, kpidMTime, VT_FILETIME},
102 { NULL, kpidAttrib, VT_UI4},
103 { NULL, kpidIsAnti, VT_BOOL}
104 };
105
106 STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **)
107 {
108 return CStatPropEnumerator::CreateEnumerator(kProps, ARRAY_SIZE(kProps), enumerator);
109 }
110 */
111
GetUpdateItemInfo(UInt32 index,Int32 * newData,Int32 * newProps,UInt32 * indexInArchive)112 STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
113 Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)
114 {
115 COM_TRY_BEGIN
116 RINOK(Callback->CheckBreak());
117 const CUpdatePair2 &up = (*UpdatePairs)[index];
118 if (newData) *newData = BoolToInt(up.NewData);
119 if (newProps) *newProps = BoolToInt(up.NewProps);
120 if (indexInArchive)
121 {
122 *indexInArchive = (UInt32)(Int32)-1;
123 if (up.ExistInArchive())
124 *indexInArchive = (ArcItems == 0) ? up.ArcIndex : (*ArcItems)[up.ArcIndex].IndexInServer;
125 }
126 return S_OK;
127 COM_TRY_END
128 }
129
GetRootProp(PROPID propID,PROPVARIANT * value)130 STDMETHODIMP CArchiveUpdateCallback::GetRootProp(PROPID propID, PROPVARIANT *value)
131 {
132 NCOM::CPropVariant prop;
133 switch (propID)
134 {
135 case kpidIsDir: prop = true; break;
136 case kpidAttrib: if (ParentDirItem) prop = ParentDirItem->Attrib; break;
137 case kpidCTime: if (ParentDirItem) prop = ParentDirItem->CTime; break;
138 case kpidATime: if (ParentDirItem) prop = ParentDirItem->ATime; break;
139 case kpidMTime: if (ParentDirItem) prop = ParentDirItem->MTime; break;
140 }
141 prop.Detach(value);
142 return S_OK;
143 }
144
GetParent(UInt32,UInt32 * parent,UInt32 * parentType)145 STDMETHODIMP CArchiveUpdateCallback::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType)
146 {
147 *parentType = NParentType::kDir;
148 *parent = (UInt32)(Int32)-1;
149 return S_OK;
150 }
151
GetNumRawProps(UInt32 * numProps)152 STDMETHODIMP CArchiveUpdateCallback::GetNumRawProps(UInt32 *numProps)
153 {
154 *numProps = 0;
155 if (StoreNtSecurity)
156 *numProps = 1;
157 return S_OK;
158 }
159
GetRawPropInfo(UInt32,BSTR * name,PROPID * propID)160 STDMETHODIMP CArchiveUpdateCallback::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
161 {
162 *name = NULL;
163 *propID = kpidNtSecure;
164 return S_OK;
165 }
166
GetRootRawProp(PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType)167 STDMETHODIMP CArchiveUpdateCallback::GetRootRawProp(PROPID
168 #ifdef _USE_SECURITY_CODE
169 propID
170 #endif
171 , const void **data, UInt32 *dataSize, UInt32 *propType)
172 {
173 *data = 0;
174 *dataSize = 0;
175 *propType = 0;
176 if (!StoreNtSecurity)
177 return S_OK;
178 #ifdef _USE_SECURITY_CODE
179 if (propID == kpidNtSecure)
180 {
181 if (StdInMode)
182 return S_OK;
183
184 if (ParentDirItem)
185 {
186 if (ParentDirItem->SecureIndex < 0)
187 return S_OK;
188 const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[ParentDirItem->SecureIndex];
189 *data = buf;
190 *dataSize = (UInt32)buf.Size();
191 *propType = NPropDataType::kRaw;
192 return S_OK;
193 }
194
195 if (Arc && Arc->GetRootProps)
196 return Arc->GetRootProps->GetRootRawProp(propID, data, dataSize, propType);
197 }
198 #endif
199 return S_OK;
200 }
201
202 // #ifdef _USE_SECURITY_CODE
203 // #endif
204
GetRawProp(UInt32 index,PROPID propID,const void ** data,UInt32 * dataSize,UInt32 * propType)205 STDMETHODIMP CArchiveUpdateCallback::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
206 {
207 *data = 0;
208 *dataSize = 0;
209 *propType = 0;
210
211 if (propID == kpidNtSecure ||
212 propID == kpidNtReparse)
213 {
214 if (StdInMode)
215 return S_OK;
216
217 const CUpdatePair2 &up = (*UpdatePairs)[index];
218 if (up.UseArcProps && up.ExistInArchive() && Arc->GetRawProps)
219 return Arc->GetRawProps->GetRawProp(
220 ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex,
221 propID, data, dataSize, propType);
222 {
223 /*
224 if (!up.NewData)
225 return E_FAIL;
226 */
227 if (up.IsAnti)
228 return S_OK;
229
230 #ifndef UNDER_CE
231 const CDirItem &di = DirItems->Items[up.DirIndex];
232 #endif
233
234 #ifdef _USE_SECURITY_CODE
235 if (propID == kpidNtSecure)
236 {
237 if (!StoreNtSecurity)
238 return S_OK;
239 if (di.SecureIndex < 0)
240 return S_OK;
241 const CByteBuffer &buf = DirItems->SecureBlocks.Bufs[di.SecureIndex];
242 *data = buf;
243 *dataSize = (UInt32)buf.Size();
244 *propType = NPropDataType::kRaw;
245 }
246 else
247 #endif
248 {
249 // propID == kpidNtReparse
250 if (!StoreSymLinks)
251 return S_OK;
252 #ifndef UNDER_CE
253 const CByteBuffer *buf = &di.ReparseData2;
254 if (buf->Size() == 0)
255 buf = &di.ReparseData;
256 if (buf->Size() != 0)
257 {
258 *data = *buf;
259 *dataSize = (UInt32)buf->Size();
260 *propType = NPropDataType::kRaw;
261 }
262 #endif
263 }
264
265 return S_OK;
266 }
267 }
268
269 return S_OK;
270 }
271
272 #ifndef UNDER_CE
273
GetRelativePath(const UString & to,const UString & from)274 static UString GetRelativePath(const UString &to, const UString &from)
275 {
276 UStringVector partsTo, partsFrom;
277 SplitPathToParts(to, partsTo);
278 SplitPathToParts(from, partsFrom);
279
280 unsigned i;
281 for (i = 0;; i++)
282 {
283 if (i + 1 >= partsFrom.Size() ||
284 i + 1 >= partsTo.Size())
285 break;
286 if (CompareFileNames(partsFrom[i], partsTo[i]) != 0)
287 break;
288 }
289
290 if (i == 0)
291 {
292 #ifdef _WIN32
293 if (NName::IsDrivePath(to) ||
294 NName::IsDrivePath(from))
295 return to;
296 #endif
297 }
298
299 UString s;
300 unsigned k;
301
302 for (k = i + 1; k < partsFrom.Size(); k++)
303 s += L".." WSTRING_PATH_SEPARATOR;
304
305 for (k = i; k < partsTo.Size(); k++)
306 {
307 if (k != i)
308 s.Add_PathSepar();
309 s += partsTo[k];
310 }
311
312 return s;
313 }
314
315 #endif
316
GetProperty(UInt32 index,PROPID propID,PROPVARIANT * value)317 STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
318 {
319 COM_TRY_BEGIN
320 const CUpdatePair2 &up = (*UpdatePairs)[index];
321 NCOM::CPropVariant prop;
322
323 if (up.NewData)
324 {
325 /*
326 if (propID == kpidIsHardLink)
327 {
328 prop = _isHardLink;
329 prop.Detach(value);
330 return S_OK;
331 }
332 */
333 if (propID == kpidSymLink)
334 {
335 if (index == _hardIndex_From)
336 {
337 prop.Detach(value);
338 return S_OK;
339 }
340 if (up.DirIndex >= 0)
341 {
342 #ifndef UNDER_CE
343 const CDirItem &di = DirItems->Items[up.DirIndex];
344 // if (di.IsDir())
345 {
346 CReparseAttr attr;
347 if (attr.Parse(di.ReparseData, di.ReparseData.Size()))
348 {
349 UString simpleName = attr.GetPath();
350 if (attr.IsRelative())
351 prop = simpleName;
352 else
353 {
354 const FString phyPath = DirItems->GetPhyPath(up.DirIndex);
355 FString fullPath;
356 if (NDir::MyGetFullPathName(phyPath, fullPath))
357 {
358 prop = GetRelativePath(simpleName, fs2us(fullPath));
359 }
360 }
361 prop.Detach(value);
362 return S_OK;
363 }
364 }
365 #endif
366 }
367 }
368 else if (propID == kpidHardLink)
369 {
370 if (index == _hardIndex_From)
371 {
372 const CKeyKeyValPair &pair = _map[_hardIndex_To];
373 const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value];
374 prop = DirItems->GetLogPath(up2.DirIndex);
375 prop.Detach(value);
376 return S_OK;
377 }
378 if (up.DirIndex >= 0)
379 {
380 prop.Detach(value);
381 return S_OK;
382 }
383 }
384 }
385
386 if (up.IsAnti
387 && propID != kpidIsDir
388 && propID != kpidPath
389 && propID != kpidIsAltStream)
390 {
391 switch (propID)
392 {
393 case kpidSize: prop = (UInt64)0; break;
394 case kpidIsAnti: prop = true; break;
395 }
396 }
397 else if (propID == kpidPath && up.NewNameIndex >= 0)
398 prop = (*NewNames)[up.NewNameIndex];
399 else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem)
400 {
401 // we can generate new ShortName here;
402 }
403 else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream)))
404 && up.ExistInArchive() && Archive)
405 return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value);
406 else if (up.ExistOnDisk())
407 {
408 const CDirItem &di = DirItems->Items[up.DirIndex];
409 switch (propID)
410 {
411 case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break;
412 case kpidIsDir: prop = di.IsDir(); break;
413 case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break;
414 case kpidAttrib: prop = di.Attrib; break;
415 case kpidCTime: prop = di.CTime; break;
416 case kpidATime: prop = di.ATime; break;
417 case kpidMTime: prop = di.MTime; break;
418 case kpidIsAltStream: prop = di.IsAltStream; break;
419 #if defined(_WIN32) && !defined(UNDER_CE)
420 // case kpidShortName: prop = di.ShortName; break;
421 #endif
422 }
423 }
424 prop.Detach(value);
425 return S_OK;
426 COM_TRY_END
427 }
428
429 #ifndef _7ZIP_ST
430 static NSynchronization::CCriticalSection CS;
431 #endif
432
GetStream2(UInt32 index,ISequentialInStream ** inStream,UInt32 mode)433 STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode)
434 {
435 COM_TRY_BEGIN
436 *inStream = NULL;
437 const CUpdatePair2 &up = (*UpdatePairs)[index];
438 if (!up.NewData)
439 return E_FAIL;
440
441 RINOK(Callback->CheckBreak());
442 // RINOK(Callback->Finalize());
443
444 bool isDir = IsDir(up);
445
446 if (up.IsAnti)
447 {
448 UString name;
449 if (up.ArcIndex >= 0)
450 name = (*ArcItems)[up.ArcIndex].Name;
451 else if (up.DirIndex >= 0)
452 name = DirItems->GetLogPath(up.DirIndex);
453 RINOK(Callback->GetStream(name, isDir, true, mode));
454
455 /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file.
456 so we return empty stream */
457
458 if (!isDir)
459 {
460 CBufInStream *inStreamSpec = new CBufInStream();
461 CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec;
462 inStreamSpec->Init(NULL, 0);
463 *inStream = inStreamLoc.Detach();
464 }
465 return S_OK;
466 }
467
468 RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode));
469
470 if (isDir)
471 return S_OK;
472
473 if (StdInMode)
474 {
475 if (mode != NUpdateNotifyOp::kAdd &&
476 mode != NUpdateNotifyOp::kUpdate)
477 return S_OK;
478
479 CStdInFileStream *inStreamSpec = new CStdInFileStream;
480 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
481 *inStream = inStreamLoc.Detach();
482 }
483 else
484 {
485 CInFileStream *inStreamSpec = new CInFileStream;
486 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
487
488 inStreamSpec->SupportHardLinks = StoreHardLinks;
489 inStreamSpec->Callback = this;
490 inStreamSpec->CallbackRef = index;
491
492 const FString path = DirItems->GetPhyPath(up.DirIndex);
493 _openFiles_Indexes.Add(index);
494 _openFiles_Paths.Add(path);
495
496 #if defined(_WIN32) && !defined(UNDER_CE)
497 if (DirItems->Items[up.DirIndex].AreReparseData())
498 {
499 if (!inStreamSpec->File.OpenReparse(path))
500 {
501 return Callback->OpenFileError(path, ::GetLastError());
502 }
503 }
504 else
505 #endif
506 if (!inStreamSpec->OpenShared(path, ShareForWrite))
507 {
508 return Callback->OpenFileError(path, ::GetLastError());
509 }
510
511 if (StoreHardLinks)
512 {
513 CStreamFileProps props;
514 if (inStreamSpec->GetProps2(&props) == S_OK)
515 {
516 if (props.NumLinks > 1)
517 {
518 CKeyKeyValPair pair;
519 pair.Key1 = props.VolID;
520 pair.Key2 = props.FileID_Low;
521 pair.Value = index;
522 unsigned numItems = _map.Size();
523 unsigned pairIndex = _map.AddToUniqueSorted2(pair);
524 if (numItems == _map.Size())
525 {
526 // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex];
527 _hardIndex_From = index;
528 _hardIndex_To = pairIndex;
529 // we could return NULL as stream, but it's better to return real stream
530 // return S_OK;
531 }
532 }
533 }
534 }
535
536 if (ProcessedItemsStatuses)
537 {
538 #ifndef _7ZIP_ST
539 NSynchronization::CCriticalSectionLock lock(CS);
540 #endif
541 ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1;
542 }
543 *inStream = inStreamLoc.Detach();
544 }
545
546 return S_OK;
547 COM_TRY_END
548 }
549
SetOperationResult(Int32 opRes)550 STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 opRes)
551 {
552 COM_TRY_BEGIN
553 return Callback->SetOperationResult(opRes);
554 COM_TRY_END
555 }
556
GetStream(UInt32 index,ISequentialInStream ** inStream)557 STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index, ISequentialInStream **inStream)
558 {
559 COM_TRY_BEGIN
560 return GetStream2(index, inStream,
561 (*UpdatePairs)[index].ArcIndex < 0 ?
562 NUpdateNotifyOp::kAdd :
563 NUpdateNotifyOp::kUpdate);
564 COM_TRY_END
565 }
566
ReportOperation(UInt32 indexType,UInt32 index,UInt32 op)567 STDMETHODIMP CArchiveUpdateCallback::ReportOperation(UInt32 indexType, UInt32 index, UInt32 op)
568 {
569 COM_TRY_BEGIN
570
571 bool isDir = false;
572
573 if (indexType == NArchive::NEventIndexType::kOutArcIndex)
574 {
575 UString name;
576 if (index != (UInt32)(Int32)-1)
577 {
578 const CUpdatePair2 &up = (*UpdatePairs)[index];
579 if (up.ExistOnDisk())
580 {
581 name = DirItems->GetLogPath(up.DirIndex);
582 isDir = DirItems->Items[up.DirIndex].IsDir();
583 }
584 }
585 return Callback->ReportUpdateOpeartion(op, name.IsEmpty() ? NULL : name.Ptr(), isDir);
586 }
587
588 wchar_t temp[16];
589 UString s2;
590 const wchar_t *s = NULL;
591
592 if (indexType == NArchive::NEventIndexType::kInArcIndex)
593 {
594 if (index != (UInt32)(Int32)-1)
595 {
596 if (ArcItems)
597 {
598 const CArcItem &ai = (*ArcItems)[index];
599 s = ai.Name;
600 isDir = ai.IsDir;
601 }
602 else if (Arc)
603 {
604 RINOK(Arc->GetItemPath(index, s2));
605 s = s2;
606 RINOK(Archive_IsItem_Dir(Arc->Archive, index, isDir));
607 }
608 }
609 }
610 else if (indexType == NArchive::NEventIndexType::kBlockIndex)
611 {
612 temp[0] = '#';
613 ConvertUInt32ToString(index, temp + 1);
614 s = temp;
615 }
616
617 if (!s)
618 s = L"";
619
620 return Callback->ReportUpdateOpeartion(op, s, isDir);
621
622 COM_TRY_END
623 }
624
ReportExtractResult(UInt32 indexType,UInt32 index,Int32 opRes)625 STDMETHODIMP CArchiveUpdateCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes)
626 {
627 COM_TRY_BEGIN
628
629 bool isEncrypted = false;
630 wchar_t temp[16];
631 UString s2;
632 const wchar_t *s = NULL;
633
634 if (indexType == NArchive::NEventIndexType::kOutArcIndex)
635 {
636 /*
637 UString name;
638 if (index != (UInt32)(Int32)-1)
639 {
640 const CUpdatePair2 &up = (*UpdatePairs)[index];
641 if (up.ExistOnDisk())
642 {
643 s2 = DirItems->GetLogPath(up.DirIndex);
644 s = s2;
645 }
646 }
647 */
648 return E_FAIL;
649 }
650
651 if (indexType == NArchive::NEventIndexType::kInArcIndex)
652 {
653 if (index != (UInt32)(Int32)-1)
654 {
655 if (ArcItems)
656 s = (*ArcItems)[index].Name;
657 else if (Arc)
658 {
659 RINOK(Arc->GetItemPath(index, s2));
660 s = s2;
661 }
662 if (Archive)
663 {
664 RINOK(Archive_GetItemBoolProp(Archive, index, kpidEncrypted, isEncrypted));
665 }
666 }
667 }
668 else if (indexType == NArchive::NEventIndexType::kBlockIndex)
669 {
670 temp[0] = '#';
671 ConvertUInt32ToString(index, temp + 1);
672 s = temp;
673 }
674
675 return Callback->ReportExtractResult(opRes, BoolToInt(isEncrypted), s);
676
677 COM_TRY_END
678 }
679
GetVolumeSize(UInt32 index,UInt64 * size)680 STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
681 {
682 if (VolumesSizes.Size() == 0)
683 return S_FALSE;
684 if (index >= (UInt32)VolumesSizes.Size())
685 index = VolumesSizes.Size() - 1;
686 *size = VolumesSizes[index];
687 return S_OK;
688 }
689
GetVolumeStream(UInt32 index,ISequentialOutStream ** volumeStream)690 STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
691 {
692 COM_TRY_BEGIN
693 FChar temp[16];
694 ConvertUInt32ToString(index + 1, temp);
695 FString res = temp;
696 while (res.Len() < 2)
697 res.InsertAtFront(FTEXT('0'));
698 FString fileName = VolName;
699 fileName += FTEXT('.');
700 fileName += res;
701 fileName += VolExt;
702 COutFileStream *streamSpec = new COutFileStream;
703 CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
704 if (!streamSpec->Create(fileName, false))
705 return ::GetLastError();
706 *volumeStream = streamLoc.Detach();
707 return S_OK;
708 COM_TRY_END
709 }
710
CryptoGetTextPassword2(Int32 * passwordIsDefined,BSTR * password)711 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
712 {
713 COM_TRY_BEGIN
714 return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
715 COM_TRY_END
716 }
717
CryptoGetTextPassword(BSTR * password)718 STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword(BSTR *password)
719 {
720 COM_TRY_BEGIN
721 return Callback->CryptoGetTextPassword(password);
722 COM_TRY_END
723 }
724
InFileStream_On_Error(UINT_PTR val,DWORD error)725 HRESULT CArchiveUpdateCallback::InFileStream_On_Error(UINT_PTR val, DWORD error)
726 {
727 if (error == ERROR_LOCK_VIOLATION)
728 {
729 MT_LOCK
730 UInt32 index = (UInt32)val;
731 FOR_VECTOR(i, _openFiles_Indexes)
732 {
733 if (_openFiles_Indexes[i] == index)
734 {
735 RINOK(Callback->ReadingFileError(_openFiles_Paths[i], error));
736 break;
737 }
738 }
739 }
740 return HRESULT_FROM_WIN32(error);
741 }
742
InFileStream_On_Destroy(UINT_PTR val)743 void CArchiveUpdateCallback::InFileStream_On_Destroy(UINT_PTR val)
744 {
745 MT_LOCK
746 UInt32 index = (UInt32)val;
747 FOR_VECTOR(i, _openFiles_Indexes)
748 {
749 if (_openFiles_Indexes[i] == index)
750 {
751 _openFiles_Indexes.Delete(i);
752 _openFiles_Paths.Delete(i);
753 return;
754 }
755 }
756 throw 20141125;
757 }
758