mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-11 00:07:09 -06:00
18.00
This commit is contained in:
@@ -55,7 +55,8 @@ static bool GetSymLink(CFSTR path, CReparseAttr &attr)
|
||||
if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))
|
||||
return false;
|
||||
|
||||
if (!attr.Parse(buf, returnedSize))
|
||||
DWORD errorCode = 0;
|
||||
if (!attr.Parse(buf, returnedSize, errorCode))
|
||||
return false;
|
||||
|
||||
CByteBuffer data2;
|
||||
@@ -291,7 +292,8 @@ void CLinkDialog::OnButton_Link()
|
||||
}
|
||||
|
||||
CReparseAttr attr;
|
||||
if (!attr.Parse(data, data.Size()))
|
||||
DWORD errorCode = 0;
|
||||
if (!attr.Parse(data, data.Size(), errorCode))
|
||||
{
|
||||
ShowError(L"Internal conversion error");
|
||||
return;
|
||||
|
||||
@@ -827,7 +827,8 @@ void CPanel::OpenFolder(int index)
|
||||
SetNewFolder(newFolder);
|
||||
LoadFullPath();
|
||||
RefreshListCtrl();
|
||||
_listView.SetItemState_Selected(_listView.GetFocusedItem());
|
||||
// 17.02: fixed : now we don't select first item
|
||||
// _listView.SetItemState_Selected(_listView.GetFocusedItem());
|
||||
_listView.EnsureVisible(_listView.GetFocusedItem(), false);
|
||||
}
|
||||
|
||||
|
||||
@@ -702,6 +702,8 @@ void CPanel::Refresh_StatusBar()
|
||||
|
||||
wchar_t temp[32];
|
||||
ConvertUInt32ToString(indices.Size(), temp);
|
||||
wcscat(temp, L" / ");
|
||||
ConvertUInt32ToString(_selectedStatusVector.Size(), temp + wcslen(temp));
|
||||
|
||||
// UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size()));
|
||||
// UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size()));
|
||||
|
||||
@@ -403,82 +403,117 @@ void CPanel::EditPaste()
|
||||
// InvokeSystemCommand("paste");
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct CFolderPidls
|
||||
{
|
||||
LPITEMIDLIST parent;
|
||||
CRecordVector<LPITEMIDLIST> items;
|
||||
|
||||
CFolderPidls(): parent(NULL) {}
|
||||
~CFolderPidls()
|
||||
{
|
||||
FOR_VECTOR (i, items)
|
||||
CoTaskMemFree(items[i]);
|
||||
CoTaskMemFree(parent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CPanel::CreateShellContextMenu(
|
||||
const CRecordVector<UInt32> &operatedIndices,
|
||||
CMyComPtr<IContextMenu> &systemContextMenu)
|
||||
{
|
||||
systemContextMenu.Release();
|
||||
UString folderPath = GetFsPath();
|
||||
const UString folderPath = GetFsPath();
|
||||
|
||||
CMyComPtr<IShellFolder> desktopFolder;
|
||||
RINOK(::SHGetDesktopFolder(&desktopFolder));
|
||||
if (!desktopFolder)
|
||||
{
|
||||
// ShowMessage("Failed to get Desktop folder.");
|
||||
// ShowMessage("Failed to get Desktop folder");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Separate the file from the folder.
|
||||
|
||||
|
||||
// Get a pidl for the folder the file
|
||||
// is located in.
|
||||
LPITEMIDLIST parentPidl;
|
||||
CFolderPidls pidls;
|
||||
DWORD eaten;
|
||||
|
||||
// if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer"
|
||||
RINOK(desktopFolder->ParseDisplayName(
|
||||
GetParent(), 0, (wchar_t *)(const wchar_t *)folderPath,
|
||||
&eaten, &parentPidl, 0));
|
||||
GetParent(), NULL, (wchar_t *)(const wchar_t *)folderPath,
|
||||
&eaten, &pidls.parent, NULL));
|
||||
|
||||
/*
|
||||
STRRET pName;
|
||||
res = desktopFolder->GetDisplayNameOf(pidls.parent, SHGDN_NORMAL, &pName);
|
||||
WCHAR dir[MAX_PATH];
|
||||
if (!SHGetPathFromIDListW(pidls.parent, dir))
|
||||
dir[0] = 0;
|
||||
*/
|
||||
|
||||
if (!pidls.parent)
|
||||
return E_FAIL;
|
||||
|
||||
if (operatedIndices.IsEmpty())
|
||||
{
|
||||
// how to get IContextMenu, if there are no selected files?
|
||||
return E_FAIL;
|
||||
|
||||
/*
|
||||
xp64 :
|
||||
1) we can't use GetUIObjectOf() with (numItems == 0), it throws exception
|
||||
2) we can't use desktopFolder->GetUIObjectOf() with absolute pidls of folder
|
||||
context menu items are different in that case:
|
||||
"Open / Explorer" for folder
|
||||
"Delete" for "My Computer" icon
|
||||
"Preperties" for "System"
|
||||
*/
|
||||
/*
|
||||
parentFolder = desktopFolder;
|
||||
pidls.items.AddInReserved(pidls.parent);
|
||||
pidls.parent = NULL;
|
||||
*/
|
||||
|
||||
// CreateViewObject() doesn't show all context menu items
|
||||
/*
|
||||
HRESULT res = parentFolder->CreateViewObject(
|
||||
GetParent(), IID_IContextMenu, (void**)&systemContextMenu);
|
||||
*/
|
||||
}
|
||||
|
||||
// Get an IShellFolder for the folder
|
||||
// the file is located in.
|
||||
CMyComPtr<IShellFolder> parentFolder;
|
||||
RINOK(desktopFolder->BindToObject(parentPidl,
|
||||
0, IID_IShellFolder, (void**)&parentFolder));
|
||||
RINOK(desktopFolder->BindToObject(pidls.parent,
|
||||
NULL, IID_IShellFolder, (void**)&parentFolder));
|
||||
if (!parentFolder)
|
||||
{
|
||||
// ShowMessage("Invalid file name.");
|
||||
// ShowMessage("Invalid file name");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Get a pidl for the file itself.
|
||||
CRecordVector<LPITEMIDLIST> pidls;
|
||||
pidls.ClearAndReserve(operatedIndices.Size());
|
||||
pidls.items.ClearAndReserve(operatedIndices.Size());
|
||||
FOR_VECTOR (i, operatedIndices)
|
||||
{
|
||||
LPITEMIDLIST pidl;
|
||||
UString fileName = GetItemRelPath2(operatedIndices[i]);
|
||||
const UString fileName = GetItemRelPath2(operatedIndices[i]);
|
||||
RINOK(parentFolder->ParseDisplayName(GetParent(), 0,
|
||||
(wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));
|
||||
pidls.AddInReserved(pidl);
|
||||
(wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0));
|
||||
pidls.items.AddInReserved(pidl);
|
||||
}
|
||||
|
||||
// Get IContextMenu for items
|
||||
|
||||
ITEMIDLIST temp;
|
||||
if (pidls.Size() == 0)
|
||||
RINOK(parentFolder->GetUIObjectOf(GetParent(), pidls.items.Size(),
|
||||
(LPCITEMIDLIST *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu));
|
||||
|
||||
if (!systemContextMenu)
|
||||
{
|
||||
temp.mkid.cb = 0;
|
||||
/*
|
||||
LPITEMIDLIST pidl;
|
||||
HRESULT result = parentFolder->ParseDisplayName(GetParent(), 0,
|
||||
L"." WSTRING_PATH_SEPARATOR, &eaten, &pidl, 0);
|
||||
if (result != NOERROR)
|
||||
return;
|
||||
*/
|
||||
pidls.Add(&temp);
|
||||
}
|
||||
|
||||
// Get the IContextMenu for the file.
|
||||
CMyComPtr<IContextMenu> cm;
|
||||
RINOK( parentFolder->GetUIObjectOf(GetParent(), pidls.Size(),
|
||||
(LPCITEMIDLIST *)&pidls.Front(), IID_IContextMenu, 0, (void**)&cm));
|
||||
if (!cm)
|
||||
{
|
||||
// ShowMessage("Unable to get context menu interface.");
|
||||
// ShowMessage("Unable to get context menu interface");
|
||||
return E_FAIL;
|
||||
}
|
||||
systemContextMenu = cm;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CPanel::CreateSystemMenu(HMENU menuSpec,
|
||||
const CRecordVector<UInt32> &operatedIndices,
|
||||
CMyComPtr<IContextMenu> &systemContextMenu)
|
||||
|
||||
@@ -218,6 +218,8 @@ void CPanel::InvertSelection()
|
||||
FOR_VECTOR (i, _selectedStatusVector)
|
||||
if (_selectedStatusVector[i])
|
||||
numSelected++;
|
||||
// 17.02: fixed : now we invert item even, if single item is selected
|
||||
/*
|
||||
if (numSelected == 1)
|
||||
{
|
||||
int focused = _listView.GetFocusedItem();
|
||||
@@ -229,6 +231,7 @@ void CPanel::InvertSelection()
|
||||
_selectedStatusVector[realIndex] = false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
FOR_VECTOR (i, _selectedStatusVector)
|
||||
_selectedStatusVector[i] = !_selectedStatusVector[i];
|
||||
|
||||
@@ -77,8 +77,6 @@ UString CVolSeqName::GetNextName()
|
||||
return UnchangedPart + ChangedPart;
|
||||
}
|
||||
|
||||
static const UInt32 kBufSize = (1 << 20);
|
||||
|
||||
class CThreadSplit: public CProgressThreadVirt
|
||||
{
|
||||
HRESULT ProcessVirt();
|
||||
@@ -89,30 +87,84 @@ public:
|
||||
CRecordVector<UInt64> VolumeSizes;
|
||||
};
|
||||
|
||||
|
||||
class CPreAllocOutFile
|
||||
{
|
||||
UInt64 _preAllocSize;
|
||||
public:
|
||||
NIO::COutFile File;
|
||||
UInt64 Written;
|
||||
|
||||
CPreAllocOutFile(): _preAllocSize(0), Written(0) {}
|
||||
|
||||
~CPreAllocOutFile()
|
||||
{
|
||||
SetCorrectFileLength();
|
||||
}
|
||||
|
||||
void PreAlloc(UInt64 preAllocSize)
|
||||
{
|
||||
_preAllocSize = 0;
|
||||
if (File.SetLength(preAllocSize))
|
||||
_preAllocSize = preAllocSize;
|
||||
File.SeekToBegin();
|
||||
}
|
||||
|
||||
bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
|
||||
{
|
||||
bool res = File.Write(data, size, processedSize);
|
||||
Written += processedSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
SetCorrectFileLength();
|
||||
Written = 0;
|
||||
_preAllocSize = 0;
|
||||
File.Close();
|
||||
}
|
||||
|
||||
void SetCorrectFileLength()
|
||||
{
|
||||
if (Written < _preAllocSize)
|
||||
{
|
||||
File.SetLength(Written);
|
||||
_preAllocSize = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static const UInt32 kBufSize = (1 << 20);
|
||||
|
||||
HRESULT CThreadSplit::ProcessVirt()
|
||||
{
|
||||
NIO::CInFile inFile;
|
||||
if (!inFile.Open(FilePath))
|
||||
return GetLastError();
|
||||
NIO::COutFile outFile;
|
||||
CMyBuffer bufferObject;
|
||||
if (!bufferObject.Allocate(kBufSize))
|
||||
|
||||
CPreAllocOutFile outFile;
|
||||
|
||||
CMyBuffer buffer;
|
||||
if (!buffer.Allocate(kBufSize))
|
||||
return E_OUTOFMEMORY;
|
||||
Byte *buffer = (Byte *)(void *)bufferObject;
|
||||
UInt64 curVolSize = 0;
|
||||
|
||||
CVolSeqName seqName;
|
||||
seqName.SetNumDigits(NumVolumes);
|
||||
|
||||
UInt64 length;
|
||||
if (!inFile.GetLength(length))
|
||||
return GetLastError();
|
||||
|
||||
CProgressSync &sync = ProgressDialog.Sync;
|
||||
sync.Set_NumBytesTotal(length);
|
||||
UInt64 pos = 0;
|
||||
|
||||
UInt64 pos = 0;
|
||||
UInt64 prev = 0;
|
||||
UInt64 numFiles = 0;
|
||||
unsigned volIndex = 0;
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt64 volSize;
|
||||
@@ -121,46 +173,65 @@ HRESULT CThreadSplit::ProcessVirt()
|
||||
else
|
||||
volSize = VolumeSizes.Back();
|
||||
|
||||
UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize));
|
||||
UInt32 needSize = kBufSize;
|
||||
{
|
||||
const UInt64 rem = volSize - outFile.Written;
|
||||
if (needSize > rem)
|
||||
needSize = (UInt32)rem;
|
||||
}
|
||||
UInt32 processedSize;
|
||||
if (!inFile.Read(buffer, needSize, processedSize))
|
||||
return GetLastError();
|
||||
if (processedSize == 0)
|
||||
break;
|
||||
return S_OK;
|
||||
needSize = processedSize;
|
||||
if (curVolSize == 0)
|
||||
|
||||
if (outFile.Written == 0)
|
||||
{
|
||||
FString name = VolBasePath;
|
||||
name += '.';
|
||||
name += us2fs(seqName.GetNextName());
|
||||
sync.Set_FilePath(fs2us(name));
|
||||
sync.Set_NumFilesCur(numFiles++);
|
||||
if (!outFile.Create(name, false))
|
||||
if (!outFile.File.Create(name, false))
|
||||
{
|
||||
HRESULT res = GetLastError();
|
||||
AddErrorPath(name);
|
||||
return res;
|
||||
}
|
||||
UInt64 expectSize = volSize;
|
||||
if (pos < length)
|
||||
{
|
||||
const UInt64 rem = length - pos;
|
||||
if (expectSize > rem)
|
||||
expectSize = rem;
|
||||
}
|
||||
outFile.PreAlloc(expectSize);
|
||||
}
|
||||
|
||||
if (!outFile.Write(buffer, needSize, processedSize))
|
||||
return GetLastError();
|
||||
if (needSize != processedSize)
|
||||
throw g_Message_FileWriteError;
|
||||
curVolSize += processedSize;
|
||||
if (curVolSize == volSize)
|
||||
|
||||
pos += processedSize;
|
||||
|
||||
if (outFile.Written == volSize)
|
||||
{
|
||||
outFile.Close();
|
||||
sync.Set_NumFilesCur(++numFiles);
|
||||
if (volIndex < VolumeSizes.Size())
|
||||
volIndex++;
|
||||
curVolSize = 0;
|
||||
}
|
||||
pos += processedSize;
|
||||
RINOK(sync.Set_NumBytesCur(pos));
|
||||
|
||||
if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0)
|
||||
{
|
||||
RINOK(sync.Set_NumBytesCur(pos));
|
||||
prev = pos;
|
||||
}
|
||||
}
|
||||
sync.Set_NumFilesCur(numFiles);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CApp::Split()
|
||||
{
|
||||
int srcPanelIndex = GetFocusedPanelIndex();
|
||||
|
||||
Reference in New Issue
Block a user