This commit is contained in:
Igor Pavlov
2018-01-11 22:16:32 +01:00
committed by Kornel
parent b5dc853b24
commit da28077952
44 changed files with 853 additions and 366 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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()));

View File

@@ -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)

View File

@@ -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];

View File

@@ -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();