summaryrefslogtreecommitdiff
path: root/plugins/PluginUpdater/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-10-29 19:21:32 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-10-29 19:21:32 +0300
commit74e691804c25c6174cb619d21b19fb5dc94afa22 (patch)
tree98625fbff7a1c7da877f208e13d0e49962ddffa1 /plugins/PluginUpdater/src
parent21aaad51c5e0bcf7157bd8e37e6e8ee0d1e55525 (diff)
Plugin Updater: pu_stub utilities moved to mir_app
Diffstat (limited to 'plugins/PluginUpdater/src')
-rw-r--r--plugins/PluginUpdater/src/DlgListNew.cpp6
-rw-r--r--plugins/PluginUpdater/src/DlgUpdate.cpp12
-rw-r--r--plugins/PluginUpdater/src/Options.cpp2
-rw-r--r--plugins/PluginUpdater/src/Utils.cpp339
-rw-r--r--plugins/PluginUpdater/src/stdafx.h11
-rw-r--r--plugins/PluginUpdater/src/unzipfile.cpp8
6 files changed, 25 insertions, 353 deletions
diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp
index b470cff31c..fb6e5b59cd 100644
--- a/plugins/PluginUpdater/src/DlgListNew.cpp
+++ b/plugins/PluginUpdater/src/DlgListNew.cpp
@@ -162,7 +162,7 @@ public:
wcscat(szPath, L".test");
HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
- Button_SetElevationRequiredState(GetDlgItem(m_hwnd, IDOK), !IsProcessElevated());
+ Button_SetElevationRequiredState(GetDlgItem(m_hwnd, IDOK), !PU::IsProcessElevated());
else {
CloseHandle(hFile);
DeleteFile(szPath);
@@ -311,7 +311,7 @@ public:
if (DownloadFile(&p->File, nlc)) {
m_list.SetItemText(i, 1, TranslateT("Succeeded."));
if (!unzip(p->File.wszDiskPath, wszMirandaPath, wszBackupFolder, false))
- SafeDeleteFile(p->File.wszDiskPath); // remove .zip after successful update
+ PU::SafeDeleteFile(p->File.wszDiskPath); // remove .zip after successful update
db_unset(0, DB_MODULE_NEW_FILES, _T2A(p->wszOldName));
}
else m_list.SetItemText(i, 1, TranslateT("Failed!"));
@@ -339,7 +339,7 @@ static void ApplyDownloads(void *param)
auto *pDlg = (CMissingPLuginsDlg *)param;
// if we need to escalate priviledges, launch a atub
- if (PrepareEscalation())
+ if (PU::PrepareEscalation())
pDlg->Unpack();
pDlg->Close();
diff --git a/plugins/PluginUpdater/src/DlgUpdate.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp
index dc5a53a527..e79d94bdc4 100644
--- a/plugins/PluginUpdater/src/DlgUpdate.cpp
+++ b/plugins/PluginUpdater/src/DlgUpdate.cpp
@@ -39,7 +39,7 @@ class CUpdateDLg : public CDlgBase
OBJLIST<FILEINFO> todo(*pDlg->m_todo);
// 1) If we need to escalate priviledges, launch a stub
- if (!PrepareEscalation()) {
+ if (!PU::PrepareEscalation()) {
pDlg->Close();
return;
}
@@ -113,7 +113,7 @@ LBL_Error:
if (dwErrorCode = unzip(it->File.wszDiskPath, wszMirandaPath, wszBackupFolder, true))
goto LBL_Error;
- SafeDeleteFile(it->File.wszDiskPath); // remove .zip after successful update
+ PU::SafeDeleteFile(it->File.wszDiskPath); // remove .zip after successful update
}
}
}
@@ -134,7 +134,7 @@ LBL_Error:
else {
ptrW oldbin(g_plugin.getWStringA("OldBin2"));
if (oldbin) {
- SafeDeleteFile(oldbin);
+ PU::SafeDeleteFile(oldbin);
g_plugin.delSetting("OldBin2");
}
}
@@ -213,7 +213,7 @@ public:
HANDLE hFile = CreateFileW(wszPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile == INVALID_HANDLE_VALUE)
// Running Windows Vista or later (major version >= 6).
- Button_SetElevationRequiredState(btnOk.GetHwnd(), !IsProcessElevated());
+ Button_SetElevationRequiredState(btnOk.GetHwnd(), !PU::IsProcessElevated());
else {
CloseHandle(hFile);
DeleteFileW(wszPath);
@@ -395,7 +395,7 @@ static void DlgUpdateSilent(void *param)
}
// 1) If we need to escalate priviledges, launch a stub
- if (!PrepareEscalation()) {
+ if (!PU::PrepareEscalation()) {
delete &UpdateFiles;
return;
}
@@ -462,7 +462,7 @@ LBL_Error:
// remove .zip after successful update
if (dwErrorCode = unzip(it->File.wszDiskPath, wszMirandaPath, wszBackupFolder, true))
goto LBL_Error;
- SafeDeleteFile(it->File.wszDiskPath);
+ PU::SafeDeleteFile(it->File.wszDiskPath);
}
}
}
diff --git a/plugins/PluginUpdater/src/Options.cpp b/plugins/PluginUpdater/src/Options.cpp
index c796524d7f..936551f5c6 100644
--- a/plugins/PluginUpdater/src/Options.cpp
+++ b/plugins/PluginUpdater/src/Options.cpp
@@ -288,7 +288,7 @@ public:
FindClose(hFind);
}
- if (PrepareEscalation())
+ if (PU::PrepareEscalation())
RemoveBackupFolders();
// if user tried to change the channel, run the update dialog immediately
diff --git a/plugins/PluginUpdater/src/Utils.cpp b/plugins/PluginUpdater/src/Utils.cpp
index 63c1ede5b4..41760a5303 100644
--- a/plugins/PluginUpdater/src/Utils.cpp
+++ b/plugins/PluginUpdater/src/Utils.cpp
@@ -20,7 +20,6 @@ Boston, MA 02111-1307, USA.
#include "stdafx.h"
HNETLIBUSER hNetlibUser = nullptr;
-HANDLE g_hPipe = nullptr;
/////////////////////////////////////////////////////////////////////////////////////
@@ -146,6 +145,8 @@ bool ParseHashes(const wchar_t *pwszUrl, ptrW &baseUrl, SERVLIST &arHashes)
return true;
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// Single file HTTP transaction
bool DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc)
{
@@ -215,7 +216,7 @@ bool DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc)
if (hFile != INVALID_HANDLE_VALUE) {
WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, nullptr);
CloseHandle(hFile);
- SafeMoveFile(wszTempFile, pFileURL->wszDiskPath);
+ PU::SafeMoveFile(wszTempFile, pFileURL->wszDiskPath);
}
}
return true;
@@ -232,212 +233,6 @@ bool DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc)
return false;
}
-/////////////////////////////////////////////////////////////////////////////////////
-// FUNCTION: IsRunAsAdmin()
-//
-// PURPOSE: The function checks whether the current process is run as
-// administrator. In other words, it dictates whether the primary access
-// token of the process belongs to user account that is a member of the
-// local Administrators group and it is elevated.
-//
-// RETURN VALUE: Returns TRUE if the primary access token of the process
-// belongs to user account that is a member of the local Administrators
-// group and it is elevated. Returns FALSE if the token does not.
-//
-// EXCEPTION: If this function fails, it throws a C++ DWORD exception which
-// contains the Win32 error code of the failure.
-//
-// EXAMPLE CALL:
-// try
-// {
-// if (IsRunAsAdmin())
-// wprintf (L"Process is run as administrator\n");
-// else
-// wprintf (L"Process is not run as administrator\n");
-// }
-// catch (DWORD dwError)
-// {
-// wprintf(L"IsRunAsAdmin failed w/err %lu\n", dwError);
-// }
-
-BOOL IsRunAsAdmin()
-{
- BOOL fIsRunAsAdmin = FALSE;
- DWORD dwError = ERROR_SUCCESS;
- PSID pAdministratorsGroup = nullptr;
-
- // Allocate and initialize a SID of the administrators group.
- SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
- if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdministratorsGroup)) {
- dwError = GetLastError();
- goto Cleanup;
- }
-
- // Determine whether the SID of administrators group is bEnabled in
- // the primary access token of the process.
- if (!CheckTokenMembership(nullptr, pAdministratorsGroup, &fIsRunAsAdmin)) {
- dwError = GetLastError();
- goto Cleanup;
- }
-
-Cleanup:
- // Centralized cleanup for all allocated resources.
- if (pAdministratorsGroup) {
- FreeSid(pAdministratorsGroup);
- pAdministratorsGroup = nullptr;
- }
-
- // Throw the error if something failed in the function.
- if (ERROR_SUCCESS != dwError) {
- throw dwError;
- }
-
- return fIsRunAsAdmin;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
-// FUNCTION: IsProcessElevated()
-//
-// PURPOSE: The function gets the elevation information of the current
-// process. It dictates whether the process is elevated or not. Token
-// elevation is only available on Windows Vista and newer operating
-// systems, thus IsProcessElevated throws a C++ exception if it is called
-// on systems prior to Windows Vista. It is not appropriate to use this
-// function to determine whether a process is run as administartor.
-//
-// RETURN VALUE: Returns TRUE if the process is elevated. Returns FALSE if
-// it is not.
-//
-// EXCEPTION: If this function fails, it throws a C++ DWORD exception
-// which contains the Win32 error code of the failure. For example, if
-// IsProcessElevated is called on systems prior to Windows Vista, the error
-// code will be ERROR_INVALID_PARAMETER.
-//
-// NOTE: TOKEN_INFORMATION_CLASS provides TokenElevationType to check the
-// elevation type (TokenElevationTypeDefault / TokenElevationTypeLimited /
-// TokenElevationTypeFull) of the process. It is different from
-// TokenElevation in that, when UAC is turned off, elevation type always
-// returns TokenElevationTypeDefault even though the process is elevated
-// (Integrity Level == High). In other words, it is not safe to say if the
-// process is elevated based on elevation type. Instead, we should use
-// TokenElevation.
-//
-// EXAMPLE CALL:
-// try
-// {
-// if (IsProcessElevated())
-// wprintf (L"Process is elevated\n");
-// else
-// wprintf (L"Process is not elevated\n");
-// }
-// catch (DWORD dwError)
-// {
-// wprintf(L"IsProcessElevated failed w/err %lu\n", dwError);
-// }
-
-BOOL IsProcessElevated()
-{
- BOOL fIsElevated = FALSE;
- DWORD dwError = ERROR_SUCCESS;
- HANDLE hToken = nullptr;
-
- // Open the primary access token of the process with TOKEN_QUERY.
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
- dwError = GetLastError();
- goto Cleanup;
- }
-
- // Retrieve token elevation information.
- TOKEN_ELEVATION elevation;
- DWORD dwSize;
- if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) {
- // When the process is run on operating systems prior to Windows
- // Vista, GetTokenInformation returns FALSE with the
- // ERROR_INVALID_PARAMETER error code because TokenElevation is
- // not supported on those operating systems.
- dwError = GetLastError();
- goto Cleanup;
- }
-
- fIsElevated = elevation.TokenIsElevated;
-
-Cleanup:
- // Centralized cleanup for all allocated resources.
- if (hToken) {
- CloseHandle(hToken);
- hToken = nullptr;
- }
-
- // Throw the error if something failed in the function.
- if (ERROR_SUCCESS != dwError) {
- throw dwError;
- }
-
- return fIsElevated;
-}
-
-bool PrepareEscalation()
-{
- // First try to create a file near Miranda32.exe
- TFileName szPath;
- GetModuleFileName(nullptr, szPath, _countof(szPath));
- wchar_t *ext = wcsrchr(szPath, '.');
- if (ext != nullptr)
- *ext = '\0';
- wcscat(szPath, L".test");
-
- HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
- if (hFile != INVALID_HANDLE_VALUE) {
- // we are admins or UAC is disable, cool
- CloseHandle(hFile);
- DeleteFile(szPath);
- return true;
- }
-
- // Check the current process's "run as administrator" status.
- if (IsRunAsAdmin())
- return true;
-
- // if pipe already opened?
- if (g_hPipe != nullptr)
- return true;
-
- // Elevate the process. Create a pipe for a stub first
- TFileName wzPipeName;
- mir_snwprintf(wzPipeName, L"\\\\.\\pipe\\Miranda_Pu_%d", GetCurrentProcessId());
- g_hPipe = CreateNamedPipe(wzPipeName, PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, nullptr);
- if (g_hPipe == INVALID_HANDLE_VALUE) {
- g_hPipe = nullptr;
- }
- else {
- wchar_t cmdLine[100], *p;
- GetModuleFileName(nullptr, szPath, ARRAYSIZE(szPath));
- if ((p = wcsrchr(szPath, '\\')) != nullptr)
- wcscpy(p + 1, L"pu_stub.exe");
- mir_snwprintf(cmdLine, L"%d", GetCurrentProcessId());
-
- // Launch a stub
- SHELLEXECUTEINFO sei = { sizeof(sei) };
- sei.lpVerb = L"runas";
- sei.lpFile = szPath;
- sei.lpParameters = cmdLine;
- sei.hwnd = nullptr;
- sei.nShow = SW_NORMAL;
- if (ShellExecuteEx(&sei)) {
- if (g_hPipe != nullptr)
- ConnectNamedPipe(g_hPipe, nullptr);
- return true;
- }
-
- DWORD dwError = GetLastError();
- if (dwError == ERROR_CANCELLED) {
- // The user refused to allow privileges elevation.
- // Do nothing ...
- }
- }
- return false;
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
// Folder creation
@@ -451,10 +246,10 @@ void CreateWorkFolders(TFileName &wszTempFolder, TFileName &wszBackupFolder)
SYSTEMTIME st;
GetLocalTime(&st);
mir_snwprintf(wszBackupFolder, L"%s\\Backups\\BKP%04d-%02d-%02d %02d-%02d-%02d-%03d", g_wszRoot, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
- SafeCreateDirectory(wszBackupFolder);
+ PU::SafeCreateDirectory(wszBackupFolder);
mir_snwprintf(wszTempFolder, L"%s\\Temp", g_wszRoot);
- SafeCreateDirectory(wszTempFolder);
+ PU::SafeCreateDirectory(wszTempFolder);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -480,10 +275,10 @@ void RemoveBackupFolders()
FindClose(hFind);
// remove all folders with lesser dates if there're more than 10 folders
- if (PrepareEscalation()) {
+ if (PU::PrepareEscalation()) {
while (arNames.getCount() > g_plugin.iNumberBackups) {
mir_snwprintf(wszMask, L"%s\\Backups\\%s", g_wszRoot, arNames[0].c_str());
- SafeDeleteDirectory(wszMask);
+ PU::SafeDeleteDirectory(wszMask);
arNames.remove(00);
}
}
@@ -512,7 +307,7 @@ static void SafeMoveFolder(const wchar_t *wszSrc, const wchar_t *wszDest)
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
SafeMoveFolder(wszNewSrc, wszNewDest);
else
- SafeMoveFile(wszNewSrc, wszNewDest);
+ PU::SafeMoveFile(wszNewSrc, wszNewDest);
}
while (FindNextFileW(hFind, &fdata));
@@ -524,119 +319,7 @@ void RollbackChanges(TFileName &pwszBackupFolder)
VARSW dirname(L"%miranda_path%");
SafeMoveFolder(pwszBackupFolder, dirname);
- SafeDeleteDirectory(pwszBackupFolder);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-int TransactPipe(int opcode, const wchar_t *p1, const wchar_t *p2)
-{
- BYTE buf[1024];
- DWORD l1 = lstrlen(p1), l2 = lstrlen(p2);
- if (l1 > MAX_PATH || l2 > MAX_PATH)
- return ERROR_BAD_ARGUMENTS;
-
- *(DWORD *)buf = opcode;
- wchar_t *dst = (wchar_t *)&buf[sizeof(DWORD)];
- lstrcpy(dst, p1);
- dst += l1 + 1;
- if (p2) {
- lstrcpy(dst, p2);
- dst += l2 + 1;
- }
- else *dst++ = 0;
-
- DWORD dwBytes = 0, dwError;
- if (!WriteFile(g_hPipe, buf, (DWORD)((BYTE *)dst - buf), &dwBytes, nullptr))
- return GetLastError();
-
- dwError = 0;
- if (!ReadFile(g_hPipe, &dwError, sizeof(DWORD), &dwBytes, nullptr))
- return GetLastError();
- if (dwBytes != sizeof(DWORD))
- return ERROR_BAD_ARGUMENTS;
-
- return dwError;
-}
-
-int SafeCopyFile(const wchar_t *pSrc, const wchar_t *pDst)
-{
- if (g_hPipe == nullptr)
- return CopyFileW(pSrc, pDst, FALSE);
-
- return TransactPipe(1, pSrc, pDst);
-}
-
-int SafeMoveFile(const wchar_t *pSrc, const wchar_t *pDst)
-{
- if (g_hPipe == nullptr) {
- if (!DeleteFileW(pDst)) {
- DWORD dwError = GetLastError();
- if (dwError != ERROR_ACCESS_DENIED && dwError != ERROR_FILE_NOT_FOUND)
- return dwError;
- }
-
- if (!MoveFileW(pSrc, pDst)) { // use copy on error
- switch (DWORD dwError = GetLastError()) {
- case ERROR_ALREADY_EXISTS:
- case ERROR_FILE_NOT_FOUND:
- return 0; // this file was included into many archives, so Miranda tries to move it again & again
-
- case ERROR_ACCESS_DENIED:
- case ERROR_SHARING_VIOLATION:
- case ERROR_LOCK_VIOLATION:
- // use copy routine if a move operation isn't available
- // for example, when files are on different disks
- if (!CopyFileW(pSrc, pDst, FALSE))
- return GetLastError();
-
- if (!DeleteFileW(pSrc))
- return GetLastError();
- break;
-
- default:
- return dwError;
- }
- }
-
- return ERROR_SUCCESS;
- }
-
- return TransactPipe(2, pSrc, pDst);
-}
-
-int SafeDeleteFile(const wchar_t *pwszFile)
-{
- if (g_hPipe == nullptr)
- return DeleteFile(pwszFile);
-
- return TransactPipe(3, pwszFile, nullptr);
-}
-
-int SafeCreateDirectory(const wchar_t *pwszFolder)
-{
- if (g_hPipe == nullptr)
- return CreateDirectoryTreeW(pwszFolder);
-
- return TransactPipe(4, pwszFolder, nullptr);
-}
-
-int SafeDeleteDirectory(const wchar_t *pwszDirName)
-{
- if (g_hPipe == nullptr)
- return DeleteDirectoryTreeW(pwszDirName);
-
- return TransactPipe(6, pwszDirName, nullptr);
-}
-
-int SafeCreateFilePath(const wchar_t *pwszFolder)
-{
- if (g_hPipe == nullptr) {
- CreatePathToFileW(pwszFolder);
- return 0;
- }
-
- return TransactPipe(5, pwszFolder, nullptr);
+ PU::SafeDeleteDirectory(pwszBackupFolder);
}
int BackupFile(wchar_t *pwszSrcFileName, wchar_t *pwszBackFileName)
@@ -644,9 +327,9 @@ int BackupFile(wchar_t *pwszSrcFileName, wchar_t *pwszBackFileName)
if (_waccess(pwszSrcFileName, 0))
return 0;
- SafeCreateFilePath(pwszBackFileName);
+ PU::SafeCreateFilePath(pwszBackFileName);
- return SafeMoveFile(pwszSrcFileName, pwszBackFileName);
+ return PU::SafeMoveFile(pwszSrcFileName, pwszBackFileName);
}
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/PluginUpdater/src/stdafx.h b/plugins/PluginUpdater/src/stdafx.h
index 8a0aea883e..db71968ea2 100644
--- a/plugins/PluginUpdater/src/stdafx.h
+++ b/plugins/PluginUpdater/src/stdafx.h
@@ -153,7 +153,6 @@ using namespace std;
extern DWORD g_mirandaVersion;
extern wchar_t g_wszRoot[MAX_PATH], g_wszTempPath[MAX_PATH];
-extern HANDLE g_hPipe;
extern HNETLIBUSER hNetlibUser;
extern IconItem iconList[];
@@ -254,18 +253,8 @@ int unzip(const wchar_t *pwszZipFile, wchar_t *pwszDestPath, wchar_t *pwszBackP
int CalculateModuleHash(const wchar_t *pwszFileName, char *dest);
-BOOL IsProcessElevated(void);
-bool PrepareEscalation(void);
-
void CreateWorkFolders(TFileName &wszTempFolder, TFileName &wszBackupFolder);
void RemoveBackupFolders(void);
void RollbackChanges(TFileName &pwszBackupFolder);
-int SafeCreateDirectory(const wchar_t *pwszDirName);
-int SafeDeleteDirectory(const wchar_t *pwszDirName);
-int SafeCopyFile(const wchar_t *pwszSrc, const wchar_t *pwszDst);
-int SafeMoveFile(const wchar_t *pwszSrc, const wchar_t *pwszDst);
-int SafeDeleteFile(const wchar_t *pwszSrc);
-int SafeCreateFilePath(const wchar_t *pFolder);
-
char* StrToLower(char *str);
diff --git a/plugins/PluginUpdater/src/unzipfile.cpp b/plugins/PluginUpdater/src/unzipfile.cpp
index fb3bb2ae5a..2dbe754af6 100644
--- a/plugins/PluginUpdater/src/unzipfile.cpp
+++ b/plugins/PluginUpdater/src/unzipfile.cpp
@@ -66,10 +66,10 @@ int extractCurrentFile(unzFile uf, wchar_t *pwszDestPath, wchar_t *pwszBackPath,
}
PrepareFileName(wszDestFile, _countof(wszDestFile), pwszDestPath, pwszNewName);
- SafeCreateFilePath(wszDestFile);
+ PU::SafeCreateFilePath(wszDestFile);
wchar_t *pwszFile2unzip;
- if (g_hPipe == nullptr) // direct mode
+ if (PU::IsDirect())
pwszFile2unzip = wszDestFile;
else {
TFileName wszTempPath;
@@ -103,8 +103,8 @@ int extractCurrentFile(unzFile uf, wchar_t *pwszDestPath, wchar_t *pwszBackPath,
CloseHandle(hFile);
unzCloseCurrentFile(uf); /* don't lose the error */
- if (g_hPipe)
- SafeMoveFile(pwszFile2unzip, wszDestFile);
+ if (!PU::IsDirect())
+ PU::SafeMoveFile(pwszFile2unzip, wszDestFile);
}
return err;
}