5 #include "Common/AutoPtr.h"
\r
6 #include "Common/StringConvert.h"
\r
8 #include "Windows/Error.h"
\r
9 #include "Windows/FileDir.h"
\r
10 #include "Windows/FileFind.h"
\r
11 #include "Windows/Process.h"
\r
12 #include "Windows/PropVariant.h"
\r
13 #include "Windows/Thread.h"
\r
15 #include "../Common/ExtractingFilePath.h"
\r
19 #include "FileFolderPluginOpen.h"
\r
20 #include "FormatUtils.h"
\r
21 #include "LangUtils.h"
\r
22 #include "RegistryUtils.h"
\r
23 #include "UpdateCallback100.h"
\r
25 #include "resource.h"
\r
27 using namespace NWindows;
\r
28 using namespace NSynchronization;
\r
29 using namespace NFile;
\r
30 using namespace NDirectory;
\r
36 static wchar_t *kTempDirPrefix = L"7zO";
\r
39 static bool IsNameVirus(const UString &name)
\r
41 return (name.Find(L" ") >= 0);
\r
44 struct CTmpProcessInfo: public CTempFileInfo
\r
46 HANDLE ProcessHandle;
\r
48 UString FullPathFolderPrefix;
\r
51 CTmpProcessInfo(): UsePassword(false) {}
\r
54 class CTmpProcessInfoRelease
\r
56 CTmpProcessInfo *_tmpProcessInfo;
\r
59 CTmpProcessInfoRelease(CTmpProcessInfo &tmpProcessInfo):
\r
60 _tmpProcessInfo(&tmpProcessInfo), _needDelete(true) {}
\r
61 ~CTmpProcessInfoRelease()
\r
64 _tmpProcessInfo->DeleteDirAndFile();
\r
68 HRESULT CPanel::OpenItemAsArchive(IInStream *inStream,
\r
69 const CTempFileInfo &tempFileInfo,
\r
70 const UString &virtualFilePath,
\r
71 const UString &arcFormat,
\r
75 CFolderLink folderLink;
\r
76 (CTempFileInfo &)folderLink = tempFileInfo;
\r
78 folderLink.IsVirtual = true;
\r
81 if (!folderLink.FileInfo.Find(folderLink.FilePath))
\r
82 return ::GetLastError();
\r
83 if (folderLink.FileInfo.IsDir())
\r
85 folderLink.IsVirtual = false;
\r
88 folderLink.VirtualPath = virtualFilePath;
\r
90 CMyComPtr<IFolderFolder> newFolder;
\r
92 // _passwordIsDefined = false;
\r
93 // _password.Empty();
\r
95 NDLL::CLibrary library;
\r
98 RINOK(OpenFileFolderPlugin(inStream,
\r
99 folderLink.FilePath.IsEmpty() ? virtualFilePath : folderLink.FilePath,
\r
101 &library, &newFolder, GetParent(), encrypted, password));
\r
103 folderLink.Password = password;
\r
104 folderLink.UsePassword = encrypted;
\r
106 folderLink.ParentFolder = _folder;
\r
107 _parentFolders.Add(folderLink);
\r
108 _parentFolders.Back().Library.Attach(_library.Detach());
\r
112 _folder = newFolder;
\r
113 _library.Attach(library.Detach());
\r
115 _flatMode = _flatModeForArc;
\r
117 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
\r
118 _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
\r
119 if (getFolderArcProps)
\r
121 CMyComPtr<IFolderArcProps> arcProps;
\r
122 getFolderArcProps->GetFolderArcProps(&arcProps);
\r
127 if (arcProps->GetArcNumLevels(&numLevels) != S_OK)
\r
129 for (UInt32 level2 = 0; level2 < numLevels; level2++)
\r
131 UInt32 level = numLevels - 1 - level2;
\r
132 PROPID propIDs[] = { kpidError, kpidPath, kpidType } ;
\r
134 for (Int32 i = 0; i < 3; i++)
\r
137 NCOM::CPropVariant prop;
\r
138 if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK)
\r
140 if (prop.vt != VT_EMPTY)
\r
141 values[i] = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?";
\r
143 if (!values[0].IsEmpty())
\r
146 s += L"--------------------\n";
\r
147 s += values[0]; s += L"\n\n[";
\r
148 s += values[2]; s += L"] ";
\r
149 s += values[1]; s += L"\n";
\r
160 HRESULT CPanel::OpenItemAsArchive(const UString &name, const UString &arcFormat, bool &encrypted)
\r
163 tfi.ItemName = name;
\r
164 tfi.FolderPath = _currentFolderPrefix;
\r
165 tfi.FilePath = _currentFolderPrefix + name;
\r
166 return OpenItemAsArchive(NULL, tfi, _currentFolderPrefix + name, arcFormat, encrypted);
\r
169 HRESULT CPanel::OpenItemAsArchive(int index)
\r
171 CDisableTimerProcessing disableTimerProcessing1(*this);
\r
173 RINOK(OpenItemAsArchive(GetItemRelPath(index), UString(), encrypted));
\r
178 HRESULT CPanel::OpenParentArchiveFolder()
\r
180 CDisableTimerProcessing disableTimerProcessing1(*this);
\r
181 if (_parentFolders.Size() < 2)
\r
183 const CFolderLink &folderLink = _parentFolders.Back();
\r
184 NFind::CFileInfoW newFileInfo;
\r
185 if (newFileInfo.Find(folderLink.FilePath))
\r
187 if (folderLink.WasChanged(newFileInfo))
\r
189 UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE,
\r
190 0x03020280, folderLink.ItemName);
\r
191 if (::MessageBoxW(HWND(*this), message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
\r
193 if (OnOpenItemChanged(folderLink.FolderPath, folderLink.ItemName,
\r
194 folderLink.UsePassword, folderLink.Password) != S_OK)
\r
196 ::MessageBoxW(HWND(*this), MyFormatNew(IDS_CANNOT_UPDATE_FILE,
\r
197 0x03020281, folderLink.FilePath), L"7-Zip", MB_OK | MB_ICONSTOP);
\r
203 folderLink.DeleteDirAndFile();
\r
207 static const char *kStartExtensions =
\r
213 " msi doc xls ppt pps wps wpt wks xlr wdb vsd pub"
\r
215 " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps"
\r
216 " xlam pptx pptm potx potm ppam ppsx ppsm xsn"
\r
228 static bool FindExt(const char *p, const UString &name)
\r
230 int extPos = name.ReverseFind('.');
\r
233 UString ext = name.Mid(extPos + 1);
\r
235 AString ext2 = UnicodeStringToMultiByte(ext);
\r
236 for (int i = 0; p[i] != 0;)
\r
239 for (j = i; p[j] != ' '; j++);
\r
240 if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)
\r
247 static bool DoItemAlwaysStart(const UString &name)
\r
249 return FindExt(kStartExtensions, name);
\r
252 static UString GetQuotedString(const UString &s)
\r
254 return UString(L'\"') + s + UString(L'\"');
\r
257 static HRESULT StartEditApplication(const UString &path, HWND window, CProcess &process)
\r
260 ReadRegEditor(command);
\r
261 if (command.IsEmpty())
\r
264 command = L"\\Windows\\";
\r
266 if (!MyGetWindowsDirectory(command))
\r
268 NFile::NName::NormalizeDirPathPrefix(command);
\r
270 command += L"notepad.exe";
\r
273 HRESULT res = process.Create(command, GetQuotedString(path), NULL);
\r
275 ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP);
\r
279 void CApp::DiffFiles()
\r
281 const CPanel &panel = GetFocusedPanel();
\r
283 CRecordVector<UInt32> indices;
\r
284 panel.GetSelectedItemsIndices(indices);
\r
286 UString path1, path2;
\r
287 if (indices.Size() == 2)
\r
289 path1 = panel.GetItemFullPath(indices[0]);
\r
290 path2 = panel.GetItemFullPath(indices[1]);
\r
292 else if (indices.Size() == 1 && NumPanels >= 2)
\r
294 const CPanel &destPanel = Panels[1 - LastFocusedPanel];
\r
295 path1 = panel.GetItemFullPath(indices[0]);
\r
296 const UString relPath = panel.GetItemRelPath(indices[0]);
\r
297 CRecordVector<UInt32> indices2;
\r
298 destPanel.GetSelectedItemsIndices(indices2);
\r
299 if (indices2.Size() == 1)
\r
300 path2 = destPanel.GetItemFullPath(indices2[0]);
\r
302 path2 = destPanel._currentFolderPrefix + relPath;
\r
308 ReadRegDiff(command);
\r
309 if (command.IsEmpty())
\r
312 UString param = GetQuotedString(path1) + L' ' + GetQuotedString(path2);
\r
314 HRESULT res = MyCreateProcess(command, param);
\r
317 ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR, 0x03020282), L"7-Zip", MB_OK | MB_ICONSTOP);
\r
321 typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo);
\r
324 static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
\r
330 SHELLEXECUTEINFOW execInfo;
\r
331 execInfo.cbSize = sizeof(execInfo);
\r
332 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
\r
333 execInfo.hwnd = NULL;
\r
334 execInfo.lpVerb = NULL;
\r
335 execInfo.lpFile = path;
\r
336 execInfo.lpParameters = NULL;
\r
337 execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
\r
338 execInfo.nShow = SW_SHOWNORMAL;
\r
339 execInfo.hProcess = 0;
\r
340 ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP)
\r
341 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW");
\r
342 if (shellExecuteExW == 0)
\r
344 shellExecuteExW(&execInfo);
\r
345 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
\r
346 process.Attach(execInfo.hProcess);
\r
351 SHELLEXECUTEINFO execInfo;
\r
352 execInfo.cbSize = sizeof(execInfo);
\r
353 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
\r
355 | SEE_MASK_FLAG_DDEWAIT
\r
358 execInfo.hwnd = NULL;
\r
359 execInfo.lpVerb = NULL;
\r
360 const CSysString sysPath = GetSystemString(path);
\r
361 const CSysString sysDir = GetSystemString(dir);
\r
362 execInfo.lpFile = sysPath;
\r
363 execInfo.lpParameters = NULL;
\r
364 execInfo.lpDirectory =
\r
368 sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
\r
371 execInfo.nShow = SW_SHOWNORMAL;
\r
372 execInfo.hProcess = 0;
\r
373 ::ShellExecuteEx(&execInfo);
\r
374 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
\r
375 process.Attach(execInfo.hProcess);
\r
381 case SE_ERR_NOASSOC:
\r
382 ::MessageBoxW(window,
\r
383 NError::MyFormatMessageW(::GetLastError()),
\r
384 // L"There is no application associated with the given file name extension",
\r
385 L"7-Zip", MB_OK | MB_ICONSTOP);
\r
391 static void StartApplicationDontWait(const UString &dir, const UString &path, HWND window)
\r
394 StartApplication(dir, path, window, process);
\r
397 void CPanel::EditItem(int index)
\r
399 if (!_parentFolders.IsEmpty())
\r
401 OpenItemInArchive(index, false, true, true);
\r
405 StartEditApplication(GetItemFullPath(index), (HWND)*this, process);
\r
408 void CPanel::OpenFolderExternal(int index)
\r
410 UString fsPrefix = GetFsPath();
\r
412 if (index == kParentIndex)
\r
414 int pos = fsPrefix.ReverseFind(WCHAR_PATH_SEPARATOR);
\r
415 if (pos >= 0 && pos == fsPrefix.Length() - 1)
\r
417 UString s = fsPrefix.Left(pos);
\r
418 pos = s.ReverseFind(WCHAR_PATH_SEPARATOR);
\r
420 fsPrefix = s.Left(pos + 1);
\r
425 name = fsPrefix + GetItemRelPath(index) + WCHAR_PATH_SEPARATOR;
\r
426 StartApplicationDontWait(fsPrefix, name, (HWND)*this);
\r
429 void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal)
\r
431 CDisableTimerProcessing disableTimerProcessing1(*this);
\r
432 if (!_parentFolders.IsEmpty())
\r
434 OpenItemInArchive(index, tryInternal, tryExternal, false);
\r
437 UString name = GetItemRelPath(index);
\r
438 if (IsNameVirus(name))
\r
440 MessageBoxErrorLang(IDS_VIRUS, 0x03020284);
\r
443 UString prefix = GetFsPath();
\r
444 UString fullPath = prefix + name;
\r
446 if (!tryExternal || !DoItemAlwaysStart(name))
\r
448 HRESULT res = OpenItemAsArchive(index);
\r
449 if (res == S_OK || res == E_ABORT)
\r
451 if (res != S_FALSE)
\r
453 MessageBoxError(res);
\r
459 // SetCurrentDirectory opens HANDLE to folder!!!
\r
460 // NDirectory::MySetCurrentDirectory(prefix);
\r
461 StartApplicationDontWait(prefix, fullPath, (HWND)*this);
\r
465 class CThreadCopyFrom: public CProgressThreadVirt
\r
467 HRESULT ProcessVirt();
\r
469 UString PathPrefix;
\r
472 CMyComPtr<IFolderOperations> FolderOperations;
\r
473 CMyComPtr<IProgress> UpdateCallback;
\r
474 CUpdateCallback100Imp *UpdateCallbackSpec;
\r
477 HRESULT CThreadCopyFrom::ProcessVirt()
\r
479 UStringVector fileNames;
\r
480 CRecordVector<const wchar_t *> fileNamePointers;
\r
481 fileNames.Add(Name);
\r
482 fileNamePointers.Add(fileNames[0]);
\r
483 return FolderOperations->CopyFrom(PathPrefix, &fileNamePointers.Front(), fileNamePointers.Size(), UpdateCallback);
\r
486 HRESULT CPanel::OnOpenItemChanged(const UString &folderPath, const UString &itemName,
\r
487 bool usePassword, const UString &password)
\r
489 CMyComPtr<IFolderOperations> folderOperations;
\r
490 if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
\r
492 MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
\r
497 t.UpdateCallbackSpec = new CUpdateCallback100Imp;
\r
498 t.UpdateCallback = t.UpdateCallbackSpec;
\r
499 t.UpdateCallbackSpec->ProgressDialog = &t.ProgressDialog;
\r
501 t.PathPrefix = folderPath;
\r
502 NName::NormalizeDirPathPrefix(t.PathPrefix);
\r
503 t.FolderOperations = folderOperations;
\r
504 t.UpdateCallbackSpec->Init(usePassword, password);
\r
505 RINOK(t.Create(itemName, (HWND)*this));
\r
509 LRESULT CPanel::OnOpenItemChanged(LPARAM lParam)
\r
511 CTmpProcessInfo &tmpProcessInfo = *(CTmpProcessInfo *)lParam;
\r
512 // LoadCurrentPath()
\r
513 if (tmpProcessInfo.FullPathFolderPrefix != _currentFolderPrefix)
\r
516 CSelectedState state;
\r
517 SaveSelectedState(state);
\r
519 HRESULT result = OnOpenItemChanged(tmpProcessInfo.FolderPath, tmpProcessInfo.ItemName,
\r
520 tmpProcessInfo.UsePassword, tmpProcessInfo.Password);
\r
521 if (result != S_OK)
\r
523 RefreshListCtrl(state);
\r
528 class CTmpProcessInfoList
\r
531 CObjectVector<CTmpProcessInfo> _items;
\r
532 } g_TmpProcessInfoList;
\r
535 class CExitEventLauncher
\r
538 NWindows::NSynchronization::CManualResetEvent _exitEvent;
\r
539 CExitEventLauncher()
\r
541 if (_exitEvent.Create(false) != S_OK)
\r
544 ~CExitEventLauncher() { _exitEvent.Set(); }
\r
545 } g_ExitEventLauncher;
\r
547 static THREAD_FUNC_DECL MyThreadFunction(void *param)
\r
549 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param);
\r
550 const CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get();
\r
552 HANDLE hProcess = tmpProcessInfo->ProcessHandle;
\r
553 HANDLE events[2] = { g_ExitEventLauncher._exitEvent, hProcess};
\r
554 DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
\r
555 ::CloseHandle(hProcess);
\r
556 if (waitResult == WAIT_OBJECT_0 + 0)
\r
558 if (waitResult != WAIT_OBJECT_0 + 1)
\r
561 NFind::CFileInfoW newFileInfo;
\r
562 if (newFileInfo.Find(tmpProcessInfo->FilePath))
\r
564 if (tmpProcessInfo->WasChanged(newFileInfo))
\r
566 UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE,
\r
567 0x03020280, tmpProcessInfo->ItemName);
\r
568 if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
\r
570 if (SendMessage(tmpProcessInfo->Window, kOpenItemChanged, 0, (LONG_PTR)tmpProcessInfo) != 1)
\r
572 ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE,
\r
573 0x03020281, tmpProcessInfo->FilePath), L"7-Zip", MB_OK | MB_ICONSTOP);
\r
579 tmpProcessInfo->DeleteDirAndFile();
\r
583 void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode)
\r
585 const UString name = GetItemName(index);
\r
586 if (IsNameVirus(name))
\r
588 MessageBoxErrorLang(IDS_VIRUS, 0x03020284);
\r
592 CMyComPtr<IFolderOperations> folderOperations;
\r
593 if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK)
\r
595 MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208);
\r
599 bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name));
\r
601 UString fullVirtPath = _currentFolderPrefix + name;
\r
603 NFile::NDirectory::CTempDirectoryW tempDirectory;
\r
604 tempDirectory.Create(kTempDirPrefix);
\r
605 UString tempDir = tempDirectory.GetPath();
\r
606 UString tempDirNorm = tempDir;
\r
607 NFile::NName::NormalizeDirPathPrefix(tempDirNorm);
\r
609 UString tempFilePath = tempDirNorm + GetCorrectFsPath(name);
\r
611 CTempFileInfo tempFileInfo;
\r
612 tempFileInfo.ItemName = name;
\r
613 tempFileInfo.FolderPath = tempDir;
\r
614 tempFileInfo.FilePath = tempFilePath;
\r
615 tempFileInfo.NeedDelete = true;
\r
619 CMyComPtr<IInArchiveGetStream> getStream;
\r
620 _folder.QueryInterface(IID_IInArchiveGetStream, &getStream);
\r
623 CMyComPtr<ISequentialInStream> subSeqStream;
\r
624 getStream->GetStream(index, &subSeqStream);
\r
627 CMyComPtr<IInStream> subStream;
\r
628 subSeqStream.QueryInterface(IID_IInStream, &subStream);
\r
632 if (OpenItemAsArchive(subStream, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK)
\r
634 tempDirectory.DisableDeleting();
\r
644 CRecordVector<UInt32> indices;
\r
645 indices.Add(index);
\r
647 UStringVector messages;
\r
649 bool usePassword = false;
\r
651 if (_parentFolders.Size() > 0)
\r
653 const CFolderLink &fl = _parentFolders.Back();
\r
654 usePassword = fl.UsePassword;
\r
655 password = fl.Password;
\r
658 HRESULT result = CopyTo(indices, tempDirNorm, false, true, &messages, usePassword, password);
\r
660 if (_parentFolders.Size() > 0)
\r
662 CFolderLink &fl = _parentFolders.Back();
\r
663 fl.UsePassword = usePassword;
\r
664 fl.Password = password;
\r
667 if (!messages.IsEmpty())
\r
669 if (result != S_OK)
\r
671 if (result != E_ABORT)
\r
672 MessageBoxError(result);
\r
680 if (OpenItemAsArchive(NULL, tempFileInfo, fullVirtPath, UString(), encrypted) == S_OK)
\r
682 tempDirectory.DisableDeleting();
\r
688 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo());
\r
689 CTmpProcessInfo *tmpProcessInfo = tmpProcessInfoPtr.get();
\r
690 tmpProcessInfo->FolderPath = tempDir;
\r
691 tmpProcessInfo->FilePath = tempFilePath;
\r
692 tmpProcessInfo->NeedDelete = true;
\r
693 tmpProcessInfo->UsePassword = usePassword;
\r
694 tmpProcessInfo->Password = password;
\r
696 if (!tmpProcessInfo->FileInfo.Find(tempFilePath))
\r
699 CTmpProcessInfoRelease tmpProcessInfoRelease(*tmpProcessInfo);
\r
707 res = StartEditApplication(tempFilePath, (HWND)*this, process);
\r
709 res = StartApplication(tempDirNorm, tempFilePath, (HWND)*this, process);
\r
711 if ((HANDLE)process == 0)
\r
714 tmpProcessInfo->Window = (HWND)(*this);
\r
715 tmpProcessInfo->FullPathFolderPrefix = _currentFolderPrefix;
\r
716 tmpProcessInfo->ItemName = name;
\r
717 tmpProcessInfo->ProcessHandle = process.Detach();
\r
719 NWindows::CThread thread;
\r
720 if (thread.Create(MyThreadFunction, tmpProcessInfo) != S_OK)
\r
722 tempDirectory.DisableDeleting();
\r
723 tmpProcessInfoPtr.release();
\r
724 tmpProcessInfoRelease._needDelete = false;
\r
728 static const UINT64 kTimeLimit = UINT64(10000000) * 3600 * 24;
\r
730 static bool CheckDeleteItem(UINT64 currentFileTime, UINT64 folderFileTime)
\r
732 return (currentFileTime - folderFileTime > kTimeLimit &&
\r
733 folderFileTime - currentFileTime > kTimeLimit);
\r
736 void DeleteOldTempFiles()
\r
739 if(!NFile::NDirectory::MyGetTempPath(tempPath))
\r
742 UINT64 currentFileTime;
\r
743 NTime::GetCurUtcFileTime(currentFileTime);
\r
744 UString searchWildCard = tempPath + kTempDirPrefix + L"*.tmp";
\r
745 searchWildCard += WCHAR(NName::kAnyStringWildcard);
\r
746 NFind::CEnumeratorW enumerator(searchWildCard);
\r
747 NFind::CFileInfoW fileInfo;
\r
748 while(enumerator.Next(fileInfo))
\r
750 if (!fileInfo.IsDir())
\r
752 const UINT64 &cTime = *(const UINT64 *)(&fileInfo.CTime);
\r
753 if(CheckDeleteItem(cTime, currentFileTime))
\r
754 RemoveDirectoryWithSubItems(tempPath + fileInfo.Name);
\r